pymodaq 5.0.0__py3-none-any.whl → 5.0.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of pymodaq might be problematic. Click here for more details.

Files changed (63) hide show
  1. pymodaq/__init__.py +55 -89
  2. pymodaq/control_modules/daq_move.py +129 -55
  3. pymodaq/control_modules/daq_move_ui.py +42 -11
  4. pymodaq/control_modules/daq_viewer.py +32 -13
  5. pymodaq/control_modules/move_utility_classes.py +346 -79
  6. pymodaq/control_modules/utils.py +26 -9
  7. pymodaq/control_modules/viewer_utility_classes.py +51 -14
  8. pymodaq/daq_utils/daq_utils.py +6 -0
  9. pymodaq/dashboard.py +532 -263
  10. pymodaq/examples/qt_less_standalone_module.py +128 -0
  11. pymodaq/extensions/bayesian/bayesian_optimisation.py +30 -21
  12. pymodaq/extensions/bayesian/utils.py +6 -3
  13. pymodaq/extensions/daq_logger/__init__.py +1 -0
  14. pymodaq/extensions/daq_logger/daq_logger.py +4 -5
  15. pymodaq/extensions/daq_scan.py +28 -8
  16. pymodaq/extensions/daq_scan_ui.py +7 -9
  17. pymodaq/extensions/pid/__init__.py +0 -1
  18. pymodaq/extensions/pid/actuator_controller.py +13 -0
  19. pymodaq/extensions/pid/daq_move_PID.py +25 -46
  20. pymodaq/extensions/pid/pid_controller.py +49 -41
  21. pymodaq/extensions/pid/utils.py +7 -31
  22. pymodaq/extensions/utils.py +41 -7
  23. pymodaq/post_treatment/load_and_plot.py +43 -10
  24. pymodaq/resources/setup_plugin.py +1 -0
  25. pymodaq/updater.py +107 -0
  26. pymodaq/utils/chrono_timer.py +6 -7
  27. pymodaq/utils/daq_utils.py +6 -3
  28. pymodaq/utils/data.py +21 -17
  29. pymodaq/utils/enums.py +6 -0
  30. pymodaq/utils/gui_utils/loader_utils.py +29 -2
  31. pymodaq/utils/gui_utils/utils.py +9 -12
  32. pymodaq/utils/gui_utils/widgets/lcd.py +8 -0
  33. pymodaq/utils/h5modules/module_saving.py +5 -2
  34. pymodaq/utils/leco/daq_move_LECODirector.py +22 -16
  35. pymodaq/utils/leco/daq_xDviewer_LECODirector.py +15 -9
  36. pymodaq/utils/leco/leco_director.py +4 -3
  37. pymodaq/utils/leco/pymodaq_listener.py +9 -13
  38. pymodaq/utils/leco/utils.py +40 -7
  39. pymodaq/utils/managers/modules_manager.py +22 -12
  40. pymodaq/utils/managers/overshoot_manager.py +45 -1
  41. pymodaq/utils/managers/preset_manager.py +22 -46
  42. pymodaq/utils/managers/preset_manager_utils.py +17 -13
  43. pymodaq/utils/managers/remote_manager.py +1 -1
  44. pymodaq/utils/messenger.py +6 -0
  45. pymodaq/utils/parameter/__init__.py +5 -1
  46. pymodaq/utils/tcp_ip/mysocket.py +4 -110
  47. pymodaq/utils/tcp_ip/serializer.py +4 -769
  48. pymodaq/utils/tcp_ip/tcp_server_client.py +5 -5
  49. pymodaq-5.0.2.dist-info/METADATA +242 -0
  50. {pymodaq-5.0.0.dist-info → pymodaq-5.0.2.dist-info}/RECORD +54 -55
  51. {pymodaq-5.0.0.dist-info → pymodaq-5.0.2.dist-info}/WHEEL +1 -1
  52. {pymodaq-5.0.0.dist-info → pymodaq-5.0.2.dist-info}/entry_points.txt +1 -0
  53. pymodaq/examples/custom_app.py +0 -255
  54. pymodaq/examples/custom_viewer.py +0 -112
  55. pymodaq/examples/parameter_ex.py +0 -158
  56. pymodaq/examples/preset_MockCamera.xml +0 -1
  57. pymodaq/post_treatment/daq_measurement/daq_measurement_GUI.py +0 -142
  58. pymodaq/post_treatment/daq_measurement/daq_measurement_GUI.ui +0 -232
  59. pymodaq/post_treatment/daq_measurement/daq_measurement_main.py +0 -391
  60. pymodaq/post_treatment/daq_measurement/process_from_QtDesigner_DAQ_Measurement_GUI.bat +0 -2
  61. pymodaq-5.0.0.dist-info/METADATA +0 -166
  62. /pymodaq/{post_treatment/daq_measurement → daq_utils}/__init__.py +0 -0
  63. {pymodaq-5.0.0.dist-info → pymodaq-5.0.2.dist-info}/licenses/LICENSE +0 -0
@@ -4,775 +4,10 @@ Created the 20/10/2023
4
4
 
5
5
  @author: Sebastien Weber
6
6
  """
7
- from base64 import b64encode, b64decode
8
- import numbers
9
- from typing import Tuple, List, Union, TYPE_CHECKING, Iterable
10
7
 
11
- import numpy as np
12
- from pymodaq_data import data as data_mod
13
- from pymodaq_data.data import DataWithAxes, DataToExport, Axis, DwaType
8
+ from pymodaq_utils.utils import deprecation_msg
14
9
 
15
- from pymodaq_gui.parameter import Parameter, utils as putils, ioxml
10
+ from pymodaq_utils.serialize.serializer_legacy import Serializer, DeSerializer, SocketString, Socket
16
11
 
17
- import pymodaq.utils.data as data_mod_pymodaq
18
-
19
- if TYPE_CHECKING:
20
- from pymodaq.utils.tcp_ip.mysocket import Socket
21
-
22
-
23
- SERIALIZABLE = Union[
24
- int,
25
- str,
26
- numbers.Number,
27
- list,
28
- np.ndarray,
29
- Axis,
30
- DataWithAxes,
31
- DataToExport,
32
- ]
33
-
34
-
35
- class SocketString:
36
- """Mimic the Socket object but actually using a bytes string not a socket connection
37
-
38
- Implements a minimal interface of two methods
39
-
40
- Parameters
41
- ----------
42
- bytes_string: bytes
43
-
44
- See Also
45
- --------
46
- :class:`~pymodaq.utils.tcp_ip.mysocket.Socket`
47
- """
48
- def __init__(self, bytes_string: bytes):
49
- self._bytes_string = bytes_string
50
-
51
- def check_received_length(self, length: int) -> bytes:
52
- """
53
- Make sure all bytes (length) that should be received are received through the socket.
54
-
55
- Here just read the content of the underlying bytes string
56
-
57
- Parameters
58
- ----------
59
- length: int
60
- The number of bytes to be read from the socket
61
-
62
- Returns
63
- -------
64
- bytes
65
- """
66
- data = self._bytes_string[0:length]
67
- self._bytes_string = self._bytes_string[length:]
68
- return data
69
-
70
- def get_first_nbytes(self, length: int) -> bytes:
71
- """ Read the first N bytes from the socket
72
-
73
- Parameters
74
- ----------
75
- length: int
76
- The number of bytes to be read from the socket
77
-
78
- Returns
79
- -------
80
- bytes
81
- the read bytes string
82
- """
83
- return self.check_received_length(length)
84
-
85
-
86
- class Serializer:
87
- """Used to Serialize to bytes python objects, numpy arrays and PyMoDAQ DataWithAxes and
88
- DataToExport objects"""
89
-
90
- def __init__(self, obj: SERIALIZABLE = None):
91
- self._bytes_string = b''
92
- self._obj = obj
93
-
94
- def to_bytes(self):
95
- """ Generic method to obtain the bytes string from various objects
96
-
97
- Compatible objects are:
98
-
99
- * :class:`bytes`
100
- * :class:`numbers.Number`
101
- * :class:`str`
102
- * :class:`numpy.ndarray`
103
- * :class:`~pymodaq.utils.data.Axis`
104
- * :class:`~pymodaq.utils.data.DataWithAxes` and sub-flavours
105
- * :class:`~pymodaq.utils.data.DataToExport`
106
- * :class:`list` of any objects above
107
-
108
- """
109
- if isinstance(self._obj, bytes):
110
- return self.bytes_serialization(self._obj)
111
- elif isinstance(self._obj, numbers.Number):
112
- return self.scalar_serialization(self._obj)
113
- elif isinstance(self._obj, str):
114
- return self.string_serialization(self._obj)
115
- elif isinstance(self._obj, np.ndarray):
116
- return self.ndarray_serialization(self._obj)
117
- elif isinstance(self._obj, Axis):
118
- return self.axis_serialization(self._obj)
119
- elif self._obj.__class__.__name__ in DwaType.names():
120
- return self.dwa_serialization(self._obj)
121
- elif isinstance(self._obj, DataToExport):
122
- return self.dte_serialization(self._obj)
123
- elif isinstance(self._obj, list):
124
- return self.list_serialization(self._obj)
125
- elif isinstance(self._obj, bool):
126
- return self.scalar_serialization(int(self._obj))
127
- raise ValueError
128
-
129
- def to_b64_string(self) -> str:
130
- b = self.to_bytes()
131
- return b64encode(b).decode()
132
-
133
- @staticmethod
134
- def int_to_bytes(an_integer: int) -> bytes:
135
- """Convert an unsigned integer into a byte array of length 4 in big endian
136
-
137
- Parameters
138
- ----------
139
- an_integer: int
140
-
141
- Returns
142
- -------
143
- bytearray
144
- """
145
- if not isinstance(an_integer, int):
146
- raise TypeError(f'{an_integer} should be an integer, not a {type(an_integer)}')
147
- elif an_integer < 0:
148
- raise ValueError('Can only serialize unsigned integer using this method')
149
- return an_integer.to_bytes(4, 'big')
150
-
151
- @staticmethod
152
- def str_to_bytes(message: str) -> bytes:
153
- if not isinstance(message, str):
154
- raise TypeError('Can only serialize str object using this method')
155
- return message.encode()
156
-
157
- @classmethod
158
- def str_len_to_bytes(cls, message: Union[str, bytes]) -> (bytes, bytes):
159
- """ Convert a string and its length to two bytes
160
- Parameters
161
- ----------
162
- message: str
163
- the message to convert
164
-
165
- Returns
166
- -------
167
- bytes: message converted as a byte array
168
- bytes: length of the message byte array, itself as a byte array of length 4
169
- """
170
-
171
- if not isinstance(message, str) and not isinstance(message, bytes):
172
- message = str(message)
173
- if not isinstance(message, bytes):
174
- message = cls.str_to_bytes(message)
175
- return message, cls.int_to_bytes(len(message))
176
-
177
- def _int_serialization(self, int_obj: int) -> bytes:
178
- """serialize an unsigned integer used for getting the length of messages internaly, for outside integer
179
- serialization or deserialization use scalar_serialization"""
180
- int_bytes = self.int_to_bytes(int_obj)
181
- bytes_string = int_bytes
182
- self._bytes_string += bytes_string
183
- return bytes_string
184
-
185
- def bytes_serialization(self, bytes_string_in: bytes) -> bytes:
186
- bytes_string = b''
187
- bytes_string += self.int_to_bytes(len(bytes_string_in))
188
- bytes_string += bytes_string_in
189
- return bytes_string
190
-
191
- def string_serialization(self, string: str) -> bytes:
192
- """ Convert a string into a bytes message together with the info to convert it back
193
-
194
- Parameters
195
- ----------
196
- string: str
197
-
198
- Returns
199
- -------
200
- bytes: the total bytes message to serialize the string
201
- """
202
- bytes_string = b''
203
- cmd_bytes, cmd_length_bytes = self.str_len_to_bytes(string)
204
- bytes_string += cmd_length_bytes
205
- bytes_string += cmd_bytes
206
- self._bytes_string += bytes_string
207
- return bytes_string
208
-
209
- def scalar_serialization(self, scalar: numbers.Number) -> bytes:
210
- """ Convert a scalar into a bytes message together with the info to convert it back
211
-
212
- Parameters
213
- ----------
214
- scalar: str
215
-
216
- Returns
217
- -------
218
- bytes: the total bytes message to serialize the scalar
219
- """
220
- if not isinstance(scalar, numbers.Number):
221
- raise TypeError(f'{scalar} should be an integer or a float, not a {type(scalar)}')
222
- scalar_array = np.array([scalar])
223
- data_type = scalar_array.dtype.descr[0][1]
224
- data_bytes = scalar_array.tobytes()
225
-
226
- bytes_string = b''
227
- bytes_string += self.string_serialization(data_type)
228
- bytes_string += self._int_serialization(len(data_bytes))
229
- bytes_string += data_bytes
230
- self._bytes_string += bytes_string
231
- return bytes_string
232
-
233
- def ndarray_serialization(self, array: np.ndarray) -> bytes:
234
- """ Convert a ndarray into a bytes message together with the info to convert it back
235
-
236
- Parameters
237
- ----------
238
- array: np.ndarray
239
-
240
- Returns
241
- -------
242
- bytes: the total bytes message to serialize the scalar
243
-
244
- Notes
245
- -----
246
-
247
- The bytes sequence is constructed as:
248
-
249
- * get data type as a string
250
- * reshape array as 1D array and get the array dimensionality (len of array's shape)
251
- * convert Data array as bytes
252
- * serialize data type
253
- * serialize data length
254
- * serialize data shape length
255
- * serialize all values of the shape as integers converted to bytes
256
- * serialize array as bytes
257
- """
258
- if not isinstance(array, np.ndarray):
259
- raise TypeError(f'{array} should be an numpy array, not a {type(array)}')
260
- array_type = array.dtype.descr[0][1]
261
- array_shape = array.shape
262
-
263
- array = array.reshape(array.size)
264
- array_bytes = array.tobytes()
265
- bytes_string = b''
266
- bytes_string += self.string_serialization(array_type)
267
- bytes_string += self._int_serialization(len(array_bytes))
268
- bytes_string += self._int_serialization(len(array_shape))
269
- for shape_elt in array_shape:
270
- bytes_string += self._int_serialization(shape_elt)
271
- bytes_string += array_bytes
272
- self._bytes_string += bytes_string
273
- return bytes_string
274
-
275
- def object_type_serialization(self, obj: Union[Axis, DataToExport, DataWithAxes]) -> bytes:
276
- """ Convert an object type into a bytes message as a string together with the info to
277
- convert it back
278
-
279
- Applies to Data object from the pymodaq.utils.data module
280
- """
281
- return self.string_serialization(obj.__class__.__name__)
282
-
283
- def axis_serialization(self, axis: Axis) -> bytes:
284
- """ Convert an Axis object into a bytes message together with the info to convert it back
285
-
286
- Parameters
287
- ----------
288
- axis: Axis
289
-
290
- Returns
291
- -------
292
- bytes: the total bytes message to serialize the Axis
293
-
294
- Notes
295
- -----
296
-
297
- The bytes sequence is constructed as:
298
-
299
- * serialize the type: 'Axis'
300
- * serialize the axis label
301
- * serialize the axis units
302
- * serialize the axis array
303
- * serialize the axis
304
- * serialize the axis spread_order
305
- """
306
- if not isinstance(axis, Axis):
307
- raise TypeError(f'{axis} should be a list, not a {type(axis)}')
308
-
309
- bytes_string = b''
310
- bytes_string += self.object_type_serialization(axis)
311
- bytes_string += self.string_serialization(axis.label)
312
- bytes_string += self.string_serialization(axis.units)
313
- bytes_string += self.ndarray_serialization(axis.get_data())
314
- bytes_string += self.scalar_serialization(axis.index)
315
- bytes_string += self.scalar_serialization(axis.spread_order)
316
- self._bytes_string += bytes_string
317
- return bytes_string
318
-
319
- def list_serialization(self, list_object: List) -> bytes:
320
- """ Convert a list of objects into a bytes message together with the info to convert it back
321
-
322
- Parameters
323
- ----------
324
- list_object: list
325
- the list could contains either scalars, strings or ndarrays or Axis objects or DataWithAxis objects
326
- module
327
-
328
- Returns
329
- -------
330
- bytes: the total bytes message to serialize the list of objects
331
-
332
- Notes
333
- -----
334
-
335
- The bytes sequence is constructed as:
336
- * the length of the list
337
-
338
- Then for each object:
339
-
340
- * get data type as a string
341
- * use the serialization method adapted to each object in the list
342
- """
343
- if not isinstance(list_object, list):
344
- raise TypeError(f'{list_object} should be a list, not a {type(list_object)}')
345
-
346
- bytes_string = b''
347
-
348
- bytes_string += self._int_serialization(len(list_object))
349
- for obj in list_object:
350
- bytes_string += self.type_and_object_serialization(obj)
351
- self._bytes_string += bytes_string
352
- return bytes_string
353
-
354
- def type_and_object_serialization(self, obj):
355
- bytes_string = b''
356
- if isinstance(obj, DataWithAxes):
357
- bytes_string += self.string_serialization('dwa')
358
- bytes_string += self.dwa_serialization(obj)
359
-
360
- elif isinstance(obj, Axis):
361
- bytes_string += self.string_serialization('axis')
362
- bytes_string += self.axis_serialization(obj)
363
-
364
- elif isinstance(obj, np.ndarray):
365
- bytes_string += self.string_serialization('array')
366
- bytes_string += self.ndarray_serialization(obj)
367
-
368
- elif isinstance(obj, bytes):
369
- bytes_string += self.string_serialization('bytes')
370
- bytes_string += self.bytes_serialization(obj)
371
-
372
- elif isinstance(obj, str):
373
- bytes_string += self.string_serialization('string')
374
- bytes_string += self.string_serialization(obj)
375
-
376
- elif isinstance(obj, numbers.Number):
377
- bytes_string += self.string_serialization('scalar')
378
- bytes_string += self.scalar_serialization(obj)
379
-
380
- elif isinstance(obj, bool):
381
- bytes_string += self.string_serialization('bool')
382
- bytes_string += self.scalar_serialization(int(obj))
383
-
384
- elif isinstance(obj, list):
385
- bytes_string += self.string_serialization('list')
386
- bytes_string += self.list_serialization(obj)
387
-
388
- elif isinstance(obj, putils.ParameterWithPath):
389
- path = obj.path
390
- param_as_xml = ioxml.parameter_to_xml_string(obj.parameter)
391
- bytes_string += self.string_serialization('parameter')
392
- bytes_string += self.list_serialization(path)
393
- bytes_string += self.string_serialization(param_as_xml)
394
-
395
- elif isinstance(obj, DataToExport):
396
- bytes_string += self.string_serialization('dte')
397
- bytes_string += self.dte_serialization(obj)
398
-
399
- else:
400
- raise TypeError(
401
- f'the element {obj} type cannot be serialized into bytes, only numpy arrays'
402
- f', strings, or scalars (int or float)')
403
-
404
- return bytes_string
405
-
406
- def dwa_serialization(self, dwa: DataWithAxes) -> bytes:
407
- """ Convert a DataWithAxes into a bytes string
408
-
409
- Parameters
410
- ----------
411
- dwa: DataWithAxes
412
-
413
- Returns
414
- -------
415
- bytes: the total bytes message to serialize the DataWithAxes
416
-
417
- Notes
418
- -----
419
- The bytes sequence is constructed as:
420
-
421
- * serialize the string type: 'DataWithAxes'
422
- * serialize the timestamp: float
423
- * serialize the name
424
- * serialize the source enum as a string
425
- * serialize the dim enum as a string
426
- * serialize the distribution enum as a string
427
- * serialize the list of numpy arrays
428
- * serialize the list of labels
429
- * serialize the origin
430
- * serialize the nav_index tuple as a list of int
431
- * serialize the list of axis
432
- * serialize the errors attributes (None or list(np.ndarray))
433
- * serialize the list of names of extra attributes
434
- * serialize the extra attributes
435
- """
436
- if not isinstance(dwa, DataWithAxes):
437
- raise TypeError(f'{dwa} should be a DataWithAxes, not a {type(dwa)}')
438
-
439
- bytes_string = b''
440
- bytes_string += self.object_type_serialization(dwa)
441
- bytes_string += self.scalar_serialization(dwa.timestamp)
442
- bytes_string += self.string_serialization(dwa.name)
443
- bytes_string += self.string_serialization(dwa.source.name)
444
- bytes_string += self.string_serialization(dwa.dim.name)
445
- bytes_string += self.string_serialization(dwa.distribution.name)
446
- bytes_string += self.list_serialization(dwa.data)
447
- bytes_string += self.list_serialization(dwa.labels)
448
- bytes_string += self.string_serialization(dwa.origin)
449
- bytes_string += self.list_serialization(list(dwa.nav_indexes))
450
- bytes_string += self.list_serialization(dwa.axes)
451
- if dwa.errors is None:
452
- errors = [] # have to use this extra attribute as if I force dwa.errors = [], it will be
453
- #internally modified as None again
454
- else:
455
- errors = dwa.errors
456
- bytes_string += self.list_serialization(errors)
457
- bytes_string += self.list_serialization(dwa.extra_attributes)
458
- for attribute in dwa.extra_attributes:
459
- bytes_string += self.type_and_object_serialization(getattr(dwa, attribute))
460
- self._bytes_string += bytes_string
461
- return bytes_string
462
-
463
- def dte_serialization(self, dte: DataToExport) -> bytes:
464
- """ Convert a DataToExport into a bytes string
465
-
466
- Parameters
467
- ----------
468
- dte: DataToExport
469
-
470
- Returns
471
- -------
472
- bytes: the total bytes message to serialize the DataToExport
473
-
474
- Notes
475
- -----
476
- The bytes sequence is constructed as:
477
-
478
- * serialize the string type: 'DataToExport'
479
- * serialize the timestamp: float
480
- * serialize the name
481
- * serialize the list of DataWithAxes
482
- """
483
- if not isinstance(dte, DataToExport):
484
- raise TypeError(f'{dte} should be a DataToExport, not a {type(dte)}')
485
-
486
- bytes_string = b''
487
- bytes_string += self.object_type_serialization(dte)
488
- bytes_string += self.scalar_serialization(dte.timestamp)
489
- bytes_string += self.string_serialization(dte.name)
490
- bytes_string += self.list_serialization(dte.data)
491
- self._bytes_string += bytes_string
492
- return bytes_string
493
-
494
-
495
- class DeSerializer:
496
- """Used to DeSerialize bytes to python objects, numpy arrays and PyMoDAQ Axis, DataWithAxes and DataToExport
497
- objects
498
-
499
- Parameters
500
- ----------
501
- bytes_string: bytes or Socket
502
- the bytes string to deserialize into an object: int, float, string, arrays, list, Axis, DataWithAxes...
503
- Could also be a Socket object reading bytes from the network having a `get_first_nbytes` method
504
-
505
- See Also
506
- --------
507
- :py:class:`~pymodaq.utils.tcp_ip.serializer.SocketString`
508
- :py:class:`~pymodaq.utils.tcp_ip.mysocket.Socket`
509
- """
510
-
511
- def __init__(self, bytes_string: Union[bytes, 'Socket'] = None):
512
- if isinstance(bytes_string, bytes):
513
- bytes_string = SocketString(bytes_string)
514
- self._bytes_string = bytes_string
515
-
516
- @classmethod
517
- def from_b64_string(cls, b64_string: Union[bytes, str]) -> "DeSerializer":
518
- return cls(b64decode(b64_string))
519
-
520
- @staticmethod
521
- def bytes_to_string(message: bytes) -> str:
522
- return message.decode()
523
-
524
- @staticmethod
525
- def bytes_to_int(bytes_string: bytes) -> int:
526
- """Convert a bytes of length 4 into an integer"""
527
- if not isinstance(bytes_string, bytes):
528
- raise TypeError(f'{bytes_string} should be an bytes string, not a {type(bytes_string)}')
529
- assert len(bytes_string) == 4
530
- return int.from_bytes(bytes_string, 'big')
531
-
532
- @staticmethod
533
- def bytes_to_scalar(data: bytes, dtype: np.dtype) -> numbers.Number:
534
- """Convert bytes to a scalar given a certain numpy dtype
535
-
536
- Parameters
537
- ----------
538
- data: bytes
539
- dtype:np.dtype
540
-
541
- Returns
542
- -------
543
- numbers.Number
544
- """
545
- return np.frombuffer(data, dtype=dtype)[0]
546
-
547
- @staticmethod
548
- def bytes_to_nd_array(data: bytes, dtype: np.dtype, shape: Tuple[int]) -> np.ndarray:
549
- """Convert bytes to a ndarray given a certain numpy dtype and shape
550
-
551
- Parameters
552
- ----------
553
- data: bytes
554
- dtype: np.dtype
555
- shape: tuple of int
556
-
557
- Returns
558
- -------
559
- np.ndarray
560
- """
561
- array = np.frombuffer(data, dtype=dtype)
562
- array = array.reshape(tuple(shape))
563
- array = np.atleast_1d(array) # remove singleton dimensions but keeping ndarrays
564
- return array
565
-
566
- def _int_deserialization(self) -> int:
567
- """Convert the fourth first bytes into an unsigned integer to be used internally. For integer serialization
568
- use scal_serialization"""
569
- int_obj = self.bytes_to_int(self._bytes_string.get_first_nbytes(4))
570
- return int_obj
571
-
572
- def bytes_deserialization(self) -> bytes:
573
- bstring_len = self._int_deserialization()
574
- bstr = self._bytes_string.get_first_nbytes(bstring_len)
575
- return bstr
576
-
577
- def string_deserialization(self) -> str:
578
- """Convert bytes into a str object
579
-
580
- Convert first the fourth first bytes into an int encoding the length of the string to decode
581
-
582
- Returns
583
- -------
584
- str: the decoded string
585
- """
586
- string_len = self._int_deserialization()
587
- str_obj = self._bytes_string.get_first_nbytes(string_len).decode()
588
- return str_obj
589
-
590
- def scalar_deserialization(self) -> numbers.Number:
591
- """Convert bytes into a numbers.Number object
592
-
593
- Get first the data type from a string deserialization, then the data length and finally convert this
594
- length of bytes into a number (float, int)
595
-
596
- Returns
597
- -------
598
- numbers.Number: the decoded number
599
- """
600
- data_type = self.string_deserialization()
601
- data_len = self._int_deserialization()
602
- number = np.frombuffer(self._bytes_string.get_first_nbytes(data_len), dtype=data_type)[0]
603
- if 'f' in data_type:
604
- number = float(number) # because one get numpy float type
605
- elif 'i' in data_type:
606
- number = int(number) # because one get numpy int type
607
- return number
608
-
609
- def boolean_deserialization(self) -> bool:
610
- """Convert bytes into a boolean object
611
-
612
- Get first the data type from a string deserialization, then the data length and finally
613
- convert this length of bytes into a number (float, int) and cast it to a bool
614
-
615
- Returns
616
- -------
617
- bool: the decoded boolean
618
- """
619
- number = self.scalar_deserialization()
620
- return bool(number)
621
-
622
- def ndarray_deserialization(self) -> np.ndarray:
623
- """Convert bytes into a numpy ndarray object
624
-
625
- Convert the first bytes into a ndarray reading first information about the array's data
626
-
627
- Returns
628
- -------
629
- ndarray: the decoded numpy array
630
- """
631
- ndarray_type = self.string_deserialization()
632
- ndarray_len = self._int_deserialization()
633
- shape_len = self._int_deserialization()
634
- shape = []
635
- for ind in range(shape_len):
636
- shape_elt = self._int_deserialization()
637
- shape.append(shape_elt)
638
-
639
- ndarray = np.frombuffer(self._bytes_string.get_first_nbytes(ndarray_len), dtype=ndarray_type)
640
- ndarray = ndarray.reshape(tuple(shape))
641
- ndarray = np.atleast_1d(ndarray) # remove singleton dimensions
642
- return ndarray
643
-
644
- def type_and_object_deserialization(self):
645
- """ Deserialize specific objects from their binary representation (inverse of `Serializer.type_and_object_serialization`).
646
-
647
- See Also
648
- --------
649
- Serializer.dwa_serialization, Serializer.dte_serialization
650
-
651
- """
652
- obj_type = self.string_deserialization()
653
- elt = None
654
- if obj_type == 'scalar':
655
- elt = self.scalar_deserialization()
656
- elif obj_type == 'string':
657
- elt = self.string_deserialization()
658
- elif obj_type == 'bytes':
659
- elt = self.bytes_deserialization()
660
- elif obj_type == 'array':
661
- elt = self.ndarray_deserialization()
662
- elif obj_type == 'dwa':
663
- elt = self.dwa_deserialization()
664
- elif obj_type == 'dte':
665
- elt = self.dte_deserialization()
666
- elif obj_type == 'axis':
667
- elt = self.axis_deserialization()
668
- elif obj_type == 'bool':
669
- elt = self.boolean_deserialization()
670
- elif obj_type == 'list':
671
- elt = self.list_deserialization()
672
- elif obj_type == 'parameter':
673
- elt = self.parameter_deserialization()
674
- else:
675
- print(f'invalid object type {obj_type}')
676
- return elt
677
-
678
- def list_deserialization(self) -> list:
679
- """Convert bytes into a list of homogeneous objects
680
-
681
- Convert the first bytes into a list reading first information about the list elt types, length ...
682
-
683
- Returns
684
- -------
685
- list: the decoded list
686
- """
687
- list_obj = []
688
- list_len = self._int_deserialization()
689
-
690
- for ind in range(list_len):
691
- list_obj.append(self.type_and_object_deserialization())
692
- return list_obj
693
-
694
- def parameter_deserialization(self) -> putils.ParameterWithPath:
695
- path = self.list_deserialization()
696
- param_as_xml = self.string_deserialization()
697
- param_dict = ioxml.XML_string_to_parameter(param_as_xml)
698
- param_obj = Parameter(**param_dict[0])
699
- return putils.ParameterWithPath(param_obj, path)
700
-
701
- def axis_deserialization(self) -> Axis:
702
- """Convert bytes into an Axis object
703
-
704
- Convert the first bytes into an Axis reading first information about the Axis
705
-
706
- Returns
707
- -------
708
- Axis: the decoded Axis
709
- """
710
-
711
- class_name = self.string_deserialization()
712
- if class_name != Axis.__name__:
713
- raise TypeError(f'Attempting to deserialize an Axis but got the bytes for a {class_name}')
714
- axis_label = self.string_deserialization()
715
- axis_units = self.string_deserialization()
716
- axis_array = self.ndarray_deserialization()
717
- axis_index = self.scalar_deserialization()
718
- axis_spread_order = self.scalar_deserialization()
719
-
720
- axis = Axis(axis_label, axis_units, data=axis_array, index=axis_index,
721
- spread_order=axis_spread_order)
722
- return axis
723
-
724
- def dwa_deserialization(self) -> DataWithAxes:
725
- """Convert bytes into a DataWithAxes object
726
-
727
- Convert the first bytes into a DataWithAxes reading first information about the underlying data
728
-
729
- Returns
730
- -------
731
- DataWithAxes: the decoded DataWithAxes
732
- """
733
- class_name = self.string_deserialization()
734
- if class_name not in DwaType.names():
735
- raise TypeError(f'Attempting to deserialize a DataWithAxes flavor but got the bytes for a {class_name}')
736
- timestamp = self.scalar_deserialization()
737
- try:
738
- dwa_class = getattr(data_mod, class_name)
739
- except AttributeError: # in case it is a particular data object defined only in pymodaq
740
- dwa_class = getattr(data_mod_pymodaq, class_name)
741
- dwa = dwa_class(self.string_deserialization(),
742
- source=self.string_deserialization(),
743
- dim=self.string_deserialization(),
744
- distribution=self.string_deserialization(),
745
- data=self.list_deserialization(),
746
- labels=self.list_deserialization(),
747
- origin=self.string_deserialization(),
748
- nav_indexes=tuple(self.list_deserialization()),
749
- axes=self.list_deserialization(),
750
- )
751
- errors = self.list_deserialization()
752
- if len(errors) != 0:
753
- dwa.errors = errors
754
- dwa.extra_attributes = self.list_deserialization()
755
- for attribute in dwa.extra_attributes:
756
- setattr(dwa, attribute, self.type_and_object_deserialization())
757
-
758
- dwa.timestamp = timestamp
759
- return dwa
760
-
761
- def dte_deserialization(self) -> DataToExport:
762
- """Convert bytes into a DataToExport object
763
-
764
- Convert the first bytes into a DataToExport reading first information about the underlying data
765
-
766
- Returns
767
- -------
768
- DataToExport: the decoded DataToExport
769
- """
770
- class_name = self.string_deserialization()
771
- if class_name != DataToExport.__name__:
772
- raise TypeError(f'Attempting to deserialize a DataToExport but got the bytes for a {class_name}')
773
- timestamp = self.scalar_deserialization()
774
- dte = DataToExport(self.string_deserialization(),
775
- data=self.list_deserialization(),
776
- )
777
- dte.timestamp = timestamp
778
- return dte
12
+ deprecation_msg('Importing Serializer, DeSerializer from pymodaq is deprecated in PyMoDAQ >= 5,'
13
+ 'import them from pymodaq_data.serialize.serializer')