pymodaq 5.0.1__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.

@@ -10,7 +10,7 @@ from __future__ import annotations
10
10
  import numbers
11
11
  from importlib import import_module
12
12
  from numbers import Number
13
- from random import randint
13
+
14
14
  import sys
15
15
  from typing import List, Tuple, Union, Optional, Type
16
16
  import numpy as np
@@ -472,16 +472,7 @@ class DAQ_Move(ParameterControlModule):
472
472
  self.init_signal.emit(self._initialized_state)
473
473
 
474
474
  elif status.command == "get_actuator_value" or status.command == 'check_position':
475
- if isinstance(status.attribute, DataActuator):
476
- data_act: DataActuator = status.attribute
477
- else:
478
- data_act: DataActuator = status.attribute[0] # backcompatibility
479
- data_act.name = self.title # for the DataActuator name to be the title of the DAQ_Move
480
- if (not Unit(self.units).is_compatible_with(Unit(data_act.units)) and
481
- data_act.units == ''): #this happens if the units have not been specified in
482
- # the plugin
483
- data_act.force_units(self.units)
484
-
475
+ data_act = self._check_data_type(status.attribute)
485
476
  if self.ui is not None:
486
477
  self.ui.display_value(data_act)
487
478
  if self.ui.is_action_checked('show_graph'):
@@ -495,11 +486,7 @@ class DAQ_Move(ParameterControlModule):
495
486
  self._command_tcpip.emit(ThreadCommand(LECOMoveCommands.POSITION, data_act))
496
487
 
497
488
  elif status.command == "move_done":
498
- if isinstance(status.attribute, DataActuator):
499
- data_act: DataActuator = status.attribute
500
- else:
501
- data_act: DataActuator = status.attribute[0] # deprecated
502
- data_act.name = self.title # for the DataActuator name to be the title of the DAQ_Move
489
+ data_act = self._check_data_type(status.attribute)
503
490
  if self.ui is not None:
504
491
  self.ui.display_value(data_act)
505
492
  self.ui.move_done = True
@@ -524,6 +511,22 @@ class DAQ_Move(ParameterControlModule):
524
511
  elif status.command == 'units':
525
512
  self.units = status.attribute
526
513
 
514
+ def _check_data_type(self, data_act: Union[list[np.ndarray], float, DataActuator]) -> DataActuator:
515
+ """ Make sure the data is a DataActuator
516
+
517
+ Mostly to make sure DAQ_Move is backcompatible with old style plugins
518
+ """
519
+ if isinstance(data_act, list): # backcompatibility
520
+ data_act = data_act[0]
521
+ if isinstance(data_act, np.ndarray): # backcompatibility
522
+ data_act = DataActuator(data=[data_act], units=self.units)
523
+ data_act.name = self.title # for the DataActuator name to be the title of the DAQ_Move
524
+ if (not Unit(self.units).is_compatible_with(Unit(data_act.units)) and
525
+ data_act.units == ''): #this happens if the units have not been specified in
526
+ # the plugin
527
+ data_act.force_units(self.units)
528
+ return data_act
529
+
527
530
  def get_actuator_value(self):
528
531
  """Get the current actuator value via the "get_actuator_value" command send to the hardware
529
532
 
@@ -6,8 +6,10 @@ Created on Wed Jan 10 16:54:14 2018
6
6
  """
7
7
  from __future__ import annotations
8
8
  from importlib import import_module
9
+
9
10
  from collections import OrderedDict
10
11
  import copy
12
+
11
13
  import os
12
14
  from pathlib import Path
13
15
  from random import randint
@@ -536,8 +536,8 @@ class DAQ_Move_base(QObject):
536
536
  return self._current_value
537
537
 
538
538
  @current_value.setter
539
- def current_value(self, value: Union[float, DataActuator]):
540
- if isinstance(value, numbers.Number):
539
+ def current_value(self, value: Union[float, np.ndarray, DataActuator]):
540
+ if isinstance(value, numbers.Number) or isinstance(value, np.ndarray):
541
541
  self._current_value = DataActuator(self._title, data=value,
542
542
  units=self.axis_unit)
543
543
  else:
pymodaq/dashboard.py CHANGED
@@ -45,7 +45,7 @@ from pymodaq.utils import config as config_mod_pymodaq
45
45
 
46
46
  from pymodaq.control_modules.daq_move import DAQ_Move
47
47
  from pymodaq.control_modules.daq_viewer import DAQ_Viewer
48
- from pymodaq.utils.gui_utils import get_splash_sc
48
+ from pymodaq_gui.utils.splash import get_splash_sc
49
49
 
50
50
  from pymodaq import extensions as extmod
51
51
 
@@ -395,11 +395,11 @@ class DashBoard(CustomApp):
395
395
  self.add_action('modify_preset', 'Modify Preset', '',
396
396
  'Modify an existing experimental setup configuration file: a "preset"',
397
397
  auto_toolbar=False)
398
- self.add_action('load_preset', 'LOAD', 'Open',
399
- tip='Load the selected Preset: ')
398
+
400
399
  self.add_widget('preset_list', QtWidgets.QComboBox, toolbar=self.toolbar,
401
400
  signal_str='currentTextChanged', slot=self.update_preset_action)
402
-
401
+ self.add_action('load_preset', 'LOAD', 'Open',
402
+ tip='Load the selected Preset: ')
403
403
  self.update_preset_action_list()
404
404
 
405
405
  self.add_action('new_overshoot', 'New Overshoot', '',
@@ -86,7 +86,12 @@ class DAQScan(QObject, ParameterManager):
86
86
  {'title': 'Timeout (ms)', 'name': 'timeout', 'type': 'int', 'value': 10000},
87
87
  ]},
88
88
  {'title': 'Scan options', 'name': 'scan_options', 'type': 'group', 'children': [
89
- {'title': 'Naverage:', 'name': 'scan_average', 'type': 'int', 'value': 1, 'min': 1},
89
+ {'title': 'Naverage:', 'name': 'scan_average', 'type': 'int',
90
+ 'value': config('scan', 'Naverage'), 'min': 1},
91
+ {'title': 'Plot on top:', 'name': 'average_on_top', 'type': 'bool',
92
+ 'value': config('scan', 'average_on_top'),
93
+ 'tip': 'At the second iteration will plot the averaged scan on top (True) of the current one'
94
+ 'or in a second panel (False)'},
90
95
  ]},
91
96
 
92
97
  {'title': 'Plotting options', 'name': 'plot_options', 'type': 'group', 'children': [
@@ -439,7 +444,7 @@ class DAQScan(QObject, ParameterManager):
439
444
  if not os.path.isdir(self.h5saver.settings['base_path']):
440
445
  os.mkdir(self.h5saver.settings['base_path'])
441
446
  filename = gutils.file_io.select_file(self.h5saver.settings['base_path'], save=True, ext='h5')
442
- self.h5saver.h5_file.copy_file(str(filename))
447
+ self.h5saver.h5_file.copy_file(str(filename), overwrite=True)
443
448
 
444
449
  def save_metadata(self, node, type_info='dataset_info'):
445
450
  """
@@ -633,6 +638,10 @@ class DAQScan(QObject, ParameterManager):
633
638
  viewers_enum.extend([ViewersEnum('Data1D').increase_dim(self.scanner.n_axes)
634
639
  for _ in range(len(self.settings['plot_options', 'plot_1d']['selected']))])
635
640
  data_names.extend(self.settings['plot_options', 'plot_1d']['selected'][:])
641
+ if not self.settings['scan_options', 'average_on_top']:
642
+
643
+ viewers_enum = viewers_enum + viewers_enum
644
+ data_names = data_names + [f'{data_name}_averaged' for data_name in data_names]
636
645
  self.live_plotter.prepare_viewers(viewers_enum, viewers_name=data_names)
637
646
 
638
647
  def update_status(self, txt: str, wait_time=0):
@@ -672,6 +681,7 @@ class DAQScan(QObject, ParameterManager):
672
681
  self.ui.set_scan_step_average(status.attribute[1] + 1)
673
682
 
674
683
  elif status.command == "Scan_done":
684
+
675
685
  self.modules_manager.reset_signals()
676
686
  self.live_timer.stop()
677
687
  self.ui.set_scan_done()
@@ -736,6 +746,7 @@ class DAQScan(QObject, ParameterManager):
736
746
  self.live_plotter.load_plot_data(group_0D=self.settings['plot_options', 'group0D'],
737
747
  average_axis=average_axis,
738
748
  average_index=self.ind_average,
749
+ separate_average= not self.settings['scan_options', 'average_on_top'],
739
750
  target_at=self.scanner.positions[self.ind_scan],
740
751
  last_step=(self.ind_scan ==
741
752
  self.scanner.positions.size - 1 and
@@ -772,6 +783,8 @@ class DAQScan(QObject, ParameterManager):
772
783
  text="There are not enough or too much selected move modules for this scan")
773
784
  return False
774
785
 
786
+ ## TODO the stuff about adaptive scans have to be moved into a dedicated extension. M
787
+ ## Most similat to the Bayesian one!
775
788
  if self.scanner.scan_sub_type == 'Adaptive':
776
789
  #todo include this in scanners objects for the adaptive scanners
777
790
  if len(self.modules_manager.get_selected_probed_data('0D')) == 0:
@@ -860,9 +873,15 @@ class DAQScan(QObject, ParameterManager):
860
873
  self.save_metadata(scan_node, 'scan_info')
861
874
 
862
875
  self._init_live()
876
+ Naverage = self.settings['scan_options', 'scan_average']
877
+ if Naverage > 1:
878
+ scan_shape = [Naverage]
879
+ scan_shape.extend(self.scanner.get_scan_shape())
880
+ else:
881
+ scan_shape = self.scanner.get_scan_shape()
863
882
  for det in self.modules_manager.detectors:
864
883
  det.module_and_data_saver = (
865
- module_saving.DetectorExtendedSaver(det, self.scanner.get_scan_shape()))
884
+ module_saving.DetectorExtendedSaver(det, scan_shape))
866
885
  self.module_and_data_saver.h5saver = self.h5saver # force the update as the h5saver ill also be set on each detectors
867
886
 
868
887
  # mandatory to deal with multithreads
@@ -1042,7 +1061,7 @@ class DAQScanAcquisition(QObject):
1042
1061
 
1043
1062
  def start_acquisition(self):
1044
1063
  try:
1045
- #todo hoaw to apply newlayout to adaptive mode?
1064
+ #todo hoaw to apply newlayout to adaptive mode? => cannot has to be a new extension
1046
1065
 
1047
1066
  self.modules_manager.connect_actuators()
1048
1067
  self.modules_manager.connect_detectors()
@@ -1114,6 +1133,7 @@ class DAQScanAcquisition(QObject):
1114
1133
  # daq_scan wait time
1115
1134
  QThread.msleep(self.scan_settings.child('time_flow', 'wait_time').value())
1116
1135
 
1136
+ self.modules_manager.timeout_signal.disconnect()
1117
1137
  self.modules_manager.connect_actuators(False)
1118
1138
  self.modules_manager.connect_detectors(False)
1119
1139
 
@@ -1121,6 +1141,7 @@ class DAQScanAcquisition(QObject):
1121
1141
  attribute="Acquisition has finished"))
1122
1142
  self.status_sig.emit(utils.ThreadCommand("Scan_done"))
1123
1143
 
1144
+
1124
1145
  except Exception as e:
1125
1146
  logger.exception(str(e))
1126
1147
 
@@ -1156,7 +1177,8 @@ class DAQScanAcquisition(QObject):
1156
1177
  full_names: list = self.scan_settings['plot_options', 'plot_0d']['selected'][:]
1157
1178
  full_names.extend(self.scan_settings['plot_options', 'plot_1d']['selected'][:])
1158
1179
  data_temp = det_done_datas.get_data_from_full_names(full_names, deepcopy=False)
1159
- data_temp = data_temp.get_data_with_naxes_lower_than(2-len(indexes)) # maximum Data2D included nav indexes
1180
+ n_nav_axis_selection = 2-len(indexes) + 1 if self.Naverage > 1 else 2-len(indexes)
1181
+ data_temp = data_temp.get_data_with_naxes_lower_than(n_nav_axis_selection) # maximum Data2D included nav indexes
1160
1182
 
1161
1183
  self.scan_data_tmp.emit(ScanDataTemp(self.ind_scan, indexes, data_temp))
1162
1184
 
@@ -166,7 +166,7 @@ class DAQ_PID(CustomExt):
166
166
  def process_output(self, data: DataToExport):
167
167
  inputs: DataRaw = data.get_data_from_name('inputs')
168
168
  outputs: DataRaw = data.get_data_from_name('outputs')
169
- self.curr_points = [float(d) for d in inputs]
169
+ self.curr_points = [float(array[0]) for array in inputs]
170
170
  self.output_viewer.show_data(outputs)
171
171
  self.input_viewer.show_data(inputs)
172
172
 
@@ -137,38 +137,14 @@ class PIDModelGeneric:
137
137
 
138
138
 
139
139
  def main(xmlfile):
140
- from pymodaq.dashboard import DashBoard
141
- from pymodaq.utils.config import get_set_preset_path
140
+ from pymodaq.utils.gui_utils.loader_utils import load_dashboard_with_preset
142
141
  from pathlib import Path
143
142
  from qtpy import QtWidgets
143
+ from pymodaq_gui.utils.utils import mkQApp
144
144
 
145
145
  import sys
146
- app = QtWidgets.QApplication(sys.argv)
147
- win = QtWidgets.QMainWindow()
148
- area = DockArea()
149
- win.setCentralWidget(area)
150
- win.resize(1000, 500)
151
- win.setWindowTitle('PyMoDAQ Dashboard')
152
-
153
- dashboard = DashBoard(area)
154
- file = Path(get_set_preset_path()).joinpath(xmlfile)
155
- if file.exists():
156
- dashboard.set_preset_mode(file)
157
- # prog.load_scan_module()
158
- pid_area = DockArea()
159
- pid_window = QtWidgets.QMainWindow()
160
- pid_window.setCentralWidget(pid_area)
161
-
162
- prog = dashboard.load_pid_module(pid_window)
163
-
164
- else:
165
- msgBox = QtWidgets.QMessageBox()
166
- msgBox.setText(f"The default file specified in the configuration file does not exists!\n"
167
- f"{file}\n"
168
- f"Impossible to load the DAQ_PID Module")
169
- msgBox.setStandardButtons(msgBox.Ok)
170
- ret = msgBox.exec()
171
-
146
+ app = mkQApp('BeamSteering')
147
+ dashboard, extension, win = load_dashboard_with_preset(xmlfile, 'DAQ_PID')
172
148
  sys.exit(app.exec_())
173
149
 
174
150
 
@@ -180,7 +156,6 @@ def get_models(model_name=None):
180
156
  -------
181
157
  list: list of disct containting the name and python module of the found models
182
158
  """
183
- from pymodaq.extensions.pid.utils import PIDModelGeneric
184
159
  models_import = []
185
160
  discovered_models = list(get_entrypoints(group='pymodaq.pid_models'))
186
161
  discovered_models.extend(list(get_entrypoints(group='pymodaq.models')))
@@ -70,7 +70,7 @@ class LoaderPlotter:
70
70
  def load_data(self, filter_dims: List[Union[DataDim, str]] = None,
71
71
  filter_full_names: List[str] = None, remove_navigation: bool = True,
72
72
  group_0D=False, average_axis: int=None, average_index: int = 0,
73
- last_step=False):
73
+ last_step=False, separate_average=False):
74
74
  """Load Data from the h5 node of the dataloader and apply some filtering/manipulation before
75
75
  plotting
76
76
 
@@ -92,6 +92,8 @@ class LoaderPlotter:
92
92
  which step in the averaging process are we in.
93
93
  last_step: bool
94
94
  tells if this is the very last step of the (averaged) scan
95
+ separate_average: bool
96
+ Tells if the averaged data are to be plotted on the same data viewer panel or another one
95
97
 
96
98
  Returns
97
99
  -------
@@ -102,7 +104,8 @@ class LoaderPlotter:
102
104
  self.dataloader.load_all('/', self._data)
103
105
 
104
106
  if average_axis is not None:
105
- self.average_axis(average_axis, average_index, last_step=last_step)
107
+ self.average_axis(average_axis, average_index, last_step=last_step,
108
+ separate_average=separate_average)
106
109
 
107
110
  if filter_dims is not None:
108
111
  filter_dims[:] = [enum_checker(DataDim, dim) for dim in filter_dims]
@@ -113,14 +116,15 @@ class LoaderPlotter:
113
116
  filter_full_names]
114
117
 
115
118
  if group_0D: # 0D initial data
116
- self.group_0D_data()
119
+ self.group_0D_data(separate_average=separate_average)
117
120
 
118
121
  if remove_navigation:
119
122
  self.remove_navigation_axes()
120
123
 
121
124
  return self._data
122
125
 
123
- def average_axis(self, average_axis, average_index, last_step=False) -> None:
126
+ def average_axis(self, average_axis, average_index, last_step=False,
127
+ separate_average=False) -> None:
124
128
  """ Average the data along their average axis
125
129
 
126
130
  Parameters
@@ -132,7 +136,12 @@ class LoaderPlotter:
132
136
  which step in the averaging process are we in.
133
137
  last_step: bool
134
138
  tells if this is the very last step of the (averaged) scan
139
+ separate_average: bool
140
+ Tells if the averaged data are to be plotted on the same data viewer panel or another one
141
+
135
142
  """
143
+ if separate_average and average_index > 0:
144
+ averaged_data = DataToExport('Averaged')
136
145
  for ind, data in enumerate(self._data):
137
146
  current_data = data.inav[average_index, ...]
138
147
  if average_index > 0:
@@ -143,10 +152,16 @@ class LoaderPlotter:
143
152
  data_to_append = data.inav[0, ...]
144
153
  else:
145
154
  data_to_append = data.inav[0:average_index, ...].mean(axis=average_axis)
146
-
155
+ data_to_append.name = f'{data_to_append.name}_averaged'
147
156
  data_to_append.labels = [f'{label}_averaged' for label in data_to_append.labels]
148
- current_data.append(data_to_append)
157
+ if not (separate_average and average_index > 0):
158
+ current_data.append(data_to_append)
159
+ else:
160
+ averaged_data.append(data_to_append)
149
161
  self._data[ind] = current_data
162
+ if separate_average and average_index > 0:
163
+ self._data.append(averaged_data.data)
164
+
150
165
 
151
166
  def remove_navigation_axes(self):
152
167
  """Make the navigation axes as signal axes
@@ -159,18 +174,27 @@ class LoaderPlotter:
159
174
  data.transpose() # because usual ND data should be plotted here as 2D with the nav axes as the minor
160
175
  # (horizontal)
161
176
 
162
- def group_0D_data(self):
177
+ def group_0D_data(self, separate_average=False):
163
178
  """Group in a single DataFromPlugins all data that are initialy Data0D
164
179
 
165
180
  """
166
181
  data = self._data.get_data_from_sig_axes(0)
167
182
  if len(data) > 0:
168
183
  data0D_arrays = []
184
+ data0D_arrays_averaged = []
169
185
  labels = []
186
+ labels_averaged = []
170
187
  for dwa in data:
171
- data0D_arrays.extend(dwa.data)
172
- labels.extend([f'{dwa.get_full_name()}/{label}' for label in dwa.labels])
173
- self._data.remove(dwa)
188
+ if 'averaged' in dwa.name and separate_average:
189
+ data0D_arrays_averaged.extend(dwa.data)
190
+ labels_averaged.extend([f'{dwa.get_full_name()}/{label}' for label in dwa.labels])
191
+ self._data.remove(dwa)
192
+
193
+
194
+ else:
195
+ data0D_arrays.extend(dwa.data)
196
+ labels.extend([f'{dwa.get_full_name()}/{label}' for label in dwa.labels])
197
+ self._data.remove(dwa)
174
198
 
175
199
  data0D = DataFromPlugins(self.grouped_data0D_fullname.split('/')[1],
176
200
  data=data0D_arrays, labels=labels,
@@ -179,6 +203,15 @@ class LoaderPlotter:
179
203
  axes=dwa.axes, nav_indexes=dwa.nav_indexes,
180
204
  )
181
205
  self._data.append(data0D)
206
+ if 'averaged' in dwa.name and separate_average:
207
+ data0D_averaged = DataFromPlugins(
208
+ f"{self.grouped_data0D_fullname.split('/')[1]}_averaged",
209
+ data=data0D_arrays_averaged, labels=labels_averaged,
210
+ dim='DataND',
211
+ origin=self.grouped_data0D_fullname.split('/')[0],
212
+ axes=dwa.axes, nav_indexes=dwa.nav_indexes,
213
+ )
214
+ self._data.append(data0D_averaged)
182
215
 
183
216
  def load_plot_data(self, **kwargs):
184
217
  """Load and plot all data from the current H5Saver
pymodaq/utils/data.py CHANGED
@@ -9,9 +9,16 @@ from pymodaq_utils.warnings import deprecation_msg, user_warning
9
9
 
10
10
  from pymodaq_data.data import (DataRaw, DataWithAxes, DataToExport, DataCalculated, DataDim,
11
11
  DataSource, DataBase, Axis, NavAxis, DataDistribution, Q_, Unit,
12
- ) # imported here for backcompatibility
12
+ ) # imported here for backcompatibility. Will allow also the object serialization
13
+ # registration
13
14
 
14
15
 
16
+ from pymodaq_utils.serialize.factory import SerializableFactory, SerializableBase
17
+
18
+ ser_factory = SerializableFactory()
19
+
20
+
21
+ @ser_factory.register_decorator()
15
22
  class DataActuator(DataRaw):
16
23
  """Specialized DataWithAxes set with source as 'raw'.
17
24
  To be used for raw data generated by actuator plugins"""
@@ -40,6 +47,7 @@ class DataActuator(DataRaw):
40
47
  return super().__add__(other)
41
48
 
42
49
 
50
+ @ser_factory.register_decorator()
43
51
  class DataFromPlugins(DataRaw):
44
52
  """Specialized DataWithAxes set with source as 'raw'. To be used for raw data generated by Detector plugins
45
53
 
@@ -83,12 +91,14 @@ class DataFromPlugins(DataRaw):
83
91
  super().__init__(*args, **kwargs)
84
92
 
85
93
 
94
+ @ser_factory.register_decorator()
86
95
  class DataScan(DataToExport):
87
96
  """Specialized DataToExport.To be used for data to be saved """
88
97
  def __init__(self, name: str, data: List[DataWithAxes] = [], **kwargs):
89
98
  super().__init__(name, data, **kwargs)
90
99
 
91
100
 
101
+ @ser_factory.register_decorator()
92
102
  class DataToActuators(DataToExport):
93
103
  """ Particular case of a DataToExport adding one named parameter to indicate what kind of change
94
104
  should be applied to the actuators, absolute or relative
@@ -115,4 +125,3 @@ class DataToActuators(DataToExport):
115
125
 
116
126
  def __repr__(self):
117
127
  return f'{super().__repr__()}: {self.mode}'
118
-
@@ -39,6 +39,8 @@ def load_dashboard_with_preset(preset_name: str, extension_name: str) -> \
39
39
  # win.setVisible(False)
40
40
  dashboard = DashBoard(area)
41
41
 
42
+ preset_name = Path(preset_name).stem
43
+
42
44
  file = Path(get_set_preset_path()).joinpath(f"{preset_name}.xml")
43
45
 
44
46
  if file is not None and file.exists():
@@ -11,7 +11,7 @@ import xml.etree.ElementTree as ET
11
11
 
12
12
 
13
13
  import numpy as np
14
-
14
+ from pymodaq_utils.logger import set_logger, get_module_name
15
15
  from pymodaq_utils.abstract import ABCMeta, abstract_attribute, abstractmethod
16
16
  from pymodaq_utils.utils import capitalize
17
17
  from pymodaq_data.data import Axis, DataDim, DataWithAxes, DataToExport, DataDistribution
@@ -28,6 +28,9 @@ if TYPE_CHECKING:
28
28
  from pymodaq.extensions.daq_logger.h5logging import H5Logger
29
29
 
30
30
 
31
+ logger = set_logger(get_module_name(__file__))
32
+
33
+
31
34
  class ModuleSaver(metaclass=ABCMeta):
32
35
  """Abstract base class to save info and data from main modules (DAQScan, DAQViewer, DAQMove, ...)"""
33
36
  group_type: GroupType = abstract_attribute()
@@ -374,7 +377,7 @@ class ScanSaver(ModuleSaver):
374
377
  try:
375
378
  detector.insert_data(indexes, where=self._module_group, distribution=distribution)
376
379
  except Exception as e:
377
- pass
380
+ logger.exception(f'Cannot insert data: {str(e)}')
378
381
 
379
382
 
380
383
  class LoggerSaver(ScanSaver):
@@ -17,8 +17,7 @@ from pymodaq_gui.parameter import Parameter
17
17
 
18
18
  from pymodaq.utils.leco.leco_director import LECODirector, leco_parameters
19
19
  from pymodaq.utils.leco.director_utils import ActuatorDirector
20
- from pymodaq.utils.tcp_ip.serializer import DeSerializer
21
-
20
+ from pymodaq_utils.serialize.serializer_legacy import DeSerializer
22
21
 
23
22
  class DAQ_Move_LECODirector(LECODirector, DAQ_Move_base):
24
23
  """A control module, which in the dashboard, allows to control a remote Move module.
@@ -6,8 +6,9 @@ from easydict import EasyDict as edict
6
6
  from pymodaq.control_modules.viewer_utility_classes import DAQ_Viewer_base, comon_parameters, main
7
7
 
8
8
  from pymodaq_utils.utils import ThreadCommand, getLineInfo
9
+
9
10
  from pymodaq_gui.parameter import Parameter
10
- from pymodaq.utils.tcp_ip.serializer import DeSerializer
11
+ from pymodaq_utils.serialize.serializer_legacy import DeSerializer
11
12
 
12
13
  from pymodaq.utils.leco.leco_director import LECODirector, leco_parameters
13
14
  from pymodaq.utils.leco.director_utils import DetectorDirector
@@ -1,8 +1,9 @@
1
-
2
1
  import random
3
-
4
2
  from typing import Callable, Sequence, List
5
3
 
4
+ from pymodaq_utils.enums import StrEnum
5
+ from typing import Callable, Sequence, List, Optional, Union
6
+
6
7
  import pymodaq_gui.parameter.utils as putils
7
8
  # object used to send info back to the main thread:
8
9
  from pymodaq_utils.utils import ThreadCommand
@@ -14,7 +15,7 @@ from pymodaq.utils.leco.pymodaq_listener import PymodaqListener
14
15
 
15
16
  leco_parameters = [
16
17
  {'title': 'Actor name:', 'name': 'actor_name', 'type': 'str', 'value': "actor_name",
17
- 'text': 'Name of the actor plugin to communicate with.'},
18
+ 'tip': 'Name of the actor plugin to communicate with.'},
18
19
  ]
19
20
 
20
21
 
@@ -1,11 +1,6 @@
1
1
 
2
- try:
3
- from enum import StrEnum # type: ignore
4
- except ImportError:
5
- from enum import Enum
2
+ from pymodaq_utils.enums import StrEnum
6
3
 
7
- class StrEnum(str, Enum):
8
- pass
9
4
  import logging
10
5
  from threading import Event
11
6
  from typing import Optional, Union, List, Type
@@ -2,10 +2,11 @@ from __future__ import annotations
2
2
  import subprocess
3
3
  import sys
4
4
  from typing import Any, Optional, Union, get_args, TypeVar
5
- from pymodaq_data import data
5
+
6
6
  from pymodaq.utils import data
7
7
  # import also the DeSerializer for easier imports in dependents
8
8
  from pymodaq_utils.serialize.serializer_legacy import Serializer, DeSerializer, SerializableFactory
9
+
9
10
  # type: ignore # noqa
10
11
  from pymodaq_utils.logger import set_logger
11
12
 
@@ -14,7 +15,6 @@ logger = set_logger('leco_utils')
14
15
  ser_factory = SerializableFactory()
15
16
  JSON_TYPES = Union[str, int, float]
16
17
 
17
- SERIALIZABLE = ser_factory.get_serializables()
18
18
 
19
19
 
20
20
  def serialize_object(pymodaq_object: Union[SERIALIZABLE, Any]) -> Union[str, Any]:
@@ -26,13 +26,20 @@ def serialize_object(pymodaq_object: Union[SERIALIZABLE, Any]) -> Union[str, Any
26
26
  #is not serializable
27
27
 
28
28
 
29
+ ## this form below is to be compatible with python <= 3.10
30
+ ## for py>= 3.11 this could be written SERIALIZABLE = Union[ser_factory.get_serializables()]
31
+ SERIALIZABLE = Union[ser_factory.get_serializables()[0]]
32
+ for klass in ser_factory.get_serializables()[1:]:
33
+ SERIALIZABLE = Union[SERIALIZABLE, klass]
34
+
35
+
29
36
  def binary_serialization(
30
37
  pymodaq_object: Union[SERIALIZABLE, Any],
31
38
  ) -> tuple[Optional[Any], Optional[list[bytes]]]:
32
39
  """Serialize (binary) a pymodaq object, if it is not JSON compatible."""
33
40
  if isinstance(pymodaq_object, get_args(JSON_TYPES)):
34
41
  return pymodaq_object, None
35
- elif isinstance(pymodaq_object, get_args(SERIALIZABLE)):
42
+ elif isinstance(pymodaq_object, get_args(Union[*ser_factory.get_serializables()])):
36
43
  return None, [Serializer(pymodaq_object).to_bytes()]
37
44
  else:
38
45
  raise ValueError(
@@ -374,12 +374,12 @@ class ModulesManager(QObject, ParameterManager):
374
374
  sig.connect(slot)
375
375
  else:
376
376
 
377
- for sig in [mod.grab_done_signal for mod in self.detectors_all]:
377
+ for sig in [mod.grab_done_signal for mod in self.detectors]:
378
378
  try:
379
379
  sig.disconnect(slot)
380
380
  except TypeError as e:
381
381
  # means the slot was not previously connected
382
- logger.info(str(e))
382
+ logger.info(f'Could not disconnect grab signal from the {slot} slot', stacklevel=2)
383
383
 
384
384
  self.detectors_connected = connect
385
385
 
@@ -7,7 +7,7 @@ Created the 20/10/2023
7
7
 
8
8
  from pymodaq_utils.utils import deprecation_msg
9
9
 
10
- from pymodaq_data.serialize.serializer_legacy import Serializer, DeSerializer, SocketString, Socket
10
+ from pymodaq_utils.serialize.serializer_legacy import Serializer, DeSerializer, SocketString, Socket
11
11
 
12
12
  deprecation_msg('Importing Serializer, DeSerializer from pymodaq is deprecated in PyMoDAQ >= 5,'
13
13
  'import them from pymodaq_data.serialize.serializer')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pymodaq
3
- Version: 5.0.1
3
+ Version: 5.0.2
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
@@ -50,11 +50,11 @@ Requires-Dist: numpy<2.0.0
50
50
  Requires-Dist: packaging
51
51
  Requires-Dist: pint
52
52
  Requires-Dist: pyleco>0.3; python_version >= '3.8'
53
- Requires-Dist: pymodaq-data>=5.0.15
54
- Requires-Dist: pymodaq-gui>=5.0.16
53
+ Requires-Dist: pymodaq-data>=5.0.18
54
+ Requires-Dist: pymodaq-gui>=5.0.17
55
55
  Requires-Dist: pymodaq-plugin-manager>=0.0.17
56
56
  Requires-Dist: pymodaq-plugins-mock>=5.0.5
57
- Requires-Dist: pymodaq-utils
57
+ Requires-Dist: pymodaq-utils>=0.0.14
58
58
  Requires-Dist: pyqtgraph>=0.12
59
59
  Requires-Dist: python-dateutil
60
60
  Requires-Dist: qtconsole
@@ -1,15 +1,15 @@
1
1
  pymodaq/__init__.py,sha256=VtSBaXkrFtgRchmQN2dIet1X88h9r9M6C8OCD9WZPy0,3250
2
- pymodaq/dashboard.py,sha256=htNN_zwK8v8wuSMA735wBiKYLu_Kx_KzAdqHpkt0FYQ,76519
2
+ pymodaq/dashboard.py,sha256=LTI3JhUpFRRw8fiuxlVwkRGpkZtLDxMimgI35bOWYkU,76520
3
3
  pymodaq/icon.ico,sha256=hOHHfNDENKphQvG1WDleSEYcHukneR2eRFJu8isIlD4,74359
4
4
  pymodaq/splash.png,sha256=ow8IECF3tPRUMA4tf2tMu1aRiMaxx91_Y2ckVxkrmF0,53114
5
5
  pymodaq/updater.py,sha256=JMCVRgAXwmlrKxZv3837E-LRhF0F8V-td_wODwCoXaY,3821
6
6
  pymodaq/control_modules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- pymodaq/control_modules/daq_move.py,sha256=YMkcaMiveStJ7EvNQAWb-PA-V2AxSj8jTv8NIAmx6-c,38467
7
+ pymodaq/control_modules/daq_move.py,sha256=qK9ehMu40tcRrD3Az9oX3POXCQtlwTHZQlfvuGTJhcg,38521
8
8
  pymodaq/control_modules/daq_move_ui.py,sha256=bdkRX0wjkQuFDr4OT1Q6jT_15DEWV1dn2R6WF50H23s,16811
9
- pymodaq/control_modules/daq_viewer.py,sha256=wMXIT62zr3W_8behOz61OjpMKP35bEwhbWICkt4_yIg,58600
9
+ pymodaq/control_modules/daq_viewer.py,sha256=f9WYEWIlVjnEakesObhsoLBIWfv1tv4Q8TopqfP8lsg,58602
10
10
  pymodaq/control_modules/daq_viewer_ui.py,sha256=7XTidYrYlzj--DbbE1Wx4UBjvp1upGpziGhSTPoMKCc,15677
11
11
  pymodaq/control_modules/mocks.py,sha256=CdczKJDAuM2oL7VvIpSBWiYtTCqK_6x9unxavezp3_s,1954
12
- pymodaq/control_modules/move_utility_classes.py,sha256=Y4AttqefEmlg_Mi-KUCNXyj27JleUu7QLclwrYvInW8,43171
12
+ pymodaq/control_modules/move_utility_classes.py,sha256=5RAhxHEyThS8um42d_nixf0a9ZOQTo6VePhOmmId4QQ,43216
13
13
  pymodaq/control_modules/utils.py,sha256=E94gyLrh7fkeppwihHXcwNyKD3CqBZvkMkk8X4fl_UE,20897
14
14
  pymodaq/control_modules/viewer_utility_classes.py,sha256=1TcyAC7AiJNKvJ6OGNOYoyFvRCT-u6RBbFv-X8IkZYA,28076
15
15
  pymodaq/daq_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -36,7 +36,7 @@ pymodaq/examples/Labview_TCP_Client/client_state.ctl,sha256=IxYi5Og0QXFB1e0VeBL2
36
36
  pymodaq/examples/Labview_TCP_Client/cmd_types.ctl,sha256=gwuDyGcte11Zqx0C-U8ljRyYCQleUPh18MYqg9GtxPg,4618
37
37
  pymodaq/extensions/__init__.py,sha256=PXelEHNgMwhjWlvxwObYU1joSLJnaIsFBZs9ZTR8w5c,470
38
38
  pymodaq/extensions/console.py,sha256=kkuHHog_a2Y_5cYrAFTD7IGRQ4BA4NBQz4hrwFYanQY,2277
39
- pymodaq/extensions/daq_scan.py,sha256=-qEl576RLvr2eF5tBHQk2UyMcFWIDCB07OxMzNvWdyE,49282
39
+ pymodaq/extensions/daq_scan.py,sha256=7GVI4hBtFAcwvz8-hMNlhB_4REcCwwxGk6rUfWoeUZU,50568
40
40
  pymodaq/extensions/daq_scan_ui.py,sha256=kKcXu2tNo-VJR7GQPNEXxMKiKitA4F3a_tOSamalWh0,10052
41
41
  pymodaq/extensions/h5browser.py,sha256=7WbF2hj7sdU0kCqTxB4nXvfKGqUnoIsa2_AhCtCBNQo,1131
42
42
  pymodaq/extensions/utils.py,sha256=18FvgD9vtwAvGdD01LiV0-jcGv0WNjYyDLSP-NFUjno,3042
@@ -53,10 +53,10 @@ pymodaq/extensions/daq_logger/db/db_logger_models.py,sha256=r9672aG8vUPqtHq6gFSu
53
53
  pymodaq/extensions/pid/__init__.py,sha256=tHegjXR1MZ3XHdFTpzYasFIzMxjkNUL-986DKLagAXs,517
54
54
  pymodaq/extensions/pid/actuator_controller.py,sha256=SOE2GjevbqxqxXewW0DMgoqNL_0CaPdNLjyKNc6ULKI,377
55
55
  pymodaq/extensions/pid/daq_move_PID.py,sha256=9q-lMVkS_yBNy0xyAhCWfreKGCOqIBt-LjReKpvNKrA,2146
56
- pymodaq/extensions/pid/pid_controller.py,sha256=fXgLbS_u32mUkDxkTli6QjHuAALnANkKwWLM8c08Olk,29046
57
- pymodaq/extensions/pid/utils.py,sha256=kvrioyi_ZwgzXODPby9FsnWpgFmS3Gcfqj1yUyX1uP8,7990
56
+ pymodaq/extensions/pid/pid_controller.py,sha256=Sqti9GyQAIXiwzmZJCz6lWHmLzYemFp3B5Fsu2zJ50c,29057
57
+ pymodaq/extensions/pid/utils.py,sha256=C1QrfDiyTzq_tkSp3LHzxlTInuGj2KtxLE97-TEiwK0,7182
58
58
  pymodaq/post_treatment/__init__.py,sha256=xaaLFZJ7OLqI_7yPurFk89A7m2ywSbYDXAsdE-QQ8Zg,81
59
- pymodaq/post_treatment/load_and_plot.py,sha256=dqDhZv_g3YY_Ah8bJ6OoOfPxR5xb-CuggbzlfSkPMvU,12158
59
+ pymodaq/post_treatment/load_and_plot.py,sha256=fmaBfdlM6WiFSAPuJxuN5W03JLr9MTn0DJMUsPfmkyg,13920
60
60
  pymodaq/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
61
61
  pymodaq/resources/preset_default.xml,sha256=3OMyj4d0SeArDNcgT41JHUWSEuITM56QsP3CHgLhhqQ,26382
62
62
  pymodaq/resources/setup_plugin.py,sha256=jvMuSp4UxGaPUe9uPUvHg9DrdwyFakG6_sFy_zXb1f8,3182
@@ -67,29 +67,29 @@ pymodaq/utils/chrono_timer.py,sha256=uBVtV3AW-m-fnHlMYgm1qYiuBpREdL1A93yJG78VAiM
67
67
  pymodaq/utils/config.py,sha256=w0EkWEvUbLCq7nTNZQccaMWVILuFaGW1JsIgX3VIKKc,1155
68
68
  pymodaq/utils/conftests.py,sha256=3Ak8WEpa3EhAp73Yb1LLq8YFONhPqiL7gG9eSDIoTNc,58
69
69
  pymodaq/utils/daq_utils.py,sha256=AJIA6PTDKe2nzoL0hgSJRWA5PYhKwZsBKfpPh0QkoTc,6131
70
- pymodaq/utils/data.py,sha256=_Xx8vVzJd6xpGgCFpa0Px48YnWBAr-uDaYzWhXYoxLQ,4068
70
+ pymodaq/utils/data.py,sha256=8iAchr5nkwDo_usgChX85MOQiHnrubPrvAg3MrYnumw,4415
71
71
  pymodaq/utils/enums.py,sha256=9PzGPsPN_6Wl9Pm0uV66-KByPsfpV2Coi5193kNVmII,233
72
72
  pymodaq/utils/exceptions.py,sha256=xWORkqBplDEKI3t5N4LEYPlowlxIs9E007AtYe4E8Y4,627
73
73
  pymodaq/utils/logger.py,sha256=6x5BPpWXw1zW2M7F4lRGIOP2TtnqJHz2m7XSqI8g0u0,293
74
74
  pymodaq/utils/math_utils.py,sha256=uBnk15-O2ucoF0dH-f41HqQYWIFsqNdkCb7AngwN8BI,248
75
75
  pymodaq/utils/messenger.py,sha256=T-RjQtx6Hz4F96TvOL61jomKjfqmNa_FdnGvvpQFfe0,246
76
76
  pymodaq/utils/gui_utils/__init__.py,sha256=MUGjejjsXUzTtDTqDzaQTL9W8Sc850ZZxYBlJn6xlxg,539
77
- pymodaq/utils/gui_utils/loader_utils.py,sha256=nuCNpzS2garrNqsEdZ8UuvOMtQwas3Tnto5UhtCXn2M,2052
77
+ pymodaq/utils/gui_utils/loader_utils.py,sha256=l7-xMbvYlTkO3uUV3UtV_-JeZ-4uVtCVOOb-2YV-sGE,2094
78
78
  pymodaq/utils/gui_utils/utils.py,sha256=0FbuHR-3glsZZO_Lye-h470y9TNuFMcVMJkMF_euzoQ,494
79
79
  pymodaq/utils/gui_utils/widgets/lcd.py,sha256=x7uUPO_JSJX6ZkIa3xvdVFC898G2e3wvPUsATOs3iik,306
80
80
  pymodaq/utils/h5modules/__init__.py,sha256=daEdpEyAJIa8b2VkCqSKcw8PaExcB6Qro80XNes_sHA,2
81
- pymodaq/utils/h5modules/module_saving.py,sha256=wGI4eHKvcHOyfJ4MTclKIpqIM8MOlBYNBvqqs6nV3qA,14112
81
+ pymodaq/utils/h5modules/module_saving.py,sha256=wUTAF0laqB8CoJWhE-1vBOHtFKlt4kRZbrUIYudCgBA,14266
82
82
  pymodaq/utils/leco/__init__.py,sha256=PVxGVZx5uHCsZmFWrVTkVX1lE5C2V95bKBj0vK9KZQU,878
83
- pymodaq/utils/leco/daq_move_LECODirector.py,sha256=7s5XD9REJr5496uRT3vaZxH8hzKM6nzB74jqAleycqA,6806
84
- pymodaq/utils/leco/daq_xDviewer_LECODirector.py,sha256=GrcVFgTNzexG3hTPF9ejWdAPWMoTbgfwkdxLxGJu6go,6311
83
+ pymodaq/utils/leco/daq_move_LECODirector.py,sha256=nw9zfWcGPaf7Zbk-jX35Nel4dHpBVjOugC6NvWWWStQ,6815
84
+ pymodaq/utils/leco/daq_xDviewer_LECODirector.py,sha256=ZC9mrGq5Pa7wv-9w44hMvFxnsUr9w4Zp6w2Aa3z-i24,6322
85
85
  pymodaq/utils/leco/desktop.ini,sha256=2zopClaSQqdFfIsC8CGo2Oc-14x9h1gV0-fUrDtLFmA,82
86
86
  pymodaq/utils/leco/director_utils.py,sha256=0inrKh5aI-1pQs3fTXYvmjvwZ6TiyEEAupr2Hw_pMj0,2105
87
- pymodaq/utils/leco/leco_director.py,sha256=TVd8DNKGoq7Uh9P5JNHFBDt1Q0VxIYPweciDbpTpa8M,3046
88
- pymodaq/utils/leco/pymodaq_listener.py,sha256=BCZlEQw5Z06tdHu6dqi2w9VMh4-UsSZC95hJXCDkW80,10835
89
- pymodaq/utils/leco/utils.py,sha256=TQQwHrVgkhqpfjg2VZq2H5cv3Vwod5E5NTrsczkahRE,2373
87
+ pymodaq/utils/leco/leco_director.py,sha256=4QZVwU2tRM2OBNC4MV-a-JHDLgH_clJYKE8QVqymLgY,3145
88
+ pymodaq/utils/leco/pymodaq_listener.py,sha256=kK3IasfKAC8bYq7h95yqVyXkNROKdhzHeAZm_zOdNt8,10736
89
+ pymodaq/utils/leco/utils.py,sha256=ETQmVNHriB1TxVjspAVctRAqGcpc5rwzFDVlaHud394,2632
90
90
  pymodaq/utils/managers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
91
91
  pymodaq/utils/managers/batchscan_manager.py,sha256=rhz2qeVfePX0h8sjIY1tHQckIHIxKhH-zOIzvM0_1Ag,13666
92
- pymodaq/utils/managers/modules_manager.py,sha256=YSpVQHA3ts9ccAgr77C_EjiMJof8R8uhZ3-aGkMQ5pQ,21016
92
+ pymodaq/utils/managers/modules_manager.py,sha256=LjYXl6TiFHUnoWpvX_Ht3uPg165C_klNgUVHI8suDbo,21076
93
93
  pymodaq/utils/managers/overshoot_manager.py,sha256=df_0cpvU5BxUvVqrWXuBFWyHSs9i_2NwLFjFsIOcBOA,9055
94
94
  pymodaq/utils/managers/preset_manager.py,sha256=JlndG8eWbqhU4ijiLsvBqAVIkSkCY5wpG8kPjlHXV5I,8014
95
95
  pymodaq/utils/managers/preset_manager_utils.py,sha256=3tmhxMKJnYA-SRPumPtdrx-3t7tyTnNr0Z7GFVN_z28,8269
@@ -113,10 +113,10 @@ pymodaq/utils/svg/svg_view.py,sha256=bmXpDqnw9S-Bp3F8Hi_oeYB5Y9gebiCNsQWVJzCq-PA
113
113
  pymodaq/utils/svg/svg_viewer2D.py,sha256=HbJKT90bu1fTY1m018NBtXCZGBXnGNAFemBDrMxc0PY,1427
114
114
  pymodaq/utils/tcp_ip/__init__.py,sha256=1e_EK0AgvdoLAD_CSGGEaITZdy6OWCO7ih9IAIp7HT4,81
115
115
  pymodaq/utils/tcp_ip/mysocket.py,sha256=03FaQskso8nLLAsN-ijX-RazXbeMezRnAPvsRxTQa4k,326
116
- pymodaq/utils/tcp_ip/serializer.py,sha256=CTgPSaG05CKCHdYMfwaTNMt6_6FbINF7uiELLgylsUE,399
116
+ pymodaq/utils/tcp_ip/serializer.py,sha256=Bp6ZpGqMdZlX4CnT371d7ZYqIp7UygsRsE9XFkWZrto,400
117
117
  pymodaq/utils/tcp_ip/tcp_server_client.py,sha256=eL-Q1HnnaAG8wfTUb9unEIiNFApMXzfzfveUWoC0_mg,30657
118
- pymodaq-5.0.1.dist-info/METADATA,sha256=UDcSy9nS66ee6lFG96hrrGXAB1CSZ0oNwkNZymr-myo,12870
119
- pymodaq-5.0.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
120
- pymodaq-5.0.1.dist-info/entry_points.txt,sha256=DvPq6fmIPH2JNsCqHDhn1xEj1kX5tfuc7xQ8-l5S2EU,387
121
- pymodaq-5.0.1.dist-info/licenses/LICENSE,sha256=VKOejxexXAe3XwfhAhcFGqeXQ12irxVHdeAojZwFEI8,1108
122
- pymodaq-5.0.1.dist-info/RECORD,,
118
+ pymodaq-5.0.2.dist-info/METADATA,sha256=wqtlmvm87MlofZCdNqxepykwmVgzwIutaWEyCqu8Tcg,12878
119
+ pymodaq-5.0.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
120
+ pymodaq-5.0.2.dist-info/entry_points.txt,sha256=DvPq6fmIPH2JNsCqHDhn1xEj1kX5tfuc7xQ8-l5S2EU,387
121
+ pymodaq-5.0.2.dist-info/licenses/LICENSE,sha256=VKOejxexXAe3XwfhAhcFGqeXQ12irxVHdeAojZwFEI8,1108
122
+ pymodaq-5.0.2.dist-info/RECORD,,