From 8d9340539967b06b1e15f21a2106a39d5c740f31 Mon Sep 17 00:00:00 2001 From: wyzula-jan Date: Wed, 17 Jul 2024 11:37:59 +0200 Subject: [PATCH] feat(waveform): export to matplotlib window of current scene --- .../assets/toolbar_icons/photo_library.svg | 3 +++ bec_widgets/cli/client.py | 6 +++++ bec_widgets/widgets/figure/plots/plot_base.py | 1 - .../widgets/figure/plots/waveform/waveform.py | 8 +++++++ .../waveform_toolbar/waveform_toolbar.py | 11 ++++++++++ .../widgets/waveform/waveform_widget.py | 22 ++++++++++++++++++- 6 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 bec_widgets/assets/toolbar_icons/photo_library.svg diff --git a/bec_widgets/assets/toolbar_icons/photo_library.svg b/bec_widgets/assets/toolbar_icons/photo_library.svg new file mode 100644 index 00000000..52da9fab --- /dev/null +++ b/bec_widgets/assets/toolbar_icons/photo_library.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/bec_widgets/cli/client.py b/bec_widgets/cli/client.py index 2e77cbcb..a5149fda 100644 --- a/bec_widgets/cli/client.py +++ b/bec_widgets/cli/client.py @@ -2010,6 +2010,12 @@ class BECWaveformWidget(RPCBase): Show the export dialog for the plot widget. """ + @rpc_call + def export_to_matplotlib(self): + """ + Export the plot widget to Matplotlib. + """ + class DeviceBox(RPCBase): @property diff --git a/bec_widgets/widgets/figure/plots/plot_base.py b/bec_widgets/widgets/figure/plots/plot_base.py index 40569167..a146288b 100644 --- a/bec_widgets/widgets/figure/plots/plot_base.py +++ b/bec_widgets/widgets/figure/plots/plot_base.py @@ -4,7 +4,6 @@ from typing import Literal, Optional import pyqtgraph as pg from pydantic import BaseModel, Field -from pyqtgraph.GraphicsScene.exportDialog import ExportDialog from qtpy.QtWidgets import QWidget from bec_widgets.utils import BECConnector, ConnectionConfig diff --git a/bec_widgets/widgets/figure/plots/waveform/waveform.py b/bec_widgets/widgets/figure/plots/waveform/waveform.py index 47f3f7e6..5c7d9eca 100644 --- a/bec_widgets/widgets/figure/plots/waveform/waveform.py +++ b/bec_widgets/widgets/figure/plots/waveform/waveform.py @@ -9,6 +9,7 @@ from bec_lib import messages from bec_lib.device import ReadoutPriority from bec_lib.endpoints import MessageEndpoints from pydantic import Field, ValidationError, field_validator +from pyqtgraph.exporters import MatplotlibExporter from qtpy.QtCore import Signal as pyqtSignal from qtpy.QtCore import Slot as pyqtSlot from qtpy.QtWidgets import QWidget @@ -1324,6 +1325,13 @@ class BECWaveform(BECPlotBase): return combined_data return data + def export_to_matplotlib(self): + """ + Export current waveform to matplotlib gui. Available only if matplotlib is installed in the enviroment. + + """ + MatplotlibExporter(self.plot_item).export() + def clear_all(self): curves_data = self._curves_data sources = list(curves_data.keys()) diff --git a/bec_widgets/widgets/waveform/waveform_toolbar/waveform_toolbar.py b/bec_widgets/widgets/waveform/waveform_toolbar/waveform_toolbar.py index 1012e2ac..bb887a86 100644 --- a/bec_widgets/widgets/waveform/waveform_toolbar/waveform_toolbar.py +++ b/bec_widgets/widgets/waveform/waveform_toolbar/waveform_toolbar.py @@ -19,6 +19,17 @@ class SaveAction(ToolBarAction): toolbar.addAction(self.action) +class MatplotlibAction(ToolBarAction): + def add_to_toolbar(self, toolbar, target): + icon = QIcon() + icon.addFile( + os.path.join(MODULE_PATH, "assets", "toolbar_icons", "photo_library.svg"), + size=QSize(20, 20), + ) + self.action = QAction(icon, "Open Matplotlib Plot", target) + toolbar.addAction(self.action) + + class CurveAction(ToolBarAction): def add_to_toolbar(self, toolbar, target): icon = QIcon() diff --git a/bec_widgets/widgets/waveform/waveform_widget.py b/bec_widgets/widgets/waveform/waveform_widget.py index 02143365..db0472e7 100644 --- a/bec_widgets/widgets/waveform/waveform_widget.py +++ b/bec_widgets/widgets/waveform/waveform_widget.py @@ -6,7 +6,7 @@ from typing import Literal import numpy as np from qtpy.QtWidgets import QVBoxLayout, QWidget -from bec_widgets.qt_utils.error_popups import error_managed +from bec_widgets.qt_utils.error_popups import WarningPopupUtility, error_managed from bec_widgets.qt_utils.settings_dialog import SettingsDialog from bec_widgets.qt_utils.toolbar import ModularToolBar, SeparatorAction from bec_widgets.utils import BECConnector @@ -44,6 +44,7 @@ class BECWaveformWidget(BECConnector, QWidget): "set_grid", "lock_aspect_ratio", "export", + "export_to_matplotlib", ] def __init__( @@ -69,6 +70,7 @@ class BECWaveformWidget(BECConnector, QWidget): self.toolbar = ModularToolBar( actions={ "save": SaveAction(), + "matplotlib": MatplotlibAction(), "separator_1": SeparatorAction(), "curves": CurveAction(), "axis_settings": SettingsAction(), @@ -82,6 +84,8 @@ class BECWaveformWidget(BECConnector, QWidget): self.layout.addWidget(self.toolbar) self.layout.addWidget(self.fig) + self.warning_util = WarningPopupUtility(self) + self.waveform = self.fig.plot() self.waveform.apply_config(config) @@ -96,6 +100,7 @@ class BECWaveformWidget(BECConnector, QWidget): def _hook_actions(self): self.toolbar.widgets["save"].action.triggered.connect(self.export) + self.toolbar.widgets["matplotlib"].action.triggered.connect(self.export_to_matplotlib) self.toolbar.widgets["curves"].action.triggered.connect(self.show_curve_settings) self.toolbar.widgets["axis_settings"].action.triggered.connect(self.show_axis_settings) self.toolbar.widgets["import"].action.triggered.connect( @@ -467,6 +472,21 @@ class BECWaveformWidget(BECConnector, QWidget): """ self.waveform.export() + def export_to_matplotlib(self): + """ + Export the plot widget to Matplotlib. + """ + try: + import matplotlib as mpl + except ImportError: + self.warning_util.show_warning( + title="Matplotlib not installed", + message="Matplotlib is required for this feature.", + detailed_text="Please install matplotlib in your Python environment by using 'pip install matplotlib'.", + ) + return + self.waveform.export_to_matplotlib() + ####################################### # User Access Methods from BECConnector ######################################