pymodaq 4.1.5__py3-none-any.whl → 4.2.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 +41 -4
- pymodaq/control_modules/daq_move.py +32 -73
- pymodaq/control_modules/daq_viewer.py +73 -98
- pymodaq/control_modules/daq_viewer_ui.py +2 -1
- pymodaq/control_modules/move_utility_classes.py +17 -7
- pymodaq/control_modules/utils.py +153 -5
- pymodaq/control_modules/viewer_utility_classes.py +31 -20
- pymodaq/dashboard.py +23 -5
- pymodaq/examples/tcp_client.py +97 -0
- pymodaq/extensions/__init__.py +4 -0
- pymodaq/extensions/bayesian/__init__.py +2 -0
- pymodaq/extensions/bayesian/bayesian_optimisation.py +673 -0
- pymodaq/extensions/bayesian/utils.py +403 -0
- pymodaq/extensions/daq_scan.py +4 -4
- pymodaq/extensions/daq_scan_ui.py +2 -1
- pymodaq/extensions/pid/pid_controller.py +12 -7
- pymodaq/extensions/pid/utils.py +9 -26
- pymodaq/extensions/utils.py +3 -0
- pymodaq/post_treatment/load_and_plot.py +42 -19
- pymodaq/resources/VERSION +1 -1
- pymodaq/resources/config_template.toml +9 -24
- pymodaq/resources/setup_plugin.py +1 -1
- pymodaq/utils/config.py +103 -5
- pymodaq/utils/daq_utils.py +35 -134
- pymodaq/utils/data.py +614 -95
- pymodaq/utils/enums.py +17 -1
- pymodaq/utils/factory.py +2 -2
- pymodaq/utils/gui_utils/custom_app.py +5 -2
- pymodaq/utils/gui_utils/dock.py +33 -4
- pymodaq/utils/gui_utils/utils.py +14 -1
- pymodaq/utils/h5modules/backends.py +9 -1
- pymodaq/utils/h5modules/data_saving.py +254 -57
- pymodaq/utils/h5modules/saving.py +1 -0
- pymodaq/utils/leco/daq_move_LECODirector.py +172 -0
- pymodaq/utils/leco/daq_xDviewer_LECODirector.py +170 -0
- pymodaq/utils/leco/desktop.ini +2 -0
- pymodaq/utils/leco/director_utils.py +58 -0
- pymodaq/utils/leco/leco_director.py +88 -0
- pymodaq/utils/leco/pymodaq_listener.py +279 -0
- pymodaq/utils/leco/utils.py +41 -0
- pymodaq/utils/managers/action_manager.py +20 -6
- pymodaq/utils/managers/parameter_manager.py +6 -4
- pymodaq/utils/managers/roi_manager.py +63 -54
- pymodaq/utils/math_utils.py +1 -1
- pymodaq/utils/plotting/data_viewers/__init__.py +3 -1
- pymodaq/utils/plotting/data_viewers/base.py +286 -0
- pymodaq/utils/plotting/data_viewers/viewer.py +29 -202
- pymodaq/utils/plotting/data_viewers/viewer0D.py +94 -47
- pymodaq/utils/plotting/data_viewers/viewer1D.py +341 -174
- pymodaq/utils/plotting/data_viewers/viewer1Dbasic.py +1 -1
- pymodaq/utils/plotting/data_viewers/viewer2D.py +271 -181
- pymodaq/utils/plotting/data_viewers/viewerND.py +26 -22
- pymodaq/utils/plotting/items/crosshair.py +3 -3
- pymodaq/utils/plotting/items/image.py +2 -1
- pymodaq/utils/plotting/plotter/plotter.py +94 -0
- pymodaq/utils/plotting/plotter/plotters/__init__.py +0 -0
- pymodaq/utils/plotting/plotter/plotters/matplotlib_plotters.py +134 -0
- pymodaq/utils/plotting/plotter/plotters/qt_plotters.py +78 -0
- pymodaq/utils/plotting/utils/axes_viewer.py +1 -1
- pymodaq/utils/plotting/utils/filter.py +194 -147
- pymodaq/utils/plotting/utils/lineout.py +13 -11
- pymodaq/utils/plotting/utils/plot_utils.py +89 -12
- pymodaq/utils/scanner/__init__.py +0 -3
- pymodaq/utils/scanner/scan_config.py +1 -9
- pymodaq/utils/scanner/scan_factory.py +10 -36
- pymodaq/utils/scanner/scanner.py +3 -2
- pymodaq/utils/scanner/scanners/_1d_scanners.py +7 -5
- pymodaq/utils/scanner/scanners/_2d_scanners.py +36 -49
- pymodaq/utils/scanner/scanners/sequential.py +10 -4
- pymodaq/utils/scanner/scanners/tabular.py +10 -5
- pymodaq/utils/slicing.py +1 -1
- pymodaq/utils/tcp_ip/serializer.py +38 -5
- pymodaq/utils/tcp_ip/tcp_server_client.py +25 -17
- {pymodaq-4.1.5.dist-info → pymodaq-4.2.0.dist-info}/METADATA +4 -2
- {pymodaq-4.1.5.dist-info → pymodaq-4.2.0.dist-info}/RECORD +78 -63
- pymodaq/resources/config_scan_template.toml +0 -42
- {pymodaq-4.1.5.dist-info → pymodaq-4.2.0.dist-info}/WHEEL +0 -0
- {pymodaq-4.1.5.dist-info → pymodaq-4.2.0.dist-info}/entry_points.txt +0 -0
- {pymodaq-4.1.5.dist-info → pymodaq-4.2.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"""
|
|
2
|
+
LECO Director instrument plugin are to be used to communicate (and control) remotely real
|
|
3
|
+
instrument plugin through TCP/IP using the LECO Protocol
|
|
4
|
+
|
|
5
|
+
For this to work a coordinator must be instantiated can be done within the dashboard or directly
|
|
6
|
+
running: `python -m pyleco.coordinators.coordinator`
|
|
7
|
+
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from typing import Union
|
|
11
|
+
|
|
12
|
+
from pymodaq.control_modules.move_utility_classes import (DAQ_Move_base, comon_parameters_fun, main,
|
|
13
|
+
DataActuatorType, DataActuator)
|
|
14
|
+
|
|
15
|
+
from pymodaq.utils.daq_utils import ThreadCommand
|
|
16
|
+
from pymodaq.utils.parameter import Parameter
|
|
17
|
+
|
|
18
|
+
from pymodaq.utils.leco.leco_director import LECODirector, leco_parameters
|
|
19
|
+
from pymodaq.utils.leco.director_utils import ActuatorDirector
|
|
20
|
+
from pymodaq.utils.tcp_ip.serializer import DeSerializer
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class DAQ_Move_LECODirector(LECODirector, DAQ_Move_base):
|
|
24
|
+
"""A control module, which in the dashboard, allows to control a remote Move module.
|
|
25
|
+
|
|
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
|
|
37
|
+
"""
|
|
38
|
+
settings: Parameter
|
|
39
|
+
controller: ActuatorDirector
|
|
40
|
+
|
|
41
|
+
is_multiaxes = False
|
|
42
|
+
axes_names = []
|
|
43
|
+
params_client = [] # parameters of a client grabber
|
|
44
|
+
data_actuator_type = DataActuatorType['float'] # DataActuatorType['DataActuator']
|
|
45
|
+
|
|
46
|
+
message_list = LECODirector.message_list + ["move_abs", 'move_home', 'move_rel',
|
|
47
|
+
'get_actuator_value', 'stop_motion', 'position_is',
|
|
48
|
+
'move_done']
|
|
49
|
+
socket_types = ["ACTUATOR"]
|
|
50
|
+
params = [
|
|
51
|
+
] + comon_parameters_fun(is_multiaxes=is_multiaxes, axes_names=axes_names) + leco_parameters
|
|
52
|
+
|
|
53
|
+
def __init__(self, parent=None, params_state=None, **kwargs) -> None:
|
|
54
|
+
super().__init__(parent=parent,
|
|
55
|
+
params_state=params_state, **kwargs)
|
|
56
|
+
self.register_rpc_methods((
|
|
57
|
+
self.set_info,
|
|
58
|
+
self.set_position,
|
|
59
|
+
self.set_move_done,
|
|
60
|
+
self.set_x_axis,
|
|
61
|
+
self.set_y_axis,
|
|
62
|
+
))
|
|
63
|
+
|
|
64
|
+
# copied, I think it is good:
|
|
65
|
+
self.settings.child('bounds').hide()
|
|
66
|
+
self.settings.child('scaling').hide()
|
|
67
|
+
self.settings.child('epsilon').setValue(1)
|
|
68
|
+
|
|
69
|
+
def commit_settings(self, param) -> None:
|
|
70
|
+
self.commit_leco_settings(param=param)
|
|
71
|
+
|
|
72
|
+
def ini_stage(self, controller=None):
|
|
73
|
+
"""Actuator communication initialization
|
|
74
|
+
|
|
75
|
+
Parameters
|
|
76
|
+
----------
|
|
77
|
+
controller: (object)
|
|
78
|
+
custom object of a PyMoDAQ plugin (Slave case). None if only one actuator by controller
|
|
79
|
+
(Master case)
|
|
80
|
+
|
|
81
|
+
Returns
|
|
82
|
+
-------
|
|
83
|
+
info: str
|
|
84
|
+
initialized: bool
|
|
85
|
+
False if initialization failed otherwise True
|
|
86
|
+
"""
|
|
87
|
+
actor_name = self.settings.child("actor_name").value()
|
|
88
|
+
self.controller = self.ini_stage_init( # type: ignore
|
|
89
|
+
old_controller=controller,
|
|
90
|
+
new_controller=ActuatorDirector(actor=actor_name, communicator=self.communicator),
|
|
91
|
+
)
|
|
92
|
+
try:
|
|
93
|
+
self.controller.set_remote_name(self.communicator.full_name) # type: ignore
|
|
94
|
+
except TimeoutError:
|
|
95
|
+
print("Timeout setting remote name.") # TODO change to real logging
|
|
96
|
+
# self.settings.child('infos').addChildren(self.params_client)
|
|
97
|
+
|
|
98
|
+
self.settings.child('units').hide()
|
|
99
|
+
self.settings.child('epsilon').hide()
|
|
100
|
+
|
|
101
|
+
self.status.info = "LECODirector"
|
|
102
|
+
self.status.controller = self.controller
|
|
103
|
+
self.status.initialized = True
|
|
104
|
+
return self.status
|
|
105
|
+
|
|
106
|
+
def move_abs(self, position: DataActuator) -> None:
|
|
107
|
+
position = self.check_bound(position)
|
|
108
|
+
position = self.set_position_with_scaling(position)
|
|
109
|
+
|
|
110
|
+
self.controller.move_abs(position=position)
|
|
111
|
+
|
|
112
|
+
self.target_value = position
|
|
113
|
+
|
|
114
|
+
def move_rel(self, position: DataActuator) -> None:
|
|
115
|
+
position = self.check_bound(self.current_value + position) - self.current_value # type: ignore # noqa
|
|
116
|
+
self.target_value = position + self.current_value
|
|
117
|
+
|
|
118
|
+
position = self.set_position_relative_with_scaling(position)
|
|
119
|
+
self.controller.move_rel(position=position)
|
|
120
|
+
|
|
121
|
+
def move_home(self):
|
|
122
|
+
self.controller.move_home()
|
|
123
|
+
|
|
124
|
+
def get_actuator_value(self) -> DataActuator:
|
|
125
|
+
"""
|
|
126
|
+
Get the current hardware position with scaling conversion given by
|
|
127
|
+
`get_position_with_scaling`.
|
|
128
|
+
|
|
129
|
+
See Also
|
|
130
|
+
--------
|
|
131
|
+
daq_move_base.get_position_with_scaling, daq_utils.ThreadCommand
|
|
132
|
+
"""
|
|
133
|
+
self.controller.set_remote_name(self.communicator.full_name) # to ensure communication
|
|
134
|
+
self.controller.get_actuator_value()
|
|
135
|
+
return self._current_value
|
|
136
|
+
|
|
137
|
+
def stop_motion(self) -> None:
|
|
138
|
+
"""
|
|
139
|
+
See Also
|
|
140
|
+
--------
|
|
141
|
+
daq_move_base.move_done
|
|
142
|
+
"""
|
|
143
|
+
self.controller.stop_motion()
|
|
144
|
+
|
|
145
|
+
# Methods accessible via remote calls
|
|
146
|
+
def _set_position_value(self, position: Union[str, float]) -> DataActuator:
|
|
147
|
+
if isinstance(position, str):
|
|
148
|
+
deserializer = DeSerializer.from_b64_string(position)
|
|
149
|
+
pos = deserializer.dwa_deserialization()
|
|
150
|
+
else:
|
|
151
|
+
pos = DataActuator(data=position)
|
|
152
|
+
pos = self.get_position_with_scaling(pos) # type: ignore
|
|
153
|
+
self._current_value = pos
|
|
154
|
+
return pos
|
|
155
|
+
|
|
156
|
+
def set_position(self, position: Union[str, float]) -> None:
|
|
157
|
+
pos = self._set_position_value(position=position)
|
|
158
|
+
self.emit_status(ThreadCommand('get_actuator_value', [pos]))
|
|
159
|
+
|
|
160
|
+
def set_move_done(self, position: Union[str, float]) -> None:
|
|
161
|
+
pos = self._set_position_value(position=position)
|
|
162
|
+
self.emit_status(ThreadCommand('move_done', [pos]))
|
|
163
|
+
|
|
164
|
+
def set_x_axis(self, data, label: str = "", units: str = "") -> None:
|
|
165
|
+
raise NotImplementedError("where is it handled?")
|
|
166
|
+
|
|
167
|
+
def set_y_axis(self, data, label: str = "", units: str = "") -> None:
|
|
168
|
+
raise NotImplementedError("where is it handled?")
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
if __name__ == '__main__':
|
|
172
|
+
main(__file__)
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
|
|
2
|
+
from typing import Union
|
|
3
|
+
|
|
4
|
+
from easydict import EasyDict as edict
|
|
5
|
+
|
|
6
|
+
from pymodaq.control_modules.viewer_utility_classes import DAQ_Viewer_base, comon_parameters, main
|
|
7
|
+
|
|
8
|
+
from pymodaq.utils.daq_utils import ThreadCommand, getLineInfo
|
|
9
|
+
from pymodaq.utils.parameter import Parameter
|
|
10
|
+
from pymodaq.utils.tcp_ip.serializer import DeSerializer
|
|
11
|
+
|
|
12
|
+
from pymodaq.utils.leco.leco_director import LECODirector, leco_parameters
|
|
13
|
+
from pymodaq.utils.leco.director_utils import DetectorDirector
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class DAQ_xDViewer_LECODirector(LECODirector, DAQ_Viewer_base):
|
|
17
|
+
"""A control module, which in the dashboard, allows to control a remote Viewer module.
|
|
18
|
+
|
|
19
|
+
This is the base class for the viewer LECO director modules.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
settings: Parameter
|
|
23
|
+
controller: DetectorDirector
|
|
24
|
+
|
|
25
|
+
params_GRABBER = []
|
|
26
|
+
|
|
27
|
+
message_list = LECODirector.message_list + ["Quit", "Send Data 0D", "Send Data 1D",
|
|
28
|
+
"Send Data 2D", "Send Data ND",
|
|
29
|
+
"Status", "Done", "Server Closed",
|
|
30
|
+
"Info", "Infos", "Info_xml", 'x_axis', 'y_axis']
|
|
31
|
+
socket_types = ["GRABBER"]
|
|
32
|
+
params = [
|
|
33
|
+
] + comon_parameters + leco_parameters
|
|
34
|
+
|
|
35
|
+
def __init__(self, parent=None, params_state=None, grabber_type: str = "0D", **kwargs) -> None:
|
|
36
|
+
super().__init__(parent=parent, params_state=params_state, **kwargs)
|
|
37
|
+
self.register_rpc_methods((
|
|
38
|
+
self.set_x_axis,
|
|
39
|
+
self.set_y_axis,
|
|
40
|
+
self.set_data,
|
|
41
|
+
))
|
|
42
|
+
|
|
43
|
+
self.client_type = "GRABBER"
|
|
44
|
+
self.x_axis = None
|
|
45
|
+
self.y_axis = None
|
|
46
|
+
self.data = None
|
|
47
|
+
self.grabber_type = grabber_type
|
|
48
|
+
self.ind_data = 0
|
|
49
|
+
self.data_mock = None
|
|
50
|
+
|
|
51
|
+
def ini_detector(self, controller=None):
|
|
52
|
+
"""
|
|
53
|
+
| Initialisation procedure of the detector updating the status dictionary.
|
|
54
|
+
|
|
|
55
|
+
| Init axes from image , here returns only None values (to tricky to di it with the
|
|
56
|
+
server and not really necessary for images anyway)
|
|
57
|
+
|
|
58
|
+
See Also
|
|
59
|
+
--------
|
|
60
|
+
utility_classes.DAQ_TCP_server.init_server, get_xaxis, get_yaxis
|
|
61
|
+
"""
|
|
62
|
+
self.status.update(edict(initialized=False, info="", x_axis=None, y_axis=None,
|
|
63
|
+
controller=None))
|
|
64
|
+
actor_name = self.settings.child("actor_name").value()
|
|
65
|
+
self.controller = self.ini_detector_init( # type: ignore
|
|
66
|
+
old_controller=controller,
|
|
67
|
+
new_controller=DetectorDirector(actor=actor_name, communicator=self.communicator),
|
|
68
|
+
)
|
|
69
|
+
self.controller.set_remote_name(self.communicator.full_name) # type: ignore
|
|
70
|
+
try:
|
|
71
|
+
# self.settings.child(('infos')).addChildren(self.params_GRABBER)
|
|
72
|
+
|
|
73
|
+
# init axes from image , here returns only None values (to tricky to di it with the
|
|
74
|
+
# server and not really necessary for images anyway)
|
|
75
|
+
self.x_axis = self.get_xaxis()
|
|
76
|
+
self.y_axis = self.get_yaxis()
|
|
77
|
+
self.status.x_axis = self.x_axis
|
|
78
|
+
self.status.y_axis = self.y_axis
|
|
79
|
+
self.status.initialized = True
|
|
80
|
+
return self.status
|
|
81
|
+
|
|
82
|
+
except Exception as e:
|
|
83
|
+
self.status.info = getLineInfo() + str(e)
|
|
84
|
+
self.status.initialized = False
|
|
85
|
+
return self.status
|
|
86
|
+
|
|
87
|
+
def get_xaxis(self):
|
|
88
|
+
"""
|
|
89
|
+
Obtain the horizontal axis of the image.
|
|
90
|
+
|
|
91
|
+
Returns
|
|
92
|
+
-------
|
|
93
|
+
1D numpy array
|
|
94
|
+
Contains a vector of integer corresponding to the horizontal camera pixels.
|
|
95
|
+
"""
|
|
96
|
+
pass
|
|
97
|
+
return self.x_axis
|
|
98
|
+
|
|
99
|
+
def get_yaxis(self):
|
|
100
|
+
"""
|
|
101
|
+
Obtain the vertical axis of the image.
|
|
102
|
+
|
|
103
|
+
Returns
|
|
104
|
+
-------
|
|
105
|
+
1D numpy array
|
|
106
|
+
Contains a vector of integer corresponding to the vertical camera pixels.
|
|
107
|
+
"""
|
|
108
|
+
pass
|
|
109
|
+
return self.y_axis
|
|
110
|
+
|
|
111
|
+
def grab_data(self, Naverage=1, **kwargs):
|
|
112
|
+
"""
|
|
113
|
+
Start new acquisition.
|
|
114
|
+
Grabbed indice is used to keep track of the current image in the average.
|
|
115
|
+
|
|
116
|
+
============== ========== ==============================
|
|
117
|
+
**Parameters** **Type** **Description**
|
|
118
|
+
|
|
119
|
+
*Naverage* int Number of images to average
|
|
120
|
+
============== ========== ==============================
|
|
121
|
+
|
|
122
|
+
See Also
|
|
123
|
+
--------
|
|
124
|
+
utility_classes.DAQ_TCP_server.process_cmds
|
|
125
|
+
"""
|
|
126
|
+
try:
|
|
127
|
+
self.ind_grabbed = 0 # to keep track of the current image in the average
|
|
128
|
+
self.Naverage = Naverage
|
|
129
|
+
self.controller.set_remote_name(self.communicator.full_name)
|
|
130
|
+
self.controller.send_data(grabber_type=self.grabber_type)
|
|
131
|
+
|
|
132
|
+
except Exception as e:
|
|
133
|
+
self.emit_status(ThreadCommand('Update_Status', [getLineInfo() + str(e), "log"]))
|
|
134
|
+
|
|
135
|
+
def stop(self):
|
|
136
|
+
"""
|
|
137
|
+
not implemented.
|
|
138
|
+
"""
|
|
139
|
+
pass
|
|
140
|
+
return ""
|
|
141
|
+
|
|
142
|
+
# Methods for RPC calls
|
|
143
|
+
def set_x_axis(self, data, label: str = "", units: str = ""):
|
|
144
|
+
# TODO make to work
|
|
145
|
+
self.x_axis = dict(data=data, label=label, units=units)
|
|
146
|
+
self.emit_x_axis()
|
|
147
|
+
|
|
148
|
+
def set_y_axis(self, data, label: str = "", units: str = ""):
|
|
149
|
+
# TODO make to work
|
|
150
|
+
self.y_axis = dict(data=data, label=label, units=units)
|
|
151
|
+
self.emit_y_axis()
|
|
152
|
+
|
|
153
|
+
def set_data(self, data: Union[list, str]) -> None:
|
|
154
|
+
"""
|
|
155
|
+
Set the grabbed data signal.
|
|
156
|
+
|
|
157
|
+
corresponds to the "data_ready" signal
|
|
158
|
+
|
|
159
|
+
:param data: If None, look for the additional object
|
|
160
|
+
"""
|
|
161
|
+
if isinstance(data, str):
|
|
162
|
+
deserializer = DeSerializer.from_b64_string(data)
|
|
163
|
+
dte = deserializer.dte_deserialization()
|
|
164
|
+
self.dte_signal.emit(dte)
|
|
165
|
+
else:
|
|
166
|
+
raise NotImplementedError("Not implemented to set a list of values.")
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
if __name__ == '__main__':
|
|
170
|
+
main(__file__)
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Utils for the Director Modules
|
|
3
|
+
|
|
4
|
+
These directors correspond to the PymodaqListener
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Optional, Union, List
|
|
8
|
+
|
|
9
|
+
from pyleco.directors.director import Director
|
|
10
|
+
|
|
11
|
+
import pymodaq.utils.parameter.utils as putils
|
|
12
|
+
from pymodaq.utils.parameter import Parameter, ioxml
|
|
13
|
+
from pymodaq.control_modules.move_utility_classes import DataActuator
|
|
14
|
+
from pymodaq.utils.leco.utils import serialize_object
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class GenericDirector(Director):
|
|
18
|
+
"""Director helper to control some Module remotely."""
|
|
19
|
+
|
|
20
|
+
def set_remote_name(self, name: Optional[str] = None):
|
|
21
|
+
"""Set the remote name of the Module (i.e. where it should send responses to)."""
|
|
22
|
+
self.ask_rpc(method="set_remote_name", name=name or self.communicator.name)
|
|
23
|
+
|
|
24
|
+
def set_info(self, param: Parameter):
|
|
25
|
+
# It removes the first two parts (main_settings and detector_settings?)
|
|
26
|
+
self.set_info_str(path=putils.get_param_path(param)[2:],
|
|
27
|
+
param_dict_str=ioxml.parameter_to_xml_string(param).decode())
|
|
28
|
+
|
|
29
|
+
def set_info_str(self, path: List[str], param_dict_str: str) -> None:
|
|
30
|
+
self.ask_rpc(method="sef_info", path=path, param_dict_str=param_dict_str)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class DetectorDirector(GenericDirector):
|
|
34
|
+
def send_data(self, grabber_type: str = "") -> None:
|
|
35
|
+
self.ask_rpc("send_data", grabber_type=grabber_type)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class ActuatorDirector(GenericDirector):
|
|
39
|
+
def move_abs(self, position: Union[float, DataActuator]) -> None:
|
|
40
|
+
self.ask_rpc("move_abs", position=serialize_object(position))
|
|
41
|
+
|
|
42
|
+
def move_rel(self, position: Union[float, DataActuator]) -> None:
|
|
43
|
+
self.ask_rpc("move_rel", position=serialize_object(position))
|
|
44
|
+
|
|
45
|
+
def move_home(self) -> None:
|
|
46
|
+
self.ask_rpc("move_home")
|
|
47
|
+
|
|
48
|
+
def get_actuator_value(self) -> None:
|
|
49
|
+
"""Request that the actuator value is sent later on.
|
|
50
|
+
|
|
51
|
+
Later the `set_data` method will be called.
|
|
52
|
+
"""
|
|
53
|
+
# according to DAQ_Move, this supersedes "check_position"
|
|
54
|
+
self.ask_rpc("get_actuator_value")
|
|
55
|
+
|
|
56
|
+
def stop_motion(self,) -> None:
|
|
57
|
+
# not implemented in DAQ_Move!
|
|
58
|
+
self.ask_rpc("stop_motion")
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
|
|
2
|
+
import random
|
|
3
|
+
|
|
4
|
+
from typing import Callable, Sequence, List
|
|
5
|
+
|
|
6
|
+
import pymodaq.utils.parameter.utils as putils
|
|
7
|
+
# object used to send info back to the main thread:
|
|
8
|
+
from pymodaq.utils.daq_utils import ThreadCommand
|
|
9
|
+
from pymodaq.utils.parameter import Parameter
|
|
10
|
+
|
|
11
|
+
from pymodaq.utils.leco.director_utils import GenericDirector
|
|
12
|
+
from pymodaq.utils.leco.pymodaq_listener import PymodaqListener
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
leco_parameters = [
|
|
16
|
+
{'title': 'Actor name:', 'name': 'actor_name', 'type': 'str', 'value': "actor_name",
|
|
17
|
+
'text': 'Name of the actor plugin to communicate with.'},
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class LECODirector:
|
|
22
|
+
"""
|
|
23
|
+
This is a mixin for a Control module to direct another, remote module (analogous to TCP Server).
|
|
24
|
+
|
|
25
|
+
================= ==============================
|
|
26
|
+
**Attributes** **Type**
|
|
27
|
+
*command_server* instance of Signal
|
|
28
|
+
*x_axis* 1D numpy array
|
|
29
|
+
*y_axis* 1D numpy array
|
|
30
|
+
*data* double precision float array
|
|
31
|
+
================= ==============================
|
|
32
|
+
|
|
33
|
+
See Also
|
|
34
|
+
--------
|
|
35
|
+
utility_classes.DAQ_TCP_server
|
|
36
|
+
"""
|
|
37
|
+
message_list = ["Quit", "Status", "Done", "Server Closed", "Info", "Infos", "Info_xml",
|
|
38
|
+
"move_abs", 'move_home', 'move_rel', 'get_actuator_value', 'stop_motion',
|
|
39
|
+
'position_is', 'move_done',
|
|
40
|
+
]
|
|
41
|
+
socket_types: List[str]
|
|
42
|
+
|
|
43
|
+
controller: GenericDirector
|
|
44
|
+
settings: Parameter
|
|
45
|
+
|
|
46
|
+
def __init__(self, **kwargs) -> None:
|
|
47
|
+
super().__init__(**kwargs)
|
|
48
|
+
|
|
49
|
+
name = f'{self._title}_{random.randrange(0, 10000)}_director'
|
|
50
|
+
# TODO use the same Listener instance as the LECOActorModule
|
|
51
|
+
self.listener = PymodaqListener(name=name)
|
|
52
|
+
self.listener.start_listen()
|
|
53
|
+
self.communicator = self.listener.get_communicator()
|
|
54
|
+
self.register_rpc_methods((
|
|
55
|
+
self.set_info,
|
|
56
|
+
))
|
|
57
|
+
|
|
58
|
+
def register_rpc_methods(self, methods: Sequence[Callable]) -> None:
|
|
59
|
+
for method in methods:
|
|
60
|
+
self.communicator.register_rpc_method(method=method)
|
|
61
|
+
|
|
62
|
+
def commit_settings(self, param: Parameter) -> None:
|
|
63
|
+
raise NotImplementedError
|
|
64
|
+
|
|
65
|
+
def commit_leco_settings(self, param: Parameter) -> None:
|
|
66
|
+
if param.name() == "actor_name":
|
|
67
|
+
self.controller.actor = param.value()
|
|
68
|
+
elif param.name() in putils.iter_children(self.settings.child('settings_client'), []):
|
|
69
|
+
self.controller.set_info(param=param)
|
|
70
|
+
|
|
71
|
+
def close(self) -> None:
|
|
72
|
+
self.listener.stop_listen()
|
|
73
|
+
|
|
74
|
+
def stop(self):
|
|
75
|
+
"""
|
|
76
|
+
not implemented.
|
|
77
|
+
"""
|
|
78
|
+
pass
|
|
79
|
+
return ""
|
|
80
|
+
|
|
81
|
+
def emit_status(self, status: ThreadCommand) -> None:
|
|
82
|
+
""" Emit the status_sig signal with the given status ThreadCommand back to the main GUI.
|
|
83
|
+
"""
|
|
84
|
+
super().emit_status(status=status) # type: ignore
|
|
85
|
+
|
|
86
|
+
# Methods accessible via remote calls
|
|
87
|
+
def set_info(self, path: List[str], param_dict_str: str) -> None:
|
|
88
|
+
self.emit_status(ThreadCommand("set_info", attribute=[path, param_dict_str]))
|