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

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

Potentially problematic release.


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

Files changed (63) hide show
  1. pymodaq/__init__.py +55 -89
  2. pymodaq/control_modules/daq_move.py +129 -55
  3. pymodaq/control_modules/daq_move_ui.py +42 -11
  4. pymodaq/control_modules/daq_viewer.py +32 -13
  5. pymodaq/control_modules/move_utility_classes.py +346 -79
  6. pymodaq/control_modules/utils.py +26 -9
  7. pymodaq/control_modules/viewer_utility_classes.py +51 -14
  8. pymodaq/daq_utils/daq_utils.py +6 -0
  9. pymodaq/dashboard.py +532 -263
  10. pymodaq/examples/qt_less_standalone_module.py +128 -0
  11. pymodaq/extensions/bayesian/bayesian_optimisation.py +30 -21
  12. pymodaq/extensions/bayesian/utils.py +6 -3
  13. pymodaq/extensions/daq_logger/__init__.py +1 -0
  14. pymodaq/extensions/daq_logger/daq_logger.py +4 -5
  15. pymodaq/extensions/daq_scan.py +28 -8
  16. pymodaq/extensions/daq_scan_ui.py +7 -9
  17. pymodaq/extensions/pid/__init__.py +0 -1
  18. pymodaq/extensions/pid/actuator_controller.py +13 -0
  19. pymodaq/extensions/pid/daq_move_PID.py +25 -46
  20. pymodaq/extensions/pid/pid_controller.py +49 -41
  21. pymodaq/extensions/pid/utils.py +7 -31
  22. pymodaq/extensions/utils.py +41 -7
  23. pymodaq/post_treatment/load_and_plot.py +43 -10
  24. pymodaq/resources/setup_plugin.py +1 -0
  25. pymodaq/updater.py +107 -0
  26. pymodaq/utils/chrono_timer.py +6 -7
  27. pymodaq/utils/daq_utils.py +6 -3
  28. pymodaq/utils/data.py +21 -17
  29. pymodaq/utils/enums.py +6 -0
  30. pymodaq/utils/gui_utils/loader_utils.py +29 -2
  31. pymodaq/utils/gui_utils/utils.py +9 -12
  32. pymodaq/utils/gui_utils/widgets/lcd.py +8 -0
  33. pymodaq/utils/h5modules/module_saving.py +5 -2
  34. pymodaq/utils/leco/daq_move_LECODirector.py +22 -16
  35. pymodaq/utils/leco/daq_xDviewer_LECODirector.py +15 -9
  36. pymodaq/utils/leco/leco_director.py +4 -3
  37. pymodaq/utils/leco/pymodaq_listener.py +9 -13
  38. pymodaq/utils/leco/utils.py +40 -7
  39. pymodaq/utils/managers/modules_manager.py +22 -12
  40. pymodaq/utils/managers/overshoot_manager.py +45 -1
  41. pymodaq/utils/managers/preset_manager.py +22 -46
  42. pymodaq/utils/managers/preset_manager_utils.py +17 -13
  43. pymodaq/utils/managers/remote_manager.py +1 -1
  44. pymodaq/utils/messenger.py +6 -0
  45. pymodaq/utils/parameter/__init__.py +5 -1
  46. pymodaq/utils/tcp_ip/mysocket.py +4 -110
  47. pymodaq/utils/tcp_ip/serializer.py +4 -769
  48. pymodaq/utils/tcp_ip/tcp_server_client.py +5 -5
  49. pymodaq-5.0.2.dist-info/METADATA +242 -0
  50. {pymodaq-5.0.0.dist-info → pymodaq-5.0.2.dist-info}/RECORD +54 -55
  51. {pymodaq-5.0.0.dist-info → pymodaq-5.0.2.dist-info}/WHEEL +1 -1
  52. {pymodaq-5.0.0.dist-info → pymodaq-5.0.2.dist-info}/entry_points.txt +1 -0
  53. pymodaq/examples/custom_app.py +0 -255
  54. pymodaq/examples/custom_viewer.py +0 -112
  55. pymodaq/examples/parameter_ex.py +0 -158
  56. pymodaq/examples/preset_MockCamera.xml +0 -1
  57. pymodaq/post_treatment/daq_measurement/daq_measurement_GUI.py +0 -142
  58. pymodaq/post_treatment/daq_measurement/daq_measurement_GUI.ui +0 -232
  59. pymodaq/post_treatment/daq_measurement/daq_measurement_main.py +0 -391
  60. pymodaq/post_treatment/daq_measurement/process_from_QtDesigner_DAQ_Measurement_GUI.bat +0 -2
  61. pymodaq-5.0.0.dist-info/METADATA +0 -166
  62. /pymodaq/{post_treatment/daq_measurement → daq_utils}/__init__.py +0 -0
  63. {pymodaq-5.0.0.dist-info → pymodaq-5.0.2.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,128 @@
1
+ """
2
+ Example how to create an actuator or detector module, which does not require Qt, nor any GUI functionality.
3
+
4
+ You can connect to this qtless module with a PyMoDAQ LECODirector module (the detector or actuator version, both are preinstalled),
5
+ as if it were any pymodaq module.
6
+
7
+ This example works best with an Actuator Director Module as it has fake movements, but does not return any detector value.
8
+ In this example, the name is "qt_less" (defined in the final if clause), which you have to give as the "actor" argument to the Director module.
9
+
10
+ Add any code in the methods defined below, for example instrument access and execute the file.
11
+ For remote control, you need to start a Coordinator, as described for remote control via LECO.
12
+ """
13
+
14
+ import logging
15
+ from time import sleep
16
+ from typing import List, Union
17
+
18
+ from pyleco.utils.listener import Listener
19
+
20
+
21
+ class QtLessModule:
22
+ """Some module doing things without Qt.
23
+
24
+ You can run an instance of this class anywhere in your LECO network.
25
+ Then you can control this instance with a PyMoDAQ LECODirectorModule (in mock modules) as if it were a PyMoDAQ module.
26
+
27
+ Just add any logic you wish to the methods below.
28
+ """
29
+
30
+ def __init__(self, name: str, host: str = "localhost", **kwargs) -> None:
31
+ super().__init__()
32
+ self.listener = Listener(name=name, host=host, timeout=1, **kwargs)
33
+ self._fake_position = 0
34
+ self.start_listen()
35
+ self._stored = []
36
+
37
+ def start_listen(self) -> None:
38
+ """Start to listen on incoming commands."""
39
+ self.listener.start_listen()
40
+ self.communicator = self.listener.get_communicator()
41
+ self.register_rpc_methods()
42
+
43
+ def register_rpc_methods(self) -> None:
44
+ """Make the following methods available via LECO."""
45
+ register_rpc_method = self.communicator.register_rpc_method
46
+ register_rpc_method(self.set_info)
47
+ register_rpc_method(self.send_data)
48
+ register_rpc_method(self.move_abs)
49
+ register_rpc_method(self.move_rel)
50
+ register_rpc_method(self.move_home)
51
+ register_rpc_method(self.get_actuator_value)
52
+ register_rpc_method(self.stop_motion)
53
+ register_rpc_method(self.set_remote_name)
54
+
55
+ def stop_listen(self) -> None:
56
+ """Stop to listen on incoming commands."""
57
+ self.listener.stop_listen()
58
+
59
+ # smethods for being remote controlled
60
+ # these methods are executed and cannot talk to the controlling module directly.
61
+ # if you need to send a response (for example with a value) you have to store the information and
62
+ # send it after these methods have been executed.
63
+ def set_remote_name(self, name: str) -> None:
64
+ """Define what the name of the remote for answers is."""
65
+ self.remote_name = name
66
+
67
+ # generic commands
68
+ def set_info(self, path: List[str], param_dict_str: str) -> None:
69
+ print("set_info", path, param_dict_str)
70
+
71
+ # detector commands
72
+ def send_data(self, grabber_type: str = "") -> None:
73
+ print("send_data")
74
+
75
+ # actuator commands
76
+ def move_abs(self, position: Union[float, str]) -> None:
77
+ print("move_abs", position)
78
+ self._fake_position = float(position)
79
+
80
+ def move_rel(self, position: Union[float, str]) -> None:
81
+ print("move_rel", position)
82
+ self._fake_position += float(position)
83
+
84
+ def move_home(self) -> None:
85
+ self._fake_position = 0
86
+ print("move_home")
87
+
88
+ def get_actuator_value(self) -> None:
89
+ """Request that the actuator value is sent later on."""
90
+ # according to DAQ_Move, this supersedes "check_position"
91
+ print("get_actuator_value")
92
+ # send the actuator position after this method has finished execution.
93
+ # this method sends the result to the controlling control module.
94
+ self.send_later(
95
+ receiver=self.remote_name,
96
+ method="set_position",
97
+ position=self._fake_position,
98
+ )
99
+
100
+ def stop_motion(self,) -> None:
101
+ # not implemented in DAQ_Move!
102
+ print("stop_motion")
103
+
104
+ # end of methods for being remote controlled
105
+
106
+ def send_later(self, receiver, method, **kwargs):
107
+ """Store information to send it later."""
108
+ self._stored.append((receiver, method, kwargs))
109
+
110
+ def send_stored(self):
111
+ """Send messages stored for later sending."""
112
+ while self._stored:
113
+ receiver, method, kwargs = self._stored.pop()
114
+ self.communicator.ask_rpc(receiver=receiver, method=method, **kwargs)
115
+
116
+
117
+ if __name__ == "__main__":
118
+ print("listening endlessly as 'qt_less'")
119
+ log = logging.getLogger()
120
+ log.addHandler(logging.StreamHandler())
121
+ # log.setLevel(logging.DEBUG)
122
+ m = QtLessModule("qt_less")
123
+ try:
124
+ while True:
125
+ sleep(0.1)
126
+ m.send_stored()
127
+ except KeyboardInterrupt:
128
+ m.stop_listen()
@@ -9,12 +9,16 @@ import numpy as np
9
9
  from pymodaq.utils.data import DataToExport, DataToActuators, DataCalculated, DataActuator
10
10
  from pymodaq.utils.managers.modules_manager import ModulesManager
11
11
  from pymodaq_utils import utils
12
- from pymodaq_utils import config as configmod
12
+ from pymodaq_utils import config as config_mod
13
+ from pymodaq_utils.enums import BaseEnum
14
+
15
+ from pymodaq_gui.config import ConfigSaverLoader
13
16
  from pymodaq_utils.logger import set_logger, get_module_name
14
17
 
15
18
  from pymodaq_gui.plotting.data_viewers.viewer0D import Viewer0D
16
19
  from pymodaq_gui.plotting.data_viewers.viewer import ViewerDispatcher, ViewersEnum
17
20
  from pymodaq_gui.utils import QLED
21
+ from pymodaq_gui.utils.utils import mkQApp
18
22
  from pymodaq_gui import utils as gutils
19
23
  from pymodaq_gui.parameter import utils as putils
20
24
  from pymodaq_gui.h5modules.saving import H5Saver
@@ -27,15 +31,24 @@ from pymodaq.extensions.bayesian.utils import (get_bayesian_models, BayesianMode
27
31
  UtilityParameters, StopType, StoppingParameters)
28
32
  from pymodaq.post_treatment.load_and_plot import LoaderPlotter
29
33
  from pymodaq.extensions.bayesian.utils import BayesianConfig
30
-
34
+ from pymodaq.extensions.utils import CustomExt
31
35
 
32
36
  EXTENSION_NAME = 'BayesianOptimisation'
33
37
  CLASS_NAME = 'BayesianOptimisation'
34
38
 
35
39
  logger = set_logger(get_module_name(__file__))
40
+ config = config_mod.Config()
41
+
36
42
 
43
+ class DataNames(BaseEnum):
44
+ Fitness = 0
45
+ Individual = 1
46
+ ProbedData = 2
47
+ Actuators = 3
48
+ Kappa = 4
37
49
 
38
- class BayesianOptimisation(gutils.CustomApp):
50
+
51
+ class BayesianOptimisation(CustomExt):
39
52
  """ PyMoDAQ extension of the DashBoard to perform the optimization of a target signal
40
53
  taken form the detectors as a function of one or more parameters controlled by the actuators.
41
54
  """
@@ -112,7 +125,7 @@ class BayesianOptimisation(gutils.CustomApp):
112
125
  self.setup_ui()
113
126
 
114
127
  self.bayesian_config = BayesianConfig()
115
- self.mainsettings_saver_loader = configmod.ConfigSaverLoader(
128
+ self.mainsettings_saver_loader = ConfigSaverLoader(
116
129
  self.settings.child('main_settings'), self.bayesian_config)
117
130
 
118
131
  self.h5temp: H5Saver = None
@@ -176,7 +189,7 @@ class BayesianOptimisation(gutils.CustomApp):
176
189
  params = getattr(model_class, 'params')
177
190
  self.settings.child('models', 'model_params').addChildren(params)
178
191
 
179
- def setup_menu(self):
192
+ def setup_menu(self, menubar: QtWidgets.QMenuBar = None):
180
193
  '''
181
194
  to be subclassed
182
195
  create menu for actions contained into the self.actions_manager, for instance:
@@ -450,20 +463,20 @@ class BayesianOptimisation(gutils.CustomApp):
450
463
  def process_output(self, dte: DataToExport):
451
464
 
452
465
  self.enl_index += 1
453
- dwa_kappa = dte.remove(dte.get_data_from_name('kappa'))
466
+ dwa_kappa = dte.remove(dte.get_data_from_name(DataNames.Kappa.name))
454
467
  self.settings.child('main_settings', 'utility', 'kappa_actual').setValue(
455
468
  float(dwa_kappa[0][0])
456
469
  )
457
470
 
458
- dwa_data = dte.remove(dte.get_data_from_name('ProbedData'))
459
- dwa_actuators: DataActuator = dte.remove(dte.get_data_from_name('Actuators'))
471
+ dwa_data = dte.remove(dte.get_data_from_name(DataNames.ProbedData.name))
472
+ dwa_actuators: DataActuator = dte.remove(dte.get_data_from_name(DataNames.Actuators.name))
460
473
  self.viewer_observable.show_data(dte)
461
474
 
462
475
  # dwa_observations = self.algorithm.get_dwa_obervations(
463
476
  # self.modules_manager.selected_actuators_name)
464
477
  self.model_class.update_plots()
465
478
 
466
- best_individual = dte.get_data_from_name('Individual')
479
+ best_individual = dte.get_data_from_name(DataNames.Individual.name)
467
480
  best_indiv_as_list = [float(best_individual[ind][0]) for ind in range(len(best_individual))]
468
481
 
469
482
 
@@ -582,7 +595,7 @@ class OptimisationRunner(QtCore.QObject):
582
595
  polling=sync_acts)
583
596
 
584
597
  # Do the evaluation (measurements)
585
- self.det_done_datas = self.modules_manager.grab_datas()
598
+ self.det_done_datas = self.modules_manager.grab_data()
586
599
  self.input_from_dets = self.model_class.convert_input(self.det_done_datas)
587
600
 
588
601
  # Run the algo internal mechanic
@@ -591,17 +604,17 @@ class OptimisationRunner(QtCore.QObject):
591
604
  dte = DataToExport('algo',
592
605
  data=[self.individual_as_data(
593
606
  np.array([self.optimisation_algorithm.best_fitness]),
594
- 'Fitness'),
607
+ DataNames.Fitness.name),
595
608
  self.individual_as_data(
596
609
  self.optimisation_algorithm.best_individual,
597
- 'Individual'),
598
- DataCalculated('ProbedData',
610
+ DataNames.Individual.name),
611
+ DataCalculated(DataNames.ProbedData.name,
599
612
  data=[np.array([self.input_from_dets])],
600
613
  ),
601
- self.output_to_actuators.merge_as_dwa('Data0D',
602
- 'Actuators'),
614
+ self.output_to_actuators.merge_as_dwa(
615
+ 'Data0D', DataNames.Actuators.name),
603
616
  DataCalculated(
604
- 'kappa',
617
+ DataNames.Kappa.name,
605
618
  data=[
606
619
  np.array([self.optimisation_algorithm.kappa])])
607
620
  ])
@@ -638,10 +651,7 @@ def main(init_qt=True):
638
651
  from pymodaq.utils.daq_utils import get_set_preset_path
639
652
 
640
653
  if init_qt: # used for the test suite
641
- app = QtWidgets.QApplication(sys.argv)
642
-
643
- import qdarkstyle
644
- app.setStyleSheet(qdarkstyle.load_stylesheet())
654
+ app = mkQApp("PyMoDAQ Dashboard")
645
655
 
646
656
  from pymodaq.dashboard import DashBoard
647
657
 
@@ -649,7 +659,6 @@ def main(init_qt=True):
649
659
  area = gutils.dock.DockArea()
650
660
  win.setCentralWidget(area)
651
661
  win.resize(1000, 500)
652
- win.setWindowTitle('PyMoDAQ Dashboard')
653
662
 
654
663
  dashboard = DashBoard(area)
655
664
  daq_scan = None
@@ -116,10 +116,13 @@ class BayesianAlgorithm:
116
116
 
117
117
  @property
118
118
  def best_individual(self) -> Union[np.ndarray, None]:
119
- max_param = self._algo.max.get('params', None)
120
- if max_param is None:
119
+ if self._algo.max is None:
121
120
  return None
122
- return self._algo.space.params_to_array(max_param)
121
+ else:
122
+ max_param = self._algo.max.get('params', None)
123
+ if max_param is None:
124
+ return None
125
+ return self._algo.space.params_to_array(max_param)
123
126
 
124
127
  def stopping(self, ind_iter: int, stopping_parameters: StoppingParameters):
125
128
  if ind_iter >= stopping_parameters.niter:
@@ -0,0 +1 @@
1
+ from .daq_logger import main
@@ -12,7 +12,6 @@ import datetime
12
12
  from typing import TYPE_CHECKING, Union
13
13
 
14
14
  from pymodaq_utils.logger import set_logger, get_module_name
15
- from pymodaq_gui.utils.custom_app import CustomApp
16
15
  from pymodaq_gui.utils.dock import Dock, DockArea
17
16
  from pymodaq_utils.config import Config
18
17
  from pymodaq_gui.parameter import ioxml
@@ -26,7 +25,7 @@ from pymodaq_gui.utils.widgets import QLED
26
25
  from pymodaq.extensions.daq_logger.h5logging import H5Logger
27
26
  from pymodaq.utils.managers.modules_manager import ModulesManager
28
27
  from pymodaq.utils.data import DataActuator, DataToExport
29
-
28
+ from pymodaq.extensions.utils import CustomExt
30
29
 
31
30
  if TYPE_CHECKING:
32
31
  from pymodaq.dashboard import DashBoard
@@ -51,7 +50,7 @@ if is_sql:
51
50
  LOG_TYPES.append('SQL DataBase')
52
51
 
53
52
 
54
- class DAQ_Logger(CustomApp):
53
+ class DAQ_Logger(CustomExt):
55
54
  """
56
55
  Main class initializing a DAQ_Logger module
57
56
  """
@@ -147,10 +146,10 @@ class DAQ_Logger(CustomApp):
147
146
 
148
147
  self._actions['infos'].connect_to(self.dashboard.show_log)
149
148
 
150
- def setup_menu(self):
149
+ def setup_menu(self, menubar: QtWidgets.QMenuBar = None):
151
150
  """
152
151
  """
153
- file_menu = self.mainwindow.menuBar().addMenu('File')
152
+ file_menu = menubar.addMenu('File')
154
153
  self.affect_to('infos', file_menu)
155
154
 
156
155
  def value_changed(self, param):
@@ -29,18 +29,16 @@ from pymodaq_gui.parameter import ioxml
29
29
  from pymodaq_gui.plotting.data_viewers import ViewersEnum
30
30
  from pymodaq_gui.managers.parameter_manager import ParameterManager, Parameter, ParameterTree
31
31
  from pymodaq_gui.plotting.navigator import Navigator
32
-
33
32
  from pymodaq_gui.messenger import messagebox
34
33
  from pymodaq_gui import utils as gutils
35
34
  from pymodaq_gui.h5modules.saving import H5Saver
36
35
 
37
- from pymodaq.utils.scanner.scanner import Scanner, scanner_factory #, adaptive, adaptive_losses
36
+ from pymodaq.utils.scanner.scanner import Scanner
38
37
  from pymodaq.utils.managers.batchscan_manager import BatchScanner
39
38
  from pymodaq.utils.managers.modules_manager import ModulesManager
40
39
  from pymodaq.post_treatment.load_and_plot import LoaderPlotter
41
40
  from pymodaq.extensions.daq_scan_ui import DAQScanUI
42
41
  from pymodaq.utils.h5modules import module_saving
43
-
44
42
  from pymodaq.utils.scanner.scan_selector import ScanSelector, SelectorItem
45
43
  from pymodaq.utils.data import DataActuator
46
44
 
@@ -88,7 +86,12 @@ class DAQScan(QObject, ParameterManager):
88
86
  {'title': 'Timeout (ms)', 'name': 'timeout', 'type': 'int', 'value': 10000},
89
87
  ]},
90
88
  {'title': 'Scan options', 'name': 'scan_options', 'type': 'group', 'children': [
91
- {'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)'},
92
95
  ]},
93
96
 
94
97
  {'title': 'Plotting options', 'name': 'plot_options', 'type': 'group', 'children': [
@@ -441,7 +444,7 @@ class DAQScan(QObject, ParameterManager):
441
444
  if not os.path.isdir(self.h5saver.settings['base_path']):
442
445
  os.mkdir(self.h5saver.settings['base_path'])
443
446
  filename = gutils.file_io.select_file(self.h5saver.settings['base_path'], save=True, ext='h5')
444
- self.h5saver.h5_file.copy_file(str(filename))
447
+ self.h5saver.h5_file.copy_file(str(filename), overwrite=True)
445
448
 
446
449
  def save_metadata(self, node, type_info='dataset_info'):
447
450
  """
@@ -635,6 +638,10 @@ class DAQScan(QObject, ParameterManager):
635
638
  viewers_enum.extend([ViewersEnum('Data1D').increase_dim(self.scanner.n_axes)
636
639
  for _ in range(len(self.settings['plot_options', 'plot_1d']['selected']))])
637
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]
638
645
  self.live_plotter.prepare_viewers(viewers_enum, viewers_name=data_names)
639
646
 
640
647
  def update_status(self, txt: str, wait_time=0):
@@ -674,6 +681,7 @@ class DAQScan(QObject, ParameterManager):
674
681
  self.ui.set_scan_step_average(status.attribute[1] + 1)
675
682
 
676
683
  elif status.command == "Scan_done":
684
+
677
685
  self.modules_manager.reset_signals()
678
686
  self.live_timer.stop()
679
687
  self.ui.set_scan_done()
@@ -738,6 +746,7 @@ class DAQScan(QObject, ParameterManager):
738
746
  self.live_plotter.load_plot_data(group_0D=self.settings['plot_options', 'group0D'],
739
747
  average_axis=average_axis,
740
748
  average_index=self.ind_average,
749
+ separate_average= not self.settings['scan_options', 'average_on_top'],
741
750
  target_at=self.scanner.positions[self.ind_scan],
742
751
  last_step=(self.ind_scan ==
743
752
  self.scanner.positions.size - 1 and
@@ -774,6 +783,8 @@ class DAQScan(QObject, ParameterManager):
774
783
  text="There are not enough or too much selected move modules for this scan")
775
784
  return False
776
785
 
786
+ ## TODO the stuff about adaptive scans have to be moved into a dedicated extension. M
787
+ ## Most similat to the Bayesian one!
777
788
  if self.scanner.scan_sub_type == 'Adaptive':
778
789
  #todo include this in scanners objects for the adaptive scanners
779
790
  if len(self.modules_manager.get_selected_probed_data('0D')) == 0:
@@ -862,9 +873,15 @@ class DAQScan(QObject, ParameterManager):
862
873
  self.save_metadata(scan_node, 'scan_info')
863
874
 
864
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()
865
882
  for det in self.modules_manager.detectors:
866
883
  det.module_and_data_saver = (
867
- module_saving.DetectorExtendedSaver(det, self.scanner.get_scan_shape()))
884
+ module_saving.DetectorExtendedSaver(det, scan_shape))
868
885
  self.module_and_data_saver.h5saver = self.h5saver # force the update as the h5saver ill also be set on each detectors
869
886
 
870
887
  # mandatory to deal with multithreads
@@ -1044,7 +1061,7 @@ class DAQScanAcquisition(QObject):
1044
1061
 
1045
1062
  def start_acquisition(self):
1046
1063
  try:
1047
- #todo hoaw to apply newlayout to adaptive mode?
1064
+ #todo hoaw to apply newlayout to adaptive mode? => cannot has to be a new extension
1048
1065
 
1049
1066
  self.modules_manager.connect_actuators()
1050
1067
  self.modules_manager.connect_detectors()
@@ -1116,6 +1133,7 @@ class DAQScanAcquisition(QObject):
1116
1133
  # daq_scan wait time
1117
1134
  QThread.msleep(self.scan_settings.child('time_flow', 'wait_time').value())
1118
1135
 
1136
+ self.modules_manager.timeout_signal.disconnect()
1119
1137
  self.modules_manager.connect_actuators(False)
1120
1138
  self.modules_manager.connect_detectors(False)
1121
1139
 
@@ -1123,6 +1141,7 @@ class DAQScanAcquisition(QObject):
1123
1141
  attribute="Acquisition has finished"))
1124
1142
  self.status_sig.emit(utils.ThreadCommand("Scan_done"))
1125
1143
 
1144
+
1126
1145
  except Exception as e:
1127
1146
  logger.exception(str(e))
1128
1147
 
@@ -1158,7 +1177,8 @@ class DAQScanAcquisition(QObject):
1158
1177
  full_names: list = self.scan_settings['plot_options', 'plot_0d']['selected'][:]
1159
1178
  full_names.extend(self.scan_settings['plot_options', 'plot_1d']['selected'][:])
1160
1179
  data_temp = det_done_datas.get_data_from_full_names(full_names, deepcopy=False)
1161
- 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
1162
1182
 
1163
1183
  self.scan_data_tmp.emit(ScanDataTemp(self.ind_scan, indexes, data_temp))
1164
1184
 
@@ -38,9 +38,10 @@ class DAQScanUI(CustomApp, ViewerDispatcher):
38
38
  def __init__(self, parent):
39
39
  CustomApp.__init__(self, parent)
40
40
  self.setup_docks()
41
- ViewerDispatcher.__init__(self, self.dockarea, title='Scanner', next_to_dock=self.dock_command)
41
+ ViewerDispatcher.__init__(self, self.dockarea, title='Scanner',
42
+ next_to_dock=self.dock_command)
42
43
 
43
- self.setup_menu()
44
+ self.setup_menu(self._menubar)
44
45
  self.setup_actions()
45
46
  self.connect_things()
46
47
 
@@ -83,13 +84,10 @@ class DAQScanUI(CustomApp, ViewerDispatcher):
83
84
  self.connect_action('navigator', lambda: self.command_sig.emit(ThreadCommand('navigator')))
84
85
  self.connect_action('batch', lambda: self.command_sig.emit(ThreadCommand('batch')))
85
86
 
86
- def setup_menu(self):
87
- self.menubar = QtWidgets.QMenuBar()
88
- self.menubar.setMaximumHeight(30)
89
- self.mainwindow.setMenuBar(self.menubar)
90
- self.file_menu = self.menubar.addMenu('File')
91
- self._extensions_menu = self.menubar.addMenu('Extensions')
92
- self.action_menu = self.menubar.addMenu('Actions')
87
+ def setup_menu(self, menubar: QtWidgets.QMenuBar = None):
88
+ self.file_menu = menubar.addMenu('File')
89
+ self._extensions_menu = menubar.addMenu('Extensions')
90
+ self.action_menu = menubar.addMenu('Actions')
93
91
 
94
92
  def setup_docks(self):
95
93
  self.dock_command = Dock('Scan Command')
@@ -3,7 +3,6 @@ from pathlib import Path
3
3
 
4
4
  from pymodaq_utils.logger import set_logger, get_module_name
5
5
 
6
-
7
6
  logger = set_logger('move_plugins', add_to_console=False)
8
7
 
9
8
 
@@ -0,0 +1,13 @@
1
+ from typing import TYPE_CHECKING
2
+
3
+ if TYPE_CHECKING:
4
+ from .pid_controller import DAQ_PID
5
+
6
+
7
+ class PIDController:
8
+ """ Fake controller object for the DAQ_Move_PID"""
9
+
10
+ def __init__(self, daq_pid: 'DAQ_PID'):
11
+ self.curr_point = daq_pid.curr_points_signal
12
+ self.setpoint = daq_pid.setpoints_signal
13
+ self.emit_curr_points = daq_pid.emit_curr_points_sig
@@ -1,32 +1,30 @@
1
- from easydict import EasyDict as edict
2
-
3
1
  from pymodaq_utils.utils import ThreadCommand
4
2
 
5
- from pymodaq.control_modules.move_utility_classes import DAQ_Move_base, comon_parameters_fun
3
+ from pymodaq.control_modules.move_utility_classes import (DAQ_Move_base, comon_parameters_fun,
4
+ DataActuatorType, DataActuator)
5
+
6
+ from pymodaq.extensions.pid.actuator_controller import PIDController
6
7
 
7
8
 
8
9
  class DAQ_Move_PID(DAQ_Move_base):
9
10
  """
10
11
  """
11
- _controller_units = 'whatever'
12
- is_multiaxes = True
13
- stage_names = []
12
+ _controller_units = ''
13
+ data_actuator_type = DataActuatorType.DataActuator
14
+ is_multiaxes = False
15
+ stage_names = ['',]
14
16
 
15
17
  params = comon_parameters_fun(is_multiaxes, stage_names, master=False)
16
18
 
17
- def __init__(self, parent=None, params_state=None):
18
- super().__init__(parent, params_state)
19
+ def ini_attributes(self):
20
+ self.controller: PIDController = None
19
21
 
20
-
21
- def update_position(self, dict_val):
22
+ def update_position(self, dict_val: dict):
22
23
  self.current_value = dict_val[self.parent.title]
23
24
 
24
25
  def get_actuator_value(self):
25
- self.controller['emit_curr_points'].emit()
26
+ self.controller.emit_curr_points.emit()
26
27
  pos = self.current_value
27
- #
28
- # pos = self.get_position_with_scaling(pos)
29
- # self.current_value = pos
30
28
  return pos
31
29
 
32
30
  def close(self):
@@ -38,51 +36,32 @@ class DAQ_Move_PID(DAQ_Move_base):
38
36
  def ini_stage(self, controller=None):
39
37
  """
40
38
  """
41
- try:
42
- self.status.update(edict(info="", controller=None, initialized=False))
43
- if self.settings.child('multiaxes', 'ismultiaxes').value() and self.settings.child('multiaxes',
44
- 'multi_status').value() == "Slave":
45
- if controller is None:
46
- raise Exception('no controller has been defined externally while this axe is a slave one')
47
- else:
48
- self.controller = controller
49
- else: # Master stage
50
- self.controller = None # any object that will control the stages
51
-
52
- self.controller['curr_point'].connect(self.update_position)
53
-
54
- info = "PID stage"
55
- self.status.info = info
56
- self.status.controller = self.controller
57
- self.status.initialized = True
58
- return self.status.info, self.status.initialized
59
-
60
- except Exception as e:
61
- self.status.info = str(e)
62
- self.status.initialized = False
63
- return self.status
64
-
65
- def move_Abs(self, position):
39
+ self.controller = controller
40
+
41
+ self.controller.curr_point.connect(self.update_position)
42
+
43
+ info = "PID stage"
44
+ initialized = True
45
+ return info, initialized
46
+
47
+ def move_abs(self, position: DataActuator):
66
48
  """
67
49
  """
68
50
  position = self.check_bound(position)
69
- # position=self.set_position_with_scaling(position)
70
- # print(position)
71
51
  self.target_position = position
72
52
 
73
- self.controller['setpoint'].emit({self.parent.title: self.target_position})
74
- self.poll_moving()
53
+ self.controller.setpoint.emit({self.parent.title: self.target_position})
75
54
 
76
- def move_Rel(self, position):
55
+ def move_rel(self, position: DataActuator):
77
56
  """
78
57
  """
79
58
  position = self.check_bound(self.current_value + position) - self.current_value
80
59
  self.target_position = position + self.current_value
81
60
 
82
- self.controller['setpoint'].emit({self.parent.title: self.target_position})
61
+ self.controller.setpoint.emit({self.parent.title: self.target_position})
83
62
  self.poll_moving()
84
63
 
85
- def move_Home(self):
64
+ def move_home(self):
86
65
  """
87
66
  """
88
67
  self.emit_status(ThreadCommand('Update_Status', ['Move Home not implemented']))