bec-widgets 1.25.1__py3-none-any.whl → 2.0.0__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 +631 -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 +186 -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.0.dist-info}/METADATA +3 -3
  146. {bec_widgets-1.25.1.dist-info → bec_widgets-2.0.0.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.0.dist-info}/WHEEL +0 -0
  195. {bec_widgets-1.25.1.dist-info → bec_widgets-2.0.0.dist-info}/entry_points.txt +0 -0
  196. {bec_widgets-1.25.1.dist-info → bec_widgets-2.0.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,340 +0,0 @@
1
- from collections import deque
2
- from typing import Literal, Optional
3
-
4
- import pyqtgraph as pg
5
- from bec_lib.endpoints import MessageEndpoints
6
- from bec_lib.logger import bec_logger
7
- from pydantic import Field, field_validator
8
- from pyqtgraph.exporters import MatplotlibExporter
9
- from qtpy.QtCore import Signal, Slot
10
- from qtpy.QtWidgets import QWidget
11
-
12
- from bec_widgets.utils import Colors
13
- from bec_widgets.widgets.containers.figure.plots.plot_base import BECPlotBase, SubplotConfig
14
-
15
- logger = bec_logger.logger
16
-
17
-
18
- class BECMultiWaveformConfig(SubplotConfig):
19
- color_palette: Optional[str] = Field(
20
- "magma", description="The color palette of the figure widget.", validate_default=True
21
- )
22
- curve_limit: Optional[int] = Field(
23
- 200, description="The maximum number of curves to display on the plot."
24
- )
25
- flush_buffer: Optional[bool] = Field(
26
- False, description="Flush the buffer of the plot widget when the curve limit is reached."
27
- )
28
- monitor: Optional[str] = Field(
29
- None, description="The monitor to set for the plot widget."
30
- ) # TODO validate monitor in bec -> maybe make it as SignalData class for validation purpose
31
- curve_width: Optional[int] = Field(1, description="The width of the curve on the plot.")
32
- opacity: Optional[int] = Field(50, description="The opacity of the curve on the plot.")
33
- highlight_last_curve: Optional[bool] = Field(
34
- True, description="Highlight the last curve on the plot."
35
- )
36
-
37
- model_config: dict = {"validate_assignment": True}
38
- _validate_color_map_z = field_validator("color_palette")(Colors.validate_color_map)
39
-
40
-
41
- class BECMultiWaveform(BECPlotBase):
42
- monitor_signal_updated = Signal()
43
- highlighted_curve_index_changed = Signal(int)
44
- USER_ACCESS = [
45
- "_rpc_id",
46
- "_config_dict",
47
- "curves",
48
- "set_monitor",
49
- "set_opacity",
50
- "set_curve_limit",
51
- "set_curve_highlight",
52
- "set_colormap",
53
- "set",
54
- "set_title",
55
- "set_x_label",
56
- "set_y_label",
57
- "set_x_scale",
58
- "set_y_scale",
59
- "set_x_lim",
60
- "set_y_lim",
61
- "set_grid",
62
- "set_colormap",
63
- "enable_fps_monitor",
64
- "lock_aspect_ratio",
65
- "export",
66
- "get_all_data",
67
- "remove",
68
- ]
69
-
70
- def __init__(
71
- self,
72
- parent: Optional[QWidget] = None,
73
- parent_figure=None,
74
- config: Optional[BECMultiWaveformConfig] = None,
75
- client=None,
76
- gui_id: Optional[str] = None,
77
- ):
78
- if config is None:
79
- config = BECMultiWaveformConfig(widget_class=self.__class__.__name__)
80
- super().__init__(
81
- parent=parent, parent_figure=parent_figure, config=config, client=client, gui_id=gui_id
82
- )
83
- self.old_scan_id = None
84
- self.scan_id = None
85
- self.monitor = None
86
- self.connected = False
87
- self.current_highlight_index = 0
88
- self._curves = deque()
89
- self.visible_curves = []
90
- self.number_of_visible_curves = 0
91
-
92
- # Get bec shortcuts dev, scans, queue, scan_storage, dap
93
- self.get_bec_shortcuts()
94
-
95
- @property
96
- def curves(self) -> deque:
97
- """
98
- Get the curves of the plot widget as a deque.
99
- Returns:
100
- deque: Deque of curves.
101
- """
102
- return self._curves
103
-
104
- @curves.setter
105
- def curves(self, value: deque):
106
- self._curves = value
107
-
108
- @property
109
- def highlight_last_curve(self) -> bool:
110
- """
111
- Get the highlight_last_curve property.
112
- Returns:
113
- bool: The highlight_last_curve property.
114
- """
115
- return self.config.highlight_last_curve
116
-
117
- @highlight_last_curve.setter
118
- def highlight_last_curve(self, value: bool):
119
- self.config.highlight_last_curve = value
120
-
121
- def set_monitor(self, monitor: str):
122
- """
123
- Set the monitor for the plot widget.
124
- Args:
125
- monitor (str): The monitor to set.
126
- """
127
- self.config.monitor = monitor
128
- self._connect_monitor()
129
-
130
- def _connect_monitor(self):
131
- """
132
- Connect the monitor to the plot widget.
133
- """
134
- try:
135
- previous_monitor = self.monitor
136
- except AttributeError:
137
- previous_monitor = None
138
-
139
- if previous_monitor and self.connected is True:
140
- self.bec_dispatcher.disconnect_slot(
141
- self.on_monitor_1d_update, MessageEndpoints.device_monitor_1d(previous_monitor)
142
- )
143
- if self.config.monitor and self.connected is False:
144
- self.bec_dispatcher.connect_slot(
145
- self.on_monitor_1d_update, MessageEndpoints.device_monitor_1d(self.config.monitor)
146
- )
147
- self.connected = True
148
- self.monitor = self.config.monitor
149
-
150
- @Slot(dict, dict)
151
- def on_monitor_1d_update(self, msg: dict, metadata: dict):
152
- """
153
- Update the plot widget with the monitor data.
154
-
155
- Args:
156
- msg(dict): The message data.
157
- metadata(dict): The metadata of the message.
158
- """
159
- data = msg.get("data", None)
160
- current_scan_id = metadata.get("scan_id", None)
161
-
162
- if current_scan_id != self.scan_id:
163
- self.scan_id = current_scan_id
164
- self.clear_curves()
165
- self.curves.clear()
166
- if self.crosshair:
167
- self.crosshair.clear_markers()
168
-
169
- # Always create a new curve and add it
170
- curve = pg.PlotDataItem()
171
- curve.setData(data)
172
- self.plot_item.addItem(curve)
173
- self.curves.append(curve)
174
-
175
- # Max Trace and scale colors
176
- self.set_curve_limit(self.config.curve_limit, self.config.flush_buffer)
177
-
178
- self.monitor_signal_updated.emit()
179
-
180
- @Slot(int)
181
- def set_curve_highlight(self, index: int):
182
- """
183
- Set the curve highlight based on visible curves.
184
-
185
- Args:
186
- index (int): The index of the curve to highlight among visible curves.
187
- """
188
- self.plot_item.visible_curves = [curve for curve in self.curves if curve.isVisible()]
189
- num_visible_curves = len(self.plot_item.visible_curves)
190
- self.number_of_visible_curves = num_visible_curves
191
-
192
- if num_visible_curves == 0:
193
- return # No curves to highlight
194
-
195
- if index >= num_visible_curves:
196
- index = num_visible_curves - 1
197
- elif index < 0:
198
- index = num_visible_curves + index
199
- self.current_highlight_index = index
200
- num_colors = num_visible_curves
201
- colors = Colors.evenly_spaced_colors(
202
- colormap=self.config.color_palette, num=num_colors, format="HEX"
203
- )
204
- for i, curve in enumerate(self.plot_item.visible_curves):
205
- curve.setPen()
206
- if i == self.current_highlight_index:
207
- curve.setPen(pg.mkPen(color=colors[i], width=5))
208
- curve.setAlpha(alpha=1, auto=False)
209
- curve.setZValue(1)
210
- else:
211
- curve.setPen(pg.mkPen(color=colors[i], width=1))
212
- curve.setAlpha(alpha=self.config.opacity / 100, auto=False)
213
- curve.setZValue(0)
214
-
215
- self.highlighted_curve_index_changed.emit(self.current_highlight_index)
216
-
217
- @Slot(int)
218
- def set_opacity(self, opacity: int):
219
- """
220
- Set the opacity of the curve on the plot.
221
-
222
- Args:
223
- opacity(int): The opacity of the curve. 0-100.
224
- """
225
- self.config.opacity = max(0, min(100, opacity))
226
- self.set_curve_highlight(self.current_highlight_index)
227
-
228
- @Slot(int, bool)
229
- def set_curve_limit(self, max_trace: int, flush_buffer: bool = False):
230
- """
231
- Set the maximum number of traces to display on the plot.
232
-
233
- Args:
234
- max_trace (int): The maximum number of traces to display.
235
- flush_buffer (bool): Flush the buffer.
236
- """
237
- self.config.curve_limit = max_trace
238
- self.config.flush_buffer = flush_buffer
239
-
240
- if self.config.curve_limit is None:
241
- self.scale_colors()
242
- return
243
-
244
- if self.config.flush_buffer:
245
- # Remove excess curves from the plot and the deque
246
- while len(self.curves) > self.config.curve_limit:
247
- curve = self.curves.popleft()
248
- self.plot_item.removeItem(curve)
249
- else:
250
- # Hide or show curves based on the new max_trace
251
- num_curves_to_show = min(self.config.curve_limit, len(self.curves))
252
- for i, curve in enumerate(self.curves):
253
- if i < len(self.curves) - num_curves_to_show:
254
- curve.hide()
255
- else:
256
- curve.show()
257
- self.scale_colors()
258
-
259
- def scale_colors(self):
260
- """
261
- Scale the colors of the curves based on the current colormap.
262
- """
263
- if self.config.highlight_last_curve:
264
- self.set_curve_highlight(-1) # Use -1 to highlight the last visible curve
265
- else:
266
- self.set_curve_highlight(self.current_highlight_index)
267
-
268
- def set_colormap(self, colormap: str):
269
- """
270
- Set the colormap for the curves.
271
-
272
- Args:
273
- colormap(str): Colormap for the curves.
274
- """
275
- self.config.color_palette = colormap
276
- self.set_curve_highlight(self.current_highlight_index)
277
-
278
- def hook_crosshair(self) -> None:
279
- super().hook_crosshair()
280
- if self.crosshair:
281
- self.highlighted_curve_index_changed.connect(self.crosshair.update_highlighted_curve)
282
- if self.curves:
283
- self.crosshair.update_highlighted_curve(self.current_highlight_index)
284
-
285
- def get_all_data(self, output: Literal["dict", "pandas"] = "dict") -> dict:
286
- """
287
- Extract all curve data into a dictionary or a pandas DataFrame.
288
-
289
- Args:
290
- output (Literal["dict", "pandas"]): Format of the output data.
291
-
292
- Returns:
293
- dict | pd.DataFrame: Data of all curves in the specified format.
294
- """
295
- data = {}
296
- try:
297
- import pandas as pd
298
- except ImportError:
299
- pd = None
300
- if output == "pandas":
301
- logger.warning(
302
- "Pandas is not installed. "
303
- "Please install pandas using 'pip install pandas'."
304
- "Output will be dictionary instead."
305
- )
306
- output = "dict"
307
-
308
- curve_keys = []
309
- curves_list = list(self.curves)
310
- for i, curve in enumerate(curves_list):
311
- x_data, y_data = curve.getData()
312
- if x_data is not None or y_data is not None:
313
- key = f"curve_{i}"
314
- curve_keys.append(key)
315
- if output == "dict":
316
- data[key] = {"x": x_data.tolist(), "y": y_data.tolist()}
317
- elif output == "pandas" and pd is not None:
318
- data[key] = pd.DataFrame({"x": x_data, "y": y_data})
319
-
320
- if output == "pandas" and pd is not None:
321
- combined_data = pd.concat([data[key] for key in curve_keys], axis=1, keys=curve_keys)
322
- return combined_data
323
- return data
324
-
325
- def clear_curves(self):
326
- """
327
- Remove all curves from the plot, excluding crosshair items.
328
- """
329
- items_to_remove = []
330
- for item in self.plot_item.items:
331
- if not getattr(item, "is_crosshair", False) and isinstance(item, pg.PlotDataItem):
332
- items_to_remove.append(item)
333
- for item in items_to_remove:
334
- self.plot_item.removeItem(item)
335
-
336
- def export_to_matplotlib(self):
337
- """
338
- Export current waveform to matplotlib GUI. Available only if matplotlib is installed in the environment.
339
- """
340
- MatplotlibExporter(self.plot_item).export()