pymodaq 5.0.18__py3-none-any.whl → 5.1.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.
Potentially problematic release.
This version of pymodaq might be problematic. Click here for more details.
- pymodaq/__init__.py +23 -11
- pymodaq/control_modules/__init__.py +1 -0
- pymodaq/control_modules/daq_move.py +451 -246
- pymodaq/control_modules/daq_move_ui/__init__.py +0 -0
- pymodaq/control_modules/daq_move_ui/factory.py +48 -0
- pymodaq/control_modules/{daq_move_ui.py → daq_move_ui/ui_base.py} +168 -210
- pymodaq/control_modules/daq_move_ui/uis/__init__.py +0 -0
- pymodaq/control_modules/daq_move_ui/uis/binary.py +139 -0
- pymodaq/control_modules/daq_move_ui/uis/original.py +120 -0
- pymodaq/control_modules/daq_move_ui/uis/relative.py +124 -0
- pymodaq/control_modules/daq_move_ui/uis/simple.py +126 -0
- pymodaq/control_modules/daq_viewer.py +113 -101
- pymodaq/control_modules/daq_viewer_ui.py +41 -31
- pymodaq/control_modules/mocks.py +2 -2
- pymodaq/control_modules/move_utility_classes.py +113 -41
- pymodaq/control_modules/thread_commands.py +137 -0
- pymodaq/control_modules/ui_utils.py +72 -0
- pymodaq/control_modules/utils.py +107 -63
- pymodaq/control_modules/viewer_utility_classes.py +13 -17
- pymodaq/dashboard.py +1294 -625
- pymodaq/examples/qt_less_standalone_module.py +48 -11
- pymodaq/extensions/__init__.py +8 -3
- pymodaq/extensions/adaptive/__init__.py +2 -0
- pymodaq/extensions/adaptive/adaptive_optimization.py +179 -0
- pymodaq/extensions/adaptive/loss_function/_1d_loss_functions.py +73 -0
- pymodaq/extensions/adaptive/loss_function/_2d_loss_functions.py +73 -0
- pymodaq/extensions/adaptive/loss_function/__init__.py +3 -0
- pymodaq/extensions/adaptive/loss_function/loss_factory.py +110 -0
- pymodaq/extensions/adaptive/utils.py +123 -0
- pymodaq/extensions/bayesian/__init__.py +1 -1
- pymodaq/extensions/bayesian/acquisition/__init__.py +2 -0
- pymodaq/extensions/bayesian/acquisition/acquisition_function_factory.py +80 -0
- pymodaq/extensions/bayesian/acquisition/base_acquisition_function.py +105 -0
- pymodaq/extensions/bayesian/bayesian_optimization.py +143 -0
- pymodaq/extensions/bayesian/utils.py +71 -297
- pymodaq/extensions/daq_logger/daq_logger.py +7 -12
- pymodaq/extensions/daq_logger/h5logging.py +1 -1
- pymodaq/extensions/daq_scan.py +30 -55
- pymodaq/extensions/data_mixer/__init__.py +0 -0
- pymodaq/extensions/data_mixer/daq_0Dviewer_DataMixer.py +97 -0
- pymodaq/extensions/data_mixer/data_mixer.py +262 -0
- pymodaq/extensions/data_mixer/model.py +108 -0
- pymodaq/extensions/data_mixer/models/__init__.py +0 -0
- pymodaq/extensions/data_mixer/models/equation_model.py +91 -0
- pymodaq/extensions/data_mixer/models/gaussian_fit_model.py +65 -0
- pymodaq/extensions/data_mixer/parser.py +53 -0
- pymodaq/extensions/data_mixer/utils.py +23 -0
- pymodaq/extensions/h5browser.py +3 -34
- pymodaq/extensions/optimizers_base/__init__.py +0 -0
- pymodaq/extensions/optimizers_base/optimizer.py +1016 -0
- pymodaq/extensions/optimizers_base/thread_commands.py +22 -0
- pymodaq/extensions/optimizers_base/utils.py +427 -0
- pymodaq/extensions/pid/actuator_controller.py +3 -2
- pymodaq/extensions/pid/daq_move_PID.py +107 -30
- pymodaq/extensions/pid/pid_controller.py +613 -287
- pymodaq/extensions/pid/utils.py +8 -5
- pymodaq/extensions/utils.py +17 -2
- pymodaq/resources/config_template.toml +57 -0
- pymodaq/resources/preset_default.xml +1 -1
- pymodaq/utils/config.py +10 -4
- pymodaq/utils/daq_utils.py +14 -0
- pymodaq/utils/data.py +1 -0
- pymodaq/utils/gui_utils/loader_utils.py +25 -15
- pymodaq/utils/h5modules/module_saving.py +134 -22
- pymodaq/utils/leco/daq_move_LECODirector.py +123 -84
- pymodaq/utils/leco/daq_xDviewer_LECODirector.py +84 -97
- pymodaq/utils/leco/director_utils.py +32 -16
- pymodaq/utils/leco/leco_director.py +104 -27
- pymodaq/utils/leco/pymodaq_listener.py +186 -97
- pymodaq/utils/leco/rpc_method_definitions.py +43 -0
- pymodaq/utils/leco/utils.py +25 -25
- pymodaq/utils/managers/batchscan_manager.py +12 -11
- pymodaq/utils/managers/modules_manager.py +74 -33
- pymodaq/utils/managers/overshoot_manager.py +11 -10
- pymodaq/utils/managers/preset_manager.py +100 -64
- pymodaq/utils/managers/preset_manager_utils.py +163 -107
- pymodaq/utils/managers/remote_manager.py +21 -16
- pymodaq/utils/scanner/scan_factory.py +12 -3
- pymodaq/utils/scanner/scan_selector.py +1 -3
- pymodaq/utils/scanner/scanner.py +35 -6
- pymodaq/utils/scanner/scanners/_1d_scanners.py +15 -46
- pymodaq/utils/scanner/scanners/_2d_scanners.py +21 -68
- pymodaq/utils/scanner/scanners/sequential.py +50 -31
- pymodaq/utils/scanner/scanners/tabular.py +45 -28
- {pymodaq-5.0.18.dist-info → pymodaq-5.1.0.dist-info}/METADATA +7 -6
- pymodaq-5.1.0.dist-info/RECORD +154 -0
- {pymodaq-5.0.18.dist-info → pymodaq-5.1.0.dist-info}/entry_points.txt +0 -2
- pymodaq/extensions/bayesian/bayesian_optimisation.py +0 -690
- pymodaq/utils/leco/desktop.ini +0 -2
- pymodaq-5.0.18.dist-info/RECORD +0 -121
- {pymodaq-5.0.18.dist-info → pymodaq-5.1.0.dist-info}/WHEEL +0 -0
- {pymodaq-5.0.18.dist-info → pymodaq-5.1.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -12,7 +12,7 @@ from importlib import import_module
|
|
|
12
12
|
from numbers import Number
|
|
13
13
|
|
|
14
14
|
import sys
|
|
15
|
-
from typing import List,
|
|
15
|
+
from typing import List, Union, Optional, Dict, TypeVar, TYPE_CHECKING
|
|
16
16
|
import numpy as np
|
|
17
17
|
|
|
18
18
|
from qtpy.QtCore import QObject, Signal, QThread, Slot, Qt, QTimer
|
|
@@ -21,7 +21,7 @@ from qtpy import QtWidgets
|
|
|
21
21
|
from easydict import EasyDict as edict
|
|
22
22
|
|
|
23
23
|
from pymodaq_utils.logger import set_logger, get_module_name
|
|
24
|
-
from pymodaq_utils.utils import
|
|
24
|
+
from pymodaq_utils.utils import find_keys_from_val
|
|
25
25
|
from pymodaq_utils import utils
|
|
26
26
|
from pymodaq.utils.gui_utils import get_splash_sc
|
|
27
27
|
from pymodaq_utils import config as config_mod
|
|
@@ -36,36 +36,63 @@ from pymodaq_gui.utils.utils import mkQApp
|
|
|
36
36
|
|
|
37
37
|
from pymodaq.utils.h5modules import module_saving
|
|
38
38
|
from pymodaq.control_modules.utils import ParameterControlModule
|
|
39
|
-
from pymodaq.control_modules.
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
from pymodaq.control_modules.thread_commands import (
|
|
40
|
+
ThreadStatus,
|
|
41
|
+
ThreadStatusMove,
|
|
42
|
+
ControlToHardwareMove,
|
|
43
|
+
UiToMainMove,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
from pymodaq.control_modules.move_utility_classes import (
|
|
48
|
+
ThreadCommand,
|
|
49
|
+
MoveCommand,
|
|
50
|
+
DAQ_Move_base,
|
|
51
|
+
DataActuatorType,
|
|
52
|
+
check_units,
|
|
53
|
+
DataUnitError,
|
|
54
|
+
)
|
|
43
55
|
|
|
44
56
|
|
|
45
57
|
from pymodaq.control_modules.move_utility_classes import params as daq_move_params
|
|
46
|
-
from pymodaq.utils.leco.pymodaq_listener import
|
|
58
|
+
from pymodaq.utils.leco.pymodaq_listener import (
|
|
59
|
+
MoveActorListener,
|
|
60
|
+
LECOMoveCommands,
|
|
61
|
+
LECOCommands,
|
|
62
|
+
)
|
|
47
63
|
|
|
48
64
|
from pymodaq.utils.daq_utils import get_plugins
|
|
49
65
|
from pymodaq import Q_, Unit
|
|
50
66
|
|
|
51
67
|
|
|
68
|
+
from pymodaq.control_modules.daq_move_ui.factory import ActuatorUIFactory
|
|
69
|
+
from pymodaq.utils.config import Config as ControlModulesConfig
|
|
70
|
+
|
|
71
|
+
if TYPE_CHECKING:
|
|
72
|
+
from pymodaq.control_modules.daq_move_ui.ui_base import DAQ_Move_UI_Base
|
|
52
73
|
|
|
53
74
|
local_path = config_mod.get_set_local_dir()
|
|
54
75
|
sys.path.append(str(local_path))
|
|
55
76
|
logger = set_logger(get_module_name(__file__))
|
|
56
|
-
config = config_mod.Config()
|
|
57
77
|
|
|
58
|
-
|
|
59
|
-
|
|
78
|
+
config_utils = config_mod.Config()
|
|
79
|
+
config = ControlModulesConfig()
|
|
80
|
+
|
|
81
|
+
HardwareController = TypeVar("HardwareController")
|
|
82
|
+
|
|
83
|
+
HardwareController = TypeVar("HardwareController")
|
|
84
|
+
|
|
85
|
+
DAQ_Move_Actuators = get_plugins("daq_move")
|
|
86
|
+
ACTUATOR_TYPES = [mov["name"] for mov in DAQ_Move_Actuators]
|
|
60
87
|
if len(ACTUATOR_TYPES) == 0:
|
|
61
|
-
raise ActuatorError(
|
|
88
|
+
raise ActuatorError("No installed Actuator")
|
|
62
89
|
|
|
63
90
|
|
|
64
91
|
STATUS_WAIT_TIME = 1000
|
|
65
92
|
|
|
66
93
|
|
|
67
94
|
class DAQ_Move(ParameterControlModule):
|
|
68
|
-
"""
|
|
95
|
+
"""Main PyMoDAQ class to drive actuators
|
|
69
96
|
|
|
70
97
|
Qt object and generic UI to drive actuators.
|
|
71
98
|
|
|
@@ -83,7 +110,8 @@ class DAQ_Move(ParameterControlModule):
|
|
|
83
110
|
--------
|
|
84
111
|
:class:`ControlModule`, :class:`ParameterManager`
|
|
85
112
|
"""
|
|
86
|
-
|
|
113
|
+
|
|
114
|
+
settings_name = "daq_move_settings"
|
|
87
115
|
|
|
88
116
|
move_done_signal = Signal(DataActuator)
|
|
89
117
|
current_value_signal = Signal(DataActuator)
|
|
@@ -92,8 +120,11 @@ class DAQ_Move(ParameterControlModule):
|
|
|
92
120
|
params = daq_move_params
|
|
93
121
|
|
|
94
122
|
listener_class = MoveActorListener
|
|
123
|
+
ui: Optional[DAQ_Move_UI_Base]
|
|
95
124
|
|
|
96
|
-
def __init__(
|
|
125
|
+
def __init__(
|
|
126
|
+
self, parent=None, title="DAQ Move", ui_identifier: Optional[str] = None, **kwargs
|
|
127
|
+
) -> None:
|
|
97
128
|
"""
|
|
98
129
|
|
|
99
130
|
Parameters
|
|
@@ -105,16 +136,25 @@ class DAQ_Move(ParameterControlModule):
|
|
|
105
136
|
The unique (should be unique) string identifier for the underlying actuator
|
|
106
137
|
"""
|
|
107
138
|
|
|
108
|
-
self.logger = set_logger(f
|
|
109
|
-
self.logger.info(f
|
|
139
|
+
self.logger = set_logger(f"{logger.name}.{title}")
|
|
140
|
+
self.logger.info(f"Initializing DAQ_Move: {title}")
|
|
141
|
+
|
|
142
|
+
super().__init__(action_list=("save", "update"), **kwargs)
|
|
143
|
+
|
|
144
|
+
if not (
|
|
145
|
+
ui_identifier is not None and ui_identifier in ActuatorUIFactory.keys()
|
|
146
|
+
):
|
|
147
|
+
ui_identifier = config("actuator", "ui")
|
|
148
|
+
self.settings.child("main_settings", "ui_type").setValue(ui_identifier)
|
|
149
|
+
self.settings.child("main_settings", "ui_type").setOpts(readonly=True)
|
|
110
150
|
|
|
111
|
-
|
|
151
|
+
DAQ_Move_UI = ActuatorUIFactory.get(ui_identifier)
|
|
112
152
|
|
|
113
153
|
self.parent = parent
|
|
114
154
|
if parent is not None:
|
|
115
155
|
self.ui = DAQ_Move_UI(parent, title)
|
|
116
156
|
else:
|
|
117
|
-
self.ui
|
|
157
|
+
self.ui = None
|
|
118
158
|
|
|
119
159
|
if self.ui is not None:
|
|
120
160
|
self.ui.actuators = ACTUATOR_TYPES
|
|
@@ -124,9 +164,9 @@ class DAQ_Move(ParameterControlModule):
|
|
|
124
164
|
self.splash_sc = get_splash_sc()
|
|
125
165
|
self._title = title
|
|
126
166
|
if len(ACTUATOR_TYPES) > 0: # will be 0 if no valid plugins are installed
|
|
127
|
-
self.actuator = kwargs.get(
|
|
167
|
+
self.actuator = kwargs.get("actuator", ACTUATOR_TYPES[0])
|
|
128
168
|
|
|
129
|
-
self.module_and_data_saver = module_saving.
|
|
169
|
+
self.module_and_data_saver = module_saving.ActuatorTimeSaver(self)
|
|
130
170
|
|
|
131
171
|
self._move_done_bool = True
|
|
132
172
|
|
|
@@ -157,58 +197,69 @@ class DAQ_Move(ParameterControlModule):
|
|
|
157
197
|
* rel_value
|
|
158
198
|
* show_config
|
|
159
199
|
"""
|
|
160
|
-
if cmd.command ==
|
|
200
|
+
if cmd.command == UiToMainMove.INIT:
|
|
161
201
|
self.init_hardware(cmd.attribute[0])
|
|
162
|
-
elif cmd.command ==
|
|
202
|
+
elif cmd.command == UiToMainMove.QUIT:
|
|
163
203
|
self.quit_fun()
|
|
164
|
-
elif cmd.command ==
|
|
204
|
+
elif cmd.command == UiToMainMove.GET_VALUE:
|
|
165
205
|
self.get_actuator_value()
|
|
166
|
-
elif cmd.command ==
|
|
206
|
+
elif cmd.command == UiToMainMove.LOOP_GET_VALUE:
|
|
167
207
|
self.get_continuous_actuator_value(cmd.attribute)
|
|
168
|
-
elif cmd.command ==
|
|
208
|
+
elif cmd.command == UiToMainMove.FIND_HOME:
|
|
169
209
|
self.move_home()
|
|
170
|
-
elif cmd.command ==
|
|
210
|
+
elif cmd.command == UiToMainMove.STOP:
|
|
171
211
|
self.stop_motion()
|
|
172
|
-
elif cmd.command ==
|
|
212
|
+
elif cmd.command == UiToMainMove.MOVE_ABS:
|
|
173
213
|
data_act: DataActuator = cmd.attribute
|
|
174
|
-
if
|
|
214
|
+
if (
|
|
215
|
+
not Unit(data_act.units).is_compatible_with(self.units)
|
|
216
|
+
and data_act.units != ""
|
|
217
|
+
):
|
|
175
218
|
data_act.force_units(self.units)
|
|
176
219
|
self.move_abs(data_act)
|
|
177
|
-
elif cmd.command ==
|
|
220
|
+
elif cmd.command == UiToMainMove.MOVE_REL:
|
|
178
221
|
data_act: DataActuator = cmd.attribute
|
|
179
|
-
if
|
|
222
|
+
if (
|
|
223
|
+
not Unit(data_act.units).is_compatible_with(self.units)
|
|
224
|
+
and data_act.units != ""
|
|
225
|
+
):
|
|
180
226
|
data_act.force_units(self.units)
|
|
181
227
|
self.move_rel(data_act)
|
|
182
|
-
elif cmd.command ==
|
|
228
|
+
elif cmd.command == UiToMainMove.SHOW_LOG:
|
|
183
229
|
self.show_log()
|
|
184
|
-
elif cmd.command ==
|
|
230
|
+
elif cmd.command == UiToMainMove.SHOW_CONFIG:
|
|
185
231
|
self.config = self.show_config(self.config)
|
|
186
232
|
self.ui.config = self.config
|
|
187
|
-
elif cmd.command ==
|
|
233
|
+
elif cmd.command == UiToMainMove.ACTUATOR_CHANGED:
|
|
188
234
|
self.actuator = cmd.attribute
|
|
189
|
-
elif cmd.command ==
|
|
235
|
+
elif cmd.command == UiToMainMove.REL_VALUE:
|
|
190
236
|
self._relative_value = cmd.attribute
|
|
191
237
|
|
|
192
238
|
@property
|
|
193
239
|
def master(self) -> bool:
|
|
194
|
-
"""
|
|
240
|
+
"""Get/Set programmatically the Master/Slave status of an actuator"""
|
|
195
241
|
if self.initialized_state:
|
|
196
|
-
return
|
|
242
|
+
return (
|
|
243
|
+
self.settings["move_settings", "multiaxes", "multi_status"] == "Master"
|
|
244
|
+
)
|
|
197
245
|
else:
|
|
198
246
|
return True
|
|
199
247
|
|
|
200
248
|
@master.setter
|
|
201
249
|
def master(self, is_master: bool):
|
|
202
250
|
if self.initialized_state:
|
|
203
|
-
self.settings.child(
|
|
204
|
-
|
|
251
|
+
self.settings.child("move_settings", "multiaxes", "multi_status").setValue(
|
|
252
|
+
"Master" if is_master else "Slave"
|
|
253
|
+
)
|
|
205
254
|
|
|
206
|
-
def append_data(
|
|
255
|
+
def append_data(
|
|
256
|
+
self, dte: Optional[DataToExport] = None, where: Union[Node, str, None] = None
|
|
257
|
+
):
|
|
207
258
|
"""Appends current DataToExport to an ActuatorEnlargeableSaver
|
|
208
259
|
|
|
209
260
|
Parameters
|
|
210
261
|
----------
|
|
211
|
-
|
|
262
|
+
dte: DataToExport, optional
|
|
212
263
|
where: Node or str
|
|
213
264
|
See Also
|
|
214
265
|
--------
|
|
@@ -236,16 +287,15 @@ class DAQ_Move(ParameterControlModule):
|
|
|
236
287
|
DetectorSaver, DetectorEnlargeableSaver, DetectorExtendedSaver
|
|
237
288
|
|
|
238
289
|
"""
|
|
239
|
-
#todo: test this for logging
|
|
290
|
+
# todo: test this for logging
|
|
240
291
|
|
|
241
292
|
node = self.module_and_data_saver.get_set_node(where)
|
|
242
293
|
self.module_and_data_saver.add_data(node, data, **kwargs)
|
|
243
294
|
|
|
244
295
|
def stop_motion(self):
|
|
245
|
-
"""Stop any motion
|
|
246
|
-
"""
|
|
296
|
+
"""Stop any motion"""
|
|
247
297
|
try:
|
|
248
|
-
self.command_hardware.emit(ThreadCommand(
|
|
298
|
+
self.command_hardware.emit(ThreadCommand(ControlToHardwareMove.STOP_MOTION))
|
|
249
299
|
except Exception as e:
|
|
250
300
|
self.logger.exception(str(e))
|
|
251
301
|
|
|
@@ -265,11 +315,11 @@ class DAQ_Move(ParameterControlModule):
|
|
|
265
315
|
:meth:`move_abs`, :meth:`move_rel`, :meth:`move_home`, :class:`..utility_classes.MoveCommand`
|
|
266
316
|
|
|
267
317
|
"""
|
|
268
|
-
if move_command.move_type ==
|
|
318
|
+
if move_command.move_type == "abs":
|
|
269
319
|
self.move_abs(move_command.value)
|
|
270
|
-
elif move_command.move_type ==
|
|
320
|
+
elif move_command.move_type == "rel":
|
|
271
321
|
self.move_rel(move_command.value)
|
|
272
|
-
elif move_command.move_type ==
|
|
322
|
+
elif move_command.move_type == "home":
|
|
273
323
|
self.move_home(move_command.value)
|
|
274
324
|
|
|
275
325
|
def move_abs(self, value: Union[DataActuator, numbers.Number], send_to_tcpip=False):
|
|
@@ -286,7 +336,9 @@ class DAQ_Move(ParameterControlModule):
|
|
|
286
336
|
"""
|
|
287
337
|
try:
|
|
288
338
|
if isinstance(value, Number):
|
|
289
|
-
value = DataActuator(
|
|
339
|
+
value = DataActuator(
|
|
340
|
+
self.title, data=[np.array([value])], units=self.units
|
|
341
|
+
)
|
|
290
342
|
self._send_to_tcpip = send_to_tcpip
|
|
291
343
|
if value != self._current_value:
|
|
292
344
|
if self.ui is not None:
|
|
@@ -294,8 +346,12 @@ class DAQ_Move(ParameterControlModule):
|
|
|
294
346
|
self._move_done_bool = False
|
|
295
347
|
self._target_value = value
|
|
296
348
|
self.update_status("Moving")
|
|
297
|
-
self.command_hardware.emit(
|
|
298
|
-
|
|
349
|
+
self.command_hardware.emit(
|
|
350
|
+
ThreadCommand(ControlToHardwareMove.RESET_STOP_MOTION)
|
|
351
|
+
)
|
|
352
|
+
self.command_hardware.emit(
|
|
353
|
+
ThreadCommand(ControlToHardwareMove.MOVE_ABS, attribute=[value])
|
|
354
|
+
)
|
|
299
355
|
|
|
300
356
|
except Exception as e:
|
|
301
357
|
self.logger.exception(str(e))
|
|
@@ -314,13 +370,17 @@ class DAQ_Move(ParameterControlModule):
|
|
|
314
370
|
self.ui.move_done = False
|
|
315
371
|
self._move_done_bool = False
|
|
316
372
|
self.update_status("Moving")
|
|
317
|
-
self.command_hardware.emit(
|
|
318
|
-
|
|
373
|
+
self.command_hardware.emit(
|
|
374
|
+
ThreadCommand(ControlToHardwareMove.RESET_STOP_MOTION)
|
|
375
|
+
)
|
|
376
|
+
self.command_hardware.emit(ThreadCommand(ControlToHardwareMove.MOVE_HOME))
|
|
319
377
|
|
|
320
378
|
except Exception as e:
|
|
321
379
|
self.logger.exception(str(e))
|
|
322
380
|
|
|
323
|
-
def move_rel(
|
|
381
|
+
def move_rel(
|
|
382
|
+
self, rel_value: Union[DataActuator, numbers.Number], send_to_tcpip=False
|
|
383
|
+
):
|
|
324
384
|
"""Move the connected hardware to the relative value
|
|
325
385
|
|
|
326
386
|
Returns nothing but the move_done_signal will be send once the action is done
|
|
@@ -335,15 +395,21 @@ class DAQ_Move(ParameterControlModule):
|
|
|
335
395
|
|
|
336
396
|
try:
|
|
337
397
|
if isinstance(rel_value, Number):
|
|
338
|
-
rel_value = DataActuator(
|
|
398
|
+
rel_value = DataActuator(
|
|
399
|
+
self.title, data=[np.array([rel_value])], units=self.units
|
|
400
|
+
)
|
|
339
401
|
self._send_to_tcpip = send_to_tcpip
|
|
340
402
|
if self.ui is not None:
|
|
341
403
|
self.ui.move_done = False
|
|
342
404
|
self._move_done_bool = False
|
|
343
405
|
self._target_value = self._current_value + rel_value
|
|
344
406
|
self.update_status("Moving")
|
|
345
|
-
self.command_hardware.emit(
|
|
346
|
-
|
|
407
|
+
self.command_hardware.emit(
|
|
408
|
+
ThreadCommand(ControlToHardwareMove.RESET_STOP_MOTION)
|
|
409
|
+
)
|
|
410
|
+
self.command_hardware.emit(
|
|
411
|
+
ThreadCommand(ControlToHardwareMove.MOVE_REL, attribute=[rel_value])
|
|
412
|
+
)
|
|
347
413
|
|
|
348
414
|
except Exception as e:
|
|
349
415
|
self.logger.exception(str(e))
|
|
@@ -369,17 +435,19 @@ class DAQ_Move(ParameterControlModule):
|
|
|
369
435
|
# self.parent.close()
|
|
370
436
|
|
|
371
437
|
def init_hardware(self, do_init=True):
|
|
372
|
-
"""
|
|
438
|
+
"""Init or desinit the selected instrument plugin class"""
|
|
373
439
|
if not do_init:
|
|
374
440
|
try:
|
|
375
|
-
self.command_hardware.emit(ThreadCommand(
|
|
441
|
+
self.command_hardware.emit(ThreadCommand(ControlToHardwareMove.CLOSE))
|
|
376
442
|
if self.ui is not None:
|
|
377
443
|
self.ui.actuator_init = False
|
|
378
444
|
except Exception as e:
|
|
379
445
|
self.logger.exception(str(e))
|
|
380
446
|
else:
|
|
381
447
|
try:
|
|
382
|
-
hardware = DAQ_Move_Hardware(
|
|
448
|
+
hardware = DAQ_Move_Hardware(
|
|
449
|
+
self._actuator_type, self._current_value, self._title
|
|
450
|
+
)
|
|
383
451
|
self._hardware_thread = QThread()
|
|
384
452
|
hardware.moveToThread(self._hardware_thread)
|
|
385
453
|
|
|
@@ -390,9 +458,14 @@ class DAQ_Move(ParameterControlModule):
|
|
|
390
458
|
self._hardware_thread.hardware = hardware
|
|
391
459
|
self._hardware_thread.start()
|
|
392
460
|
self.command_hardware.emit(
|
|
393
|
-
ThreadCommand(
|
|
394
|
-
|
|
395
|
-
|
|
461
|
+
ThreadCommand(
|
|
462
|
+
ControlToHardwareMove.INI_STAGE,
|
|
463
|
+
attribute=[
|
|
464
|
+
self.settings.child("move_settings").saveState(),
|
|
465
|
+
self.controller,
|
|
466
|
+
],
|
|
467
|
+
)
|
|
468
|
+
)
|
|
396
469
|
except Exception as e:
|
|
397
470
|
self.logger.exception(str(e))
|
|
398
471
|
|
|
@@ -407,33 +480,40 @@ class DAQ_Move(ParameterControlModule):
|
|
|
407
480
|
return self._move_done_bool
|
|
408
481
|
|
|
409
482
|
def value_changed(self, param: Parameter):
|
|
410
|
-
"""
|
|
483
|
+
"""Apply changes of value in the settings"""
|
|
411
484
|
super().value_changed(param=param)
|
|
412
485
|
|
|
413
|
-
if param.name() ==
|
|
486
|
+
if param.name() == "refresh_timeout":
|
|
414
487
|
self._refresh_timer.setInterval(param.value())
|
|
415
488
|
|
|
416
489
|
self._update_settings(param=param)
|
|
417
490
|
|
|
418
491
|
def param_deleted(self, param):
|
|
419
|
-
"""
|
|
420
|
-
if param.name() not in putils.iter_children(
|
|
421
|
-
self.
|
|
492
|
+
"""Apply deletion of settings"""
|
|
493
|
+
if param.name() not in putils.iter_children(
|
|
494
|
+
self.settings.child("main_settings"), []
|
|
495
|
+
):
|
|
496
|
+
self._update_settings_signal.emit(
|
|
497
|
+
edict(path=["move_settings"], param=param, change="parent")
|
|
498
|
+
)
|
|
422
499
|
|
|
423
500
|
def child_added(self, param, data):
|
|
424
|
-
"""
|
|
501
|
+
"""Apply addition of settings"""
|
|
425
502
|
path = self.settings.childPath(param)
|
|
426
|
-
if
|
|
427
|
-
self._update_settings_signal.emit(
|
|
503
|
+
if "main_settings" not in path:
|
|
504
|
+
self._update_settings_signal.emit(
|
|
505
|
+
edict(path=path, param=data[0].saveState(), change="childAdded")
|
|
506
|
+
)
|
|
428
507
|
|
|
429
508
|
def raise_timeout(self):
|
|
430
|
-
"""
|
|
431
|
-
"""
|
|
509
|
+
"""Update status with "Timeout occurred" statement and change the timeout flag."""
|
|
432
510
|
self.update_status("Timeout occurred")
|
|
433
511
|
self.wait_position_flag = False
|
|
434
512
|
|
|
435
513
|
@Slot(ThreadCommand)
|
|
436
|
-
def thread_status(
|
|
514
|
+
def thread_status(
|
|
515
|
+
self, status: ThreadCommand
|
|
516
|
+
): # general function to get datas/infos from all threads back to the main
|
|
437
517
|
"""Get back info (using the ThreadCommand object) from the hardware
|
|
438
518
|
|
|
439
519
|
And re-emit this ThreadCommand using the custom_sig signal if it should be used in a higher level module
|
|
@@ -455,13 +535,15 @@ class DAQ_Move(ParameterControlModule):
|
|
|
455
535
|
* stop: stop the motion
|
|
456
536
|
"""
|
|
457
537
|
|
|
458
|
-
super().thread_status(status,
|
|
538
|
+
super().thread_status(status, "move")
|
|
459
539
|
|
|
460
|
-
if status.command ==
|
|
461
|
-
self.update_status(
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
540
|
+
if status.command == ThreadStatusMove.INI_STAGE:
|
|
541
|
+
self.update_status(
|
|
542
|
+
f"Stage initialized: {status.attribute['initialized']} "
|
|
543
|
+
f"info: {status.attribute['info']}"
|
|
544
|
+
)
|
|
545
|
+
if status.attribute["initialized"]:
|
|
546
|
+
self.controller = status.attribute["controller"]
|
|
465
547
|
if self.ui is not None:
|
|
466
548
|
self.ui.actuator_init = True
|
|
467
549
|
self._initialized_state = True
|
|
@@ -471,21 +553,33 @@ class DAQ_Move(ParameterControlModule):
|
|
|
471
553
|
self.get_actuator_value()
|
|
472
554
|
self.init_signal.emit(self._initialized_state)
|
|
473
555
|
|
|
474
|
-
elif
|
|
556
|
+
elif (
|
|
557
|
+
status.command == ThreadStatusMove.GET_ACTUATOR_VALUE
|
|
558
|
+
or status.command == "check_position"
|
|
559
|
+
):
|
|
475
560
|
data_act = self._check_data_type(status.attribute)
|
|
476
561
|
if self.ui is not None:
|
|
477
562
|
self.ui.display_value(data_act)
|
|
478
|
-
if self.ui.
|
|
479
|
-
|
|
480
|
-
|
|
563
|
+
if self.ui.has_action("show_graph") and self.ui.is_action_checked(
|
|
564
|
+
"show_graph"
|
|
565
|
+
):
|
|
566
|
+
self.ui.show_data(DataToExport(name=self.title, data=[data_act]))
|
|
481
567
|
self._current_value = data_act
|
|
482
568
|
self.current_value_signal.emit(self._current_value)
|
|
483
|
-
if
|
|
484
|
-
self.
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
569
|
+
if (
|
|
570
|
+
self.settings["main_settings", "tcpip", "tcp_connected"]
|
|
571
|
+
and self._send_to_tcpip
|
|
572
|
+
):
|
|
573
|
+
self._command_tcpip.emit(ThreadCommand("position_is", data_act))
|
|
574
|
+
if (
|
|
575
|
+
self.settings["main_settings", "leco", "leco_connected"]
|
|
576
|
+
and self._send_to_tcpip
|
|
577
|
+
):
|
|
578
|
+
self._command_tcpip.emit(
|
|
579
|
+
ThreadCommand(LECOMoveCommands.POSITION, data_act)
|
|
580
|
+
)
|
|
581
|
+
|
|
582
|
+
elif status.command == ThreadStatusMove.MOVE_DONE:
|
|
489
583
|
data_act = self._check_data_type(status.attribute)
|
|
490
584
|
if self.ui is not None:
|
|
491
585
|
self.ui.display_value(data_act)
|
|
@@ -493,47 +587,63 @@ class DAQ_Move(ParameterControlModule):
|
|
|
493
587
|
self._current_value = data_act
|
|
494
588
|
self._move_done_bool = True
|
|
495
589
|
self.move_done_signal.emit(data_act)
|
|
496
|
-
if
|
|
497
|
-
self.
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
590
|
+
if (
|
|
591
|
+
self.settings.child("main_settings", "tcpip", "tcp_connected").value()
|
|
592
|
+
and self._send_to_tcpip
|
|
593
|
+
):
|
|
594
|
+
self._command_tcpip.emit(ThreadCommand("move_done", data_act))
|
|
595
|
+
if (
|
|
596
|
+
self.settings.child("main_settings", "leco", "leco_connected").value()
|
|
597
|
+
and self._send_to_tcpip
|
|
598
|
+
):
|
|
599
|
+
self._command_tcpip.emit(
|
|
600
|
+
ThreadCommand(LECOMoveCommands.MOVE_DONE, data_act)
|
|
601
|
+
)
|
|
602
|
+
|
|
603
|
+
elif status.command == ThreadStatusMove.OUT_OF_BOUNDS:
|
|
604
|
+
logger.warning(f"The Actuator {self.title} has reached its defined bounds")
|
|
503
605
|
self.bounds_signal.emit(True)
|
|
504
606
|
|
|
505
|
-
elif status.command ==
|
|
607
|
+
elif status.command == ThreadStatusMove.SET_ALLOWED_VALUES:
|
|
506
608
|
if self.ui is not None:
|
|
507
609
|
self.ui.set_abs_spinbox_properties(**status.attribute)
|
|
508
610
|
|
|
509
|
-
elif status.command ==
|
|
611
|
+
elif status.command == ThreadStatusMove.STOP:
|
|
510
612
|
self.stop_motion()
|
|
511
613
|
|
|
512
|
-
elif status.command ==
|
|
614
|
+
elif status.command == ThreadStatusMove.UNITS:
|
|
513
615
|
self.units = status.attribute
|
|
514
616
|
|
|
515
|
-
def _check_data_type(
|
|
516
|
-
|
|
617
|
+
def _check_data_type(
|
|
618
|
+
self, data_act: Union[list, np.ndarray, Number, DataActuator]
|
|
619
|
+
) -> DataActuator:
|
|
620
|
+
"""Make sure the data is a DataActuator
|
|
517
621
|
|
|
518
622
|
Mostly to make sure DAQ_Move is backcompatible with old style plugins
|
|
519
623
|
"""
|
|
520
624
|
if isinstance(data_act, list): # backcompatibility
|
|
521
625
|
if isinstance(data_act[0], Number):
|
|
522
|
-
data_act = DataActuator(
|
|
626
|
+
data_act = DataActuator(
|
|
627
|
+
data=[np.atleast_1d(val) for val in data_act], units=self.units
|
|
628
|
+
)
|
|
523
629
|
elif isinstance(data_act[0], np.ndarray):
|
|
524
630
|
data_act = DataActuator(data=data_act, units=self.units)
|
|
525
631
|
elif isinstance(data_act[0], DataActuator):
|
|
526
632
|
data_act = data_act[0]
|
|
527
633
|
else:
|
|
528
|
-
raise TypeError(
|
|
634
|
+
raise TypeError("Unknown data type")
|
|
529
635
|
elif isinstance(data_act, np.ndarray): # backcompatibility
|
|
530
636
|
data_act = DataActuator(data=[data_act], units=self.units)
|
|
531
|
-
data_act.name =
|
|
532
|
-
|
|
533
|
-
|
|
637
|
+
data_act.name = (
|
|
638
|
+
self.title
|
|
639
|
+
) # for the DataActuator name to be the title of the DAQ_Move
|
|
640
|
+
if (
|
|
641
|
+
not Unit(self.units).is_compatible_with(Unit(data_act.units))
|
|
642
|
+
and data_act.units == ""
|
|
643
|
+
): # this happens if the units have not been specified in
|
|
534
644
|
# the plugin
|
|
535
645
|
data_act.force_units(self.units)
|
|
536
|
-
return
|
|
646
|
+
return data_act
|
|
537
647
|
|
|
538
648
|
def get_actuator_value(self):
|
|
539
649
|
"""Get the current actuator value via the "get_actuator_value" command send to the hardware
|
|
@@ -541,14 +651,16 @@ class DAQ_Move(ParameterControlModule):
|
|
|
541
651
|
Returns nothing but the `move_done_signal` will be send once the action is done
|
|
542
652
|
"""
|
|
543
653
|
try:
|
|
544
|
-
self.command_hardware.emit(
|
|
654
|
+
self.command_hardware.emit(
|
|
655
|
+
ThreadCommand(ControlToHardwareMove.GET_ACTUATOR_VALUE)
|
|
656
|
+
)
|
|
545
657
|
|
|
546
658
|
except Exception as e:
|
|
547
659
|
self.logger.exception(str(e))
|
|
548
660
|
|
|
549
661
|
def grab(self):
|
|
550
662
|
if self.ui is not None:
|
|
551
|
-
self.manage_ui_actions(
|
|
663
|
+
self.manage_ui_actions("refresh_value", "setChecked", False)
|
|
552
664
|
self.get_continuous_actuator_value(False)
|
|
553
665
|
|
|
554
666
|
def stop_grab(self):
|
|
@@ -557,7 +669,7 @@ class DAQ_Move(ParameterControlModule):
|
|
|
557
669
|
First uncheck the ui action if ui is not None, then stop the polling
|
|
558
670
|
"""
|
|
559
671
|
if self.ui is not None:
|
|
560
|
-
self.manage_ui_actions(
|
|
672
|
+
self.manage_ui_actions("refresh_value", "setChecked", False)
|
|
561
673
|
self.get_continuous_actuator_value(False)
|
|
562
674
|
|
|
563
675
|
def get_continuous_actuator_value(self, get_value=True):
|
|
@@ -573,7 +685,9 @@ class DAQ_Move(ParameterControlModule):
|
|
|
573
685
|
The current timer period is set by the refresh value *'refresh_timeout'* in the actuator main settings.
|
|
574
686
|
"""
|
|
575
687
|
if get_value:
|
|
576
|
-
self._refresh_timer.setInterval(
|
|
688
|
+
self._refresh_timer.setInterval(
|
|
689
|
+
self.settings["main_settings", "refresh_timeout"]
|
|
690
|
+
)
|
|
577
691
|
self._refresh_timer.start()
|
|
578
692
|
else:
|
|
579
693
|
self._refresh_timer.stop()
|
|
@@ -597,33 +711,92 @@ class DAQ_Move(ParameterControlModule):
|
|
|
597
711
|
self.ui.actuator = act_type
|
|
598
712
|
self.update_settings()
|
|
599
713
|
else:
|
|
600
|
-
raise ActuatorError(
|
|
714
|
+
raise ActuatorError(
|
|
715
|
+
f"{act_type} is an invalid actuator, should be within {ACTUATOR_TYPES}"
|
|
716
|
+
)
|
|
601
717
|
|
|
602
718
|
@property
|
|
603
719
|
def actuators(self) -> List[str]:
|
|
604
|
-
"""
|
|
720
|
+
"""Get the list of possible actuators"""
|
|
605
721
|
return ACTUATOR_TYPES
|
|
606
722
|
|
|
607
723
|
def update_plugin_config(self):
|
|
608
|
-
parent_module = utils.find_dict_in_list_from_key_val(
|
|
609
|
-
|
|
610
|
-
|
|
724
|
+
parent_module = utils.find_dict_in_list_from_key_val(
|
|
725
|
+
DAQ_Move_Actuators, "name", self.actuator
|
|
726
|
+
)
|
|
727
|
+
mod = import_module(parent_module["module"].__package__.split(".")[0])
|
|
728
|
+
if hasattr(mod, "config"):
|
|
611
729
|
self.plugin_config = mod.config
|
|
612
730
|
|
|
613
731
|
@property
|
|
614
732
|
def units(self):
|
|
615
733
|
"""Get/Set the units for the controller"""
|
|
616
|
-
return self.settings[
|
|
734
|
+
return self.settings["move_settings", "units"]
|
|
617
735
|
|
|
618
736
|
@units.setter
|
|
619
737
|
def units(self, unit: str):
|
|
620
|
-
self.settings.child(
|
|
621
|
-
if self.ui is not None and config(
|
|
622
|
-
self.
|
|
738
|
+
self.settings.child("move_settings", "units").setValue(unit)
|
|
739
|
+
if self.ui is not None and config("actuator", "display_units"):
|
|
740
|
+
unit = self.get_unit_to_display(unit)
|
|
741
|
+
self.ui.set_unit_as_suffix(unit)
|
|
742
|
+
self.ui.set_unit_prefix(
|
|
743
|
+
config("actuator", "siprefix")
|
|
744
|
+
and (unit != "" or config("actuator", "siprefix_even_without_units"))
|
|
745
|
+
)
|
|
746
|
+
|
|
747
|
+
@property
|
|
748
|
+
def axis_names(self) -> Union[List, Dict]:
|
|
749
|
+
""" Get the names of all possible axis"""
|
|
750
|
+
return self.settings.child('move_settings', 'multiaxes', 'axis').opts['limits']
|
|
751
|
+
|
|
752
|
+
@property
|
|
753
|
+
def axis_name(self) -> str:
|
|
754
|
+
""" Get/Set the current axis"""
|
|
755
|
+
limits = self.settings.child('move_settings', 'multiaxes', 'axis').opts['limits']
|
|
756
|
+
if isinstance(limits, list):
|
|
757
|
+
return self.settings['move_settings', 'multiaxes', 'axis']
|
|
758
|
+
elif isinstance(limits, dict):
|
|
759
|
+
return find_keys_from_val(limits,
|
|
760
|
+
val=self.settings['move_settings', 'multiaxes', 'axis'])[0]
|
|
761
|
+
|
|
762
|
+
@axis_name.setter
|
|
763
|
+
def axis_name(self, name: str):
|
|
764
|
+
""" Get/Set the current axis"""
|
|
765
|
+
limits = self.settings.child('move_settings', 'multiaxes', 'axis').opts['limits']
|
|
766
|
+
if name in limits:
|
|
767
|
+
if isinstance(limits, list):
|
|
768
|
+
self.settings.child('move_settings', 'multiaxes', 'axis').setValue(name)
|
|
769
|
+
elif isinstance(limits, dict):
|
|
770
|
+
self.settings.child('move_settings', 'multiaxes', 'axis').setValue(limits[name])
|
|
771
|
+
|
|
772
|
+
@property
|
|
773
|
+
def axis_names(self) -> Union[List, Dict]:
|
|
774
|
+
""" Get the names of all possible axis"""
|
|
775
|
+
return self.settings.child('move_settings', 'multiaxes', 'axis').opts['limits']
|
|
776
|
+
|
|
777
|
+
@property
|
|
778
|
+
def axis_name(self) -> str:
|
|
779
|
+
""" Get/Set the current axis"""
|
|
780
|
+
limits = self.settings.child('move_settings', 'multiaxes', 'axis').opts['limits']
|
|
781
|
+
if isinstance(limits, list):
|
|
782
|
+
return self.settings['move_settings', 'multiaxes', 'axis']
|
|
783
|
+
elif isinstance(limits, dict):
|
|
784
|
+
return find_keys_from_val(limits,
|
|
785
|
+
val=self.settings['move_settings', 'multiaxes', 'axis'])[0]
|
|
786
|
+
|
|
787
|
+
@axis_name.setter
|
|
788
|
+
def axis_name(self, name: str):
|
|
789
|
+
""" Get/Set the current axis"""
|
|
790
|
+
limits = self.settings.child('move_settings', 'multiaxes', 'axis').opts['limits']
|
|
791
|
+
if name in limits:
|
|
792
|
+
if isinstance(limits, list):
|
|
793
|
+
self.settings.child('move_settings', 'multiaxes', 'axis').setValue(name)
|
|
794
|
+
elif isinstance(limits, dict):
|
|
795
|
+
self.settings.child('move_settings', 'multiaxes', 'axis').setValue(limits[name])
|
|
623
796
|
|
|
624
797
|
@staticmethod
|
|
625
798
|
def get_unit_to_display(unit: str) -> str:
|
|
626
|
-
"""
|
|
799
|
+
"""Get the unit to be displayed in the UI
|
|
627
800
|
|
|
628
801
|
If the controller units are in mm the displayed unit will be m
|
|
629
802
|
because m is the base unit, then the user could ask for mm, km, µm...
|
|
@@ -637,94 +810,96 @@ class DAQ_Move(ParameterControlModule):
|
|
|
637
810
|
-------
|
|
638
811
|
str: the unit to be displayed on the ui
|
|
639
812
|
"""
|
|
640
|
-
if (
|
|
813
|
+
if ("°" in unit or "degree" in unit) and not "°C" in unit:
|
|
641
814
|
# special cas as pint base unit for angles are radians
|
|
642
|
-
return
|
|
643
|
-
elif
|
|
644
|
-
return
|
|
645
|
-
elif '°C' in unit or 'Celsius' in unit:
|
|
646
|
-
return '°C'
|
|
647
|
-
elif 'V' in unit or 'volt' in unit.lower():
|
|
648
|
-
return 'V'
|
|
649
|
-
elif 'Hz' in unit:
|
|
650
|
-
return 'Hz'
|
|
651
|
-
elif 'rpm' in unit or 'revolutions_per_minute' in unit:
|
|
652
|
-
return 'rpm'
|
|
815
|
+
return "°"
|
|
816
|
+
elif "°C" in unit:
|
|
817
|
+
return "°C"
|
|
653
818
|
else:
|
|
819
|
+
for key in config("actuator", "allowed_units"):
|
|
820
|
+
if key in unit:
|
|
821
|
+
return config("actuator", "allowed_units", key)
|
|
654
822
|
return str(Q_(1, unit).to_base_units().units)
|
|
655
823
|
|
|
656
824
|
def update_settings(self):
|
|
657
|
-
|
|
658
|
-
self.settings.child(
|
|
659
|
-
self.settings.child('main_settings', 'module_name').setValue(self._title)
|
|
825
|
+
self.settings.child("main_settings", "move_type").setValue(self._actuator_type)
|
|
826
|
+
self.settings.child("main_settings", "module_name").setValue(self._title)
|
|
660
827
|
try:
|
|
661
|
-
for child in self.settings.child(
|
|
828
|
+
for child in self.settings.child("move_settings").children():
|
|
662
829
|
child.remove()
|
|
663
|
-
parent_module = utils.find_dict_in_list_from_key_val(
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
830
|
+
parent_module = utils.find_dict_in_list_from_key_val(
|
|
831
|
+
DAQ_Move_Actuators, "name", self._actuator_type
|
|
832
|
+
)
|
|
833
|
+
class_ = getattr(
|
|
834
|
+
getattr(parent_module["module"], "daq_move_" + self._actuator_type),
|
|
835
|
+
"DAQ_Move_" + self._actuator_type,
|
|
836
|
+
)
|
|
837
|
+
params = getattr(class_, "params")
|
|
838
|
+
move_params = Parameter.create(
|
|
839
|
+
name="move_settings", type="group", children=params
|
|
840
|
+
)
|
|
841
|
+
|
|
842
|
+
self.settings.child("move_settings").addChildren(move_params.children())
|
|
670
843
|
|
|
671
844
|
except Exception as e:
|
|
672
845
|
self.logger.exception(str(e))
|
|
673
846
|
|
|
674
847
|
def connect_tcp_ip(self):
|
|
675
|
-
super().connect_tcp_ip(
|
|
676
|
-
|
|
848
|
+
super().connect_tcp_ip(
|
|
849
|
+
params_state=self.settings.child("move_settings"), client_type="ACTUATOR"
|
|
850
|
+
)
|
|
851
|
+
|
|
852
|
+
def connect_leco(self, connect: bool) -> None:
|
|
853
|
+
super().connect_leco(connect)
|
|
677
854
|
|
|
678
855
|
@Slot(ThreadCommand)
|
|
679
856
|
def process_tcpip_cmds(self, status: ThreadCommand) -> None:
|
|
680
857
|
if super().process_tcpip_cmds(status=status) is None:
|
|
681
858
|
return
|
|
682
|
-
if
|
|
683
|
-
self.move_abs(status.attribute
|
|
859
|
+
if LECOMoveCommands.MOVE_ABS == status.command:
|
|
860
|
+
self.move_abs(status.attribute, send_to_tcpip=True)
|
|
684
861
|
|
|
685
|
-
elif
|
|
686
|
-
self.move_rel(status.attribute
|
|
862
|
+
elif LECOMoveCommands.MOVE_REL == status.command:
|
|
863
|
+
self.move_rel(status.attribute, send_to_tcpip=True)
|
|
687
864
|
|
|
688
|
-
elif
|
|
865
|
+
elif LECOMoveCommands.MOVE_HOME == status.command:
|
|
689
866
|
self.move_home(send_to_tcpip=True)
|
|
690
867
|
|
|
691
|
-
elif
|
|
692
|
-
deprecation_msg(
|
|
868
|
+
elif "check_position" in status.command:
|
|
869
|
+
deprecation_msg(
|
|
870
|
+
"check_position is deprecated, you should use get_actuator_value"
|
|
871
|
+
)
|
|
693
872
|
self._send_to_tcpip = True
|
|
694
|
-
self.
|
|
873
|
+
self.get_actuator_value()
|
|
695
874
|
|
|
696
|
-
elif
|
|
875
|
+
elif LECOMoveCommands.GET_ACTUATOR_VALUE in status.command:
|
|
697
876
|
self._send_to_tcpip = True
|
|
698
|
-
self.
|
|
877
|
+
self.get_actuator_value()
|
|
699
878
|
|
|
700
|
-
elif status.command ==
|
|
701
|
-
|
|
702
|
-
param_as_xml = status.attribute[1]
|
|
703
|
-
param_dict = ioxml.XML_string_to_parameter(param_as_xml)[0]
|
|
704
|
-
param_tmp = Parameter.create(**param_dict)
|
|
705
|
-
param = self.settings.child('move_settings', *path_in_settings[1:])
|
|
706
|
-
param.restoreState(param_tmp.saveState())
|
|
879
|
+
elif status.command == LECOMoveCommands.STOP:
|
|
880
|
+
self.stop_motion()
|
|
707
881
|
|
|
708
882
|
|
|
709
883
|
class DAQ_Move_Hardware(QObject):
|
|
710
884
|
"""
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
885
|
+
================== ========================
|
|
886
|
+
**Attributes** **Type**
|
|
887
|
+
*status_sig* instance of Signal
|
|
888
|
+
*hardware* ???
|
|
889
|
+
*actuator_type* string
|
|
890
|
+
*current_position* float
|
|
891
|
+
*target_value* float
|
|
892
|
+
*hardware_adress* string
|
|
893
|
+
*axis_address* string
|
|
894
|
+
*motion_stoped* boolean
|
|
895
|
+
================== ========================
|
|
722
896
|
"""
|
|
897
|
+
|
|
723
898
|
status_sig = Signal(ThreadCommand)
|
|
724
899
|
|
|
725
|
-
def __init__(self, actuator_type, position: DataActuator, title=
|
|
900
|
+
def __init__(self, actuator_type, position: DataActuator, title="actuator"):
|
|
726
901
|
super().__init__()
|
|
727
|
-
self.logger = set_logger(f
|
|
902
|
+
self.logger = set_logger(f"{logger.name}.{title}.actuator")
|
|
728
903
|
self._title = title
|
|
729
904
|
self.hardware: Optional[DAQ_Move_base] = None
|
|
730
905
|
self.actuator_type = actuator_type
|
|
@@ -738,7 +913,7 @@ class DAQ_Move_Hardware(QObject):
|
|
|
738
913
|
|
|
739
914
|
def close(self):
|
|
740
915
|
"""
|
|
741
|
-
|
|
916
|
+
Uninitialize the stage closing the hardware.
|
|
742
917
|
|
|
743
918
|
"""
|
|
744
919
|
if self.hardware is not None and self.hardware.controller is not None:
|
|
@@ -747,8 +922,7 @@ class DAQ_Move_Hardware(QObject):
|
|
|
747
922
|
return "Stage uninitialized"
|
|
748
923
|
|
|
749
924
|
def get_actuator_value(self):
|
|
750
|
-
"""Get the current position checking the hardware value.
|
|
751
|
-
"""
|
|
925
|
+
"""Get the current position checking the hardware value."""
|
|
752
926
|
if self.hardware is not None:
|
|
753
927
|
pos = self.hardware.get_actuator_value()
|
|
754
928
|
if self.hardware.data_actuator_type == DataActuatorType.float:
|
|
@@ -756,86 +930,107 @@ class DAQ_Move_Hardware(QObject):
|
|
|
756
930
|
return pos
|
|
757
931
|
|
|
758
932
|
def check_position(self):
|
|
759
|
-
"""Get the current position checking the hardware position (deprecated)
|
|
760
|
-
""
|
|
761
|
-
deprecation_msg('check_position is deprecated, use get_actuator_value')
|
|
933
|
+
"""Get the current position checking the hardware position (deprecated)"""
|
|
934
|
+
deprecation_msg("check_position is deprecated, use get_actuator_value")
|
|
762
935
|
pos = self.hardware.get_actuator_value()
|
|
763
936
|
return pos
|
|
764
937
|
|
|
765
|
-
def ini_stage(self, params_state=None, controller=None):
|
|
938
|
+
def ini_stage(self, params_state=None, controller: Optional[HardwareController] = None) -> edict:
|
|
766
939
|
"""
|
|
767
|
-
|
|
940
|
+
Init a stage updating the hardware and sending an hardware move_done signal.
|
|
768
941
|
|
|
769
|
-
|
|
770
|
-
|
|
942
|
+
=============== =================================== ==========================================================================================================================
|
|
943
|
+
**Parameters** **Type** **Description**
|
|
771
944
|
|
|
772
|
-
|
|
945
|
+
*params_state* ordered dictionary list The parameter state of the hardware class composed by a list representing the tree to keep a temporary save of the tree
|
|
773
946
|
|
|
774
|
-
|
|
947
|
+
*controller* one or many instance of DAQ_Move The controller id of the hardware
|
|
775
948
|
|
|
776
|
-
|
|
777
|
-
|
|
949
|
+
*stage* instance of DAQ_Move Defining axes and motors
|
|
950
|
+
=============== =================================== ==========================================================================================================================
|
|
778
951
|
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
952
|
+
See Also
|
|
953
|
+
--------
|
|
954
|
+
DAQ_utils.ThreadCommand, DAQ_Move
|
|
782
955
|
"""
|
|
783
956
|
|
|
784
957
|
status = edict(initialized=False, info="")
|
|
785
958
|
try:
|
|
786
|
-
parent_module = utils.find_dict_in_list_from_key_val(
|
|
787
|
-
|
|
788
|
-
|
|
959
|
+
parent_module = utils.find_dict_in_list_from_key_val(
|
|
960
|
+
DAQ_Move_Actuators, "name", self.actuator_type
|
|
961
|
+
)
|
|
962
|
+
class_ = getattr(
|
|
963
|
+
getattr(parent_module["module"], "daq_move_" + self.actuator_type),
|
|
964
|
+
"DAQ_Move_" + self.actuator_type,
|
|
965
|
+
)
|
|
789
966
|
self.hardware = class_(self, params_state)
|
|
967
|
+
assert self.hardware is not None
|
|
790
968
|
try:
|
|
791
|
-
infos = self.hardware.ini_stage(
|
|
969
|
+
infos = self.hardware.ini_stage(
|
|
970
|
+
controller
|
|
971
|
+
) # return edict(info="", controller=, stage=)
|
|
792
972
|
except Exception as e:
|
|
793
973
|
logger.exception("Hardware couldn't be initialized", exc_info=e)
|
|
794
974
|
infos = str(e), False
|
|
795
975
|
|
|
796
976
|
if isinstance(infos, edict): # following old plugin templating
|
|
797
977
|
status.update(infos)
|
|
798
|
-
deprecation_msg(
|
|
799
|
-
|
|
978
|
+
deprecation_msg(
|
|
979
|
+
"Returns from init_stage should now be a string and a boolean,"
|
|
980
|
+
" see pymodaq_plugins_template",
|
|
981
|
+
stacklevel=3,
|
|
982
|
+
)
|
|
800
983
|
else:
|
|
801
984
|
status.info = infos[0]
|
|
802
985
|
status.initialized = infos[1]
|
|
803
986
|
status.controller = self.hardware.controller
|
|
804
987
|
self.hardware.move_done_signal.connect(self.move_done)
|
|
805
988
|
if status.initialized:
|
|
806
|
-
self.status_sig.emit(
|
|
989
|
+
self.status_sig.emit(
|
|
990
|
+
ThreadCommand(
|
|
991
|
+
ThreadStatusMove.GET_ACTUATOR_VALUE, self.get_actuator_value()
|
|
992
|
+
)
|
|
993
|
+
)
|
|
807
994
|
|
|
808
995
|
return status
|
|
809
996
|
except Exception as e:
|
|
810
997
|
self.logger.exception(str(e))
|
|
811
998
|
return status
|
|
812
999
|
|
|
813
|
-
def move_abs(self, position: DataActuator, polling=True):
|
|
1000
|
+
def move_abs(self, position: DataActuator, polling: bool = True) -> None:
|
|
814
1001
|
"""
|
|
815
1002
|
|
|
816
1003
|
"""
|
|
1004
|
+
assert self.hardware is not None
|
|
817
1005
|
position = check_units(position, self.hardware.axis_unit)
|
|
818
1006
|
self.hardware.move_is_done = False
|
|
819
1007
|
self.hardware.ispolling = polling
|
|
820
1008
|
if self.hardware.data_actuator_type == self.hardware.data_actuator_type.float:
|
|
821
|
-
self.hardware.move_abs(
|
|
1009
|
+
self.hardware.move_abs(
|
|
1010
|
+
position.units_as(self.hardware.axis_unit).value()
|
|
1011
|
+
) # convert to plugin controller current axis units
|
|
822
1012
|
else:
|
|
823
|
-
position.units =
|
|
1013
|
+
position.units = (
|
|
1014
|
+
self.hardware.axis_unit
|
|
1015
|
+
) # convert to plugin controller current axis units
|
|
824
1016
|
self.hardware.move_abs(position)
|
|
825
1017
|
self.hardware.poll_moving()
|
|
826
1018
|
|
|
827
|
-
def move_rel(self, rel_position: DataActuator, polling=True):
|
|
1019
|
+
def move_rel(self, rel_position: DataActuator, polling: bool = True) -> None:
|
|
828
1020
|
"""
|
|
829
1021
|
|
|
830
1022
|
"""
|
|
1023
|
+
assert self.hardware is not None
|
|
831
1024
|
rel_position = check_units(rel_position, self.hardware.axis_unit)
|
|
832
1025
|
self.hardware.move_is_done = False
|
|
833
1026
|
self.hardware.ispolling = polling
|
|
834
1027
|
|
|
835
1028
|
if self.hardware.data_actuator_type.name == 'float':
|
|
836
|
-
self.hardware.move_rel(rel_position.value())
|
|
1029
|
+
self.hardware.move_rel(rel_position.units_as(self.hardware.axis_unit).value())
|
|
837
1030
|
else:
|
|
838
|
-
rel_position.units =
|
|
1031
|
+
rel_position.units = (
|
|
1032
|
+
self.hardware.axis_unit
|
|
1033
|
+
) # convert to plugin current axis units
|
|
839
1034
|
self.hardware.move_rel(rel_position)
|
|
840
1035
|
|
|
841
1036
|
self.hardware.poll_moving()
|
|
@@ -843,28 +1038,30 @@ class DAQ_Move_Hardware(QObject):
|
|
|
843
1038
|
@Slot(float)
|
|
844
1039
|
def Move_Stoped(self, pos):
|
|
845
1040
|
"""
|
|
846
|
-
|
|
1041
|
+
Send a "move_done" Thread Command with the given position as an attribute.
|
|
847
1042
|
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
1043
|
+
See Also
|
|
1044
|
+
--------
|
|
1045
|
+
DAQ_utils.ThreadCommand
|
|
851
1046
|
"""
|
|
852
|
-
self.status_sig.emit(ThreadCommand(
|
|
1047
|
+
self.status_sig.emit(ThreadCommand(ThreadStatusMove.MOVE_DONE, pos))
|
|
853
1048
|
|
|
854
1049
|
def move_home(self):
|
|
855
1050
|
"""
|
|
856
|
-
|
|
1051
|
+
Make the hardware move to the init position.
|
|
857
1052
|
|
|
858
1053
|
"""
|
|
1054
|
+
assert self.hardware is not None
|
|
859
1055
|
self.hardware.move_is_done = False
|
|
860
1056
|
self.hardware.move_home()
|
|
861
1057
|
|
|
862
1058
|
@Slot(DataActuator)
|
|
863
1059
|
def move_done(self, pos: DataActuator):
|
|
864
|
-
"""Send the move_done signal back to the main class
|
|
865
|
-
"""
|
|
1060
|
+
"""Send the move_done signal back to the main class"""
|
|
866
1061
|
self._current_value = pos
|
|
867
|
-
self.status_sig.emit(
|
|
1062
|
+
self.status_sig.emit(
|
|
1063
|
+
ThreadCommand(command=ThreadStatusMove.MOVE_DONE, attribute=pos)
|
|
1064
|
+
)
|
|
868
1065
|
|
|
869
1066
|
@Slot(ThreadCommand)
|
|
870
1067
|
def queue_command(self, command: ThreadCommand):
|
|
@@ -892,32 +1089,38 @@ class DAQ_Move_Hardware(QObject):
|
|
|
892
1089
|
* **reset_stop_motion** command, set the motion_stopped attribute to false
|
|
893
1090
|
"""
|
|
894
1091
|
try:
|
|
895
|
-
logger.debug(f
|
|
896
|
-
if command.command ==
|
|
1092
|
+
logger.debug(f"Threadcommand {command.command} sent to {self.title}")
|
|
1093
|
+
if command.command == ControlToHardwareMove.INI_STAGE:
|
|
897
1094
|
status: edict = self.ini_stage(*command.attribute)
|
|
898
|
-
self.status_sig.emit(
|
|
1095
|
+
self.status_sig.emit(
|
|
1096
|
+
ThreadCommand(command=ThreadStatusMove.INI_STAGE, attribute=status)
|
|
1097
|
+
)
|
|
899
1098
|
|
|
900
|
-
elif command.command ==
|
|
1099
|
+
elif command.command == ControlToHardwareMove.CLOSE:
|
|
901
1100
|
status = self.close()
|
|
902
|
-
self.status_sig.emit(
|
|
1101
|
+
self.status_sig.emit(
|
|
1102
|
+
ThreadCommand(command=ThreadStatus.CLOSE, attribute=[status])
|
|
1103
|
+
)
|
|
903
1104
|
|
|
904
|
-
elif command.command ==
|
|
1105
|
+
elif command.command == ControlToHardwareMove.MOVE_ABS:
|
|
905
1106
|
self.move_abs(*command.attribute)
|
|
906
1107
|
|
|
907
|
-
elif command.command ==
|
|
1108
|
+
elif command.command == ControlToHardwareMove.MOVE_REL:
|
|
908
1109
|
self.move_rel(*command.attribute)
|
|
909
1110
|
|
|
910
|
-
elif command.command ==
|
|
1111
|
+
elif command.command == ControlToHardwareMove.MOVE_HOME:
|
|
911
1112
|
self.move_home()
|
|
912
1113
|
|
|
913
|
-
elif command.command ==
|
|
1114
|
+
elif command.command == ControlToHardwareMove.GET_ACTUATOR_VALUE:
|
|
914
1115
|
pos = self.get_actuator_value()
|
|
915
|
-
self.status_sig.emit(
|
|
1116
|
+
self.status_sig.emit(
|
|
1117
|
+
ThreadCommand(ThreadStatusMove.GET_ACTUATOR_VALUE, pos)
|
|
1118
|
+
)
|
|
916
1119
|
|
|
917
|
-
elif command.command ==
|
|
1120
|
+
elif command.command == ControlToHardwareMove.STOP_MOTION:
|
|
918
1121
|
self.stop_motion()
|
|
919
1122
|
|
|
920
|
-
elif command.command ==
|
|
1123
|
+
elif command.command == ControlToHardwareMove.RESET_STOP_MOTION:
|
|
921
1124
|
self.motion_stoped = False
|
|
922
1125
|
|
|
923
1126
|
else: # custom commands for particular plugins (see spectrometer module 'get_spectro_wl' for instance)
|
|
@@ -932,14 +1135,17 @@ class DAQ_Move_Hardware(QObject):
|
|
|
932
1135
|
|
|
933
1136
|
def stop_motion(self):
|
|
934
1137
|
"""
|
|
935
|
-
|
|
1138
|
+
stop hardware motion with motion_stopped attribute updtaed to True and a status signal sended with an "update_status" Thread Command
|
|
936
1139
|
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
1140
|
+
See Also
|
|
1141
|
+
--------
|
|
1142
|
+
DAQ_utils.ThreadCommand, stop_motion
|
|
940
1143
|
"""
|
|
941
|
-
self.status_sig.emit(
|
|
1144
|
+
self.status_sig.emit(
|
|
1145
|
+
ThreadCommand(command="Update_Status", attribute=["Motion stoping", "log"])
|
|
1146
|
+
)
|
|
942
1147
|
self.motion_stoped = True
|
|
1148
|
+
assert self.hardware is not None
|
|
943
1149
|
if self.hardware is not None and self.hardware.controller is not None:
|
|
944
1150
|
self.hardware.stop_motion()
|
|
945
1151
|
self.hardware.poll_timer.stop()
|
|
@@ -947,26 +1153,26 @@ class DAQ_Move_Hardware(QObject):
|
|
|
947
1153
|
@Slot(edict)
|
|
948
1154
|
def update_settings(self, settings_parameter_dict):
|
|
949
1155
|
"""
|
|
950
|
-
|
|
1156
|
+
Update settings of hardware with dictionary parameters in case of "Move_Settings" path, else update attribute with dictionnary parameters.
|
|
951
1157
|
|
|
952
|
-
|
|
953
|
-
|
|
1158
|
+
========================= =========== ======================================================
|
|
1159
|
+
**Parameters** **Type** **Description**
|
|
954
1160
|
|
|
955
|
-
|
|
956
|
-
|
|
1161
|
+
*settings_parameter_dict* dictionary Dictionary containing the path and linked parameter
|
|
1162
|
+
========================= =========== ======================================================
|
|
957
1163
|
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
1164
|
+
See Also
|
|
1165
|
+
--------
|
|
1166
|
+
update_settings
|
|
961
1167
|
"""
|
|
962
1168
|
# settings_parameter_dict = edict(path=path,param=param)
|
|
963
|
-
path = settings_parameter_dict[
|
|
964
|
-
param = settings_parameter_dict[
|
|
965
|
-
if path[0] ==
|
|
1169
|
+
path = settings_parameter_dict["path"]
|
|
1170
|
+
param = settings_parameter_dict["param"]
|
|
1171
|
+
if path[0] == "main_settings":
|
|
966
1172
|
if hasattr(self, path[-1]):
|
|
967
1173
|
setattr(self, path[-1], param.value())
|
|
968
1174
|
|
|
969
|
-
elif path[0] ==
|
|
1175
|
+
elif path[0] == "move_settings":
|
|
970
1176
|
if self.hardware is not None:
|
|
971
1177
|
self.hardware.update_settings(settings_parameter_dict)
|
|
972
1178
|
|
|
@@ -984,6 +1190,5 @@ def main(init_qt=True):
|
|
|
984
1190
|
return prog, widget
|
|
985
1191
|
|
|
986
1192
|
|
|
987
|
-
if __name__ ==
|
|
1193
|
+
if __name__ == "__main__":
|
|
988
1194
|
main()
|
|
989
|
-
|