bec-widgets 0.55.0__py3-none-any.whl → 0.56.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.
- .gitlab-ci.yml +113 -8
- CHANGELOG.md +34 -28
- PKG-INFO +3 -1
- bec_widgets/examples/jupyter_console/jupyter_console_window.py +28 -38
- bec_widgets/examples/motor_movement/motor_control_compilations.py +1 -7
- bec_widgets/utils/__init__.py +1 -0
- bec_widgets/utils/crosshair.py +13 -9
- bec_widgets/utils/ui_loader.py +58 -0
- bec_widgets/widgets/motor_control/motor_table/motor_table.py +44 -43
- bec_widgets/widgets/motor_control/movement_absolute/movement_absolute.py +25 -23
- bec_widgets/widgets/motor_control/movement_relative/movement_relative.py +51 -48
- bec_widgets/widgets/spiral_progress_bar/ring.py +5 -5
- {bec_widgets-0.55.0.dist-info → bec_widgets-0.56.1.dist-info}/METADATA +3 -1
- {bec_widgets-0.55.0.dist-info → bec_widgets-0.56.1.dist-info}/RECORD +22 -43
- docs/user/apps.md +1 -26
- pyproject.toml +2 -1
- tests/end-2-end/test_bec_dock_rpc_e2e.py +1 -1
- tests/unit_tests/test_client_utils.py +2 -2
- tests/unit_tests/test_crosshair.py +5 -5
- tests/unit_tests/test_motor_control.py +49 -45
- bec_widgets/examples/eiger_plot/__init__.py +0 -0
- bec_widgets/examples/eiger_plot/eiger_plot.py +0 -307
- bec_widgets/examples/eiger_plot/eiger_plot.ui +0 -207
- bec_widgets/examples/mca_readout/__init__.py +0 -0
- bec_widgets/examples/mca_readout/mca_plot.py +0 -159
- bec_widgets/examples/mca_readout/mca_sim.py +0 -28
- bec_widgets/examples/modular_app/___init__.py +0 -0
- bec_widgets/examples/modular_app/modular.ui +0 -92
- bec_widgets/examples/modular_app/modular_app.py +0 -197
- bec_widgets/examples/motor_movement/config_example.yaml +0 -17
- bec_widgets/examples/motor_movement/csax_bec_config.yaml +0 -10
- bec_widgets/examples/motor_movement/csaxs_config.yaml +0 -17
- bec_widgets/examples/motor_movement/motor_example.py +0 -1344
- bec_widgets/examples/stream_plot/__init__.py +0 -0
- bec_widgets/examples/stream_plot/line_plot.ui +0 -155
- bec_widgets/examples/stream_plot/stream_plot.py +0 -337
- docs/user/apps/modular_app.md +0 -6
- docs/user/apps/motor_app.md +0 -34
- docs/user/apps/motor_app_10fps.gif +0 -0
- docs/user/apps/plot_app.md +0 -6
- tests/unit_tests/test_eiger_plot.py +0 -115
- tests/unit_tests/test_stream_plot.py +0 -158
- {bec_widgets-0.55.0.dist-info → bec_widgets-0.56.1.dist-info}/WHEEL +0 -0
- {bec_widgets-0.55.0.dist-info → bec_widgets-0.56.1.dist-info}/licenses/LICENSE +0 -0
@@ -16,6 +16,7 @@ from qtpy.QtWidgets import (
|
|
16
16
|
QTableWidgetItem,
|
17
17
|
)
|
18
18
|
|
19
|
+
from bec_widgets.utils import UILoader
|
19
20
|
from bec_widgets.widgets.motor_control.motor_control import MotorControlWidget
|
20
21
|
|
21
22
|
|
@@ -37,25 +38,25 @@ class MotorCoordinateTable(MotorControlWidget):
|
|
37
38
|
def _load_ui(self):
|
38
39
|
"""Load the UI for the coordinate table."""
|
39
40
|
current_path = os.path.dirname(__file__)
|
40
|
-
|
41
|
+
self.ui = UILoader().load_ui(os.path.join(current_path, "motor_table.ui"), self)
|
41
42
|
|
42
43
|
def _init_ui(self):
|
43
44
|
"""Initialize the UI"""
|
44
45
|
# Setup table behaviour
|
45
46
|
self._setup_table()
|
46
|
-
self.table.setSelectionBehavior(QTableWidget.SelectRows)
|
47
|
+
self.ui.table.setSelectionBehavior(QTableWidget.SelectRows)
|
47
48
|
|
48
49
|
# for tag columns default tag
|
49
50
|
self.tag_counter = 1
|
50
51
|
|
51
52
|
# Connect signals and slots
|
52
|
-
self.checkBox_resize_auto.stateChanged.connect(self.resize_table_auto)
|
53
|
-
self.comboBox_mode.currentIndexChanged.connect(self.mode_switch)
|
53
|
+
self.ui.checkBox_resize_auto.stateChanged.connect(self.resize_table_auto)
|
54
|
+
self.ui.comboBox_mode.currentIndexChanged.connect(self.mode_switch)
|
54
55
|
|
55
56
|
# Keyboard shortcuts for deleting a row
|
56
|
-
self.delete_shortcut = QShortcut(QKeySequence(Qt.Key_Delete), self.table)
|
57
|
+
self.delete_shortcut = QShortcut(QKeySequence(Qt.Key_Delete), self.ui.table)
|
57
58
|
self.delete_shortcut.activated.connect(self.delete_selected_row)
|
58
|
-
self.backspace_shortcut = QShortcut(QKeySequence(Qt.Key_Backspace), self.table)
|
59
|
+
self.backspace_shortcut = QShortcut(QKeySequence(Qt.Key_Backspace), self.ui.table)
|
59
60
|
self.backspace_shortcut.activated.connect(self.delete_selected_row)
|
60
61
|
|
61
62
|
# Warning message for mode switch enable/disable
|
@@ -83,13 +84,13 @@ class MotorCoordinateTable(MotorControlWidget):
|
|
83
84
|
self.mode = self.config["motor_control"].get("mode", "Individual")
|
84
85
|
|
85
86
|
# Set combobox to default mode
|
86
|
-
self.comboBox_mode.setCurrentText(self.mode)
|
87
|
+
self.ui.comboBox_mode.setCurrentText(self.mode)
|
87
88
|
|
88
89
|
self._init_ui()
|
89
90
|
|
90
91
|
def _setup_table(self):
|
91
92
|
"""Setup the table with appropriate headers and configurations."""
|
92
|
-
mode = self.comboBox_mode.currentText()
|
93
|
+
mode = self.ui.comboBox_mode.currentText()
|
93
94
|
|
94
95
|
if mode == "Individual":
|
95
96
|
self._setup_individual_mode()
|
@@ -101,14 +102,14 @@ class MotorCoordinateTable(MotorControlWidget):
|
|
101
102
|
|
102
103
|
def _setup_individual_mode(self):
|
103
104
|
"""Setup the table for individual mode."""
|
104
|
-
self.table.setColumnCount(5)
|
105
|
-
self.table.setHorizontalHeaderLabels(["Show", "Move", "Tag", "X", "Y"])
|
106
|
-
self.table.verticalHeader().setVisible(False)
|
105
|
+
self.ui.table.setColumnCount(5)
|
106
|
+
self.ui.table.setHorizontalHeaderLabels(["Show", "Move", "Tag", "X", "Y"])
|
107
|
+
self.ui.table.verticalHeader().setVisible(False)
|
107
108
|
|
108
109
|
def _setup_start_stop_mode(self):
|
109
110
|
"""Setup the table for start/stop mode."""
|
110
|
-
self.table.setColumnCount(8)
|
111
|
-
self.table.setHorizontalHeaderLabels(
|
111
|
+
self.ui.table.setColumnCount(8)
|
112
|
+
self.ui.table.setHorizontalHeaderLabels(
|
112
113
|
[
|
113
114
|
"Show",
|
114
115
|
"Move [start]",
|
@@ -120,15 +121,15 @@ class MotorCoordinateTable(MotorControlWidget):
|
|
120
121
|
"Y [end]",
|
121
122
|
]
|
122
123
|
)
|
123
|
-
self.table.verticalHeader().setVisible(False)
|
124
|
+
self.ui.table.verticalHeader().setVisible(False)
|
124
125
|
# Set flag to track if the coordinate is stat or the end of the entry
|
125
126
|
self.is_next_entry_end = False
|
126
127
|
|
127
128
|
def mode_switch(self):
|
128
129
|
"""Switch between individual and start/stop mode."""
|
129
|
-
last_selected_index = self.comboBox_mode.currentIndex()
|
130
|
+
last_selected_index = self.ui.comboBox_mode.currentIndex()
|
130
131
|
|
131
|
-
if self.table.rowCount() > 0 and self.warning_message is True:
|
132
|
+
if self.ui.table.rowCount() > 0 and self.warning_message is True:
|
132
133
|
msgBox = QMessageBox()
|
133
134
|
msgBox.setIcon(QMessageBox.Critical)
|
134
135
|
msgBox.setText(
|
@@ -138,9 +139,9 @@ class MotorCoordinateTable(MotorControlWidget):
|
|
138
139
|
returnValue = msgBox.exec()
|
139
140
|
|
140
141
|
if returnValue is QMessageBox.Cancel:
|
141
|
-
self.comboBox_mode.blockSignals(True) # Block signals
|
142
|
-
self.comboBox_mode.setCurrentIndex(last_selected_index)
|
143
|
-
self.comboBox_mode.blockSignals(False) # Unblock signals
|
142
|
+
self.ui.comboBox_mode.blockSignals(True) # Block signals
|
143
|
+
self.ui.comboBox_mode.setCurrentIndex(last_selected_index)
|
144
|
+
self.ui.comboBox_mode.blockSignals(False) # Unblock signals
|
144
145
|
return
|
145
146
|
|
146
147
|
# Wipe table
|
@@ -170,7 +171,7 @@ class MotorCoordinateTable(MotorControlWidget):
|
|
170
171
|
y(float): Y coordinate.
|
171
172
|
"""
|
172
173
|
|
173
|
-
mode = self.comboBox_mode.currentText()
|
174
|
+
mode = self.ui.comboBox_mode.currentText()
|
174
175
|
if mode == "Individual":
|
175
176
|
checkbox_pos = 0
|
176
177
|
button_pos = 1
|
@@ -181,8 +182,8 @@ class MotorCoordinateTable(MotorControlWidget):
|
|
181
182
|
color = "green"
|
182
183
|
|
183
184
|
# Add new row -> new entry
|
184
|
-
row_count = self.table.rowCount()
|
185
|
-
self.table.insertRow(row_count)
|
185
|
+
row_count = self.ui.table.rowCount()
|
186
|
+
self.ui.table.insertRow(row_count)
|
186
187
|
|
187
188
|
# Add Widgets
|
188
189
|
self._add_widgets(
|
@@ -213,8 +214,8 @@ class MotorCoordinateTable(MotorControlWidget):
|
|
213
214
|
color = "blue"
|
214
215
|
|
215
216
|
# Add new row -> new entry
|
216
|
-
row_count = self.table.rowCount()
|
217
|
-
self.table.insertRow(row_count)
|
217
|
+
row_count = self.ui.table.rowCount()
|
218
|
+
self.ui.table.insertRow(row_count)
|
218
219
|
|
219
220
|
# Add Widgets
|
220
221
|
self._add_widgets(
|
@@ -236,7 +237,7 @@ class MotorCoordinateTable(MotorControlWidget):
|
|
236
237
|
|
237
238
|
elif self.is_next_entry_end is True: # It is the end position of the entry
|
238
239
|
print("End position")
|
239
|
-
row_count = self.table.rowCount() - 1 # Current row
|
240
|
+
row_count = self.ui.table.rowCount() - 1 # Current row
|
240
241
|
button_pos = 2
|
241
242
|
x_pos = 6
|
242
243
|
y_pos = 7
|
@@ -294,7 +295,7 @@ class MotorCoordinateTable(MotorControlWidget):
|
|
294
295
|
# Add widgets
|
295
296
|
self._add_checkbox(row, checkBox_pos, x_pos, y_pos)
|
296
297
|
self._add_move_button(row, button_pos, x_pos, y_pos)
|
297
|
-
self.table.setItem(row, tag_pos, QTableWidgetItem(tag))
|
298
|
+
self.ui.table.setItem(row, tag_pos, QTableWidgetItem(tag))
|
298
299
|
self._add_line_edit(x, row, x_pos, x_pos, y_pos, coordinate_reference, color)
|
299
300
|
self._add_line_edit(y, row, y_pos, x_pos, y_pos, coordinate_reference, color)
|
300
301
|
|
@@ -302,10 +303,10 @@ class MotorCoordinateTable(MotorControlWidget):
|
|
302
303
|
self.emit_plot_coordinates(x_pos, y_pos, coordinate_reference, color)
|
303
304
|
|
304
305
|
# Connect item edit to emit coordinates
|
305
|
-
self.table.itemChanged.connect(
|
306
|
+
self.ui.table.itemChanged.connect(
|
306
307
|
lambda: print(f"item changed from {coordinate_reference} slot \n {x}-{y}-{color}")
|
307
308
|
)
|
308
|
-
self.table.itemChanged.connect(
|
309
|
+
self.ui.table.itemChanged.connect(
|
309
310
|
lambda: self.emit_plot_coordinates(x_pos, y_pos, coordinate_reference, color)
|
310
311
|
)
|
311
312
|
|
@@ -321,7 +322,7 @@ class MotorCoordinateTable(MotorControlWidget):
|
|
321
322
|
show_checkbox = QCheckBox()
|
322
323
|
show_checkbox.setChecked(True)
|
323
324
|
show_checkbox.stateChanged.connect(lambda: self.emit_plot_coordinates(x_pos, y_pos))
|
324
|
-
self.table.setCellWidget(row, checkBox_pos, show_checkbox)
|
325
|
+
self.ui.table.setCellWidget(row, checkBox_pos, show_checkbox)
|
325
326
|
|
326
327
|
def _add_move_button(self, row: int, button_pos: int, x_pos: int, y_pos: int) -> None:
|
327
328
|
"""
|
@@ -334,7 +335,7 @@ class MotorCoordinateTable(MotorControlWidget):
|
|
334
335
|
"""
|
335
336
|
move_button = QPushButton("Move")
|
336
337
|
move_button.clicked.connect(lambda: self.handle_move_button_click(x_pos, y_pos))
|
337
|
-
self.table.setCellWidget(row, button_pos, move_button)
|
338
|
+
self.ui.table.setCellWidget(row, button_pos, move_button)
|
338
339
|
|
339
340
|
def _add_line_edit(
|
340
341
|
self,
|
@@ -367,7 +368,7 @@ class MotorCoordinateTable(MotorControlWidget):
|
|
367
368
|
edit.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
368
369
|
|
369
370
|
# Add line edit to the table
|
370
|
-
self.table.setCellWidget(row, line_pos, edit)
|
371
|
+
self.ui.table.setCellWidget(row, line_pos, edit)
|
371
372
|
edit.textChanged.connect(
|
372
373
|
lambda: self.emit_plot_coordinates(x_pos, y_pos, coordinate_reference, color)
|
373
374
|
)
|
@@ -375,10 +376,10 @@ class MotorCoordinateTable(MotorControlWidget):
|
|
375
376
|
def wipe_motor_map_coordinates(self):
|
376
377
|
"""Wipe the motor map coordinates."""
|
377
378
|
try:
|
378
|
-
self.table.itemChanged.disconnect() # Disconnect all previous connections
|
379
|
+
self.ui.table.itemChanged.disconnect() # Disconnect all previous connections
|
379
380
|
except TypeError:
|
380
381
|
print("No previous connections to disconnect")
|
381
|
-
self.table.setRowCount(0)
|
382
|
+
self.ui.table.setRowCount(0)
|
382
383
|
reference_tags = ["Individual", "Start", "Stop"]
|
383
384
|
for reference_tag in reference_tags:
|
384
385
|
self.plot_coordinates_signal.emit([], reference_tag, "green")
|
@@ -391,7 +392,7 @@ class MotorCoordinateTable(MotorControlWidget):
|
|
391
392
|
y_pos(int): Y position of the coordinate.
|
392
393
|
"""
|
393
394
|
button = self.sender()
|
394
|
-
row = self.table.indexAt(button.pos()).row()
|
395
|
+
row = self.ui.table.indexAt(button.pos()).row()
|
395
396
|
|
396
397
|
x = self.get_coordinate(row, x_pos)
|
397
398
|
y = self.get_coordinate(row, y_pos)
|
@@ -410,8 +411,8 @@ class MotorCoordinateTable(MotorControlWidget):
|
|
410
411
|
f"Emitting plot coordinates: x_pos={x_pos}, y_pos={y_pos}, reference_tag={reference_tag}, color={color}"
|
411
412
|
)
|
412
413
|
coordinates = []
|
413
|
-
for row in range(self.table.rowCount()):
|
414
|
-
show = self.table.cellWidget(row, 0).isChecked()
|
414
|
+
for row in range(self.ui.table.rowCount()):
|
415
|
+
show = self.ui.table.cellWidget(row, 0).isChecked()
|
415
416
|
x = self.get_coordinate(row, x_pos)
|
416
417
|
y = self.get_coordinate(row, y_pos)
|
417
418
|
|
@@ -427,27 +428,27 @@ class MotorCoordinateTable(MotorControlWidget):
|
|
427
428
|
Returns:
|
428
429
|
float: Value of the coordinate.
|
429
430
|
"""
|
430
|
-
edit = self.table.cellWidget(row, column)
|
431
|
+
edit = self.ui.table.cellWidget(row, column)
|
431
432
|
value = float(edit.text()) if edit and edit.text() != "" else None
|
432
433
|
if value:
|
433
434
|
return value
|
434
435
|
|
435
436
|
def delete_selected_row(self):
|
436
437
|
"""Delete the selected row from the table."""
|
437
|
-
selected_rows = self.table.selectionModel().selectedRows()
|
438
|
+
selected_rows = self.ui.table.selectionModel().selectedRows()
|
438
439
|
for row in selected_rows:
|
439
|
-
self.table.removeRow(row.row())
|
440
|
-
if self.comboBox_mode.currentText() == "Start/Stop":
|
440
|
+
self.ui.table.removeRow(row.row())
|
441
|
+
if self.ui.comboBox_mode.currentText() == "Start/Stop":
|
441
442
|
self.emit_plot_coordinates(x_pos=4, y_pos=5, reference_tag="Start", color="blue")
|
442
443
|
self.emit_plot_coordinates(x_pos=6, y_pos=7, reference_tag="Stop", color="red")
|
443
444
|
self.is_next_entry_end = False
|
444
|
-
elif self.comboBox_mode.currentText() == "Individual":
|
445
|
+
elif self.ui.comboBox_mode.currentText() == "Individual":
|
445
446
|
self.emit_plot_coordinates(x_pos=3, y_pos=4, reference_tag="Individual", color="green")
|
446
447
|
|
447
448
|
def resize_table_auto(self):
|
448
449
|
"""Resize the table to fit the contents."""
|
449
|
-
if self.checkBox_resize_auto.isChecked():
|
450
|
-
self.table.resizeColumnsToContents()
|
450
|
+
if self.ui.checkBox_resize_auto.isChecked():
|
451
|
+
self.ui.table.resizeColumnsToContents()
|
451
452
|
|
452
453
|
def move_motor(self, x: float, y: float) -> None:
|
453
454
|
"""
|
@@ -3,8 +3,10 @@ import os
|
|
3
3
|
from qtpy import uic
|
4
4
|
from qtpy.QtCore import Signal as pyqtSignal
|
5
5
|
from qtpy.QtCore import Slot as pyqtSlot
|
6
|
+
from qtpy.QtWidgets import QWidget
|
6
7
|
|
7
|
-
from bec_widgets.
|
8
|
+
from bec_widgets.utils import UILoader
|
9
|
+
from bec_widgets.widgets.motor_control.motor_control import MotorControlErrors, MotorControlWidget
|
8
10
|
|
9
11
|
|
10
12
|
class MotorControlAbsolute(MotorControlWidget):
|
@@ -23,26 +25,26 @@ class MotorControlAbsolute(MotorControlWidget):
|
|
23
25
|
def _load_ui(self):
|
24
26
|
"""Load the UI from the .ui file."""
|
25
27
|
current_path = os.path.dirname(__file__)
|
26
|
-
|
28
|
+
self.ui = UILoader().load_ui(os.path.join(current_path, "movement_absolute.ui"), self)
|
27
29
|
|
28
30
|
def _init_ui(self):
|
29
31
|
"""Initialize the UI."""
|
30
32
|
|
31
33
|
# Check if there are any motors connected
|
32
34
|
if self.motor_x is None or self.motor_y is None:
|
33
|
-
self.motorControl_absolute.setEnabled(False)
|
35
|
+
self.ui.motorControl_absolute.setEnabled(False)
|
34
36
|
return
|
35
37
|
|
36
38
|
# Move to absolute coordinates
|
37
|
-
self.pushButton_go_absolute.clicked.connect(
|
39
|
+
self.ui.pushButton_go_absolute.clicked.connect(
|
38
40
|
lambda: self.move_motor_absolute(
|
39
|
-
self.spinBox_absolute_x.value(), self.spinBox_absolute_y.value()
|
41
|
+
self.ui.spinBox_absolute_x.value(), self.ui.spinBox_absolute_y.value()
|
40
42
|
)
|
41
43
|
)
|
42
44
|
|
43
|
-
self.pushButton_set.clicked.connect(self.save_absolute_coordinates)
|
44
|
-
self.pushButton_save.clicked.connect(self.save_current_coordinates)
|
45
|
-
self.pushButton_stop.clicked.connect(self.motor_thread.stop_movement)
|
45
|
+
self.ui.pushButton_set.clicked.connect(self.save_absolute_coordinates)
|
46
|
+
self.ui.pushButton_save.clicked.connect(self.save_current_coordinates)
|
47
|
+
self.ui.pushButton_stop.clicked.connect(self.motor_thread.stop_movement)
|
46
48
|
|
47
49
|
# Enable/Disable GUI
|
48
50
|
self.motor_thread.lock_gui.connect(self.enable_motor_controls)
|
@@ -80,11 +82,11 @@ class MotorControlAbsolute(MotorControlWidget):
|
|
80
82
|
"""
|
81
83
|
|
82
84
|
# Disable or enable all controls within the motorControl_absolute group box
|
83
|
-
for widget in self.motorControl_absolute.findChildren(QWidget):
|
85
|
+
for widget in self.ui.motorControl_absolute.findChildren(QWidget):
|
84
86
|
widget.setEnabled(enable)
|
85
87
|
|
86
88
|
# Enable the pushButton_stop if the motor is moving
|
87
|
-
self.pushButton_stop.setEnabled(True)
|
89
|
+
self.ui.pushButton_stop.setEnabled(True)
|
88
90
|
|
89
91
|
@pyqtSlot(str, str)
|
90
92
|
def change_motors(self, motor_x: str, motor_y: str):
|
@@ -109,8 +111,8 @@ class MotorControlAbsolute(MotorControlWidget):
|
|
109
111
|
"""
|
110
112
|
self.precision = precision
|
111
113
|
self.config["motor_control"]["precision"] = precision
|
112
|
-
self.spinBox_absolute_x.setDecimals(precision)
|
113
|
-
self.spinBox_absolute_y.setDecimals(precision)
|
114
|
+
self.ui.spinBox_absolute_x.setDecimals(precision)
|
115
|
+
self.ui.spinBox_absolute_y.setDecimals(precision)
|
114
116
|
|
115
117
|
def move_motor_absolute(self, x: float, y: float) -> None:
|
116
118
|
"""
|
@@ -122,32 +124,32 @@ class MotorControlAbsolute(MotorControlWidget):
|
|
122
124
|
# self._enable_motor_controls(False)
|
123
125
|
target_coordinates = (x, y)
|
124
126
|
self.motor_thread.move_absolute(self.motor_x, self.motor_y, target_coordinates)
|
125
|
-
if self.checkBox_save_with_go.isChecked():
|
127
|
+
if self.ui.checkBox_save_with_go.isChecked():
|
126
128
|
self.save_absolute_coordinates()
|
127
129
|
|
128
130
|
def _init_keyboard_shortcuts(self):
|
129
131
|
"""Initialize the keyboard shortcuts."""
|
130
132
|
# Go absolute button
|
131
|
-
self.pushButton_go_absolute.setShortcut("Ctrl+G")
|
132
|
-
self.pushButton_go_absolute.setToolTip("Ctrl+G")
|
133
|
+
self.ui.pushButton_go_absolute.setShortcut("Ctrl+G")
|
134
|
+
self.ui.pushButton_go_absolute.setToolTip("Ctrl+G")
|
133
135
|
|
134
136
|
# Set absolute coordinates
|
135
|
-
self.pushButton_set.setShortcut("Ctrl+D")
|
136
|
-
self.pushButton_set.setToolTip("Ctrl+D")
|
137
|
+
self.ui.pushButton_set.setShortcut("Ctrl+D")
|
138
|
+
self.ui.pushButton_set.setToolTip("Ctrl+D")
|
137
139
|
|
138
140
|
# Save Current coordinates
|
139
|
-
self.pushButton_save.setShortcut("Ctrl+S")
|
140
|
-
self.pushButton_save.setToolTip("Ctrl+S")
|
141
|
+
self.ui.pushButton_save.setShortcut("Ctrl+S")
|
142
|
+
self.ui.pushButton_save.setToolTip("Ctrl+S")
|
141
143
|
|
142
144
|
# Stop Button
|
143
|
-
self.pushButton_stop.setShortcut("Ctrl+X")
|
144
|
-
self.pushButton_stop.setToolTip("Ctrl+X")
|
145
|
+
self.ui.pushButton_stop.setShortcut("Ctrl+X")
|
146
|
+
self.ui.pushButton_stop.setToolTip("Ctrl+X")
|
145
147
|
|
146
148
|
def save_absolute_coordinates(self):
|
147
149
|
"""Emit the setup coordinates from the spinboxes"""
|
148
150
|
|
149
|
-
x, y = round(self.spinBox_absolute_x.value(), self.precision), round(
|
150
|
-
self.spinBox_absolute_y.value(), self.precision
|
151
|
+
x, y = round(self.ui.spinBox_absolute_x.value(), self.precision), round(
|
152
|
+
self.ui.spinBox_absolute_y.value(), self.precision
|
151
153
|
)
|
152
154
|
self.coordinates_signal.emit((x, y))
|
153
155
|
|
@@ -7,6 +7,7 @@ from qtpy.QtCore import Slot as pyqtSlot
|
|
7
7
|
from qtpy.QtGui import QKeySequence
|
8
8
|
from qtpy.QtWidgets import QDoubleSpinBox, QShortcut, QWidget
|
9
9
|
|
10
|
+
from bec_widgets.utils import UILoader
|
10
11
|
from bec_widgets.widgets.motor_control.motor_control import MotorControlWidget
|
11
12
|
|
12
13
|
|
@@ -27,7 +28,7 @@ class MotorControlRelative(MotorControlWidget):
|
|
27
28
|
"""Load the UI from the .ui file."""
|
28
29
|
# Loading UI
|
29
30
|
current_path = os.path.dirname(__file__)
|
30
|
-
|
31
|
+
self.ui = UILoader().load_ui(os.path.join(current_path, "movement_relative.ui"), self)
|
31
32
|
|
32
33
|
def _init_ui(self):
|
33
34
|
"""Initialize the UI."""
|
@@ -51,15 +52,15 @@ class MotorControlRelative(MotorControlWidget):
|
|
51
52
|
|
52
53
|
# Update step precision
|
53
54
|
self.precision = self.config["motor_control"]["precision"]
|
54
|
-
self.spinBox_precision.setValue(self.precision)
|
55
|
+
self.ui.spinBox_precision.setValue(self.precision)
|
55
56
|
|
56
57
|
# Update step sizes
|
57
|
-
self.spinBox_step_x.setValue(self.config["motor_control"]["step_size_x"])
|
58
|
-
self.spinBox_step_y.setValue(self.config["motor_control"]["step_size_y"])
|
58
|
+
self.ui.spinBox_step_x.setValue(self.config["motor_control"]["step_size_x"])
|
59
|
+
self.ui.spinBox_step_y.setValue(self.config["motor_control"]["step_size_y"])
|
59
60
|
|
60
61
|
# Checkboxes for keyboard shortcuts and x/y step size link
|
61
|
-
self.checkBox_same_xy.setChecked(self.config["motor_control"]["step_x_y_same"])
|
62
|
-
self.checkBox_enableArrows.setChecked(self.config["motor_control"]["move_with_arrows"])
|
62
|
+
self.ui.checkBox_same_xy.setChecked(self.config["motor_control"]["step_x_y_same"])
|
63
|
+
self.ui.checkBox_enableArrows.setChecked(self.config["motor_control"]["move_with_arrows"])
|
63
64
|
|
64
65
|
self._init_ui()
|
65
66
|
|
@@ -67,30 +68,32 @@ class MotorControlRelative(MotorControlWidget):
|
|
67
68
|
"""Initialize the motor control elements"""
|
68
69
|
|
69
70
|
# Connect checkbox and spinBoxes
|
70
|
-
self.checkBox_same_xy.stateChanged.connect(self._sync_step_sizes)
|
71
|
-
self.spinBox_step_x.valueChanged.connect(self._update_step_size_x)
|
72
|
-
self.spinBox_step_y.valueChanged.connect(self._update_step_size_y)
|
71
|
+
self.ui.checkBox_same_xy.stateChanged.connect(self._sync_step_sizes)
|
72
|
+
self.ui.spinBox_step_x.valueChanged.connect(self._update_step_size_x)
|
73
|
+
self.ui.spinBox_step_y.valueChanged.connect(self._update_step_size_y)
|
73
74
|
|
74
|
-
self.toolButton_right.clicked.connect(
|
75
|
+
self.ui.toolButton_right.clicked.connect(
|
75
76
|
lambda: self.move_motor_relative(self.motor_x, "x", 1)
|
76
77
|
)
|
77
|
-
self.toolButton_left.clicked.connect(
|
78
|
+
self.ui.toolButton_left.clicked.connect(
|
78
79
|
lambda: self.move_motor_relative(self.motor_x, "x", -1)
|
79
80
|
)
|
80
|
-
self.toolButton_up.clicked.connect(
|
81
|
-
|
81
|
+
self.ui.toolButton_up.clicked.connect(
|
82
|
+
lambda: self.move_motor_relative(self.motor_y, "y", 1)
|
83
|
+
)
|
84
|
+
self.ui.toolButton_down.clicked.connect(
|
82
85
|
lambda: self.move_motor_relative(self.motor_y, "y", -1)
|
83
86
|
)
|
84
87
|
|
85
88
|
# Switch between key shortcuts active
|
86
|
-
self.checkBox_enableArrows.stateChanged.connect(self._update_arrow_key_shortcuts)
|
89
|
+
self.ui.checkBox_enableArrows.stateChanged.connect(self._update_arrow_key_shortcuts)
|
87
90
|
self._update_arrow_key_shortcuts()
|
88
91
|
|
89
92
|
# Enable/Disable GUI
|
90
93
|
self.motor_thread.lock_gui.connect(self.enable_motor_controls)
|
91
94
|
|
92
95
|
# Precision update
|
93
|
-
self.spinBox_precision.valueChanged.connect(lambda x: self._update_precision(x))
|
96
|
+
self.ui.spinBox_precision.valueChanged.connect(lambda x: self._update_precision(x))
|
94
97
|
|
95
98
|
# Error messages
|
96
99
|
self.motor_thread.motor_error.connect(
|
@@ -98,7 +101,7 @@ class MotorControlRelative(MotorControlWidget):
|
|
98
101
|
)
|
99
102
|
|
100
103
|
# Stop Button
|
101
|
-
self.pushButton_stop.clicked.connect(self.motor_thread.stop_movement)
|
104
|
+
self.ui.pushButton_stop.clicked.connect(self.motor_thread.stop_movement)
|
102
105
|
|
103
106
|
def _init_keyboard_shortcuts(self) -> None:
|
104
107
|
"""Initialize the keyboard shortcuts"""
|
@@ -107,42 +110,42 @@ class MotorControlRelative(MotorControlWidget):
|
|
107
110
|
increase_x_shortcut = QShortcut(QKeySequence("Ctrl+A"), self)
|
108
111
|
decrease_x_shortcut = QShortcut(QKeySequence("Ctrl+Z"), self)
|
109
112
|
increase_x_shortcut.activated.connect(
|
110
|
-
lambda: self._change_step_size(self.spinBox_step_x, 2)
|
113
|
+
lambda: self._change_step_size(self.ui.spinBox_step_x, 2)
|
111
114
|
)
|
112
115
|
decrease_x_shortcut.activated.connect(
|
113
|
-
lambda: self._change_step_size(self.spinBox_step_x, 0.5)
|
116
|
+
lambda: self._change_step_size(self.ui.spinBox_step_x, 0.5)
|
114
117
|
)
|
115
|
-
self.spinBox_step_x.setToolTip("Increase step size: Ctrl+A\nDecrease step size: Ctrl+Z")
|
118
|
+
self.ui.spinBox_step_x.setToolTip("Increase step size: Ctrl+A\nDecrease step size: Ctrl+Z")
|
116
119
|
|
117
120
|
# Increase/decrease step size for Y motor
|
118
121
|
increase_y_shortcut = QShortcut(QKeySequence("Alt+A"), self)
|
119
122
|
decrease_y_shortcut = QShortcut(QKeySequence("Alt+Z"), self)
|
120
123
|
increase_y_shortcut.activated.connect(
|
121
|
-
lambda: self._change_step_size(self.spinBox_step_y, 2)
|
124
|
+
lambda: self._change_step_size(self.ui.spinBox_step_y, 2)
|
122
125
|
)
|
123
126
|
decrease_y_shortcut.activated.connect(
|
124
|
-
lambda: self._change_step_size(self.spinBox_step_y, 0.5)
|
127
|
+
lambda: self._change_step_size(self.ui.spinBox_step_y, 0.5)
|
125
128
|
)
|
126
|
-
self.spinBox_step_y.setToolTip("Increase step size: Alt+A\nDecrease step size: Alt+Z")
|
129
|
+
self.ui.spinBox_step_y.setToolTip("Increase step size: Alt+A\nDecrease step size: Alt+Z")
|
127
130
|
|
128
131
|
# Stop Button
|
129
|
-
self.pushButton_stop.setShortcut("Ctrl+X")
|
130
|
-
self.pushButton_stop.setToolTip("Ctrl+X")
|
132
|
+
self.ui.pushButton_stop.setShortcut("Ctrl+X")
|
133
|
+
self.ui.pushButton_stop.setToolTip("Ctrl+X")
|
131
134
|
|
132
135
|
def _update_arrow_key_shortcuts(self) -> None:
|
133
136
|
"""Update the arrow key shortcuts based on the checkbox state."""
|
134
|
-
if self.checkBox_enableArrows.isChecked():
|
137
|
+
if self.ui.checkBox_enableArrows.isChecked():
|
135
138
|
# Set the arrow key shortcuts for motor movement
|
136
|
-
self.toolButton_right.setShortcut(Qt.Key_Right)
|
137
|
-
self.toolButton_left.setShortcut(Qt.Key_Left)
|
138
|
-
self.toolButton_up.setShortcut(Qt.Key_Up)
|
139
|
-
self.toolButton_down.setShortcut(Qt.Key_Down)
|
139
|
+
self.ui.toolButton_right.setShortcut(Qt.Key_Right)
|
140
|
+
self.ui.toolButton_left.setShortcut(Qt.Key_Left)
|
141
|
+
self.ui.toolButton_up.setShortcut(Qt.Key_Up)
|
142
|
+
self.ui.toolButton_down.setShortcut(Qt.Key_Down)
|
140
143
|
else:
|
141
144
|
# Clear the shortcuts
|
142
|
-
self.toolButton_right.setShortcut("")
|
143
|
-
self.toolButton_left.setShortcut("")
|
144
|
-
self.toolButton_up.setShortcut("")
|
145
|
-
self.toolButton_down.setShortcut("")
|
145
|
+
self.ui.toolButton_right.setShortcut("")
|
146
|
+
self.ui.toolButton_left.setShortcut("")
|
147
|
+
self.ui.toolButton_up.setShortcut("")
|
148
|
+
self.ui.toolButton_down.setShortcut("")
|
146
149
|
|
147
150
|
def _update_precision(self, precision: int) -> None:
|
148
151
|
"""
|
@@ -150,8 +153,8 @@ class MotorControlRelative(MotorControlWidget):
|
|
150
153
|
Args:
|
151
154
|
precision(int): Precision of the coordinates.
|
152
155
|
"""
|
153
|
-
self.spinBox_step_x.setDecimals(precision)
|
154
|
-
self.spinBox_step_y.setDecimals(precision)
|
156
|
+
self.ui.spinBox_step_x.setDecimals(precision)
|
157
|
+
self.ui.spinBox_step_y.setDecimals(precision)
|
155
158
|
self.precision_signal.emit(precision)
|
156
159
|
|
157
160
|
def _change_step_size(self, spinBox: QDoubleSpinBox, factor: float) -> None:
|
@@ -167,21 +170,21 @@ class MotorControlRelative(MotorControlWidget):
|
|
167
170
|
|
168
171
|
def _sync_step_sizes(self):
|
169
172
|
"""Sync step sizes based on checkbox state."""
|
170
|
-
if self.checkBox_same_xy.isChecked():
|
171
|
-
value = self.spinBox_step_x.value()
|
172
|
-
self.spinBox_step_y.setValue(value)
|
173
|
+
if self.ui.checkBox_same_xy.isChecked():
|
174
|
+
value = self.ui.spinBox_step_x.value()
|
175
|
+
self.ui.spinBox_step_y.setValue(value)
|
173
176
|
|
174
177
|
def _update_step_size_x(self):
|
175
178
|
"""Update step size for x if checkbox is checked."""
|
176
|
-
if self.checkBox_same_xy.isChecked():
|
177
|
-
value = self.spinBox_step_x.value()
|
178
|
-
self.spinBox_step_y.setValue(value)
|
179
|
+
if self.ui.checkBox_same_xy.isChecked():
|
180
|
+
value = self.ui.spinBox_step_x.value()
|
181
|
+
self.ui.spinBox_step_y.setValue(value)
|
179
182
|
|
180
183
|
def _update_step_size_y(self):
|
181
184
|
"""Update step size for y if checkbox is checked."""
|
182
|
-
if self.checkBox_same_xy.isChecked():
|
183
|
-
value = self.spinBox_step_y.value()
|
184
|
-
self.spinBox_step_x.setValue(value)
|
185
|
+
if self.ui.checkBox_same_xy.isChecked():
|
186
|
+
value = self.ui.spinBox_step_y.value()
|
187
|
+
self.ui.spinBox_step_x.setValue(value)
|
185
188
|
|
186
189
|
@pyqtSlot(str, str)
|
187
190
|
def change_motors(self, motor_x: str, motor_y: str):
|
@@ -206,11 +209,11 @@ class MotorControlRelative(MotorControlWidget):
|
|
206
209
|
"""
|
207
210
|
|
208
211
|
# Disable or enable all controls within the motorControl_absolute group box
|
209
|
-
for widget in self.motorControl.findChildren(QWidget):
|
212
|
+
for widget in self.ui.motorControl.findChildren(QWidget):
|
210
213
|
widget.setEnabled(disable)
|
211
214
|
|
212
215
|
# Enable the pushButton_stop if the motor is moving
|
213
|
-
self.pushButton_stop.setEnabled(True)
|
216
|
+
self.ui.pushButton_stop.setEnabled(True)
|
214
217
|
|
215
218
|
def move_motor_relative(self, motor, axis: str, direction: int) -> None:
|
216
219
|
"""
|
@@ -221,7 +224,7 @@ class MotorControlRelative(MotorControlWidget):
|
|
221
224
|
direction(int): Direction to move. 1 for positive, -1 for negative.
|
222
225
|
"""
|
223
226
|
if axis == "x":
|
224
|
-
step = direction * self.spinBox_step_x.value()
|
227
|
+
step = direction * self.ui.spinBox_step_x.value()
|
225
228
|
elif axis == "y":
|
226
|
-
step = direction * self.spinBox_step_y.value()
|
229
|
+
step = direction * self.ui.spinBox_step_y.value()
|
227
230
|
self.motor_thread.move_relative(motor, step)
|
@@ -17,16 +17,16 @@ class RingConnections(BaseModel):
|
|
17
17
|
@field_validator("endpoint")
|
18
18
|
def validate_endpoint(cls, v, values):
|
19
19
|
slot = values.data["slot"]
|
20
|
-
|
20
|
+
v = v.endpoint if isinstance(v, EndpointInfo) else v
|
21
21
|
if slot == "on_scan_progress":
|
22
|
-
if
|
22
|
+
if v != "scans/scan_progress":
|
23
23
|
raise PydanticCustomError(
|
24
24
|
"unsupported endpoint",
|
25
25
|
"For slot 'on_scan_progress', endpoint must be MessageEndpoint.scan_progress or 'scans/scan_progress'.",
|
26
26
|
{"wrong_value": v},
|
27
27
|
)
|
28
28
|
elif slot == "on_device_readback":
|
29
|
-
if not
|
29
|
+
if not v.startswith("internal/devices/readback/"):
|
30
30
|
raise PydanticCustomError(
|
31
31
|
"unsupported endpoint",
|
32
32
|
"For slot 'on_device_readback', endpoint must be MessageEndpoint.device_readback(device) or 'internal/devices/readback/{device}'.",
|
@@ -54,8 +54,8 @@ class RingConfig(ConnectionConfig):
|
|
54
54
|
description="Start position for the progress bars in degrees. Default is 90 degrees - corespons to "
|
55
55
|
"the top of the ring.",
|
56
56
|
)
|
57
|
-
min_value: int | None = Field(0, description="Minimum value for the progress bars.")
|
58
|
-
max_value: int | None = Field(100, description="Maximum value for the progress bars.")
|
57
|
+
min_value: int | float | None = Field(0, description="Minimum value for the progress bars.")
|
58
|
+
max_value: int | float | None = Field(100, description="Maximum value for the progress bars.")
|
59
59
|
precision: int | None = Field(3, description="Precision for the progress bars.")
|
60
60
|
update_behaviour: Literal["manual", "auto"] | None = Field(
|
61
61
|
"auto", description="Update behaviour for the progress bars."
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: bec_widgets
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.56.1
|
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
|
@@ -31,3 +31,5 @@ Provides-Extra: pyqt5
|
|
31
31
|
Requires-Dist: pyqt5>=5.9; extra == 'pyqt5'
|
32
32
|
Provides-Extra: pyqt6
|
33
33
|
Requires-Dist: pyqt6>=6.7; extra == 'pyqt6'
|
34
|
+
Provides-Extra: pyside6
|
35
|
+
Requires-Dist: pyside6>=6.7; extra == 'pyside6'
|