pymodaq 5.0.0__py3-none-any.whl → 5.0.2__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 +55 -89
- pymodaq/control_modules/daq_move.py +129 -55
- pymodaq/control_modules/daq_move_ui.py +42 -11
- pymodaq/control_modules/daq_viewer.py +32 -13
- pymodaq/control_modules/move_utility_classes.py +346 -79
- pymodaq/control_modules/utils.py +26 -9
- pymodaq/control_modules/viewer_utility_classes.py +51 -14
- pymodaq/daq_utils/daq_utils.py +6 -0
- pymodaq/dashboard.py +532 -263
- pymodaq/examples/qt_less_standalone_module.py +128 -0
- pymodaq/extensions/bayesian/bayesian_optimisation.py +30 -21
- pymodaq/extensions/bayesian/utils.py +6 -3
- pymodaq/extensions/daq_logger/__init__.py +1 -0
- pymodaq/extensions/daq_logger/daq_logger.py +4 -5
- pymodaq/extensions/daq_scan.py +28 -8
- pymodaq/extensions/daq_scan_ui.py +7 -9
- pymodaq/extensions/pid/__init__.py +0 -1
- pymodaq/extensions/pid/actuator_controller.py +13 -0
- pymodaq/extensions/pid/daq_move_PID.py +25 -46
- pymodaq/extensions/pid/pid_controller.py +49 -41
- pymodaq/extensions/pid/utils.py +7 -31
- pymodaq/extensions/utils.py +41 -7
- pymodaq/post_treatment/load_and_plot.py +43 -10
- pymodaq/resources/setup_plugin.py +1 -0
- pymodaq/updater.py +107 -0
- pymodaq/utils/chrono_timer.py +6 -7
- pymodaq/utils/daq_utils.py +6 -3
- pymodaq/utils/data.py +21 -17
- pymodaq/utils/enums.py +6 -0
- pymodaq/utils/gui_utils/loader_utils.py +29 -2
- pymodaq/utils/gui_utils/utils.py +9 -12
- pymodaq/utils/gui_utils/widgets/lcd.py +8 -0
- pymodaq/utils/h5modules/module_saving.py +5 -2
- pymodaq/utils/leco/daq_move_LECODirector.py +22 -16
- pymodaq/utils/leco/daq_xDviewer_LECODirector.py +15 -9
- pymodaq/utils/leco/leco_director.py +4 -3
- pymodaq/utils/leco/pymodaq_listener.py +9 -13
- pymodaq/utils/leco/utils.py +40 -7
- pymodaq/utils/managers/modules_manager.py +22 -12
- pymodaq/utils/managers/overshoot_manager.py +45 -1
- pymodaq/utils/managers/preset_manager.py +22 -46
- pymodaq/utils/managers/preset_manager_utils.py +17 -13
- pymodaq/utils/managers/remote_manager.py +1 -1
- pymodaq/utils/messenger.py +6 -0
- pymodaq/utils/parameter/__init__.py +5 -1
- pymodaq/utils/tcp_ip/mysocket.py +4 -110
- pymodaq/utils/tcp_ip/serializer.py +4 -769
- pymodaq/utils/tcp_ip/tcp_server_client.py +5 -5
- pymodaq-5.0.2.dist-info/METADATA +242 -0
- {pymodaq-5.0.0.dist-info → pymodaq-5.0.2.dist-info}/RECORD +54 -55
- {pymodaq-5.0.0.dist-info → pymodaq-5.0.2.dist-info}/WHEEL +1 -1
- {pymodaq-5.0.0.dist-info → pymodaq-5.0.2.dist-info}/entry_points.txt +1 -0
- pymodaq/examples/custom_app.py +0 -255
- pymodaq/examples/custom_viewer.py +0 -112
- pymodaq/examples/parameter_ex.py +0 -158
- pymodaq/examples/preset_MockCamera.xml +0 -1
- pymodaq/post_treatment/daq_measurement/daq_measurement_GUI.py +0 -142
- pymodaq/post_treatment/daq_measurement/daq_measurement_GUI.ui +0 -232
- pymodaq/post_treatment/daq_measurement/daq_measurement_main.py +0 -391
- pymodaq/post_treatment/daq_measurement/process_from_QtDesigner_DAQ_Measurement_GUI.bat +0 -2
- pymodaq-5.0.0.dist-info/METADATA +0 -166
- /pymodaq/{post_treatment/daq_measurement → daq_utils}/__init__.py +0 -0
- {pymodaq-5.0.0.dist-info → pymodaq-5.0.2.dist-info}/licenses/LICENSE +0 -0
pymodaq/__init__.py
CHANGED
|
@@ -6,23 +6,11 @@ from pathlib import Path
|
|
|
6
6
|
|
|
7
7
|
import warnings
|
|
8
8
|
|
|
9
|
+
import pymodaq_utils # to init stuff related to pymodaq_utils # necessary, leave it there
|
|
10
|
+
import pymodaq_data # to init stuff related to pymodaq_data # necessary, leave it there
|
|
11
|
+
import pymodaq_gui # to init stuff related to pymodaq_gui # necessary, leave it there
|
|
9
12
|
|
|
10
|
-
|
|
11
|
-
try:
|
|
12
|
-
from qtpy import QtWidgets
|
|
13
|
-
except ImportError as e:
|
|
14
|
-
msg = f"\n\n" \
|
|
15
|
-
f"****************************************************************************************\n" \
|
|
16
|
-
f"No Qt backend could be found in your system, please install either pyqt5/6 or pyside2/6.\n\n" \
|
|
17
|
-
f"pyqt5 is still preferred, while pyqt6 should mostly work.\n\n" \
|
|
18
|
-
f"do:\n" \
|
|
19
|
-
f"pip install pyqt5\n for instance\n"\
|
|
20
|
-
f"****************************************************************************************\n"
|
|
21
|
-
warnings.warn(msg, FutureWarning, 2)
|
|
22
|
-
sys.exit()
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
check_qt_presence()
|
|
13
|
+
from pymodaq_data import Q_, Unit, ureg # necessary, leave it there
|
|
26
14
|
|
|
27
15
|
|
|
28
16
|
try:
|
|
@@ -31,87 +19,65 @@ try:
|
|
|
31
19
|
|
|
32
20
|
from pymodaq_utils.logger import set_logger
|
|
33
21
|
from pymodaq_utils.utils import get_version
|
|
34
|
-
__version__ = get_version()
|
|
22
|
+
__version__ = get_version('pymodaq')
|
|
35
23
|
try:
|
|
36
24
|
logger = set_logger('pymodaq', add_handler=True, base_logger=True)
|
|
37
|
-
except Exception:
|
|
38
|
-
print("Couldn't create the local folder to store logs , presets...")
|
|
39
25
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
from pymodaq_data.plotting.plotter.plotter import register_plotter, PlotterFactory
|
|
65
|
-
|
|
66
|
-
# issue on windows when using .NET code within multithreads, this below allows it but requires
|
|
67
|
-
# the pywin32 (pythoncom) package
|
|
68
|
-
if importlib.util.find_spec('clr') is not None:
|
|
26
|
+
from pymodaq.utils.daq_utils import copy_preset, get_instrument_plugins
|
|
27
|
+
|
|
28
|
+
from pymodaq_utils.config import Config
|
|
29
|
+
from pymodaq.utils.scanner.utils import register_scanners
|
|
30
|
+
from pymodaq_data.plotting.plotter.plotter import register_plotter, PlotterFactory
|
|
31
|
+
|
|
32
|
+
# issue on windows when using .NET code within multithreads, this below allows it but requires
|
|
33
|
+
# the pywin32 (pythoncom) package
|
|
34
|
+
if importlib.util.find_spec('clr') is not None:
|
|
35
|
+
try:
|
|
36
|
+
import pythoncom
|
|
37
|
+
pythoncom.CoInitialize()
|
|
38
|
+
except ModuleNotFoundError as e:
|
|
39
|
+
infos = "You have installed plugins requiring the pywin32 package to work correctly," \
|
|
40
|
+
" please type in *pip install pywin32* and restart PyMoDAQ"
|
|
41
|
+
print(infos)
|
|
42
|
+
logger.warning(infos)
|
|
43
|
+
|
|
44
|
+
config = Config() # to ckeck for config file existence, otherwise create one
|
|
45
|
+
copy_preset()
|
|
46
|
+
|
|
47
|
+
from pymodaq_utils.config import Config
|
|
48
|
+
from pymodaq.utils.scanner.utils import register_scanners
|
|
49
|
+
|
|
69
50
|
try:
|
|
70
|
-
|
|
71
|
-
|
|
51
|
+
# Need the config to exists before importing
|
|
52
|
+
from pymodaq_utils.environment import EnvironmentBackupManager
|
|
53
|
+
|
|
54
|
+
if config['backup']['keep_backup']:
|
|
55
|
+
ebm = EnvironmentBackupManager()
|
|
56
|
+
ebm.save_backup()
|
|
72
57
|
except ModuleNotFoundError as e:
|
|
73
|
-
infos = "
|
|
74
|
-
"
|
|
58
|
+
infos = "Your pymodaq_utils version is outdated and doesn't allow for automatic backup of pip packages." \
|
|
59
|
+
" You should update it."
|
|
75
60
|
print(infos)
|
|
76
61
|
logger.warning(infos)
|
|
77
62
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
logger.info('')
|
|
97
|
-
get_instrument_plugins()
|
|
98
|
-
logger.info('*************************************************************************')
|
|
99
|
-
|
|
100
|
-
logger.info('')
|
|
101
|
-
logger.info('')
|
|
102
|
-
logger.info('************************')
|
|
103
|
-
logger.info(f"Registering Scanners...")
|
|
104
|
-
register_scanners()
|
|
105
|
-
logger.info(f"Done")
|
|
106
|
-
logger.info('************************')
|
|
107
|
-
|
|
108
|
-
logger.info('')
|
|
109
|
-
logger.info('')
|
|
110
|
-
logger.info('************************')
|
|
111
|
-
logger.info(f"Registering plotters...")
|
|
112
|
-
register_plotter()
|
|
113
|
-
logger.info(f"Done")
|
|
114
|
-
logger.info('************************')
|
|
63
|
+
logger.info('*************************************************************************')
|
|
64
|
+
logger.info(f"Getting the list of instrument plugins...")
|
|
65
|
+
logger.info('')
|
|
66
|
+
get_instrument_plugins()
|
|
67
|
+
logger.info('*************************************************************************')
|
|
68
|
+
|
|
69
|
+
logger.info('')
|
|
70
|
+
logger.info('')
|
|
71
|
+
logger.info('************************')
|
|
72
|
+
logger.info(f"Registering Scanners...")
|
|
73
|
+
register_scanners()
|
|
74
|
+
logger.info(f"Done")
|
|
75
|
+
logger.info('************************')
|
|
76
|
+
|
|
77
|
+
except Exception:
|
|
78
|
+
print("Couldn't create the local folder to store logs , presets...")
|
|
79
|
+
|
|
80
|
+
|
|
115
81
|
|
|
116
82
|
except Exception as e:
|
|
117
83
|
try:
|
|
@@ -10,7 +10,7 @@ from __future__ import annotations
|
|
|
10
10
|
import numbers
|
|
11
11
|
from importlib import import_module
|
|
12
12
|
from numbers import Number
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
import sys
|
|
15
15
|
from typing import List, Tuple, Union, Optional, Type
|
|
16
16
|
import numpy as np
|
|
@@ -32,14 +32,22 @@ from pymodaq_data.h5modules.backends import Node
|
|
|
32
32
|
|
|
33
33
|
from pymodaq_gui.parameter import ioxml, Parameter
|
|
34
34
|
from pymodaq_gui.parameter import utils as putils
|
|
35
|
+
from pymodaq_gui.utils.utils import mkQApp
|
|
35
36
|
|
|
36
37
|
from pymodaq.utils.h5modules import module_saving
|
|
37
38
|
from pymodaq.control_modules.utils import ParameterControlModule
|
|
38
|
-
from pymodaq.control_modules.daq_move_ui import DAQ_Move_UI
|
|
39
|
-
from pymodaq.control_modules.move_utility_classes import MoveCommand, DAQ_Move_base
|
|
39
|
+
from pymodaq.control_modules.daq_move_ui import DAQ_Move_UI, ThreadCommand
|
|
40
|
+
from pymodaq.control_modules.move_utility_classes import (MoveCommand, DAQ_Move_base,
|
|
41
|
+
DataActuatorType, check_units,
|
|
42
|
+
DataUnitError)
|
|
43
|
+
|
|
44
|
+
|
|
40
45
|
from pymodaq.control_modules.move_utility_classes import params as daq_move_params
|
|
41
46
|
from pymodaq.utils.leco.pymodaq_listener import MoveActorListener, LECOMoveCommands
|
|
47
|
+
|
|
42
48
|
from pymodaq.utils.daq_utils import get_plugins
|
|
49
|
+
from pymodaq import Q_, Unit
|
|
50
|
+
|
|
43
51
|
|
|
44
52
|
|
|
45
53
|
local_path = config_mod.get_set_local_dir()
|
|
@@ -116,15 +124,15 @@ class DAQ_Move(ParameterControlModule):
|
|
|
116
124
|
self.splash_sc = get_splash_sc()
|
|
117
125
|
self._title = title
|
|
118
126
|
if len(ACTUATOR_TYPES) > 0: # will be 0 if no valid plugins are installed
|
|
119
|
-
self.actuator = ACTUATOR_TYPES[0]
|
|
127
|
+
self.actuator = kwargs.get('actuator', ACTUATOR_TYPES[0])
|
|
120
128
|
|
|
121
129
|
self.module_and_data_saver = module_saving.ActuatorSaver(self)
|
|
122
130
|
|
|
123
131
|
self._move_done_bool = True
|
|
124
132
|
|
|
125
|
-
self._current_value = DataActuator(title)
|
|
126
|
-
self._target_value
|
|
127
|
-
self._relative_value
|
|
133
|
+
self._current_value = DataActuator(title, units=self.units)
|
|
134
|
+
self._target_value = DataActuator(title, units=self.units)
|
|
135
|
+
self._relative_value = DataActuator(title, units=self.units)
|
|
128
136
|
|
|
129
137
|
self._refresh_timer = QTimer()
|
|
130
138
|
self._refresh_timer.timeout.connect(self.get_actuator_value)
|
|
@@ -162,9 +170,15 @@ class DAQ_Move(ParameterControlModule):
|
|
|
162
170
|
elif cmd.command == 'stop':
|
|
163
171
|
self.stop_motion()
|
|
164
172
|
elif cmd.command == 'move_abs':
|
|
165
|
-
|
|
173
|
+
data_act: DataActuator = cmd.attribute
|
|
174
|
+
if not Unit(data_act.units).is_compatible_with(self.units) and data_act.units != '':
|
|
175
|
+
data_act.force_units(self.units)
|
|
176
|
+
self.move_abs(data_act)
|
|
166
177
|
elif cmd.command == 'move_rel':
|
|
167
|
-
|
|
178
|
+
data_act: DataActuator = cmd.attribute
|
|
179
|
+
if not Unit(data_act.units).is_compatible_with(self.units) and data_act.units != '':
|
|
180
|
+
data_act.force_units(self.units)
|
|
181
|
+
self.move_rel(data_act)
|
|
168
182
|
elif cmd.command == 'show_log':
|
|
169
183
|
self.show_log()
|
|
170
184
|
elif cmd.command == 'show_config':
|
|
@@ -175,6 +189,20 @@ class DAQ_Move(ParameterControlModule):
|
|
|
175
189
|
elif cmd.command == 'rel_value':
|
|
176
190
|
self._relative_value = cmd.attribute
|
|
177
191
|
|
|
192
|
+
@property
|
|
193
|
+
def master(self) -> bool:
|
|
194
|
+
""" Get/Set programmatically the Master/Slave status of an actuator"""
|
|
195
|
+
if self.initialized_state:
|
|
196
|
+
return self.settings['move_settings', 'multiaxes', 'multi_status'] == 'Master'
|
|
197
|
+
else:
|
|
198
|
+
return True
|
|
199
|
+
|
|
200
|
+
@master.setter
|
|
201
|
+
def master(self, is_master: bool):
|
|
202
|
+
if self.initialized_state:
|
|
203
|
+
self.settings.child('move_settings', 'multiaxes', 'multi_status').setValue(
|
|
204
|
+
'Master' if is_master else 'Slave')
|
|
205
|
+
|
|
178
206
|
def append_data(self, dte: Optional[DataToExport] = None, where: Union[Node, str, None] = None):
|
|
179
207
|
"""Appends current DataToExport to an ActuatorEnlargeableSaver
|
|
180
208
|
|
|
@@ -258,7 +286,7 @@ class DAQ_Move(ParameterControlModule):
|
|
|
258
286
|
"""
|
|
259
287
|
try:
|
|
260
288
|
if isinstance(value, Number):
|
|
261
|
-
value = DataActuator(self.title, data=[np.array([value])])
|
|
289
|
+
value = DataActuator(self.title, data=[np.array([value])], units=self.units)
|
|
262
290
|
self._send_to_tcpip = send_to_tcpip
|
|
263
291
|
if value != self._current_value:
|
|
264
292
|
if self.ui is not None:
|
|
@@ -307,7 +335,7 @@ class DAQ_Move(ParameterControlModule):
|
|
|
307
335
|
|
|
308
336
|
try:
|
|
309
337
|
if isinstance(rel_value, Number):
|
|
310
|
-
rel_value = DataActuator(self.title, data=[np.array([rel_value])])
|
|
338
|
+
rel_value = DataActuator(self.title, data=[np.array([rel_value])], units=self.units)
|
|
311
339
|
self._send_to_tcpip = send_to_tcpip
|
|
312
340
|
if self.ui is not None:
|
|
313
341
|
self.ui.move_done = False
|
|
@@ -362,8 +390,9 @@ class DAQ_Move(ParameterControlModule):
|
|
|
362
390
|
self._hardware_thread.hardware = hardware
|
|
363
391
|
self._hardware_thread.start()
|
|
364
392
|
self.command_hardware.emit(
|
|
365
|
-
ThreadCommand(command="ini_stage", attribute=[
|
|
366
|
-
|
|
393
|
+
ThreadCommand(command="ini_stage", attribute=[
|
|
394
|
+
self.settings.child('move_settings').saveState(),
|
|
395
|
+
self.controller]))
|
|
367
396
|
except Exception as e:
|
|
368
397
|
self.logger.exception(str(e))
|
|
369
398
|
|
|
@@ -429,11 +458,10 @@ class DAQ_Move(ParameterControlModule):
|
|
|
429
458
|
super().thread_status(status, 'move')
|
|
430
459
|
|
|
431
460
|
if status.command == "ini_stage":
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
self.controller = status.attribute[0]['controller']
|
|
461
|
+
self.update_status(f"Stage initialized: {status.attribute['initialized']} "
|
|
462
|
+
f"info: {status.attribute['info']}")
|
|
463
|
+
if status.attribute['initialized']:
|
|
464
|
+
self.controller = status.attribute['controller']
|
|
437
465
|
if self.ui is not None:
|
|
438
466
|
self.ui.actuator_init = True
|
|
439
467
|
self._initialized_state = True
|
|
@@ -444,8 +472,7 @@ class DAQ_Move(ParameterControlModule):
|
|
|
444
472
|
self.init_signal.emit(self._initialized_state)
|
|
445
473
|
|
|
446
474
|
elif status.command == "get_actuator_value" or status.command == 'check_position':
|
|
447
|
-
data_act
|
|
448
|
-
data_act.name = self.title # for the DataActuator name to be the title of the DAQ_Move
|
|
475
|
+
data_act = self._check_data_type(status.attribute)
|
|
449
476
|
if self.ui is not None:
|
|
450
477
|
self.ui.display_value(data_act)
|
|
451
478
|
if self.ui.is_action_checked('show_graph'):
|
|
@@ -454,13 +481,12 @@ class DAQ_Move(ParameterControlModule):
|
|
|
454
481
|
self._current_value = data_act
|
|
455
482
|
self.current_value_signal.emit(self._current_value)
|
|
456
483
|
if self.settings['main_settings', 'tcpip', 'tcp_connected'] and self._send_to_tcpip:
|
|
457
|
-
self._command_tcpip.emit(ThreadCommand('position_is',
|
|
484
|
+
self._command_tcpip.emit(ThreadCommand('position_is', data_act))
|
|
458
485
|
if self.settings['main_settings', 'leco', 'leco_connected'] and self._send_to_tcpip:
|
|
459
|
-
self._command_tcpip.emit(ThreadCommand(LECOMoveCommands.POSITION,
|
|
486
|
+
self._command_tcpip.emit(ThreadCommand(LECOMoveCommands.POSITION, data_act))
|
|
460
487
|
|
|
461
488
|
elif status.command == "move_done":
|
|
462
|
-
data_act
|
|
463
|
-
data_act.name = self.title # for the DataActuator name to be the title of the DAQ_Move
|
|
489
|
+
data_act = self._check_data_type(status.attribute)
|
|
464
490
|
if self.ui is not None:
|
|
465
491
|
self.ui.display_value(data_act)
|
|
466
492
|
self.ui.move_done = True
|
|
@@ -468,9 +494,9 @@ class DAQ_Move(ParameterControlModule):
|
|
|
468
494
|
self._move_done_bool = True
|
|
469
495
|
self.move_done_signal.emit(data_act)
|
|
470
496
|
if self.settings.child('main_settings', 'tcpip', 'tcp_connected').value() and self._send_to_tcpip:
|
|
471
|
-
self._command_tcpip.emit(ThreadCommand('move_done',
|
|
497
|
+
self._command_tcpip.emit(ThreadCommand('move_done', data_act))
|
|
472
498
|
if self.settings.child('main_settings', 'leco', 'leco_connected').value() and self._send_to_tcpip:
|
|
473
|
-
self._command_tcpip.emit(ThreadCommand(LECOMoveCommands.MOVE_DONE,
|
|
499
|
+
self._command_tcpip.emit(ThreadCommand(LECOMoveCommands.MOVE_DONE, data_act))
|
|
474
500
|
|
|
475
501
|
elif status.command == 'outofbounds':
|
|
476
502
|
self.bounds_signal.emit(True)
|
|
@@ -485,6 +511,22 @@ class DAQ_Move(ParameterControlModule):
|
|
|
485
511
|
elif status.command == 'units':
|
|
486
512
|
self.units = status.attribute
|
|
487
513
|
|
|
514
|
+
def _check_data_type(self, data_act: Union[list[np.ndarray], float, DataActuator]) -> DataActuator:
|
|
515
|
+
""" Make sure the data is a DataActuator
|
|
516
|
+
|
|
517
|
+
Mostly to make sure DAQ_Move is backcompatible with old style plugins
|
|
518
|
+
"""
|
|
519
|
+
if isinstance(data_act, list): # backcompatibility
|
|
520
|
+
data_act = data_act[0]
|
|
521
|
+
if isinstance(data_act, np.ndarray): # backcompatibility
|
|
522
|
+
data_act = DataActuator(data=[data_act], units=self.units)
|
|
523
|
+
data_act.name = self.title # for the DataActuator name to be the title of the DAQ_Move
|
|
524
|
+
if (not Unit(self.units).is_compatible_with(Unit(data_act.units)) and
|
|
525
|
+
data_act.units == ''): #this happens if the units have not been specified in
|
|
526
|
+
# the plugin
|
|
527
|
+
data_act.force_units(self.units)
|
|
528
|
+
return data_act
|
|
529
|
+
|
|
488
530
|
def get_actuator_value(self):
|
|
489
531
|
"""Get the current actuator value via the "get_actuator_value" command send to the hardware
|
|
490
532
|
|
|
@@ -545,10 +587,15 @@ class DAQ_Move(ParameterControlModule):
|
|
|
545
587
|
self.update_plugin_config()
|
|
546
588
|
if self.ui is not None:
|
|
547
589
|
self.ui.actuator = act_type
|
|
548
|
-
|
|
590
|
+
self.update_settings()
|
|
549
591
|
else:
|
|
550
592
|
raise ActuatorError(f'{act_type} is an invalid actuator, should be within {ACTUATOR_TYPES}')
|
|
551
593
|
|
|
594
|
+
@property
|
|
595
|
+
def actuators(self) -> List[str]:
|
|
596
|
+
""" Get the list of possible actuators"""
|
|
597
|
+
return ACTUATOR_TYPES
|
|
598
|
+
|
|
552
599
|
def update_plugin_config(self):
|
|
553
600
|
parent_module = utils.find_dict_in_list_from_key_val(DAQ_Move_Actuators, 'name', self.actuator)
|
|
554
601
|
mod = import_module(parent_module['module'].__package__.split('.')[0])
|
|
@@ -564,7 +611,35 @@ class DAQ_Move(ParameterControlModule):
|
|
|
564
611
|
def units(self, unit: str):
|
|
565
612
|
self.settings.child('move_settings', 'units').setValue(unit)
|
|
566
613
|
if self.ui is not None and config('actuator', 'display_units'):
|
|
567
|
-
self.ui.set_unit_as_suffix(unit)
|
|
614
|
+
self.ui.set_unit_as_suffix(self.get_unit_to_display(unit))
|
|
615
|
+
|
|
616
|
+
@staticmethod
|
|
617
|
+
def get_unit_to_display(unit: str) -> str:
|
|
618
|
+
""" Get the unit to be displayed in the UI
|
|
619
|
+
|
|
620
|
+
If the controller units are in mm the displayed unit will be m
|
|
621
|
+
because m is the base unit, then the user could ask for mm, km, µm...
|
|
622
|
+
only issue is when the usual displayed unit is not the base one, then add cases below
|
|
623
|
+
|
|
624
|
+
Parameters
|
|
625
|
+
----------
|
|
626
|
+
unit: str
|
|
627
|
+
|
|
628
|
+
Returns
|
|
629
|
+
-------
|
|
630
|
+
str: the unit to be displayed on the ui
|
|
631
|
+
"""
|
|
632
|
+
if ('°' in unit or 'degree' in unit) and not '°C' in unit:
|
|
633
|
+
# special cas as pint base unit for angles are radians
|
|
634
|
+
return '°'
|
|
635
|
+
elif 'W' in unit or 'watt' in unit.lower():
|
|
636
|
+
return 'W'
|
|
637
|
+
elif '°C' in unit or 'Celsius' in unit:
|
|
638
|
+
return '°C'
|
|
639
|
+
elif 'V' in unit or 'volt' in unit.lower():
|
|
640
|
+
return 'V'
|
|
641
|
+
else:
|
|
642
|
+
return str(Q_(1, unit).to_base_units().units)
|
|
568
643
|
|
|
569
644
|
def update_settings(self):
|
|
570
645
|
|
|
@@ -641,8 +716,6 @@ class DAQ_Move_Hardware(QObject):
|
|
|
641
716
|
self._title = title
|
|
642
717
|
self.hardware: Optional[DAQ_Move_base] = None
|
|
643
718
|
self.actuator_type = actuator_type
|
|
644
|
-
self.current_position: DataActuator = position
|
|
645
|
-
self._target_value: Optional[DataActuator] = None
|
|
646
719
|
self.hardware_adress = None
|
|
647
720
|
self.axis_address = None
|
|
648
721
|
self.motion_stoped = False
|
|
@@ -656,17 +729,18 @@ class DAQ_Move_Hardware(QObject):
|
|
|
656
729
|
Uninitialize the stage closing the hardware.
|
|
657
730
|
|
|
658
731
|
"""
|
|
659
|
-
self.hardware.
|
|
732
|
+
if self.hardware is not None and self.hardware.controller is not None:
|
|
733
|
+
self.hardware.close()
|
|
660
734
|
|
|
661
735
|
return "Stage uninitialized"
|
|
662
736
|
|
|
663
737
|
def get_actuator_value(self):
|
|
664
738
|
"""Get the current position checking the hardware value.
|
|
665
739
|
"""
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
740
|
+
if self.hardware is not None:
|
|
741
|
+
pos = self.hardware.get_actuator_value()
|
|
742
|
+
if self.hardware.data_actuator_type == DataActuatorType.float:
|
|
743
|
+
pos = DataActuator(self._title, data=pos, units=self.hardware.axis_unit)
|
|
670
744
|
return pos
|
|
671
745
|
|
|
672
746
|
def check_position(self):
|
|
@@ -716,6 +790,8 @@ class DAQ_Move_Hardware(QObject):
|
|
|
716
790
|
status.initialized = infos[1]
|
|
717
791
|
status.controller = self.hardware.controller
|
|
718
792
|
self.hardware.move_done_signal.connect(self.move_done)
|
|
793
|
+
if status.initialized:
|
|
794
|
+
self.status_sig.emit(ThreadCommand('get_actuator_value', [self.get_actuator_value()]))
|
|
719
795
|
|
|
720
796
|
return status
|
|
721
797
|
except Exception as e:
|
|
@@ -726,15 +802,13 @@ class DAQ_Move_Hardware(QObject):
|
|
|
726
802
|
"""
|
|
727
803
|
|
|
728
804
|
"""
|
|
729
|
-
|
|
730
|
-
# position = float(position) # because it may be a numpy float and could cause issues
|
|
731
|
-
# # see https://github.com/pythonnet/pythonnet/issues/1833
|
|
732
|
-
self._target_value = position
|
|
805
|
+
position = check_units(position, self.hardware.axis_unit)
|
|
733
806
|
self.hardware.move_is_done = False
|
|
734
807
|
self.hardware.ispolling = polling
|
|
735
808
|
if self.hardware.data_actuator_type.name == 'float':
|
|
736
809
|
self.hardware.move_abs(position.value())
|
|
737
810
|
else:
|
|
811
|
+
position.units = self.hardware.axis_unit # convert to plugin controller current axis units
|
|
738
812
|
self.hardware.move_abs(position)
|
|
739
813
|
self.hardware.poll_moving()
|
|
740
814
|
|
|
@@ -742,14 +816,14 @@ class DAQ_Move_Hardware(QObject):
|
|
|
742
816
|
"""
|
|
743
817
|
|
|
744
818
|
"""
|
|
745
|
-
|
|
819
|
+
rel_position = check_units(rel_position, self.hardware.axis_unit)
|
|
746
820
|
self.hardware.move_is_done = False
|
|
747
|
-
self._target_value = self.current_position + rel_position
|
|
748
821
|
self.hardware.ispolling = polling
|
|
749
822
|
|
|
750
823
|
if self.hardware.data_actuator_type.name == 'float':
|
|
751
824
|
self.hardware.move_rel(rel_position.value())
|
|
752
825
|
else:
|
|
826
|
+
rel_position.units = self.hardware.axis_unit # convert to plugin current axis units
|
|
753
827
|
self.hardware.move_rel(rel_position)
|
|
754
828
|
|
|
755
829
|
self.hardware.poll_moving()
|
|
@@ -763,7 +837,7 @@ class DAQ_Move_Hardware(QObject):
|
|
|
763
837
|
--------
|
|
764
838
|
DAQ_utils.ThreadCommand
|
|
765
839
|
"""
|
|
766
|
-
self.status_sig.emit(ThreadCommand("move_done",
|
|
840
|
+
self.status_sig.emit(ThreadCommand("move_done", pos))
|
|
767
841
|
|
|
768
842
|
def move_home(self):
|
|
769
843
|
"""
|
|
@@ -771,7 +845,6 @@ class DAQ_Move_Hardware(QObject):
|
|
|
771
845
|
|
|
772
846
|
"""
|
|
773
847
|
self.hardware.move_is_done = False
|
|
774
|
-
self._target_value = 0
|
|
775
848
|
self.hardware.move_home()
|
|
776
849
|
|
|
777
850
|
@Slot(DataActuator)
|
|
@@ -779,7 +852,7 @@ class DAQ_Move_Hardware(QObject):
|
|
|
779
852
|
"""Send the move_done signal back to the main class
|
|
780
853
|
"""
|
|
781
854
|
self._current_value = pos
|
|
782
|
-
self.status_sig.emit(ThreadCommand(command="move_done", attribute=
|
|
855
|
+
self.status_sig.emit(ThreadCommand(command="move_done", attribute=pos))
|
|
783
856
|
|
|
784
857
|
@Slot(ThreadCommand)
|
|
785
858
|
def queue_command(self, command: ThreadCommand):
|
|
@@ -807,10 +880,10 @@ class DAQ_Move_Hardware(QObject):
|
|
|
807
880
|
* **reset_stop_motion** command, set the motion_stopped attribute to false
|
|
808
881
|
"""
|
|
809
882
|
try:
|
|
883
|
+
logger.debug(f'Threadcommand {command.command} sent to {self.title}')
|
|
810
884
|
if command.command == "ini_stage":
|
|
811
|
-
status = self.ini_stage(
|
|
812
|
-
|
|
813
|
-
self.status_sig.emit(ThreadCommand(command=command.command, attribute=[status, 'log']))
|
|
885
|
+
status: edict = self.ini_stage(*command.attribute)
|
|
886
|
+
self.status_sig.emit(ThreadCommand(command=command.command, attribute=status))
|
|
814
887
|
|
|
815
888
|
elif command.command == "close":
|
|
816
889
|
status = self.close()
|
|
@@ -838,11 +911,13 @@ class DAQ_Move_Hardware(QObject):
|
|
|
838
911
|
else: # custom commands for particular plugins (see spectrometer module 'get_spectro_wl' for instance)
|
|
839
912
|
if hasattr(self.hardware, command.command):
|
|
840
913
|
cmd = getattr(self.hardware, command.command)
|
|
841
|
-
|
|
914
|
+
if isinstance(command.attribute, list):
|
|
915
|
+
cmd(*command.attribute)
|
|
916
|
+
elif isinstance(command.attribute, dict):
|
|
917
|
+
cmd(**command.attribute)
|
|
842
918
|
except Exception as e:
|
|
843
919
|
self.logger.exception(str(e))
|
|
844
920
|
|
|
845
|
-
|
|
846
921
|
def stop_motion(self):
|
|
847
922
|
"""
|
|
848
923
|
stop hardware motion with motion_stopped attribute updtaed to True and a status signal sended with an "update_status" Thread Command
|
|
@@ -853,7 +928,8 @@ class DAQ_Move_Hardware(QObject):
|
|
|
853
928
|
"""
|
|
854
929
|
self.status_sig.emit(ThreadCommand(command="Update_Status", attribute=["Motion stoping", 'log']))
|
|
855
930
|
self.motion_stoped = True
|
|
856
|
-
self.hardware.
|
|
931
|
+
if self.hardware is not None and self.hardware.controller is not None:
|
|
932
|
+
self.hardware.stop_motion()
|
|
857
933
|
self.hardware.poll_timer.stop()
|
|
858
934
|
|
|
859
935
|
@Slot(edict)
|
|
@@ -879,15 +955,13 @@ class DAQ_Move_Hardware(QObject):
|
|
|
879
955
|
setattr(self, path[-1], param.value())
|
|
880
956
|
|
|
881
957
|
elif path[0] == 'move_settings':
|
|
882
|
-
self.hardware
|
|
958
|
+
if self.hardware is not None:
|
|
959
|
+
self.hardware.update_settings(settings_parameter_dict)
|
|
883
960
|
|
|
884
961
|
|
|
885
962
|
def main(init_qt=True):
|
|
886
963
|
if init_qt: # used for the test suite
|
|
887
|
-
app =
|
|
888
|
-
if config('style', 'darkstyle'):
|
|
889
|
-
import qdarkstyle
|
|
890
|
-
app.setStyleSheet(qdarkstyle.load_stylesheet(qdarkstyle.DarkPalette))
|
|
964
|
+
app = mkQApp("PyMoDAQ Move")
|
|
891
965
|
|
|
892
966
|
widget = QtWidgets.QWidget()
|
|
893
967
|
prog = DAQ_Move(widget, title="test")
|