diff --git a/b_asic/gui_utils/mpl_window.py b/b_asic/gui_utils/mpl_window.py new file mode 100644 index 0000000000000000000000000000000000000000..7251ac38fd2e1a84e5f2f217211e39fac6703557 --- /dev/null +++ b/b_asic/gui_utils/mpl_window.py @@ -0,0 +1,39 @@ +"""MPLWindow is a dialog that provides an Axes for plotting in.""" + +from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas +from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar +from matplotlib.figure import Figure +from qtpy.QtCore import Qt +from qtpy.QtWidgets import QDialog, QVBoxLayout + + +class MPLWindow(QDialog): + """ + Dialog for plotting Matplotlib things. + """ + + def __init__(self, title: str = "B-ASIC"): + super().__init__() + self.setWindowFlags( + Qt.WindowTitleHint + | Qt.WindowCloseButtonHint + | Qt.WindowMinimizeButtonHint + | Qt.WindowMaximizeButtonHint + ) + self.setWindowTitle(title) + + self._dialog_layout = QVBoxLayout() + self.setLayout(self._dialog_layout) + + self._plot_fig = Figure(figsize=(5, 4), layout="compressed") + self._plot_axes = self._plot_fig.add_subplot(111) + + self._plot_canvas = FigureCanvas(self._plot_fig) + self._toolbar = NavigationToolbar(self._plot_canvas, self) + + self._dialog_layout.addWidget(self._toolbar) + self._dialog_layout.addWidget(self._plot_canvas) + + @property + def axes(self): + return self._plot_axes diff --git a/b_asic/scheduler_gui/operation_item.py b/b_asic/scheduler_gui/operation_item.py index e960997add05a8919f8a718bb2b0d2fa7385bd34..c84529fafe27b5b7569e6ca60c4a68faa6579e01 100644 --- a/b_asic/scheduler_gui/operation_item.py +++ b/b_asic/scheduler_gui/operation_item.py @@ -309,7 +309,15 @@ class OperationItem(QGraphicsItemGroup): menu.addAction(swap) swap.setEnabled(self._operation.is_swappable) swap.triggered.connect(self._swap_io) + execution_time_plot = QAction( + f"Show execution times for {self._operation.type_name()}" + ) + menu.addAction(execution_time_plot) + execution_time_plot.triggered.connect(self._execution_time_plot) menu.exec_(self.cursor().pos()) def _swap_io(self, event=None) -> None: self._parent._swap_io_of_operation(self._operation.graph_id) + + def _execution_time_plot(self, event=None) -> None: + self._parent._execution_time_plot(self._operation.type_name()) diff --git a/b_asic/scheduler_gui/scheduler_item.py b/b_asic/scheduler_gui/scheduler_item.py index 8c80d33f2e9444bb866445356d5efa088c1711b8..74051251c82df1ecdbc8d37e53f9a895a868975b 100644 --- a/b_asic/scheduler_gui/scheduler_item.py +++ b/b_asic/scheduler_gui/scheduler_item.py @@ -15,6 +15,7 @@ from typing import Dict, List, Optional, Set, cast 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,6 +90,7 @@ 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) @@ -359,5 +361,14 @@ 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__)