bec-widgets 0.112.0__py3-none-any.whl → 0.113.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 (33) hide show
  1. CHANGELOG.md +46 -48
  2. PKG-INFO +1 -1
  3. bec_widgets/applications/__init__.py +0 -0
  4. bec_widgets/applications/alignment/__init__.py +0 -0
  5. bec_widgets/applications/alignment/alignment_1d/__init__.py +0 -0
  6. bec_widgets/applications/alignment/alignment_1d/alignment_1d.py +265 -0
  7. bec_widgets/applications/alignment/alignment_1d/alignment_1d.ui +869 -0
  8. bec_widgets/assets/app_icons/alignment_1d.png +0 -0
  9. bec_widgets/qt_utils/toolbar.py +3 -1
  10. bec_widgets/utils/bec_signal_proxy.py +54 -0
  11. bec_widgets/utils/linear_region_selector.py +15 -3
  12. bec_widgets/utils/plot_indicator_items.py +247 -0
  13. bec_widgets/widgets/bec_status_box/bec_status_box.py +5 -9
  14. bec_widgets/widgets/bec_status_box/status_item.py +18 -9
  15. bec_widgets/widgets/dap_combo_box/dap_combo_box.py +12 -13
  16. bec_widgets/widgets/figure/plots/plot_base.py +5 -0
  17. bec_widgets/widgets/figure/plots/waveform/waveform.py +17 -15
  18. bec_widgets/widgets/lmfit_dialog/lmfit_dialog.py +151 -16
  19. bec_widgets/widgets/lmfit_dialog/lmfit_dialog_vertical.ui +47 -14
  20. bec_widgets/widgets/positioner_box/positioner_box.py +4 -1
  21. bec_widgets/widgets/scan_control/scan_control.py +38 -0
  22. bec_widgets/widgets/stop_button/stop_button.py +14 -2
  23. {bec_widgets-0.112.0.dist-info → bec_widgets-0.113.0.dist-info}/METADATA +1 -1
  24. {bec_widgets-0.112.0.dist-info → bec_widgets-0.113.0.dist-info}/RECORD +28 -25
  25. pyproject.toml +1 -1
  26. bec_widgets/assets/status_icons/error.svg +0 -3
  27. bec_widgets/assets/status_icons/not_connected.svg +0 -3
  28. bec_widgets/assets/status_icons/refresh.svg +0 -3
  29. bec_widgets/assets/status_icons/running.svg +0 -3
  30. bec_widgets/assets/status_icons/warning.svg +0 -3
  31. {bec_widgets-0.112.0.dist-info → bec_widgets-0.113.0.dist-info}/WHEEL +0 -0
  32. {bec_widgets-0.112.0.dist-info → bec_widgets-0.113.0.dist-info}/entry_points.txt +0 -0
  33. {bec_widgets-0.112.0.dist-info → bec_widgets-0.113.0.dist-info}/licenses/LICENSE +0 -0
CHANGELOG.md CHANGED
@@ -1,5 +1,51 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## v0.113.0 (2024-10-02)
4
+
5
+ ### Feature
6
+
7
+ * feat: add first draft for alignment_1d GUI ([`63c24f9`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/63c24f97a355edaa928b6e222909252b276bcada))
8
+
9
+ * feat: add move to position button to lmfit dialog ([`281cb27`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/281cb27d8b5433e27a7ba0ca0a19e4b45b9c544f))
10
+
11
+ ### Fix
12
+
13
+ * fix: add is_log checks and functionality to plot_indicator_items ([`0f9953e`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/0f9953e8fdcf3f9b5a09f994c69edb6b34756df9))
14
+
15
+ ### Refactor
16
+
17
+ * refactor: various minor improvements for the alignment gui ([`f554f3c`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/f554f3c1672c4fe32968a5991dc98802556a6f3b))
18
+
19
+ * refactor: allow hiding of arg/kwarg boxes ([`efe90eb`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/efe90eb163e2123a5b4d0bb59f66025a569336ad))
20
+
21
+ * refactor: add proxy to waveform to limit the dap_request frequency ([`5c74037`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/5c740371d86d9b1b341bc3c4d8bdf62027aa089b))
22
+
23
+ * refactor: update dap_model also if x and y axis are selected ([`28ee385`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/28ee3856be2c47a63182b16454ece37a0ec04811))
24
+
25
+ * refactor: linear_region_selector accepts log_x data ([`7cc0726`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/7cc07263982a171744ff87adb10ea77585764b71))
26
+
27
+ * refactor: use accent colors for bec_status_box icons; closes #338 ([`e039304`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/e039304fd3ee03dc4a3fa22a69c207139e0c0d28))
28
+
29
+ ### Test
30
+
31
+ * test: add tests for scan_status_callback ([`dc0c825`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/dc0c825fd594c093a24543ff803d6c6564010e92))
32
+
33
+ ### Unknown
34
+
35
+ * feat : Add bec_signal_proxy to handle signals with option to unblock them manually. ([`1dcfeb6`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/1dcfeb6cfce3c69f0c5401731d4d3f9a1981b22e))
36
+
37
+ ## v0.112.1 (2024-09-19)
38
+
39
+ ### Documentation
40
+
41
+ * docs(dap_combo_box): updated screenshot ([`e3b5e33`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/e3b5e338bfaec276979183fb6d79ab41a7ca21e1))
42
+
43
+ * docs(device_box): updated screenshot ([`c8e614b`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/c8e614b575b48be788a6389a7aa0cfa033d86ab8))
44
+
45
+ ### Fix
46
+
47
+ * fix: test e2e dap wait_for_fit ([`b2f7d3c`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/b2f7d3c5f3f4bf00cc628f788e2c278ebb5688ae))
48
+
3
49
  ## v0.112.0 (2024-09-17)
4
50
 
5
51
  ### Feature
@@ -106,54 +152,6 @@
106
152
 
107
153
  ## v0.104.0 (2024-09-04)
108
154
 
109
- ### Documentation
110
-
111
- * docs(scan_control): docs extended ([`730e25f`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/730e25fd3a8be156603005982bfd2a2c2b16dff1))
112
-
113
- ### Feature
114
-
115
- * feat(scan_control): scan control remember the previously set parameters and shares kwarg settings across scans ([`d28f9b0`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/d28f9b04c45385179353cc247221ec821dcaa29b))
116
-
117
155
  ### Fix
118
156
 
119
157
  * fix(scan_control): SafeSlot applied to run_scan to avoid faulty scan requests ([`9047916`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/90479167fb5cae393c884e71a80fcfdb48a76427))
120
-
121
- * fix(scan_control): scan parameters can be loaded from the last executed scan from redis ([`ec3bc8b`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/ec3bc8b5194c680b847d3306c41eef4638ccfcc7))
122
-
123
- * fix(toggle): state can be determined with the widget initialisation ([`2cd9c7f`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/2cd9c7f5854f158468e53b5b29ec31b1ff1e00e6))
124
-
125
- ### Refactor
126
-
127
- * refactor(scan_control): scan control layout adjusted ([`85dcbda`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/85dcbdaa88fe77aeea7012bfc16f10c4f873f75e))
128
-
129
- * refactor(scan_control): basic pydantic config added ([`fe8dc55`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/fe8dc55eb102c51c34bf9606690914da53b5ac02))
130
-
131
- ### Test
132
-
133
- * test(scan_control): tests extended for getting kwargs between scan switching and getting parameters from redis ([`b07e677`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/b07e67715c9284e9bf36056ba4ba8068f60cbaf3))
134
-
135
- * test(conftest): only run cleanup checks if test passed ([`26920f8`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/26920f8482bdb35ece46df37232af50ab9cab463))
136
-
137
- ## v0.103.0 (2024-09-04)
138
-
139
- ### Ci
140
-
141
- * ci: prefill variables for manual pipeline start ([`158c19e`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/158c19eda771562a325fd59405f9fd4cb9a17ed6))
142
-
143
- ### Feature
144
-
145
- * feat(vscode): open vscode on a free port ([`52da835`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/52da835803f2453096a8b7df23bee5fdf93ae2bb))
146
-
147
- * feat(website): added method to wait until the webpage is loaded ([`9be19d4`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/9be19d4abebad08c5fc6bea936dd97475fe8f628))
148
-
149
- ### Fix
150
-
151
- * fix(theme): fixed segfault for webengineview for auto updates ([`9866075`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/9866075100577948755b563dc7b7dc4cdc60d040))
152
-
153
- ### Test
154
-
155
- * test(webview): fixed tests after refactoring ([`d5eb30c`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/d5eb30cd7df4cb0dc3275dd362768afc211eaf2d))
156
-
157
- * test(vscode): popen call does not have to be the only one ([`39f98ec`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/39f98ec223ba8b59e478ac788c08c59ffe886b4e))
158
-
159
- ## v0.102.0 (2024-09-04)
PKG-INFO CHANGED
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: bec_widgets
3
- Version: 0.112.0
3
+ Version: 0.113.0
4
4
  Summary: BEC Widgets
5
5
  Project-URL: Bug Tracker, https://gitlab.psi.ch/bec/bec_widgets/issues
6
6
  Project-URL: Homepage, https://gitlab.psi.ch/bec/bec_widgets
File without changes
File without changes
@@ -0,0 +1,265 @@
1
+ """ This module contains the GUI for the 1D alignment application.
2
+ It is a preliminary version of the GUI, which will be added to the main branch and steadily updated to be improved.
3
+ """
4
+
5
+ import os
6
+ from typing import Optional
7
+
8
+ from bec_lib.device import Positioner as BECPositioner
9
+ from bec_lib.device import Signal as BECSignal
10
+ from bec_lib.endpoints import MessageEndpoints
11
+ from qtpy.QtCore import QSize, Signal
12
+ from qtpy.QtGui import QIcon
13
+ from qtpy.QtWidgets import QCheckBox, QDoubleSpinBox, QPushButton, QSpinBox, QVBoxLayout, QWidget
14
+
15
+ import bec_widgets
16
+ from bec_widgets.qt_utils.error_popups import SafeSlot as Slot
17
+ from bec_widgets.qt_utils.toolbar import WidgetAction
18
+ from bec_widgets.utils import UILoader
19
+ from bec_widgets.utils.bec_widget import BECWidget
20
+ from bec_widgets.utils.colors import get_accent_colors
21
+ from bec_widgets.widgets.bec_progressbar.bec_progressbar import BECProgressBar
22
+ from bec_widgets.widgets.device_line_edit.device_line_edit import DeviceLineEdit
23
+ from bec_widgets.widgets.lmfit_dialog.lmfit_dialog import LMFitDialog
24
+ from bec_widgets.widgets.positioner_box.positioner_box import PositionerBox
25
+ from bec_widgets.widgets.stop_button.stop_button import StopButton
26
+ from bec_widgets.widgets.toggle.toggle import ToggleSwitch
27
+ from bec_widgets.widgets.waveform.waveform_widget import BECWaveformWidget
28
+
29
+ MODULE_PATH = os.path.dirname(bec_widgets.__file__)
30
+
31
+
32
+ class Alignment1D(BECWidget, QWidget):
33
+ """Alignment GUI to perform 1D scans"""
34
+
35
+ # Emit a signal when a motion is ongoing
36
+ motion_is_active = Signal(bool)
37
+
38
+ def __init__(
39
+ self, parent: Optional[QWidget] = None, client=None, gui_id: Optional[str] = None
40
+ ) -> None:
41
+ """Initialise the widget
42
+
43
+ Args:
44
+ parent: Parent widget.
45
+ config: Configuration of the widget.
46
+ client: BEC client object.
47
+ gui_id: GUI ID.
48
+ """
49
+ super().__init__(client=client, gui_id=gui_id)
50
+ QWidget.__init__(self, parent)
51
+ self.get_bec_shortcuts()
52
+ self._accent_colors = get_accent_colors()
53
+ self.ui_file = "alignment_1d.ui"
54
+ self.ui = None
55
+ self.progress_bar = None
56
+ self.waveform = None
57
+ self.init_ui()
58
+
59
+ def init_ui(self):
60
+ """Initialise the UI from QT Designer file"""
61
+ current_path = os.path.dirname(__file__)
62
+ self.ui = UILoader(self).loader(os.path.join(current_path, self.ui_file))
63
+ layout = QVBoxLayout(self)
64
+ layout.addWidget(self.ui)
65
+ self.setLayout(layout)
66
+ # Customize the plotting widget
67
+ self.waveform = self.ui.findChild(BECWaveformWidget, "bec_waveform_widget")
68
+ self._customise_bec_waveform_widget()
69
+ # Setup comboboxes for motor and signal selection
70
+ # FIXME after changing the filtering in the combobox
71
+ self._setup_motor_combobox()
72
+ self._setup_signal_combobox()
73
+ # Setup motor indicator
74
+ self._setup_motor_indicator()
75
+ # Connect spinboxes to scan Control
76
+ self._setup_scan_control()
77
+ # Setup progress bar
78
+ self._setup_progress_bar()
79
+ # Add actions buttons
80
+ self._customise_buttons()
81
+ # Customize the positioner box
82
+ self._customize_positioner_box()
83
+ # Hook scaninfo updates
84
+ self.bec_dispatcher.connect_slot(self.scan_status_callback, MessageEndpoints.scan_status())
85
+
86
+ ##############################
87
+ ############ SLOTS ###########
88
+ ##############################
89
+
90
+ @Slot(dict, dict)
91
+ def scan_status_callback(self, content: dict, _) -> None:
92
+ """This slot allows to enable/disable the UI critical components when a scan is running"""
93
+ if content["status"] in ["open"]:
94
+ self.motion_is_active.emit(True)
95
+ self.enable_ui(False)
96
+ elif content["status"] in ["aborted", "halted", "closed"]:
97
+ self.motion_is_active.emit(False)
98
+ self.enable_ui(True)
99
+
100
+ @Slot(tuple)
101
+ def move_to_center(self, move_request: tuple) -> None:
102
+ """Move the selected motor to the center"""
103
+ motor = self.ui.device_combobox.currentText()
104
+ if move_request[0] in ["center", "center1", "center2"]:
105
+ pos = move_request[1]
106
+ self.dev.get(motor).move(float(pos), relative=False)
107
+
108
+ @Slot()
109
+ def reset_progress_bar(self) -> None:
110
+ """Reset the progress bar"""
111
+ self.progress_bar.set_value(0)
112
+ self.progress_bar.set_minimum(0)
113
+
114
+ @Slot(dict, dict)
115
+ def update_progress_bar(self, content: dict, _) -> None:
116
+ """Hook to update the progress bar
117
+
118
+ Args:
119
+ content: Content of the scan progress message.
120
+ metadata: Metadata of the message.
121
+ """
122
+ if content["max_value"] == 0:
123
+ self.progress_bar.set_value(0)
124
+ return
125
+ self.progress_bar.set_maximum(content["max_value"])
126
+ self.progress_bar.set_value(content["value"])
127
+
128
+ @Slot()
129
+ def clear_queue(self) -> None:
130
+ """Clear the scan queue"""
131
+ self.queue.request_queue_reset()
132
+
133
+ ##############################
134
+ ######## END OF SLOTS ########
135
+ ##############################
136
+
137
+ def enable_ui(self, enable: bool) -> None:
138
+ """Enable or disable the UI components"""
139
+ # Enable/disable motor and signal selection
140
+ self.ui.device_combobox.setEnabled(enable)
141
+ self.ui.device_combobox_2.setEnabled(enable)
142
+ # Enable/disable DAP selection
143
+ self.ui.dap_combo_box.setEnabled(enable)
144
+ # Enable/disable Scan Button
145
+ self.ui.scan_button.setEnabled(enable)
146
+ # Positioner control line
147
+ # pylint: disable=protected-access
148
+ self.ui.positioner_box._toogle_enable_buttons(enable)
149
+ # Disable move to buttons in LMFitDialog
150
+ self.ui.findChild(LMFitDialog).set_actions_enabled(enable)
151
+
152
+ def _customise_buttons(self) -> None:
153
+ """Add action buttons for the Action Control.
154
+ In addition, we are adding a callback to also clear the queue to the stop button
155
+ to ensure that upon clicking the button, no scans from another client may be queued
156
+ which would be confusing without the queue widget.
157
+ """
158
+ fit_dialog = self.ui.findChild(LMFitDialog)
159
+ fit_dialog.active_action_list = ["center", "center1", "center2"]
160
+ fit_dialog.move_action.connect(self.move_to_center)
161
+ scan_button = self.ui.findChild(QPushButton, "scan_button")
162
+ scan_button.setStyleSheet(
163
+ f"""
164
+ QPushButton:enabled {{ background-color: {self._accent_colors.success.name()};color: white; }}
165
+ QPushButton:disabled {{ background-color: grey;color: white; }}
166
+ """
167
+ )
168
+ stop_button = self.ui.findChild(StopButton)
169
+ stop_button.button.setText("Stop and Clear Queue")
170
+ stop_button.button.clicked.connect(self.clear_queue)
171
+
172
+ def _customise_bec_waveform_widget(self) -> None:
173
+ """Customise the BEC Waveform Widget, i.e. clear the toolbar, add the DAP ROI selection to the toolbar.
174
+ We also move the scan_control widget which is fully hidden and solely used for setting up the scan parameters to the toolbar.
175
+ """
176
+ self.waveform.toolbar.clear()
177
+ toggle_switch = self.ui.findChild(ToggleSwitch, "toggle_switch")
178
+ scan_control = self.ui.scan_control
179
+ self.waveform.toolbar.populate_toolbar(
180
+ {
181
+ "label": WidgetAction(label="ENABLE DAP ROI", widget=toggle_switch),
182
+ "scan_control": WidgetAction(widget=scan_control),
183
+ },
184
+ self.waveform,
185
+ )
186
+
187
+ def _setup_motor_indicator(self) -> None:
188
+ """Setup the arrow item"""
189
+ self.waveform.waveform.tick_item.add_to_plot()
190
+ positioner_box = self.ui.findChild(PositionerBox)
191
+ positioner_box.position_update.connect(self.waveform.waveform.tick_item.set_position)
192
+ try:
193
+ pos = float(positioner_box.ui.readback.text())
194
+ except ValueError:
195
+ pos = 0
196
+ self.waveform.waveform.tick_item.set_position(pos)
197
+
198
+ def _setup_motor_combobox(self) -> None:
199
+ """Setup motor selection"""
200
+ # FIXME after changing the filtering in the combobox
201
+ motors = [name for name in self.dev if isinstance(self.dev.get(name), BECPositioner)]
202
+ self.ui.device_combobox.setCurrentText(motors[0])
203
+ self.ui.device_combobox.set_device_filter("Positioner")
204
+
205
+ def _setup_signal_combobox(self) -> None:
206
+ """Setup signal selection"""
207
+ # FIXME after changing the filtering in the combobox
208
+ signals = [name for name in self.dev if isinstance(self.dev.get(name), BECSignal)]
209
+ self.ui.device_combobox_2.setCurrentText(signals[0])
210
+ self.ui.device_combobox_2.set_device_filter("Signal")
211
+
212
+ def _setup_scan_control(self) -> None:
213
+ """Setup scan control, connect spin and check boxes to the scan_control widget"""
214
+ # Connect motor
215
+ device_line_edit = self.ui.scan_control.arg_box.findChild(DeviceLineEdit)
216
+ self.ui.device_combobox.currentTextChanged.connect(device_line_edit.setText)
217
+ device_line_edit.setText(self.ui.device_combobox.currentText())
218
+ # Connect start, stop, step, exp_time and relative check box
219
+ spin_boxes = self.ui.scan_control.arg_box.findChildren(QDoubleSpinBox)
220
+ start = self.ui.findChild(QDoubleSpinBox, "linescan_start")
221
+ start.valueChanged.connect(spin_boxes[0].setValue)
222
+ stop = self.ui.findChild(QDoubleSpinBox, "linescan_stop")
223
+ stop.valueChanged.connect(spin_boxes[1].setValue)
224
+ step = self.ui.findChild(QSpinBox, "linescan_step")
225
+ step.valueChanged.connect(
226
+ self.ui.scan_control.kwarg_boxes[0].findChildren(QSpinBox)[0].setValue
227
+ )
228
+ exp_time = self.ui.findChild(QDoubleSpinBox, "linescan_exp_time")
229
+ exp_time.valueChanged.connect(
230
+ self.ui.scan_control.kwarg_boxes[1].findChildren(QDoubleSpinBox)[0].setValue
231
+ )
232
+ relative = self.ui.findChild(QCheckBox, "linescan_relative")
233
+ relative.toggled.connect(
234
+ self.ui.scan_control.kwarg_boxes[0].findChildren(QCheckBox)[0].setChecked
235
+ )
236
+
237
+ def _setup_progress_bar(self) -> None:
238
+ """Setup progress bar"""
239
+ # FIXME once the BECScanProgressBar is implemented
240
+ self.progress_bar = self.ui.findChild(BECProgressBar, "bec_progress_bar")
241
+ self.progress_bar.set_value(0)
242
+ self.ui.bec_waveform_widget.new_scan.connect(self.reset_progress_bar)
243
+ self.bec_dispatcher.connect_slot(self.update_progress_bar, MessageEndpoints.scan_progress())
244
+
245
+ def _customize_positioner_box(self) -> None:
246
+ """Customize the positioner Box, i.e. remove the stop button"""
247
+ box = self.ui.findChild(PositionerBox)
248
+ box.ui.stop.setVisible(False)
249
+ box.ui.position_indicator.setFixedHeight(20)
250
+
251
+
252
+ if __name__ == "__main__": # pragma: no cover
253
+ import sys
254
+
255
+ from qtpy.QtWidgets import QApplication # pylint: disable=ungrouped-imports
256
+
257
+ app = QApplication(sys.argv)
258
+ icon = QIcon()
259
+ icon.addFile(
260
+ os.path.join(MODULE_PATH, "assets", "app_icons", "alignment_1d.png"), size=QSize(48, 48)
261
+ )
262
+ app.setWindowIcon(icon)
263
+ window = Alignment1D()
264
+ window.show()
265
+ sys.exit(app.exec_())