bec-widgets 1.25.1__py3-none-any.whl → 2.0.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.
Files changed (196) hide show
  1. .gitlab-ci.yml +3 -5
  2. CHANGELOG.md +639 -0
  3. PKG-INFO +3 -3
  4. bec_widgets/__init__.py +4 -0
  5. bec_widgets/applications/bw_launch.py +23 -0
  6. bec_widgets/applications/launch_window.py +430 -0
  7. bec_widgets/assets/app_icons/auto_update.png +0 -0
  8. bec_widgets/assets/app_icons/ui_loader_tile.png +0 -0
  9. bec_widgets/cli/__init__.py +0 -1
  10. bec_widgets/cli/client.py +1779 -2064
  11. bec_widgets/cli/client_utils.py +346 -174
  12. bec_widgets/cli/generate_cli.py +143 -37
  13. bec_widgets/cli/rpc/rpc_base.py +152 -21
  14. bec_widgets/cli/rpc/rpc_register.py +113 -6
  15. bec_widgets/cli/rpc/rpc_widget_handler.py +13 -11
  16. bec_widgets/cli/server.py +125 -239
  17. bec_widgets/examples/jupyter_console/jupyter_console_window.py +97 -145
  18. bec_widgets/examples/plugin_example_pyside/tictactoetaskmenu.py +1 -1
  19. bec_widgets/utils/bec_connector.py +190 -21
  20. bec_widgets/utils/bec_designer.py +7 -0
  21. bec_widgets/utils/bec_dispatcher.py +71 -4
  22. bec_widgets/utils/bec_plugin_helper.py +89 -0
  23. bec_widgets/utils/bec_signal_proxy.py +1 -1
  24. bec_widgets/utils/bec_widget.py +26 -10
  25. bec_widgets/utils/colors.py +1 -1
  26. bec_widgets/{qt_utils → utils}/compact_popup.py +2 -0
  27. bec_widgets/utils/container_utils.py +37 -12
  28. bec_widgets/utils/crosshair.py +25 -8
  29. bec_widgets/utils/entry_validator.py +3 -1
  30. bec_widgets/{qt_utils → utils}/error_popups.py +18 -0
  31. bec_widgets/{qt_utils → utils}/expandable_frame.py +2 -2
  32. bec_widgets/utils/forms_from_types/forms.py +182 -0
  33. bec_widgets/{widgets/editors/scan_metadata/_metadata_widgets.py → utils/forms_from_types/items.py} +41 -30
  34. bec_widgets/utils/generate_designer_plugin.py +40 -36
  35. bec_widgets/utils/linear_region_selector.py +2 -0
  36. bec_widgets/utils/name_utils.py +16 -0
  37. bec_widgets/{qt_utils → utils}/palette_viewer.py +2 -2
  38. bec_widgets/utils/plot_indicator_items.py +2 -5
  39. bec_widgets/utils/plugin_utils.py +47 -1
  40. bec_widgets/{qt_utils → utils}/round_frame.py +14 -14
  41. bec_widgets/utils/rpc_server.py +277 -0
  42. bec_widgets/utils/serialization.py +44 -0
  43. bec_widgets/{qt_utils → utils}/settings_dialog.py +26 -1
  44. bec_widgets/{qt_utils → utils}/side_panel.py +17 -10
  45. bec_widgets/{qt_utils → utils}/toolbar.py +69 -25
  46. bec_widgets/utils/ui_loader.py +8 -8
  47. bec_widgets/utils/widget_io.py +166 -25
  48. bec_widgets/widgets/containers/auto_update/auto_updates.py +364 -0
  49. bec_widgets/widgets/containers/dock/dock.py +157 -49
  50. bec_widgets/widgets/containers/dock/dock_area.py +188 -138
  51. bec_widgets/widgets/containers/layout_manager/layout_manager.py +2 -1
  52. bec_widgets/widgets/containers/main_window/addons/web_links.py +15 -0
  53. bec_widgets/widgets/containers/main_window/main_window.py +189 -41
  54. bec_widgets/widgets/control/buttons/button_abort/button_abort.py +3 -4
  55. bec_widgets/widgets/control/buttons/button_reset/button_reset.py +3 -4
  56. bec_widgets/widgets/control/buttons/button_resume/button_resume.py +3 -3
  57. bec_widgets/widgets/control/buttons/stop_button/stop_button.py +18 -7
  58. bec_widgets/widgets/control/device_control/position_indicator/position_indicator.py +22 -3
  59. bec_widgets/widgets/control/device_control/positioner_box/_base/positioner_box_base.py +31 -13
  60. bec_widgets/widgets/control/device_control/positioner_box/positioner_box/positioner_box.py +3 -1
  61. bec_widgets/widgets/control/device_control/positioner_box/positioner_box/positioner_box.ui +27 -4
  62. bec_widgets/widgets/control/device_control/positioner_box/positioner_box_2d/positioner_box_2d.py +5 -2
  63. bec_widgets/widgets/control/device_control/positioner_box/positioner_box_2d/positioner_box_2d.ui +97 -31
  64. bec_widgets/widgets/control/device_control/positioner_box/positioner_control_line/positioner_control_line.ui +11 -4
  65. bec_widgets/widgets/control/device_control/positioner_group/positioner_group.py +2 -3
  66. bec_widgets/widgets/control/device_input/base_classes/device_input_base.py +29 -4
  67. bec_widgets/widgets/control/device_input/base_classes/device_signal_input_base.py +1 -0
  68. bec_widgets/widgets/control/device_input/device_combobox/device_combobox.py +2 -2
  69. bec_widgets/widgets/control/device_input/device_line_edit/device_line_edit.py +2 -2
  70. bec_widgets/widgets/control/device_input/signal_combobox/signal_combobox.py +1 -2
  71. bec_widgets/widgets/control/device_input/signal_line_edit/signal_line_edit.py +1 -2
  72. bec_widgets/widgets/control/scan_control/scan_control.py +7 -5
  73. bec_widgets/widgets/control/scan_control/scan_group_box.py +28 -5
  74. bec_widgets/widgets/dap/dap_combo_box/dap_combo_box.py +1 -2
  75. bec_widgets/widgets/dap/lmfit_dialog/lmfit_dialog.py +3 -4
  76. bec_widgets/widgets/dap/lmfit_dialog/lmfit_dialog_vertical.ui +14 -8
  77. bec_widgets/widgets/editors/console/console.py +1 -1
  78. bec_widgets/widgets/editors/{scan_metadata/additional_metadata_table.py → dict_backed_table.py} +29 -6
  79. bec_widgets/widgets/editors/scan_metadata/__init__.py +0 -7
  80. bec_widgets/widgets/editors/scan_metadata/_util.py +1 -1
  81. bec_widgets/widgets/{plots/motor_map/register_bec_motor_map_widget.py → editors/scan_metadata/register_scan_metadata.py} +2 -4
  82. bec_widgets/widgets/editors/scan_metadata/scan_metadata.py +42 -136
  83. bec_widgets/widgets/editors/scan_metadata/scan_metadata.pyproject +1 -0
  84. bec_widgets/widgets/{plots/multi_waveform/bec_multi_waveform_widget_plugin.py → editors/scan_metadata/scan_metadata_plugin.py} +9 -9
  85. bec_widgets/widgets/editors/text_box/text_box.py +2 -3
  86. bec_widgets/widgets/editors/website/website.py +2 -2
  87. bec_widgets/widgets/games/minesweeper.py +3 -2
  88. bec_widgets/widgets/plots/image/image.py +960 -0
  89. bec_widgets/widgets/plots/image/image.pyproject +1 -0
  90. bec_widgets/widgets/plots/image/image_item.py +279 -0
  91. bec_widgets/widgets/plots/{motor_map/bec_motor_map_widget_plugin.py → image/image_plugin.py} +11 -13
  92. bec_widgets/widgets/{containers/figure/plots → plots}/image/image_processor.py +31 -64
  93. bec_widgets/widgets/plots/image/{register_bec_image_widget.py → register_image.py} +2 -2
  94. bec_widgets/widgets/plots/image/toolbar_bundles/image_selection.py +59 -0
  95. bec_widgets/widgets/plots/image/toolbar_bundles/processing.py +79 -0
  96. bec_widgets/widgets/plots/motor_map/motor_map.py +832 -0
  97. bec_widgets/widgets/plots/motor_map/motor_map.pyproject +1 -0
  98. bec_widgets/widgets/plots/motor_map/motor_map_plugin.py +54 -0
  99. bec_widgets/widgets/plots/{multi_waveform/register_bec_multi_waveform_widget.py → motor_map/register_motor_map.py} +2 -4
  100. bec_widgets/widgets/plots/motor_map/settings/motor_map_settings.py +129 -0
  101. bec_widgets/widgets/plots/motor_map/settings/motor_map_settings.ui +120 -0
  102. bec_widgets/widgets/plots/motor_map/toolbar_bundles/motor_selection.py +70 -0
  103. bec_widgets/widgets/plots/multi_waveform/multi_waveform.py +508 -0
  104. bec_widgets/widgets/plots/multi_waveform/multi_waveform.pyproject +1 -0
  105. bec_widgets/widgets/plots/multi_waveform/multi_waveform_plugin.py +54 -0
  106. bec_widgets/widgets/plots/multi_waveform/register_multi_waveform.py +15 -0
  107. bec_widgets/widgets/plots/multi_waveform/settings/control_panel.py +144 -0
  108. bec_widgets/widgets/plots/multi_waveform/settings/multi_waveform_controls.ui +164 -0
  109. bec_widgets/widgets/plots/multi_waveform/toolbar_bundles/monitor_selection.py +65 -0
  110. bec_widgets/widgets/{plots_next_gen → plots}/plot_base.py +321 -40
  111. bec_widgets/widgets/plots/{waveform/register_bec_waveform_widget.py → scatter_waveform/register_scatter_waveform.py} +3 -3
  112. bec_widgets/widgets/plots/scatter_waveform/scatter_curve.py +197 -0
  113. bec_widgets/widgets/plots/scatter_waveform/scatter_waveform.py +553 -0
  114. bec_widgets/widgets/plots/scatter_waveform/scatter_waveform.pyproject +1 -0
  115. bec_widgets/widgets/plots/{image/bec_image_widget_plugin.py → scatter_waveform/scatter_waveform_plugin.py} +9 -13
  116. bec_widgets/widgets/plots/scatter_waveform/settings/scatter_curve_setting.py +138 -0
  117. bec_widgets/widgets/plots/scatter_waveform/settings/scatter_curve_settings_horizontal.ui +195 -0
  118. bec_widgets/widgets/plots/scatter_waveform/settings/scatter_curve_settings_vertical.ui +204 -0
  119. bec_widgets/widgets/{plots_next_gen → plots}/setting_menus/axis_settings.py +8 -8
  120. bec_widgets/widgets/{plots_next_gen → plots}/toolbar_bundles/mouse_interactions.py +4 -18
  121. bec_widgets/widgets/{plots_next_gen → plots}/toolbar_bundles/plot_export.py +14 -3
  122. bec_widgets/widgets/{plots_next_gen → plots}/toolbar_bundles/roi_bundle.py +6 -1
  123. bec_widgets/widgets/{plots_next_gen → plots}/toolbar_bundles/save_state.py +2 -2
  124. bec_widgets/widgets/{containers/figure/plots/waveform/waveform_curve.py → plots/waveform/curve.py} +119 -49
  125. bec_widgets/widgets/plots/waveform/register_waveform.py +15 -0
  126. bec_widgets/widgets/plots/waveform/settings/curve_settings/curve_setting.py +125 -0
  127. bec_widgets/widgets/plots/waveform/settings/curve_settings/curve_tree.py +576 -0
  128. bec_widgets/widgets/plots/waveform/utils/__init__.py +0 -0
  129. bec_widgets/widgets/plots/waveform/utils/roi_manager.py +84 -0
  130. bec_widgets/widgets/plots/waveform/waveform.py +1794 -0
  131. bec_widgets/widgets/plots/waveform/waveform.pyproject +1 -0
  132. bec_widgets/widgets/plots/waveform/{bec_waveform_widget_plugin.py → waveform_plugin.py} +9 -13
  133. bec_widgets/widgets/progress/bec_progressbar/bec_progressbar.py +1 -2
  134. bec_widgets/widgets/progress/ring_progress_bar/ring.py +11 -10
  135. bec_widgets/widgets/progress/ring_progress_bar/ring_progress_bar.py +24 -14
  136. bec_widgets/widgets/services/bec_queue/bec_queue.py +13 -11
  137. bec_widgets/widgets/services/bec_status_box/bec_status_box.py +3 -4
  138. bec_widgets/widgets/services/device_browser/device_browser.py +5 -2
  139. bec_widgets/widgets/services/device_browser/device_item/device_item.py +1 -1
  140. bec_widgets/widgets/utility/logpanel/logpanel.py +36 -17
  141. bec_widgets/widgets/utility/spinbox/decimal_spinbox.py +3 -3
  142. bec_widgets/widgets/utility/visual/color_button/color_button.py +1 -1
  143. bec_widgets/widgets/utility/visual/colormap_widget/colormap_widget.py +4 -6
  144. bec_widgets/widgets/utility/visual/dark_mode_button/dark_mode_button.py +4 -8
  145. {bec_widgets-1.25.1.dist-info → bec_widgets-2.0.1.dist-info}/METADATA +3 -3
  146. {bec_widgets-1.25.1.dist-info → bec_widgets-2.0.1.dist-info}/RECORD +168 -153
  147. pyproject.toml +3 -3
  148. bec_widgets/applications/alignment/alignment_1d/alignment_1d.py +0 -198
  149. bec_widgets/applications/alignment/alignment_1d/alignment_1d.ui +0 -615
  150. bec_widgets/applications/bec_app.py +0 -84
  151. bec_widgets/cli/auto_updates.py +0 -168
  152. bec_widgets/widgets/containers/figure/__init__.py +0 -1
  153. bec_widgets/widgets/containers/figure/figure.py +0 -796
  154. bec_widgets/widgets/containers/figure/plots/axis_settings.py +0 -91
  155. bec_widgets/widgets/containers/figure/plots/axis_settings.ui +0 -256
  156. bec_widgets/widgets/containers/figure/plots/image/image.py +0 -772
  157. bec_widgets/widgets/containers/figure/plots/image/image_item.py +0 -337
  158. bec_widgets/widgets/containers/figure/plots/motor_map/motor_map.py +0 -525
  159. bec_widgets/widgets/containers/figure/plots/multi_waveform/multi_waveform.py +0 -340
  160. bec_widgets/widgets/containers/figure/plots/plot_base.py +0 -505
  161. bec_widgets/widgets/containers/figure/plots/waveform/waveform.py +0 -1563
  162. bec_widgets/widgets/plots/image/bec_image_widget.pyproject +0 -1
  163. bec_widgets/widgets/plots/image/image_widget.py +0 -515
  164. bec_widgets/widgets/plots/motor_map/bec_motor_map_widget.pyproject +0 -1
  165. bec_widgets/widgets/plots/motor_map/motor_map_dialog/motor_map_settings.py +0 -56
  166. bec_widgets/widgets/plots/motor_map/motor_map_dialog/motor_map_settings.ui +0 -108
  167. bec_widgets/widgets/plots/motor_map/motor_map_widget.py +0 -234
  168. bec_widgets/widgets/plots/multi_waveform/bec_multi_waveform_widget.pyproject +0 -1
  169. bec_widgets/widgets/plots/multi_waveform/multi_waveform_controls.ui +0 -99
  170. bec_widgets/widgets/plots/multi_waveform/multi_waveform_widget.py +0 -536
  171. bec_widgets/widgets/plots/waveform/bec_waveform_widget.pyproject +0 -1
  172. bec_widgets/widgets/plots/waveform/waveform_popups/curve_dialog/curve_dialog.py +0 -336
  173. bec_widgets/widgets/plots/waveform/waveform_popups/curve_dialog/curve_dialog.ui +0 -372
  174. bec_widgets/widgets/plots/waveform/waveform_popups/dap_summary_dialog/dap_summary_dialog.py +0 -25
  175. bec_widgets/widgets/plots/waveform/waveform_widget.py +0 -751
  176. /bec_widgets/{qt_utils → utils}/collapsible_panel_manager.py +0 -0
  177. /bec_widgets/{applications/alignment → utils/forms_from_types}/__init__.py +0 -0
  178. /bec_widgets/{qt_utils → utils}/redis_message_waiter.py +0 -0
  179. /bec_widgets/{applications/alignment/alignment_1d → widgets/containers/auto_update}/__init__.py +0 -0
  180. /bec_widgets/{qt_utils → widgets/containers/main_window/addons}/__init__.py +0 -0
  181. /bec_widgets/widgets/{containers/figure/plots → plots/image/toolbar_bundles}/__init__.py +0 -0
  182. /bec_widgets/widgets/{containers/figure/plots/image → plots/motor_map/settings}/__init__.py +0 -0
  183. /bec_widgets/widgets/{containers/figure/plots/motor_map → plots/motor_map/toolbar_bundles}/__init__.py +0 -0
  184. /bec_widgets/widgets/{containers/figure/plots/multi_waveform → plots/multi_waveform/settings}/__init__.py +0 -0
  185. /bec_widgets/widgets/{containers/figure/plots/waveform → plots/multi_waveform/toolbar_bundles}/__init__.py +0 -0
  186. /bec_widgets/widgets/plots/{motor_map/motor_map_dialog → scatter_waveform}/__init__.py +0 -0
  187. /bec_widgets/widgets/plots/{waveform/waveform_popups → scatter_waveform/settings}/__init__.py +0 -0
  188. /bec_widgets/widgets/plots/{waveform/waveform_popups/curve_dialog → setting_menus}/__init__.py +0 -0
  189. /bec_widgets/widgets/{plots_next_gen → plots}/setting_menus/axis_settings_horizontal.ui +0 -0
  190. /bec_widgets/widgets/{plots_next_gen → plots}/setting_menus/axis_settings_vertical.ui +0 -0
  191. /bec_widgets/widgets/plots/{waveform/waveform_popups/dap_summary_dialog → toolbar_bundles}/__init__.py +0 -0
  192. /bec_widgets/widgets/{plots_next_gen/setting_menus → plots/waveform/settings}/__init__.py +0 -0
  193. /bec_widgets/widgets/{plots_next_gen/toolbar_bundles → plots/waveform/settings/curve_settings}/__init__.py +0 -0
  194. {bec_widgets-1.25.1.dist-info → bec_widgets-2.0.1.dist-info}/WHEEL +0 -0
  195. {bec_widgets-1.25.1.dist-info → bec_widgets-2.0.1.dist-info}/entry_points.txt +0 -0
  196. {bec_widgets-1.25.1.dist-info → bec_widgets-2.0.1.dist-info}/licenses/LICENSE +0 -0
@@ -1,536 +0,0 @@
1
- import os
2
- from typing import Literal
3
-
4
- import pyqtgraph as pg
5
- from bec_lib.device import ReadoutPriority
6
- from bec_lib.logger import bec_logger
7
- from qtpy.QtCore import Slot
8
- from qtpy.QtWidgets import QVBoxLayout, QWidget
9
-
10
- from bec_widgets.qt_utils.error_popups import SafeSlot
11
- from bec_widgets.qt_utils.settings_dialog import SettingsDialog
12
- from bec_widgets.qt_utils.toolbar import (
13
- DeviceSelectionAction,
14
- MaterialIconAction,
15
- ModularToolBar,
16
- SeparatorAction,
17
- WidgetAction,
18
- )
19
- from bec_widgets.utils import UILoader
20
- from bec_widgets.utils.bec_widget import BECWidget
21
- from bec_widgets.widgets.containers.figure import BECFigure
22
- from bec_widgets.widgets.containers.figure.plots.axis_settings import AxisSettings
23
- from bec_widgets.widgets.containers.figure.plots.multi_waveform.multi_waveform import (
24
- BECMultiWaveformConfig,
25
- )
26
- from bec_widgets.widgets.control.device_input.base_classes.device_input_base import BECDeviceFilter
27
- from bec_widgets.widgets.control.device_input.device_combobox.device_combobox import DeviceComboBox
28
- from bec_widgets.widgets.utility.visual.colormap_widget.colormap_widget import BECColorMapWidget
29
-
30
- logger = bec_logger.logger
31
-
32
-
33
- class BECMultiWaveformWidget(BECWidget, QWidget):
34
- PLUGIN = True
35
- ICON_NAME = "ssid_chart"
36
- USER_ACCESS = [
37
- "curves",
38
- "set_monitor",
39
- "set_curve_highlight",
40
- "set_opacity",
41
- "set_curve_limit",
42
- "set_buffer_flush",
43
- "set_highlight_last_curve",
44
- "set_colormap",
45
- "set",
46
- "set_title",
47
- "set_x_label",
48
- "set_y_label",
49
- "set_x_scale",
50
- "set_y_scale",
51
- "set_x_lim",
52
- "set_y_lim",
53
- "set_grid",
54
- "set_colormap",
55
- "enable_fps_monitor",
56
- "lock_aspect_ratio",
57
- "export",
58
- ]
59
-
60
- def __init__(
61
- self,
62
- parent: QWidget | None = None,
63
- config: BECMultiWaveformConfig | dict = None,
64
- client=None,
65
- gui_id: str | None = None,
66
- **kwargs,
67
- ) -> None:
68
- if config is None:
69
- config = BECMultiWaveformConfig(widget_class=self.__class__.__name__)
70
- else:
71
- if isinstance(config, dict):
72
- config = BECMultiWaveformConfig(**config)
73
- super().__init__(client=client, gui_id=gui_id, **kwargs)
74
- QWidget.__init__(self, parent)
75
-
76
- self.layout = QVBoxLayout(self)
77
- self.layout.setSpacing(0)
78
- self.layout.setContentsMargins(0, 0, 0, 0)
79
-
80
- self.fig = BECFigure()
81
- self.colormap_button = BECColorMapWidget(cmap="magma")
82
- self.toolbar = ModularToolBar(
83
- actions={
84
- "monitor": DeviceSelectionAction(
85
- "",
86
- DeviceComboBox(
87
- device_filter=BECDeviceFilter.DEVICE,
88
- readout_priority_filter=ReadoutPriority.ASYNC,
89
- ),
90
- ),
91
- "connect": MaterialIconAction(icon_name="link", tooltip="Connect Device"),
92
- "separator_0": SeparatorAction(),
93
- "colormap": WidgetAction(widget=self.colormap_button),
94
- "separator_1": SeparatorAction(),
95
- "save": MaterialIconAction(icon_name="save", tooltip="Open Export Dialog"),
96
- "matplotlib": MaterialIconAction(
97
- icon_name="photo_library", tooltip="Open Matplotlib Plot"
98
- ),
99
- "separator_2": SeparatorAction(),
100
- "drag_mode": MaterialIconAction(
101
- icon_name="drag_pan", tooltip="Drag Mouse Mode", checkable=True
102
- ),
103
- "rectangle_mode": MaterialIconAction(
104
- icon_name="frame_inspect", tooltip="Rectangle Zoom Mode", checkable=True
105
- ),
106
- "auto_range": MaterialIconAction(
107
- icon_name="open_in_full", tooltip="Autorange Plot"
108
- ),
109
- "crosshair": MaterialIconAction(
110
- icon_name="point_scan", tooltip="Show Crosshair", checkable=True
111
- ),
112
- "separator_3": SeparatorAction(),
113
- "fps_monitor": MaterialIconAction(
114
- icon_name="speed", tooltip="Show FPS Monitor", checkable=True
115
- ),
116
- "axis_settings": MaterialIconAction(
117
- icon_name="settings", tooltip="Open Configuration Dialog"
118
- ),
119
- },
120
- target_widget=self,
121
- )
122
-
123
- self.layout.addWidget(self.toolbar)
124
- self.layout.addWidget(self.fig)
125
-
126
- self.waveform = self.fig.multi_waveform() # FIXME config should be injected here
127
- self.config = config
128
-
129
- self.create_multi_waveform_controls()
130
-
131
- self._hook_actions()
132
- self.waveform.monitor_signal_updated.connect(self.update_controls_limits)
133
-
134
- def create_multi_waveform_controls(self):
135
- """
136
- Create the controls for the multi waveform widget.
137
- """
138
- current_path = os.path.dirname(__file__)
139
- self.controls = UILoader(self).loader(
140
- os.path.join(current_path, "multi_waveform_controls.ui")
141
- )
142
- self.layout.addWidget(self.controls)
143
-
144
- # Hook default controls properties
145
- self.controls.checkbox_highlight.setChecked(self.config.highlight_last_curve)
146
- self.controls.spinbox_opacity.setValue(self.config.opacity)
147
- self.controls.slider_opacity.setValue(self.config.opacity)
148
- self.controls.spinbox_max_trace.setValue(self.config.curve_limit)
149
- self.controls.checkbox_flush_buffer.setChecked(self.config.flush_buffer)
150
-
151
- # Connect signals
152
- self.controls.spinbox_max_trace.valueChanged.connect(self.set_curve_limit)
153
- self.controls.checkbox_flush_buffer.toggled.connect(self.set_buffer_flush)
154
- self.controls.slider_opacity.valueChanged.connect(self.controls.spinbox_opacity.setValue)
155
- self.controls.spinbox_opacity.valueChanged.connect(self.controls.slider_opacity.setValue)
156
- self.controls.slider_opacity.valueChanged.connect(self.set_opacity)
157
- self.controls.spinbox_opacity.valueChanged.connect(self.set_opacity)
158
- self.controls.slider_index.valueChanged.connect(self.controls.spinbox_index.setValue)
159
- self.controls.spinbox_index.valueChanged.connect(self.controls.slider_index.setValue)
160
- self.controls.slider_index.valueChanged.connect(self.set_curve_highlight)
161
- self.controls.spinbox_index.valueChanged.connect(self.set_curve_highlight)
162
- self.controls.checkbox_highlight.toggled.connect(self.set_highlight_last_curve)
163
-
164
- # Trigger first round of settings
165
- self.set_curve_limit(self.config.curve_limit)
166
- self.set_opacity(self.config.opacity)
167
- self.set_highlight_last_curve(self.config.highlight_last_curve)
168
-
169
- @Slot()
170
- def update_controls_limits(self):
171
- """
172
- Update the limits of the controls.
173
- """
174
- num_curves = len(self.waveform.curves)
175
- if num_curves == 0:
176
- num_curves = 1 # Avoid setting max to 0
177
- current_index = num_curves - 1
178
- self.controls.slider_index.setMinimum(0)
179
- self.controls.slider_index.setMaximum(self.waveform.number_of_visible_curves - 1)
180
- self.controls.spinbox_index.setMaximum(self.waveform.number_of_visible_curves - 1)
181
- if self.controls.checkbox_highlight.isChecked():
182
- self.controls.slider_index.setValue(current_index)
183
- self.controls.spinbox_index.setValue(current_index)
184
-
185
- def _hook_actions(self):
186
- self.toolbar.widgets["connect"].action.triggered.connect(self._connect_action)
187
- # Separator 0
188
- self.toolbar.widgets["save"].action.triggered.connect(self.export)
189
- self.toolbar.widgets["matplotlib"].action.triggered.connect(self.export_to_matplotlib)
190
- self.toolbar.widgets["colormap"].widget.colormap_changed_signal.connect(self.set_colormap)
191
- # Separator 1
192
- self.toolbar.widgets["drag_mode"].action.triggered.connect(self.enable_mouse_pan_mode)
193
- self.toolbar.widgets["rectangle_mode"].action.triggered.connect(
194
- self.enable_mouse_rectangle_mode
195
- )
196
- self.toolbar.widgets["auto_range"].action.triggered.connect(self._auto_range_from_toolbar)
197
- self.toolbar.widgets["crosshair"].action.triggered.connect(self.waveform.toggle_crosshair)
198
- # Separator 2
199
- self.toolbar.widgets["fps_monitor"].action.triggered.connect(self.enable_fps_monitor)
200
- self.toolbar.widgets["axis_settings"].action.triggered.connect(self.show_axis_settings)
201
-
202
- ###################################
203
- # Dialog Windows
204
- ###################################
205
- @SafeSlot(popup_error=True)
206
- def _connect_action(self):
207
- monitor_combo = self.toolbar.widgets["monitor"].device_combobox
208
- monitor_name = monitor_combo.currentText()
209
- self.set_monitor(monitor=monitor_name)
210
- monitor_combo.setStyleSheet("QComboBox { background-color: " "; }")
211
-
212
- def show_axis_settings(self):
213
- dialog = SettingsDialog(
214
- self,
215
- settings_widget=AxisSettings(),
216
- window_title="Axis Settings",
217
- config=self.waveform._config_dict["axis"],
218
- )
219
- dialog.exec()
220
-
221
- ########################################
222
- # User Access Methods from MultiWaveform
223
- ########################################
224
- @property
225
- def curves(self) -> list[pg.PlotDataItem]:
226
- """
227
- Get the curves of the plot widget as a list
228
- Returns:
229
- list: List of curves.
230
- """
231
- return list(self.waveform.curves)
232
-
233
- @curves.setter
234
- def curves(self, value: list[pg.PlotDataItem]):
235
- self.waveform.curves = value
236
-
237
- @SafeSlot(popup_error=True)
238
- def set_monitor(self, monitor: str) -> None:
239
- """
240
- Set the monitor of the plot widget.
241
-
242
- Args:
243
- monitor(str): The monitor to set.
244
- """
245
- self.waveform.set_monitor(monitor)
246
- if self.toolbar.widgets["monitor"].device_combobox.currentText() != monitor:
247
- self.toolbar.widgets["monitor"].device_combobox.setCurrentText(monitor)
248
- self.toolbar.widgets["monitor"].device_combobox.setStyleSheet(
249
- "QComboBox { background-color: " "; }"
250
- )
251
-
252
- @SafeSlot(int)
253
- def set_curve_highlight(self, index: int) -> None:
254
- """
255
- Set the curve highlight of the plot widget by index
256
-
257
- Args:
258
- index(int): The index of the curve to highlight.
259
- """
260
- if self.controls.checkbox_highlight.isChecked():
261
- # If always highlighting the last curve, set index to -1
262
- self.waveform.set_curve_highlight(-1)
263
- else:
264
- self.waveform.set_curve_highlight(index)
265
-
266
- @SafeSlot(int)
267
- def set_opacity(self, opacity: int) -> None:
268
- """
269
- Set the opacity of the plot widget.
270
-
271
- Args:
272
- opacity(int): The opacity to set.
273
- """
274
- self.waveform.set_opacity(opacity)
275
-
276
- @SafeSlot(int)
277
- def set_curve_limit(self, curve_limit: int) -> None:
278
- """
279
- Set the maximum number of traces to display on the plot widget.
280
-
281
- Args:
282
- curve_limit(int): The maximum number of traces to display.
283
- """
284
- flush_buffer = self.controls.checkbox_flush_buffer.isChecked()
285
- self.waveform.set_curve_limit(curve_limit, flush_buffer)
286
- self.update_controls_limits()
287
-
288
- @SafeSlot(bool)
289
- def set_buffer_flush(self, flush_buffer: bool) -> None:
290
- """
291
- Set the buffer flush property of the plot widget.
292
-
293
- Args:
294
- flush_buffer(bool): True to flush the buffer, False to not flush the buffer.
295
- """
296
- curve_limit = self.controls.spinbox_max_trace.value()
297
- self.waveform.set_curve_limit(curve_limit, flush_buffer)
298
- self.update_controls_limits()
299
-
300
- @SafeSlot(bool)
301
- def set_highlight_last_curve(self, enable: bool) -> None:
302
- """
303
- Enable or disable highlighting of the last curve.
304
-
305
- Args:
306
- enable(bool): True to enable highlighting of the last curve, False to disable.
307
- """
308
- self.waveform.config.highlight_last_curve = enable
309
- if enable:
310
- self.controls.slider_index.setEnabled(False)
311
- self.controls.spinbox_index.setEnabled(False)
312
- self.controls.checkbox_highlight.setChecked(True)
313
- self.waveform.set_curve_highlight(-1)
314
- else:
315
- self.controls.slider_index.setEnabled(True)
316
- self.controls.spinbox_index.setEnabled(True)
317
- self.controls.checkbox_highlight.setChecked(False)
318
- index = self.controls.spinbox_index.value()
319
- self.waveform.set_curve_highlight(index)
320
-
321
- @SafeSlot()
322
- def set_colormap(self, colormap: str) -> None:
323
- """
324
- Set the colormap of the plot widget.
325
-
326
- Args:
327
- colormap(str): The colormap to set.
328
- """
329
- self.waveform.set_colormap(colormap)
330
-
331
- ###################################
332
- # User Access Methods from PlotBase
333
- ###################################
334
- def set(self, **kwargs):
335
- """
336
- Set the properties of the plot widget.
337
-
338
- Args:
339
- **kwargs: Keyword arguments for the properties to be set.
340
-
341
- Possible properties:
342
- - title: str
343
- - x_label: str
344
- - y_label: str
345
- - x_scale: Literal["linear", "log"]
346
- - y_scale: Literal["linear", "log"]
347
- - x_lim: tuple
348
- - y_lim: tuple
349
- - legend_label_size: int
350
- """
351
- self.waveform.set(**kwargs)
352
-
353
- def set_title(self, title: str):
354
- """
355
- Set the title of the plot widget.
356
-
357
- Args:
358
- title(str): The title to set.
359
- """
360
- self.waveform.set_title(title)
361
-
362
- def set_x_label(self, x_label: str):
363
- """
364
- Set the x-axis label of the plot widget.
365
-
366
- Args:
367
- x_label(str): The x-axis label to set.
368
- """
369
- self.waveform.set_x_label(x_label)
370
-
371
- def set_y_label(self, y_label: str):
372
- """
373
- Set the y-axis label of the plot widget.
374
-
375
- Args:
376
- y_label(str): The y-axis label to set.
377
- """
378
- self.waveform.set_y_label(y_label)
379
-
380
- def set_x_scale(self, x_scale: Literal["linear", "log"]):
381
- """
382
- Set the x-axis scale of the plot widget.
383
-
384
- Args:
385
- x_scale(str): The x-axis scale to set.
386
- """
387
- self.waveform.set_x_scale(x_scale)
388
-
389
- def set_y_scale(self, y_scale: Literal["linear", "log"]):
390
- """
391
- Set the y-axis scale of the plot widget.
392
-
393
- Args:
394
- y_scale(str): The y-axis scale to set.
395
- """
396
- self.waveform.set_y_scale(y_scale)
397
-
398
- def set_x_lim(self, x_lim: tuple):
399
- """
400
- Set x-axis limits of the plot widget.
401
-
402
- Args:
403
- x_lim(tuple): The x-axis limits to set.
404
- """
405
- self.waveform.set_x_lim(x_lim)
406
-
407
- def set_y_lim(self, y_lim: tuple):
408
- """
409
- Set y-axis limits of the plot widget.
410
-
411
- Args:
412
- y_lim(tuple): The y-axis limits to set.
413
- """
414
- self.waveform.set_y_lim(y_lim)
415
-
416
- def set_legend_label_size(self, legend_label_size: int):
417
- """
418
- Set the legend label size of the plot widget.
419
-
420
- Args:
421
- legend_label_size(int): The legend label size to set.
422
- """
423
- self.waveform.set_legend_label_size(legend_label_size)
424
-
425
- def set_auto_range(self, enabled: bool, axis: str = "xy"):
426
- """
427
- Set the auto range of the plot widget.
428
-
429
- Args:
430
- enabled(bool): True to enable auto range, False to disable.
431
- axis(str): The axis to set the auto range for. Default is "xy".
432
- """
433
- self.waveform.set_auto_range(enabled, axis)
434
-
435
- def enable_fps_monitor(self, enabled: bool):
436
- """
437
- Enable or disable the FPS monitor
438
-
439
- Args:
440
- enabled(bool): True to enable the FPS monitor, False to disable.
441
- """
442
- self.waveform.enable_fps_monitor(enabled)
443
- if self.toolbar.widgets["fps_monitor"].action.isChecked() != enabled:
444
- self.toolbar.widgets["fps_monitor"].action.setChecked(enabled)
445
-
446
- @SafeSlot()
447
- def _auto_range_from_toolbar(self):
448
- """
449
- Set the auto range of the plot widget from the toolbar.
450
- """
451
- self.waveform.set_auto_range(True, "xy")
452
-
453
- def set_grid(self, x_grid: bool, y_grid: bool):
454
- """
455
- Set the grid of the plot widget.
456
-
457
- Args:
458
- x_grid(bool): True to enable the x-grid, False to disable.
459
- y_grid(bool): True to enable the y-grid, False to disable.
460
- """
461
- self.waveform.set_grid(x_grid, y_grid)
462
-
463
- def set_outer_axes(self, show: bool):
464
- """
465
- Set the outer axes of the plot widget.
466
-
467
- Args:
468
- show(bool): True to show the outer axes, False to hide.
469
- """
470
- self.waveform.set_outer_axes(show)
471
-
472
- def lock_aspect_ratio(self, lock: bool):
473
- """
474
- Lock the aspect ratio of the plot widget.
475
-
476
- Args:
477
- lock(bool): True to lock the aspect ratio, False to unlock.
478
- """
479
- self.waveform.lock_aspect_ratio(lock)
480
-
481
- @SafeSlot()
482
- def enable_mouse_rectangle_mode(self):
483
- """
484
- Enable the mouse rectangle mode of the plot widget.
485
- """
486
- self.toolbar.widgets["rectangle_mode"].action.setChecked(True)
487
- self.toolbar.widgets["drag_mode"].action.setChecked(False)
488
- self.waveform.plot_item.getViewBox().setMouseMode(pg.ViewBox.RectMode)
489
-
490
- @SafeSlot()
491
- def enable_mouse_pan_mode(self):
492
- """
493
- Enable the mouse pan mode of the plot widget.
494
- """
495
- self.toolbar.widgets["drag_mode"].action.setChecked(True)
496
- self.toolbar.widgets["rectangle_mode"].action.setChecked(False)
497
- self.waveform.plot_item.getViewBox().setMouseMode(pg.ViewBox.PanMode)
498
-
499
- def export(self):
500
- """
501
- Export the plot widget.
502
- """
503
- self.waveform.export()
504
-
505
- def export_to_matplotlib(self):
506
- """
507
- Export the plot widget to matplotlib.
508
- """
509
- try:
510
- import matplotlib as mpl
511
- except ImportError:
512
- self.warning_util.show_warning(
513
- title="Matplotlib not installed",
514
- message="Matplotlib is required for this feature.",
515
- detailed_text="Please install matplotlib in your Python environment by using 'pip install matplotlib'.",
516
- )
517
- return
518
- self.waveform.export_to_matplotlib()
519
-
520
- #######################################
521
- # User Access Methods from BECConnector
522
- ######################################
523
- def cleanup(self):
524
- self.fig.cleanup()
525
- return super().cleanup()
526
-
527
-
528
- if __name__ == "__main__": # pragma: no cover
529
- import sys
530
-
531
- from qtpy.QtWidgets import QApplication
532
-
533
- app = QApplication(sys.argv)
534
- widget = BECMultiWaveformWidget()
535
- widget.show()
536
- sys.exit(app.exec())
@@ -1 +0,0 @@
1
- {'files': ['waveform_widget.py']}