pymodaq 4.1.1__py3-none-any.whl → 4.1.4__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/examples/parameter_ex.py +7 -3
- pymodaq/extensions/daq_scan.py +6 -1
- pymodaq/extensions/h5browser.py +18 -8
- pymodaq/resources/VERSION +1 -1
- pymodaq/utils/data.py +4 -0
- pymodaq/utils/h5modules/browsing.py +3 -2
- pymodaq/utils/h5modules/data_saving.py +2 -1
- pymodaq/utils/h5modules/exporters/base.py +7 -1
- pymodaq/utils/parameter/ioxml.py +5 -1
- pymodaq/utils/parameter/pymodaq_ptypes/__init__.py +11 -9
- pymodaq/utils/parameter/pymodaq_ptypes/bool.py +7 -1
- pymodaq/utils/parameter/pymodaq_ptypes/pixmap.py +14 -0
- pymodaq/utils/parameter/pymodaq_ptypes/slide.py +9 -2
- pymodaq/utils/scanner/scanners/tabular.py +7 -8
- pymodaq/utils/tcp_ip/serializer.py +83 -33
- {pymodaq-4.1.1.dist-info → pymodaq-4.1.4.dist-info}/METADATA +4 -4
- {pymodaq-4.1.1.dist-info → pymodaq-4.1.4.dist-info}/RECORD +20 -20
- {pymodaq-4.1.1.dist-info → pymodaq-4.1.4.dist-info}/WHEEL +1 -1
- {pymodaq-4.1.1.dist-info → pymodaq-4.1.4.dist-info}/entry_points.txt +0 -0
- {pymodaq-4.1.1.dist-info → pymodaq-4.1.4.dist-info}/licenses/LICENSE +0 -0
pymodaq/examples/parameter_ex.py
CHANGED
|
@@ -51,11 +51,15 @@ class ParameterEx(ParameterManager):
|
|
|
51
51
|
{'title': 'An action', 'name': 'action', 'type': 'action'}, # action whose displayed text corresponds to title
|
|
52
52
|
|
|
53
53
|
{'title': 'Lists:', 'name': 'lists', 'type': 'group', 'children': [
|
|
54
|
-
{'title': 'Standard list:', 'name': 'alist', 'type': 'list',
|
|
55
|
-
|
|
54
|
+
{'title': 'Standard list:', 'name': 'alist', 'type': 'list',
|
|
55
|
+
'limits': ['a value', 'another one'], 'value': 'a value'},
|
|
56
|
+
{'title': 'List with add:', 'name': 'anotherlist', 'type': 'list',
|
|
57
|
+
'limits': ['a value', 'another one'], 'value': 'a value',
|
|
56
58
|
'show_pb': True, 'tip': 'when using the "show_pb" option, displays a plus button to add elt to the list'},
|
|
57
59
|
{'title': 'List defined from a dict:', 'name': 'dict_list', 'type': 'list',
|
|
58
|
-
'limits': {'xaxis': 0, 'yaxis': [0, 1, 2]},
|
|
60
|
+
'limits': {'xaxis': 0, 'yaxis': [0, 1, 2]},
|
|
61
|
+
'value': 'yaxis',
|
|
62
|
+
'tip': 'Such a parameter display text that are keys of a dict while'
|
|
59
63
|
'values could be any object'
|
|
60
64
|
},
|
|
61
65
|
]},
|
pymodaq/extensions/daq_scan.py
CHANGED
|
@@ -570,7 +570,12 @@ class DAQScan(QObject, ParameterManager):
|
|
|
570
570
|
print(f'clicked at: {posx}, {posy}')
|
|
571
571
|
positions = [posx, posy]
|
|
572
572
|
positions = positions[:self.scanner.n_axes]
|
|
573
|
-
self.modules_manager.
|
|
573
|
+
actuators = self.modules_manager.actuators
|
|
574
|
+
dte = DataToExport(name="move_at")
|
|
575
|
+
for ind, pos in enumerate(positions):
|
|
576
|
+
dte.append(DataActuator(actuators[ind].title, data=float(pos)))
|
|
577
|
+
|
|
578
|
+
self.modules_manager.move_actuators(dte)
|
|
574
579
|
|
|
575
580
|
def value_changed(self, param):
|
|
576
581
|
"""
|
pymodaq/extensions/h5browser.py
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
from pathlib import Path
|
|
1
3
|
import sys
|
|
4
|
+
|
|
2
5
|
from qtpy import QtWidgets
|
|
6
|
+
|
|
3
7
|
from pymodaq.utils.h5modules.browsing import H5Browser
|
|
4
8
|
from pymodaq.utils.config import Config
|
|
5
|
-
from pathlib import Path
|
|
6
|
-
|
|
7
|
-
config = Config()
|
|
8
9
|
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
win = QtWidgets.QMainWindow()
|
|
12
|
-
prog = H5Browser(win, h5file_path=h5file_path)
|
|
13
|
-
win.show()
|
|
11
|
+
config = Config()
|
|
14
12
|
|
|
15
13
|
|
|
16
14
|
def main(h5file_path: Path = None):
|
|
@@ -19,8 +17,20 @@ def main(h5file_path: Path = None):
|
|
|
19
17
|
import qdarkstyle
|
|
20
18
|
app.setStyleSheet(qdarkstyle.load_stylesheet())
|
|
21
19
|
|
|
20
|
+
h5file_path_tmp = None
|
|
21
|
+
parser = argparse.ArgumentParser(description="Opens HDF5 files and navigate their contents")
|
|
22
|
+
parser.add_argument("-i", "--input", help="specify path to the file to be opened")
|
|
23
|
+
args = parser.parse_args()
|
|
24
|
+
|
|
25
|
+
if args.input:
|
|
26
|
+
h5file_path_tmp = Path(args.input).resolve() # Transform to absolute Path in case it is relative
|
|
27
|
+
|
|
28
|
+
if not h5file_path_tmp.exists():
|
|
29
|
+
print(f'Error: {args.input} does not exist. Opening h5browser without input file.')
|
|
30
|
+
h5file_path_tmp = h5file_path
|
|
31
|
+
|
|
22
32
|
win = QtWidgets.QMainWindow()
|
|
23
|
-
prog = H5Browser(win, h5file_path=
|
|
33
|
+
prog = H5Browser(win, h5file_path=h5file_path_tmp)
|
|
24
34
|
win.show()
|
|
25
35
|
QtWidgets.QApplication.processEvents()
|
|
26
36
|
sys.exit(app.exec_())
|
pymodaq/resources/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
version = '4.1.
|
|
1
|
+
version = '4.1.4'
|
pymodaq/utils/data.py
CHANGED
|
@@ -647,6 +647,10 @@ class DataBase(DataLowLevel):
|
|
|
647
647
|
eq = False
|
|
648
648
|
break
|
|
649
649
|
eq = eq and np.all(getattr(self[ind], operator)(other[ind]))
|
|
650
|
+
# extra attributes are not relevant as they may contain module specific data...
|
|
651
|
+
# eq = eq and (self.extra_attributes == other.extra_attributes)
|
|
652
|
+
# for attribute in self.extra_attributes:
|
|
653
|
+
# eq = eq and (getattr(self, attribute) == getattr(other, attribute))
|
|
650
654
|
return eq
|
|
651
655
|
elif isinstance(other, numbers.Number):
|
|
652
656
|
return np.all(getattr(self[0], operator)(other))
|
|
@@ -464,7 +464,8 @@ class H5Browser(QObject, ActionManager):
|
|
|
464
464
|
child.remove()
|
|
465
465
|
params = []
|
|
466
466
|
for attr in attr_dict:
|
|
467
|
-
params.append({'title': attr, 'name': attr, 'type': 'str', 'value': attr_dict[attr],
|
|
467
|
+
params.append({'title': attr, 'name': attr, 'type': 'str', 'value': attr_dict[attr],
|
|
468
|
+
'readonly': True})
|
|
468
469
|
self.settings_attributes.settings.addChildren(params)
|
|
469
470
|
|
|
470
471
|
if settings is not None:
|
|
@@ -525,7 +526,7 @@ class H5Browser(QObject, ActionManager):
|
|
|
525
526
|
self.view.text_list.clear()
|
|
526
527
|
for txt in node.read():
|
|
527
528
|
self.view.text_list.addItem(txt)
|
|
528
|
-
|
|
529
|
+
elif 'data_type' in node.attrs:
|
|
529
530
|
data_with_axes = self.data_loader.load_data(node, with_bkg=with_bkg, load_all=plot_all)
|
|
530
531
|
self.hyper_viewer.show_data(data_with_axes, force_update=True)
|
|
531
532
|
|
|
@@ -388,7 +388,7 @@ class DataSaverLoader(DataManagement):
|
|
|
388
388
|
extra_attributes = data_node.attrs.to_dict()
|
|
389
389
|
for name in ['TITLE', 'CLASS', 'VERSION', 'backend', 'source', 'data_dimension',
|
|
390
390
|
'distribution', 'label', 'origin', 'nav_indexes', 'dtype', 'data_type',
|
|
391
|
-
'subdtype', 'shape', 'size', 'EXTDIM', 'path']:
|
|
391
|
+
'subdtype', 'shape', 'size', 'EXTDIM', 'path', 'timestamp']:
|
|
392
392
|
extra_attributes.pop(name, None)
|
|
393
393
|
|
|
394
394
|
data = DataWithAxes(data_node.attrs['TITLE'],
|
|
@@ -404,6 +404,7 @@ class DataSaverLoader(DataManagement):
|
|
|
404
404
|
axes=axes,
|
|
405
405
|
path=data_node.path,
|
|
406
406
|
**extra_attributes)
|
|
407
|
+
data.timestamp = data_node.attrs['timestamp']
|
|
407
408
|
return data
|
|
408
409
|
|
|
409
410
|
|
|
@@ -38,8 +38,14 @@ class H5h5Exporter(H5Exporter):
|
|
|
38
38
|
new_file = H5Backend(backend="tables")
|
|
39
39
|
new_file.open_file(str(filename), 'a')
|
|
40
40
|
|
|
41
|
-
new_file.h5file.move_node(
|
|
41
|
+
new_file.h5file.move_node(new_file.get_node_path(node), newparent='/')
|
|
42
42
|
new_file.h5file.remove_node('/RawData', recursive=True)
|
|
43
|
+
new_file.flush()
|
|
44
|
+
|
|
45
|
+
new_file.get_set_group('/', 'RawData')
|
|
46
|
+
new_file.h5file.move_node(f'/{node.name}',
|
|
47
|
+
newparent='/RawData')
|
|
48
|
+
|
|
43
49
|
new_file.close_file()
|
|
44
50
|
|
|
45
51
|
|
pymodaq/utils/parameter/ioxml.py
CHANGED
|
@@ -466,6 +466,9 @@ def set_txt_from_elt(el, param_dict):
|
|
|
466
466
|
else:
|
|
467
467
|
param_value = val_text
|
|
468
468
|
param_dict.update(dict(value=param_value))
|
|
469
|
+
else:
|
|
470
|
+
if param_type == 'str':
|
|
471
|
+
param_dict.update(dict(value=''))
|
|
469
472
|
|
|
470
473
|
|
|
471
474
|
def XML_file_to_parameter(file_name: Union[str, Path]) -> list:
|
|
@@ -535,4 +538,5 @@ def XML_string_to_pobject(xml_string) -> Parameter:
|
|
|
535
538
|
--------
|
|
536
539
|
parameter_to_xml_string
|
|
537
540
|
"""
|
|
538
|
-
return Parameter.create(name='settings', type='group',
|
|
541
|
+
return Parameter.create(name='settings', type='group',
|
|
542
|
+
children=XML_string_to_parameter(xml_string))
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
from pyqtgraph.parametertree.parameterTypes.basetypes import SimpleParameter, GroupParameter,
|
|
2
|
-
|
|
3
|
-
from .
|
|
4
|
-
from .
|
|
1
|
+
from pyqtgraph.parametertree.parameterTypes.basetypes import (SimpleParameter, GroupParameter,
|
|
2
|
+
GroupParameterItem)
|
|
3
|
+
from .bool import BoolPushParameter
|
|
4
|
+
from .pixmap import PixmapParameter, PixmapCheckParameter
|
|
5
|
+
from .slide import SliderSpinBox, SliderParameter
|
|
5
6
|
from .led import LedPushParameter, LedParameter
|
|
6
7
|
from .date import DateParameter, DateTimeParameter, TimeParameter
|
|
7
8
|
from .list import ListParameter
|
|
@@ -12,14 +13,15 @@ from .filedir import FileDirParameter
|
|
|
12
13
|
from .text import PlainTextPbParameter
|
|
13
14
|
from .numeric import NumericParameter
|
|
14
15
|
|
|
15
|
-
from pyqtgraph.parametertree.Parameter import registerParameterType, registerParameterItemType
|
|
16
|
+
from pyqtgraph.parametertree.Parameter import registerParameterType, registerParameterItemType, Parameter
|
|
16
17
|
|
|
17
18
|
registerParameterType('float', NumericParameter, override=True)
|
|
18
19
|
registerParameterType('int', NumericParameter, override=True)
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
registerParameterType('bool_push', BoolPushParameter, override=True)
|
|
21
|
+
registerParameterType('pixmap', PixmapParameter, override=True)
|
|
22
|
+
registerParameterType('pixmap_check', PixmapCheckParameter, override=True)
|
|
23
|
+
|
|
24
|
+
registerParameterType('slide', SliderParameter, override=True)
|
|
23
25
|
|
|
24
26
|
registerParameterType('led', LedParameter, override=True)
|
|
25
27
|
registerParameterType('led_push', LedPushParameter, override=True)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from qtpy import QtWidgets
|
|
2
|
-
from pyqtgraph.parametertree.parameterTypes.basetypes import WidgetParameterItem
|
|
2
|
+
from pyqtgraph.parametertree.parameterTypes.basetypes import WidgetParameterItem, SimpleParameter
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
class BoolPushParameterItem(WidgetParameterItem):
|
|
@@ -23,3 +23,9 @@ class BoolPushParameterItem(WidgetParameterItem):
|
|
|
23
23
|
self.hideWidget = False
|
|
24
24
|
return w
|
|
25
25
|
|
|
26
|
+
|
|
27
|
+
class BoolPushParameter(SimpleParameter):
|
|
28
|
+
itemClass = BoolPushParameterItem
|
|
29
|
+
|
|
30
|
+
def __init__(self, *args, **kwargs):
|
|
31
|
+
super().__init__(*args, **kwargs)
|
|
@@ -111,6 +111,20 @@ class PixmapCheckParameterItem(WidgetParameterItem):
|
|
|
111
111
|
return w
|
|
112
112
|
|
|
113
113
|
|
|
114
|
+
class PixmapCheckParameter(SimpleParameter):
|
|
115
|
+
itemClass = PixmapCheckParameterItem
|
|
116
|
+
|
|
117
|
+
def __init__(self, **kwargs):
|
|
118
|
+
super().__init__(**kwargs)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class PixmapParameter(SimpleParameter):
|
|
122
|
+
itemClass = PixmapParameterItem
|
|
123
|
+
|
|
124
|
+
def __init__(self, **kwargs):
|
|
125
|
+
super().__init__(**kwargs)
|
|
126
|
+
|
|
127
|
+
|
|
114
128
|
def main_widget():
|
|
115
129
|
import sys
|
|
116
130
|
app = QtWidgets.QApplication(sys.argv)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from qtpy import QtWidgets, QtCore
|
|
2
2
|
from pyqtgraph.widgets.SpinBox import SpinBox
|
|
3
|
-
from pyqtgraph.parametertree.parameterTypes.basetypes import WidgetParameterItem
|
|
3
|
+
from pyqtgraph.parametertree.parameterTypes.basetypes import WidgetParameterItem, SimpleParameter
|
|
4
4
|
from pymodaq.utils.parameter.utils import scroll_log, scroll_linear
|
|
5
5
|
import numpy as np
|
|
6
6
|
|
|
@@ -135,4 +135,11 @@ class SliderParameterItem(WidgetParameterItem):
|
|
|
135
135
|
|
|
136
136
|
w = SliderSpinBox(subtype=opts['subtype'], bounds=defs['bounds'], value=defs['value'], int=defs['int'])
|
|
137
137
|
self.setSizeHint(1, QtCore.QSize(50, 50))
|
|
138
|
-
return w
|
|
138
|
+
return w
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
class SliderParameter(SimpleParameter):
|
|
142
|
+
itemClass = SliderParameterItem
|
|
143
|
+
|
|
144
|
+
def __init__(self, **kwargs):
|
|
145
|
+
super().__init__(**kwargs)
|
|
@@ -107,7 +107,6 @@ class TabularScanner(ScannerBase):
|
|
|
107
107
|
self.table_model: TableModelTabular = None
|
|
108
108
|
self.table_view: TableViewCustom = None
|
|
109
109
|
super().__init__(actuators=actuators)
|
|
110
|
-
self.update_model()
|
|
111
110
|
|
|
112
111
|
@property
|
|
113
112
|
def actuators(self):
|
|
@@ -209,13 +208,15 @@ class TabularScanner(ScannerBase):
|
|
|
209
208
|
|
|
210
209
|
|
|
211
210
|
@ScannerFactory.register()
|
|
212
|
-
class
|
|
213
|
-
|
|
211
|
+
class TabularScannerSubSegmented(TabularScanner):
|
|
212
|
+
|
|
213
|
+
scan_subtype = 'SubSegmented'
|
|
214
214
|
save_settings = False
|
|
215
215
|
params = [{'title': 'Step:', 'name': 'tabular_step', 'type': 'float', 'value': 0.1},
|
|
216
|
-
{'title': 'Points', 'name': 'tabular_points', 'type': 'table_view',
|
|
216
|
+
{'title': 'Points', 'name': 'tabular_points', 'type': 'table_view',
|
|
217
|
+
'delegate': gutils.SpinBoxDelegate,
|
|
217
218
|
'menu': True},
|
|
218
|
-
|
|
219
|
+
] + TabularScanner.params
|
|
219
220
|
|
|
220
221
|
def __init__(self, actuators: List[str]):
|
|
221
222
|
self.table_model: TableModelTabularReadOnly = None
|
|
@@ -223,8 +224,6 @@ class TabularScannerSubsegmented(TabularScanner):
|
|
|
223
224
|
self.table_model_points: TableModelTabular = None
|
|
224
225
|
self.table_view_points: TableViewCustom = None
|
|
225
226
|
super().__init__(actuators=actuators)
|
|
226
|
-
self.update_model()
|
|
227
|
-
self.update_model_points()
|
|
228
227
|
|
|
229
228
|
@property
|
|
230
229
|
def actuators(self):
|
|
@@ -295,4 +294,4 @@ class TabularScannerSubsegmented(TabularScanner):
|
|
|
295
294
|
def update_from_scan_selector(self, scan_selector: Selector):
|
|
296
295
|
coordinates = scan_selector.get_coordinates()
|
|
297
296
|
self.update_model_points(init_data=coordinates)
|
|
298
|
-
self.set_scan()
|
|
297
|
+
self.set_scan()
|
|
@@ -5,7 +5,7 @@ Created the 20/10/2023
|
|
|
5
5
|
@author: Sebastien Weber
|
|
6
6
|
"""
|
|
7
7
|
import numbers
|
|
8
|
-
from typing import Tuple, List, Union, TYPE_CHECKING
|
|
8
|
+
from typing import Tuple, List, Union, TYPE_CHECKING, Iterable
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
import numpy as np
|
|
@@ -105,6 +105,8 @@ class Serializer:
|
|
|
105
105
|
return self.dte_serialization(self._obj)
|
|
106
106
|
elif isinstance(self._obj, list):
|
|
107
107
|
return self.list_serialization(self._obj)
|
|
108
|
+
elif isinstance(self._obj, bool):
|
|
109
|
+
return self.scalar_serialization(int(self._obj))
|
|
108
110
|
|
|
109
111
|
@staticmethod
|
|
110
112
|
def int_to_bytes(an_integer: int) -> bytes:
|
|
@@ -322,30 +324,45 @@ class Serializer:
|
|
|
322
324
|
|
|
323
325
|
bytes_string += self._int_serialization(len(list_object))
|
|
324
326
|
for obj in list_object:
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
327
|
+
bytes_string += self.type_and_object_serialization(obj)
|
|
328
|
+
self._bytes_string += bytes_string
|
|
329
|
+
return bytes_string
|
|
328
330
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
331
|
+
def type_and_object_serialization(self, obj):
|
|
332
|
+
bytes_string = b''
|
|
333
|
+
if isinstance(obj, DataWithAxes):
|
|
334
|
+
bytes_string += self.string_serialization('dwa')
|
|
335
|
+
bytes_string += self.dwa_serialization(obj)
|
|
332
336
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
337
|
+
elif isinstance(obj, Axis):
|
|
338
|
+
bytes_string += self.string_serialization('axis')
|
|
339
|
+
bytes_string += self.axis_serialization(obj)
|
|
336
340
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
341
|
+
elif isinstance(obj, np.ndarray):
|
|
342
|
+
bytes_string += self.string_serialization('array')
|
|
343
|
+
bytes_string += self.ndarray_serialization(obj)
|
|
340
344
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
345
|
+
elif isinstance(obj, str):
|
|
346
|
+
bytes_string += self.string_serialization('string')
|
|
347
|
+
bytes_string += self.string_serialization(obj)
|
|
348
|
+
|
|
349
|
+
elif isinstance(obj, numbers.Number):
|
|
350
|
+
bytes_string += self.string_serialization('scalar')
|
|
351
|
+
bytes_string += self.scalar_serialization(obj)
|
|
352
|
+
|
|
353
|
+
elif isinstance(obj, bool):
|
|
354
|
+
bytes_string += self.string_serialization('bool')
|
|
355
|
+
bytes_string += self.scalar_serialization(int(obj))
|
|
356
|
+
|
|
357
|
+
elif isinstance(obj, list):
|
|
358
|
+
bytes_string += self.string_serialization('list')
|
|
359
|
+
bytes_string += self.list_serialization(obj)
|
|
360
|
+
|
|
361
|
+
else:
|
|
362
|
+
raise TypeError(
|
|
363
|
+
f'the element {obj} type cannot be serialized into bytes, only numpy arrays'
|
|
364
|
+
f', strings, or scalars (int or float)')
|
|
344
365
|
|
|
345
|
-
else:
|
|
346
|
-
raise TypeError(f'the element {obj} type cannot be serialized into bytes, only numpy arrays'
|
|
347
|
-
f', strings, or scalars (int or float)')
|
|
348
|
-
self._bytes_string += bytes_string
|
|
349
366
|
return bytes_string
|
|
350
367
|
|
|
351
368
|
def dwa_serialization(self, dwa: DataWithAxes) -> bytes:
|
|
@@ -374,6 +391,8 @@ class Serializer:
|
|
|
374
391
|
* serialize the origin
|
|
375
392
|
* serialize the nav_index tuple as a list of int
|
|
376
393
|
* serialize the list of axis
|
|
394
|
+
* serialize the list of names of extra attributes
|
|
395
|
+
* serialize the extra attributes
|
|
377
396
|
"""
|
|
378
397
|
if not isinstance(dwa, DataWithAxes):
|
|
379
398
|
raise TypeError(f'{dwa} should be a DataWithAxes, not a {type(dwa)}')
|
|
@@ -390,6 +409,9 @@ class Serializer:
|
|
|
390
409
|
bytes_string += self.string_serialization(dwa.origin)
|
|
391
410
|
bytes_string += self.list_serialization(list(dwa.nav_indexes))
|
|
392
411
|
bytes_string += self.list_serialization(dwa.axes)
|
|
412
|
+
bytes_string += self.list_serialization(dwa.extra_attributes)
|
|
413
|
+
for attribute in dwa.extra_attributes:
|
|
414
|
+
bytes_string += self.type_and_object_serialization(getattr(dwa, attribute))
|
|
393
415
|
self._bytes_string += bytes_string
|
|
394
416
|
return bytes_string
|
|
395
417
|
|
|
@@ -530,6 +552,19 @@ class DeSerializer:
|
|
|
530
552
|
number = int(number) # because one get numpy int type
|
|
531
553
|
return number
|
|
532
554
|
|
|
555
|
+
def boolean_deserialization(self) -> bool:
|
|
556
|
+
"""Convert bytes into a boolean object
|
|
557
|
+
|
|
558
|
+
Get first the data type from a string deserialization, then the data length and finally
|
|
559
|
+
convert this length of bytes into a number (float, int) and cast it to a bool
|
|
560
|
+
|
|
561
|
+
Returns
|
|
562
|
+
-------
|
|
563
|
+
bool: the decoded boolean
|
|
564
|
+
"""
|
|
565
|
+
number = self.scalar_deserialization()
|
|
566
|
+
return bool(number)
|
|
567
|
+
|
|
533
568
|
def ndarray_deserialization(self) -> np.ndarray:
|
|
534
569
|
"""Convert bytes into a numpy ndarray object
|
|
535
570
|
|
|
@@ -552,6 +587,27 @@ class DeSerializer:
|
|
|
552
587
|
ndarray = np.atleast_1d(ndarray) # remove singleton dimensions
|
|
553
588
|
return ndarray
|
|
554
589
|
|
|
590
|
+
def object_deserialization(self):
|
|
591
|
+
obj_type = self.string_deserialization()
|
|
592
|
+
elt = None
|
|
593
|
+
if obj_type == 'scalar':
|
|
594
|
+
elt = self.scalar_deserialization()
|
|
595
|
+
elif obj_type == 'string':
|
|
596
|
+
elt = self.string_deserialization()
|
|
597
|
+
elif obj_type == 'array':
|
|
598
|
+
elt = self.ndarray_deserialization()
|
|
599
|
+
elif obj_type == 'dwa':
|
|
600
|
+
elt = self.dwa_deserialization()
|
|
601
|
+
elif obj_type == 'axis':
|
|
602
|
+
elt = self.axis_deserialization()
|
|
603
|
+
elif obj_type == 'bool':
|
|
604
|
+
elt = self.boolean_deserialization()
|
|
605
|
+
elif obj_type == 'list':
|
|
606
|
+
elt = self.list_deserialization()
|
|
607
|
+
else:
|
|
608
|
+
print(f'invalid object type {obj_type}')
|
|
609
|
+
return elt
|
|
610
|
+
|
|
555
611
|
def list_deserialization(self) -> list:
|
|
556
612
|
"""Convert bytes into a list of homogeneous objects
|
|
557
613
|
|
|
@@ -565,18 +621,7 @@ class DeSerializer:
|
|
|
565
621
|
list_len = self._int_deserialization()
|
|
566
622
|
|
|
567
623
|
for ind in range(list_len):
|
|
568
|
-
|
|
569
|
-
if obj_type == 'scalar':
|
|
570
|
-
list_elt = self.scalar_deserialization()
|
|
571
|
-
elif obj_type == 'string':
|
|
572
|
-
list_elt = self.string_deserialization()
|
|
573
|
-
elif obj_type == 'array':
|
|
574
|
-
list_elt = self.ndarray_deserialization()
|
|
575
|
-
elif obj_type == 'dwa':
|
|
576
|
-
list_elt = self.dwa_deserialization()
|
|
577
|
-
elif obj_type == 'axis':
|
|
578
|
-
list_elt = self.axis_deserialization()
|
|
579
|
-
list_obj.append(list_elt)
|
|
624
|
+
list_obj.append(self.object_deserialization())
|
|
580
625
|
return list_obj
|
|
581
626
|
|
|
582
627
|
def axis_deserialization(self) -> Axis:
|
|
@@ -598,7 +643,8 @@ class DeSerializer:
|
|
|
598
643
|
axis_index = self.scalar_deserialization()
|
|
599
644
|
axis_spread_order = self.scalar_deserialization()
|
|
600
645
|
|
|
601
|
-
axis = Axis(axis_label, axis_units, data=axis_array, index=axis_index,
|
|
646
|
+
axis = Axis(axis_label, axis_units, data=axis_array, index=axis_index,
|
|
647
|
+
spread_order=axis_spread_order)
|
|
602
648
|
return axis
|
|
603
649
|
|
|
604
650
|
def dwa_deserialization(self) -> DataWithAxes:
|
|
@@ -624,6 +670,10 @@ class DeSerializer:
|
|
|
624
670
|
nav_indexes=tuple(self.list_deserialization()),
|
|
625
671
|
axes=self.list_deserialization(),
|
|
626
672
|
)
|
|
673
|
+
dwa.extra_attributes = self.list_deserialization()
|
|
674
|
+
for attribute in dwa.extra_attributes:
|
|
675
|
+
setattr(dwa, attribute, self.object_deserialization())
|
|
676
|
+
|
|
627
677
|
dwa.timestamp = timestamp
|
|
628
678
|
return dwa
|
|
629
679
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
2
|
Name: pymodaq
|
|
3
|
-
Version: 4.1.
|
|
3
|
+
Version: 4.1.4
|
|
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
|
|
@@ -47,12 +47,12 @@ Requires-Python: >=3.7
|
|
|
47
47
|
Requires-Dist: easydict
|
|
48
48
|
Requires-Dist: importlib-metadata; python_version < '3.8'
|
|
49
49
|
Requires-Dist: multipledispatch
|
|
50
|
-
Requires-Dist: numpy
|
|
50
|
+
Requires-Dist: numpy<2.0.0
|
|
51
51
|
Requires-Dist: packaging
|
|
52
52
|
Requires-Dist: pint
|
|
53
53
|
Requires-Dist: pymodaq-plugin-manager>=0.0.17
|
|
54
54
|
Requires-Dist: pymodaq-plugins-mock
|
|
55
|
-
Requires-Dist: pyqtgraph
|
|
55
|
+
Requires-Dist: pyqtgraph<=0.13.3
|
|
56
56
|
Requires-Dist: python-dateutil
|
|
57
57
|
Requires-Dist: qdarkstyle
|
|
58
58
|
Requires-Dist: qtconsole
|
|
@@ -16,7 +16,7 @@ pymodaq/examples/custom_app.py,sha256=2wQR0hlPWjZrWK0abNF6ASv8iQyJqRn2CKnBa_nAgN
|
|
|
16
16
|
pymodaq/examples/custom_viewer.py,sha256=IeLqiDkIIxLps5juaW1fVSNSzOKt5iceyzwV0DJTbnM,4813
|
|
17
17
|
pymodaq/examples/function_plotter.py,sha256=T-VT0Rd3jHP9GcR2h6Nao6lwZE06P8zWUbOlz8b8Rxk,6104
|
|
18
18
|
pymodaq/examples/nonlinearscanner.py,sha256=x0R2_FP0YnuOCCAmYRiAiZ1jfUdRxu5RqIYLyGQMZ0U,3790
|
|
19
|
-
pymodaq/examples/parameter_ex.py,sha256
|
|
19
|
+
pymodaq/examples/parameter_ex.py,sha256=yuUjHfiZg6LjNN0QYxZH264AjZt5SikNQRTVnqVS8jY,8067
|
|
20
20
|
pymodaq/examples/preset_MockCamera.xml,sha256=quQlMsX6YSoqqc9_9Y-9zu3TDM6Xvnuc2JSWwg9f948,15774
|
|
21
21
|
pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.aliases,sha256=t0eKH9Uq_AMk4wQ-6Pm5mKUjGcCvfT9GtvMsvDhkCUk,47
|
|
22
22
|
pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.lvlps,sha256=VZHH96rKSnRYKeCAXUmKI3vQOX8Wz53FYCF2yXuqnaU,84
|
|
@@ -36,9 +36,9 @@ pymodaq/examples/Labview_TCP_Client/cmd_types.ctl,sha256=gwuDyGcte11Zqx0C-U8ljRy
|
|
|
36
36
|
pymodaq/extensions/__init__.py,sha256=EnlA2Pv8B2HSYzHz_QJhxvWBSEaE1BvFQEA_puxuD9U,321
|
|
37
37
|
pymodaq/extensions/console.py,sha256=SOKQCZtOB6sqtI7JoiG7sRfL1KWLGGI_3VGDEva2Ufg,2522
|
|
38
38
|
pymodaq/extensions/daq_logger.py,sha256=7G7LzL_Xu7PEQUk-N-3lQXEochysCmvv_bbf2nGUpmE,19508
|
|
39
|
-
pymodaq/extensions/daq_scan.py,sha256=
|
|
39
|
+
pymodaq/extensions/daq_scan.py,sha256=SKpMhtI5yyBoNC55-c1WXgDSG5rRYWXm1WmilKIXSks,54243
|
|
40
40
|
pymodaq/extensions/daq_scan_ui.py,sha256=zp9dCOnsWdPRe0LuU8hxhTf8L3t2eo-MjBd8xiHX_mk,10134
|
|
41
|
-
pymodaq/extensions/h5browser.py,sha256=
|
|
41
|
+
pymodaq/extensions/h5browser.py,sha256=T0AwRbTraEJNEDI7TC86i1Fl2AgcpmHcNBbyvLW6L0k,1159
|
|
42
42
|
pymodaq/extensions/utils.py,sha256=lGyPCnN8PEWuSNbQisHjd4PBMjlnh_Zz2BqJplkvqE4,1881
|
|
43
43
|
pymodaq/extensions/pid/__init__.py,sha256=YP5CemFZ54mFlFIhktct2SeOmkAuvxQm2y1Fiq5HiMQ,534
|
|
44
44
|
pymodaq/extensions/pid/daq_move_PID.py,sha256=EiTJz4fLcjVL1UxnFREu2oZEz2nl-iL5xgxf83YG85M,3090
|
|
@@ -53,7 +53,7 @@ pymodaq/post_treatment/daq_measurement/daq_measurement_GUI.py,sha256=1u7hWDaiwsZ
|
|
|
53
53
|
pymodaq/post_treatment/daq_measurement/daq_measurement_GUI.ui,sha256=PyzbCWPMkh5oIYYteZczXyWMeHKW9EJmM1QlzXhnyTk,7037
|
|
54
54
|
pymodaq/post_treatment/daq_measurement/daq_measurement_main.py,sha256=CAKwcWMOD86aXB8mbdxOK7e8nZRos5d59FzDtqK1QoY,17093
|
|
55
55
|
pymodaq/post_treatment/daq_measurement/process_from_QtDesigner_DAQ_Measurement_GUI.bat,sha256=e1tu2A67MS9fk3jhriF6saQgRxWIucIvNW92iWXFP6E,164
|
|
56
|
-
pymodaq/resources/VERSION,sha256=
|
|
56
|
+
pymodaq/resources/VERSION,sha256=5U3JYk2vAxVFFvzTP7EnpXSg6wFXCzQax6tldqbIqHU,17
|
|
57
57
|
pymodaq/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
58
58
|
pymodaq/resources/config_scan_template.toml,sha256=zlbFO6pOdrLOFJTVMXfek8YpvOo29tqv0aTjGnB7_mA,570
|
|
59
59
|
pymodaq/resources/config_template.toml,sha256=b91pWeFlKKN-HPpYkwzBLEsEQnoKEM6GmNKQq7aCfts,3352
|
|
@@ -302,7 +302,7 @@ pymodaq/utils/chrono_timer.py,sha256=rwX8apS8B-IKhA0Cp2H9tLz0BRN7G3Pg5ptozvd3MKM
|
|
|
302
302
|
pymodaq/utils/config.py,sha256=iaZpoI-l5KkCKlE49k6IPcRXKB_Ai6bi72Vaf6a2Xbg,12480
|
|
303
303
|
pymodaq/utils/conftests.py,sha256=3Ak8WEpa3EhAp73Yb1LLq8YFONhPqiL7gG9eSDIoTNc,58
|
|
304
304
|
pymodaq/utils/daq_utils.py,sha256=LCz6wM1sAkKPf4CMnYB9HXGiizlVpN5Yj4KXo6D-oRg,30312
|
|
305
|
-
pymodaq/utils/data.py,sha256=
|
|
305
|
+
pymodaq/utils/data.py,sha256=4O43O1ljHsXhfovxSviSrRfvF45HT9wfd4xeyBZmc3o,86475
|
|
306
306
|
pymodaq/utils/enums.py,sha256=WNU6w3tsNpP7HQnNrQ6eKnDTXulOlZufQRr11__-l0M,1822
|
|
307
307
|
pymodaq/utils/exceptions.py,sha256=wLO6VlofzfwWkOOWMN2B-3NEWMfpgygyeEdakIx_rAs,668
|
|
308
308
|
pymodaq/utils/factory.py,sha256=OLPxzbgpvIuxMN9e59O768NN25FXagcLuE8juvVbhT0,2311
|
|
@@ -336,15 +336,15 @@ pymodaq/utils/gui_utils/widgets/tree_layout.py,sha256=OCXj59SzVQPi1ksxxvvbr5AIZ5
|
|
|
336
336
|
pymodaq/utils/gui_utils/widgets/tree_toml.py,sha256=Csq1v1_sqdCEvrb4VCewfsMVMpu-cmH6K_E7UV_ae2o,4373
|
|
337
337
|
pymodaq/utils/h5modules/__init__.py,sha256=x3_4ELvG9onTKEFgIt9xEGg_mA1bB07dvVbU9q0xQKw,104
|
|
338
338
|
pymodaq/utils/h5modules/backends.py,sha256=6n_6HoeQ5gLE_e9pme-ByzN8oidtvQn04TGfk0FPxSc,33040
|
|
339
|
-
pymodaq/utils/h5modules/browsing.py,sha256=
|
|
340
|
-
pymodaq/utils/h5modules/data_saving.py,sha256=
|
|
339
|
+
pymodaq/utils/h5modules/browsing.py,sha256=NQuLJHh7AsU1q3vH_Pmi_FUx3V1KR2PV7SPnWb47y7Y,23356
|
|
340
|
+
pymodaq/utils/h5modules/data_saving.py,sha256=ymAxHOS1To71qas3J-JI0PlaVRwh2vghJZh1LcKOSLY,34301
|
|
341
341
|
pymodaq/utils/h5modules/exporter.py,sha256=iCfUjkuGjs3-ijcUkt38NMrjO8tI9wXShvwYHJIUU70,3670
|
|
342
342
|
pymodaq/utils/h5modules/h5logging.py,sha256=UhRo9YvjU5Ujw_i5aPHXOgOdw_IszxmekOa7gYUY5AQ,2492
|
|
343
343
|
pymodaq/utils/h5modules/module_saving.py,sha256=r9rzHQhePS78yRZd4Sb-4vccLGNY8n_ulB0qJb6HogA,13761
|
|
344
344
|
pymodaq/utils/h5modules/saving.py,sha256=0Cw3cgc_kfI6nWTTLjUkeUpYcA00VIgx5QkJypUwkP8,34013
|
|
345
345
|
pymodaq/utils/h5modules/utils.py,sha256=0isF661xthXlT3hFJvXTcgGqkZcGQmSanTNAGSInez4,3368
|
|
346
346
|
pymodaq/utils/h5modules/exporters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
347
|
-
pymodaq/utils/h5modules/exporters/base.py,sha256=
|
|
347
|
+
pymodaq/utils/h5modules/exporters/base.py,sha256=hGX2teIMO03QB0qBGTP4rzeXbZrQcVLskO0oQuGGgpE,4120
|
|
348
348
|
pymodaq/utils/h5modules/exporters/flimj.py,sha256=z44C30KlAbaPmjnS5inYophnA18LwwqZOa1UMLEi4Tw,2361
|
|
349
349
|
pymodaq/utils/h5modules/exporters/hyperspy.py,sha256=rheeVJQO0BAF606D_0S_j8huzOLzZfkUAp0OdJEnUz4,6517
|
|
350
350
|
pymodaq/utils/managers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -358,18 +358,18 @@ pymodaq/utils/managers/preset_manager_utils.py,sha256=d148YBjeNOP9FTkFoTsfdRDxMI
|
|
|
358
358
|
pymodaq/utils/managers/remote_manager.py,sha256=H6k9aiBkuJRJbZ4rpd5jfawQ-pMRFAXOE_miakvciP8,22251
|
|
359
359
|
pymodaq/utils/managers/roi_manager.py,sha256=VEBQITlEW56CAu3iGIOm1hWd1fabq5HqdRPNK8OhiRo,28869
|
|
360
360
|
pymodaq/utils/parameter/__init__.py,sha256=fMljZeQ9EVvh2bmss550C5BpxFeKOxT8_AVJdPxQ0kQ,433
|
|
361
|
-
pymodaq/utils/parameter/ioxml.py,sha256=
|
|
361
|
+
pymodaq/utils/parameter/ioxml.py,sha256=AKOgAyaE8P2yiPIRO4d9Jiq2Bjv00jbJkbzVar-qwrg,16887
|
|
362
362
|
pymodaq/utils/parameter/utils.py,sha256=2tXcfRn_96rpjxdID2vMUctWxdZ41t8G8uZXNUzEMqA,9615
|
|
363
|
-
pymodaq/utils/parameter/pymodaq_ptypes/__init__.py,sha256=
|
|
364
|
-
pymodaq/utils/parameter/pymodaq_ptypes/bool.py,sha256=
|
|
363
|
+
pymodaq/utils/parameter/pymodaq_ptypes/__init__.py,sha256=acdpRpZRDqpSbXLQYk2uXuZm1LFpjAV24RKV7HlBG2k,1948
|
|
364
|
+
pymodaq/utils/parameter/pymodaq_ptypes/bool.py,sha256=6MtKm9fPRCB2SNBWqh7beriHTo781rQBB1GUuhfOiy4,943
|
|
365
365
|
pymodaq/utils/parameter/pymodaq_ptypes/date.py,sha256=ND9lnRxbEE_KNb1utypYM9rvC7d01GJYNa13XJpadqE,3829
|
|
366
366
|
pymodaq/utils/parameter/pymodaq_ptypes/filedir.py,sha256=IVFbN08Dr3NdRNMufBef1vWr2igiULq3CBu10-yLqSQ,4571
|
|
367
367
|
pymodaq/utils/parameter/pymodaq_ptypes/itemselect.py,sha256=Zxg1HpRDz8R0aQ38ZGD5vfXwIyR6bPddDTHul_zxGes,11002
|
|
368
368
|
pymodaq/utils/parameter/pymodaq_ptypes/led.py,sha256=oDKM3k4aPy_CArgQIEqjLx3KG5CR7NrywacJKalmKQ4,1129
|
|
369
369
|
pymodaq/utils/parameter/pymodaq_ptypes/list.py,sha256=bXGlUxKVAA5_QY41BmzG2iWWoh1Qq-w-QHgMo-_Kc7Q,5716
|
|
370
370
|
pymodaq/utils/parameter/pymodaq_ptypes/numeric.py,sha256=lzklQWAnzh9LDC20hdlGbAj2NdVzNDDeJke1KnPi7GU,560
|
|
371
|
-
pymodaq/utils/parameter/pymodaq_ptypes/pixmap.py,sha256=
|
|
372
|
-
pymodaq/utils/parameter/pymodaq_ptypes/slide.py,sha256=
|
|
371
|
+
pymodaq/utils/parameter/pymodaq_ptypes/pixmap.py,sha256=vIhWscDZRM7Bc3RRf4kBs2g0QNE3-tfp1P4T8EO7AxY,5534
|
|
372
|
+
pymodaq/utils/parameter/pymodaq_ptypes/slide.py,sha256=uEtWs8qnf33OOooD2Uc-6gQOBKjvRIvql7jOlk3WDgA,4988
|
|
373
373
|
pymodaq/utils/parameter/pymodaq_ptypes/table.py,sha256=kM6Kb_KZfJ-sA6tSgn76EDBZK_Cbpc4jfw2KEJ5E2Cg,4819
|
|
374
374
|
pymodaq/utils/parameter/pymodaq_ptypes/tableview.py,sha256=EXMHEGlkL2JC7_fau2ysL3oCvq2XmeCuJNYEu-hp9iY,4866
|
|
375
375
|
pymodaq/utils/parameter/pymodaq_ptypes/text.py,sha256=iPMS3dEz2evsX_1ThX-sqNzfyIL8w0D0tpM87jF8ODo,4708
|
|
@@ -406,17 +406,17 @@ pymodaq/utils/scanner/scanners/_1d_scanners.py,sha256=rmqyHCSCD5HynuFELlzRd7URli
|
|
|
406
406
|
pymodaq/utils/scanner/scanners/_2d_scanners.py,sha256=-25DBTJrO7k7REREGH5i-6DbVRApc76B3OaJeeJTC1M,15560
|
|
407
407
|
pymodaq/utils/scanner/scanners/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
408
408
|
pymodaq/utils/scanner/scanners/sequential.py,sha256=7hcjg0csoA-umV3hd51AdiD0THZjcI2JorMzhS81BO4,7842
|
|
409
|
-
pymodaq/utils/scanner/scanners/tabular.py,sha256=
|
|
409
|
+
pymodaq/utils/scanner/scanners/tabular.py,sha256=zAtAMBolDZnV_HC2toBicgF51eX6J85hJSuX_tXqiNQ,12583
|
|
410
410
|
pymodaq/utils/svg/__init__.py,sha256=QWpeotkNhAQkoVTdWBH8t6MRr9-lrPJx4bXn7J6fCNA,81
|
|
411
411
|
pymodaq/utils/svg/svg_renderer.py,sha256=USEcrOWmQAq8UM620e_XIGPI6z9IQmhyJuqbPo3jLzE,406
|
|
412
412
|
pymodaq/utils/svg/svg_view.py,sha256=bmXpDqnw9S-Bp3F8Hi_oeYB5Y9gebiCNsQWVJzCq-PA,901
|
|
413
413
|
pymodaq/utils/svg/svg_viewer2D.py,sha256=LTJ3Ulb5zWXdRPr7vqcWumbpq7ZctzrYUMtD5QV3x60,1523
|
|
414
414
|
pymodaq/utils/tcp_ip/__init__.py,sha256=1e_EK0AgvdoLAD_CSGGEaITZdy6OWCO7ih9IAIp7HT4,81
|
|
415
415
|
pymodaq/utils/tcp_ip/mysocket.py,sha256=StAWj8dzHeMnbLj68Sel81uWFy-YkKVNRnVf7gXrESI,3452
|
|
416
|
-
pymodaq/utils/tcp_ip/serializer.py,sha256=
|
|
416
|
+
pymodaq/utils/tcp_ip/serializer.py,sha256=YyVjOyuOLDdRTH7YMUlSXrmuuY0e8km-6KeZrAj7HA8,24932
|
|
417
417
|
pymodaq/utils/tcp_ip/tcp_server_client.py,sha256=eZswNZWKyL6ZFHuSROf3nL53fVgDNXMV1PMK5lJNS1o,30490
|
|
418
|
-
pymodaq-4.1.
|
|
419
|
-
pymodaq-4.1.
|
|
420
|
-
pymodaq-4.1.
|
|
421
|
-
pymodaq-4.1.
|
|
422
|
-
pymodaq-4.1.
|
|
418
|
+
pymodaq-4.1.4.dist-info/METADATA,sha256=zoSdpiYnQvX5zBccJ0LBef808ByYmvypdPdQxHDQeMQ,7583
|
|
419
|
+
pymodaq-4.1.4.dist-info/WHEEL,sha256=osohxoshIHTFJFVPhsi1UkZuLRGMHRXZzwEBW2ezjrc,87
|
|
420
|
+
pymodaq-4.1.4.dist-info/entry_points.txt,sha256=RAzdYNjvUT28I2eiCKki_g2NzXq0woWxhev6lwzwRv8,348
|
|
421
|
+
pymodaq-4.1.4.dist-info/licenses/LICENSE,sha256=VKOejxexXAe3XwfhAhcFGqeXQ12irxVHdeAojZwFEI8,1108
|
|
422
|
+
pymodaq-4.1.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|