diff --git a/b_asic/gui_utils/mpl_window.py b/b_asic/gui_utils/mpl_window.py index eec93e2c35cf1eecf16c2e197c2808ed1f6281ef..266d4ae7669a521ca2be9f211fc20c7fb50dc476 100644 --- a/b_asic/gui_utils/mpl_window.py +++ b/b_asic/gui_utils/mpl_window.py @@ -37,3 +37,6 @@ class MPLWindow(QDialog): @property def axes(self): return self._plot_axes + + def redraw(self): + self._plot_canvas.draw() diff --git a/b_asic/scheduler_gui/main_window.py b/b_asic/scheduler_gui/main_window.py index 4233cd17b04b674663899cb65e8e58d8d1c723f9..c1740e5814762b19764cfdc41186f0debea6d1dd 100644 --- a/b_asic/scheduler_gui/main_window.py +++ b/b_asic/scheduler_gui/main_window.py @@ -11,7 +11,7 @@ import os import pickle import sys import webbrowser -from collections import deque +from collections import defaultdict, deque from copy import deepcopy from importlib.machinery import SourceFileLoader from typing import TYPE_CHECKING, Deque, List, Optional, cast @@ -123,6 +123,7 @@ class ScheduleMainWindow(QMainWindow, Ui_MainWindow): self._show_incorrect_execution_time = True self._show_port_numbers = True self._execution_time_for_variables = None + self._execution_time_plot_dialogs = defaultdict(lambda: None) self._ports_accesses_for_storage = None # Recent files @@ -402,7 +403,13 @@ class ScheduleMainWindow(QMainWindow, Ui_MainWindow): self._graph._signals.schedule_time_changed.disconnect( self.info_table_update_schedule ) + self._graph._signals.schedule_time_changed.disconnect( + self._schedule_changed + ) self._graph._signals.reopen.disconnect(self._reopen_schedule) + self._graph._signals.execution_time_plot.disconnect( + self._execution_time_plot + ) self._graph.removeSceneEventFilters(self._graph.event_items) self._scene.removeItem(self._graph) self.menu_close_schedule.setEnabled(False) @@ -627,6 +634,9 @@ class ScheduleMainWindow(QMainWindow, Ui_MainWindow): self._ports_accesses_for_storage.close() if self._execution_time_for_variables: self._execution_time_for_variables.close() + for dialog in self._execution_time_plot_dialogs.values(): + if dialog: + dialog.close() event.accept() else: event.ignore() @@ -660,11 +670,14 @@ class ScheduleMainWindow(QMainWindow, Ui_MainWindow): self.info_table_update_component ) self._graph._signals.component_moved.connect(self.info_table_update_component) + self._graph._signals.component_moved.connect(self._schedule_changed) self._graph._signals.schedule_time_changed.connect( self.info_table_update_schedule ) + self._graph._signals.schedule_time_changed.connect(self._schedule_changed) self._graph._signals.redraw_all.connect(self._redraw_all) self._graph._signals.reopen.connect(self._reopen_schedule) + self._graph._signals.execution_time_plot.connect(self._execution_time_plot) self.info_table_fill_schedule(self._schedule) self._update_operation_types() self.action_view_variables.setEnabled(True) @@ -848,8 +861,30 @@ class ScheduleMainWindow(QMainWindow, Ui_MainWindow): ) self.menu_view_execution_times.addAction(type_action) + @Slot(str) def _show_execution_times_for_type(self, type_name): - self._graph._execution_time_plot(type_name) + self._execution_time_plot(type_name) + + def _closed_execution_times_for_type(self, type_name): + self._execution_time_plot_dialogs[type_name] = None + + def _execution_time_plot(self, type_name: str) -> None: + self._execution_time_plot_dialogs[type_name] = MPLWindow( + f"Execution times for {type_name}" + ) + self._execution_time_plot_dialogs[type_name].finished.connect( + lambda b=0, x=type_name: self._closed_execution_times_for_type(x) + ) + self._update_execution_times_for_type(type_name) + self._execution_time_plot_dialogs[type_name].show() + + def _update_execution_times_for_type(self, type_name): + if self._execution_time_plot_dialogs[type_name]: + self._execution_time_plot_dialogs[type_name].axes.clear() + self._schedule.get_operations().get_by_type_name(type_name).plot( + self._execution_time_plot_dialogs[type_name].axes + ) + self._execution_time_plot_dialogs[type_name].redraw() def _show_execution_times_for_variables(self): self._execution_time_for_variables = MPLWindow("Execution times for variables") @@ -865,6 +900,7 @@ class ScheduleMainWindow(QMainWindow, Ui_MainWindow): self._schedule.get_memory_variables().plot( self._execution_time_for_variables.axes, allow_excessive_lifetimes=True ) + self._execution_time_for_variables.redraw() @Slot() def _execution_times_for_variables_closed(self): @@ -887,11 +923,21 @@ class ScheduleMainWindow(QMainWindow, Ui_MainWindow): mem_vars = self._schedule.get_memory_variables() _, mem_vars = mem_vars.split_on_length() mem_vars.plot_port_accesses(self._ports_accesses_for_storage.axes) + self._ports_accesses_for_storage.redraw() @Slot() def _ports_accesses_for_storage_closed(self) -> None: self._ports_accesses_for_storage = None + @Slot() + @Slot(str) + def _schedule_changed(self, type_name: Optional[str] = None): + self._update_execution_times_for_variables() + self._update_ports_accesses_for_storage() + for key, dialog in self._execution_time_plot_dialogs.items(): + if dialog: + self._update_execution_times_for_type(key) + def _update_recent_file_list(self): settings = QSettings() diff --git a/b_asic/scheduler_gui/scheduler_event.py b/b_asic/scheduler_gui/scheduler_event.py index 293bb4126ebf9e7d9b6846e8e2cb2b5e1652bfbc..d11df3465833b7ccfcc9178f1a8cd31085392b49 100644 --- a/b_asic/scheduler_gui/scheduler_event.py +++ b/b_asic/scheduler_gui/scheduler_event.py @@ -37,6 +37,7 @@ class SchedulerEvent: # PyQt5 component_moved = Signal(str) redraw_all = Signal() reopen = Signal() + execution_time_plot = Signal(str) _axes: Optional[AxesItem] _current_pos: QPointF diff --git a/b_asic/scheduler_gui/scheduler_item.py b/b_asic/scheduler_gui/scheduler_item.py index 35bddbdd48022faced1334f0da759915c9caef43..4042beb9d08a986e74664884ae101ddd14d89b12 100644 --- a/b_asic/scheduler_gui/scheduler_item.py +++ b/b_asic/scheduler_gui/scheduler_item.py @@ -11,10 +11,10 @@ from pprint import pprint from typing import Dict, List, Optional, Set, cast # QGraphics and QPainter imports +from qtpy.QtCore import Signal from qtpy.QtWidgets import QGraphicsItem, QGraphicsItemGroup # B-ASIC -from b_asic.gui_utils.mpl_window import MPLWindow from b_asic.operation import Operation from b_asic.port import InputPort from b_asic.schedule import Schedule @@ -89,11 +89,11 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup): # PySide2 / PyQt5 self._operation_items = {} self._x_axis_indent = SCHEDULE_INDENT self._event_items = [] - self._execution_time_plot_dialogs = {} self._signal_dict = defaultdict(set) self._make_graph() self.set_warnings(warnings) self.set_port_numbers(show_port_numbers) + self._schedule_changed = Signal() def clear(self) -> None: """ @@ -298,6 +298,9 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup): # PySide2 / PyQt5 self._redraw_all_lines() self._update_axes() + def _execution_time_plot(self, type_name: str): + self._signals.execution_time_plot.emit(type_name) + def _redraw_all(self) -> None: for graph_id in self._operation_items: self._set_position(graph_id) @@ -359,14 +362,5 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup): # PySide2 / PyQt5 print(f"schedule.swap_io_of_operation({graph_id!r})") self._signals.reopen.emit() - def _execution_time_plot(self, type_name: str) -> None: - self._execution_time_plot_dialogs[type_name] = MPLWindow( - f"Execution times for {type_name}" - ) - self._schedule.get_operations().get_by_type_name(type_name).plot( - self._execution_time_plot_dialogs[type_name].axes - ) - self._execution_time_plot_dialogs[type_name].show() - pprint(SchedulerItem.__mro__)