bec-widgets 0.87.1__py3-none-any.whl → 0.88.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- CHANGELOG.md +72 -70
- PKG-INFO +1 -1
- bec_widgets/assets/designer_icons/BECWaveformWidget.png +0 -0
- bec_widgets/assets/designer_icons/colormap_selector.png +0 -0
- bec_widgets/assets/designer_icons/motor_map.png +0 -0
- bec_widgets/assets/toolbar_icons/add.svg +3 -0
- bec_widgets/assets/toolbar_icons/auto_range.svg +3 -0
- bec_widgets/assets/toolbar_icons/drag_pan_mode.svg +3 -0
- bec_widgets/assets/toolbar_icons/export.svg +9 -0
- bec_widgets/assets/toolbar_icons/fitting_parameters.svg +3 -0
- bec_widgets/assets/toolbar_icons/import.svg +9 -0
- bec_widgets/assets/toolbar_icons/line_axis.svg +3 -0
- bec_widgets/assets/toolbar_icons/photo_library.svg +3 -0
- bec_widgets/assets/toolbar_icons/rectangle_mode.svg +3 -0
- bec_widgets/assets/toolbar_icons/remove.svg +5 -0
- bec_widgets/assets/toolbar_icons/save.svg +3 -0
- bec_widgets/cli/client.py +320 -5
- bec_widgets/cli/server.py +2 -1
- bec_widgets/examples/jupyter_console/jupyter_console_window.py +12 -5
- bec_widgets/examples/plugin_example_pyside/tictactoe.py +1 -0
- bec_widgets/qt_utils/toolbar.py +74 -2
- bec_widgets/widgets/{color_map_selector/color_map_selector.py → colormap_selector/colormap_selector.py} +3 -1
- bec_widgets/widgets/colormap_selector/colormap_selector.pyproject +1 -0
- bec_widgets/widgets/{color_map_selector/color_map_selector_plugin.py → colormap_selector/colormap_selector_plugin.py} +8 -6
- bec_widgets/widgets/{color_map_selector/register_color_map_selector.py → colormap_selector/register_colormap_selector.py} +1 -1
- bec_widgets/widgets/figure/figure.py +12 -0
- bec_widgets/widgets/figure/plots/axis_settings.py +38 -11
- bec_widgets/widgets/figure/plots/image/image.py +1 -0
- bec_widgets/widgets/figure/plots/motor_map/motor_map.py +1 -0
- bec_widgets/widgets/figure/plots/plot_base.py +20 -3
- bec_widgets/widgets/figure/plots/waveform/waveform.py +48 -50
- bec_widgets/widgets/figure/plots/waveform/waveform_curve.py +9 -0
- bec_widgets/widgets/motor_map/bec_motor_map_widget_plugin.py +5 -3
- bec_widgets/widgets/motor_map/motor_map_widget.py +18 -12
- bec_widgets/widgets/waveform/__init__.py +0 -0
- bec_widgets/widgets/waveform/bec_waveform_widget.pyproject +1 -0
- bec_widgets/widgets/waveform/bec_waveform_widget_plugin.py +59 -0
- bec_widgets/widgets/waveform/register_bec_waveform_widget.py +15 -0
- bec_widgets/widgets/waveform/waveform_popups/__init__.py +0 -0
- bec_widgets/widgets/waveform/waveform_popups/curve_dialog/__init__.py +0 -0
- bec_widgets/widgets/waveform/waveform_popups/curve_dialog/curve_dialog.py +341 -0
- bec_widgets/widgets/waveform/waveform_popups/curve_dialog/curve_dialog.ui +358 -0
- bec_widgets/widgets/waveform/waveform_popups/dap_summary_dialog/__init__.py +0 -0
- bec_widgets/widgets/waveform/waveform_popups/dap_summary_dialog/dap_summary.ui +127 -0
- bec_widgets/widgets/waveform/waveform_popups/dap_summary_dialog/dap_summary_dialog.py +69 -0
- bec_widgets/widgets/waveform/waveform_widget.py +579 -0
- {bec_widgets-0.87.1.dist-info → bec_widgets-0.88.1.dist-info}/METADATA +1 -1
- {bec_widgets-0.87.1.dist-info → bec_widgets-0.88.1.dist-info}/RECORD +61 -37
- docs/conf.py +1 -1
- pyproject.toml +1 -1
- tests/unit_tests/test_color_map_selector.py +1 -1
- tests/unit_tests/test_waveform_widget.py +264 -0
- bec_widgets/widgets/color_map_selector/assets/color_map_selector_icon.png +0 -0
- bec_widgets/widgets/color_map_selector/color_map_selector.pyproject +0 -1
- bec_widgets/widgets/motor_map/assets/motor_map.png +0 -0
- bec_widgets/widgets/motor_map/motor_map_dialog/motor_map_toolbar.py +0 -59
- /bec_widgets/assets/{bec_widgets_icon.png → app_icons/bec_widgets_icon.png} +0 -0
- /bec_widgets/assets/{terminal_icon.png → app_icons/terminal_icon.png} +0 -0
- /bec_widgets/{widgets/motor_map/assets → assets/toolbar_icons}/connection.svg +0 -0
- /bec_widgets/{widgets/motor_map/assets → assets/toolbar_icons}/history.svg +0 -0
- /bec_widgets/{widgets/motor_map/assets → assets/toolbar_icons}/settings.svg +0 -0
- /bec_widgets/widgets/{color_map_selector → colormap_selector}/__init__.py +0 -0
- {bec_widgets-0.87.1.dist-info → bec_widgets-0.88.1.dist-info}/WHEEL +0 -0
- {bec_widgets-0.87.1.dist-info → bec_widgets-0.88.1.dist-info}/entry_points.txt +0 -0
- {bec_widgets-0.87.1.dist-info → bec_widgets-0.88.1.dist-info}/licenses/LICENSE +0 -0
@@ -1,14 +1,14 @@
|
|
1
1
|
import os
|
2
2
|
|
3
3
|
from qtpy.QtCore import Slot
|
4
|
-
from qtpy.QtWidgets import QVBoxLayout
|
4
|
+
from qtpy.QtWidgets import QVBoxLayout
|
5
5
|
|
6
|
+
from bec_widgets.qt_utils.settings_dialog import SettingWidget
|
6
7
|
from bec_widgets.utils import UILoader
|
7
|
-
from bec_widgets.utils.colors import apply_theme
|
8
8
|
from bec_widgets.utils.widget_io import WidgetIO
|
9
9
|
|
10
10
|
|
11
|
-
class AxisSettings(
|
11
|
+
class AxisSettings(SettingWidget):
|
12
12
|
def __init__(self, parent=None, *args, **kwargs):
|
13
13
|
super().__init__(parent=parent, *args, **kwargs)
|
14
14
|
|
@@ -25,6 +25,10 @@ class AxisSettings(QWidget):
|
|
25
25
|
|
26
26
|
@Slot(dict)
|
27
27
|
def display_current_settings(self, axis_config: dict):
|
28
|
+
|
29
|
+
if axis_config == {}:
|
30
|
+
return
|
31
|
+
|
28
32
|
# Top Box
|
29
33
|
WidgetIO.set_value(self.ui.plot_title, axis_config["title"])
|
30
34
|
|
@@ -37,6 +41,10 @@ class AxisSettings(QWidget):
|
|
37
41
|
WidgetIO.check_and_adjust_limits(self.ui.x_max, axis_config["x_lim"][1])
|
38
42
|
WidgetIO.set_value(self.ui.x_min, axis_config["x_lim"][0])
|
39
43
|
WidgetIO.set_value(self.ui.x_max, axis_config["x_lim"][1])
|
44
|
+
if axis_config["x_lim"] is None:
|
45
|
+
x_range = self.target_widget.fig.widget_list[0].plot_item.viewRange()[0]
|
46
|
+
WidgetIO.set_value(self.ui.x_min, x_range[0])
|
47
|
+
WidgetIO.set_value(self.ui.x_max, x_range[1])
|
40
48
|
|
41
49
|
# Y Axis Box
|
42
50
|
WidgetIO.set_value(self.ui.y_label, axis_config["y_label"])
|
@@ -47,15 +55,34 @@ class AxisSettings(QWidget):
|
|
47
55
|
WidgetIO.check_and_adjust_limits(self.ui.y_max, axis_config["y_lim"][1])
|
48
56
|
WidgetIO.set_value(self.ui.y_min, axis_config["y_lim"][0])
|
49
57
|
WidgetIO.set_value(self.ui.y_max, axis_config["y_lim"][1])
|
58
|
+
if axis_config["y_lim"] is None:
|
59
|
+
y_range = self.target_widget.fig.widget_list[0].plot_item.viewRange()[1]
|
60
|
+
WidgetIO.set_value(self.ui.y_min, y_range[0])
|
61
|
+
WidgetIO.set_value(self.ui.y_max, y_range[1])
|
50
62
|
|
63
|
+
@Slot()
|
64
|
+
def accept_changes(self):
|
65
|
+
title = WidgetIO.get_value(self.ui.plot_title)
|
51
66
|
|
52
|
-
|
53
|
-
|
67
|
+
# X Axis
|
68
|
+
x_label = WidgetIO.get_value(self.ui.x_label)
|
69
|
+
x_scale = self.ui.x_scale.currentText()
|
70
|
+
x_grid = WidgetIO.get_value(self.ui.x_grid)
|
71
|
+
x_lim = (WidgetIO.get_value(self.ui.x_min), WidgetIO.get_value(self.ui.x_max))
|
54
72
|
|
55
|
-
|
73
|
+
# Y Axis
|
74
|
+
y_label = WidgetIO.get_value(self.ui.y_label)
|
75
|
+
y_scale = self.ui.y_scale.currentText()
|
76
|
+
y_grid = WidgetIO.get_value(self.ui.y_grid)
|
77
|
+
y_lim = (WidgetIO.get_value(self.ui.y_min), WidgetIO.get_value(self.ui.y_max))
|
56
78
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
79
|
+
self.target_widget.set(
|
80
|
+
title=title,
|
81
|
+
x_label=x_label,
|
82
|
+
x_scale=x_scale,
|
83
|
+
x_lim=x_lim,
|
84
|
+
y_label=y_label,
|
85
|
+
y_scale=y_scale,
|
86
|
+
y_lim=y_lim,
|
87
|
+
)
|
88
|
+
self.target_widget.set_grid(x_grid, y_grid)
|
@@ -2,11 +2,8 @@ from __future__ import annotations
|
|
2
2
|
|
3
3
|
from typing import Literal, Optional
|
4
4
|
|
5
|
-
import numpy as np
|
6
5
|
import pyqtgraph as pg
|
7
6
|
from pydantic import BaseModel, Field
|
8
|
-
from qtpy import QT_VERSION
|
9
|
-
from qtpy.QtGui import QFont, QFontDatabase, QFontInfo
|
10
7
|
from qtpy.QtWidgets import QWidget
|
11
8
|
|
12
9
|
from bec_widgets.utils import BECConnector, ConnectionConfig
|
@@ -57,6 +54,7 @@ class BECPlotBase(BECConnector, pg.GraphicsLayout):
|
|
57
54
|
"set_y_lim",
|
58
55
|
"set_grid",
|
59
56
|
"lock_aspect_ratio",
|
57
|
+
"export",
|
60
58
|
"remove",
|
61
59
|
"set_legend_label_size",
|
62
60
|
]
|
@@ -293,6 +291,25 @@ class BECPlotBase(BECConnector, pg.GraphicsLayout):
|
|
293
291
|
"""
|
294
292
|
self.plot_item.setAspectLocked(lock)
|
295
293
|
|
294
|
+
def set_auto_range(self, enabled: bool, axis: str = "xy"):
|
295
|
+
"""
|
296
|
+
Set the auto range of the plot widget.
|
297
|
+
|
298
|
+
Args:
|
299
|
+
enabled(bool): If True, enable the auto range.
|
300
|
+
axis(str, optional): The axis to enable the auto range.
|
301
|
+
- "xy": Enable auto range for both x and y axis.
|
302
|
+
- "x": Enable auto range for x axis.
|
303
|
+
- "y": Enable auto range for y axis.
|
304
|
+
"""
|
305
|
+
self.plot_item.enableAutoRange(axis, enabled)
|
306
|
+
|
307
|
+
def export(self):
|
308
|
+
"""Show the Export Dialog of the plot widget."""
|
309
|
+
scene = self.plot_item.scene()
|
310
|
+
scene.contextMenuItem = self.plot_item
|
311
|
+
scene.showExportDialog()
|
312
|
+
|
296
313
|
def remove(self):
|
297
314
|
"""Remove the plot widget from the figure."""
|
298
315
|
if self.figure is not None:
|
@@ -1,7 +1,5 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
import datetime
|
4
|
-
import time
|
5
3
|
from collections import defaultdict
|
6
4
|
from typing import Any, Literal, Optional
|
7
5
|
|
@@ -10,7 +8,8 @@ import pyqtgraph as pg
|
|
10
8
|
from bec_lib import messages
|
11
9
|
from bec_lib.device import ReadoutPriority
|
12
10
|
from bec_lib.endpoints import MessageEndpoints
|
13
|
-
from pydantic import Field, ValidationError
|
11
|
+
from pydantic import Field, ValidationError, field_validator
|
12
|
+
from pyqtgraph.exporters import MatplotlibExporter
|
14
13
|
from qtpy.QtCore import Signal as pyqtSignal
|
15
14
|
from qtpy.QtCore import Slot as pyqtSlot
|
16
15
|
from qtpy.QtWidgets import QWidget
|
@@ -26,13 +25,16 @@ from bec_widgets.widgets.figure.plots.waveform.waveform_curve import (
|
|
26
25
|
|
27
26
|
|
28
27
|
class Waveform1DConfig(SubplotConfig):
|
29
|
-
color_palette:
|
30
|
-
"plasma", description="The color palette of the figure widget."
|
28
|
+
color_palette: Optional[str] = Field(
|
29
|
+
"plasma", description="The color palette of the figure widget.", validate_default=True
|
31
30
|
)
|
32
31
|
curves: dict[str, CurveConfig] = Field(
|
33
32
|
{}, description="The list of curves to be added to the 1D waveform widget."
|
34
33
|
)
|
35
34
|
|
35
|
+
model_config: dict = {"validate_assignment": True}
|
36
|
+
_validate_color_map_z = field_validator("color_palette")(Colors.validate_color_map)
|
37
|
+
|
36
38
|
|
37
39
|
class BECWaveform(BECPlotBase):
|
38
40
|
READOUT_PRIORITY_HANDLER = {
|
@@ -63,7 +65,9 @@ class BECWaveform(BECPlotBase):
|
|
63
65
|
"set_x_lim",
|
64
66
|
"set_y_lim",
|
65
67
|
"set_grid",
|
68
|
+
"set_colormap",
|
66
69
|
"lock_aspect_ratio",
|
70
|
+
"export",
|
67
71
|
"remove",
|
68
72
|
"clear_all",
|
69
73
|
"set_legend_label_size",
|
@@ -71,6 +75,7 @@ class BECWaveform(BECPlotBase):
|
|
71
75
|
scan_signal_update = pyqtSignal()
|
72
76
|
async_signal_update = pyqtSignal()
|
73
77
|
dap_params_update = pyqtSignal(dict)
|
78
|
+
dap_summary_update = pyqtSignal(dict)
|
74
79
|
autorange_signal = pyqtSignal()
|
75
80
|
|
76
81
|
def __init__(
|
@@ -385,7 +390,6 @@ class BECWaveform(BECPlotBase):
|
|
385
390
|
|
386
391
|
self.async_signal_update.emit()
|
387
392
|
self.scan_signal_update.emit()
|
388
|
-
# self.autorange_timer.start(200)
|
389
393
|
|
390
394
|
@pyqtSlot()
|
391
395
|
def auto_range(self):
|
@@ -651,6 +655,19 @@ class BECWaveform(BECPlotBase):
|
|
651
655
|
params[curve_id] = curve.dap_params
|
652
656
|
return params
|
653
657
|
|
658
|
+
@pyqtSlot()
|
659
|
+
def get_dap_summary(self) -> dict:
|
660
|
+
"""
|
661
|
+
Get the DAP summary of all DAP curves.
|
662
|
+
|
663
|
+
Returns:
|
664
|
+
dict: DAP summary of all DAP curves.
|
665
|
+
"""
|
666
|
+
summary = {}
|
667
|
+
for curve_id, curve in self._curves_data["DAP"].items():
|
668
|
+
summary[curve_id] = curve.dap_summary
|
669
|
+
return summary
|
670
|
+
|
654
671
|
def _add_curve_object(
|
655
672
|
self,
|
656
673
|
name: str,
|
@@ -954,6 +971,22 @@ class BECWaveform(BECPlotBase):
|
|
954
971
|
current_label = "" if self.config.axis.x_label is None else self.config.axis.x_label
|
955
972
|
self.plot_item.setLabel("bottom", f"{current_label}{self._x_axis_mode['label_suffix']}")
|
956
973
|
|
974
|
+
def set_colormap(self, colormap: str | None = None):
|
975
|
+
"""
|
976
|
+
Set the colormap of the plot widget.
|
977
|
+
|
978
|
+
Args:
|
979
|
+
colormap(str, optional): Scale the colors of curves to colormap. If None, use the default color palette.
|
980
|
+
"""
|
981
|
+
if colormap is not None:
|
982
|
+
self.config.color_palette = colormap
|
983
|
+
|
984
|
+
colors = Colors.golden_angle_color(
|
985
|
+
colormap=self.config.color_palette, num=len(self.plot_item.curves) + 1, format="HEX"
|
986
|
+
)
|
987
|
+
for curve, color in zip(self.curves, colors):
|
988
|
+
curve.set_color(color)
|
989
|
+
|
957
990
|
def setup_dap(self, old_scan_id: str | None, new_scan_id: str | None):
|
958
991
|
"""
|
959
992
|
Setup DAP for the new scan.
|
@@ -1051,7 +1084,9 @@ class BECWaveform(BECPlotBase):
|
|
1051
1084
|
y = msg["data"][0]["y"]
|
1052
1085
|
curve.setData(x, y)
|
1053
1086
|
curve.dap_params = msg["data"][1]["fit_parameters"]
|
1087
|
+
curve.dap_summary = msg["data"][1]["fit_summary"]
|
1054
1088
|
self.dap_params_update.emit(curve.dap_params)
|
1089
|
+
self.dap_summary_update.emit(curve.dap_summary)
|
1055
1090
|
break
|
1056
1091
|
|
1057
1092
|
@pyqtSlot(dict, dict)
|
@@ -1180,7 +1215,6 @@ class BECWaveform(BECPlotBase):
|
|
1180
1215
|
timestamps = self.scan_item.data[y_name][y_entry].timestamps
|
1181
1216
|
|
1182
1217
|
x_data = timestamps
|
1183
|
-
print(x_data)
|
1184
1218
|
return x_data
|
1185
1219
|
if self._x_axis_mode["name"] == "index":
|
1186
1220
|
x_data = None
|
@@ -1214,49 +1248,6 @@ class BECWaveform(BECPlotBase):
|
|
1214
1248
|
x_data = []
|
1215
1249
|
return x_data
|
1216
1250
|
|
1217
|
-
# def _get_x_data(self, curve: BECCurve, y_name: str, y_entry: str) -> list | np.ndarray | None:
|
1218
|
-
# """
|
1219
|
-
# Get the x data for the curve with the decision logic based on the curve configuration:
|
1220
|
-
# - If x is called 'timestamp', use the timestamp data from the scan item.
|
1221
|
-
# - If x is called 'index', use the rolling index.
|
1222
|
-
# - If x is a custom signal, use the data from the scan item.
|
1223
|
-
# - If x is not specified, use the first device from the scan report.
|
1224
|
-
#
|
1225
|
-
# Args:
|
1226
|
-
# curve(BECCurve): The curve object.
|
1227
|
-
#
|
1228
|
-
# Returns:
|
1229
|
-
# list|np.ndarray|None: X data for the curve.
|
1230
|
-
# """
|
1231
|
-
# x_data = None
|
1232
|
-
# if curve.config.signals.x is not None:
|
1233
|
-
# if curve.config.signals.x.name == "timestamp":
|
1234
|
-
# timestamps = self.scan_item.data[y_name][y_entry].timestamps
|
1235
|
-
# x_data = self.convert_timestamps(timestamps)
|
1236
|
-
# elif curve.config.signals.x.name == "index":
|
1237
|
-
# x_data = None
|
1238
|
-
# else:
|
1239
|
-
# x_name = curve.config.signals.x.name
|
1240
|
-
# x_entry = curve.config.signals.x.entry
|
1241
|
-
# try:
|
1242
|
-
# x_data = self.scan_item.data[x_name][x_entry].val
|
1243
|
-
# except TypeError:
|
1244
|
-
# x_data = []
|
1245
|
-
# else:
|
1246
|
-
# if len(self._curves_data["async"]) > 0:
|
1247
|
-
# x_data = None
|
1248
|
-
# else:
|
1249
|
-
# x_name = self.scan_item.status_message.info["scan_report_devices"][0]
|
1250
|
-
# x_entry = self.entry_validator.validate_signal(x_name, None)
|
1251
|
-
# x_data = self.scan_item.data[x_name][x_entry].val
|
1252
|
-
# self._x_axis_mode["label_suffix"] = f" [auto: {x_name}-{x_entry}]"
|
1253
|
-
# current_label = "" if self.config.axis.x_label is None else self.config.axis.x_label
|
1254
|
-
# self.plot_item.setLabel(
|
1255
|
-
# "bottom", f"{current_label}{self._x_axis_mode['label_suffix']}"
|
1256
|
-
# )
|
1257
|
-
#
|
1258
|
-
# return x_data
|
1259
|
-
|
1260
1251
|
def _make_z_gradient(self, data_z: list | np.ndarray, colormap: str) -> list | None:
|
1261
1252
|
"""
|
1262
1253
|
Make a gradient color for the z values.
|
@@ -1349,6 +1340,13 @@ class BECWaveform(BECPlotBase):
|
|
1349
1340
|
return combined_data
|
1350
1341
|
return data
|
1351
1342
|
|
1343
|
+
def export_to_matplotlib(self):
|
1344
|
+
"""
|
1345
|
+
Export current waveform to matplotlib gui. Available only if matplotlib is installed in the enviroment.
|
1346
|
+
|
1347
|
+
"""
|
1348
|
+
MatplotlibExporter(self.plot_item).export()
|
1349
|
+
|
1352
1350
|
def clear_all(self):
|
1353
1351
|
curves_data = self._curves_data
|
1354
1352
|
sources = list(curves_data.keys())
|
@@ -101,6 +101,7 @@ class BECCurve(BECConnector, pg.PlotDataItem):
|
|
101
101
|
self.parent_item = parent_item
|
102
102
|
self.apply_config()
|
103
103
|
self.dap_params = None
|
104
|
+
self.dap_summary = None
|
104
105
|
if kwargs:
|
105
106
|
self.set(**kwargs)
|
106
107
|
|
@@ -132,6 +133,14 @@ class BECCurve(BECConnector, pg.PlotDataItem):
|
|
132
133
|
def dap_params(self, value):
|
133
134
|
self._dap_params = value
|
134
135
|
|
136
|
+
@property
|
137
|
+
def dap_summary(self):
|
138
|
+
return self._dap_report
|
139
|
+
|
140
|
+
@dap_summary.setter
|
141
|
+
def dap_summary(self, value):
|
142
|
+
self._dap_report = value
|
143
|
+
|
135
144
|
def set_data(self, x, y):
|
136
145
|
if self.config.source == "custom":
|
137
146
|
self.setData(x, y)
|
@@ -3,6 +3,7 @@ import os
|
|
3
3
|
from qtpy.QtDesigner import QDesignerCustomWidgetInterface
|
4
4
|
from qtpy.QtGui import QIcon
|
5
5
|
|
6
|
+
import bec_widgets
|
6
7
|
from bec_widgets.widgets.motor_map.motor_map_widget import BECMotorMapWidget
|
7
8
|
|
8
9
|
DOM_XML = """
|
@@ -12,6 +13,8 @@ DOM_XML = """
|
|
12
13
|
</ui>
|
13
14
|
"""
|
14
15
|
|
16
|
+
MODULE_PATH = os.path.dirname(bec_widgets.__file__)
|
17
|
+
|
15
18
|
|
16
19
|
class BECMotorMapWidgetPlugin(QDesignerCustomWidgetInterface): # pragma: no cover
|
17
20
|
def __init__(self):
|
@@ -26,11 +29,10 @@ class BECMotorMapWidgetPlugin(QDesignerCustomWidgetInterface): # pragma: no cov
|
|
26
29
|
return DOM_XML
|
27
30
|
|
28
31
|
def group(self):
|
29
|
-
return "BEC
|
32
|
+
return "BEC Plots"
|
30
33
|
|
31
34
|
def icon(self):
|
32
|
-
|
33
|
-
icon_path = os.path.join(current_path, "assets", "motor_map.png")
|
35
|
+
icon_path = os.path.join(MODULE_PATH, "assets", "designer_icons", "motor_map.png")
|
34
36
|
return QIcon(icon_path)
|
35
37
|
|
36
38
|
def includeFile(self):
|
@@ -5,17 +5,12 @@ import sys
|
|
5
5
|
from qtpy.QtWidgets import QVBoxLayout, QWidget
|
6
6
|
|
7
7
|
from bec_widgets.qt_utils.settings_dialog import SettingsDialog
|
8
|
-
from bec_widgets.qt_utils.toolbar import ModularToolBar
|
8
|
+
from bec_widgets.qt_utils.toolbar import DeviceSelectionAction, IconAction, ModularToolBar
|
9
9
|
from bec_widgets.utils.bec_widget import BECWidget
|
10
|
+
from bec_widgets.widgets.device_combobox.device_combobox import DeviceComboBox
|
10
11
|
from bec_widgets.widgets.figure import BECFigure
|
11
12
|
from bec_widgets.widgets.figure.plots.motor_map.motor_map import MotorMapConfig
|
12
13
|
from bec_widgets.widgets.motor_map.motor_map_dialog.motor_map_settings import MotorMapSettings
|
13
|
-
from bec_widgets.widgets.motor_map.motor_map_dialog.motor_map_toolbar import (
|
14
|
-
ConnectAction,
|
15
|
-
DeviceSelectionAction,
|
16
|
-
ResetHistoryAction,
|
17
|
-
SettingsAction,
|
18
|
-
)
|
19
14
|
|
20
15
|
|
21
16
|
class BECMotorMapWidget(BECWidget, QWidget):
|
@@ -28,6 +23,7 @@ class BECMotorMapWidget(BECWidget, QWidget):
|
|
28
23
|
"set_scatter_size",
|
29
24
|
"get_data",
|
30
25
|
"reset_history",
|
26
|
+
"export",
|
31
27
|
]
|
32
28
|
|
33
29
|
def __init__(
|
@@ -52,11 +48,15 @@ class BECMotorMapWidget(BECWidget, QWidget):
|
|
52
48
|
self.fig = BECFigure()
|
53
49
|
self.toolbar = ModularToolBar(
|
54
50
|
actions={
|
55
|
-
"motor_x": DeviceSelectionAction(
|
56
|
-
|
57
|
-
|
58
|
-
"
|
59
|
-
|
51
|
+
"motor_x": DeviceSelectionAction(
|
52
|
+
"Motor X:", DeviceComboBox(device_filter="Positioner")
|
53
|
+
),
|
54
|
+
"motor_y": DeviceSelectionAction(
|
55
|
+
"Motor Y:", DeviceComboBox(device_filter="Positioner")
|
56
|
+
),
|
57
|
+
"connect": IconAction(icon_path="connection.svg", tooltip="Connect Motors"),
|
58
|
+
"history": IconAction(icon_path="history.svg", tooltip="Reset Trace History"),
|
59
|
+
"config": IconAction(icon_path="settings.svg", tooltip="Open Configuration Dialog"),
|
60
60
|
},
|
61
61
|
target_widget=self,
|
62
62
|
)
|
@@ -202,6 +202,12 @@ class BECMotorMapWidget(BECWidget, QWidget):
|
|
202
202
|
"""
|
203
203
|
self.map.set_scatter_size(scatter_size)
|
204
204
|
|
205
|
+
def export(self):
|
206
|
+
"""
|
207
|
+
Show the export dialog for the motor map.
|
208
|
+
"""
|
209
|
+
self.map.export()
|
210
|
+
|
205
211
|
def cleanup(self):
|
206
212
|
self.fig.cleanup()
|
207
213
|
self.toolbar.widgets["motor_x"].device_combobox.cleanup()
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
{'files': ['waveform_widget.py']}
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# Copyright (C) 2022 The Qt Company Ltd.
|
2
|
+
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
3
|
+
import os
|
4
|
+
|
5
|
+
from qtpy.QtDesigner import QDesignerCustomWidgetInterface
|
6
|
+
from qtpy.QtGui import QIcon
|
7
|
+
|
8
|
+
import bec_widgets
|
9
|
+
from bec_widgets.widgets.waveform.waveform_widget import BECWaveformWidget
|
10
|
+
|
11
|
+
DOM_XML = """
|
12
|
+
<ui language='c++'>
|
13
|
+
<widget class='BECWaveformWidget' name='bec_waveform_widget'>
|
14
|
+
</widget>
|
15
|
+
</ui>
|
16
|
+
"""
|
17
|
+
|
18
|
+
MODULE_PATH = os.path.dirname(bec_widgets.__file__)
|
19
|
+
|
20
|
+
|
21
|
+
class BECWaveformWidgetPlugin(QDesignerCustomWidgetInterface): # pragma: no cover
|
22
|
+
def __init__(self):
|
23
|
+
super().__init__()
|
24
|
+
self._form_editor = None
|
25
|
+
|
26
|
+
def createWidget(self, parent):
|
27
|
+
t = BECWaveformWidget(parent)
|
28
|
+
return t
|
29
|
+
|
30
|
+
def domXml(self):
|
31
|
+
return DOM_XML
|
32
|
+
|
33
|
+
def group(self):
|
34
|
+
return "BEC Plots"
|
35
|
+
|
36
|
+
def icon(self):
|
37
|
+
icon_path = os.path.join(MODULE_PATH, "assets", "designer_icons", "BECWaveformWidget.png")
|
38
|
+
return QIcon(icon_path)
|
39
|
+
|
40
|
+
def includeFile(self):
|
41
|
+
return "bec_waveform_widget"
|
42
|
+
|
43
|
+
def initialize(self, form_editor):
|
44
|
+
self._form_editor = form_editor
|
45
|
+
|
46
|
+
def isContainer(self):
|
47
|
+
return False
|
48
|
+
|
49
|
+
def isInitialized(self):
|
50
|
+
return self._form_editor is not None
|
51
|
+
|
52
|
+
def name(self):
|
53
|
+
return "BECWaveformWidget"
|
54
|
+
|
55
|
+
def toolTip(self):
|
56
|
+
return "BECWaveformWidget"
|
57
|
+
|
58
|
+
def whatsThis(self):
|
59
|
+
return self.toolTip()
|
@@ -0,0 +1,15 @@
|
|
1
|
+
def main(): # pragma: no cover
|
2
|
+
from qtpy import PYSIDE6
|
3
|
+
|
4
|
+
if not PYSIDE6:
|
5
|
+
print("PYSIDE6 is not available in the environment. Cannot patch designer.")
|
6
|
+
return
|
7
|
+
from PySide6.QtDesigner import QPyDesignerCustomWidgetCollection
|
8
|
+
|
9
|
+
from bec_widgets.widgets.waveform.bec_waveform_widget_plugin import BECWaveformWidgetPlugin
|
10
|
+
|
11
|
+
QPyDesignerCustomWidgetCollection.addCustomWidget(BECWaveformWidgetPlugin())
|
12
|
+
|
13
|
+
|
14
|
+
if __name__ == "__main__": # pragma: no cover
|
15
|
+
main()
|
File without changes
|
File without changes
|