pymodaq 4.4.5__py3-none-any.whl → 4.4.7__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 +27 -8
- pymodaq/control_modules/move_utility_classes.py +10 -1
- pymodaq/examples/qt_less_standalone_module.py +128 -0
- pymodaq/resources/VERSION +1 -1
- pymodaq/resources/setup_plugin.py +1 -0
- pymodaq/utils/data.py +8 -0
- pymodaq/utils/leco/daq_move_LECODirector.py +20 -10
- pymodaq/utils/leco/daq_xDviewer_LECODirector.py +11 -6
- pymodaq/utils/leco/pymodaq_listener.py +6 -6
- pymodaq/utils/leco/utils.py +25 -1
- pymodaq/utils/managers/remote_manager.py +1 -1
- pymodaq/utils/tcp_ip/serializer.py +73 -40
- {pymodaq-4.4.5.dist-info → pymodaq-4.4.7.dist-info}/METADATA +2 -3
- {pymodaq-4.4.5.dist-info → pymodaq-4.4.7.dist-info}/RECORD +17 -16
- {pymodaq-4.4.5.dist-info → pymodaq-4.4.7.dist-info}/WHEEL +1 -1
- {pymodaq-4.4.5.dist-info → pymodaq-4.4.7.dist-info}/entry_points.txt +0 -0
- {pymodaq-4.4.5.dist-info → pymodaq-4.4.7.dist-info}/licenses/LICENSE +0 -0
|
@@ -595,14 +595,33 @@ class DAQ_Move(ParameterControlModule):
|
|
|
595
595
|
def units(self, unit: str):
|
|
596
596
|
self.settings.child('move_settings', 'units').setValue(unit)
|
|
597
597
|
if self.ui is not None and config('actuator', 'display_units'):
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
598
|
+
self.ui.set_unit_as_suffix(self.get_unit_to_display(unit))
|
|
599
|
+
|
|
600
|
+
@staticmethod
|
|
601
|
+
def get_unit_to_display(unit: str) -> str:
|
|
602
|
+
""" Get the unit to be displayed in the UI
|
|
603
|
+
|
|
604
|
+
If the controller units are in mm the displayed unit will be m
|
|
605
|
+
because m is the base unit, then the user could ask for mm, km, µm...
|
|
606
|
+
only issue is when the usual displayed unit is not the base one, then add cases below
|
|
607
|
+
|
|
608
|
+
Parameters
|
|
609
|
+
----------
|
|
610
|
+
unit: str
|
|
611
|
+
|
|
612
|
+
Returns
|
|
613
|
+
-------
|
|
614
|
+
str: the unit to be displayed on the ui
|
|
615
|
+
"""
|
|
616
|
+
if ('°' in unit or 'degree' in unit) and not '°C' in unit:
|
|
617
|
+
# special cas as pint base unit for angles are radians
|
|
618
|
+
return '°'
|
|
619
|
+
elif 'W' in unit or 'watt' in unit:
|
|
620
|
+
return 'W'
|
|
621
|
+
elif '°C' in unit or 'Celsius' in unit:
|
|
622
|
+
return '°C'
|
|
623
|
+
else:
|
|
624
|
+
return str(Q_(1, unit).to_base_units().units)
|
|
606
625
|
|
|
607
626
|
def update_settings(self):
|
|
608
627
|
|
|
@@ -25,6 +25,7 @@ from pymodaq.utils.enums import BaseEnum, enum_checker
|
|
|
25
25
|
from pymodaq.utils.tcp_ip.mysocket import Socket
|
|
26
26
|
from pymodaq.utils.tcp_ip.serializer import DeSerializer, Serializer
|
|
27
27
|
from pymodaq import Unit
|
|
28
|
+
from pint.errors import OffsetUnitCalculusError
|
|
28
29
|
|
|
29
30
|
if TYPE_CHECKING:
|
|
30
31
|
from pymodaq.control_modules.daq_move import DAQ_Move_Hardware
|
|
@@ -437,7 +438,8 @@ class DAQ_Move_base(QObject):
|
|
|
437
438
|
QtWidgets.QApplication.processEvents()
|
|
438
439
|
self.axis_unit = self.axis_unit
|
|
439
440
|
self.settings.child('epsilon').setValue(self.epsilon)
|
|
440
|
-
|
|
441
|
+
if self.controller is not None:
|
|
442
|
+
self._current_value = self.get_actuator_value()
|
|
441
443
|
|
|
442
444
|
@property
|
|
443
445
|
def axis_names(self) -> Union[List, Dict]:
|
|
@@ -728,6 +730,13 @@ class DAQ_Move_base(QObject):
|
|
|
728
730
|
epsilon_calculated = abs(self._current_value.value() - self._target_value.value())
|
|
729
731
|
logger.warning(f'Unit issue when calculating epsilon, units are not compatible between'
|
|
730
732
|
f'target and current values')
|
|
733
|
+
except OffsetUnitCalculusError as e:
|
|
734
|
+
if '°C' in self.axis_unit or 'celcius' in self.axis_unit.lower():
|
|
735
|
+
epsilon_calculated = (
|
|
736
|
+
self._current_value.to_base_units() -
|
|
737
|
+
self._target_value.to_base_units()).abs().value()
|
|
738
|
+
else:
|
|
739
|
+
raise e
|
|
731
740
|
|
|
732
741
|
return (epsilon_calculated < self.epsilon) and self.user_condition_to_reach_target()
|
|
733
742
|
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Example how to create an actuator or detector module, which does not require Qt, nor any GUI functionality.
|
|
3
|
+
|
|
4
|
+
You can connect to this qtless module with a PyMoDAQ LECODirector module (the detector or actuator version, both are preinstalled),
|
|
5
|
+
as if it were any pymodaq module.
|
|
6
|
+
|
|
7
|
+
This example works best with an Actuator Director Module as it has fake movements, but does not return any detector value.
|
|
8
|
+
In this example, the name is "qt_less" (defined in the final if clause), which you have to give as the "actor" argument to the Director module.
|
|
9
|
+
|
|
10
|
+
Add any code in the methods defined below, for example instrument access and execute the file.
|
|
11
|
+
For remote control, you need to start a Coordinator, as described for remote control via LECO.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import logging
|
|
15
|
+
from time import sleep
|
|
16
|
+
from typing import List, Union
|
|
17
|
+
|
|
18
|
+
from pyleco.utils.listener import Listener
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class QtLessModule:
|
|
22
|
+
"""Some module doing things without Qt.
|
|
23
|
+
|
|
24
|
+
You can run an instance of this class anywhere in your LECO network.
|
|
25
|
+
Then you can control this instance with a PyMoDAQ LECODirectorModule (in mock modules) as if it were a PyMoDAQ module.
|
|
26
|
+
|
|
27
|
+
Just add any logic you wish to the methods below.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
def __init__(self, name: str, host: str = "localhost", **kwargs) -> None:
|
|
31
|
+
super().__init__()
|
|
32
|
+
self.listener = Listener(name=name, host=host, timeout=1, **kwargs)
|
|
33
|
+
self._fake_position = 0
|
|
34
|
+
self.start_listen()
|
|
35
|
+
self._stored = []
|
|
36
|
+
|
|
37
|
+
def start_listen(self) -> None:
|
|
38
|
+
"""Start to listen on incoming commands."""
|
|
39
|
+
self.listener.start_listen()
|
|
40
|
+
self.communicator = self.listener.get_communicator()
|
|
41
|
+
self.register_rpc_methods()
|
|
42
|
+
|
|
43
|
+
def register_rpc_methods(self) -> None:
|
|
44
|
+
"""Make the following methods available via LECO."""
|
|
45
|
+
register_rpc_method = self.communicator.register_rpc_method
|
|
46
|
+
register_rpc_method(self.set_info)
|
|
47
|
+
register_rpc_method(self.send_data)
|
|
48
|
+
register_rpc_method(self.move_abs)
|
|
49
|
+
register_rpc_method(self.move_rel)
|
|
50
|
+
register_rpc_method(self.move_home)
|
|
51
|
+
register_rpc_method(self.get_actuator_value)
|
|
52
|
+
register_rpc_method(self.stop_motion)
|
|
53
|
+
register_rpc_method(self.set_remote_name)
|
|
54
|
+
|
|
55
|
+
def stop_listen(self) -> None:
|
|
56
|
+
"""Stop to listen on incoming commands."""
|
|
57
|
+
self.listener.stop_listen()
|
|
58
|
+
|
|
59
|
+
# smethods for being remote controlled
|
|
60
|
+
# these methods are executed and cannot talk to the controlling module directly.
|
|
61
|
+
# if you need to send a response (for example with a value) you have to store the information and
|
|
62
|
+
# send it after these methods have been executed.
|
|
63
|
+
def set_remote_name(self, name: str) -> None:
|
|
64
|
+
"""Define what the name of the remote for answers is."""
|
|
65
|
+
self.remote_name = name
|
|
66
|
+
|
|
67
|
+
# generic commands
|
|
68
|
+
def set_info(self, path: List[str], param_dict_str: str) -> None:
|
|
69
|
+
print("set_info", path, param_dict_str)
|
|
70
|
+
|
|
71
|
+
# detector commands
|
|
72
|
+
def send_data(self, grabber_type: str = "") -> None:
|
|
73
|
+
print("send_data")
|
|
74
|
+
|
|
75
|
+
# actuator commands
|
|
76
|
+
def move_abs(self, position: Union[float, str]) -> None:
|
|
77
|
+
print("move_abs", position)
|
|
78
|
+
self._fake_position = float(position)
|
|
79
|
+
|
|
80
|
+
def move_rel(self, position: Union[float, str]) -> None:
|
|
81
|
+
print("move_rel", position)
|
|
82
|
+
self._fake_position += float(position)
|
|
83
|
+
|
|
84
|
+
def move_home(self) -> None:
|
|
85
|
+
self._fake_position = 0
|
|
86
|
+
print("move_home")
|
|
87
|
+
|
|
88
|
+
def get_actuator_value(self) -> None:
|
|
89
|
+
"""Request that the actuator value is sent later on."""
|
|
90
|
+
# according to DAQ_Move, this supersedes "check_position"
|
|
91
|
+
print("get_actuator_value")
|
|
92
|
+
# send the actuator position after this method has finished execution.
|
|
93
|
+
# this method sends the result to the controlling control module.
|
|
94
|
+
self.send_later(
|
|
95
|
+
receiver=self.remote_name,
|
|
96
|
+
method="set_position",
|
|
97
|
+
position=self._fake_position,
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
def stop_motion(self,) -> None:
|
|
101
|
+
# not implemented in DAQ_Move!
|
|
102
|
+
print("stop_motion")
|
|
103
|
+
|
|
104
|
+
# end of methods for being remote controlled
|
|
105
|
+
|
|
106
|
+
def send_later(self, receiver, method, **kwargs):
|
|
107
|
+
"""Store information to send it later."""
|
|
108
|
+
self._stored.append((receiver, method, kwargs))
|
|
109
|
+
|
|
110
|
+
def send_stored(self):
|
|
111
|
+
"""Send messages stored for later sending."""
|
|
112
|
+
while self._stored:
|
|
113
|
+
receiver, method, kwargs = self._stored.pop()
|
|
114
|
+
self.communicator.ask_rpc(receiver=receiver, method=method, **kwargs)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
if __name__ == "__main__":
|
|
118
|
+
print("listening endlessly as 'qt_less'")
|
|
119
|
+
log = logging.getLogger()
|
|
120
|
+
log.addHandler(logging.StreamHandler())
|
|
121
|
+
# log.setLevel(logging.DEBUG)
|
|
122
|
+
m = QtLessModule("qt_less")
|
|
123
|
+
try:
|
|
124
|
+
while True:
|
|
125
|
+
sleep(0.1)
|
|
126
|
+
m.send_stored()
|
|
127
|
+
except KeyboardInterrupt:
|
|
128
|
+
m.stop_listen()
|
pymodaq/resources/VERSION
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
version = '4.4.
|
|
1
|
+
version = '4.4.7'
|
|
2
2
|
|
|
@@ -23,6 +23,7 @@ def setup(path: Path):
|
|
|
23
23
|
name=PLUGIN_NAME,
|
|
24
24
|
description=config['plugin-info']['description'],
|
|
25
25
|
long_description=long_description,
|
|
26
|
+
long_description_content_type='text/x-rst',
|
|
26
27
|
license=config['plugin-info']['license'],
|
|
27
28
|
url=config['plugin-info']['package-url'],
|
|
28
29
|
author=config['plugin-info']['author'],
|
pymodaq/utils/data.py
CHANGED
|
@@ -98,6 +98,7 @@ class DataUnitError(Exception):
|
|
|
98
98
|
|
|
99
99
|
|
|
100
100
|
class DwaType(BaseEnum):
|
|
101
|
+
"""Different types of `DataWithAxes`."""
|
|
101
102
|
DataWithAxes = 0
|
|
102
103
|
DataRaw = 1
|
|
103
104
|
DataActuator = 2
|
|
@@ -648,6 +649,13 @@ class DataBase(DataLowLevel):
|
|
|
648
649
|
""" Change immediately the units to whatever else. Use this with care!"""
|
|
649
650
|
self._units = units
|
|
650
651
|
|
|
652
|
+
def to_base_units(self):
|
|
653
|
+
dwa = self.deepcopy()
|
|
654
|
+
data_quantities = [quantity.to_base_units() for quantity in self.quantities]
|
|
655
|
+
dwa.data = [quantity.magnitude for quantity in data_quantities]
|
|
656
|
+
dwa.force_units(str(data_quantities[0].units))
|
|
657
|
+
return dwa
|
|
658
|
+
|
|
651
659
|
def units_as(self, units: str, inplace=True) -> 'DataBase':
|
|
652
660
|
""" Set the object units to the new one (if possible)
|
|
653
661
|
|
|
@@ -55,11 +55,14 @@ class DAQ_Move_LECODirector(LECODirector, DAQ_Move_base):
|
|
|
55
55
|
params_state=params_state, **kwargs)
|
|
56
56
|
self.register_rpc_methods((
|
|
57
57
|
self.set_info,
|
|
58
|
+
))
|
|
59
|
+
for method in (
|
|
58
60
|
self.set_position,
|
|
59
61
|
self.set_move_done,
|
|
60
62
|
self.set_x_axis,
|
|
61
63
|
self.set_y_axis,
|
|
62
|
-
)
|
|
64
|
+
):
|
|
65
|
+
self.listener.register_binary_rpc_method(method, accept_binary_input=True)
|
|
63
66
|
|
|
64
67
|
# copied, I think it is good:
|
|
65
68
|
self.settings.child('bounds').hide()
|
|
@@ -143,22 +146,29 @@ class DAQ_Move_LECODirector(LECODirector, DAQ_Move_base):
|
|
|
143
146
|
self.controller.stop_motion()
|
|
144
147
|
|
|
145
148
|
# Methods accessible via remote calls
|
|
146
|
-
def _set_position_value(
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
149
|
+
def _set_position_value(
|
|
150
|
+
self, position: Union[str, float, None], additional_payload=None
|
|
151
|
+
) -> DataActuator:
|
|
152
|
+
if position:
|
|
153
|
+
if isinstance(position, str):
|
|
154
|
+
deserializer = DeSerializer.from_b64_string(position)
|
|
155
|
+
pos = deserializer.dwa_deserialization()
|
|
156
|
+
else:
|
|
157
|
+
pos = DataActuator(data=position)
|
|
158
|
+
elif additional_payload is not None:
|
|
159
|
+
pos = DeSerializer(additional_payload[0]).dwa_deserialization()
|
|
150
160
|
else:
|
|
151
|
-
|
|
161
|
+
raise ValueError("No position given")
|
|
152
162
|
pos = self.get_position_with_scaling(pos) # type: ignore
|
|
153
163
|
self._current_value = pos
|
|
154
164
|
return pos
|
|
155
165
|
|
|
156
|
-
def set_position(self, position: Union[str, float]) -> None:
|
|
157
|
-
pos = self._set_position_value(position=position)
|
|
166
|
+
def set_position(self, position: Union[str, float, None], additional_payload=None) -> None:
|
|
167
|
+
pos = self._set_position_value(position=position, additional_payload=additional_payload)
|
|
158
168
|
self.emit_status(ThreadCommand('get_actuator_value', [pos]))
|
|
159
169
|
|
|
160
|
-
def set_move_done(self, position: Union[str, float]) -> None:
|
|
161
|
-
pos = self._set_position_value(position=position)
|
|
170
|
+
def set_move_done(self, position: Union[str, float, None], additional_payload=None) -> None:
|
|
171
|
+
pos = self._set_position_value(position=position, additional_payload=additional_payload)
|
|
162
172
|
self.emit_status(ThreadCommand('move_done', [pos]))
|
|
163
173
|
|
|
164
174
|
def set_x_axis(self, data, label: str = "", units: str = "") -> None:
|
|
@@ -1,5 +1,5 @@
|
|
|
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
|
|
|
@@ -37,8 +37,11 @@ class DAQ_xDViewer_LECODirector(LECODirector, DAQ_Viewer_base):
|
|
|
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,7 @@ 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]) -> None:
|
|
156
|
+
def set_data(self, data: Union[list, str, None], additional_payload: Optional[list[bytes]]=None) -> None:
|
|
154
157
|
"""
|
|
155
158
|
Set the grabbed data signal.
|
|
156
159
|
|
|
@@ -160,10 +163,12 @@ class DAQ_xDViewer_LECODirector(LECODirector, DAQ_Viewer_base):
|
|
|
160
163
|
"""
|
|
161
164
|
if isinstance(data, str):
|
|
162
165
|
deserializer = DeSerializer.from_b64_string(data)
|
|
163
|
-
|
|
164
|
-
|
|
166
|
+
elif additional_payload is not None:
|
|
167
|
+
deserializer = DeSerializer(additional_payload[0])
|
|
165
168
|
else:
|
|
166
169
|
raise NotImplementedError("Not implemented to set a list of values.")
|
|
170
|
+
dte = deserializer.dte_deserialization()
|
|
171
|
+
self.dte_signal.emit(dte)
|
|
167
172
|
|
|
168
173
|
|
|
169
174
|
if __name__ == '__main__':
|
|
@@ -17,7 +17,7 @@ from qtpy.QtCore import QObject, Signal # type: ignore
|
|
|
17
17
|
from pymodaq.utils.daq_utils import ThreadCommand
|
|
18
18
|
from pymodaq.utils.parameter import ioxml
|
|
19
19
|
from pymodaq.utils.tcp_ip.serializer import DataWithAxes, SERIALIZABLE, DeSerializer
|
|
20
|
-
from pymodaq.utils.leco.utils import
|
|
20
|
+
from pymodaq.utils.leco.utils import binary_serialization_to_kwargs
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
class LECOClientCommands(StrEnum):
|
|
@@ -220,7 +220,7 @@ class ActorListener(PymodaqListener):
|
|
|
220
220
|
self.communicator.ask_rpc(
|
|
221
221
|
receiver=self.remote_name,
|
|
222
222
|
method="set_data",
|
|
223
|
-
|
|
223
|
+
**binary_serialization_to_kwargs(value),
|
|
224
224
|
)
|
|
225
225
|
|
|
226
226
|
elif command.command == 'send_info':
|
|
@@ -236,14 +236,14 @@ class ActorListener(PymodaqListener):
|
|
|
236
236
|
value = command.attribute[0] # type: ignore
|
|
237
237
|
self.communicator.ask_rpc(receiver=self.remote_name,
|
|
238
238
|
method="set_position",
|
|
239
|
-
|
|
239
|
+
**binary_serialization_to_kwargs(value, data_key="position"),
|
|
240
240
|
)
|
|
241
241
|
|
|
242
242
|
elif command.command == LECOMoveCommands.MOVE_DONE:
|
|
243
243
|
value = command.attribute[0] # type: ignore
|
|
244
244
|
self.communicator.ask_rpc(receiver=self.remote_name,
|
|
245
245
|
method="set_move_done",
|
|
246
|
-
|
|
246
|
+
**binary_serialization_to_kwargs(value, data_key="position"),
|
|
247
247
|
)
|
|
248
248
|
|
|
249
249
|
elif command.command == 'x_axis':
|
|
@@ -251,7 +251,7 @@ class ActorListener(PymodaqListener):
|
|
|
251
251
|
if isinstance(value, SERIALIZABLE):
|
|
252
252
|
self.communicator.ask_rpc(receiver=self.remote_name,
|
|
253
253
|
method="set_x_axis",
|
|
254
|
-
|
|
254
|
+
**binary_serialization_to_kwargs(value),
|
|
255
255
|
)
|
|
256
256
|
elif isinstance(value, dict):
|
|
257
257
|
self.communicator.ask_rpc(receiver=self.remote_name, method="set_x_axis", **value)
|
|
@@ -263,7 +263,7 @@ class ActorListener(PymodaqListener):
|
|
|
263
263
|
if isinstance(value, SERIALIZABLE):
|
|
264
264
|
self.communicator.ask_rpc(receiver=self.remote_name,
|
|
265
265
|
method="set_y_axis",
|
|
266
|
-
|
|
266
|
+
**binary_serialization_to_kwargs(value),
|
|
267
267
|
)
|
|
268
268
|
elif isinstance(value, dict):
|
|
269
269
|
self.communicator.ask_rpc(receiver=self.remote_name, method="set_y_axis", **value)
|
pymodaq/utils/leco/utils.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
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
|
|
4
5
|
|
|
5
6
|
# import also the DeSerializer for easier imports in dependents
|
|
6
7
|
from pymodaq.utils.tcp_ip.serializer import SERIALIZABLE, Serializer, DeSerializer # type: ignore # noqa
|
|
@@ -23,6 +24,29 @@ def serialize_object(pymodaq_object: Union[SERIALIZABLE, Any]) -> Union[str, Any
|
|
|
23
24
|
"JSON serializable, nor via PyMoDAQ.")
|
|
24
25
|
|
|
25
26
|
|
|
27
|
+
def binary_serialization(
|
|
28
|
+
pymodaq_object: Union[SERIALIZABLE, Any],
|
|
29
|
+
) -> tuple[Optional[Any], Optional[list[bytes]]]:
|
|
30
|
+
"""Serialize (binary) a pymodaq object, if it is not JSON compatible."""
|
|
31
|
+
if isinstance(pymodaq_object, get_args(JSON_TYPES)):
|
|
32
|
+
return pymodaq_object, None
|
|
33
|
+
elif isinstance(pymodaq_object, get_args(SERIALIZABLE)):
|
|
34
|
+
return None, [Serializer(pymodaq_object).to_bytes()]
|
|
35
|
+
else:
|
|
36
|
+
raise ValueError(
|
|
37
|
+
f"{pymodaq_object} of type '{type(pymodaq_object).__name__}' is neither "
|
|
38
|
+
"JSON serializable, nor via PyMoDAQ."
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def binary_serialization_to_kwargs(
|
|
43
|
+
pymodaq_object: Union[SERIALIZABLE, Any], data_key: str = "data"
|
|
44
|
+
) -> dict[str, Any]:
|
|
45
|
+
"""Create a dictionary of data parameters and of additional payload to send."""
|
|
46
|
+
d, b = binary_serialization(pymodaq_object=pymodaq_object)
|
|
47
|
+
return {data_key: d, "additional_payload": b}
|
|
48
|
+
|
|
49
|
+
|
|
26
50
|
def run_coordinator():
|
|
27
51
|
command = [sys.executable, '-m', 'pyleco.coordinators.coordinator']
|
|
28
52
|
subprocess.Popen(command)
|
|
@@ -17,7 +17,7 @@ logger = set_logger(get_module_name(__file__))
|
|
|
17
17
|
remote_path = pymodaq.utils.config.get_set_remote_path()
|
|
18
18
|
remote_types = ['ShortCut', 'Joystick']
|
|
19
19
|
|
|
20
|
-
actuator_actions = ['
|
|
20
|
+
actuator_actions = ['move_rel', 'move_rel_p', 'move_rel_m']
|
|
21
21
|
detector_actions = ['snap', 'grab', 'stop']
|
|
22
22
|
remote_types = ['Keyboard', 'Joystick']
|
|
23
23
|
try:
|
|
@@ -5,8 +5,9 @@ Created the 20/10/2023
|
|
|
5
5
|
@author: Sebastien Weber
|
|
6
6
|
"""
|
|
7
7
|
from base64 import b64encode, b64decode
|
|
8
|
+
from enum import Enum
|
|
8
9
|
import numbers
|
|
9
|
-
from typing import Tuple, List, Union, TYPE_CHECKING
|
|
10
|
+
from typing import Optional, Tuple, List, Union, TYPE_CHECKING
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
import numpy as np
|
|
@@ -20,17 +21,38 @@ if TYPE_CHECKING:
|
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
SERIALIZABLE = Union[
|
|
23
|
-
|
|
24
|
+
# native
|
|
25
|
+
bool,
|
|
26
|
+
bytes,
|
|
24
27
|
str,
|
|
25
|
-
|
|
28
|
+
complex, # float and int are subtypes for type hinting
|
|
29
|
+
float,
|
|
30
|
+
int,
|
|
26
31
|
list,
|
|
32
|
+
# numpy
|
|
27
33
|
np.ndarray,
|
|
34
|
+
# pymodaq
|
|
28
35
|
Axis,
|
|
29
36
|
DataWithAxes,
|
|
30
37
|
DataToExport,
|
|
38
|
+
putils.ParameterWithPath,
|
|
31
39
|
]
|
|
32
40
|
|
|
33
41
|
|
|
42
|
+
class SerializableTypes(Enum):
|
|
43
|
+
"""Type names of serializable types"""
|
|
44
|
+
BOOL = "bool"
|
|
45
|
+
BYTES = "bytes"
|
|
46
|
+
STRING = "string"
|
|
47
|
+
SCALAR = "scalar"
|
|
48
|
+
LIST = "list"
|
|
49
|
+
ARRAY = "array"
|
|
50
|
+
AXIS = "axis"
|
|
51
|
+
DATA_WITH_AXES = "dwa"
|
|
52
|
+
DATA_TO_EXPORT = "dte"
|
|
53
|
+
PARAMETER = "parameter"
|
|
54
|
+
|
|
55
|
+
|
|
34
56
|
class SocketString:
|
|
35
57
|
"""Mimic the Socket object but actually using a bytes string not a socket connection
|
|
36
58
|
|
|
@@ -86,7 +108,7 @@ class Serializer:
|
|
|
86
108
|
"""Used to Serialize to bytes python objects, numpy arrays and PyMoDAQ DataWithAxes and
|
|
87
109
|
DataToExport objects"""
|
|
88
110
|
|
|
89
|
-
def __init__(self, obj: SERIALIZABLE = None):
|
|
111
|
+
def __init__(self, obj: Optional[SERIALIZABLE] = None) -> None:
|
|
90
112
|
self._bytes_string = b''
|
|
91
113
|
self._obj = obj
|
|
92
114
|
|
|
@@ -154,7 +176,7 @@ class Serializer:
|
|
|
154
176
|
return message.encode()
|
|
155
177
|
|
|
156
178
|
@classmethod
|
|
157
|
-
def str_len_to_bytes(cls, message: Union[str, bytes]) ->
|
|
179
|
+
def str_len_to_bytes(cls, message: Union[str, bytes]) -> Tuple[bytes, bytes]:
|
|
158
180
|
""" Convert a string and its length to two bytes
|
|
159
181
|
Parameters
|
|
160
182
|
----------
|
|
@@ -174,7 +196,7 @@ class Serializer:
|
|
|
174
196
|
return message, cls.int_to_bytes(len(message))
|
|
175
197
|
|
|
176
198
|
def _int_serialization(self, int_obj: int) -> bytes:
|
|
177
|
-
"""
|
|
199
|
+
"""Serialize an unsigned integer used for getting the length of messages internally, for outside integer
|
|
178
200
|
serialization or deserialization use scalar_serialization"""
|
|
179
201
|
int_bytes = self.int_to_bytes(int_obj)
|
|
180
202
|
bytes_string = int_bytes
|
|
@@ -205,18 +227,19 @@ class Serializer:
|
|
|
205
227
|
self._bytes_string += bytes_string
|
|
206
228
|
return bytes_string
|
|
207
229
|
|
|
208
|
-
def scalar_serialization(self, scalar:
|
|
230
|
+
def scalar_serialization(self, scalar: complex) -> bytes:
|
|
209
231
|
""" Convert a scalar into a bytes message together with the info to convert it back
|
|
210
232
|
|
|
211
233
|
Parameters
|
|
212
234
|
----------
|
|
213
|
-
scalar:
|
|
235
|
+
scalar: A python number (complex or subtypes like float and int)
|
|
214
236
|
|
|
215
237
|
Returns
|
|
216
238
|
-------
|
|
217
239
|
bytes: the total bytes message to serialize the scalar
|
|
218
240
|
"""
|
|
219
241
|
if not isinstance(scalar, numbers.Number):
|
|
242
|
+
# type hint is complex, instance comparison Number
|
|
220
243
|
raise TypeError(f'{scalar} should be an integer or a float, not a {type(scalar)}')
|
|
221
244
|
scalar_array = np.array([scalar])
|
|
222
245
|
data_type = scalar_array.dtype.descr[0][1]
|
|
@@ -350,49 +373,56 @@ class Serializer:
|
|
|
350
373
|
self._bytes_string += bytes_string
|
|
351
374
|
return bytes_string
|
|
352
375
|
|
|
353
|
-
def type_and_object_serialization(self, obj):
|
|
376
|
+
def type_and_object_serialization(self, obj: Optional[SERIALIZABLE] = None) -> bytes:
|
|
377
|
+
"""Serialize an object with its type, such that it can be retrieved by
|
|
378
|
+
`DeSerializer.type_and_object_deserialization`.
|
|
379
|
+
"""
|
|
380
|
+
|
|
381
|
+
if obj is None and self._obj is not None:
|
|
382
|
+
obj = self._obj
|
|
383
|
+
|
|
354
384
|
bytes_string = b''
|
|
355
385
|
if isinstance(obj, DataWithAxes):
|
|
356
|
-
bytes_string += self.string_serialization(
|
|
386
|
+
bytes_string += self.string_serialization(SerializableTypes.DATA_WITH_AXES.value)
|
|
357
387
|
bytes_string += self.dwa_serialization(obj)
|
|
358
388
|
|
|
359
389
|
elif isinstance(obj, Axis):
|
|
360
|
-
bytes_string += self.string_serialization(
|
|
390
|
+
bytes_string += self.string_serialization(SerializableTypes.AXIS.value)
|
|
361
391
|
bytes_string += self.axis_serialization(obj)
|
|
362
392
|
|
|
363
393
|
elif isinstance(obj, np.ndarray):
|
|
364
|
-
bytes_string += self.string_serialization(
|
|
394
|
+
bytes_string += self.string_serialization(SerializableTypes.ARRAY.value)
|
|
365
395
|
bytes_string += self.ndarray_serialization(obj)
|
|
366
396
|
|
|
367
397
|
elif isinstance(obj, bytes):
|
|
368
|
-
bytes_string += self.string_serialization(
|
|
398
|
+
bytes_string += self.string_serialization(SerializableTypes.BYTES.value)
|
|
369
399
|
bytes_string += self.bytes_serialization(obj)
|
|
370
400
|
|
|
371
401
|
elif isinstance(obj, str):
|
|
372
|
-
bytes_string += self.string_serialization(
|
|
402
|
+
bytes_string += self.string_serialization(SerializableTypes.STRING.value)
|
|
373
403
|
bytes_string += self.string_serialization(obj)
|
|
374
404
|
|
|
375
|
-
elif isinstance(obj,
|
|
376
|
-
bytes_string += self.string_serialization(
|
|
405
|
+
elif isinstance(obj, bool):
|
|
406
|
+
bytes_string += self.string_serialization(SerializableTypes.BOOL.value)
|
|
377
407
|
bytes_string += self.scalar_serialization(obj)
|
|
378
408
|
|
|
379
|
-
elif isinstance(obj,
|
|
380
|
-
bytes_string += self.string_serialization(
|
|
381
|
-
bytes_string += self.scalar_serialization(
|
|
409
|
+
elif isinstance(obj, numbers.Number):
|
|
410
|
+
bytes_string += self.string_serialization(SerializableTypes.SCALAR.value)
|
|
411
|
+
bytes_string += self.scalar_serialization(obj)
|
|
382
412
|
|
|
383
413
|
elif isinstance(obj, list):
|
|
384
|
-
bytes_string += self.string_serialization(
|
|
414
|
+
bytes_string += self.string_serialization(SerializableTypes.LIST.value)
|
|
385
415
|
bytes_string += self.list_serialization(obj)
|
|
386
416
|
|
|
387
417
|
elif isinstance(obj, putils.ParameterWithPath):
|
|
388
418
|
path = obj.path
|
|
389
419
|
param_as_xml = ioxml.parameter_to_xml_string(obj.parameter)
|
|
390
|
-
bytes_string += self.string_serialization(
|
|
420
|
+
bytes_string += self.string_serialization(SerializableTypes.PARAMETER.value)
|
|
391
421
|
bytes_string += self.list_serialization(path)
|
|
392
|
-
bytes_string += self.
|
|
422
|
+
bytes_string += self.bytes_serialization(param_as_xml)
|
|
393
423
|
|
|
394
424
|
elif isinstance(obj, DataToExport):
|
|
395
|
-
bytes_string += self.string_serialization(
|
|
425
|
+
bytes_string += self.string_serialization(SerializableTypes.DATA_TO_EXPORT.value)
|
|
396
426
|
bytes_string += self.dte_serialization(obj)
|
|
397
427
|
|
|
398
428
|
else:
|
|
@@ -509,7 +539,7 @@ class DeSerializer:
|
|
|
509
539
|
:py:class:`~pymodaq.utils.tcp_ip.mysocket.Socket`
|
|
510
540
|
"""
|
|
511
541
|
|
|
512
|
-
def __init__(self, bytes_string: Union[bytes, 'Socket'] = None):
|
|
542
|
+
def __init__(self, bytes_string: Union[bytes, 'Socket'] = None) -> None:
|
|
513
543
|
if isinstance(bytes_string, bytes):
|
|
514
544
|
bytes_string = SocketString(bytes_string)
|
|
515
545
|
self._bytes_string = bytes_string
|
|
@@ -531,7 +561,7 @@ class DeSerializer:
|
|
|
531
561
|
return int.from_bytes(bytes_string, 'big')
|
|
532
562
|
|
|
533
563
|
@staticmethod
|
|
534
|
-
def bytes_to_scalar(data: bytes, dtype: np.dtype) ->
|
|
564
|
+
def bytes_to_scalar(data: bytes, dtype: np.dtype) -> complex:
|
|
535
565
|
"""Convert bytes to a scalar given a certain numpy dtype
|
|
536
566
|
|
|
537
567
|
Parameters
|
|
@@ -588,8 +618,8 @@ class DeSerializer:
|
|
|
588
618
|
str_obj = self._bytes_string.get_first_nbytes(string_len).decode()
|
|
589
619
|
return str_obj
|
|
590
620
|
|
|
591
|
-
def scalar_deserialization(self) ->
|
|
592
|
-
"""Convert bytes into a
|
|
621
|
+
def scalar_deserialization(self) -> complex:
|
|
622
|
+
"""Convert bytes into a python number object
|
|
593
623
|
|
|
594
624
|
Get first the data type from a string deserialization, then the data length and finally convert this
|
|
595
625
|
length of bytes into a number (float, int)
|
|
@@ -602,9 +632,11 @@ class DeSerializer:
|
|
|
602
632
|
data_len = self._int_deserialization()
|
|
603
633
|
number = np.frombuffer(self._bytes_string.get_first_nbytes(data_len), dtype=data_type)[0]
|
|
604
634
|
if 'f' in data_type:
|
|
605
|
-
number = float(number) # because one get numpy
|
|
635
|
+
number = float(number) # because one get numpy float type
|
|
606
636
|
elif 'i' in data_type:
|
|
607
637
|
number = int(number) # because one get numpy int type
|
|
638
|
+
elif 'c' in data_type:
|
|
639
|
+
number = complex(number) # because one get numpy complex type
|
|
608
640
|
return number
|
|
609
641
|
|
|
610
642
|
def boolean_deserialization(self) -> bool:
|
|
@@ -642,7 +674,7 @@ class DeSerializer:
|
|
|
642
674
|
ndarray = np.atleast_1d(ndarray) # remove singleton dimensions
|
|
643
675
|
return ndarray
|
|
644
676
|
|
|
645
|
-
def type_and_object_deserialization(self):
|
|
677
|
+
def type_and_object_deserialization(self) -> SERIALIZABLE:
|
|
646
678
|
""" Deserialize specific objects from their binary representation (inverse of `Serializer.type_and_object_serialization`).
|
|
647
679
|
|
|
648
680
|
See Also
|
|
@@ -652,28 +684,29 @@ class DeSerializer:
|
|
|
652
684
|
"""
|
|
653
685
|
obj_type = self.string_deserialization()
|
|
654
686
|
elt = None
|
|
655
|
-
if obj_type ==
|
|
687
|
+
if obj_type == SerializableTypes.SCALAR.value:
|
|
656
688
|
elt = self.scalar_deserialization()
|
|
657
|
-
elif obj_type ==
|
|
689
|
+
elif obj_type == SerializableTypes.STRING.value:
|
|
658
690
|
elt = self.string_deserialization()
|
|
659
|
-
elif obj_type ==
|
|
691
|
+
elif obj_type == SerializableTypes.BYTES.value:
|
|
660
692
|
elt = self.bytes_deserialization()
|
|
661
|
-
elif obj_type ==
|
|
693
|
+
elif obj_type == SerializableTypes.ARRAY.value:
|
|
662
694
|
elt = self.ndarray_deserialization()
|
|
663
|
-
elif obj_type ==
|
|
695
|
+
elif obj_type == SerializableTypes.DATA_WITH_AXES.value:
|
|
664
696
|
elt = self.dwa_deserialization()
|
|
665
|
-
elif obj_type ==
|
|
697
|
+
elif obj_type == SerializableTypes.DATA_TO_EXPORT.value:
|
|
666
698
|
elt = self.dte_deserialization()
|
|
667
|
-
elif obj_type ==
|
|
699
|
+
elif obj_type == SerializableTypes.AXIS.value:
|
|
668
700
|
elt = self.axis_deserialization()
|
|
669
|
-
elif obj_type ==
|
|
701
|
+
elif obj_type == SerializableTypes.BOOL.value:
|
|
670
702
|
elt = self.boolean_deserialization()
|
|
671
|
-
elif obj_type ==
|
|
703
|
+
elif obj_type == SerializableTypes.LIST.value:
|
|
672
704
|
elt = self.list_deserialization()
|
|
673
|
-
elif obj_type ==
|
|
705
|
+
elif obj_type == SerializableTypes.PARAMETER.value:
|
|
674
706
|
elt = self.parameter_deserialization()
|
|
675
707
|
else:
|
|
676
708
|
print(f'invalid object type {obj_type}')
|
|
709
|
+
elt = None # desired behavior?
|
|
677
710
|
return elt
|
|
678
711
|
|
|
679
712
|
def list_deserialization(self) -> list:
|
|
@@ -774,4 +807,4 @@ class DeSerializer:
|
|
|
774
807
|
data=self.list_deserialization(),
|
|
775
808
|
)
|
|
776
809
|
dte.timestamp = timestamp
|
|
777
|
-
return dte
|
|
810
|
+
return dte
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: pymodaq
|
|
3
|
-
Version: 4.4.
|
|
3
|
+
Version: 4.4.7
|
|
4
4
|
Summary: Modular Data Acquisition with Python
|
|
5
5
|
Project-URL: Homepage, http://pymodaq.cnrs.fr
|
|
6
6
|
Project-URL: Source, https://github.com/PyMoDAQ/PyMoDAQ
|
|
@@ -27,7 +27,6 @@ License: The MIT License (MIT)
|
|
|
27
27
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
28
28
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
29
29
|
THE SOFTWARE.
|
|
30
|
-
License-File: LICENSE
|
|
31
30
|
Classifier: Development Status :: 5 - Production/Stable
|
|
32
31
|
Classifier: Environment :: Other Environment
|
|
33
32
|
Classifier: Intended Audience :: Science/Research
|
|
@@ -51,7 +50,7 @@ Requires-Dist: multipledispatch
|
|
|
51
50
|
Requires-Dist: numpy<2.0.0
|
|
52
51
|
Requires-Dist: packaging
|
|
53
52
|
Requires-Dist: pint
|
|
54
|
-
Requires-Dist: pyleco; python_version >= '3.8'
|
|
53
|
+
Requires-Dist: pyleco>0.3; python_version >= '3.8'
|
|
55
54
|
Requires-Dist: pymodaq-plugin-manager>=0.0.17
|
|
56
55
|
Requires-Dist: pymodaq-plugins-mock<5.0.0
|
|
57
56
|
Requires-Dist: pyqtgraph>=0.12
|
|
@@ -3,12 +3,12 @@ pymodaq/dashboard.py,sha256=4fbV92erom0yWwqPMtx3KW1q-d6QYflV-EhOZMg24a4,64476
|
|
|
3
3
|
pymodaq/icon.ico,sha256=hOHHfNDENKphQvG1WDleSEYcHukneR2eRFJu8isIlD4,74359
|
|
4
4
|
pymodaq/splash.png,sha256=ow8IECF3tPRUMA4tf2tMu1aRiMaxx91_Y2ckVxkrmF0,53114
|
|
5
5
|
pymodaq/control_modules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
-
pymodaq/control_modules/daq_move.py,sha256=
|
|
6
|
+
pymodaq/control_modules/daq_move.py,sha256=0zit9shAo6HAVxkaYdhhuSN-yu8j8T_TLSF6YOaM85Y,37842
|
|
7
7
|
pymodaq/control_modules/daq_move_ui.py,sha256=IbqNAErwXGjKUbYEptvZUz3J8MapNBFIbQnUf9nQrMw,15753
|
|
8
8
|
pymodaq/control_modules/daq_viewer.py,sha256=5CYmdWHGE7sQApeMfdWNV3zbPyoxxYtzFlQ1PaEw4fI,57883
|
|
9
9
|
pymodaq/control_modules/daq_viewer_ui.py,sha256=FWP3jdIOR9vTgYqNaaodteGZ3dwgQ1GdWKrOpOAuSrs,15693
|
|
10
10
|
pymodaq/control_modules/mocks.py,sha256=hh_xSWp9g1UV3NAQVD9Ft9tNWfTsSvKU0OU0trgzP2w,1956
|
|
11
|
-
pymodaq/control_modules/move_utility_classes.py,sha256=
|
|
11
|
+
pymodaq/control_modules/move_utility_classes.py,sha256=PDiPVAfOEAhtTc6MS0oVCy3AL-6KLSxOgYg3c5jctoA,43417
|
|
12
12
|
pymodaq/control_modules/utils.py,sha256=5YdSwq_lFJm7IalYWe_Hn1U4LUoUmo1gedvV9UguU0Y,20016
|
|
13
13
|
pymodaq/control_modules/viewer_utility_classes.py,sha256=OHxwue1t3z2AXyeqNjnwPT2pMc8yXhnqyiWc9IdCI2c,26841
|
|
14
14
|
pymodaq/examples/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -18,6 +18,7 @@ pymodaq/examples/function_plotter.py,sha256=T-VT0Rd3jHP9GcR2h6Nao6lwZE06P8zWUbOl
|
|
|
18
18
|
pymodaq/examples/nonlinearscanner.py,sha256=x0R2_FP0YnuOCCAmYRiAiZ1jfUdRxu5RqIYLyGQMZ0U,3790
|
|
19
19
|
pymodaq/examples/parameter_ex.py,sha256=NmFUvUByNtm3j4leN_MkufQsKlNU8Rx5lmpsVG58IIM,8556
|
|
20
20
|
pymodaq/examples/preset_MockCamera.xml,sha256=quQlMsX6YSoqqc9_9Y-9zu3TDM6Xvnuc2JSWwg9f948,15774
|
|
21
|
+
pymodaq/examples/qt_less_standalone_module.py,sha256=9UD4niVfNXscDVQiOJuuL6lN9PC7Jfp9FwVJ0qz_6Do,4857
|
|
21
22
|
pymodaq/examples/tcp_client.py,sha256=FSdPlb3R_rxxNIqPqHVU8PxJzNZeFk_93l4TqsB5SnA,2584
|
|
22
23
|
pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.aliases,sha256=t0eKH9Uq_AMk4wQ-6Pm5mKUjGcCvfT9GtvMsvDhkCUk,47
|
|
23
24
|
pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.lvlps,sha256=VZHH96rKSnRYKeCAXUmKI3vQOX8Wz53FYCF2yXuqnaU,84
|
|
@@ -58,11 +59,11 @@ pymodaq/post_treatment/daq_measurement/daq_measurement_GUI.py,sha256=1u7hWDaiwsZ
|
|
|
58
59
|
pymodaq/post_treatment/daq_measurement/daq_measurement_GUI.ui,sha256=PyzbCWPMkh5oIYYteZczXyWMeHKW9EJmM1QlzXhnyTk,7037
|
|
59
60
|
pymodaq/post_treatment/daq_measurement/daq_measurement_main.py,sha256=CAKwcWMOD86aXB8mbdxOK7e8nZRos5d59FzDtqK1QoY,17093
|
|
60
61
|
pymodaq/post_treatment/daq_measurement/process_from_QtDesigner_DAQ_Measurement_GUI.bat,sha256=e1tu2A67MS9fk3jhriF6saQgRxWIucIvNW92iWXFP6E,164
|
|
61
|
-
pymodaq/resources/VERSION,sha256=
|
|
62
|
+
pymodaq/resources/VERSION,sha256=ib4rQ9G3YTfdijgNEWBcOoAIZQyUy-mfF0jvGog9fno,19
|
|
62
63
|
pymodaq/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
63
64
|
pymodaq/resources/config_template.toml,sha256=d3pofgIK5FxaRMELAI1qEsRcMD3GlYd87zZjDj9G9m0,3210
|
|
64
65
|
pymodaq/resources/preset_default.xml,sha256=Dt8iWLwPPOPtcG00JCVP-mh-G7KC6B0YN8hd8RQdnNI,27256
|
|
65
|
-
pymodaq/resources/setup_plugin.py,sha256=
|
|
66
|
+
pymodaq/resources/setup_plugin.py,sha256=jvMuSp4UxGaPUe9uPUvHg9DrdwyFakG6_sFy_zXb1f8,3182
|
|
66
67
|
pymodaq/resources/triangulation_data.npy,sha256=Dzq6eE8f_i7Woloy1iUn6N1OfVdBZ4WnK4J4SCoqXso,9320
|
|
67
68
|
pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources.bat,sha256=gqBmrc6Cfzn7wIZQtzgcglKRQ8zLXLW9Xt8LWxkJdw0,205
|
|
68
69
|
pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources.qrc,sha256=S99847o7hvKYOWa9lR3qErMHwcjhjYPEduoq2ylCn4I,10123
|
|
@@ -311,7 +312,7 @@ pymodaq/utils/chrono_timer.py,sha256=rwX8apS8B-IKhA0Cp2H9tLz0BRN7G3Pg5ptozvd3MKM
|
|
|
311
312
|
pymodaq/utils/config.py,sha256=0QqoBJC4ECuIeh1UsvUQqhxkKl7Vfgi4iERp-6qNWAc,16202
|
|
312
313
|
pymodaq/utils/conftests.py,sha256=3Ak8WEpa3EhAp73Yb1LLq8YFONhPqiL7gG9eSDIoTNc,58
|
|
313
314
|
pymodaq/utils/daq_utils.py,sha256=0jTrbT0aaZr3KaTgeDicmK9FbVnu3iaWBmNHnNJpr3A,28050
|
|
314
|
-
pymodaq/utils/data.py,sha256=
|
|
315
|
+
pymodaq/utils/data.py,sha256=RdzEDz3ziRmwbaqy875fLr06jrmaG1wzU-0e_5QQKXM,111908
|
|
315
316
|
pymodaq/utils/enums.py,sha256=wpRipioUJkKcEfoaY2NrDQ2WhGxZTZiZoJty5f2Ljpc,2236
|
|
316
317
|
pymodaq/utils/exceptions.py,sha256=wLO6VlofzfwWkOOWMN2B-3NEWMfpgygyeEdakIx_rAs,668
|
|
317
318
|
pymodaq/utils/factory.py,sha256=QLqAPFnTZ93eUpmAAIr7kESDk2enD57RNSuFUsjxE4E,2311
|
|
@@ -358,13 +359,13 @@ pymodaq/utils/h5modules/exporters/base.py,sha256=hGX2teIMO03QB0qBGTP4rzeXbZrQcVL
|
|
|
358
359
|
pymodaq/utils/h5modules/exporters/flimj.py,sha256=z44C30KlAbaPmjnS5inYophnA18LwwqZOa1UMLEi4Tw,2361
|
|
359
360
|
pymodaq/utils/h5modules/exporters/hyperspy.py,sha256=rheeVJQO0BAF606D_0S_j8huzOLzZfkUAp0OdJEnUz4,6517
|
|
360
361
|
pymodaq/utils/leco/__init__.py,sha256=wxgCC-0eragO_REWDMp-2zg9kK5l_W9oO68dtRYdoKA,878
|
|
361
|
-
pymodaq/utils/leco/daq_move_LECODirector.py,sha256=
|
|
362
|
-
pymodaq/utils/leco/daq_xDviewer_LECODirector.py,sha256=
|
|
362
|
+
pymodaq/utils/leco/daq_move_LECODirector.py,sha256=neYq17utjIm_5KzJkglABd_iL0Ltolcri9oMcBDs-I8,6915
|
|
363
|
+
pymodaq/utils/leco/daq_xDviewer_LECODirector.py,sha256=q6r-oJFMWqc0AOlRQShxX1w64LgnVVSyFzh3sSYUFV4,6310
|
|
363
364
|
pymodaq/utils/leco/desktop.ini,sha256=2zopClaSQqdFfIsC8CGo2Oc-14x9h1gV0-fUrDtLFmA,82
|
|
364
365
|
pymodaq/utils/leco/director_utils.py,sha256=f_rzS6p7VxfWvgm36JRgBHphqYMZrw3gqsadgF9ZtIg,2109
|
|
365
366
|
pymodaq/utils/leco/leco_director.py,sha256=WPsZB6oJIkDJIqtagbeuErfpGB-ENF-s0rtoj_EGVdM,3054
|
|
366
|
-
pymodaq/utils/leco/pymodaq_listener.py,sha256=
|
|
367
|
-
pymodaq/utils/leco/utils.py,sha256=
|
|
367
|
+
pymodaq/utils/leco/pymodaq_listener.py,sha256=OmYC6c3OYjqcT7M881b-g8lXIua2Pq-YYv4X_TuxaPM,10802
|
|
368
|
+
pymodaq/utils/leco/utils.py,sha256=jCHhco89uG9UA-t9LpaEuyZQMQW5XQP_t0URcvqLDNU,2362
|
|
368
369
|
pymodaq/utils/managers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
369
370
|
pymodaq/utils/managers/action_manager.py,sha256=v99NuRq7uT_PNTAsqbUyoWyDGUzhlP6dYtdAO30_cbc,17756
|
|
370
371
|
pymodaq/utils/managers/batchscan_manager.py,sha256=jcL08YvFafX5kiy03BV1_6obt2Xogiby5pvTKeN8_ho,13905
|
|
@@ -373,7 +374,7 @@ pymodaq/utils/managers/overshoot_manager.py,sha256=fe_CR1Bkw85BER34MoVFlm-xtKl9H
|
|
|
373
374
|
pymodaq/utils/managers/parameter_manager.py,sha256=hO3RXcpkYOtuqjAQaD5H3r71rVEHntYg64VHZwVCQBg,11473
|
|
374
375
|
pymodaq/utils/managers/preset_manager.py,sha256=m8r_TcfFbUatddBX9SJj7XI_GZ3FhoiwzhFgocw9jZ8,9481
|
|
375
376
|
pymodaq/utils/managers/preset_manager_utils.py,sha256=d148YBjeNOP9FTkFoTsfdRDxMIXOR8JJHqbOmoL2aVA,8155
|
|
376
|
-
pymodaq/utils/managers/remote_manager.py,sha256=
|
|
377
|
+
pymodaq/utils/managers/remote_manager.py,sha256=SwzefJuGpgzvvjTbJSo3T3Rc2rncvHHyPYPBd8gCQX8,22251
|
|
377
378
|
pymodaq/utils/managers/roi_manager.py,sha256=RRICNSLMxiUoq8tEBKihpdydIVAu78ogkYOFWWphaHE,29892
|
|
378
379
|
pymodaq/utils/parameter/__init__.py,sha256=fMljZeQ9EVvh2bmss550C5BpxFeKOxT8_AVJdPxQ0kQ,433
|
|
379
380
|
pymodaq/utils/parameter/ioxml.py,sha256=jduHhMrpc0lkSJlznnI-LRHUJ0Ofc4PoFfNlxLbLmw8,17091
|
|
@@ -436,10 +437,10 @@ pymodaq/utils/svg/svg_view.py,sha256=bmXpDqnw9S-Bp3F8Hi_oeYB5Y9gebiCNsQWVJzCq-PA
|
|
|
436
437
|
pymodaq/utils/svg/svg_viewer2D.py,sha256=LTJ3Ulb5zWXdRPr7vqcWumbpq7ZctzrYUMtD5QV3x60,1523
|
|
437
438
|
pymodaq/utils/tcp_ip/__init__.py,sha256=1e_EK0AgvdoLAD_CSGGEaITZdy6OWCO7ih9IAIp7HT4,81
|
|
438
439
|
pymodaq/utils/tcp_ip/mysocket.py,sha256=StAWj8dzHeMnbLj68Sel81uWFy-YkKVNRnVf7gXrESI,3452
|
|
439
|
-
pymodaq/utils/tcp_ip/serializer.py,sha256=
|
|
440
|
+
pymodaq/utils/tcp_ip/serializer.py,sha256=kXmvFLR5ZedjY2rVGUs83lsJk9Z9l_iAWR6srDxzaYQ,29262
|
|
440
441
|
pymodaq/utils/tcp_ip/tcp_server_client.py,sha256=xIMTNgVW_rKK0yTi4FDNFLf85-Akb27Jz2LdrvOrP68,30660
|
|
441
|
-
pymodaq-4.4.
|
|
442
|
-
pymodaq-4.4.
|
|
443
|
-
pymodaq-4.4.
|
|
444
|
-
pymodaq-4.4.
|
|
445
|
-
pymodaq-4.4.
|
|
442
|
+
pymodaq-4.4.7.dist-info/METADATA,sha256=jkmtri16XiPHC-2It45CeeZp--C6giXVJ0FLp3g13u8,7611
|
|
443
|
+
pymodaq-4.4.7.dist-info/WHEEL,sha256=3U_NnUcV_1B1kPkYaPzN-irRckL5VW_lytn0ytO_kRY,87
|
|
444
|
+
pymodaq-4.4.7.dist-info/entry_points.txt,sha256=RAzdYNjvUT28I2eiCKki_g2NzXq0woWxhev6lwzwRv8,348
|
|
445
|
+
pymodaq-4.4.7.dist-info/licenses/LICENSE,sha256=VKOejxexXAe3XwfhAhcFGqeXQ12irxVHdeAojZwFEI8,1108
|
|
446
|
+
pymodaq-4.4.7.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|