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.
- pymodaq/__init__.py +23 -4
- pymodaq/control_modules/daq_move.py +32 -73
- pymodaq/control_modules/daq_viewer.py +73 -98
- pymodaq/control_modules/daq_viewer_ui.py +2 -1
- pymodaq/control_modules/move_utility_classes.py +17 -7
- pymodaq/control_modules/utils.py +153 -5
- pymodaq/control_modules/viewer_utility_classes.py +31 -20
- pymodaq/dashboard.py +23 -5
- pymodaq/examples/tcp_client.py +97 -0
- pymodaq/extensions/__init__.py +4 -0
- pymodaq/extensions/bayesian/__init__.py +2 -0
- pymodaq/extensions/bayesian/bayesian_optimisation.py +673 -0
- pymodaq/extensions/bayesian/utils.py +403 -0
- pymodaq/extensions/daq_scan.py +4 -4
- pymodaq/extensions/daq_scan_ui.py +2 -1
- pymodaq/extensions/pid/pid_controller.py +12 -7
- pymodaq/extensions/pid/utils.py +9 -26
- pymodaq/extensions/utils.py +3 -0
- pymodaq/post_treatment/load_and_plot.py +42 -19
- pymodaq/resources/VERSION +1 -1
- pymodaq/resources/config_template.toml +9 -24
- pymodaq/resources/setup_plugin.py +1 -1
- pymodaq/utils/config.py +103 -5
- pymodaq/utils/daq_utils.py +35 -134
- pymodaq/utils/data.py +614 -95
- pymodaq/utils/enums.py +17 -1
- pymodaq/utils/factory.py +2 -2
- pymodaq/utils/gui_utils/custom_app.py +5 -2
- pymodaq/utils/gui_utils/dock.py +33 -4
- pymodaq/utils/gui_utils/utils.py +14 -1
- pymodaq/utils/h5modules/backends.py +9 -1
- pymodaq/utils/h5modules/data_saving.py +254 -57
- pymodaq/utils/h5modules/saving.py +1 -0
- pymodaq/utils/leco/__init__.py +25 -0
- pymodaq/utils/leco/daq_move_LECODirector.py +172 -0
- pymodaq/utils/leco/daq_xDviewer_LECODirector.py +170 -0
- pymodaq/utils/leco/desktop.ini +2 -0
- pymodaq/utils/leco/director_utils.py +58 -0
- pymodaq/utils/leco/leco_director.py +88 -0
- pymodaq/utils/leco/pymodaq_listener.py +279 -0
- pymodaq/utils/leco/utils.py +41 -0
- pymodaq/utils/managers/action_manager.py +20 -6
- pymodaq/utils/managers/parameter_manager.py +6 -4
- pymodaq/utils/managers/roi_manager.py +63 -54
- pymodaq/utils/math_utils.py +1 -1
- pymodaq/utils/plotting/data_viewers/__init__.py +3 -1
- pymodaq/utils/plotting/data_viewers/base.py +286 -0
- pymodaq/utils/plotting/data_viewers/viewer.py +29 -202
- pymodaq/utils/plotting/data_viewers/viewer0D.py +94 -47
- pymodaq/utils/plotting/data_viewers/viewer1D.py +341 -174
- pymodaq/utils/plotting/data_viewers/viewer1Dbasic.py +1 -1
- pymodaq/utils/plotting/data_viewers/viewer2D.py +271 -181
- pymodaq/utils/plotting/data_viewers/viewerND.py +26 -22
- pymodaq/utils/plotting/items/crosshair.py +3 -3
- pymodaq/utils/plotting/items/image.py +2 -1
- pymodaq/utils/plotting/plotter/plotter.py +94 -0
- pymodaq/utils/plotting/plotter/plotters/__init__.py +0 -0
- pymodaq/utils/plotting/plotter/plotters/matplotlib_plotters.py +134 -0
- pymodaq/utils/plotting/plotter/plotters/qt_plotters.py +78 -0
- pymodaq/utils/plotting/utils/axes_viewer.py +1 -1
- pymodaq/utils/plotting/utils/filter.py +194 -147
- pymodaq/utils/plotting/utils/lineout.py +13 -11
- pymodaq/utils/plotting/utils/plot_utils.py +89 -12
- pymodaq/utils/scanner/__init__.py +0 -3
- pymodaq/utils/scanner/scan_config.py +1 -9
- pymodaq/utils/scanner/scan_factory.py +10 -36
- pymodaq/utils/scanner/scanner.py +3 -2
- pymodaq/utils/scanner/scanners/_1d_scanners.py +7 -5
- pymodaq/utils/scanner/scanners/_2d_scanners.py +36 -49
- pymodaq/utils/scanner/scanners/sequential.py +10 -4
- pymodaq/utils/scanner/scanners/tabular.py +10 -5
- pymodaq/utils/slicing.py +1 -1
- pymodaq/utils/tcp_ip/serializer.py +38 -5
- pymodaq/utils/tcp_ip/tcp_server_client.py +25 -17
- {pymodaq-4.1.5.dist-info → pymodaq-4.2.1.dist-info}/METADATA +4 -2
- {pymodaq-4.1.5.dist-info → pymodaq-4.2.1.dist-info}/RECORD +79 -63
- pymodaq/resources/config_scan_template.toml +0 -42
- {pymodaq-4.1.5.dist-info → pymodaq-4.2.1.dist-info}/WHEEL +0 -0
- {pymodaq-4.1.5.dist-info → pymodaq-4.2.1.dist-info}/entry_points.txt +0 -0
- {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
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
395
|
-
self.
|
|
380
|
+
if param.name() == 'refresh_timeout':
|
|
381
|
+
self._refresh_timer.setInterval(param.value())
|
|
396
382
|
|
|
397
|
-
|
|
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
|
-
|
|
590
|
-
|
|
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
|
|
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
|
|
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*
|
|
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
|
|
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
|
|
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(
|
|
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
|
|
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
|
-
|
|
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[
|
|
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
|
-
|
|
376
|
-
|
|
377
|
-
|
|
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 ('
|
|
665
|
-
('
|
|
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
|
|
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('
|
|
822
|
-
data_to_plot.append(self._data_to_save_export.get_data_from_missing_attribute('
|
|
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
|
-
('
|
|
854
|
-
('
|
|
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 ('
|
|
874
|
-
('
|
|
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
|
-
|
|
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
|
-
|
|
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 ==
|
|
1130
|
-
self.settings.child('main_settings', '
|
|
1103
|
+
elif status.command == LECOClientCommands.LECO_CONNECTED:
|
|
1104
|
+
self.settings.child('main_settings', 'leco', 'leco_connected').setValue(True)
|
|
1131
1105
|
|
|
1132
|
-
elif status.command ==
|
|
1133
|
-
self.
|
|
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
|
-
|
|
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
|
|
1391
|
-
# self.detector.live_mode_available is True all data is continuously
|
|
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
|
|
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
|
|
1414
|
-
|
|
1415
|
-
#
|
|
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,
|
|
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
|
|