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/utils/data.py
CHANGED
|
@@ -1,15 +1,24 @@
|
|
|
1
1
|
import numpy as np
|
|
2
2
|
import numbers
|
|
3
3
|
import warnings
|
|
4
|
+
import copy
|
|
4
5
|
|
|
5
6
|
from typing import List
|
|
6
7
|
|
|
7
8
|
from pymodaq_utils.warnings import deprecation_msg, user_warning
|
|
8
9
|
|
|
9
10
|
from pymodaq_data.data import (DataRaw, DataWithAxes, DataToExport, DataCalculated, DataDim,
|
|
10
|
-
DataSource, DataBase, Axis, NavAxis
|
|
11
|
+
DataSource, DataBase, Axis, NavAxis, DataDistribution, Q_, Unit,
|
|
12
|
+
) # imported here for backcompatibility. Will allow also the object serialization
|
|
13
|
+
# registration
|
|
11
14
|
|
|
12
15
|
|
|
16
|
+
from pymodaq_utils.serialize.factory import SerializableFactory, SerializableBase
|
|
17
|
+
|
|
18
|
+
ser_factory = SerializableFactory()
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@ser_factory.register_decorator()
|
|
13
22
|
class DataActuator(DataRaw):
|
|
14
23
|
"""Specialized DataWithAxes set with source as 'raw'.
|
|
15
24
|
To be used for raw data generated by actuator plugins"""
|
|
@@ -24,27 +33,21 @@ class DataActuator(DataRaw):
|
|
|
24
33
|
|
|
25
34
|
def __repr__(self):
|
|
26
35
|
if self.dim.name == 'Data0D':
|
|
27
|
-
return f'<{self.__class__.__name__} ({self.data[0][0]})>'
|
|
36
|
+
return f'<{self.__class__.__name__} ({self.data[0][0]} {self.units})>'
|
|
28
37
|
else:
|
|
29
|
-
return f'<{self.__class__.__name__} ({self.shape})>'
|
|
38
|
+
return f'<{self.__class__.__name__} ({self.shape} {self.units})>'
|
|
30
39
|
|
|
31
|
-
def
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
return
|
|
36
|
-
else:
|
|
37
|
-
return float(np.mean(self.data))
|
|
40
|
+
def __add__(self, other: object):
|
|
41
|
+
if isinstance(other, numbers.Number) and self.length == 1 and self.size == 1:
|
|
42
|
+
new_data = copy.deepcopy(self)
|
|
43
|
+
new_data = new_data + DataActuator(data=other)
|
|
44
|
+
return new_data
|
|
38
45
|
|
|
39
|
-
def values(self) -> List[float]:
|
|
40
|
-
"""Returns the underlying float value (for each data array in the data list) if this data
|
|
41
|
-
holds only a float otherwise returns a mean of the underlying data"""
|
|
42
|
-
if self.length == 1 and self.size == 1:
|
|
43
|
-
return [float(data_array[0]) for data_array in self.data]
|
|
44
46
|
else:
|
|
45
|
-
return
|
|
47
|
+
return super().__add__(other)
|
|
46
48
|
|
|
47
49
|
|
|
50
|
+
@ser_factory.register_decorator()
|
|
48
51
|
class DataFromPlugins(DataRaw):
|
|
49
52
|
"""Specialized DataWithAxes set with source as 'raw'. To be used for raw data generated by Detector plugins
|
|
50
53
|
|
|
@@ -88,12 +91,14 @@ class DataFromPlugins(DataRaw):
|
|
|
88
91
|
super().__init__(*args, **kwargs)
|
|
89
92
|
|
|
90
93
|
|
|
94
|
+
@ser_factory.register_decorator()
|
|
91
95
|
class DataScan(DataToExport):
|
|
92
96
|
"""Specialized DataToExport.To be used for data to be saved """
|
|
93
97
|
def __init__(self, name: str, data: List[DataWithAxes] = [], **kwargs):
|
|
94
98
|
super().__init__(name, data, **kwargs)
|
|
95
99
|
|
|
96
100
|
|
|
101
|
+
@ser_factory.register_decorator()
|
|
97
102
|
class DataToActuators(DataToExport):
|
|
98
103
|
""" Particular case of a DataToExport adding one named parameter to indicate what kind of change
|
|
99
104
|
should be applied to the actuators, absolute or relative
|
|
@@ -120,4 +125,3 @@ class DataToActuators(DataToExport):
|
|
|
120
125
|
|
|
121
126
|
def __repr__(self):
|
|
122
127
|
return f'{super().__repr__()}: {self.mode}'
|
|
123
|
-
|
pymodaq/utils/enums.py
ADDED
|
@@ -5,19 +5,42 @@ from qtpy import QtWidgets
|
|
|
5
5
|
from pymodaq.dashboard import DashBoard
|
|
6
6
|
from pymodaq.utils.gui_utils import DockArea
|
|
7
7
|
from pymodaq.utils.config import get_set_preset_path
|
|
8
|
+
from pymodaq.extensions.utils import CustomExt
|
|
8
9
|
|
|
9
10
|
|
|
10
|
-
def load_dashboard_with_preset(preset_name: str, extension_name: str)
|
|
11
|
+
def load_dashboard_with_preset(preset_name: str, extension_name: str) -> \
|
|
12
|
+
(DashBoard, CustomExt, QtWidgets.QMainWindow):
|
|
13
|
+
""" Load the Dashboard using a given preset then load an extension
|
|
14
|
+
|
|
15
|
+
Parameters
|
|
16
|
+
----------
|
|
17
|
+
preset_name: str
|
|
18
|
+
The filename (without extension) defining the preset to be loaded in the Dashboard
|
|
19
|
+
extension_name: str
|
|
20
|
+
The name of the extension. Either the builtins ones:
|
|
21
|
+
* 'DAQScan'
|
|
22
|
+
* 'DAQLogger'
|
|
23
|
+
* 'DAQ_PID'
|
|
24
|
+
* 'Bayesian'
|
|
25
|
+
|
|
26
|
+
or the ones defined within a plugin
|
|
27
|
+
|
|
28
|
+
Returns
|
|
29
|
+
-------
|
|
30
|
+
|
|
31
|
+
"""
|
|
11
32
|
win = QtWidgets.QMainWindow()
|
|
12
33
|
area = DockArea()
|
|
13
34
|
win.setCentralWidget(area)
|
|
14
35
|
win.resize(1000, 500)
|
|
15
|
-
win.setWindowTitle('
|
|
36
|
+
win.setWindowTitle('extension_name')
|
|
16
37
|
win.show()
|
|
17
38
|
|
|
18
39
|
# win.setVisible(False)
|
|
19
40
|
dashboard = DashBoard(area)
|
|
20
41
|
|
|
42
|
+
preset_name = Path(preset_name).stem
|
|
43
|
+
|
|
21
44
|
file = Path(get_set_preset_path()).joinpath(f"{preset_name}.xml")
|
|
22
45
|
|
|
23
46
|
if file is not None and file.exists():
|
|
@@ -26,6 +49,10 @@ def load_dashboard_with_preset(preset_name: str, extension_name: str):
|
|
|
26
49
|
extension = dashboard.load_scan_module()
|
|
27
50
|
elif extension_name == 'DAQLogger':
|
|
28
51
|
extension = dashboard.load_log_module()
|
|
52
|
+
elif extension_name == 'DAQ_PID':
|
|
53
|
+
extension = dashboard.load_pid_module()
|
|
54
|
+
elif extension_name == 'Bayesian':
|
|
55
|
+
extension = dashboard.load_bayesian()
|
|
29
56
|
else:
|
|
30
57
|
extension = dashboard.load_extension_from_name(extension_name)
|
|
31
58
|
else:
|
pymodaq/utils/gui_utils/utils.py
CHANGED
|
@@ -1,21 +1,18 @@
|
|
|
1
|
-
import sys
|
|
2
|
-
|
|
3
|
-
from qtpy.QtCore import QObject, Signal, QEvent, QBuffer, QIODevice, Qt
|
|
4
|
-
from qtpy import QtWidgets, QtCore, QtGui
|
|
5
|
-
|
|
6
|
-
from pathlib import Path
|
|
7
1
|
from pymodaq_utils.config import Config
|
|
8
2
|
from pymodaq_utils.logger import set_logger, get_module_name
|
|
9
3
|
|
|
4
|
+
from pymodaq_gui.utils.splash import get_splash_sc
|
|
5
|
+
|
|
6
|
+
|
|
10
7
|
config = Config()
|
|
11
8
|
logger = set_logger(get_module_name(__file__))
|
|
12
9
|
|
|
10
|
+
from pymodaq_utils.warnings import deprecation_msg
|
|
11
|
+
|
|
12
|
+
deprecation_msg('Importing get_splash_sc stuff from pymodaq is deprecated '
|
|
13
|
+
'in pymodaq>5.0.0,'
|
|
14
|
+
'please use the same method from the '
|
|
15
|
+
'pymodaq_gui.utils.splash module')
|
|
13
16
|
|
|
14
|
-
def get_splash_sc():
|
|
15
|
-
here = Path(__file__)
|
|
16
|
-
splash_sc = QtWidgets.QSplashScreen(
|
|
17
|
-
QtGui.QPixmap(str(here.parent.parent.parent.joinpath('splash.png'))),
|
|
18
|
-
Qt.WindowStaysOnTopHint)
|
|
19
|
-
return splash_sc
|
|
20
17
|
|
|
21
18
|
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
from pymodaq_gui.utils.widgets.lcd import LCD
|
|
2
|
+
|
|
3
|
+
from pymodaq_utils.warnings import deprecation_msg
|
|
4
|
+
|
|
5
|
+
deprecation_msg('Importing LCD from pymodaq is deprecated '
|
|
6
|
+
'in pymodaq>5.0.0,'
|
|
7
|
+
'please use the same method from the '
|
|
8
|
+
'pymodaq_gui.utils.widgets.lcd module')
|
|
@@ -11,7 +11,7 @@ import xml.etree.ElementTree as ET
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
import numpy as np
|
|
14
|
-
|
|
14
|
+
from pymodaq_utils.logger import set_logger, get_module_name
|
|
15
15
|
from pymodaq_utils.abstract import ABCMeta, abstract_attribute, abstractmethod
|
|
16
16
|
from pymodaq_utils.utils import capitalize
|
|
17
17
|
from pymodaq_data.data import Axis, DataDim, DataWithAxes, DataToExport, DataDistribution
|
|
@@ -28,6 +28,9 @@ if TYPE_CHECKING:
|
|
|
28
28
|
from pymodaq.extensions.daq_logger.h5logging import H5Logger
|
|
29
29
|
|
|
30
30
|
|
|
31
|
+
logger = set_logger(get_module_name(__file__))
|
|
32
|
+
|
|
33
|
+
|
|
31
34
|
class ModuleSaver(metaclass=ABCMeta):
|
|
32
35
|
"""Abstract base class to save info and data from main modules (DAQScan, DAQViewer, DAQMove, ...)"""
|
|
33
36
|
group_type: GroupType = abstract_attribute()
|
|
@@ -374,7 +377,7 @@ class ScanSaver(ModuleSaver):
|
|
|
374
377
|
try:
|
|
375
378
|
detector.insert_data(indexes, where=self._module_group, distribution=distribution)
|
|
376
379
|
except Exception as e:
|
|
377
|
-
|
|
380
|
+
logger.exception(f'Cannot insert data: {str(e)}')
|
|
378
381
|
|
|
379
382
|
|
|
380
383
|
class LoggerSaver(ScanSaver):
|
|
@@ -17,8 +17,7 @@ from pymodaq_gui.parameter import Parameter
|
|
|
17
17
|
|
|
18
18
|
from pymodaq.utils.leco.leco_director import LECODirector, leco_parameters
|
|
19
19
|
from pymodaq.utils.leco.director_utils import ActuatorDirector
|
|
20
|
-
from
|
|
21
|
-
|
|
20
|
+
from pymodaq_utils.serialize.serializer_legacy import DeSerializer
|
|
22
21
|
|
|
23
22
|
class DAQ_Move_LECODirector(LECODirector, DAQ_Move_base):
|
|
24
23
|
"""A control module, which in the dashboard, allows to control a remote Move module.
|
|
@@ -38,8 +37,6 @@ class DAQ_Move_LECODirector(LECODirector, DAQ_Move_base):
|
|
|
38
37
|
settings: Parameter
|
|
39
38
|
controller: ActuatorDirector
|
|
40
39
|
|
|
41
|
-
is_multiaxes = False
|
|
42
|
-
axes_names = []
|
|
43
40
|
params_client = [] # parameters of a client grabber
|
|
44
41
|
data_actuator_type = DataActuatorType['float'] # DataActuatorType['DataActuator']
|
|
45
42
|
|
|
@@ -47,19 +44,21 @@ class DAQ_Move_LECODirector(LECODirector, DAQ_Move_base):
|
|
|
47
44
|
'get_actuator_value', 'stop_motion', 'position_is',
|
|
48
45
|
'move_done']
|
|
49
46
|
socket_types = ["ACTUATOR"]
|
|
50
|
-
params =
|
|
51
|
-
] + comon_parameters_fun(is_multiaxes=is_multiaxes, axes_names=axes_names) + leco_parameters
|
|
47
|
+
params = comon_parameters_fun() + leco_parameters
|
|
52
48
|
|
|
53
49
|
def __init__(self, parent=None, params_state=None, **kwargs) -> None:
|
|
54
50
|
super().__init__(parent=parent,
|
|
55
51
|
params_state=params_state, **kwargs)
|
|
56
52
|
self.register_rpc_methods((
|
|
57
53
|
self.set_info,
|
|
54
|
+
))
|
|
55
|
+
for method in (
|
|
58
56
|
self.set_position,
|
|
59
57
|
self.set_move_done,
|
|
60
58
|
self.set_x_axis,
|
|
61
59
|
self.set_y_axis,
|
|
62
|
-
)
|
|
60
|
+
):
|
|
61
|
+
self.listener.register_binary_rpc_method(method, accept_binary_input=True)
|
|
63
62
|
|
|
64
63
|
# copied, I think it is good:
|
|
65
64
|
self.settings.child('bounds').hide()
|
|
@@ -143,22 +142,29 @@ class DAQ_Move_LECODirector(LECODirector, DAQ_Move_base):
|
|
|
143
142
|
self.controller.stop_motion()
|
|
144
143
|
|
|
145
144
|
# Methods accessible via remote calls
|
|
146
|
-
def _set_position_value(
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
145
|
+
def _set_position_value(
|
|
146
|
+
self, position: Union[str, float, None], additional_payload=None
|
|
147
|
+
) -> DataActuator:
|
|
148
|
+
if position:
|
|
149
|
+
if isinstance(position, str):
|
|
150
|
+
deserializer = DeSerializer.from_b64_string(position)
|
|
151
|
+
pos = deserializer.dwa_deserialization()
|
|
152
|
+
else:
|
|
153
|
+
pos = DataActuator(data=position)
|
|
154
|
+
elif additional_payload is not None:
|
|
155
|
+
pos = DeSerializer(additional_payload[0]).dwa_deserialization()
|
|
150
156
|
else:
|
|
151
|
-
|
|
157
|
+
raise ValueError("No position given")
|
|
152
158
|
pos = self.get_position_with_scaling(pos) # type: ignore
|
|
153
159
|
self._current_value = pos
|
|
154
160
|
return pos
|
|
155
161
|
|
|
156
|
-
def set_position(self, position: Union[str, float]) -> None:
|
|
157
|
-
pos = self._set_position_value(position=position)
|
|
162
|
+
def set_position(self, position: Union[str, float, None], additional_payload=None) -> None:
|
|
163
|
+
pos = self._set_position_value(position=position, additional_payload=additional_payload)
|
|
158
164
|
self.emit_status(ThreadCommand('get_actuator_value', [pos]))
|
|
159
165
|
|
|
160
|
-
def set_move_done(self, position: Union[str, float]) -> None:
|
|
161
|
-
pos = self._set_position_value(position=position)
|
|
166
|
+
def set_move_done(self, position: Union[str, float, None], additional_payload=None) -> None:
|
|
167
|
+
pos = self._set_position_value(position=position, additional_payload=additional_payload)
|
|
162
168
|
self.emit_status(ThreadCommand('move_done', [pos]))
|
|
163
169
|
|
|
164
170
|
def set_x_axis(self, data, label: str = "", units: str = "") -> None:
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
from typing import Union
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
from typing import Optional, Union
|
|
3
3
|
|
|
4
4
|
from easydict import EasyDict as edict
|
|
5
5
|
|
|
6
6
|
from pymodaq.control_modules.viewer_utility_classes import DAQ_Viewer_base, comon_parameters, main
|
|
7
7
|
|
|
8
8
|
from pymodaq_utils.utils import ThreadCommand, getLineInfo
|
|
9
|
+
|
|
9
10
|
from pymodaq_gui.parameter import Parameter
|
|
10
|
-
from
|
|
11
|
+
from pymodaq_utils.serialize.serializer_legacy import DeSerializer
|
|
11
12
|
|
|
12
13
|
from pymodaq.utils.leco.leco_director import LECODirector, leco_parameters
|
|
13
14
|
from pymodaq.utils.leco.director_utils import DetectorDirector
|
|
@@ -29,16 +30,18 @@ class DAQ_xDViewer_LECODirector(LECODirector, DAQ_Viewer_base):
|
|
|
29
30
|
"Status", "Done", "Server Closed",
|
|
30
31
|
"Info", "Infos", "Info_xml", 'x_axis', 'y_axis']
|
|
31
32
|
socket_types = ["GRABBER"]
|
|
32
|
-
params =
|
|
33
|
-
] + comon_parameters + leco_parameters
|
|
33
|
+
params = comon_parameters + leco_parameters
|
|
34
34
|
|
|
35
35
|
def __init__(self, parent=None, params_state=None, grabber_type: str = "0D", **kwargs) -> None:
|
|
36
36
|
super().__init__(parent=parent, params_state=params_state, **kwargs)
|
|
37
37
|
self.register_rpc_methods((
|
|
38
38
|
self.set_x_axis,
|
|
39
39
|
self.set_y_axis,
|
|
40
|
-
self.set_data,
|
|
41
40
|
))
|
|
41
|
+
for method in (
|
|
42
|
+
self.set_data,
|
|
43
|
+
):
|
|
44
|
+
self.listener.register_binary_rpc_method(method, accept_binary_input=True)
|
|
42
45
|
|
|
43
46
|
self.client_type = "GRABBER"
|
|
44
47
|
self.x_axis = None
|
|
@@ -150,7 +153,8 @@ class DAQ_xDViewer_LECODirector(LECODirector, DAQ_Viewer_base):
|
|
|
150
153
|
self.y_axis = dict(data=data, label=label, units=units)
|
|
151
154
|
self.emit_y_axis()
|
|
152
155
|
|
|
153
|
-
def set_data(self, data: Union[list, str
|
|
156
|
+
def set_data(self, data: Union[list, str, None],
|
|
157
|
+
additional_payload: Optional[list[bytes]]=None) -> None:
|
|
154
158
|
"""
|
|
155
159
|
Set the grabbed data signal.
|
|
156
160
|
|
|
@@ -160,10 +164,12 @@ class DAQ_xDViewer_LECODirector(LECODirector, DAQ_Viewer_base):
|
|
|
160
164
|
"""
|
|
161
165
|
if isinstance(data, str):
|
|
162
166
|
deserializer = DeSerializer.from_b64_string(data)
|
|
163
|
-
|
|
164
|
-
|
|
167
|
+
elif additional_payload is not None:
|
|
168
|
+
deserializer = DeSerializer(additional_payload[0])
|
|
165
169
|
else:
|
|
166
170
|
raise NotImplementedError("Not implemented to set a list of values.")
|
|
171
|
+
dte = deserializer.dte_deserialization()
|
|
172
|
+
self.dte_signal.emit(dte)
|
|
167
173
|
|
|
168
174
|
|
|
169
175
|
if __name__ == '__main__':
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
|
|
2
1
|
import random
|
|
3
|
-
|
|
4
2
|
from typing import Callable, Sequence, List
|
|
5
3
|
|
|
4
|
+
from pymodaq_utils.enums import StrEnum
|
|
5
|
+
from typing import Callable, Sequence, List, Optional, Union
|
|
6
|
+
|
|
6
7
|
import pymodaq_gui.parameter.utils as putils
|
|
7
8
|
# object used to send info back to the main thread:
|
|
8
9
|
from pymodaq_utils.utils import ThreadCommand
|
|
@@ -14,7 +15,7 @@ from pymodaq.utils.leco.pymodaq_listener import PymodaqListener
|
|
|
14
15
|
|
|
15
16
|
leco_parameters = [
|
|
16
17
|
{'title': 'Actor name:', 'name': 'actor_name', 'type': 'str', 'value': "actor_name",
|
|
17
|
-
'
|
|
18
|
+
'tip': 'Name of the actor plugin to communicate with.'},
|
|
18
19
|
]
|
|
19
20
|
|
|
20
21
|
|
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
|
|
2
|
-
|
|
3
|
-
from enum import StrEnum # type: ignore
|
|
4
|
-
except ImportError:
|
|
5
|
-
from enum import Enum
|
|
2
|
+
from pymodaq_utils.enums import StrEnum
|
|
6
3
|
|
|
7
|
-
class StrEnum(str, Enum):
|
|
8
|
-
pass
|
|
9
4
|
import logging
|
|
10
5
|
from threading import Event
|
|
11
6
|
from typing import Optional, Union, List, Type
|
|
@@ -16,8 +11,9 @@ from qtpy.QtCore import QObject, Signal # type: ignore
|
|
|
16
11
|
|
|
17
12
|
from pymodaq_utils.utils import ThreadCommand
|
|
18
13
|
from pymodaq_gui.parameter import ioxml
|
|
19
|
-
from
|
|
20
|
-
from
|
|
14
|
+
from pymodaq_data.data import DataWithAxes
|
|
15
|
+
from pymodaq_utils.serialize.serializer_legacy import SERIALIZABLE, DeSerializer
|
|
16
|
+
from pymodaq.utils.leco.utils import binary_serialization_to_kwargs
|
|
21
17
|
|
|
22
18
|
|
|
23
19
|
class LECOClientCommands(StrEnum):
|
|
@@ -220,7 +216,7 @@ class ActorListener(PymodaqListener):
|
|
|
220
216
|
self.communicator.ask_rpc(
|
|
221
217
|
receiver=self.remote_name,
|
|
222
218
|
method="set_data",
|
|
223
|
-
|
|
219
|
+
**binary_serialization_to_kwargs(value),
|
|
224
220
|
)
|
|
225
221
|
|
|
226
222
|
elif command.command == 'send_info':
|
|
@@ -236,14 +232,14 @@ class ActorListener(PymodaqListener):
|
|
|
236
232
|
value = command.attribute[0] # type: ignore
|
|
237
233
|
self.communicator.ask_rpc(receiver=self.remote_name,
|
|
238
234
|
method="set_position",
|
|
239
|
-
|
|
235
|
+
**binary_serialization_to_kwargs(value, data_key="position"),
|
|
240
236
|
)
|
|
241
237
|
|
|
242
238
|
elif command.command == LECOMoveCommands.MOVE_DONE:
|
|
243
239
|
value = command.attribute[0] # type: ignore
|
|
244
240
|
self.communicator.ask_rpc(receiver=self.remote_name,
|
|
245
241
|
method="set_move_done",
|
|
246
|
-
|
|
242
|
+
**binary_serialization_to_kwargs(value, data_key="position"),
|
|
247
243
|
)
|
|
248
244
|
|
|
249
245
|
elif command.command == 'x_axis':
|
|
@@ -251,7 +247,7 @@ class ActorListener(PymodaqListener):
|
|
|
251
247
|
if isinstance(value, SERIALIZABLE):
|
|
252
248
|
self.communicator.ask_rpc(receiver=self.remote_name,
|
|
253
249
|
method="set_x_axis",
|
|
254
|
-
|
|
250
|
+
**binary_serialization_to_kwargs(value),
|
|
255
251
|
)
|
|
256
252
|
elif isinstance(value, dict):
|
|
257
253
|
self.communicator.ask_rpc(receiver=self.remote_name, method="set_x_axis", **value)
|
|
@@ -263,7 +259,7 @@ class ActorListener(PymodaqListener):
|
|
|
263
259
|
if isinstance(value, SERIALIZABLE):
|
|
264
260
|
self.communicator.ask_rpc(receiver=self.remote_name,
|
|
265
261
|
method="set_y_axis",
|
|
266
|
-
|
|
262
|
+
**binary_serialization_to_kwargs(value),
|
|
267
263
|
)
|
|
268
264
|
elif isinstance(value, dict):
|
|
269
265
|
self.communicator.ask_rpc(receiver=self.remote_name, method="set_y_axis", **value)
|
pymodaq/utils/leco/utils.py
CHANGED
|
@@ -1,26 +1,59 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
1
2
|
import subprocess
|
|
2
3
|
import sys
|
|
3
|
-
from typing import Any, Union, get_args
|
|
4
|
+
from typing import Any, Optional, Union, get_args, TypeVar
|
|
4
5
|
|
|
6
|
+
from pymodaq.utils import data
|
|
5
7
|
# import also the DeSerializer for easier imports in dependents
|
|
6
|
-
from
|
|
8
|
+
from pymodaq_utils.serialize.serializer_legacy import Serializer, DeSerializer, SerializableFactory
|
|
9
|
+
|
|
10
|
+
# type: ignore # noqa
|
|
7
11
|
from pymodaq_utils.logger import set_logger
|
|
8
12
|
|
|
9
13
|
|
|
10
14
|
logger = set_logger('leco_utils')
|
|
11
|
-
|
|
15
|
+
ser_factory = SerializableFactory()
|
|
12
16
|
JSON_TYPES = Union[str, int, float]
|
|
13
17
|
|
|
14
18
|
|
|
19
|
+
|
|
15
20
|
def serialize_object(pymodaq_object: Union[SERIALIZABLE, Any]) -> Union[str, Any]:
|
|
16
21
|
"""Serialize a pymodaq object, if it is not JSON compatible."""
|
|
17
22
|
if isinstance(pymodaq_object, get_args(JSON_TYPES)):
|
|
18
23
|
return pymodaq_object
|
|
19
|
-
elif isinstance(pymodaq_object, get_args(SERIALIZABLE)):
|
|
20
|
-
return Serializer(pymodaq_object).to_b64_string()
|
|
21
24
|
else:
|
|
22
|
-
|
|
23
|
-
|
|
25
|
+
return Serializer(pymodaq_object).to_b64_string() # will raise a proper error if the object
|
|
26
|
+
#is not serializable
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
## this form below is to be compatible with python <= 3.10
|
|
30
|
+
## for py>= 3.11 this could be written SERIALIZABLE = Union[ser_factory.get_serializables()]
|
|
31
|
+
SERIALIZABLE = Union[ser_factory.get_serializables()[0]]
|
|
32
|
+
for klass in ser_factory.get_serializables()[1:]:
|
|
33
|
+
SERIALIZABLE = Union[SERIALIZABLE, klass]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def binary_serialization(
|
|
37
|
+
pymodaq_object: Union[SERIALIZABLE, Any],
|
|
38
|
+
) -> tuple[Optional[Any], Optional[list[bytes]]]:
|
|
39
|
+
"""Serialize (binary) a pymodaq object, if it is not JSON compatible."""
|
|
40
|
+
if isinstance(pymodaq_object, get_args(JSON_TYPES)):
|
|
41
|
+
return pymodaq_object, None
|
|
42
|
+
elif isinstance(pymodaq_object, get_args(Union[*ser_factory.get_serializables()])):
|
|
43
|
+
return None, [Serializer(pymodaq_object).to_bytes()]
|
|
44
|
+
else:
|
|
45
|
+
raise ValueError(
|
|
46
|
+
f"{pymodaq_object} of type '{type(pymodaq_object).__name__}' is neither "
|
|
47
|
+
"JSON serializable, nor via PyMoDAQ."
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def binary_serialization_to_kwargs(
|
|
52
|
+
pymodaq_object: Union[SERIALIZABLE, Any], data_key: str = "data"
|
|
53
|
+
) -> dict[str, Any]:
|
|
54
|
+
"""Create a dictionary of data parameters and of additional payload to send."""
|
|
55
|
+
d, b = binary_serialization(pymodaq_object=pymodaq_object)
|
|
56
|
+
return {data_key: d, "additional_payload": b}
|
|
24
57
|
|
|
25
58
|
|
|
26
59
|
def run_coordinator():
|
|
@@ -39,6 +39,7 @@ class ModulesManager(QObject, ParameterManager):
|
|
|
39
39
|
selected_actuators: list of DAQ_Move
|
|
40
40
|
sublist of actuators
|
|
41
41
|
"""
|
|
42
|
+
settings_name = 'ModulesManagerSettings'
|
|
42
43
|
detectors_changed = Signal(list)
|
|
43
44
|
actuators_changed = Signal(list)
|
|
44
45
|
det_done_signal = Signal(DataToExport) # dte here contains DataWithAxes
|
|
@@ -117,7 +118,7 @@ class ModulesManager(QObject, ParameterManager):
|
|
|
117
118
|
modules = [modules]
|
|
118
119
|
return [mod.title for mod in modules]
|
|
119
120
|
|
|
120
|
-
def get_mods_from_names(self, names, mod='det'):
|
|
121
|
+
def get_mods_from_names(self, names, mod='det') -> List[Union['DAQ_Move', 'DAQ_Viewer']]:
|
|
121
122
|
"""Getter of a list of given modules from their name (title)
|
|
122
123
|
|
|
123
124
|
Parameters
|
|
@@ -172,9 +173,14 @@ class ModulesManager(QObject, ParameterManager):
|
|
|
172
173
|
|
|
173
174
|
@property
|
|
174
175
|
def detectors_all(self):
|
|
175
|
-
"""Get the list of all detectors"""
|
|
176
|
+
"""Get/Set the list of all detectors"""
|
|
176
177
|
return self._detectors
|
|
177
178
|
|
|
179
|
+
@detectors_all.setter
|
|
180
|
+
def detectors_all(self, detectors: List['DAQ_Viewer']):
|
|
181
|
+
self._detectors = detectors
|
|
182
|
+
|
|
183
|
+
|
|
178
184
|
@property
|
|
179
185
|
def actuators(self) -> List['DAQ_Move']:
|
|
180
186
|
"""Get the list of selected actuators"""
|
|
@@ -185,6 +191,10 @@ class ModulesManager(QObject, ParameterManager):
|
|
|
185
191
|
"""Get the list of all actuators"""
|
|
186
192
|
return self._actuators
|
|
187
193
|
|
|
194
|
+
@actuators_all.setter
|
|
195
|
+
def actuators_all(self, actuators: List['DAQ_Move']):
|
|
196
|
+
self._actuators = actuators
|
|
197
|
+
|
|
188
198
|
@property
|
|
189
199
|
def modules(self):
|
|
190
200
|
"""Get the list of all detectors and actuators"""
|
|
@@ -244,11 +254,11 @@ class ModulesManager(QObject, ParameterManager):
|
|
|
244
254
|
elif param.name() == 'actuators':
|
|
245
255
|
self.actuators_changed.emit(param.value()['selected'])
|
|
246
256
|
|
|
247
|
-
def get_det_data_list(self):
|
|
257
|
+
def get_det_data_list(self) -> DataToExport:
|
|
248
258
|
"""Do a snap of selected detectors, to get the list of all the data and processed data"""
|
|
249
259
|
|
|
250
260
|
self.connect_detectors()
|
|
251
|
-
datas: DataToExport = self.
|
|
261
|
+
datas: DataToExport = self.grab_data()
|
|
252
262
|
|
|
253
263
|
data_list0D = datas.get_full_names('data0D')
|
|
254
264
|
data_list1D = datas.get_full_names('data1D')
|
|
@@ -265,6 +275,7 @@ class ModulesManager(QObject, ParameterManager):
|
|
|
265
275
|
dict(all_items=data_listND, selected=[]))
|
|
266
276
|
|
|
267
277
|
self.connect_detectors(False)
|
|
278
|
+
return datas
|
|
268
279
|
|
|
269
280
|
def get_selected_probed_data(self, dim='0D'):
|
|
270
281
|
"""Get the name of selected data names of a given dimensionality
|
|
@@ -276,7 +287,7 @@ class ModulesManager(QObject, ParameterManager):
|
|
|
276
287
|
"""
|
|
277
288
|
return self.settings.child('data_dimensions', f'det_data_list{dim.upper()}').value()['selected']
|
|
278
289
|
|
|
279
|
-
def
|
|
290
|
+
def grab_data(self, **kwargs):
|
|
280
291
|
"""Do a single grab of connected and selected detectors"""
|
|
281
292
|
self.det_done_datas = DataToExport(name=__class__.__name__, control_module='DAQ_Viewer')
|
|
282
293
|
self._received_data = 0
|
|
@@ -300,6 +311,10 @@ class ModulesManager(QObject, ParameterManager):
|
|
|
300
311
|
self.det_done_signal.emit(self.det_done_datas)
|
|
301
312
|
return self.det_done_datas
|
|
302
313
|
|
|
314
|
+
def grab_datas(self, **kwargs):
|
|
315
|
+
""" For back compatibility but use self.grab_data"""
|
|
316
|
+
return self.grab_data(**kwargs)
|
|
317
|
+
|
|
303
318
|
def connect_actuators(self, connect=True, slot=None, signal='move_done'):
|
|
304
319
|
"""Connect the selected actuators signal to a given or default slot
|
|
305
320
|
|
|
@@ -359,12 +374,12 @@ class ModulesManager(QObject, ParameterManager):
|
|
|
359
374
|
sig.connect(slot)
|
|
360
375
|
else:
|
|
361
376
|
|
|
362
|
-
for sig in [mod.grab_done_signal for mod in self.
|
|
377
|
+
for sig in [mod.grab_done_signal for mod in self.detectors]:
|
|
363
378
|
try:
|
|
364
379
|
sig.disconnect(slot)
|
|
365
380
|
except TypeError as e:
|
|
366
381
|
# means the slot was not previously connected
|
|
367
|
-
logger.info(
|
|
382
|
+
logger.info(f'Could not disconnect grab signal from the {slot} slot', stacklevel=2)
|
|
368
383
|
|
|
369
384
|
self.detectors_connected = connect
|
|
370
385
|
|
|
@@ -482,11 +497,6 @@ class ModulesManager(QObject, ParameterManager):
|
|
|
482
497
|
self.det_done_flag = True
|
|
483
498
|
self.settings.child('det_done').setValue(self.det_done_flag)
|
|
484
499
|
|
|
485
|
-
# if data.name not in list(self.det_done_datas.keys()):
|
|
486
|
-
# self.det_done_datas[data['name']] = data
|
|
487
|
-
# if len(self.det_done_datas.items()) == len(self.detectors):
|
|
488
|
-
# self.det_done_flag = True
|
|
489
|
-
|
|
490
500
|
|
|
491
501
|
if __name__ == '__main__':
|
|
492
502
|
import sys
|