pymodaq 4.1.5__py3-none-any.whl → 4.2.1__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 (80) hide show
  1. pymodaq/__init__.py +23 -4
  2. pymodaq/control_modules/daq_move.py +32 -73
  3. pymodaq/control_modules/daq_viewer.py +73 -98
  4. pymodaq/control_modules/daq_viewer_ui.py +2 -1
  5. pymodaq/control_modules/move_utility_classes.py +17 -7
  6. pymodaq/control_modules/utils.py +153 -5
  7. pymodaq/control_modules/viewer_utility_classes.py +31 -20
  8. pymodaq/dashboard.py +23 -5
  9. pymodaq/examples/tcp_client.py +97 -0
  10. pymodaq/extensions/__init__.py +4 -0
  11. pymodaq/extensions/bayesian/__init__.py +2 -0
  12. pymodaq/extensions/bayesian/bayesian_optimisation.py +673 -0
  13. pymodaq/extensions/bayesian/utils.py +403 -0
  14. pymodaq/extensions/daq_scan.py +4 -4
  15. pymodaq/extensions/daq_scan_ui.py +2 -1
  16. pymodaq/extensions/pid/pid_controller.py +12 -7
  17. pymodaq/extensions/pid/utils.py +9 -26
  18. pymodaq/extensions/utils.py +3 -0
  19. pymodaq/post_treatment/load_and_plot.py +42 -19
  20. pymodaq/resources/VERSION +1 -1
  21. pymodaq/resources/config_template.toml +9 -24
  22. pymodaq/resources/setup_plugin.py +1 -1
  23. pymodaq/utils/config.py +103 -5
  24. pymodaq/utils/daq_utils.py +35 -134
  25. pymodaq/utils/data.py +614 -95
  26. pymodaq/utils/enums.py +17 -1
  27. pymodaq/utils/factory.py +2 -2
  28. pymodaq/utils/gui_utils/custom_app.py +5 -2
  29. pymodaq/utils/gui_utils/dock.py +33 -4
  30. pymodaq/utils/gui_utils/utils.py +14 -1
  31. pymodaq/utils/h5modules/backends.py +9 -1
  32. pymodaq/utils/h5modules/data_saving.py +254 -57
  33. pymodaq/utils/h5modules/saving.py +1 -0
  34. pymodaq/utils/leco/__init__.py +25 -0
  35. pymodaq/utils/leco/daq_move_LECODirector.py +172 -0
  36. pymodaq/utils/leco/daq_xDviewer_LECODirector.py +170 -0
  37. pymodaq/utils/leco/desktop.ini +2 -0
  38. pymodaq/utils/leco/director_utils.py +58 -0
  39. pymodaq/utils/leco/leco_director.py +88 -0
  40. pymodaq/utils/leco/pymodaq_listener.py +279 -0
  41. pymodaq/utils/leco/utils.py +41 -0
  42. pymodaq/utils/managers/action_manager.py +20 -6
  43. pymodaq/utils/managers/parameter_manager.py +6 -4
  44. pymodaq/utils/managers/roi_manager.py +63 -54
  45. pymodaq/utils/math_utils.py +1 -1
  46. pymodaq/utils/plotting/data_viewers/__init__.py +3 -1
  47. pymodaq/utils/plotting/data_viewers/base.py +286 -0
  48. pymodaq/utils/plotting/data_viewers/viewer.py +29 -202
  49. pymodaq/utils/plotting/data_viewers/viewer0D.py +94 -47
  50. pymodaq/utils/plotting/data_viewers/viewer1D.py +341 -174
  51. pymodaq/utils/plotting/data_viewers/viewer1Dbasic.py +1 -1
  52. pymodaq/utils/plotting/data_viewers/viewer2D.py +271 -181
  53. pymodaq/utils/plotting/data_viewers/viewerND.py +26 -22
  54. pymodaq/utils/plotting/items/crosshair.py +3 -3
  55. pymodaq/utils/plotting/items/image.py +2 -1
  56. pymodaq/utils/plotting/plotter/plotter.py +94 -0
  57. pymodaq/utils/plotting/plotter/plotters/__init__.py +0 -0
  58. pymodaq/utils/plotting/plotter/plotters/matplotlib_plotters.py +134 -0
  59. pymodaq/utils/plotting/plotter/plotters/qt_plotters.py +78 -0
  60. pymodaq/utils/plotting/utils/axes_viewer.py +1 -1
  61. pymodaq/utils/plotting/utils/filter.py +194 -147
  62. pymodaq/utils/plotting/utils/lineout.py +13 -11
  63. pymodaq/utils/plotting/utils/plot_utils.py +89 -12
  64. pymodaq/utils/scanner/__init__.py +0 -3
  65. pymodaq/utils/scanner/scan_config.py +1 -9
  66. pymodaq/utils/scanner/scan_factory.py +10 -36
  67. pymodaq/utils/scanner/scanner.py +3 -2
  68. pymodaq/utils/scanner/scanners/_1d_scanners.py +7 -5
  69. pymodaq/utils/scanner/scanners/_2d_scanners.py +36 -49
  70. pymodaq/utils/scanner/scanners/sequential.py +10 -4
  71. pymodaq/utils/scanner/scanners/tabular.py +10 -5
  72. pymodaq/utils/slicing.py +1 -1
  73. pymodaq/utils/tcp_ip/serializer.py +38 -5
  74. pymodaq/utils/tcp_ip/tcp_server_client.py +25 -17
  75. {pymodaq-4.1.5.dist-info → pymodaq-4.2.1.dist-info}/METADATA +4 -2
  76. {pymodaq-4.1.5.dist-info → pymodaq-4.2.1.dist-info}/RECORD +79 -63
  77. pymodaq/resources/config_scan_template.toml +0 -42
  78. {pymodaq-4.1.5.dist-info → pymodaq-4.2.1.dist-info}/WHEEL +0 -0
  79. {pymodaq-4.1.5.dist-info → pymodaq-4.2.1.dist-info}/entry_points.txt +0 -0
  80. {pymodaq-4.1.5.dist-info → pymodaq-4.2.1.dist-info}/licenses/LICENSE +0 -0
pymodaq/__init__.py CHANGED
@@ -39,9 +39,10 @@ try:
39
39
  # in a try statement for compilation on readthedocs server but if this fail, you cannot use the code
40
40
  from pymodaq.utils.plotting import data_viewers # imported here as to avoid circular imports later on
41
41
  from pymodaq.utils.daq_utils import copy_preset, setLocale, set_qt_backend
42
-
42
+ from pymodaq.utils.daq_utils import get_instrument_plugins
43
43
  from pymodaq.utils.config import Config
44
-
44
+ from pymodaq.utils.scanner.utils import register_scanners
45
+ from pymodaq.utils.plotting.plotter.plotter import register_plotter, PlotterFactory
45
46
 
46
47
  # issue on windows when using .NET code within multithreads, this below allows it but requires the
47
48
  # pywin32 (pythoncom) package
@@ -66,8 +67,8 @@ try:
66
67
  logger.info('')
67
68
  logger.info('************************')
68
69
  logger.info(f"Setting Qt backend to: {config['qtbackend']['backend']} ...")
69
- logger.info('************************')
70
70
  set_qt_backend()
71
+ logger.info('************************')
71
72
  logger.info('')
72
73
  logger.info('')
73
74
  logger.info('************************')
@@ -83,8 +84,26 @@ try:
83
84
  Q_ = ureg.Quantity
84
85
  logger.info('')
85
86
  logger.info('')
86
- logger.info('************************')
87
+ logger.info('*************************************************************************')
87
88
  logger.info(f"Getting the list of instrument plugins...")
89
+ logger.info('')
90
+ get_instrument_plugins()
91
+ logger.info('*************************************************************************')
92
+
93
+ logger.info('')
94
+ logger.info('')
95
+ logger.info('************************')
96
+ logger.info(f"Registering Scanners...")
97
+ register_scanners()
98
+ logger.info(f"Done")
99
+ logger.info('************************')
100
+
101
+ logger.info('')
102
+ logger.info('')
103
+ logger.info('************************')
104
+ logger.info(f"Registering plotters...")
105
+ register_plotter()
106
+ logger.info(f"Done")
88
107
  logger.info('************************')
89
108
 
90
109
  except Exception as e:
@@ -10,8 +10,9 @@ 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
  import sys
14
- from typing import List, Tuple, Union
15
+ from typing import List, Tuple, Union, Optional, Type
15
16
  import numpy as np
16
17
 
17
18
  from qtpy.QtCore import QObject, Signal, QThread, Slot, Qt, QTimer
@@ -20,15 +21,12 @@ from qtpy import QtWidgets
20
21
  from easydict import EasyDict as edict
21
22
 
22
23
  from pymodaq.utils.logger import set_logger, get_module_name
23
- from pymodaq.control_modules.utils import ControlModule
24
- from pymodaq.utils.parameter import ioxml
24
+ from pymodaq.control_modules.utils import ParameterControlModule
25
25
  from pymodaq.control_modules.daq_move_ui import DAQ_Move_UI, ThreadCommand
26
- from pymodaq.utils.managers.parameter_manager import ParameterManager, Parameter
27
26
  from pymodaq.control_modules.move_utility_classes import MoveCommand, DAQ_Move_base
28
- from pymodaq.utils.tcp_ip.tcp_server_client import TCPClient
29
27
  from pymodaq.control_modules.move_utility_classes import params as daq_move_params
30
28
  from pymodaq.utils import daq_utils as utils
31
- from pymodaq.utils.parameter import utils as putils
29
+ from pymodaq.utils.parameter import Parameter, utils as putils
32
30
  from pymodaq.utils.gui_utils import get_splash_sc
33
31
  from pymodaq.utils import config as config_mod
34
32
  from pymodaq.utils.exceptions import ActuatorError
@@ -37,6 +35,8 @@ from pymodaq.utils.h5modules import module_saving
37
35
  from pymodaq.utils.data import DataRaw, DataToExport, DataFromPlugins, DataActuator
38
36
  from pymodaq.utils.h5modules.backends import Node
39
37
 
38
+ from pymodaq.utils.leco.pymodaq_listener import MoveActorListener, LECOMoveCommands
39
+
40
40
 
41
41
  local_path = config_mod.get_set_local_dir()
42
42
  sys.path.append(str(local_path))
@@ -52,7 +52,7 @@ if len(ACTUATOR_TYPES) == 0:
52
52
  STATUS_WAIT_TIME = 1000
53
53
 
54
54
 
55
- class DAQ_Move(ParameterManager, ControlModule):
55
+ class DAQ_Move(ParameterControlModule):
56
56
  """ Main PyMoDAQ class to drive actuators
57
57
 
58
58
  Qt object and generic UI to drive actuators.
@@ -75,12 +75,13 @@ class DAQ_Move(ParameterManager, ControlModule):
75
75
 
76
76
  move_done_signal = Signal(DataActuator)
77
77
  current_value_signal = Signal(DataActuator)
78
- _update_settings_signal = Signal(edict)
79
78
  bounds_signal = Signal(bool)
80
79
 
81
80
  params = daq_move_params
82
81
 
83
- def __init__(self, parent=None, title="DAQ Move"):
82
+ listener_class = MoveActorListener
83
+
84
+ def __init__(self, parent=None, title="DAQ Move", **kwargs):
84
85
  """
85
86
 
86
87
  Parameters
@@ -95,15 +96,13 @@ class DAQ_Move(ParameterManager, ControlModule):
95
96
  self.logger = set_logger(f'{logger.name}.{title}')
96
97
  self.logger.info(f'Initializing DAQ_Move: {title}')
97
98
 
98
- QObject.__init__(self)
99
- ParameterManager.__init__(self, action_list= ('save', 'update'))
100
- ControlModule.__init__(self)
99
+ super().__init__(action_list=('save', 'update'), **kwargs)
101
100
 
102
101
  self.parent = parent
103
102
  if parent is not None:
104
103
  self.ui = DAQ_Move_UI(parent, title)
105
104
  else:
106
- self.ui: DAQ_Move_UI = None
105
+ self.ui: Optional[DAQ_Move_UI] = None
107
106
 
108
107
  if self.ui is not None:
109
108
  self.ui.actuators = ACTUATOR_TYPES
@@ -172,7 +171,7 @@ class DAQ_Move(ParameterManager, ControlModule):
172
171
  elif cmd.command == 'rel_value':
173
172
  self._relative_value = cmd.attribute
174
173
 
175
- def append_data(self, dte: DataToExport = None, where: Union[Node, str] = None):
174
+ def append_data(self, dte: Optional[DataToExport] = None, where: Union[Node, str, None] = None):
176
175
  """Appends current DataToExport to an ActuatorEnlargeableSaver
177
176
 
178
177
  Parameters
@@ -374,32 +373,14 @@ class DAQ_Move(ParameterManager, ControlModule):
374
373
  """bool: status of the actuator's status (done or not)"""
375
374
  return self._move_done_bool
376
375
 
377
- def value_changed(self, param):
376
+ def value_changed(self, param: Parameter):
378
377
  """ Apply changes of value in the settings"""
379
- if param.name() == 'connect_server':
380
- if param.value():
381
- self.connect_tcp_ip()
382
- else:
383
- self._command_tcpip.emit(ThreadCommand('quit', ))
384
-
385
- elif param.name() == 'ip_address' or param.name == 'port':
386
- self._command_tcpip.emit(
387
- ThreadCommand('update_connection', dict(ipaddress=self.settings.child('main_settings', 'tcpip',
388
- 'ip_address').value(),
389
- port=self.settings.child('main_settings', 'tcpip',
390
- 'port').value())))
391
- elif param.name() == 'refresh_timeout':
392
- self._refresh_timer.setInterval(param.value())
378
+ super().value_changed(param=param)
393
379
 
394
- elif param.name() == 'plugin_config':
395
- self.show_config(self.plugin_config)
380
+ if param.name() == 'refresh_timeout':
381
+ self._refresh_timer.setInterval(param.value())
396
382
 
397
- path = self.settings.childPath(param)
398
- if path is not None:
399
- if 'main_settings' not in path:
400
- self._update_settings_signal.emit(edict(path=path, param=param, change='value'))
401
- if self.settings.child('main_settings', 'tcpip', 'tcp_connected').value():
402
- self._command_tcpip.emit(ThreadCommand('send_info', dict(path=path, param=param)))
383
+ self._update_settings(param=param)
403
384
 
404
385
  def param_deleted(self, param):
405
386
  """ Apply deletion of settings """
@@ -470,6 +451,8 @@ class DAQ_Move(ParameterManager, ControlModule):
470
451
  self.current_value_signal.emit(self._current_value)
471
452
  if self.settings['main_settings', 'tcpip', 'tcp_connected'] and self._send_to_tcpip:
472
453
  self._command_tcpip.emit(ThreadCommand('position_is', status.attribute))
454
+ if self.settings['main_settings', 'leco', 'leco_connected'] and self._send_to_tcpip:
455
+ self._command_tcpip.emit(ThreadCommand(LECOMoveCommands.POSITION, status.attribute))
473
456
 
474
457
  elif status.command == "move_done":
475
458
  data_act: DataActuator = status.attribute[0]
@@ -482,6 +465,8 @@ class DAQ_Move(ParameterManager, ControlModule):
482
465
  self.move_done_signal.emit(data_act)
483
466
  if self.settings.child('main_settings', 'tcpip', 'tcp_connected').value() and self._send_to_tcpip:
484
467
  self._command_tcpip.emit(ThreadCommand('move_done', status.attribute))
468
+ if self.settings.child('main_settings', 'leco', 'leco_connected').value() and self._send_to_tcpip:
469
+ self._command_tcpip.emit(ThreadCommand(LECOMoveCommands.MOVE_DONE, status.attribute))
485
470
 
486
471
  elif status.command == 'outofbounds':
487
472
  self.bounds_signal.emit(True)
@@ -586,23 +571,13 @@ class DAQ_Move(ParameterManager, ControlModule):
586
571
  self.logger.exception(str(e))
587
572
 
588
573
  def connect_tcp_ip(self):
589
- if self.settings.child('main_settings', 'tcpip', 'connect_server').value():
590
- self._tcpclient_thread = QThread()
591
-
592
- tcpclient = TCPClient(self.settings.child('main_settings', 'tcpip', 'ip_address').value(),
593
- self.settings.child('main_settings', 'tcpip', 'port').value(),
594
- self.settings.child('move_settings'), client_type="ACTUATOR")
595
- tcpclient.moveToThread(self._tcpclient_thread)
596
- self._tcpclient_thread.tcpclient = tcpclient
597
- tcpclient.cmd_signal.connect(self.process_tcpip_cmds)
598
-
599
- self._command_tcpip[ThreadCommand].connect(tcpclient.queue_command)
600
- self._tcpclient_thread.started.connect(tcpclient.init_connection)
601
-
602
- self._tcpclient_thread.start()
574
+ super().connect_tcp_ip(params_state=self.settings.child('move_settings'),
575
+ client_type="ACTUATOR")
603
576
 
604
577
  @Slot(ThreadCommand)
605
- def process_tcpip_cmds(self, status):
578
+ def process_tcpip_cmds(self, status: ThreadCommand) -> None:
579
+ if super().process_tcpip_cmds(status=status) is None:
580
+ return
606
581
  if 'move_abs' in status.command:
607
582
  self.move_abs(status.attribute[0], send_to_tcpip=True)
608
583
 
@@ -621,22 +596,6 @@ class DAQ_Move(ParameterManager, ControlModule):
621
596
  self._send_to_tcpip = True
622
597
  self.command_hardware.emit(ThreadCommand('get_actuator_value', ))
623
598
 
624
- elif status.command == 'connected':
625
- self.settings.child('main_settings', 'tcpip', 'tcp_connected').setValue(True)
626
-
627
- elif status.command == 'disconnected':
628
- self.settings.child('main_settings', 'tcpip', 'tcp_connected').setValue(False)
629
-
630
- elif status.command == 'Update_Status':
631
- self.thread_status(status)
632
-
633
- elif status.command == 'set_info':
634
- param_dict = ioxml.XML_string_to_parameter(status.attribute[1])[0]
635
- param_tmp = Parameter.create(**param_dict)
636
- param = self.settings.child('move_settings', *status.attribute[0][1:])
637
-
638
- param.restoreState(param_tmp.saveState())
639
-
640
599
 
641
600
  class DAQ_Move_Hardware(QObject):
642
601
  """
@@ -658,10 +617,10 @@ class DAQ_Move_Hardware(QObject):
658
617
  super().__init__()
659
618
  self.logger = set_logger(f'{logger.name}.{title}.actuator')
660
619
  self._title = title
661
- self.hardware: DAQ_Move_base = None
620
+ self.hardware: Optional[DAQ_Move_base] = None
662
621
  self.actuator_type = actuator_type
663
622
  self.current_position: DataActuator = position
664
- self._target_value: DataActuator = None
623
+ self._target_value: Optional[DataActuator] = None
665
624
  self.hardware_adress = None
666
625
  self.axis_address = None
667
626
  self.motion_stoped = False
@@ -702,7 +661,7 @@ class DAQ_Move_Hardware(QObject):
702
661
  =============== =================================== ==========================================================================================================================
703
662
  **Parameters** **Type** **Description**
704
663
 
705
- *params_state* ordered dictionnary list The parameter state of the hardware class composed by a list representing the tree to keep a temporary save of the tree
664
+ *params_state* ordered dictionary list The parameter state of the hardware class composed by a list representing the tree to keep a temporary save of the tree
706
665
 
707
666
  *controller* one or many instance of DAQ_Move The controller id of the hardware
708
667
 
@@ -878,12 +837,12 @@ class DAQ_Move_Hardware(QObject):
878
837
  @Slot(edict)
879
838
  def update_settings(self, settings_parameter_dict):
880
839
  """
881
- Update settings of hardware with dictionnary parameters in case of "Move_Settings" path, else update attribute with dictionnary parameters.
840
+ Update settings of hardware with dictionary parameters in case of "Move_Settings" path, else update attribute with dictionnary parameters.
882
841
 
883
842
  ========================= =========== ======================================================
884
843
  **Parameters** **Type** **Description**
885
844
 
886
- *settings_parameter_dict* dictionnary Dictionnary containing the path and linked parameter
845
+ *settings_parameter_dict* dictionary Dictionary containing the path and linked parameter
887
846
  ========================= =========== ======================================================
888
847
 
889
848
  See Also
@@ -10,8 +10,9 @@ from collections import OrderedDict
10
10
  import copy
11
11
  import os
12
12
  from pathlib import Path
13
+ from random import randint
13
14
  import sys
14
- from typing import List, Tuple, Union
15
+ from typing import List, Tuple, Union, Optional
15
16
  import time
16
17
 
17
18
  from easydict import EasyDict as edict
@@ -21,9 +22,8 @@ from qtpy.QtCore import Qt, QObject, Slot, QThread, Signal
21
22
 
22
23
  from pymodaq.utils.data import DataFromPlugins, DataToExport, Axis, DataDistribution
23
24
  from pymodaq.utils.logger import set_logger, get_module_name
24
- from pymodaq.control_modules.utils import ControlModule
25
+ from pymodaq.control_modules.utils import ParameterControlModule
25
26
  from pymodaq.utils.gui_utils.file_io import select_file
26
- from pymodaq.utils.tcp_ip.tcp_server_client import TCPClient
27
27
  from pymodaq.utils.gui_utils.widgets.lcd import LCD
28
28
  from pymodaq.utils.config import Config, get_set_local_dir
29
29
  from pymodaq.utils.h5modules.browsing import browse_data
@@ -31,26 +31,28 @@ from pymodaq.utils.h5modules.saving import H5Saver
31
31
  from pymodaq.utils.h5modules import module_saving
32
32
  from pymodaq.utils.h5modules.backends import Node
33
33
  from pymodaq.utils.daq_utils import ThreadCommand
34
- from pymodaq.utils.parameter import ioxml
34
+ from pymodaq.utils.parameter import ioxml, Parameter
35
35
  from pymodaq.utils.parameter import utils as putils
36
36
  from pymodaq.control_modules.viewer_utility_classes import params as daq_viewer_params
37
37
  from pymodaq.utils import daq_utils as utils
38
38
  from pymodaq.utils.messenger import deprecation_msg
39
39
  from pymodaq.utils.gui_utils import DockArea, get_splash_sc, Dock
40
- from pymodaq.utils.managers.parameter_manager import ParameterManager, Parameter
41
40
  from pymodaq.control_modules.daq_viewer_ui import DAQ_Viewer_UI
42
41
  from pymodaq.control_modules.utils import DET_TYPES, get_viewer_plugins, DAQTypesEnum, DetectorError
43
- from pymodaq.utils.plotting.data_viewers.viewer import ViewerBase, ViewersEnum
42
+ from pymodaq.utils.plotting.data_viewers.viewer import ViewerBase
43
+ from pymodaq.utils.plotting.data_viewers import ViewersEnum
44
44
  from pymodaq.utils.enums import enum_checker
45
45
  from pymodaq.control_modules.viewer_utility_classes import DAQ_Viewer_base
46
46
 
47
+ from pymodaq.utils.leco.pymodaq_listener import ViewerActorListener, LECOClientCommands
48
+
47
49
  logger = set_logger(get_module_name(__file__))
48
50
  config = Config()
49
51
 
50
52
  local_path = get_set_local_dir()
51
53
 
52
54
 
53
- class DAQ_Viewer(ParameterManager, ControlModule):
55
+ class DAQ_Viewer(ParameterControlModule):
54
56
  """ Main PyMoDAQ class to drive detectors
55
57
 
56
58
  Qt object and generic UI to drive actuators. The class is giving you full functionality to select (daq_detector),
@@ -80,26 +82,27 @@ class DAQ_Viewer(ParameterManager, ControlModule):
80
82
  create if one want to receive infos from the ROI
81
83
  """
82
84
  settings_name = 'daq_viewer_settings'
83
- custom_sig = Signal(ThreadCommand) # particular case where DAQ_Viewer is used for a custom module
85
+ custom_sig = Signal(ThreadCommand) # particular case where DAQ_Viewer is used for a custom module
84
86
 
85
87
  grab_done_signal = Signal(DataToExport)
86
88
 
87
- _update_settings_signal = Signal(edict)
88
89
  overshoot_signal = Signal(bool)
89
90
  data_saved = Signal()
90
91
  grab_status = Signal(bool)
91
92
 
92
93
  params = daq_viewer_params
93
94
 
95
+ listener_class = ViewerActorListener
96
+
94
97
  def __init__(self, parent=None, title="Testing",
95
98
  daq_type=config('viewer', 'daq_type'),
96
- dock_settings=None, dock_viewer=None):
99
+ dock_settings=None, dock_viewer=None,
100
+ **kwargs):
97
101
 
98
102
  self.logger = set_logger(f'{logger.name}.{title}')
99
103
  self.logger.info(f'Initializing DAQ_Viewer: {title}')
100
104
 
101
- ParameterManager.__init__(self, action_list = ('save','update'))
102
- ControlModule.__init__(self)
105
+ super().__init__(**kwargs)
103
106
 
104
107
  daq_type = enum_checker(DAQTypesEnum, daq_type)
105
108
  self._daq_type: DAQTypesEnum = daq_type
@@ -118,7 +121,7 @@ class DAQ_Viewer(ParameterManager, ControlModule):
118
121
  dock_settings=dock_settings,
119
122
  dock_viewer=dock_viewer)
120
123
  else:
121
- self.ui: DAQ_Viewer_UI = None
124
+ self.ui: Optional[DAQ_Viewer_UI] = None
122
125
 
123
126
  if self.ui is not None:
124
127
  QtWidgets.QApplication.processEvents()
@@ -131,10 +134,11 @@ class DAQ_Viewer(ParameterManager, ControlModule):
131
134
 
132
135
  self._title = title
133
136
 
134
- self.module_and_data_saver: Union[module_saving.DetectorSaver,
137
+ self.module_and_data_saver: Union[None,
138
+ module_saving.DetectorSaver,
135
139
  module_saving.DetectorEnlargeableSaver,
136
140
  module_saving.DetectorExtendedSaver] = None
137
- self._h5saver_continuous: H5Saver = None
141
+ self._h5saver_continuous: Optional[H5Saver] = None
138
142
  self._ind_continuous_grab = 0
139
143
  self.setup_continuous_saving()
140
144
 
@@ -154,14 +158,14 @@ class DAQ_Viewer(ParameterManager, ControlModule):
154
158
  self._start_grab_time: float = 0. # used for the refreshing rate
155
159
  self._received_data: int = 0
156
160
 
157
- self._lcd: LCD = None
161
+ self._lcd: Optional[LCD] = None
158
162
 
159
- self._bkg: DataToExport = None # buffer to store background
163
+ self._bkg: Optional[DataToExport] = None # buffer to store background
160
164
 
161
- self._save_file_pathname: Path = None # to store last active path, will be an Path object
165
+ self._save_file_pathname: Optional[Path] = None # to store last active path, will be an Path object
162
166
 
163
- self._snapshot_pathname: Path = None
164
- self._data_to_save_export: DataToExport = None
167
+ self._snapshot_pathname: Optional[Path] = None
168
+ self._data_to_save_export: Optional[DataToExport] = None
165
169
 
166
170
  self._do_save_data: bool = False
167
171
 
@@ -370,11 +374,17 @@ class DAQ_Viewer(ParameterManager, ControlModule):
370
374
  viewer.data_to_export_signal.disconnect()
371
375
  except:
372
376
  pass
373
- for viewer in viewers:
377
+ for ind_viewer, viewer in enumerate(viewers):
374
378
  viewer.data_to_export_signal.connect(self._get_data_from_viewer)
375
- if hasattr(viewer, 'ROI_select_signal'):
376
- viewer.ROI_select_signal.connect(
377
- lambda roi_pos_size: self.command_hardware.emit(ThreadCommand('ROISelect', roi_pos_size)))
379
+ #deprecated:
380
+ viewer.ROI_select_signal.connect(
381
+ lambda roi_info: self.command_hardware.emit(ThreadCommand('ROISelect', roi_info)))
382
+ #use that now
383
+ viewer.roi_select_signal.connect(
384
+ lambda roi_info: self.command_hardware.emit(
385
+ ThreadCommand('roi_select',
386
+ dict(roi_info=roi_info, ind_viewer=ind_viewer))))
387
+
378
388
  self._viewers = viewers
379
389
 
380
390
  def quit_fun(self):
@@ -661,8 +671,8 @@ class DAQ_Viewer(ParameterManager, ControlModule):
661
671
  dte.get_data_from_source('raw') # filters depending on the source: raw or calculated
662
672
 
663
673
  dte = DataToExport(name=dte.name, data= # filters depending on the extra argument 'save'
664
- [dwa for dwa in dte if ('save' not in dwa.extra_attributes) or
665
- ('save' in dwa.extra_attributes and dwa.save)])
674
+ [dwa for dwa in dte if ('do_save' not in dwa.extra_attributes) or
675
+ ('do_save' in dwa.extra_attributes and dwa.do_save)])
666
676
 
667
677
  self.module_and_data_saver.add_data(detector_node, dte, **kwargs)
668
678
 
@@ -787,7 +797,9 @@ class DAQ_Viewer(ParameterManager, ControlModule):
787
797
  """
788
798
  try:
789
799
  dte = dte.deepcopy()
790
- if self.settings.child('main_settings', 'tcpip', 'tcp_connected').value() and self._send_to_tcpip:
800
+ if self.settings['main_settings', 'tcpip', 'tcp_connected'] and self._send_to_tcpip:
801
+ self._command_tcpip.emit(ThreadCommand('data_ready', dte))
802
+ if self.settings['main_settings', 'leco', 'leco_connected'] and self._send_to_tcpip:
791
803
  self._command_tcpip.emit(ThreadCommand('data_ready', dte))
792
804
  if self.ui is not None:
793
805
  self.ui.data_ready = True
@@ -818,8 +830,8 @@ class DAQ_Viewer(ParameterManager, ControlModule):
818
830
  refresh = True # if single
819
831
  if self.ui is not None and self.settings.child('main_settings', 'show_data').value() and refresh:
820
832
  self._received_data = 0 # so that data send back from viewers can be properly counted
821
- data_to_plot = self._data_to_save_export.get_data_from_attribute('plot', True, deepcopy=True)
822
- data_to_plot.append(self._data_to_save_export.get_data_from_missing_attribute('plot', deepcopy=True))
833
+ data_to_plot = self._data_to_save_export.get_data_from_attribute('do_plot', True, deepcopy=True)
834
+ data_to_plot.append(self._data_to_save_export.get_data_from_missing_attribute('do_plot', deepcopy=True))
823
835
  # process bkg if needed
824
836
  if self.do_bkg and self._bkg is not None:
825
837
  data_to_plot -= self._bkg
@@ -850,8 +862,8 @@ class DAQ_Viewer(ParameterManager, ControlModule):
850
862
  self._process_overshoot(dte)
851
863
 
852
864
  self._viewer_types = [ViewersEnum(dwa.dim.name) for dwa in dte if
853
- ('plot' not in dwa.extra_attributes) or
854
- ('plot' in dwa.extra_attributes and dwa.plot)]
865
+ ('do_plot' not in dwa.extra_attributes) or
866
+ ('do_plot' in dwa.extra_attributes and dwa.do_plot)]
855
867
  if self.ui is not None:
856
868
  if self.ui.viewer_types != self._viewer_types:
857
869
  self.ui.update_viewers(self._viewer_types)
@@ -870,8 +882,8 @@ class DAQ_Viewer(ParameterManager, ControlModule):
870
882
  ViewerBase, Viewer0D, Viewer1D, Viewer2D
871
883
  """
872
884
  for ind, dwa in enumerate(dte):
873
- if ('plot' not in dwa.extra_attributes) or \
874
- ('plot' in dwa.extra_attributes and dwa.plot):
885
+ if ('do_plot' not in dwa.extra_attributes) or \
886
+ ('do_plot' in dwa.extra_attributes and dwa.do_plot):
875
887
  self.viewers[ind].title = dwa.name
876
888
  self.viewer_docks[ind].setTitle(self._title + ' ' + dwa.name)
877
889
 
@@ -888,6 +900,8 @@ class DAQ_Viewer(ParameterManager, ControlModule):
888
900
  param: Parameter
889
901
  a given parameter whose value has been changed by user
890
902
  """
903
+ super().value_changed(param=param)
904
+
891
905
  path = self.settings.childPath(param)
892
906
  if param.name() == 'DAQ_type':
893
907
  self._h5saver_continuous.settings.child('do_save').setValue(False)
@@ -927,27 +941,7 @@ class DAQ_Viewer(ParameterManager, ControlModule):
927
941
  elif param.name() == 'wait_time':
928
942
  self.command_hardware.emit(ThreadCommand('update_wait_time', [param.value()]))
929
943
 
930
- elif param.name() == 'connect_server':
931
- if param.value():
932
- self.connect_tcp_ip()
933
- else:
934
- self._command_tcpip.emit(ThreadCommand('quit', ))
935
-
936
- elif param.name() == 'ip_address' or param.name == 'port':
937
- self._command_tcpip.emit(
938
- ThreadCommand('update_connection',
939
- dict(ipaddress=self.settings['main_settings', 'tcpip', 'ip_address'],
940
- port=self.settings['main_settings', 'tcpip', 'port'])))
941
-
942
- elif param.name() == 'plugin_config':
943
- self.show_config(self.plugin_config)
944
-
945
- if path is not None:
946
- if 'main_settings' not in path:
947
- self._update_settings_signal.emit(edict(path=path, param=param, change='value'))
948
-
949
- if self.settings.child('main_settings', 'tcpip', 'tcp_connected').value():
950
- self._command_tcpip.emit(ThreadCommand('send_info', dict(path=path, param=param)))
944
+ self._update_settings(param=param)
951
945
 
952
946
  def child_added(self, param, data):
953
947
  """ Adds a child in the settings attribute
@@ -991,6 +985,7 @@ class DAQ_Viewer(ParameterManager, ControlModule):
991
985
 
992
986
  det_params, _class = get_viewer_plugins(self.daq_type.name, self.detector)
993
987
  self.settings.child('detector_settings').addChildren(det_params.children())
988
+ self.settings.child('main_settings', 'module_name').setValue(self._title)
994
989
  except Exception as e:
995
990
  self.logger.exception(str(e))
996
991
 
@@ -1078,32 +1073,11 @@ class DAQ_Viewer(ParameterManager, ControlModule):
1078
1073
  self.stop_grab()
1079
1074
 
1080
1075
  def connect_tcp_ip(self):
1081
- """Init a TCPClient in a separated thread to communicate with a distant TCp/IP Server
1082
-
1083
- Use the settings: ip_address and port to specify the connection
1084
-
1085
- See Also
1086
- --------
1087
- TCPServer
1088
- """
1089
- if self.settings.child('main_settings', 'tcpip', 'connect_server').value():
1090
- self._tcpclient_thread = QThread()
1091
-
1092
- tcpclient = TCPClient(self.settings.child('main_settings', 'tcpip', 'ip_address').value(),
1093
- self.settings.child('main_settings', 'tcpip', 'port').value(),
1094
- self.settings.child('detector_settings'))
1095
- tcpclient.moveToThread(self._tcpclient_thread)
1096
- self._tcpclient_thread.tcpclient = tcpclient
1097
- tcpclient.cmd_signal.connect(self.process_tcpip_cmds)
1098
-
1099
- self._command_tcpip[ThreadCommand].connect(tcpclient.queue_command)
1100
-
1101
- self._tcpclient_thread.started.connect(tcpclient.init_connection)
1102
-
1103
- self._tcpclient_thread.start()
1076
+ super().connect_tcp_ip(params_state=self.settings.child('detector_settings'),
1077
+ client_type="GRABBER")
1104
1078
 
1105
1079
  @Slot(ThreadCommand)
1106
- def process_tcpip_cmds(self, status):
1080
+ def process_tcpip_cmds(self, status: ThreadCommand) -> None:
1107
1081
  """Receive commands from the TCP Server (if connected) and process them
1108
1082
 
1109
1083
  Parameters
@@ -1121,23 +1095,16 @@ class DAQ_Viewer(ParameterManager, ControlModule):
1121
1095
  connect_tcp_ip, TCPServer
1122
1096
 
1123
1097
  """
1098
+ if super().process_tcpip_cmds(status=status) is None:
1099
+ return
1124
1100
  if 'Send Data' in status.command:
1125
1101
  self.snapshot('', send_to_tcpip=True)
1126
- elif status.command == 'connected':
1127
- self.settings.child('main_settings', 'tcpip', 'tcp_connected').setValue(True)
1128
1102
 
1129
- elif status.command == 'disconnected':
1130
- self.settings.child('main_settings', 'tcpip', 'tcp_connected').setValue(False)
1103
+ elif status.command == LECOClientCommands.LECO_CONNECTED:
1104
+ self.settings.child('main_settings', 'leco', 'leco_connected').setValue(True)
1131
1105
 
1132
- elif status.command == 'Update_Status':
1133
- self.thread_status(status)
1134
-
1135
- elif status.command == 'set_info':
1136
- param_dict = ioxml.XML_string_to_parameter(status.attribute[1])[0]
1137
- param_tmp = Parameter.create(**param_dict)
1138
- param = self.settings.child('detector_settings', *status.attribute[0][1:])
1139
-
1140
- param.restoreState(param_tmp.saveState())
1106
+ elif status.command == LECOClientCommands.LECO_DISCONNECTED:
1107
+ self.settings.child('main_settings', 'leco', 'leco_connected').setValue(False)
1141
1108
 
1142
1109
  elif status.command == 'get_axis':
1143
1110
  raise DeprecationWarning('Do not use this, the axis are in the data objects')
@@ -1270,7 +1237,12 @@ class DAQ_Detector(QObject):
1270
1237
  else: # custom commands for particular plugins
1271
1238
  if hasattr(self.detector, command.command):
1272
1239
  cmd = getattr(self.detector, command.command)
1273
- cmd(command.attribute)
1240
+ if isinstance(command.attribute, list):
1241
+ cmd(*command.attribute)
1242
+ elif isinstance(command.attribute, dict):
1243
+ cmd(**command.attribute)
1244
+ else:
1245
+ cmd(command.attribute)
1274
1246
 
1275
1247
  def ini_detector(self, params_state=None, controller=None):
1276
1248
  """ Initialize an instrument plugin class and tries to apply preset settings
@@ -1387,8 +1359,9 @@ class DAQ_Detector(QObject):
1387
1359
  self.average_done = False
1388
1360
  self.waiting_for_data = False
1389
1361
 
1390
- # for live mode:two possibilities: either snap one data and regrab softwarewise (while True) or if
1391
- # self.detector.live_mode_available is True all data is continuously emitted from the plugin
1362
+ # for live mode:two possibilities: either snap one data and regrab softwarewise
1363
+ # (while True) or if self.detector.live_mode_available is True all data is continuously
1364
+ # emitted from the plugin
1392
1365
  if self.detector.live_mode_available:
1393
1366
  kwargs['wait_time'] = self.wait_time
1394
1367
  else:
@@ -1407,12 +1380,14 @@ class DAQ_Detector(QObject):
1407
1380
  if self.average_done:
1408
1381
  break
1409
1382
  else:
1410
- QThread.msleep(self.wait_time) # if in grab mode apply a waiting time after acquisition
1383
+ QThread.msleep(self.wait_time) # if in grab mode apply a waiting time
1384
+ # after acquisition
1411
1385
  if not self.grab_state:
1412
1386
  break # if not in grab mode breaks the while loop
1413
- if self.detector.live_mode_available and (not self.hardware_averaging and self.average_done):
1414
- break # if live can be done in the plugin breaks the while loop except if average is asked but
1415
- # not done hardware wise
1387
+ if self.detector.live_mode_available and (not self.hardware_averaging and
1388
+ self.average_done):
1389
+ break # if live can be done in the plugin breaks the while loop except
1390
+ # if average is asked but not done hardware wise
1416
1391
  except Exception as e:
1417
1392
  self.logger.exception(str(e))
1418
1393
  self.status_sig.emit(ThreadCommand('grab_stopped'))
@@ -19,7 +19,8 @@ from pymodaq.utils.gui_utils.widgets import PushButtonIcon, LabelWithFont, QLED
19
19
  from pymodaq.utils.gui_utils import Dock
20
20
  from pymodaq.utils.config import Config
21
21
  from pymodaq.control_modules.utils import DET_TYPES, DAQTypesEnum
22
- from pymodaq.utils.plotting.data_viewers.viewer import ViewerFactory, ViewersEnum, ViewerDispatcher
22
+ from pymodaq.utils.plotting.data_viewers.viewer import ViewerFactory, ViewerDispatcher
23
+ from pymodaq.utils.plotting.data_viewers import ViewersEnum
23
24
  from pymodaq.utils.enums import enum_checker
24
25
 
25
26