pymodaq 5.0.5__py3-none-any.whl → 5.1.0a0__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/control_modules/daq_move.py +77 -64
- pymodaq/control_modules/daq_move_ui.py +16 -15
- pymodaq/control_modules/daq_viewer.py +95 -87
- pymodaq/control_modules/daq_viewer_ui.py +22 -23
- pymodaq/control_modules/mocks.py +2 -2
- pymodaq/control_modules/move_utility_classes.py +28 -19
- pymodaq/control_modules/thread_commands.py +138 -0
- pymodaq/control_modules/utils.py +88 -20
- pymodaq/control_modules/viewer_utility_classes.py +8 -17
- pymodaq/dashboard.py +90 -27
- pymodaq/examples/qt_less_standalone_module.py +48 -11
- pymodaq/extensions/__init__.py +7 -3
- pymodaq/extensions/adaptive/__init__.py +2 -0
- pymodaq/extensions/adaptive/adaptive_optimization.py +159 -0
- pymodaq/extensions/adaptive/loss_function/_1d_loss_functions.py +73 -0
- pymodaq/extensions/adaptive/loss_function/_2d_loss_functions.py +86 -0
- pymodaq/extensions/adaptive/loss_function/__init__.py +3 -0
- pymodaq/extensions/adaptive/loss_function/loss_factory.py +106 -0
- pymodaq/extensions/adaptive/utils.py +97 -0
- pymodaq/extensions/bayesian/__init__.py +1 -1
- pymodaq/extensions/bayesian/acquisition/__init__.py +2 -0
- pymodaq/extensions/bayesian/acquisition/acquisition_function_factory.py +71 -0
- pymodaq/extensions/bayesian/acquisition/base_acquisition_function.py +86 -0
- pymodaq/extensions/bayesian/bayesian_optimization.py +121 -0
- pymodaq/extensions/bayesian/utils.py +27 -286
- pymodaq/extensions/daq_logger/daq_logger.py +7 -12
- pymodaq/extensions/daq_logger/h5logging.py +1 -1
- pymodaq/extensions/daq_scan.py +18 -47
- pymodaq/extensions/h5browser.py +3 -34
- pymodaq/extensions/optimizers_base/__init__.py +0 -0
- pymodaq/extensions/{bayesian/bayesian_optimisation.py → optimizers_base/optimizer.py} +441 -334
- pymodaq/extensions/optimizers_base/thread_commands.py +20 -0
- pymodaq/extensions/optimizers_base/utils.py +378 -0
- pymodaq/extensions/pid/pid_controller.py +6 -10
- pymodaq/extensions/utils.py +12 -0
- pymodaq/utils/data.py +1 -0
- pymodaq/utils/gui_utils/loader_utils.py +2 -0
- pymodaq/utils/h5modules/module_saving.py +134 -22
- pymodaq/utils/leco/daq_move_LECODirector.py +73 -73
- pymodaq/utils/leco/daq_xDviewer_LECODirector.py +36 -84
- pymodaq/utils/leco/director_utils.py +25 -10
- pymodaq/utils/leco/leco_director.py +65 -26
- pymodaq/utils/leco/pymodaq_listener.py +118 -68
- pymodaq/utils/leco/utils.py +24 -24
- pymodaq/utils/managers/modules_manager.py +37 -8
- pymodaq/utils/scanner/scanners/_1d_scanners.py +0 -38
- pymodaq/utils/scanner/scanners/_2d_scanners.py +0 -58
- {pymodaq-5.0.5.dist-info → pymodaq-5.1.0a0.dist-info}/METADATA +4 -3
- {pymodaq-5.0.5.dist-info → pymodaq-5.1.0a0.dist-info}/RECORD +52 -38
- {pymodaq-5.0.5.dist-info → pymodaq-5.1.0a0.dist-info}/entry_points.txt +0 -2
- pymodaq/utils/leco/desktop.ini +0 -2
- {pymodaq-5.0.5.dist-info → pymodaq-5.1.0a0.dist-info}/WHEEL +0 -0
- {pymodaq-5.0.5.dist-info → pymodaq-5.1.0a0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
from typing import Optional, Union
|
|
3
3
|
|
|
4
|
-
from easydict import EasyDict as edict
|
|
5
|
-
|
|
6
4
|
from pymodaq.control_modules.viewer_utility_classes import DAQ_Viewer_base, comon_parameters, main
|
|
7
|
-
|
|
5
|
+
from pymodaq.control_modules.thread_commands import ThreadStatus, ThreadStatusViewer
|
|
6
|
+
from pymodaq_utils.serialize.factory import SerializableFactory
|
|
8
7
|
from pymodaq_utils.utils import ThreadCommand, getLineInfo
|
|
9
8
|
|
|
9
|
+
|
|
10
|
+
from pymodaq.utils import data # for serialization factory registration # noqa: F401
|
|
10
11
|
from pymodaq_gui.parameter import Parameter
|
|
11
|
-
from pymodaq_utils.serialize.serializer_legacy import DeSerializer
|
|
12
12
|
|
|
13
13
|
from pymodaq.utils.leco.leco_director import LECODirector, leco_parameters
|
|
14
14
|
from pymodaq.utils.leco.director_utils import DetectorDirector
|
|
15
|
+
from pymodaq_utils.logger import set_logger, get_module_name
|
|
16
|
+
|
|
17
|
+
logger = set_logger(get_module_name(__file__))
|
|
15
18
|
|
|
16
19
|
|
|
17
20
|
class DAQ_xDViewer_LECODirector(LECODirector, DAQ_Viewer_base):
|
|
@@ -25,19 +28,14 @@ class DAQ_xDViewer_LECODirector(LECODirector, DAQ_Viewer_base):
|
|
|
25
28
|
|
|
26
29
|
params_GRABBER = []
|
|
27
30
|
|
|
28
|
-
message_list = LECODirector.message_list + ["Quit", "Send Data 0D", "Send Data 1D",
|
|
29
|
-
"Send Data 2D", "Send Data ND",
|
|
30
|
-
"Status", "Done", "Server Closed",
|
|
31
|
-
"Info", "Infos", "Info_xml", 'x_axis', 'y_axis']
|
|
32
31
|
socket_types = ["GRABBER"]
|
|
33
32
|
params = comon_parameters + leco_parameters
|
|
33
|
+
live_mode_available = True
|
|
34
34
|
|
|
35
35
|
def __init__(self, parent=None, params_state=None, grabber_type: str = "0D", **kwargs) -> None:
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
self.set_y_axis,
|
|
40
|
-
))
|
|
36
|
+
DAQ_Viewer_base.__init__(self, parent=parent,
|
|
37
|
+
params_state=params_state)
|
|
38
|
+
LECODirector.__init__(self, host=self.settings['host'])
|
|
41
39
|
for method in (
|
|
42
40
|
self.set_data,
|
|
43
41
|
):
|
|
@@ -62,54 +60,23 @@ class DAQ_xDViewer_LECODirector(LECODirector, DAQ_Viewer_base):
|
|
|
62
60
|
--------
|
|
63
61
|
utility_classes.DAQ_TCP_server.init_server, get_xaxis, get_yaxis
|
|
64
62
|
"""
|
|
65
|
-
self.status.update(edict(initialized=False, info="", x_axis=None, y_axis=None,
|
|
66
|
-
controller=None))
|
|
67
|
-
actor_name = self.settings.child("actor_name").value()
|
|
68
|
-
self.controller = self.ini_detector_init( # type: ignore
|
|
69
|
-
old_controller=controller,
|
|
70
|
-
new_controller=DetectorDirector(actor=actor_name, communicator=self.communicator),
|
|
71
|
-
)
|
|
72
|
-
self.controller.set_remote_name(self.communicator.full_name) # type: ignore
|
|
73
|
-
try:
|
|
74
|
-
# self.settings.child(('infos')).addChildren(self.params_GRABBER)
|
|
75
|
-
|
|
76
|
-
# init axes from image , here returns only None values (to tricky to di it with the
|
|
77
|
-
# server and not really necessary for images anyway)
|
|
78
|
-
self.x_axis = self.get_xaxis()
|
|
79
|
-
self.y_axis = self.get_yaxis()
|
|
80
|
-
self.status.x_axis = self.x_axis
|
|
81
|
-
self.status.y_axis = self.y_axis
|
|
82
|
-
self.status.initialized = True
|
|
83
|
-
return self.status
|
|
84
|
-
|
|
85
|
-
except Exception as e:
|
|
86
|
-
self.status.info = getLineInfo() + str(e)
|
|
87
|
-
self.status.initialized = False
|
|
88
|
-
return self.status
|
|
89
|
-
|
|
90
|
-
def get_xaxis(self):
|
|
91
|
-
"""
|
|
92
|
-
Obtain the horizontal axis of the image.
|
|
93
63
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
64
|
+
actor_name = self.settings["actor_name"]
|
|
65
|
+
if self.is_master:
|
|
66
|
+
self.controller = DetectorDirector(actor=actor_name,
|
|
67
|
+
communicator=self.communicator)
|
|
68
|
+
try:
|
|
69
|
+
self.controller.set_remote_name(self.communicator.full_name) # type: ignore
|
|
70
|
+
except TimeoutError:
|
|
71
|
+
logger.warning("Timeout setting remote name.")
|
|
72
|
+
else:
|
|
73
|
+
self.controller = controller
|
|
101
74
|
|
|
102
|
-
|
|
103
|
-
"""
|
|
104
|
-
Obtain the vertical axis of the image.
|
|
75
|
+
self.controller.get_settings()
|
|
105
76
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
Contains a vector of integer corresponding to the vertical camera pixels.
|
|
110
|
-
"""
|
|
111
|
-
pass
|
|
112
|
-
return self.y_axis
|
|
77
|
+
initialized = True
|
|
78
|
+
info = 'Viewer Director ready'
|
|
79
|
+
return info, initialized
|
|
113
80
|
|
|
114
81
|
def grab_data(self, Naverage=1, **kwargs):
|
|
115
82
|
"""
|
|
@@ -126,32 +93,20 @@ class DAQ_xDViewer_LECODirector(LECODirector, DAQ_Viewer_base):
|
|
|
126
93
|
--------
|
|
127
94
|
utility_classes.DAQ_TCP_server.process_cmds
|
|
128
95
|
"""
|
|
129
|
-
try:
|
|
130
|
-
self.ind_grabbed = 0 # to keep track of the current image in the average
|
|
131
|
-
self.Naverage = Naverage
|
|
132
|
-
self.controller.set_remote_name(self.communicator.full_name)
|
|
133
|
-
self.controller.send_data(grabber_type=self.grabber_type)
|
|
134
96
|
|
|
135
|
-
|
|
136
|
-
|
|
97
|
+
self.ind_grabbed = 0 # to keep track of the current image in the average
|
|
98
|
+
self.Naverage = Naverage
|
|
99
|
+
self.controller.set_remote_name(self.communicator.full_name)
|
|
100
|
+
if kwargs.get('live', False):
|
|
101
|
+
self.controller.send_data_grab()
|
|
102
|
+
else:
|
|
103
|
+
self.controller.send_data_snap()
|
|
137
104
|
|
|
138
105
|
def stop(self):
|
|
139
106
|
"""
|
|
140
107
|
not implemented.
|
|
141
108
|
"""
|
|
142
|
-
|
|
143
|
-
return ""
|
|
144
|
-
|
|
145
|
-
# Methods for RPC calls
|
|
146
|
-
def set_x_axis(self, data, label: str = "", units: str = ""):
|
|
147
|
-
# TODO make to work
|
|
148
|
-
self.x_axis = dict(data=data, label=label, units=units)
|
|
149
|
-
self.emit_x_axis()
|
|
150
|
-
|
|
151
|
-
def set_y_axis(self, data, label: str = "", units: str = ""):
|
|
152
|
-
# TODO make to work
|
|
153
|
-
self.y_axis = dict(data=data, label=label, units=units)
|
|
154
|
-
self.emit_y_axis()
|
|
109
|
+
self.controller.stop_grab()
|
|
155
110
|
|
|
156
111
|
def set_data(self, data: Union[list, str, None],
|
|
157
112
|
additional_payload: Optional[list[bytes]]=None) -> None:
|
|
@@ -162,15 +117,12 @@ class DAQ_xDViewer_LECODirector(LECODirector, DAQ_Viewer_base):
|
|
|
162
117
|
|
|
163
118
|
:param data: If None, look for the additional object
|
|
164
119
|
"""
|
|
165
|
-
if
|
|
166
|
-
|
|
167
|
-
elif additional_payload is not None:
|
|
168
|
-
deserializer = DeSerializer(additional_payload[0])
|
|
120
|
+
if additional_payload is not None:
|
|
121
|
+
dte = SerializableFactory().get_apply_deserializer(additional_payload[0])
|
|
169
122
|
else:
|
|
170
123
|
raise NotImplementedError("Not implemented to set a list of values.")
|
|
171
|
-
dte = deserializer.dte_deserialization()
|
|
172
124
|
self.dte_signal.emit(dte)
|
|
173
125
|
|
|
174
126
|
|
|
175
127
|
if __name__ == '__main__':
|
|
176
|
-
main(__file__)
|
|
128
|
+
main(__file__, init=False)
|
|
@@ -10,8 +10,11 @@ from pyleco.directors.director import Director
|
|
|
10
10
|
|
|
11
11
|
import pymodaq_gui.parameter.utils as putils
|
|
12
12
|
from pymodaq_gui.parameter import Parameter, ioxml
|
|
13
|
-
from pymodaq.
|
|
14
|
-
from pymodaq.utils.leco.utils import
|
|
13
|
+
from pymodaq.utils.data import DataActuator
|
|
14
|
+
from pymodaq.utils.leco.utils import binary_serialization_to_kwargs, SerializableFactory
|
|
15
|
+
|
|
16
|
+
from pymodaq_gui.parameter.utils import ParameterWithPath
|
|
17
|
+
|
|
15
18
|
|
|
16
19
|
|
|
17
20
|
class GenericDirector(Director):
|
|
@@ -23,24 +26,35 @@ class GenericDirector(Director):
|
|
|
23
26
|
|
|
24
27
|
def set_info(self, param: Parameter):
|
|
25
28
|
# It removes the first two parts (main_settings and detector_settings?)
|
|
26
|
-
|
|
27
|
-
|
|
29
|
+
pwp = ParameterWithPath(param, putils.get_param_path(param)[2:])
|
|
30
|
+
self.ask_rpc(method="set_info",
|
|
31
|
+
**binary_serialization_to_kwargs(pwp, data_key='parameter'))
|
|
28
32
|
|
|
29
|
-
def
|
|
30
|
-
self.ask_rpc(
|
|
33
|
+
def get_settings(self,) -> None:
|
|
34
|
+
self.ask_rpc('get_settings')
|
|
31
35
|
|
|
32
36
|
|
|
33
37
|
class DetectorDirector(GenericDirector):
|
|
34
|
-
def
|
|
35
|
-
self.ask_rpc("
|
|
38
|
+
def send_data_grab(self, grabber_type: str = "") -> None:
|
|
39
|
+
self.ask_rpc("send_data_grab", grabber_type=grabber_type)
|
|
40
|
+
|
|
41
|
+
def send_data_snap(self, grabber_type: str = "") -> None:
|
|
42
|
+
self.ask_rpc("send_data_snap", grabber_type=grabber_type)
|
|
43
|
+
|
|
44
|
+
def stop_grab(self, grabber_type: str = "") -> None:
|
|
45
|
+
self.ask_rpc("stop_grab", grabber_type=grabber_type)
|
|
36
46
|
|
|
37
47
|
|
|
38
48
|
class ActuatorDirector(GenericDirector):
|
|
39
49
|
def move_abs(self, position: Union[float, DataActuator]) -> None:
|
|
40
|
-
self.ask_rpc(
|
|
50
|
+
self.ask_rpc(
|
|
51
|
+
"move_abs", **binary_serialization_to_kwargs(position, data_key="position")
|
|
52
|
+
)
|
|
41
53
|
|
|
42
54
|
def move_rel(self, position: Union[float, DataActuator]) -> None:
|
|
43
|
-
self.ask_rpc(
|
|
55
|
+
self.ask_rpc(
|
|
56
|
+
"move_rel", **binary_serialization_to_kwargs(position, data_key="position")
|
|
57
|
+
)
|
|
44
58
|
|
|
45
59
|
def move_home(self) -> None:
|
|
46
60
|
self.ask_rpc("move_home")
|
|
@@ -56,3 +70,4 @@ class ActuatorDirector(GenericDirector):
|
|
|
56
70
|
def stop_motion(self,) -> None:
|
|
57
71
|
# not implemented in DAQ_Move!
|
|
58
72
|
self.ask_rpc("stop_motion")
|
|
73
|
+
|
|
@@ -1,21 +1,42 @@
|
|
|
1
|
-
import random
|
|
2
|
-
from typing import Callable, Sequence, List
|
|
3
1
|
|
|
2
|
+
import random
|
|
4
3
|
from pymodaq_utils.enums import StrEnum
|
|
5
4
|
from typing import Callable, Sequence, List, Optional, Union
|
|
6
5
|
|
|
7
6
|
import pymodaq_gui.parameter.utils as putils
|
|
8
7
|
# object used to send info back to the main thread:
|
|
9
8
|
from pymodaq_utils.utils import ThreadCommand
|
|
9
|
+
from pymodaq.utils.config import Config
|
|
10
10
|
from pymodaq_gui.parameter import Parameter
|
|
11
|
+
from pymodaq_gui.parameter import ioxml
|
|
12
|
+
from pymodaq_gui.parameter.utils import ParameterWithPath
|
|
11
13
|
|
|
12
14
|
from pymodaq.utils.leco.director_utils import GenericDirector
|
|
13
15
|
from pymodaq.utils.leco.pymodaq_listener import PymodaqListener
|
|
16
|
+
from pymodaq_utils.serialize.factory import SerializableFactory
|
|
17
|
+
from pymodaq.control_modules.thread_commands import ThreadStatusMove
|
|
18
|
+
|
|
19
|
+
config = Config()
|
|
20
|
+
|
|
21
|
+
class DirectorCommands(StrEnum):
|
|
22
|
+
SET_SETTINGS = 'set_settings'
|
|
23
|
+
SET_INFO = 'set_info'
|
|
24
|
+
|
|
25
|
+
SEND_POSITION = 'send_position' # to display the actor position
|
|
26
|
+
SET_MOVE_DONE = 'set_move_done'
|
|
27
|
+
SET_UNITS = 'set_units' # to set units accordingly to the one of the actor
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class DirectorReceivedCommands(StrEnum):
|
|
31
|
+
MOVE_DONE = ThreadStatusMove.MOVE_DONE
|
|
32
|
+
GET_ACTUATOR_VALUE = ThreadStatusMove.GET_ACTUATOR_VALUE
|
|
14
33
|
|
|
15
34
|
|
|
16
35
|
leco_parameters = [
|
|
17
36
|
{'title': 'Actor name:', 'name': 'actor_name', 'type': 'str', 'value': "actor_name",
|
|
18
37
|
'tip': 'Name of the actor plugin to communicate with.'},
|
|
38
|
+
{'title': 'Coordinator Host:', 'name': 'host', 'type': 'str', 'value': config('network', "leco-server", "host")},
|
|
39
|
+
{'title': 'Settings PyMoDAQ Client:', 'name': 'settings_client', 'type': 'group', 'children': []},
|
|
19
40
|
]
|
|
20
41
|
|
|
21
42
|
|
|
@@ -23,45 +44,40 @@ class LECODirector:
|
|
|
23
44
|
"""
|
|
24
45
|
This is a mixin for a Control module to direct another, remote module (analogous to TCP Server).
|
|
25
46
|
|
|
26
|
-
|
|
27
|
-
**Attributes** **Type**
|
|
28
|
-
*command_server* instance of Signal
|
|
29
|
-
*x_axis* 1D numpy array
|
|
30
|
-
*y_axis* 1D numpy array
|
|
31
|
-
*data* double precision float array
|
|
32
|
-
================= ==============================
|
|
33
|
-
|
|
34
|
-
See Also
|
|
35
|
-
--------
|
|
36
|
-
utility_classes.DAQ_TCP_server
|
|
47
|
+
|
|
37
48
|
"""
|
|
38
|
-
message_list = ["Quit", "Status", "Done", "Server Closed", "Info", "Infos", "Info_xml",
|
|
39
|
-
"move_abs", 'move_home', 'move_rel', 'get_actuator_value', 'stop_motion',
|
|
40
|
-
'position_is', 'move_done',
|
|
41
|
-
]
|
|
42
|
-
socket_types: List[str]
|
|
43
49
|
|
|
44
50
|
controller: GenericDirector
|
|
45
51
|
settings: Parameter
|
|
52
|
+
_title: str
|
|
46
53
|
|
|
47
|
-
def __init__(self, **kwargs) -> None:
|
|
48
|
-
super().__init__(**kwargs)
|
|
54
|
+
def __init__(self, host: str = 'localhost', **kwargs) -> None:
|
|
49
55
|
|
|
50
56
|
name = f'{self._title}_{random.randrange(0, 10000)}_director'
|
|
51
|
-
|
|
52
|
-
self.listener = PymodaqListener(name=name)
|
|
57
|
+
|
|
58
|
+
self.listener = PymodaqListener(name=name, host=host)
|
|
53
59
|
self.listener.start_listen()
|
|
60
|
+
|
|
54
61
|
self.communicator = self.listener.get_communicator()
|
|
62
|
+
|
|
63
|
+
#registering rpc methods common to all Directors
|
|
55
64
|
self.register_rpc_methods((
|
|
65
|
+
self.set_settings,
|
|
66
|
+
))
|
|
67
|
+
self.register_binary_rpc_methods((
|
|
56
68
|
self.set_info,
|
|
57
69
|
))
|
|
58
70
|
|
|
71
|
+
def register_binary_rpc_methods(self, methods: Sequence[Callable]) -> None:
|
|
72
|
+
for method in methods:
|
|
73
|
+
self.listener.register_binary_rpc_method(method, accept_binary_input=True)
|
|
74
|
+
|
|
59
75
|
def register_rpc_methods(self, methods: Sequence[Callable]) -> None:
|
|
60
76
|
for method in methods:
|
|
61
77
|
self.communicator.register_rpc_method(method=method)
|
|
62
78
|
|
|
63
|
-
def commit_settings(self, param
|
|
64
|
-
|
|
79
|
+
def commit_settings(self, param) -> None:
|
|
80
|
+
self.commit_leco_settings(param=param)
|
|
65
81
|
|
|
66
82
|
def commit_leco_settings(self, param: Parameter) -> None:
|
|
67
83
|
if param.name() == "actor_name":
|
|
@@ -70,6 +86,8 @@ class LECODirector:
|
|
|
70
86
|
self.controller.set_info(param=param)
|
|
71
87
|
|
|
72
88
|
def close(self) -> None:
|
|
89
|
+
""" Clear the content of the settings_clients setting"""
|
|
90
|
+
self.settings.child('settings_client').clearChildren()
|
|
73
91
|
self.listener.stop_listen()
|
|
74
92
|
|
|
75
93
|
def stop(self):
|
|
@@ -85,5 +103,26 @@ class LECODirector:
|
|
|
85
103
|
super().emit_status(status=status) # type: ignore
|
|
86
104
|
|
|
87
105
|
# Methods accessible via remote calls
|
|
88
|
-
def set_info(self,
|
|
89
|
-
|
|
106
|
+
def set_info(self,
|
|
107
|
+
parameter: Optional[Union[float, str]],
|
|
108
|
+
additional_payload: Optional[List[bytes]] = None,
|
|
109
|
+
) -> None:
|
|
110
|
+
""" Write the value of a param upfated from the actor to here in the
|
|
111
|
+
Parameter with path: ('move_settings', 'settings_client')
|
|
112
|
+
"""
|
|
113
|
+
param: ParameterWithPath = SerializableFactory().get_apply_deserializer(additional_payload[0])
|
|
114
|
+
|
|
115
|
+
try:
|
|
116
|
+
path = ['settings_client']
|
|
117
|
+
path.extend(param.path[1:])
|
|
118
|
+
|
|
119
|
+
self.settings.child(*path).setValue(param.value())
|
|
120
|
+
except Exception as e:
|
|
121
|
+
print(f'could not set the param {param} in the director:\n'
|
|
122
|
+
f'{str(e)}')
|
|
123
|
+
|
|
124
|
+
def set_settings(self, settings: bytes):
|
|
125
|
+
""" Get the content of the actor settings to pe populated in this plugin
|
|
126
|
+
'settings_client' parameter"""
|
|
127
|
+
params = ioxml.XML_string_to_parameter(settings)
|
|
128
|
+
self.settings.child('settings_client').addChildren(params)
|
|
@@ -3,16 +3,18 @@ from pymodaq_utils.enums import StrEnum
|
|
|
3
3
|
|
|
4
4
|
import logging
|
|
5
5
|
from threading import Event
|
|
6
|
-
from typing import Optional, Union, List, Type
|
|
6
|
+
from typing import cast, Optional, Union, List, Sequence, Type
|
|
7
7
|
|
|
8
8
|
from pyleco.core import COORDINATOR_PORT
|
|
9
9
|
from pyleco.utils.listener import Listener, PipeHandler
|
|
10
10
|
from qtpy.QtCore import QObject, Signal # type: ignore
|
|
11
11
|
|
|
12
|
+
from pymodaq_data.data import DataWithAxes
|
|
13
|
+
from pymodaq_utils.serialize.factory import SerializableFactory, SerializableBase
|
|
12
14
|
from pymodaq_utils.utils import ThreadCommand
|
|
13
15
|
from pymodaq_gui.parameter import ioxml
|
|
14
|
-
from
|
|
15
|
-
|
|
16
|
+
from pymodaq_gui.parameter.utils import ParameterWithPath
|
|
17
|
+
|
|
16
18
|
from pymodaq.utils.leco.utils import binary_serialization_to_kwargs
|
|
17
19
|
|
|
18
20
|
|
|
@@ -24,15 +26,28 @@ class LECOClientCommands(StrEnum):
|
|
|
24
26
|
class LECOCommands(StrEnum):
|
|
25
27
|
CONNECT = "ini_connection"
|
|
26
28
|
QUIT = "quit"
|
|
29
|
+
GET_SETTINGS = 'get_settings'
|
|
30
|
+
SET_SETTINGS = 'set_settings'
|
|
31
|
+
SET_INFO = 'set_info'
|
|
32
|
+
SEND_INFO = 'send_info'
|
|
27
33
|
|
|
28
34
|
|
|
29
35
|
class LECOMoveCommands(StrEnum):
|
|
30
36
|
POSITION = 'position_is'
|
|
31
37
|
MOVE_DONE = 'move_done'
|
|
38
|
+
UNITS_CHANGED = 'units_changed'
|
|
39
|
+
STOP = 'stop_motion'
|
|
40
|
+
MOVE_ABS = 'move_abs'
|
|
41
|
+
MOVE_REL = 'move_rel'
|
|
42
|
+
MOVE_HOME = 'move_home'
|
|
43
|
+
GET_ACTUATOR_VALUE = 'get_actuator_value'
|
|
32
44
|
|
|
33
45
|
|
|
34
46
|
class LECOViewerCommands(StrEnum):
|
|
35
47
|
DATA_READY = 'data_ready'
|
|
48
|
+
GRAB = 'grab'
|
|
49
|
+
SNAP = 'snap'
|
|
50
|
+
STOP = 'stop_grab'
|
|
36
51
|
|
|
37
52
|
|
|
38
53
|
class ListenerSignals(QObject):
|
|
@@ -53,54 +68,109 @@ class PymodaqPipeHandler(PipeHandler):
|
|
|
53
68
|
def __init__(self, name: str, signals: ListenerSignals, **kwargs) -> None:
|
|
54
69
|
super().__init__(name, **kwargs)
|
|
55
70
|
self.signals = signals
|
|
56
|
-
|
|
71
|
+
self.register_data_types_for_deserialization()
|
|
72
|
+
|
|
73
|
+
def register_data_types_for_deserialization(
|
|
74
|
+
self, types: Optional[Sequence[type[SerializableBase]]] = None
|
|
75
|
+
) -> None:
|
|
76
|
+
"""Register different data types for deserialization in subclasses."""
|
|
77
|
+
if types is None:
|
|
78
|
+
return
|
|
79
|
+
for cls in types:
|
|
80
|
+
SerializableFactory().register_from_type(
|
|
81
|
+
cls, cls.serialize, cls.deserialize
|
|
82
|
+
)
|
|
57
83
|
|
|
58
84
|
class ActorHandler(PymodaqPipeHandler):
|
|
85
|
+
def register_data_types_for_deserialization(
|
|
86
|
+
self, types: Optional[Sequence[type[SerializableBase]]] = None
|
|
87
|
+
) -> None:
|
|
88
|
+
all_types: Sequence[type[SerializableBase]] = [DataWithAxes]
|
|
89
|
+
if types:
|
|
90
|
+
all_types.extend(types) # type: ignore
|
|
91
|
+
super().register_data_types_for_deserialization(all_types)
|
|
59
92
|
|
|
60
93
|
def register_rpc_methods(self) -> None:
|
|
61
94
|
super().register_rpc_methods()
|
|
62
|
-
self.
|
|
63
|
-
self.register_rpc_method(self.
|
|
64
|
-
self.register_rpc_method(self.
|
|
65
|
-
self.
|
|
95
|
+
self.register_binary_rpc_method(self.set_info, accept_binary_input=True)
|
|
96
|
+
self.register_rpc_method(self.send_data_grab)
|
|
97
|
+
self.register_rpc_method(self.send_data_snap)
|
|
98
|
+
self.register_binary_rpc_method(self.move_abs, accept_binary_input=True)
|
|
99
|
+
self.register_binary_rpc_method(self.move_rel, accept_binary_input=True)
|
|
66
100
|
self.register_rpc_method(self.move_home)
|
|
67
101
|
self.register_rpc_method(self.get_actuator_value)
|
|
68
102
|
self.register_rpc_method(self.stop_motion)
|
|
103
|
+
self.register_rpc_method(self.stop_grab)
|
|
104
|
+
self.register_rpc_method(self.get_settings)
|
|
69
105
|
|
|
70
106
|
@staticmethod
|
|
71
|
-
def
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
107
|
+
def extract_pymodaq_object(
|
|
108
|
+
value: Optional[Union[float, str]], additional_payload: Optional[List[bytes]]
|
|
109
|
+
):
|
|
110
|
+
if value is None and additional_payload:
|
|
111
|
+
return cast(DataWithAxes, SerializableFactory().get_apply_deserializer(additional_payload[0]))
|
|
112
|
+
else:
|
|
113
|
+
return value
|
|
75
114
|
|
|
76
115
|
# generic commands
|
|
77
|
-
def set_info(self,
|
|
78
|
-
|
|
116
|
+
def set_info(self,
|
|
117
|
+
parameter: Optional[Union[float, str]],
|
|
118
|
+
additional_payload: Optional[List[bytes]] = None,
|
|
119
|
+
) -> None:
|
|
120
|
+
param: ParameterWithPath = SerializableFactory().get_apply_deserializer(additional_payload[0])
|
|
121
|
+
self.signals.cmd_signal.emit(ThreadCommand(LECOCommands.SET_INFO, attribute=param))
|
|
122
|
+
|
|
123
|
+
def get_settings(self):
|
|
124
|
+
self.signals.cmd_signal.emit(ThreadCommand(LECOCommands.GET_SETTINGS))
|
|
79
125
|
|
|
80
126
|
# detector commands
|
|
81
|
-
def
|
|
82
|
-
self.signals.cmd_signal.emit(ThreadCommand(
|
|
127
|
+
def send_data_grab(self,) -> None:
|
|
128
|
+
self.signals.cmd_signal.emit(ThreadCommand(LECOViewerCommands.GRAB))
|
|
83
129
|
|
|
84
|
-
#
|
|
85
|
-
def
|
|
86
|
-
|
|
87
|
-
self.signals.cmd_signal.emit(ThreadCommand("move_abs", attribute=[pos]))
|
|
130
|
+
# detector commands
|
|
131
|
+
def send_data_snap(self,) -> None:
|
|
132
|
+
self.signals.cmd_signal.emit(ThreadCommand(LECOViewerCommands.SNAP))
|
|
88
133
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
self
|
|
134
|
+
# actuator commands
|
|
135
|
+
def move_abs(
|
|
136
|
+
self,
|
|
137
|
+
position: Optional[Union[float, str]],
|
|
138
|
+
additional_payload: Optional[List[bytes]] = None,
|
|
139
|
+
) -> None:
|
|
140
|
+
"""Move to an absolute position.
|
|
141
|
+
|
|
142
|
+
:param position: Deprecated, should be None and content transferred binary.
|
|
143
|
+
:param additional_payload: binary frames containing the position as PyMoDAQ `DataActuator`.
|
|
144
|
+
"""
|
|
145
|
+
pos = self.extract_pymodaq_object(position, additional_payload)
|
|
146
|
+
self.signals.cmd_signal.emit(ThreadCommand(LECOMoveCommands.MOVE_ABS, pos))
|
|
147
|
+
|
|
148
|
+
def move_rel(
|
|
149
|
+
self,
|
|
150
|
+
position: Optional[Union[float, str]],
|
|
151
|
+
additional_payload: Optional[List[bytes]] = None,
|
|
152
|
+
) -> None:
|
|
153
|
+
"""Move by a relative position.
|
|
154
|
+
|
|
155
|
+
:param position: Deprecated, should be None and content transferred binary.
|
|
156
|
+
:param additional_payload: binary frames containing the position as PyMoDAQ `DataActuator`.
|
|
157
|
+
"""
|
|
158
|
+
pos = self.extract_pymodaq_object(position, additional_payload)
|
|
159
|
+
self.signals.cmd_signal.emit(ThreadCommand(LECOMoveCommands.MOVE_REL, pos))
|
|
92
160
|
|
|
93
161
|
def move_home(self) -> None:
|
|
94
|
-
self.signals.cmd_signal.emit(ThreadCommand(
|
|
162
|
+
self.signals.cmd_signal.emit(ThreadCommand(LECOMoveCommands.MOVE_HOME))
|
|
95
163
|
|
|
96
164
|
def get_actuator_value(self) -> None:
|
|
97
165
|
"""Request that the actuator value is sent later on."""
|
|
98
166
|
# according to DAQ_Move, this supersedes "check_position"
|
|
99
|
-
self.signals.cmd_signal.emit(ThreadCommand(
|
|
167
|
+
self.signals.cmd_signal.emit(ThreadCommand(LECOMoveCommands.GET_ACTUATOR_VALUE))
|
|
100
168
|
|
|
101
169
|
def stop_motion(self,) -> None:
|
|
102
|
-
|
|
103
|
-
|
|
170
|
+
self.signals.cmd_signal.emit(ThreadCommand(LECOMoveCommands.STOP))
|
|
171
|
+
|
|
172
|
+
def stop_grab(self,) -> None:
|
|
173
|
+
self.signals.cmd_signal.emit(ThreadCommand(LECOViewerCommands.STOP))
|
|
104
174
|
|
|
105
175
|
|
|
106
176
|
# to be able to separate them later on
|
|
@@ -182,7 +252,6 @@ class ActorListener(PymodaqListener):
|
|
|
182
252
|
"""Define what the name of the remote for answers is."""
|
|
183
253
|
self.remote_name = name
|
|
184
254
|
|
|
185
|
-
# @Slot(ThreadCommand)
|
|
186
255
|
def queue_command(self, command: ThreadCommand) -> None:
|
|
187
256
|
"""Queue a command to send it via LECO to the server."""
|
|
188
257
|
|
|
@@ -203,15 +272,7 @@ class ActorListener(PymodaqListener):
|
|
|
203
272
|
finally:
|
|
204
273
|
self.cmd_signal.emit(ThreadCommand('disconnected'))
|
|
205
274
|
|
|
206
|
-
elif command.command == 'update_connection':
|
|
207
|
-
# self.ipaddress = command.attribute['ipaddress']
|
|
208
|
-
# self.port = command.attribute['port']
|
|
209
|
-
pass # TODO change name?
|
|
210
|
-
|
|
211
275
|
elif command.command == LECOViewerCommands.DATA_READY:
|
|
212
|
-
# code from the original:
|
|
213
|
-
# self.data_ready(data=command.attribute)
|
|
214
|
-
# def data_ready(data): self.send_data(datas[0]['data'])
|
|
215
276
|
value = command.attribute # type: ignore
|
|
216
277
|
self.communicator.ask_rpc(
|
|
217
278
|
receiver=self.remote_name,
|
|
@@ -219,52 +280,41 @@ class ActorListener(PymodaqListener):
|
|
|
219
280
|
**binary_serialization_to_kwargs(value),
|
|
220
281
|
)
|
|
221
282
|
|
|
222
|
-
elif command.command ==
|
|
223
|
-
path = command.attribute['path'] # type: ignore
|
|
224
|
-
param = command.attribute['param'] # type: ignore
|
|
283
|
+
elif command.command == LECOCommands.SEND_INFO:
|
|
225
284
|
self.communicator.ask_rpc(
|
|
226
285
|
receiver=self.remote_name,
|
|
227
286
|
method="set_info",
|
|
228
|
-
|
|
229
|
-
param_dict_str=ioxml.parameter_to_xml_string(param).decode())
|
|
287
|
+
**binary_serialization_to_kwargs(command.attribute, data_key='parameter'))
|
|
230
288
|
|
|
231
289
|
elif command.command == LECOMoveCommands.POSITION:
|
|
232
|
-
value = command.attribute
|
|
290
|
+
value = command.attribute
|
|
291
|
+
if isinstance(value, (list, tuple)):
|
|
292
|
+
value = value[0] # for backward compatibility with attributes list
|
|
233
293
|
self.communicator.ask_rpc(receiver=self.remote_name,
|
|
234
|
-
method="
|
|
235
|
-
**binary_serialization_to_kwargs(value, data_key="position"),
|
|
294
|
+
method="send_position",
|
|
295
|
+
**binary_serialization_to_kwargs(pymodaq_object=value, data_key="position"),
|
|
236
296
|
)
|
|
237
297
|
|
|
238
298
|
elif command.command == LECOMoveCommands.MOVE_DONE:
|
|
239
|
-
value = command.attribute
|
|
299
|
+
value = command.attribute
|
|
300
|
+
if isinstance(value, (list, tuple)):
|
|
301
|
+
value = value[0] # for backward compatibility with attributes list
|
|
240
302
|
self.communicator.ask_rpc(receiver=self.remote_name,
|
|
241
303
|
method="set_move_done",
|
|
242
304
|
**binary_serialization_to_kwargs(value, data_key="position"),
|
|
243
305
|
)
|
|
244
306
|
|
|
245
|
-
elif command.command ==
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
elif command.command == 'y_axis':
|
|
258
|
-
value = command.attribute[0] # type: ignore
|
|
259
|
-
if isinstance(value, SERIALIZABLE):
|
|
260
|
-
self.communicator.ask_rpc(receiver=self.remote_name,
|
|
261
|
-
method="set_y_axis",
|
|
262
|
-
**binary_serialization_to_kwargs(value),
|
|
263
|
-
)
|
|
264
|
-
elif isinstance(value, dict):
|
|
265
|
-
self.communicator.ask_rpc(receiver=self.remote_name, method="set_y_axis", **value)
|
|
266
|
-
else:
|
|
267
|
-
raise ValueError("Nothing to send!")
|
|
307
|
+
elif command.command == LECOMoveCommands.UNITS_CHANGED:
|
|
308
|
+
units: str = command.attribute
|
|
309
|
+
self.communicator.ask_rpc(receiver=self.remote_name,
|
|
310
|
+
method="set_units",
|
|
311
|
+
units=units.encode(),
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
elif command.command == LECOCommands.SET_SETTINGS:
|
|
315
|
+
self.communicator.ask_rpc(receiver=self.remote_name,
|
|
316
|
+
method='set_settings',
|
|
317
|
+
settings=command.attribute.decode())
|
|
268
318
|
|
|
269
319
|
else:
|
|
270
320
|
raise IOError('Unknown TCP client command')
|