bec-widgets 0.80.1__py3-none-any.whl → 0.81.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. CHANGELOG.md +12 -12
  2. PKG-INFO +1 -1
  3. bec_widgets/examples/__init__.py +0 -9
  4. bec_widgets/widgets/buttons/color_button/color_button.py +19 -0
  5. {bec_widgets-0.80.1.dist-info → bec_widgets-0.81.1.dist-info}/METADATA +1 -1
  6. {bec_widgets-0.80.1.dist-info → bec_widgets-0.81.1.dist-info}/RECORD +10 -28
  7. pyproject.toml +1 -1
  8. bec_widgets/examples/motor_movement/__init__.py +0 -9
  9. bec_widgets/examples/motor_movement/motor_control_compilations.py +0 -250
  10. bec_widgets/examples/motor_movement/motor_controller.ui +0 -926
  11. bec_widgets/widgets/motor_control/__init__.py +0 -0
  12. bec_widgets/widgets/motor_control/motor_control.py +0 -252
  13. bec_widgets/widgets/motor_control/motor_table/__init__.py +0 -0
  14. bec_widgets/widgets/motor_control/motor_table/motor_table.py +0 -484
  15. bec_widgets/widgets/motor_control/motor_table/motor_table.ui +0 -113
  16. bec_widgets/widgets/motor_control/movement_absolute/__init__.py +0 -0
  17. bec_widgets/widgets/motor_control/movement_absolute/movement_absolute.py +0 -159
  18. bec_widgets/widgets/motor_control/movement_absolute/movement_absolute.ui +0 -149
  19. bec_widgets/widgets/motor_control/movement_relative/__init__.py +0 -0
  20. bec_widgets/widgets/motor_control/movement_relative/movement_relative.py +0 -230
  21. bec_widgets/widgets/motor_control/movement_relative/movement_relative.ui +0 -298
  22. bec_widgets/widgets/motor_control/selection/__init__.py +0 -0
  23. bec_widgets/widgets/motor_control/selection/selection.py +0 -110
  24. bec_widgets/widgets/motor_control/selection/selection.ui +0 -69
  25. tests/unit_tests/test_motor_control.py +0 -588
  26. {bec_widgets-0.80.1.dist-info → bec_widgets-0.81.1.dist-info}/WHEEL +0 -0
  27. {bec_widgets-0.80.1.dist-info → bec_widgets-0.81.1.dist-info}/entry_points.txt +0 -0
  28. {bec_widgets-0.80.1.dist-info → bec_widgets-0.81.1.dist-info}/licenses/LICENSE +0 -0
File without changes
@@ -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()
File without changes