pymodaq 5.0.18__py3-none-any.whl → 5.1.0__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (92) hide show
  1. pymodaq/__init__.py +23 -11
  2. pymodaq/control_modules/__init__.py +1 -0
  3. pymodaq/control_modules/daq_move.py +451 -246
  4. pymodaq/control_modules/daq_move_ui/__init__.py +0 -0
  5. pymodaq/control_modules/daq_move_ui/factory.py +48 -0
  6. pymodaq/control_modules/{daq_move_ui.py → daq_move_ui/ui_base.py} +168 -210
  7. pymodaq/control_modules/daq_move_ui/uis/__init__.py +0 -0
  8. pymodaq/control_modules/daq_move_ui/uis/binary.py +139 -0
  9. pymodaq/control_modules/daq_move_ui/uis/original.py +120 -0
  10. pymodaq/control_modules/daq_move_ui/uis/relative.py +124 -0
  11. pymodaq/control_modules/daq_move_ui/uis/simple.py +126 -0
  12. pymodaq/control_modules/daq_viewer.py +113 -101
  13. pymodaq/control_modules/daq_viewer_ui.py +41 -31
  14. pymodaq/control_modules/mocks.py +2 -2
  15. pymodaq/control_modules/move_utility_classes.py +113 -41
  16. pymodaq/control_modules/thread_commands.py +137 -0
  17. pymodaq/control_modules/ui_utils.py +72 -0
  18. pymodaq/control_modules/utils.py +107 -63
  19. pymodaq/control_modules/viewer_utility_classes.py +13 -17
  20. pymodaq/dashboard.py +1294 -625
  21. pymodaq/examples/qt_less_standalone_module.py +48 -11
  22. pymodaq/extensions/__init__.py +8 -3
  23. pymodaq/extensions/adaptive/__init__.py +2 -0
  24. pymodaq/extensions/adaptive/adaptive_optimization.py +179 -0
  25. pymodaq/extensions/adaptive/loss_function/_1d_loss_functions.py +73 -0
  26. pymodaq/extensions/adaptive/loss_function/_2d_loss_functions.py +73 -0
  27. pymodaq/extensions/adaptive/loss_function/__init__.py +3 -0
  28. pymodaq/extensions/adaptive/loss_function/loss_factory.py +110 -0
  29. pymodaq/extensions/adaptive/utils.py +123 -0
  30. pymodaq/extensions/bayesian/__init__.py +1 -1
  31. pymodaq/extensions/bayesian/acquisition/__init__.py +2 -0
  32. pymodaq/extensions/bayesian/acquisition/acquisition_function_factory.py +80 -0
  33. pymodaq/extensions/bayesian/acquisition/base_acquisition_function.py +105 -0
  34. pymodaq/extensions/bayesian/bayesian_optimization.py +143 -0
  35. pymodaq/extensions/bayesian/utils.py +71 -297
  36. pymodaq/extensions/daq_logger/daq_logger.py +7 -12
  37. pymodaq/extensions/daq_logger/h5logging.py +1 -1
  38. pymodaq/extensions/daq_scan.py +30 -55
  39. pymodaq/extensions/data_mixer/__init__.py +0 -0
  40. pymodaq/extensions/data_mixer/daq_0Dviewer_DataMixer.py +97 -0
  41. pymodaq/extensions/data_mixer/data_mixer.py +262 -0
  42. pymodaq/extensions/data_mixer/model.py +108 -0
  43. pymodaq/extensions/data_mixer/models/__init__.py +0 -0
  44. pymodaq/extensions/data_mixer/models/equation_model.py +91 -0
  45. pymodaq/extensions/data_mixer/models/gaussian_fit_model.py +65 -0
  46. pymodaq/extensions/data_mixer/parser.py +53 -0
  47. pymodaq/extensions/data_mixer/utils.py +23 -0
  48. pymodaq/extensions/h5browser.py +3 -34
  49. pymodaq/extensions/optimizers_base/__init__.py +0 -0
  50. pymodaq/extensions/optimizers_base/optimizer.py +1016 -0
  51. pymodaq/extensions/optimizers_base/thread_commands.py +22 -0
  52. pymodaq/extensions/optimizers_base/utils.py +427 -0
  53. pymodaq/extensions/pid/actuator_controller.py +3 -2
  54. pymodaq/extensions/pid/daq_move_PID.py +107 -30
  55. pymodaq/extensions/pid/pid_controller.py +613 -287
  56. pymodaq/extensions/pid/utils.py +8 -5
  57. pymodaq/extensions/utils.py +17 -2
  58. pymodaq/resources/config_template.toml +57 -0
  59. pymodaq/resources/preset_default.xml +1 -1
  60. pymodaq/utils/config.py +10 -4
  61. pymodaq/utils/daq_utils.py +14 -0
  62. pymodaq/utils/data.py +1 -0
  63. pymodaq/utils/gui_utils/loader_utils.py +25 -15
  64. pymodaq/utils/h5modules/module_saving.py +134 -22
  65. pymodaq/utils/leco/daq_move_LECODirector.py +123 -84
  66. pymodaq/utils/leco/daq_xDviewer_LECODirector.py +84 -97
  67. pymodaq/utils/leco/director_utils.py +32 -16
  68. pymodaq/utils/leco/leco_director.py +104 -27
  69. pymodaq/utils/leco/pymodaq_listener.py +186 -97
  70. pymodaq/utils/leco/rpc_method_definitions.py +43 -0
  71. pymodaq/utils/leco/utils.py +25 -25
  72. pymodaq/utils/managers/batchscan_manager.py +12 -11
  73. pymodaq/utils/managers/modules_manager.py +74 -33
  74. pymodaq/utils/managers/overshoot_manager.py +11 -10
  75. pymodaq/utils/managers/preset_manager.py +100 -64
  76. pymodaq/utils/managers/preset_manager_utils.py +163 -107
  77. pymodaq/utils/managers/remote_manager.py +21 -16
  78. pymodaq/utils/scanner/scan_factory.py +12 -3
  79. pymodaq/utils/scanner/scan_selector.py +1 -3
  80. pymodaq/utils/scanner/scanner.py +35 -6
  81. pymodaq/utils/scanner/scanners/_1d_scanners.py +15 -46
  82. pymodaq/utils/scanner/scanners/_2d_scanners.py +21 -68
  83. pymodaq/utils/scanner/scanners/sequential.py +50 -31
  84. pymodaq/utils/scanner/scanners/tabular.py +45 -28
  85. {pymodaq-5.0.18.dist-info → pymodaq-5.1.0.dist-info}/METADATA +7 -6
  86. pymodaq-5.1.0.dist-info/RECORD +154 -0
  87. {pymodaq-5.0.18.dist-info → pymodaq-5.1.0.dist-info}/entry_points.txt +0 -2
  88. pymodaq/extensions/bayesian/bayesian_optimisation.py +0 -690
  89. pymodaq/utils/leco/desktop.ini +0 -2
  90. pymodaq-5.0.18.dist-info/RECORD +0 -121
  91. {pymodaq-5.0.18.dist-info → pymodaq-5.1.0.dist-info}/WHEEL +0 -0
  92. {pymodaq-5.0.18.dist-info → pymodaq-5.1.0.dist-info}/licenses/LICENSE +0 -0
@@ -4,133 +4,129 @@ Created the 31/08/2023
4
4
 
5
5
  @author: Sebastien Weber
6
6
  """
7
- from abc import ABC, abstractproperty, abstractmethod
7
+
8
8
  from typing import List, TYPE_CHECKING, Union, Dict, Tuple, Iterable
9
- from pathlib import Path
10
- import importlib
11
- import pkgutil
12
- import inspect
9
+
10
+ import bayes_opt.exception
13
11
  import numpy as np
14
12
  from collections import namedtuple
15
13
 
16
14
  from bayes_opt import BayesianOptimization
17
- from bayes_opt import UtilityFunction
15
+ from bayes_opt.exception import TargetSpaceEmptyError
16
+
18
17
 
19
- from pymodaq_utils.utils import find_dict_in_list_from_key_val, get_entrypoints
20
18
  from pymodaq_utils.logger import set_logger, get_module_name
21
- from pymodaq_utils.enums import BaseEnum
22
- from pymodaq_utils.config import BaseConfig
23
19
 
24
- from pymodaq_gui.parameter import Parameter
25
- from pymodaq_gui.plotting.data_viewers.viewer import ViewersEnum
26
20
 
27
21
  from pymodaq_data.data import (DataToExport, DataCalculated,
28
22
  DataRaw, Axis)
29
23
 
30
- from pymodaq.utils.data import DataActuator, DataToActuators
31
- from pymodaq.utils.managers.modules_manager import ModulesManager
32
-
33
-
34
- if TYPE_CHECKING:
35
- from pymodaq.extensions.bayesian.bayesian_optimisation import BayesianOptimisation
36
24
 
37
- logger = set_logger(get_module_name(__file__))
38
-
39
-
40
- class StopType(BaseEnum):
41
- Predict = 0
25
+ from pymodaq.extensions.bayesian.acquisition import GenericAcquisitionFunctionFactory
42
26
 
27
+ from pymodaq.extensions.optimizers_base.utils import (
28
+ GenericAlgorithm, OptimizerModelDefault, StopType, StoppingParameters,
29
+ OptimizerConfig, PredictionError)
43
30
 
44
- class UtilityKind(BaseEnum):
45
- ucb = 'Upper Confidence Bound'
46
- ei = 'Expected Improvement'
47
- poi = 'Probability of Improvement'
48
31
 
49
-
50
- UtilityParameters = namedtuple('UtilityParameters',
51
- ['kind', 'kappa', 'xi', 'kappa_decay', 'kappa_decay_delay'])
32
+ logger = set_logger(get_module_name(__file__))
52
33
 
53
34
 
54
- StoppingParameters = namedtuple('StoppingParameters',
55
- ['niter', 'stop_type', 'tolerance', 'npoints'])
35
+ class BayesianConfig(OptimizerConfig):
36
+ config_name = f"bayesian_settings"
56
37
 
57
38
 
58
- class BayesianAlgorithm:
59
39
 
60
- def __init__(self, ini_random: int, bounds: dict, **kwargs):
40
+ class BayesianAlgorithm(GenericAlgorithm):
61
41
 
42
+ def __init__(self, ini_random: int, bounds: dict[str, tuple[float, float]], actuators: list[str], **kwargs):
43
+ super().__init__(ini_random, bounds, actuators)
62
44
  self._algo = BayesianOptimization(f=None,
63
45
  pbounds=bounds,
64
46
  **kwargs
65
47
  )
66
- self._next_point: np.ndarray = None
67
- self._suggested_coordinates: List[np.ndarray] = []
68
- self.ini_random_points = ini_random
69
- self.kappa = 2.5
48
+ self.sorting_index: list = None
70
49
 
71
- self._utility = UtilityFunction(kind="ucb", kappa=self.kappa, xi=0.0)
50
+ def set_prediction_function(self, kind: str = '', **kwargs):
51
+ self._prediction = GenericAcquisitionFunctionFactory.create(kind, **kwargs)
72
52
 
73
- def set_utility_function(self, kind: str, **kwargs):
74
- if kind in UtilityKind.names():
75
- self._utility = UtilityFunction(kind, **kwargs)
53
+ def update_prediction_function(self):
54
+ """ Update the parameters of the acquisition function (kappa decay for instance)"""
55
+ self._prediction.decay_exploration()
76
56
 
77
- def update_utility_function(self):
78
- """ Update the parameters of the Utility function (kappa decay for instance)"""
79
- self._utility.update_params()
80
- self.kappa = self._utility.kappa
57
+ @property
58
+ def tradeoff(self):
59
+ return self._prediction.tradeoff
60
+
61
+ def get_random_point(self) -> dict[str, float]:
62
+ """ Get a random point coordinates in the defined bounds"""
63
+ point = dict()
64
+ for key, vals in self.bounds.items():
65
+ point[key] = (np.max(vals) - np.min(vals)) * np.random.random_sample() + np.min(vals)
66
+ return point
81
67
 
82
68
  @property
83
- def bounds(self) -> List[np.ndarray]:
84
- return [bound for bound in self._algo._space.bounds]
69
+ def bounds(self) -> dict[str, float]:
70
+ """ Return bounds as a dict.
71
+ """
72
+ return self._algo.space.array_to_params(self._algo.space.bounds)
85
73
 
86
74
  @bounds.setter
87
- def bounds(self, bounds: Union[Dict[str, Tuple[float, float]], Iterable[np.ndarray]]):
75
+ def bounds(self, bounds: Dict[str, Tuple[float, float]]):
88
76
  if isinstance(bounds, dict):
89
77
  self._algo.set_bounds(bounds)
90
78
  else:
91
- self._algo.set_bounds(self._algo._space.array_to_params(np.array(bounds)))
79
+ raise TypeError('Bounds should be defined as a dictionary')
80
+
81
+ def prediction_ask(self) -> dict[str, float]:
82
+ """ Ask the prediction function or algo to provide the next point to probe
83
+
84
+ Warning the space algo object is sorting by name the bounds...
85
+ """
86
+ try:
87
+ return self._algo.space.array_to_params(self._prediction.suggest(self._algo._gp, self._algo.space))
88
+ except TargetSpaceEmptyError as e:
89
+ raise PredictionError(str(e))
92
90
 
93
- def get_random_point(self) -> np.ndarray:
94
- """ Get a random point coordinates in the defined bounds"""
95
- point = []
96
- for bound in self.bounds:
97
- point.append((np.max(bound) - np.min(bound)) * np.random.random_sample() +
98
- np.min(bound))
99
- return np.array(point)
100
-
101
- def ask(self) -> np.ndarray:
102
- if self.ini_random_points > 0:
103
- self.ini_random_points -= 1
104
- self._next_point = self.get_random_point()
105
- else:
106
- self._next_point = self._algo.space.params_to_array(self._algo.suggest(self._utility))
107
- self._suggested_coordinates.append(self._next_point)
108
- return self._next_point
109
91
 
110
92
  def tell(self, function_value: float):
111
93
  self._algo.register(params=self._next_point, target=function_value)
112
-
94
+
113
95
  @property
114
96
  def best_fitness(self) -> float:
115
- return self._algo.max['target']
97
+ if self._algo.max is None:
98
+ return 0.001
99
+ else:
100
+ return self._algo.max['target']
116
101
 
117
102
  @property
118
- def best_individual(self) -> Union[np.ndarray, None]:
103
+ def best_individual(self) -> Union[dict[str, float], None]:
119
104
  if self._algo.max is None:
120
105
  return None
121
106
  else:
122
107
  max_param = self._algo.max.get('params', None)
123
108
  if max_param is None:
124
109
  return None
125
- return self._algo.space.params_to_array(max_param)
110
+ return max_param
126
111
 
127
112
  def stopping(self, ind_iter: int, stopping_parameters: StoppingParameters):
128
- if ind_iter >= stopping_parameters.niter:
129
- return True
130
- if ind_iter > stopping_parameters.npoints and stopping_parameters.stop_type == 'Predict':
131
- coordinates = np.array(self._suggested_coordinates[-stopping_parameters.npoints:]).T
132
- return np.all(np.std(coordinates, axis=1)
133
- < stopping_parameters.tolerance)
113
+ if stopping_parameters.stop_type != StopType.NONE:
114
+ if ind_iter >= stopping_parameters.niter: # For instance StopType.ITER
115
+ return True
116
+ if ind_iter > stopping_parameters.npoints:
117
+ if stopping_parameters.stop_type == StopType.PREDICT:
118
+ coordinates = np.atleast_1d([
119
+ [coordinates[act] for coordinates in self._suggested_coordinates[-stopping_parameters.npoints:]]
120
+ for act in self.actuators])
121
+ return np.all(np.abs((np.std(coordinates, axis=1) / np.mean(coordinates, axis=1)))
122
+ < stopping_parameters.tolerance)
123
+ elif stopping_parameters.stop_type == StopType.BEST:
124
+ coordinates = np.atleast_1d(
125
+ [[best['params'][act] for best in
126
+ sorted(self._algo.res, key=lambda x: x['target'])[-stopping_parameters.npoints:]]
127
+ for act in self.actuators])
128
+ return np.all(np.abs((np.std(coordinates, axis=1) / np.mean(coordinates, axis=1)))
129
+ < stopping_parameters.tolerance)
134
130
  return False
135
131
 
136
132
  def _posterior(self, x_obs, y_obs, grid):
@@ -181,226 +177,4 @@ class BayesianAlgorithm:
181
177
  return dwa_measured, dwa_prediction
182
178
 
183
179
 
184
- class BayesianModelGeneric(ABC):
185
-
186
- optimisation_algorithm: BayesianAlgorithm = BayesianAlgorithm
187
-
188
- actuators_name: List[str] = []
189
- detectors_name: List[str] = []
190
-
191
- observables_dim: List[ViewersEnum] = []
192
-
193
- params = [] # to be subclassed
194
-
195
- def __init__(self, optimisation_controller: 'BayesianOptimisation'):
196
- self.optimisation_controller = optimisation_controller # instance of the pid_controller using this model
197
- self.modules_manager: ModulesManager = optimisation_controller.modules_manager
198
-
199
- self.settings = self.optimisation_controller.settings.child('models', 'model_params') # set of parameters
200
- self.check_modules(self.modules_manager)
201
-
202
- def check_modules(self, modules_manager):
203
- for act in self.actuators_name:
204
- if act not in modules_manager.actuators_name:
205
- logger.warning(f'The actuator {act} defined in the model is'
206
- f' not present in the Dashboard')
207
- return False
208
- for det in self.detectors_name:
209
- if det not in modules_manager.detectors_name:
210
- logger.warning(f'The detector {det} defined in the model is'
211
- f' not present in the Dashboard')
212
-
213
- def update_detector_names(self):
214
- names = self.optimisation_controller.settings.child(
215
- 'main_settings', 'detector_modules').value()['selected']
216
- self.data_names = []
217
- for name in names:
218
- name = name.split('//')
219
- self.data_names.append(name)
220
-
221
- def update_settings(self, param: Parameter):
222
- """
223
- Get a parameter instance whose value has been modified by a user on the UI
224
- To be overwritten in child class
225
- """
226
- ...
227
-
228
- def update_plots(self):
229
- """ Called when updating the live plots """
230
- pass
231
-
232
- def ini_model_base(self):
233
- self.modules_manager.selected_actuators_name = self.actuators_name
234
- self.modules_manager.selected_detectors_name = self.detectors_name
235
-
236
- self.ini_model()
237
-
238
- def ini_model(self):
239
- """ To be subclassed
240
180
 
241
- Initialize whatever is needed by your custom model
242
- """
243
- raise NotImplementedError
244
-
245
- def runner_initialized(self):
246
- """ To be subclassed
247
-
248
- Initialize whatever is needed by your custom model after the optimization runner is
249
- initialized
250
- """
251
- pass
252
-
253
- def convert_input(self, measurements: DataToExport) -> float:
254
- """
255
- Convert the measurements in the units to be fed to the Optimisation Controller
256
- Parameters
257
- ----------
258
- measurements: DataToExport
259
- data object exported from the detectors from which the model extract a float value
260
- (fitness) to be fed to the algorithm
261
-
262
- Returns
263
- -------
264
- float
265
-
266
- """
267
- raise NotImplementedError
268
-
269
- def convert_output(self, outputs: List[np.ndarray], best_individual=None) -> DataToActuators:
270
- """ Convert the output of the Optimisation Controller in units to be fed into the actuators
271
- Parameters
272
- ----------
273
- outputs: list of numpy ndarray
274
- output value from the controller from which the model extract a value of the same units as the actuators
275
- best_individual: np.ndarray
276
- the coordinates of the best individual so far
277
- Returns
278
- -------
279
- DataToActuatorOpti: derived from DataToExport. Contains value to be fed to the actuators with a a mode
280
- attribute, either 'rel' for relative or 'abs' for absolute.
281
-
282
- """
283
- raise NotImplementedError
284
-
285
-
286
- class BayesianModelDefault(BayesianModelGeneric):
287
-
288
- actuators_name: List[str] = [] # to be populated dynamically at instantiation
289
- detectors_name: List[str] = [] # to be populated dynamically at instantiation
290
-
291
- params = [{'title': 'Optimizing signal', 'name': 'optimizing_signal', 'type': 'group',
292
- 'children': [
293
- {'title': 'Get data', 'name': 'data_probe', 'type': 'action'},
294
- {'title': 'Optimize 0Ds:', 'name': 'optimize_0d', 'type': 'itemselect',
295
- 'checkbox': True},
296
- ]},]
297
-
298
- def __init__(self, optimisation_controller: 'BayesianOptimisation'):
299
- self.actuators_name = optimisation_controller.modules_manager.actuators_name
300
- self.detectors_name = optimisation_controller.modules_manager.detectors_name
301
- super().__init__(optimisation_controller)
302
-
303
- self.settings.child('optimizing_signal', 'data_probe').sigActivated.connect(
304
- self.optimize_from)
305
-
306
- def ini_model(self):
307
- pass
308
-
309
- def optimize_from(self):
310
- self.modules_manager.get_det_data_list()
311
- data0D = self.modules_manager.settings['data_dimensions', 'det_data_list0D']
312
- data0D['selected'] = data0D['all_items']
313
- self.settings.child('optimizing_signal', 'optimize_0d').setValue(data0D)
314
-
315
- def update_settings(self, param: Parameter):
316
- pass
317
-
318
- def convert_input(self, measurements: DataToExport) -> float:
319
- """ Convert the measurements in the units to be fed to the Optimisation Controller
320
-
321
- Parameters
322
- ----------
323
- measurements: DataToExport
324
- data object exported from the detectors from which the model extract a float value
325
- (fitness) to be fed to the algorithm
326
-
327
- Returns
328
- -------
329
- float
330
-
331
- """
332
- data_name: str = self.settings['optimizing_signal', 'optimize_0d']['selected'][0]
333
- origin, name = data_name.split('/')
334
- return float(measurements.get_data_from_name_origin(name, origin).data[0][0])
335
-
336
- def convert_output(self, outputs: List[np.ndarray], best_individual=None) -> DataToActuators:
337
- """ Convert the output of the Optimisation Controller in units to be fed into the actuators
338
- Parameters
339
- ----------
340
- outputs: list of numpy ndarray
341
- output value from the controller from which the model extract a value of the same units as the actuators
342
- best_individual: np.ndarray
343
- the coordinates of the best individual so far
344
-
345
- Returns
346
- -------
347
- DataToActuators: derived from DataToExport. Contains value to be fed to the actuators
348
- with a mode attribute, either 'rel' for relative or 'abs' for absolute.
349
-
350
- """
351
- return DataToActuators('outputs', mode='abs',
352
- data=[DataActuator(self.modules_manager.actuators_name[ind],
353
- data=float(outputs[ind])) for ind in
354
- range(len(outputs))])
355
-
356
-
357
- def get_bayesian_models(model_name=None):
358
- """
359
- Get PID Models as a list to instantiate Control Actuators per degree of liberty in the model
360
-
361
- Returns
362
- -------
363
- list: list of disct containting the name and python module of the found models
364
- """
365
- models_import = []
366
- discovered_models = get_entrypoints(group='pymodaq.models')
367
- if len(discovered_models) > 0:
368
- for pkg in discovered_models:
369
- try:
370
- module = importlib.import_module(pkg.value)
371
- module_name = pkg.value
372
-
373
- for mod in pkgutil.iter_modules([
374
- str(Path(module.__file__).parent.joinpath('models'))]):
375
- try:
376
- model_module = importlib.import_module(f'{module_name}.models.{mod.name}',
377
- module)
378
- classes = inspect.getmembers(model_module, inspect.isclass)
379
- for name, klass in classes:
380
- if issubclass(klass, BayesianModelGeneric):
381
- if find_dict_in_list_from_key_val(models_import, 'name', mod.name)\
382
- is None:
383
- models_import.append({'name': klass.__name__,
384
- 'module': model_module,
385
- 'class': klass})
386
-
387
- except Exception as e:
388
- logger.warning(str(e))
389
-
390
- except Exception as e:
391
- logger.warning(f'Impossible to import the {pkg.value} bayesian model: {str(e)}')
392
- if find_dict_in_list_from_key_val(models_import, 'name', 'BayesianModelDefault') \
393
- is None:
394
- models_import.append({'name': 'BayesianModelDefault',
395
- 'module': inspect.getmodule(BayesianModelDefault),
396
- 'class': BayesianModelDefault})
397
- if model_name is None:
398
- return models_import
399
- else:
400
- return find_dict_in_list_from_key_val(models_import, 'name', model_name)
401
-
402
-
403
- class BayesianConfig(BaseConfig):
404
- """Main class to deal with configuration values for this plugin"""
405
- config_template_path = None
406
- config_name = f"bayesian_settings"
@@ -75,8 +75,6 @@ class DAQ_Logger(CustomExt):
75
75
  super().__init__(dockarea, dashboard)
76
76
 
77
77
  self.wait_time = 1000
78
-
79
- self.logger_thread = None
80
78
  self.logger: Union[H5Logger, DataBaseLogger] = None
81
79
  self.setup_ui()
82
80
 
@@ -293,25 +291,22 @@ class DAQ_Logger(CustomExt):
293
291
  res = self.set_logging()
294
292
 
295
293
  # mandatory to deal with multithreads
296
- if self.logger_thread is not None:
294
+ if self.runner_thread is not None:
297
295
  self.command_DAQ_signal.disconnect()
298
- if self.logger_thread.isRunning():
299
- self.logger_thread.exit()
300
- while not self.logger_thread.isFinished():
301
- QThread.msleep(100)
302
- self.logger_thread = None
296
+ self.exit_runner_thread()
297
+ self.runner_thread = None
303
298
 
304
- self.logger_thread = QThread()
299
+ self.runner_thread = QThread()
305
300
 
306
301
  log_acquisition = DAQ_Logging(self.settings, self.logger, self.modules_manager)
307
302
 
308
- log_acquisition.moveToThread(self.logger_thread)
303
+ log_acquisition.moveToThread(self.runner_thread)
309
304
 
310
305
  self.command_DAQ_signal[list].connect(log_acquisition.queue_command)
311
306
  log_acquisition.status_sig[list].connect(self.thread_status)
312
307
 
313
- self.logger_thread.log_acquisition = log_acquisition
314
- self.logger_thread.start()
308
+ self.runner_thread.log_acquisition = log_acquisition
309
+ self.runner_thread.start()
315
310
 
316
311
  self._actions['start'].setEnabled(False)
317
312
  QtWidgets.QApplication.processEvents()
@@ -45,7 +45,7 @@ class H5Logger(AbstractLogger):
45
45
 
46
46
  self.module_and_data_saver = module_saving.LoggerSaver(self)
47
47
  for det in self.modules_manager.detectors_all:
48
- det.module_and_data_saver = module_saving.DetectorEnlargeableSaver(det)
48
+ det.module_and_data_saver = module_saving.DetectorTimeSaver(det)
49
49
  self.module_and_data_saver.h5saver = self.h5saver # will update its h5saver and all submodules's h5saver
50
50
 
51
51
  def close(self):