pymodaq 5.0.17__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 +458 -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 +13 -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 +18 -4
- 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.17.dist-info → pymodaq-5.1.0.dist-info}/METADATA +7 -6
- pymodaq-5.1.0.dist-info/RECORD +154 -0
- {pymodaq-5.0.17.dist-info → pymodaq-5.1.0.dist-info}/entry_points.txt +0 -2
- pymodaq/extensions/bayesian/bayesian_optimisation.py +0 -685
- pymodaq/utils/leco/desktop.ini +0 -2
- pymodaq-5.0.17.dist-info/RECORD +0 -121
- {pymodaq-5.0.17.dist-info → pymodaq-5.1.0.dist-info}/WHEEL +0 -0
- {pymodaq-5.0.17.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,40 +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
|
-
|
|
522
|
-
|
|
625
|
+
if isinstance(data_act[0], Number):
|
|
626
|
+
data_act = DataActuator(
|
|
627
|
+
data=[np.atleast_1d(val) for val in data_act], units=self.units
|
|
628
|
+
)
|
|
629
|
+
elif isinstance(data_act[0], np.ndarray):
|
|
630
|
+
data_act = DataActuator(data=data_act, units=self.units)
|
|
631
|
+
elif isinstance(data_act[0], DataActuator):
|
|
632
|
+
data_act = data_act[0]
|
|
633
|
+
else:
|
|
634
|
+
raise TypeError("Unknown data type")
|
|
635
|
+
elif isinstance(data_act, np.ndarray): # backcompatibility
|
|
523
636
|
data_act = DataActuator(data=[data_act], units=self.units)
|
|
524
|
-
data_act.name =
|
|
525
|
-
|
|
526
|
-
|
|
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
|
|
527
644
|
# the plugin
|
|
528
645
|
data_act.force_units(self.units)
|
|
529
|
-
return
|
|
646
|
+
return data_act
|
|
530
647
|
|
|
531
648
|
def get_actuator_value(self):
|
|
532
649
|
"""Get the current actuator value via the "get_actuator_value" command send to the hardware
|
|
@@ -534,14 +651,16 @@ class DAQ_Move(ParameterControlModule):
|
|
|
534
651
|
Returns nothing but the `move_done_signal` will be send once the action is done
|
|
535
652
|
"""
|
|
536
653
|
try:
|
|
537
|
-
self.command_hardware.emit(
|
|
654
|
+
self.command_hardware.emit(
|
|
655
|
+
ThreadCommand(ControlToHardwareMove.GET_ACTUATOR_VALUE)
|
|
656
|
+
)
|
|
538
657
|
|
|
539
658
|
except Exception as e:
|
|
540
659
|
self.logger.exception(str(e))
|
|
541
660
|
|
|
542
661
|
def grab(self):
|
|
543
662
|
if self.ui is not None:
|
|
544
|
-
self.manage_ui_actions(
|
|
663
|
+
self.manage_ui_actions("refresh_value", "setChecked", False)
|
|
545
664
|
self.get_continuous_actuator_value(False)
|
|
546
665
|
|
|
547
666
|
def stop_grab(self):
|
|
@@ -550,7 +669,7 @@ class DAQ_Move(ParameterControlModule):
|
|
|
550
669
|
First uncheck the ui action if ui is not None, then stop the polling
|
|
551
670
|
"""
|
|
552
671
|
if self.ui is not None:
|
|
553
|
-
self.manage_ui_actions(
|
|
672
|
+
self.manage_ui_actions("refresh_value", "setChecked", False)
|
|
554
673
|
self.get_continuous_actuator_value(False)
|
|
555
674
|
|
|
556
675
|
def get_continuous_actuator_value(self, get_value=True):
|
|
@@ -566,7 +685,9 @@ class DAQ_Move(ParameterControlModule):
|
|
|
566
685
|
The current timer period is set by the refresh value *'refresh_timeout'* in the actuator main settings.
|
|
567
686
|
"""
|
|
568
687
|
if get_value:
|
|
569
|
-
self._refresh_timer.setInterval(
|
|
688
|
+
self._refresh_timer.setInterval(
|
|
689
|
+
self.settings["main_settings", "refresh_timeout"]
|
|
690
|
+
)
|
|
570
691
|
self._refresh_timer.start()
|
|
571
692
|
else:
|
|
572
693
|
self._refresh_timer.stop()
|
|
@@ -590,33 +711,92 @@ class DAQ_Move(ParameterControlModule):
|
|
|
590
711
|
self.ui.actuator = act_type
|
|
591
712
|
self.update_settings()
|
|
592
713
|
else:
|
|
593
|
-
raise ActuatorError(
|
|
714
|
+
raise ActuatorError(
|
|
715
|
+
f"{act_type} is an invalid actuator, should be within {ACTUATOR_TYPES}"
|
|
716
|
+
)
|
|
594
717
|
|
|
595
718
|
@property
|
|
596
719
|
def actuators(self) -> List[str]:
|
|
597
|
-
"""
|
|
720
|
+
"""Get the list of possible actuators"""
|
|
598
721
|
return ACTUATOR_TYPES
|
|
599
722
|
|
|
600
723
|
def update_plugin_config(self):
|
|
601
|
-
parent_module = utils.find_dict_in_list_from_key_val(
|
|
602
|
-
|
|
603
|
-
|
|
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"):
|
|
604
729
|
self.plugin_config = mod.config
|
|
605
730
|
|
|
606
731
|
@property
|
|
607
732
|
def units(self):
|
|
608
733
|
"""Get/Set the units for the controller"""
|
|
609
|
-
return self.settings[
|
|
734
|
+
return self.settings["move_settings", "units"]
|
|
610
735
|
|
|
611
736
|
@units.setter
|
|
612
737
|
def units(self, unit: str):
|
|
613
|
-
self.settings.child(
|
|
614
|
-
if self.ui is not None and config(
|
|
615
|
-
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])
|
|
616
796
|
|
|
617
797
|
@staticmethod
|
|
618
798
|
def get_unit_to_display(unit: str) -> str:
|
|
619
|
-
"""
|
|
799
|
+
"""Get the unit to be displayed in the UI
|
|
620
800
|
|
|
621
801
|
If the controller units are in mm the displayed unit will be m
|
|
622
802
|
because m is the base unit, then the user could ask for mm, km, µm...
|
|
@@ -630,94 +810,96 @@ class DAQ_Move(ParameterControlModule):
|
|
|
630
810
|
-------
|
|
631
811
|
str: the unit to be displayed on the ui
|
|
632
812
|
"""
|
|
633
|
-
if (
|
|
813
|
+
if ("°" in unit or "degree" in unit) and not "°C" in unit:
|
|
634
814
|
# special cas as pint base unit for angles are radians
|
|
635
|
-
return
|
|
636
|
-
elif
|
|
637
|
-
return
|
|
638
|
-
elif '°C' in unit or 'Celsius' in unit:
|
|
639
|
-
return '°C'
|
|
640
|
-
elif 'V' in unit or 'volt' in unit.lower():
|
|
641
|
-
return 'V'
|
|
642
|
-
elif 'Hz' in unit:
|
|
643
|
-
return 'Hz'
|
|
644
|
-
elif 'rpm' in unit or 'revolutions_per_minute' in unit:
|
|
645
|
-
return 'rpm'
|
|
815
|
+
return "°"
|
|
816
|
+
elif "°C" in unit:
|
|
817
|
+
return "°C"
|
|
646
818
|
else:
|
|
819
|
+
for key in config("actuator", "allowed_units"):
|
|
820
|
+
if key in unit:
|
|
821
|
+
return config("actuator", "allowed_units", key)
|
|
647
822
|
return str(Q_(1, unit).to_base_units().units)
|
|
648
823
|
|
|
649
824
|
def update_settings(self):
|
|
650
|
-
|
|
651
|
-
self.settings.child(
|
|
652
|
-
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)
|
|
653
827
|
try:
|
|
654
|
-
for child in self.settings.child(
|
|
828
|
+
for child in self.settings.child("move_settings").children():
|
|
655
829
|
child.remove()
|
|
656
|
-
parent_module = utils.find_dict_in_list_from_key_val(
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
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())
|
|
663
843
|
|
|
664
844
|
except Exception as e:
|
|
665
845
|
self.logger.exception(str(e))
|
|
666
846
|
|
|
667
847
|
def connect_tcp_ip(self):
|
|
668
|
-
super().connect_tcp_ip(
|
|
669
|
-
|
|
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)
|
|
670
854
|
|
|
671
855
|
@Slot(ThreadCommand)
|
|
672
856
|
def process_tcpip_cmds(self, status: ThreadCommand) -> None:
|
|
673
857
|
if super().process_tcpip_cmds(status=status) is None:
|
|
674
858
|
return
|
|
675
|
-
if
|
|
676
|
-
self.move_abs(status.attribute
|
|
859
|
+
if LECOMoveCommands.MOVE_ABS == status.command:
|
|
860
|
+
self.move_abs(status.attribute, send_to_tcpip=True)
|
|
677
861
|
|
|
678
|
-
elif
|
|
679
|
-
self.move_rel(status.attribute
|
|
862
|
+
elif LECOMoveCommands.MOVE_REL == status.command:
|
|
863
|
+
self.move_rel(status.attribute, send_to_tcpip=True)
|
|
680
864
|
|
|
681
|
-
elif
|
|
865
|
+
elif LECOMoveCommands.MOVE_HOME == status.command:
|
|
682
866
|
self.move_home(send_to_tcpip=True)
|
|
683
867
|
|
|
684
|
-
elif
|
|
685
|
-
deprecation_msg(
|
|
868
|
+
elif "check_position" in status.command:
|
|
869
|
+
deprecation_msg(
|
|
870
|
+
"check_position is deprecated, you should use get_actuator_value"
|
|
871
|
+
)
|
|
686
872
|
self._send_to_tcpip = True
|
|
687
|
-
self.
|
|
873
|
+
self.get_actuator_value()
|
|
688
874
|
|
|
689
|
-
elif
|
|
875
|
+
elif LECOMoveCommands.GET_ACTUATOR_VALUE in status.command:
|
|
690
876
|
self._send_to_tcpip = True
|
|
691
|
-
self.
|
|
877
|
+
self.get_actuator_value()
|
|
692
878
|
|
|
693
|
-
elif status.command ==
|
|
694
|
-
|
|
695
|
-
param_as_xml = status.attribute[1]
|
|
696
|
-
param_dict = ioxml.XML_string_to_parameter(param_as_xml)[0]
|
|
697
|
-
param_tmp = Parameter.create(**param_dict)
|
|
698
|
-
param = self.settings.child('move_settings', *path_in_settings[1:])
|
|
699
|
-
param.restoreState(param_tmp.saveState())
|
|
879
|
+
elif status.command == LECOMoveCommands.STOP:
|
|
880
|
+
self.stop_motion()
|
|
700
881
|
|
|
701
882
|
|
|
702
883
|
class DAQ_Move_Hardware(QObject):
|
|
703
884
|
"""
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
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
|
+
================== ========================
|
|
715
896
|
"""
|
|
897
|
+
|
|
716
898
|
status_sig = Signal(ThreadCommand)
|
|
717
899
|
|
|
718
|
-
def __init__(self, actuator_type, position: DataActuator, title=
|
|
900
|
+
def __init__(self, actuator_type, position: DataActuator, title="actuator"):
|
|
719
901
|
super().__init__()
|
|
720
|
-
self.logger = set_logger(f
|
|
902
|
+
self.logger = set_logger(f"{logger.name}.{title}.actuator")
|
|
721
903
|
self._title = title
|
|
722
904
|
self.hardware: Optional[DAQ_Move_base] = None
|
|
723
905
|
self.actuator_type = actuator_type
|
|
@@ -731,7 +913,7 @@ class DAQ_Move_Hardware(QObject):
|
|
|
731
913
|
|
|
732
914
|
def close(self):
|
|
733
915
|
"""
|
|
734
|
-
|
|
916
|
+
Uninitialize the stage closing the hardware.
|
|
735
917
|
|
|
736
918
|
"""
|
|
737
919
|
if self.hardware is not None and self.hardware.controller is not None:
|
|
@@ -740,8 +922,7 @@ class DAQ_Move_Hardware(QObject):
|
|
|
740
922
|
return "Stage uninitialized"
|
|
741
923
|
|
|
742
924
|
def get_actuator_value(self):
|
|
743
|
-
"""Get the current position checking the hardware value.
|
|
744
|
-
"""
|
|
925
|
+
"""Get the current position checking the hardware value."""
|
|
745
926
|
if self.hardware is not None:
|
|
746
927
|
pos = self.hardware.get_actuator_value()
|
|
747
928
|
if self.hardware.data_actuator_type == DataActuatorType.float:
|
|
@@ -749,86 +930,107 @@ class DAQ_Move_Hardware(QObject):
|
|
|
749
930
|
return pos
|
|
750
931
|
|
|
751
932
|
def check_position(self):
|
|
752
|
-
"""Get the current position checking the hardware position (deprecated)
|
|
753
|
-
""
|
|
754
|
-
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")
|
|
755
935
|
pos = self.hardware.get_actuator_value()
|
|
756
936
|
return pos
|
|
757
937
|
|
|
758
|
-
def ini_stage(self, params_state=None, controller=None):
|
|
938
|
+
def ini_stage(self, params_state=None, controller: Optional[HardwareController] = None) -> edict:
|
|
759
939
|
"""
|
|
760
|
-
|
|
940
|
+
Init a stage updating the hardware and sending an hardware move_done signal.
|
|
761
941
|
|
|
762
|
-
|
|
763
|
-
|
|
942
|
+
=============== =================================== ==========================================================================================================================
|
|
943
|
+
**Parameters** **Type** **Description**
|
|
764
944
|
|
|
765
|
-
|
|
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
|
|
766
946
|
|
|
767
|
-
|
|
947
|
+
*controller* one or many instance of DAQ_Move The controller id of the hardware
|
|
768
948
|
|
|
769
|
-
|
|
770
|
-
|
|
949
|
+
*stage* instance of DAQ_Move Defining axes and motors
|
|
950
|
+
=============== =================================== ==========================================================================================================================
|
|
771
951
|
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
952
|
+
See Also
|
|
953
|
+
--------
|
|
954
|
+
DAQ_utils.ThreadCommand, DAQ_Move
|
|
775
955
|
"""
|
|
776
956
|
|
|
777
957
|
status = edict(initialized=False, info="")
|
|
778
958
|
try:
|
|
779
|
-
parent_module = utils.find_dict_in_list_from_key_val(
|
|
780
|
-
|
|
781
|
-
|
|
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
|
+
)
|
|
782
966
|
self.hardware = class_(self, params_state)
|
|
967
|
+
assert self.hardware is not None
|
|
783
968
|
try:
|
|
784
|
-
infos = self.hardware.ini_stage(
|
|
969
|
+
infos = self.hardware.ini_stage(
|
|
970
|
+
controller
|
|
971
|
+
) # return edict(info="", controller=, stage=)
|
|
785
972
|
except Exception as e:
|
|
786
973
|
logger.exception("Hardware couldn't be initialized", exc_info=e)
|
|
787
974
|
infos = str(e), False
|
|
788
975
|
|
|
789
976
|
if isinstance(infos, edict): # following old plugin templating
|
|
790
977
|
status.update(infos)
|
|
791
|
-
deprecation_msg(
|
|
792
|
-
|
|
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
|
+
)
|
|
793
983
|
else:
|
|
794
984
|
status.info = infos[0]
|
|
795
985
|
status.initialized = infos[1]
|
|
796
986
|
status.controller = self.hardware.controller
|
|
797
987
|
self.hardware.move_done_signal.connect(self.move_done)
|
|
798
988
|
if status.initialized:
|
|
799
|
-
self.status_sig.emit(
|
|
989
|
+
self.status_sig.emit(
|
|
990
|
+
ThreadCommand(
|
|
991
|
+
ThreadStatusMove.GET_ACTUATOR_VALUE, self.get_actuator_value()
|
|
992
|
+
)
|
|
993
|
+
)
|
|
800
994
|
|
|
801
995
|
return status
|
|
802
996
|
except Exception as e:
|
|
803
997
|
self.logger.exception(str(e))
|
|
804
998
|
return status
|
|
805
999
|
|
|
806
|
-
def move_abs(self, position: DataActuator, polling=True):
|
|
1000
|
+
def move_abs(self, position: DataActuator, polling: bool = True) -> None:
|
|
807
1001
|
"""
|
|
808
1002
|
|
|
809
1003
|
"""
|
|
1004
|
+
assert self.hardware is not None
|
|
810
1005
|
position = check_units(position, self.hardware.axis_unit)
|
|
811
1006
|
self.hardware.move_is_done = False
|
|
812
1007
|
self.hardware.ispolling = polling
|
|
813
1008
|
if self.hardware.data_actuator_type == self.hardware.data_actuator_type.float:
|
|
814
|
-
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
|
|
815
1012
|
else:
|
|
816
|
-
position.units =
|
|
1013
|
+
position.units = (
|
|
1014
|
+
self.hardware.axis_unit
|
|
1015
|
+
) # convert to plugin controller current axis units
|
|
817
1016
|
self.hardware.move_abs(position)
|
|
818
1017
|
self.hardware.poll_moving()
|
|
819
1018
|
|
|
820
|
-
def move_rel(self, rel_position: DataActuator, polling=True):
|
|
1019
|
+
def move_rel(self, rel_position: DataActuator, polling: bool = True) -> None:
|
|
821
1020
|
"""
|
|
822
1021
|
|
|
823
1022
|
"""
|
|
1023
|
+
assert self.hardware is not None
|
|
824
1024
|
rel_position = check_units(rel_position, self.hardware.axis_unit)
|
|
825
1025
|
self.hardware.move_is_done = False
|
|
826
1026
|
self.hardware.ispolling = polling
|
|
827
1027
|
|
|
828
1028
|
if self.hardware.data_actuator_type.name == 'float':
|
|
829
|
-
self.hardware.move_rel(rel_position.value())
|
|
1029
|
+
self.hardware.move_rel(rel_position.units_as(self.hardware.axis_unit).value())
|
|
830
1030
|
else:
|
|
831
|
-
rel_position.units =
|
|
1031
|
+
rel_position.units = (
|
|
1032
|
+
self.hardware.axis_unit
|
|
1033
|
+
) # convert to plugin current axis units
|
|
832
1034
|
self.hardware.move_rel(rel_position)
|
|
833
1035
|
|
|
834
1036
|
self.hardware.poll_moving()
|
|
@@ -836,28 +1038,30 @@ class DAQ_Move_Hardware(QObject):
|
|
|
836
1038
|
@Slot(float)
|
|
837
1039
|
def Move_Stoped(self, pos):
|
|
838
1040
|
"""
|
|
839
|
-
|
|
1041
|
+
Send a "move_done" Thread Command with the given position as an attribute.
|
|
840
1042
|
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
1043
|
+
See Also
|
|
1044
|
+
--------
|
|
1045
|
+
DAQ_utils.ThreadCommand
|
|
844
1046
|
"""
|
|
845
|
-
self.status_sig.emit(ThreadCommand(
|
|
1047
|
+
self.status_sig.emit(ThreadCommand(ThreadStatusMove.MOVE_DONE, pos))
|
|
846
1048
|
|
|
847
1049
|
def move_home(self):
|
|
848
1050
|
"""
|
|
849
|
-
|
|
1051
|
+
Make the hardware move to the init position.
|
|
850
1052
|
|
|
851
1053
|
"""
|
|
1054
|
+
assert self.hardware is not None
|
|
852
1055
|
self.hardware.move_is_done = False
|
|
853
1056
|
self.hardware.move_home()
|
|
854
1057
|
|
|
855
1058
|
@Slot(DataActuator)
|
|
856
1059
|
def move_done(self, pos: DataActuator):
|
|
857
|
-
"""Send the move_done signal back to the main class
|
|
858
|
-
"""
|
|
1060
|
+
"""Send the move_done signal back to the main class"""
|
|
859
1061
|
self._current_value = pos
|
|
860
|
-
self.status_sig.emit(
|
|
1062
|
+
self.status_sig.emit(
|
|
1063
|
+
ThreadCommand(command=ThreadStatusMove.MOVE_DONE, attribute=pos)
|
|
1064
|
+
)
|
|
861
1065
|
|
|
862
1066
|
@Slot(ThreadCommand)
|
|
863
1067
|
def queue_command(self, command: ThreadCommand):
|
|
@@ -885,32 +1089,38 @@ class DAQ_Move_Hardware(QObject):
|
|
|
885
1089
|
* **reset_stop_motion** command, set the motion_stopped attribute to false
|
|
886
1090
|
"""
|
|
887
1091
|
try:
|
|
888
|
-
logger.debug(f
|
|
889
|
-
if command.command ==
|
|
1092
|
+
logger.debug(f"Threadcommand {command.command} sent to {self.title}")
|
|
1093
|
+
if command.command == ControlToHardwareMove.INI_STAGE:
|
|
890
1094
|
status: edict = self.ini_stage(*command.attribute)
|
|
891
|
-
self.status_sig.emit(
|
|
1095
|
+
self.status_sig.emit(
|
|
1096
|
+
ThreadCommand(command=ThreadStatusMove.INI_STAGE, attribute=status)
|
|
1097
|
+
)
|
|
892
1098
|
|
|
893
|
-
elif command.command ==
|
|
1099
|
+
elif command.command == ControlToHardwareMove.CLOSE:
|
|
894
1100
|
status = self.close()
|
|
895
|
-
self.status_sig.emit(
|
|
1101
|
+
self.status_sig.emit(
|
|
1102
|
+
ThreadCommand(command=ThreadStatus.CLOSE, attribute=[status])
|
|
1103
|
+
)
|
|
896
1104
|
|
|
897
|
-
elif command.command ==
|
|
1105
|
+
elif command.command == ControlToHardwareMove.MOVE_ABS:
|
|
898
1106
|
self.move_abs(*command.attribute)
|
|
899
1107
|
|
|
900
|
-
elif command.command ==
|
|
1108
|
+
elif command.command == ControlToHardwareMove.MOVE_REL:
|
|
901
1109
|
self.move_rel(*command.attribute)
|
|
902
1110
|
|
|
903
|
-
elif command.command ==
|
|
1111
|
+
elif command.command == ControlToHardwareMove.MOVE_HOME:
|
|
904
1112
|
self.move_home()
|
|
905
1113
|
|
|
906
|
-
elif command.command ==
|
|
1114
|
+
elif command.command == ControlToHardwareMove.GET_ACTUATOR_VALUE:
|
|
907
1115
|
pos = self.get_actuator_value()
|
|
908
|
-
self.status_sig.emit(
|
|
1116
|
+
self.status_sig.emit(
|
|
1117
|
+
ThreadCommand(ThreadStatusMove.GET_ACTUATOR_VALUE, pos)
|
|
1118
|
+
)
|
|
909
1119
|
|
|
910
|
-
elif command.command ==
|
|
1120
|
+
elif command.command == ControlToHardwareMove.STOP_MOTION:
|
|
911
1121
|
self.stop_motion()
|
|
912
1122
|
|
|
913
|
-
elif command.command ==
|
|
1123
|
+
elif command.command == ControlToHardwareMove.RESET_STOP_MOTION:
|
|
914
1124
|
self.motion_stoped = False
|
|
915
1125
|
|
|
916
1126
|
else: # custom commands for particular plugins (see spectrometer module 'get_spectro_wl' for instance)
|
|
@@ -925,14 +1135,17 @@ class DAQ_Move_Hardware(QObject):
|
|
|
925
1135
|
|
|
926
1136
|
def stop_motion(self):
|
|
927
1137
|
"""
|
|
928
|
-
|
|
1138
|
+
stop hardware motion with motion_stopped attribute updtaed to True and a status signal sended with an "update_status" Thread Command
|
|
929
1139
|
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
1140
|
+
See Also
|
|
1141
|
+
--------
|
|
1142
|
+
DAQ_utils.ThreadCommand, stop_motion
|
|
933
1143
|
"""
|
|
934
|
-
self.status_sig.emit(
|
|
1144
|
+
self.status_sig.emit(
|
|
1145
|
+
ThreadCommand(command="Update_Status", attribute=["Motion stoping", "log"])
|
|
1146
|
+
)
|
|
935
1147
|
self.motion_stoped = True
|
|
1148
|
+
assert self.hardware is not None
|
|
936
1149
|
if self.hardware is not None and self.hardware.controller is not None:
|
|
937
1150
|
self.hardware.stop_motion()
|
|
938
1151
|
self.hardware.poll_timer.stop()
|
|
@@ -940,26 +1153,26 @@ class DAQ_Move_Hardware(QObject):
|
|
|
940
1153
|
@Slot(edict)
|
|
941
1154
|
def update_settings(self, settings_parameter_dict):
|
|
942
1155
|
"""
|
|
943
|
-
|
|
1156
|
+
Update settings of hardware with dictionary parameters in case of "Move_Settings" path, else update attribute with dictionnary parameters.
|
|
944
1157
|
|
|
945
|
-
|
|
946
|
-
|
|
1158
|
+
========================= =========== ======================================================
|
|
1159
|
+
**Parameters** **Type** **Description**
|
|
947
1160
|
|
|
948
|
-
|
|
949
|
-
|
|
1161
|
+
*settings_parameter_dict* dictionary Dictionary containing the path and linked parameter
|
|
1162
|
+
========================= =========== ======================================================
|
|
950
1163
|
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
1164
|
+
See Also
|
|
1165
|
+
--------
|
|
1166
|
+
update_settings
|
|
954
1167
|
"""
|
|
955
1168
|
# settings_parameter_dict = edict(path=path,param=param)
|
|
956
|
-
path = settings_parameter_dict[
|
|
957
|
-
param = settings_parameter_dict[
|
|
958
|
-
if path[0] ==
|
|
1169
|
+
path = settings_parameter_dict["path"]
|
|
1170
|
+
param = settings_parameter_dict["param"]
|
|
1171
|
+
if path[0] == "main_settings":
|
|
959
1172
|
if hasattr(self, path[-1]):
|
|
960
1173
|
setattr(self, path[-1], param.value())
|
|
961
1174
|
|
|
962
|
-
elif path[0] ==
|
|
1175
|
+
elif path[0] == "move_settings":
|
|
963
1176
|
if self.hardware is not None:
|
|
964
1177
|
self.hardware.update_settings(settings_parameter_dict)
|
|
965
1178
|
|
|
@@ -977,6 +1190,5 @@ def main(init_qt=True):
|
|
|
977
1190
|
return prog, widget
|
|
978
1191
|
|
|
979
1192
|
|
|
980
|
-
if __name__ ==
|
|
1193
|
+
if __name__ == "__main__":
|
|
981
1194
|
main()
|
|
982
|
-
|