bec-widgets 0.80.0__py3-none-any.whl → 0.82.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.
- CHANGELOG.md +40 -46
- PKG-INFO +1 -1
- bec_widgets/cli/client.py +1 -0
- bec_widgets/examples/__init__.py +0 -9
- bec_widgets/utils/entry_validator.py +1 -1
- bec_widgets/widgets/{device_inputs → base_classes}/device_input_base.py +2 -0
- bec_widgets/widgets/color_button/color_button.py +36 -0
- bec_widgets/widgets/{buttons/color_button → color_button}/color_button_plugin.py +1 -1
- bec_widgets/widgets/{buttons/color_button → color_button}/register_color_button.py +1 -1
- bec_widgets/widgets/device_combobox/assets/device_combobox_icon.png +0 -0
- bec_widgets/widgets/{device_inputs/device_combobox → device_combobox}/device_combobox.py +2 -2
- bec_widgets/widgets/device_combobox/device_combobox.pyproject +3 -0
- bec_widgets/widgets/{device_inputs/device_combobox → device_combobox}/device_combobox_plugin.py +6 -3
- bec_widgets/widgets/{device_inputs/device_combobox → device_combobox}/register_device_combobox.py +1 -3
- bec_widgets/widgets/device_line_edit/assets/line_edit_icon.png +0 -0
- bec_widgets/widgets/{device_inputs/device_line_edit → device_line_edit}/device_line_edit.py +2 -2
- bec_widgets/widgets/device_line_edit/device_line_edit.pyproject +3 -0
- bec_widgets/widgets/{device_inputs/device_line_edit → device_line_edit}/device_line_edit_plugin.py +6 -3
- bec_widgets/widgets/{device_inputs/device_line_edit → device_line_edit}/register_device_line_edit.py +1 -3
- bec_widgets/widgets/figure/plots/waveform/waveform.py +8 -2
- bec_widgets/widgets/motor_map/motor_map_dialog/motor_map_settings.py +1 -1
- bec_widgets/widgets/motor_map/motor_map_dialog/motor_map_toolbar.py +1 -1
- bec_widgets/widgets/motor_map/motor_map_widget.py +0 -12
- bec_widgets/widgets/scan_control/scan_control.py +1 -1
- bec_widgets/widgets/scan_control/scan_group_box.py +1 -1
- bec_widgets/widgets/stop_button/assets/stop.png +0 -0
- bec_widgets/widgets/stop_button/register_stop_button.py +15 -0
- bec_widgets/widgets/{buttons/stop_button → stop_button}/stop_button.py +5 -12
- bec_widgets/widgets/stop_button/stop_button.pyproject +1 -0
- bec_widgets/widgets/stop_button/stop_button_plugin.py +57 -0
- bec_widgets/widgets/toggle/register_toggle_switch.py +15 -0
- bec_widgets/widgets/toggle/toggle.py +149 -0
- bec_widgets/widgets/toggle/toggle_switch.pyproject +1 -0
- bec_widgets/widgets/toggle/toggle_switch_plugin.py +54 -0
- {bec_widgets-0.80.0.dist-info → bec_widgets-0.82.0.dist-info}/METADATA +1 -1
- {bec_widgets-0.80.0.dist-info → bec_widgets-0.82.0.dist-info}/RECORD +52 -61
- pyproject.toml +1 -1
- tests/unit_tests/test_device_input_base.py +1 -1
- tests/unit_tests/test_device_input_widgets.py +2 -2
- tests/unit_tests/test_stop_button.py +5 -2
- tests/unit_tests/test_toggle.py +38 -0
- bec_widgets/examples/motor_movement/__init__.py +0 -9
- bec_widgets/examples/motor_movement/motor_control_compilations.py +0 -250
- bec_widgets/examples/motor_movement/motor_controller.ui +0 -926
- bec_widgets/widgets/buttons/__init__.py +0 -1
- bec_widgets/widgets/buttons/color_button/color_button.py +0 -17
- bec_widgets/widgets/device_inputs/__init__.py +0 -2
- bec_widgets/widgets/device_inputs/device_combobox/device_combobox.pyproject +0 -4
- bec_widgets/widgets/device_inputs/device_combobox/launch_device_combobox.py +0 -11
- bec_widgets/widgets/device_inputs/device_line_edit/device_line_edit.pyproject +0 -4
- bec_widgets/widgets/device_inputs/device_line_edit/launch_device_line_edit.py +0 -11
- bec_widgets/widgets/motor_control/motor_control.py +0 -252
- bec_widgets/widgets/motor_control/motor_table/motor_table.py +0 -484
- bec_widgets/widgets/motor_control/motor_table/motor_table.ui +0 -113
- bec_widgets/widgets/motor_control/movement_absolute/__init__.py +0 -0
- bec_widgets/widgets/motor_control/movement_absolute/movement_absolute.py +0 -159
- bec_widgets/widgets/motor_control/movement_absolute/movement_absolute.ui +0 -149
- bec_widgets/widgets/motor_control/movement_relative/__init__.py +0 -0
- bec_widgets/widgets/motor_control/movement_relative/movement_relative.py +0 -230
- bec_widgets/widgets/motor_control/movement_relative/movement_relative.ui +0 -298
- bec_widgets/widgets/motor_control/selection/__init__.py +0 -0
- bec_widgets/widgets/motor_control/selection/selection.py +0 -110
- bec_widgets/widgets/motor_control/selection/selection.ui +0 -69
- tests/unit_tests/test_motor_control.py +0 -588
- /bec_widgets/widgets/{buttons/color_button → base_classes}/__init__.py +0 -0
- /bec_widgets/widgets/{buttons/stop_button → color_button}/__init__.py +0 -0
- /bec_widgets/widgets/{buttons/color_button → color_button}/assets/color_button.png +0 -0
- /bec_widgets/widgets/{buttons/color_button → color_button}/color_button.pyproject +0 -0
- /bec_widgets/widgets/{device_inputs/device_combobox → device_combobox}/__init__.py +0 -0
- /bec_widgets/widgets/{device_inputs/device_line_edit → device_line_edit}/__init__.py +0 -0
- /bec_widgets/widgets/{motor_control → stop_button}/__init__.py +0 -0
- /bec_widgets/widgets/{motor_control/motor_table → toggle}/__init__.py +0 -0
- {bec_widgets-0.80.0.dist-info → bec_widgets-0.82.0.dist-info}/WHEEL +0 -0
- {bec_widgets-0.80.0.dist-info → bec_widgets-0.82.0.dist-info}/entry_points.txt +0 -0
- {bec_widgets-0.80.0.dist-info → bec_widgets-0.82.0.dist-info}/licenses/LICENSE +0 -0
@@ -1 +0,0 @@
|
|
1
|
-
from .stop_button.stop_button import StopButton
|
@@ -1,17 +0,0 @@
|
|
1
|
-
import pyqtgraph as pg
|
2
|
-
|
3
|
-
|
4
|
-
class ColorButton(pg.ColorButton):
|
5
|
-
"""
|
6
|
-
A ColorButton that opens a dialog to select a color. Inherits from pyqtgraph.ColorButton.
|
7
|
-
Patches event loop of the ColorDialog, if opened in another QDialog.
|
8
|
-
"""
|
9
|
-
|
10
|
-
def __init__(self, *args, **kwargs):
|
11
|
-
super().__init__(*args, **kwargs)
|
12
|
-
|
13
|
-
def selectColor(self):
|
14
|
-
self.origColor = self.color()
|
15
|
-
self.colorDialog.setCurrentColor(self.color())
|
16
|
-
self.colorDialog.open()
|
17
|
-
self.colorDialog.exec()
|
@@ -1,11 +0,0 @@
|
|
1
|
-
from bec_widgets.widgets.device_inputs import DeviceComboBox
|
2
|
-
|
3
|
-
if __name__ == "__main__": # pragma: no cover
|
4
|
-
import sys
|
5
|
-
|
6
|
-
from qtpy.QtWidgets import QApplication
|
7
|
-
|
8
|
-
app = QApplication(sys.argv)
|
9
|
-
w = DeviceComboBox()
|
10
|
-
w.show()
|
11
|
-
sys.exit(app.exec_())
|
@@ -1,11 +0,0 @@
|
|
1
|
-
from bec_widgets.widgets.device_inputs import DeviceLineEdit
|
2
|
-
|
3
|
-
if __name__ == "__main__": # pragma: no cover
|
4
|
-
import sys
|
5
|
-
|
6
|
-
from qtpy.QtWidgets import QApplication
|
7
|
-
|
8
|
-
app = QApplication(sys.argv)
|
9
|
-
w = DeviceLineEdit()
|
10
|
-
w.show()
|
11
|
-
sys.exit(app.exec_())
|
@@ -1,252 +0,0 @@
|
|
1
|
-
# pylint: disable = no-name-in-module,missing-module-docstring
|
2
|
-
from enum import Enum
|
3
|
-
|
4
|
-
from bec_lib.alarm_handler import AlarmBase
|
5
|
-
from bec_lib.device import Positioner
|
6
|
-
from qtpy.QtCore import QThread
|
7
|
-
from qtpy.QtCore import Signal as pyqtSignal
|
8
|
-
from qtpy.QtCore import Slot as pyqtSlot
|
9
|
-
from qtpy.QtWidgets import QMessageBox, QWidget
|
10
|
-
|
11
|
-
from bec_widgets.utils.bec_dispatcher import BECDispatcher
|
12
|
-
|
13
|
-
CONFIG_DEFAULT = {
|
14
|
-
"motor_control": {
|
15
|
-
"motor_x": "samx",
|
16
|
-
"motor_y": "samy",
|
17
|
-
"step_size_x": 3,
|
18
|
-
"step_size_y": 50,
|
19
|
-
"precision": 4,
|
20
|
-
"step_x_y_same": False,
|
21
|
-
"move_with_arrows": False,
|
22
|
-
}
|
23
|
-
}
|
24
|
-
|
25
|
-
|
26
|
-
class MotorControlWidget(QWidget):
|
27
|
-
"""Base class for motor control widgets."""
|
28
|
-
|
29
|
-
def __init__(self, parent=None, client=None, motor_thread=None, config=None):
|
30
|
-
super().__init__(parent)
|
31
|
-
self.client = client
|
32
|
-
self.motor_thread = motor_thread
|
33
|
-
self.config = config
|
34
|
-
|
35
|
-
self.motor_x = None
|
36
|
-
self.motor_y = None
|
37
|
-
|
38
|
-
if not self.client:
|
39
|
-
bec_dispatcher = BECDispatcher()
|
40
|
-
self.client = bec_dispatcher.client
|
41
|
-
|
42
|
-
if not self.motor_thread:
|
43
|
-
self.motor_thread = MotorThread(client=self.client)
|
44
|
-
|
45
|
-
self._load_ui()
|
46
|
-
|
47
|
-
if self.config is None:
|
48
|
-
print(f"No initial config found for {self.__class__.__name__}")
|
49
|
-
self._init_ui()
|
50
|
-
else:
|
51
|
-
self.on_config_update(self.config)
|
52
|
-
|
53
|
-
def _load_ui(self):
|
54
|
-
"""Load the UI from the .ui file."""
|
55
|
-
|
56
|
-
def _init_ui(self):
|
57
|
-
"""Initialize the UI components specific to the widget."""
|
58
|
-
|
59
|
-
@pyqtSlot(dict)
|
60
|
-
def on_config_update(self, config):
|
61
|
-
"""Handle configuration updates."""
|
62
|
-
self.config = config
|
63
|
-
self._init_ui()
|
64
|
-
|
65
|
-
|
66
|
-
class MotorControlErrors:
|
67
|
-
"""Class for displaying formatted error messages."""
|
68
|
-
|
69
|
-
@staticmethod
|
70
|
-
def display_error_message(error_message: str) -> None:
|
71
|
-
"""
|
72
|
-
Display a critical error message.
|
73
|
-
Args:
|
74
|
-
error_message(str): Error message to display.
|
75
|
-
"""
|
76
|
-
# Create a QMessageBox
|
77
|
-
msg = QMessageBox()
|
78
|
-
msg.setIcon(QMessageBox.Critical)
|
79
|
-
msg.setWindowTitle("Critical Error")
|
80
|
-
|
81
|
-
# Format the message
|
82
|
-
formatted_message = MotorControlErrors._format_error_message(error_message)
|
83
|
-
msg.setText(formatted_message)
|
84
|
-
|
85
|
-
# Display the message box
|
86
|
-
msg.exec_()
|
87
|
-
|
88
|
-
@staticmethod
|
89
|
-
def _format_error_message(error_message: str) -> str:
|
90
|
-
"""
|
91
|
-
Format the error message.
|
92
|
-
Args:
|
93
|
-
error_message(str): Error message to format.
|
94
|
-
|
95
|
-
Returns:
|
96
|
-
str: Formatted error message.
|
97
|
-
"""
|
98
|
-
# Split the message into lines
|
99
|
-
lines = error_message.split("\n")
|
100
|
-
formatted_lines = [
|
101
|
-
f"<b>{line.strip()}</b>" if i == 0 else line.strip()
|
102
|
-
for i, line in enumerate(lines)
|
103
|
-
if line.strip()
|
104
|
-
]
|
105
|
-
|
106
|
-
# Join the lines with double breaks for empty lines in between
|
107
|
-
formatted_message = "<br><br>".join(formatted_lines)
|
108
|
-
|
109
|
-
return formatted_message
|
110
|
-
|
111
|
-
|
112
|
-
class MotorActions(Enum):
|
113
|
-
"""Enum for motor actions."""
|
114
|
-
|
115
|
-
MOVE_ABSOLUTE = "move_absolute"
|
116
|
-
MOVE_RELATIVE = "move_relative"
|
117
|
-
|
118
|
-
|
119
|
-
class MotorThread(QThread):
|
120
|
-
"""
|
121
|
-
QThread subclass for controlling motor actions asynchronously.
|
122
|
-
|
123
|
-
Signals:
|
124
|
-
coordinates_updated (pyqtSignal): Signal to emit current coordinates.
|
125
|
-
motor_error (pyqtSignal): Signal to emit when there is an error with the motors.
|
126
|
-
lock_gui (pyqtSignal): Signal to lock/unlock the GUI.
|
127
|
-
"""
|
128
|
-
|
129
|
-
coordinates_updated = pyqtSignal(float, float) # Signal to emit current coordinates
|
130
|
-
motor_error = pyqtSignal(str) # Signal to emit when there is an error with the motors
|
131
|
-
lock_gui = pyqtSignal(bool) # Signal to lock/unlock the GUI
|
132
|
-
|
133
|
-
def __init__(self, parent=None, client=None):
|
134
|
-
super().__init__(parent)
|
135
|
-
|
136
|
-
bec_dispatcher = BECDispatcher()
|
137
|
-
self.client = bec_dispatcher.client if client is None else client
|
138
|
-
self.dev = self.client.device_manager.devices
|
139
|
-
self.scans = self.client.scans
|
140
|
-
self.queue = self.client.queue
|
141
|
-
self.action = None
|
142
|
-
|
143
|
-
self.motor = None
|
144
|
-
self.motor_x = None
|
145
|
-
self.motor_y = None
|
146
|
-
self.target_coordinates = None
|
147
|
-
self.value = None
|
148
|
-
|
149
|
-
def get_all_motors_names(self) -> list:
|
150
|
-
"""
|
151
|
-
Get all the motors names.
|
152
|
-
Returns:
|
153
|
-
list: List of all the motors names.
|
154
|
-
"""
|
155
|
-
all_devices = self.client.device_manager.devices.enabled_devices
|
156
|
-
all_motors_names = [motor.name for motor in all_devices if isinstance(motor, Positioner)]
|
157
|
-
return all_motors_names
|
158
|
-
|
159
|
-
def get_coordinates(self, motor_x: str, motor_y: str) -> tuple:
|
160
|
-
"""
|
161
|
-
Get the current coordinates of the motors.
|
162
|
-
Args:
|
163
|
-
motor_x(str): Motor X to get positions from.
|
164
|
-
motor_y(str): Motor Y to get positions from.
|
165
|
-
|
166
|
-
Returns:
|
167
|
-
tuple: Current coordinates of the motors.
|
168
|
-
"""
|
169
|
-
x = self.dev[motor_x].readback.get()
|
170
|
-
y = self.dev[motor_y].readback.get()
|
171
|
-
return x, y
|
172
|
-
|
173
|
-
def move_absolute(self, motor_x: str, motor_y: str, target_coordinates: tuple) -> None:
|
174
|
-
"""
|
175
|
-
Wrapper for moving the motor to the target coordinates.
|
176
|
-
Args:
|
177
|
-
motor_x(str): Motor X to move.
|
178
|
-
motor_y(str): Motor Y to move.
|
179
|
-
target_coordinates(tuple): Target coordinates.
|
180
|
-
"""
|
181
|
-
self.action = MotorActions.MOVE_ABSOLUTE
|
182
|
-
self.motor_x = motor_x
|
183
|
-
self.motor_y = motor_y
|
184
|
-
self.target_coordinates = target_coordinates
|
185
|
-
self.start()
|
186
|
-
|
187
|
-
def move_relative(self, motor: str, value: float) -> None:
|
188
|
-
"""
|
189
|
-
Wrapper for moving the motor relative to the current position.
|
190
|
-
Args:
|
191
|
-
motor(str): Motor to move.
|
192
|
-
value(float): Value to move.
|
193
|
-
"""
|
194
|
-
self.action = MotorActions.MOVE_RELATIVE
|
195
|
-
self.motor = motor
|
196
|
-
self.value = value
|
197
|
-
self.start()
|
198
|
-
|
199
|
-
def run(self):
|
200
|
-
"""
|
201
|
-
Run the thread.
|
202
|
-
Possible actions:
|
203
|
-
- Move to coordinates
|
204
|
-
- Move relative
|
205
|
-
"""
|
206
|
-
if self.action == MotorActions.MOVE_ABSOLUTE:
|
207
|
-
self._move_motor_absolute(self.motor_x, self.motor_y, self.target_coordinates)
|
208
|
-
elif self.action == MotorActions.MOVE_RELATIVE:
|
209
|
-
self._move_motor_relative(self.motor, self.value)
|
210
|
-
|
211
|
-
def _move_motor_absolute(self, motor_x: str, motor_y: str, target_coordinates: tuple) -> None:
|
212
|
-
"""
|
213
|
-
Move the motor to the target coordinates.
|
214
|
-
Args:
|
215
|
-
motor_x(str): Motor X to move.
|
216
|
-
motor_y(str): Motor Y to move.
|
217
|
-
target_coordinates(tuple): Target coordinates.
|
218
|
-
"""
|
219
|
-
self.lock_gui.emit(False)
|
220
|
-
try:
|
221
|
-
status = self.scans.mv(
|
222
|
-
self.dev[motor_x],
|
223
|
-
target_coordinates[0],
|
224
|
-
self.dev[motor_y],
|
225
|
-
target_coordinates[1],
|
226
|
-
relative=False,
|
227
|
-
)
|
228
|
-
status.wait()
|
229
|
-
except AlarmBase as e:
|
230
|
-
self.motor_error.emit(str(e))
|
231
|
-
finally:
|
232
|
-
self.lock_gui.emit(True)
|
233
|
-
|
234
|
-
def _move_motor_relative(self, motor, value: float) -> None:
|
235
|
-
"""
|
236
|
-
Move the motor relative to the current position.
|
237
|
-
Args:
|
238
|
-
motor(str): Motor to move.
|
239
|
-
value(float): Value to move.
|
240
|
-
"""
|
241
|
-
self.lock_gui.emit(False)
|
242
|
-
try:
|
243
|
-
status = self.scans.mv(self.dev[motor], value, relative=True)
|
244
|
-
status.wait()
|
245
|
-
except AlarmBase as e:
|
246
|
-
self.motor_error.emit(str(e))
|
247
|
-
finally:
|
248
|
-
self.lock_gui.emit(True)
|
249
|
-
|
250
|
-
def stop_movement(self):
|
251
|
-
self.queue.request_scan_abortion()
|
252
|
-
self.queue.request_queue_reset()
|