pymodaq 5.1.6__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.
- pymodaq/__init__.py +98 -0
- pymodaq/control_modules/__init__.py +1 -0
- pymodaq/control_modules/daq_move.py +1238 -0
- pymodaq/control_modules/daq_move_ui/__init__.py +0 -0
- pymodaq/control_modules/daq_move_ui/factory.py +48 -0
- pymodaq/control_modules/daq_move_ui/ui_base.py +359 -0
- pymodaq/control_modules/daq_move_ui/uis/__init__.py +0 -0
- pymodaq/control_modules/daq_move_ui/uis/binary.py +139 -0
- pymodaq/control_modules/daq_move_ui/uis/original.py +120 -0
- pymodaq/control_modules/daq_move_ui/uis/relative.py +124 -0
- pymodaq/control_modules/daq_move_ui/uis/simple.py +126 -0
- pymodaq/control_modules/daq_viewer.py +1517 -0
- pymodaq/control_modules/daq_viewer_ui.py +407 -0
- pymodaq/control_modules/mocks.py +57 -0
- pymodaq/control_modules/move_utility_classes.py +1141 -0
- pymodaq/control_modules/thread_commands.py +137 -0
- pymodaq/control_modules/ui_utils.py +72 -0
- pymodaq/control_modules/utils.py +591 -0
- pymodaq/control_modules/viewer_utility_classes.py +670 -0
- pymodaq/daq_utils/__init__.py +0 -0
- pymodaq/daq_utils/daq_utils.py +6 -0
- pymodaq/dashboard.py +2396 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.aliases +3 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.lvlps +3 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.lvproj +32 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Server_1Dgaussian.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Server_2Dgaussian.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_read_cmd.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_read_float.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_read_int.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_data.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_int.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_scalar.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_string.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/client_state.ctl +0 -0
- pymodaq/examples/Labview_TCP_Client/cmd_types.ctl +0 -0
- pymodaq/examples/__init__.py +0 -0
- pymodaq/examples/function_plotter.py +160 -0
- pymodaq/examples/nonlinearscanner.py +126 -0
- pymodaq/examples/qt_less_standalone_module.py +165 -0
- pymodaq/examples/tcp_client.py +97 -0
- pymodaq/extensions/__init__.py +25 -0
- pymodaq/extensions/adaptive/__init__.py +2 -0
- pymodaq/extensions/adaptive/adaptive_optimization.py +179 -0
- pymodaq/extensions/adaptive/loss_function/_1d_loss_functions.py +73 -0
- pymodaq/extensions/adaptive/loss_function/_2d_loss_functions.py +73 -0
- pymodaq/extensions/adaptive/loss_function/__init__.py +3 -0
- pymodaq/extensions/adaptive/loss_function/loss_factory.py +110 -0
- pymodaq/extensions/adaptive/utils.py +123 -0
- pymodaq/extensions/bayesian/__init__.py +2 -0
- pymodaq/extensions/bayesian/acquisition/__init__.py +2 -0
- pymodaq/extensions/bayesian/acquisition/acquisition_function_factory.py +80 -0
- pymodaq/extensions/bayesian/acquisition/base_acquisition_function.py +105 -0
- pymodaq/extensions/bayesian/bayesian_optimization.py +143 -0
- pymodaq/extensions/bayesian/utils.py +180 -0
- pymodaq/extensions/console.py +73 -0
- pymodaq/extensions/daq_logger/__init__.py +1 -0
- pymodaq/extensions/daq_logger/abstract.py +52 -0
- pymodaq/extensions/daq_logger/daq_logger.py +519 -0
- pymodaq/extensions/daq_logger/db/__init__.py +0 -0
- pymodaq/extensions/daq_logger/db/db_logger.py +300 -0
- pymodaq/extensions/daq_logger/db/db_logger_models.py +100 -0
- pymodaq/extensions/daq_logger/h5logging.py +84 -0
- pymodaq/extensions/daq_scan.py +1218 -0
- pymodaq/extensions/daq_scan_ui.py +241 -0
- pymodaq/extensions/data_mixer/__init__.py +0 -0
- pymodaq/extensions/data_mixer/daq_0Dviewer_DataMixer.py +97 -0
- pymodaq/extensions/data_mixer/data_mixer.py +262 -0
- pymodaq/extensions/data_mixer/model.py +108 -0
- pymodaq/extensions/data_mixer/models/__init__.py +0 -0
- pymodaq/extensions/data_mixer/models/equation_model.py +91 -0
- pymodaq/extensions/data_mixer/models/gaussian_fit_model.py +65 -0
- pymodaq/extensions/data_mixer/parser.py +53 -0
- pymodaq/extensions/data_mixer/utils.py +23 -0
- pymodaq/extensions/h5browser.py +9 -0
- pymodaq/extensions/optimizers_base/__init__.py +0 -0
- pymodaq/extensions/optimizers_base/optimizer.py +1016 -0
- pymodaq/extensions/optimizers_base/thread_commands.py +22 -0
- pymodaq/extensions/optimizers_base/utils.py +427 -0
- pymodaq/extensions/pid/__init__.py +16 -0
- pymodaq/extensions/pid/actuator_controller.py +14 -0
- pymodaq/extensions/pid/daq_move_PID.py +154 -0
- pymodaq/extensions/pid/pid_controller.py +1016 -0
- pymodaq/extensions/pid/utils.py +189 -0
- pymodaq/extensions/utils.py +111 -0
- pymodaq/icon.ico +0 -0
- pymodaq/post_treatment/__init__.py +6 -0
- pymodaq/post_treatment/load_and_plot.py +352 -0
- pymodaq/resources/__init__.py +0 -0
- pymodaq/resources/config_template.toml +57 -0
- pymodaq/resources/preset_default.xml +1 -0
- pymodaq/resources/setup_plugin.py +73 -0
- pymodaq/splash.png +0 -0
- pymodaq/utils/__init__.py +0 -0
- pymodaq/utils/array_manipulation.py +6 -0
- pymodaq/utils/calibration_camera.py +180 -0
- pymodaq/utils/chrono_timer.py +203 -0
- pymodaq/utils/config.py +53 -0
- pymodaq/utils/conftests.py +5 -0
- pymodaq/utils/daq_utils.py +158 -0
- pymodaq/utils/data.py +128 -0
- pymodaq/utils/enums.py +6 -0
- pymodaq/utils/exceptions.py +38 -0
- pymodaq/utils/gui_utils/__init__.py +10 -0
- pymodaq/utils/gui_utils/loader_utils.py +75 -0
- pymodaq/utils/gui_utils/utils.py +18 -0
- pymodaq/utils/gui_utils/widgets/lcd.py +8 -0
- pymodaq/utils/h5modules/__init__.py +2 -0
- pymodaq/utils/h5modules/module_saving.py +526 -0
- pymodaq/utils/leco/__init__.py +25 -0
- pymodaq/utils/leco/daq_move_LECODirector.py +217 -0
- pymodaq/utils/leco/daq_xDviewer_LECODirector.py +163 -0
- pymodaq/utils/leco/director_utils.py +74 -0
- pymodaq/utils/leco/leco_director.py +166 -0
- pymodaq/utils/leco/pymodaq_listener.py +364 -0
- pymodaq/utils/leco/rpc_method_definitions.py +43 -0
- pymodaq/utils/leco/utils.py +74 -0
- pymodaq/utils/logger.py +6 -0
- pymodaq/utils/managers/__init__.py +0 -0
- pymodaq/utils/managers/batchscan_manager.py +346 -0
- pymodaq/utils/managers/modules_manager.py +589 -0
- pymodaq/utils/managers/overshoot_manager.py +242 -0
- pymodaq/utils/managers/preset_manager.py +229 -0
- pymodaq/utils/managers/preset_manager_utils.py +262 -0
- pymodaq/utils/managers/remote_manager.py +484 -0
- pymodaq/utils/math_utils.py +6 -0
- pymodaq/utils/messenger.py +6 -0
- pymodaq/utils/parameter/__init__.py +10 -0
- pymodaq/utils/parameter/utils.py +6 -0
- pymodaq/utils/scanner/__init__.py +5 -0
- pymodaq/utils/scanner/scan_config.py +16 -0
- pymodaq/utils/scanner/scan_factory.py +259 -0
- pymodaq/utils/scanner/scan_selector.py +477 -0
- pymodaq/utils/scanner/scanner.py +324 -0
- pymodaq/utils/scanner/scanners/_1d_scanners.py +174 -0
- pymodaq/utils/scanner/scanners/_2d_scanners.py +299 -0
- pymodaq/utils/scanner/scanners/__init__.py +1 -0
- pymodaq/utils/scanner/scanners/sequential.py +224 -0
- pymodaq/utils/scanner/scanners/tabular.py +319 -0
- pymodaq/utils/scanner/utils.py +110 -0
- pymodaq/utils/svg/__init__.py +6 -0
- pymodaq/utils/svg/svg_renderer.py +20 -0
- pymodaq/utils/svg/svg_view.py +35 -0
- pymodaq/utils/svg/svg_viewer2D.py +50 -0
- pymodaq/utils/tcp_ip/__init__.py +6 -0
- pymodaq/utils/tcp_ip/mysocket.py +12 -0
- pymodaq/utils/tcp_ip/serializer.py +13 -0
- pymodaq/utils/tcp_ip/tcp_server_client.py +772 -0
- pymodaq-5.1.6.dist-info/METADATA +238 -0
- pymodaq-5.1.6.dist-info/RECORD +154 -0
- pymodaq-5.1.6.dist-info/WHEEL +4 -0
- pymodaq-5.1.6.dist-info/entry_points.txt +7 -0
- pymodaq-5.1.6.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,670 @@
|
|
|
1
|
+
from abc import abstractmethod
|
|
2
|
+
from typing import Union, Iterable
|
|
3
|
+
from qtpy import QtWidgets
|
|
4
|
+
from qtpy.QtCore import QObject, Slot, Signal
|
|
5
|
+
|
|
6
|
+
from pymodaq.utils.parameter import ioxml
|
|
7
|
+
from pymodaq.utils.parameter.utils import get_param_path, get_param_from_name, iter_children
|
|
8
|
+
from pymodaq.utils.parameter import Parameter
|
|
9
|
+
from easydict import EasyDict as edict
|
|
10
|
+
|
|
11
|
+
import numpy as np
|
|
12
|
+
from pymodaq.utils.math_utils import gauss1D, gauss2D
|
|
13
|
+
from pymodaq_utils.utils import ThreadCommand, getLineInfo
|
|
14
|
+
|
|
15
|
+
from pymodaq_utils.config import Config, get_set_local_dir
|
|
16
|
+
from pymodaq.utils.tcp_ip.tcp_server_client import TCPServer, tcp_parameters
|
|
17
|
+
from pymodaq_data.data import DataToExport, DataRaw
|
|
18
|
+
from pymodaq_utils.warnings import deprecation_msg
|
|
19
|
+
from pymodaq_utils.serialize.mysocket import Socket
|
|
20
|
+
from pymodaq_utils.serialize.serializer_legacy import DeSerializer, Serializer
|
|
21
|
+
from pymodaq_gui.plotting.utils.plot_utils import RoiInfo
|
|
22
|
+
from pymodaq.control_modules.thread_commands import ThreadStatus, ThreadStatusViewer
|
|
23
|
+
from pymodaq_gui.utils.utils import mkQApp
|
|
24
|
+
|
|
25
|
+
comon_parameters = [{'title': 'Controller Status:', 'name': 'controller_status', 'type': 'list',
|
|
26
|
+
'value': 'Master',
|
|
27
|
+
'limits': ['Master', 'Slave']},
|
|
28
|
+
{'title': 'Controller ID:', 'name': 'controller_ID', 'type': 'int', 'value': 0,
|
|
29
|
+
'default': 0, 'readonly': False},
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
local_path = get_set_local_dir()
|
|
33
|
+
# look for eventual calibration files
|
|
34
|
+
calibs = ['None']
|
|
35
|
+
if local_path.joinpath('camera_calibrations').is_dir():
|
|
36
|
+
for ind_file, file in enumerate(local_path.joinpath('camera_calibrations').iterdir()):
|
|
37
|
+
if 'xml' in file.suffix:
|
|
38
|
+
calibs.append(file.stem)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
config = Config()
|
|
42
|
+
|
|
43
|
+
params = [
|
|
44
|
+
{'title': 'Main Settings:', 'name': 'main_settings', 'expanded': False, 'type': 'group', 'children': [
|
|
45
|
+
{'title': 'DAQ type:', 'name': 'DAQ_type', 'type': 'list', 'limits': ['DAQ0D', 'DAQ1D', 'DAQ2D', 'DAQND'],
|
|
46
|
+
'readonly': True},
|
|
47
|
+
{'title': 'Detector type:', 'name': 'detector_type', 'type': 'str', 'value': '', 'readonly': True},
|
|
48
|
+
{'title': 'Detector Name:', 'name': 'module_name', 'type': 'str', 'value': '', 'readonly': True},
|
|
49
|
+
{'title': 'Plugin Config:', 'name': 'plugin_config', 'type': 'bool_push', 'label': 'Show Config', },
|
|
50
|
+
|
|
51
|
+
{'title': 'Show data and process:', 'name': 'show_data', 'type': 'bool', 'value': True, },
|
|
52
|
+
{'title': 'Refresh time (ms):', 'name': 'refresh_time', 'type': 'float', 'value': 50., 'min': 0.},
|
|
53
|
+
{'title': 'Naverage', 'name': 'Naverage', 'type': 'int', 'default': 1, 'value': 1, 'min': 1},
|
|
54
|
+
{'title': 'Show averaging:', 'name': 'show_averaging', 'type': 'bool', 'default': False, 'value': False},
|
|
55
|
+
{'title': 'Live averaging:', 'name': 'live_averaging', 'type': 'bool', 'default': False, 'value': False},
|
|
56
|
+
{'title': 'N Live aver.:', 'name': 'N_live_averaging', 'type': 'int', 'default': 0, 'value': 0,
|
|
57
|
+
'visible': False},
|
|
58
|
+
{'title': 'Wait time (ms):', 'name': 'wait_time', 'type': 'int', 'default': 0, 'value': 00, 'min': 0},
|
|
59
|
+
{'title': 'Continuous saving:', 'name': 'continuous_saving_opt', 'type': 'bool', 'default': False,
|
|
60
|
+
'value': False},
|
|
61
|
+
{'title': 'TCP/IP options:', 'name': 'tcpip', 'type': 'group', 'visible': True, 'expanded': False, 'children': [
|
|
62
|
+
{'title': 'Connect to server:', 'name': 'connect_server', 'type': 'bool_push', 'label': 'Connect',
|
|
63
|
+
'value': False},
|
|
64
|
+
{'title': 'Connected?:', 'name': 'tcp_connected', 'type': 'led', 'value': False},
|
|
65
|
+
{'title': 'IP address:', 'name': 'ip_address', 'type': 'str',
|
|
66
|
+
'value': config('network', 'tcp-server', 'ip')},
|
|
67
|
+
{'title': 'Port:', 'name': 'port', 'type': 'int', 'value': config('network', 'tcp-server', 'port')},
|
|
68
|
+
]},
|
|
69
|
+
{'title': 'LECO options:', 'name': 'leco', 'type': 'group', 'visible': True, 'expanded': False,
|
|
70
|
+
'children': [
|
|
71
|
+
{'title': 'Connect:', 'name': 'connect_leco_server', 'type': 'bool_push', 'label': 'Connect',
|
|
72
|
+
'value': False},
|
|
73
|
+
{'title': 'Connected?:', 'name': 'leco_connected', 'type': 'led', 'value': False},
|
|
74
|
+
{'title': 'Name', 'name': 'leco_name', 'type': 'str', 'value': "", 'default': ""},
|
|
75
|
+
{'title': 'Host:', 'name': 'host', 'type': 'str', 'value': config('network', "leco-server", "host"), "default": "localhost"},
|
|
76
|
+
{'title': 'Port:', 'name': 'port', 'type': 'int', 'value': config('network', 'leco-server', 'port')},
|
|
77
|
+
]},
|
|
78
|
+
{'title': 'Overshoot options:', 'name': 'overshoot', 'type': 'group', 'visible': True, 'expanded': False,
|
|
79
|
+
'children': [
|
|
80
|
+
{'title': 'Overshoot:', 'name': 'stop_overshoot', 'type': 'bool', 'value': False},
|
|
81
|
+
{'title': 'Overshoot value:', 'name': 'overshoot_value', 'type': 'float', 'value': 0}]},
|
|
82
|
+
{'title': 'Axis options:', 'name': 'axes', 'type': 'group', 'visible': False, 'expanded': False, 'children': [
|
|
83
|
+
{'title': 'Use calibration?:', 'name': 'use_calib', 'type': 'list', 'limits': calibs},
|
|
84
|
+
{'title': 'X axis:', 'name': 'xaxis', 'type': 'group', 'children': [
|
|
85
|
+
{'title': 'Label:', 'name': 'xlabel', 'type': 'str', 'value': "x axis"},
|
|
86
|
+
{'title': 'Units:', 'name': 'xunits', 'type': 'str', 'value': "pxls"},
|
|
87
|
+
{'title': 'Offset:', 'name': 'xoffset', 'type': 'float', 'default': 0., 'value': 0.},
|
|
88
|
+
{'title': 'Scaling', 'name': 'xscaling', 'type': 'float', 'default': 1., 'value': 1.},
|
|
89
|
+
]},
|
|
90
|
+
{'title': 'Y axis:', 'name': 'yaxis', 'type': 'group', 'children': [
|
|
91
|
+
{'title': 'Label:', 'name': 'ylabel', 'type': 'str', 'value': "y axis"},
|
|
92
|
+
{'title': 'Units:', 'name': 'yunits', 'type': 'str', 'value': "pxls"},
|
|
93
|
+
{'title': 'Offset:', 'name': 'yoffset', 'type': 'float', 'default': 0., 'value': 0.},
|
|
94
|
+
{'title': 'Scaling', 'name': 'yscaling', 'type': 'float', 'default': 1., 'value': 1.},
|
|
95
|
+
]},
|
|
96
|
+
]},
|
|
97
|
+
|
|
98
|
+
]},
|
|
99
|
+
{'title': 'Detector Settings', 'name': 'detector_settings', 'type': 'group', 'children': []}
|
|
100
|
+
]
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def main(plugin_file=None, init=True, title='Testing'):
|
|
104
|
+
"""
|
|
105
|
+
this method start a DAQ_Viewer object with this defined plugin as detector
|
|
106
|
+
Returns
|
|
107
|
+
-------
|
|
108
|
+
"""
|
|
109
|
+
import sys
|
|
110
|
+
from qtpy import QtWidgets
|
|
111
|
+
from pymodaq.utils.gui_utils import DockArea
|
|
112
|
+
from pymodaq.control_modules.daq_viewer import DAQ_Viewer
|
|
113
|
+
from pathlib import Path
|
|
114
|
+
|
|
115
|
+
app = mkQApp("PyMoDAQ Viewer")
|
|
116
|
+
|
|
117
|
+
win = QtWidgets.QMainWindow()
|
|
118
|
+
area = DockArea()
|
|
119
|
+
win.setCentralWidget(area)
|
|
120
|
+
win.resize(1000, 500)
|
|
121
|
+
win.setWindowTitle('PyMoDAQ Viewer')
|
|
122
|
+
if plugin_file is None:
|
|
123
|
+
detector = 'Mock'
|
|
124
|
+
det_type = f'DAQ0D'
|
|
125
|
+
else:
|
|
126
|
+
detector = Path(plugin_file).stem[13:]
|
|
127
|
+
det_type = f'DAQ{Path(plugin_file).stem[4:6].upper()}'
|
|
128
|
+
prog = DAQ_Viewer(area, title=title)
|
|
129
|
+
win.show()
|
|
130
|
+
prog.daq_type = det_type
|
|
131
|
+
prog.detector = detector
|
|
132
|
+
if init:
|
|
133
|
+
prog.init_hardware_ui()
|
|
134
|
+
|
|
135
|
+
sys.exit(app.exec_())
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
class DAQ_Viewer_base(QObject):
|
|
139
|
+
"""
|
|
140
|
+
===================== ===================================
|
|
141
|
+
**Attributes** **Type**
|
|
142
|
+
*hardware_averaging* boolean
|
|
143
|
+
*data_grabed_signal* instance of Signal
|
|
144
|
+
*params* list
|
|
145
|
+
*settings* instance of pyqtgraph Parameter
|
|
146
|
+
*parent* ???
|
|
147
|
+
*status* dictionary
|
|
148
|
+
===================== ===================================
|
|
149
|
+
|
|
150
|
+
See Also
|
|
151
|
+
--------
|
|
152
|
+
send_param_status
|
|
153
|
+
"""
|
|
154
|
+
hardware_averaging = False
|
|
155
|
+
live_mode_available = False
|
|
156
|
+
data_grabed_signal = Signal(list) # will be deprecated use dte_signal
|
|
157
|
+
data_grabed_signal_temp = Signal(list) # will be deprecated use dte_signal_temp
|
|
158
|
+
dte_signal = Signal(DataToExport)
|
|
159
|
+
dte_signal_temp = Signal(DataToExport)
|
|
160
|
+
|
|
161
|
+
params = []
|
|
162
|
+
|
|
163
|
+
def __init__(self, parent=None, params_state=None):
|
|
164
|
+
QObject.__init__(self) # to make sure this is the parent class
|
|
165
|
+
|
|
166
|
+
self.parent_parameters_path = [] # this is to be added in the send_param_status to take into account when
|
|
167
|
+
# the current class instance parameter list is a child of some other class
|
|
168
|
+
self.settings = Parameter.create(name='Settings', type='group', children=self.params)
|
|
169
|
+
if params_state is not None:
|
|
170
|
+
if isinstance(params_state, dict):
|
|
171
|
+
self.settings.restoreState(params_state)
|
|
172
|
+
elif isinstance(params_state, Parameter):
|
|
173
|
+
self.settings.restoreState(params_state.saveState())
|
|
174
|
+
|
|
175
|
+
if '0D' in str(self.__class__):
|
|
176
|
+
self.plugin_type = '0D'
|
|
177
|
+
elif '1D' in str(self.__class__):
|
|
178
|
+
self.plugin_type = '1D'
|
|
179
|
+
else:
|
|
180
|
+
self.plugin_type = '2D'
|
|
181
|
+
|
|
182
|
+
self.settings.sigTreeStateChanged.connect(self.send_param_status)
|
|
183
|
+
|
|
184
|
+
self.parent = parent
|
|
185
|
+
self.status = edict(info="", controller=None, initialized=False)
|
|
186
|
+
self.scan_parameters = None
|
|
187
|
+
|
|
188
|
+
self.x_axis = None
|
|
189
|
+
self.y_axis = None
|
|
190
|
+
|
|
191
|
+
self.controller = None
|
|
192
|
+
|
|
193
|
+
if parent is not None:
|
|
194
|
+
self._title = parent.title
|
|
195
|
+
else:
|
|
196
|
+
self._title = "mydetector"
|
|
197
|
+
|
|
198
|
+
self.ini_attributes()
|
|
199
|
+
|
|
200
|
+
try:
|
|
201
|
+
self.data_grabed_signal.connect(self._emit_dte)
|
|
202
|
+
self.data_grabed_signal_temp.connect(self._emit_dte_temp)
|
|
203
|
+
except Exception as exc:
|
|
204
|
+
print(f"Error with old message signal stuff: {exc}")
|
|
205
|
+
|
|
206
|
+
@property
|
|
207
|
+
def is_master(self):
|
|
208
|
+
""" Get the controller master/slave status
|
|
209
|
+
|
|
210
|
+
new in version 4.3.0
|
|
211
|
+
"""
|
|
212
|
+
return self.settings['controller_status'] == 'Master'
|
|
213
|
+
|
|
214
|
+
def _emit_dte(self, dte: Union[DataToExport, list]):
|
|
215
|
+
if isinstance(dte, list):
|
|
216
|
+
deprecation_msg('Data emitted from the instrument plugins should be a DataToExport instance'
|
|
217
|
+
'See: http://pymodaq.cnrs.fr/en/latest/developer_folder/'
|
|
218
|
+
'instrument_plugins.html#emission-of-data')
|
|
219
|
+
dte = DataToExport('temp', dte)
|
|
220
|
+
self.dte_signal.emit(dte)
|
|
221
|
+
|
|
222
|
+
def _emit_dte_temp(self, dte: Union[DataToExport, list]):
|
|
223
|
+
if isinstance(dte, list):
|
|
224
|
+
deprecation_msg('Data emitted from the instrument plugins should be a DataToExport instance'
|
|
225
|
+
'See: http://pymodaq.cnrs.fr/en/latest/developer_folder/'
|
|
226
|
+
'instrument_plugins.html#emission-of-data')
|
|
227
|
+
dte = DataToExport('temp', dte)
|
|
228
|
+
self.dte_signal_temp.emit(dte)
|
|
229
|
+
|
|
230
|
+
def ini_attributes(self):
|
|
231
|
+
"""
|
|
232
|
+
To be reimplemented in subclass
|
|
233
|
+
"""
|
|
234
|
+
pass
|
|
235
|
+
|
|
236
|
+
def ini_detector_init(self, old_controller=None, new_controller=None,
|
|
237
|
+
slave_controller=None):
|
|
238
|
+
"""Manage the Master/Slave controller issue
|
|
239
|
+
|
|
240
|
+
First initialize the status dictionary
|
|
241
|
+
Then check whether this stage is controlled by a multiaxe controller (to be defined for each plugin)
|
|
242
|
+
if it is a multiaxes controller then:
|
|
243
|
+
* if it is Master: init the controller here
|
|
244
|
+
* if it is Slave: use an already initialized controller (defined in the preset of the dashboard)
|
|
245
|
+
|
|
246
|
+
Parameters
|
|
247
|
+
----------
|
|
248
|
+
old_controller: object (deprecated)
|
|
249
|
+
The particular object that allow the communication with the hardware, in general a python wrapper around the
|
|
250
|
+
hardware library. In case of Slave this one comes from a previously initialized plugin
|
|
251
|
+
slave_controller: object
|
|
252
|
+
The particular object that allow the communication with the hardware, in general a python wrapper around the
|
|
253
|
+
hardware library. In case of Slave this one comes from a previously initialized plugin
|
|
254
|
+
new_controller: object
|
|
255
|
+
The particular object that allow the communication with the hardware, in general a python wrapper around the
|
|
256
|
+
hardware library. In case of Master it is the new instance of your plugin controller
|
|
257
|
+
"""
|
|
258
|
+
if old_controller is None and slave_controller is not None:
|
|
259
|
+
old_controller = slave_controller
|
|
260
|
+
self.status.update(edict(info="", controller=None, initialized=False))
|
|
261
|
+
if self.settings['controller_status'] == "Slave":
|
|
262
|
+
if old_controller is None:
|
|
263
|
+
raise Exception('no controller has been defined externally while this axe is a slave one')
|
|
264
|
+
else:
|
|
265
|
+
controller = old_controller
|
|
266
|
+
else: # Master stage
|
|
267
|
+
controller = new_controller
|
|
268
|
+
self.controller = controller
|
|
269
|
+
return controller
|
|
270
|
+
|
|
271
|
+
@abstractmethod
|
|
272
|
+
def ini_detector(self, controller=None):
|
|
273
|
+
"""
|
|
274
|
+
Mandatory
|
|
275
|
+
To be reimplemented in subclass
|
|
276
|
+
"""
|
|
277
|
+
raise NotImplementedError
|
|
278
|
+
|
|
279
|
+
@abstractmethod
|
|
280
|
+
def close(self):
|
|
281
|
+
"""
|
|
282
|
+
Mandatory
|
|
283
|
+
To be reimplemented in subclass
|
|
284
|
+
"""
|
|
285
|
+
raise NotImplementedError
|
|
286
|
+
|
|
287
|
+
@abstractmethod
|
|
288
|
+
def grab_data(self, Naverage=1, **kwargs):
|
|
289
|
+
"""
|
|
290
|
+
Mandatory
|
|
291
|
+
To be reimplemented in subclass
|
|
292
|
+
"""
|
|
293
|
+
raise NotImplementedError
|
|
294
|
+
|
|
295
|
+
@abstractmethod
|
|
296
|
+
def stop(self):
|
|
297
|
+
"""
|
|
298
|
+
Mandatory
|
|
299
|
+
To be reimplemented in subclass
|
|
300
|
+
"""
|
|
301
|
+
raise NotImplementedError
|
|
302
|
+
|
|
303
|
+
def commit_settings(self, param):
|
|
304
|
+
"""
|
|
305
|
+
To be reimplemented in subclass
|
|
306
|
+
"""
|
|
307
|
+
pass
|
|
308
|
+
|
|
309
|
+
def roi_select(self, roi_info: RoiInfo, ind_viewer: int = 0):
|
|
310
|
+
""" Every time a ROISelect is updated on a 2D Viewer,
|
|
311
|
+
this method receive the corresponding info
|
|
312
|
+
|
|
313
|
+
To be subclassed in a plugin to use the info
|
|
314
|
+
|
|
315
|
+
Parameters
|
|
316
|
+
----------
|
|
317
|
+
roi_info: RoiInfo
|
|
318
|
+
ind_viewer: int
|
|
319
|
+
The index of the viewer (if multiple) in which the roi is declared
|
|
320
|
+
"""
|
|
321
|
+
pass
|
|
322
|
+
|
|
323
|
+
def crosshair(self, crosshair_info: Iterable[float], ind_viewer: int = 0):
|
|
324
|
+
""" Every time a crosshair is updated, this method receive the corresponding info
|
|
325
|
+
|
|
326
|
+
To be subclassed in a plugin to use the info
|
|
327
|
+
|
|
328
|
+
Parameters
|
|
329
|
+
----------
|
|
330
|
+
crosshair_info: list of float
|
|
331
|
+
ind_viewer: int
|
|
332
|
+
The index of the viewer (if multiple) in which the crosshair is declared
|
|
333
|
+
"""
|
|
334
|
+
pass
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
def emit_status(self, status: ThreadCommand):
|
|
338
|
+
"""
|
|
339
|
+
Emit the status signal from the given status.
|
|
340
|
+
|
|
341
|
+
=============== ============ =====================================
|
|
342
|
+
**Parameters** **Type** **Description**
|
|
343
|
+
*status* the status information to transmit
|
|
344
|
+
=============== ============ =====================================
|
|
345
|
+
"""
|
|
346
|
+
if self.parent is not None:
|
|
347
|
+
self.parent.status_sig.emit(status)
|
|
348
|
+
QtWidgets.QApplication.processEvents()
|
|
349
|
+
else:
|
|
350
|
+
print(status)
|
|
351
|
+
|
|
352
|
+
def update_scanner(self, scan_parameters):
|
|
353
|
+
# todo check this because ScanParameters has been removed
|
|
354
|
+
self.scan_parameters = scan_parameters
|
|
355
|
+
|
|
356
|
+
@Slot(edict)
|
|
357
|
+
def update_settings(self, settings_parameter_dict):
|
|
358
|
+
"""
|
|
359
|
+
Update the settings tree from settings_parameter_dict.
|
|
360
|
+
Finally do a commit to activate changes.
|
|
361
|
+
|
|
362
|
+
========================== ============= =====================================================
|
|
363
|
+
**Parameters** **Type** **Description**
|
|
364
|
+
*settings_parameter_dict* dictionnnary a dictionary listing path and associated parameter
|
|
365
|
+
========================== ============= =====================================================
|
|
366
|
+
|
|
367
|
+
See Also
|
|
368
|
+
--------
|
|
369
|
+
send_param_status, commit_settings
|
|
370
|
+
"""
|
|
371
|
+
# settings_parameter_dict=edict(path=path,param=param)
|
|
372
|
+
try:
|
|
373
|
+
path = settings_parameter_dict['path']
|
|
374
|
+
param = settings_parameter_dict['param']
|
|
375
|
+
change = settings_parameter_dict['change']
|
|
376
|
+
try:
|
|
377
|
+
self.settings.sigTreeStateChanged.disconnect(self.send_param_status)
|
|
378
|
+
except Exception:
|
|
379
|
+
pass
|
|
380
|
+
if change == 'value':
|
|
381
|
+
self.settings.child(*path[1:]).setValue(param.value()) # blocks signal back to main UI
|
|
382
|
+
elif change == 'childAdded':
|
|
383
|
+
child = Parameter.create(name='tmp')
|
|
384
|
+
child.restoreState(param.saveState())
|
|
385
|
+
self.settings.child(*path[1:]).addChild(child) # blocks signal back to main UI
|
|
386
|
+
param = child
|
|
387
|
+
|
|
388
|
+
elif change == 'parent':
|
|
389
|
+
children = get_param_from_name(self.settings, param.name())
|
|
390
|
+
|
|
391
|
+
if children is not None:
|
|
392
|
+
path = get_param_path(children)
|
|
393
|
+
self.settings.child(*path[1:-1]).removeChild(children)
|
|
394
|
+
|
|
395
|
+
self.settings.sigTreeStateChanged.connect(self.send_param_status)
|
|
396
|
+
|
|
397
|
+
self.commit_settings(param)
|
|
398
|
+
except Exception as e:
|
|
399
|
+
self.emit_status(ThreadCommand(ThreadStatus.UPDATE_STATUS, str(e)))
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
def send_param_status(self, param, changes):
|
|
403
|
+
"""
|
|
404
|
+
Check for changes in the given (parameter,change,information) tuple list.
|
|
405
|
+
In case of value changed, send the 'update_settings' ThreadCommand with concerned path,data and change as attribute.
|
|
406
|
+
|
|
407
|
+
=============== ============================================ ============================
|
|
408
|
+
**Parameters** **Type** **Description**
|
|
409
|
+
*param* instance of pyqtgraph parameter The parameter to check
|
|
410
|
+
*changes* (parameter,change,information) tuple list The changes list to course
|
|
411
|
+
=============== ============================================ ============================
|
|
412
|
+
|
|
413
|
+
See Also
|
|
414
|
+
--------
|
|
415
|
+
daq_utils.ThreadCommand
|
|
416
|
+
"""
|
|
417
|
+
for param, change, data in changes:
|
|
418
|
+
path = self.settings.childPath(param)
|
|
419
|
+
if change == 'childAdded':
|
|
420
|
+
# first create a "copy" of the actual parameter and send this "copy", to be restored in the main UI
|
|
421
|
+
self.emit_status(ThreadCommand(ThreadStatus.UPDATE_SETTINGS,
|
|
422
|
+
[self.parent_parameters_path + path, [data[0].saveState(), data[1]],
|
|
423
|
+
change])) # send parameters values/limits back to the GUI. Send kind of a copy back the GUI otherwise the child reference will be the same in both th eUI and the plugin so one of them will be removed
|
|
424
|
+
|
|
425
|
+
elif change == 'value' or change == 'limits' or change == 'options':
|
|
426
|
+
self.emit_status(ThreadCommand(ThreadStatus.UPDATE_SETTINGS,
|
|
427
|
+
[self.parent_parameters_path + path, data,
|
|
428
|
+
change])) # send parameters values/limits back to the GUI
|
|
429
|
+
elif change == 'parent':
|
|
430
|
+
pass
|
|
431
|
+
|
|
432
|
+
pass
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
class DAQ_Viewer_TCP_server(DAQ_Viewer_base, TCPServer):
|
|
436
|
+
"""
|
|
437
|
+
================= ==============================
|
|
438
|
+
**Attributes** **Type**
|
|
439
|
+
*command_server* instance of Signal
|
|
440
|
+
*x_axis* 1D numpy array
|
|
441
|
+
*y_axis* 1D numpy array
|
|
442
|
+
*data* double precision float array
|
|
443
|
+
================= ==============================
|
|
444
|
+
|
|
445
|
+
See Also
|
|
446
|
+
--------
|
|
447
|
+
utility_classes.DAQ_TCP_server
|
|
448
|
+
"""
|
|
449
|
+
params_GRABBER = [] # parameters of a client grabber
|
|
450
|
+
command_server = Signal(list)
|
|
451
|
+
|
|
452
|
+
message_list = ["Quit", "Send Data 0D", "Send Data 1D", "Send Data 2D", "Send Data ND", "Status", "Done",
|
|
453
|
+
"Server Closed", "Info",
|
|
454
|
+
"Infos",
|
|
455
|
+
"Info_xml", 'x_axis', 'y_axis']
|
|
456
|
+
socket_types = ["GRABBER"]
|
|
457
|
+
params = comon_parameters + tcp_parameters
|
|
458
|
+
|
|
459
|
+
def __init__(self, parent=None, params_state=None, grabber_type='2D'):
|
|
460
|
+
"""
|
|
461
|
+
|
|
462
|
+
Parameters
|
|
463
|
+
----------
|
|
464
|
+
parent
|
|
465
|
+
params_state
|
|
466
|
+
grabber_type: (str) either '0D', '1D' or '2D'
|
|
467
|
+
"""
|
|
468
|
+
self.client_type = "GRABBER"
|
|
469
|
+
DAQ_Viewer_base.__init__(self, parent, params_state) # initialize base class with common attribute and methods
|
|
470
|
+
TCPServer.__init__(self, self.client_type)
|
|
471
|
+
|
|
472
|
+
self.x_axis = None
|
|
473
|
+
self.y_axis = None
|
|
474
|
+
self.data = None
|
|
475
|
+
self.grabber_type = grabber_type
|
|
476
|
+
self.ind_data = 0
|
|
477
|
+
self.data_mock: DataToExport = None
|
|
478
|
+
|
|
479
|
+
def command_to_from_client(self, command: str):
|
|
480
|
+
"""Process the command"""
|
|
481
|
+
sock = self.find_socket_within_connected_clients(self.client_type)
|
|
482
|
+
if sock is not None: # if client self.client_type is connected then send it the command
|
|
483
|
+
|
|
484
|
+
if command == 'x_axis':
|
|
485
|
+
raise DeprecationWarning(f'The command {command} is deprecated use the data objects')
|
|
486
|
+
elif command == 'y_axis':
|
|
487
|
+
raise DeprecationWarning(f'The command {command} is deprecated use the data objects')
|
|
488
|
+
|
|
489
|
+
else:
|
|
490
|
+
self.send_command(sock, command)
|
|
491
|
+
|
|
492
|
+
else: # else simulate mock data
|
|
493
|
+
if command == "Send Data 0D":
|
|
494
|
+
self.set_0D_Mock_data()
|
|
495
|
+
elif command == "Send Data 1D":
|
|
496
|
+
self.set_1D_Mock_data()
|
|
497
|
+
elif command == "Send Data 2D":
|
|
498
|
+
self.set_2D_Mock_data()
|
|
499
|
+
self.process_cmds('Done')
|
|
500
|
+
|
|
501
|
+
def send_data(self, sock: Socket, data: DataToExport):
|
|
502
|
+
"""
|
|
503
|
+
To match digital and labview, send again a command.
|
|
504
|
+
|
|
505
|
+
=============== ============================== ====================
|
|
506
|
+
**Parameters** **Type** **Description**
|
|
507
|
+
*sock* the socket receipt
|
|
508
|
+
*data* double precision float array the data to be sent
|
|
509
|
+
=============== ============================== ====================
|
|
510
|
+
|
|
511
|
+
See Also
|
|
512
|
+
--------
|
|
513
|
+
send_command, check_send_data
|
|
514
|
+
"""
|
|
515
|
+
self.send_command(sock, 'Done')
|
|
516
|
+
sock.check_sended_with_serializer(data)
|
|
517
|
+
|
|
518
|
+
def read_data(self, sock: Socket) -> DataToExport:
|
|
519
|
+
"""Read data from the socket
|
|
520
|
+
"""
|
|
521
|
+
return DeSerializer(sock).dte_deserialization()
|
|
522
|
+
|
|
523
|
+
def data_ready(self, data: DataToExport):
|
|
524
|
+
"""
|
|
525
|
+
Send the grabbed data signal.
|
|
526
|
+
"""
|
|
527
|
+
self.dte_signal.emit(data)
|
|
528
|
+
|
|
529
|
+
def command_done(self, command_sock):
|
|
530
|
+
try:
|
|
531
|
+
sock = self.find_socket_within_connected_clients(self.client_type)
|
|
532
|
+
if sock is not None: # if client self.client_type is connected then send it the command
|
|
533
|
+
data: DataToExport = self.read_data(sock)
|
|
534
|
+
else:
|
|
535
|
+
data = self.data_mock
|
|
536
|
+
|
|
537
|
+
if command_sock is None:
|
|
538
|
+
self.data_ready(data)
|
|
539
|
+
else:
|
|
540
|
+
self.send_data(command_sock, data) # to be send to a client
|
|
541
|
+
|
|
542
|
+
except Exception as e:
|
|
543
|
+
self.emit_status(ThreadCommand(ThreadStatus.UPDATE_STATUS, str(e)))
|
|
544
|
+
|
|
545
|
+
def commit_settings(self, param):
|
|
546
|
+
|
|
547
|
+
if param.name() in iter_children(self.settings.child(('settings_client')), []):
|
|
548
|
+
grabber_socket: Socket = \
|
|
549
|
+
[client['socket'] for client in self.connected_clients if client['type'] == self.client_type][0]
|
|
550
|
+
grabber_socket.check_sended_with_serializer('set_info')
|
|
551
|
+
|
|
552
|
+
path = get_param_path(param)[2:] # get the path of this param as a list starting at parent 'infos'
|
|
553
|
+
grabber_socket.check_sended_with_serializer(path)
|
|
554
|
+
|
|
555
|
+
# send value
|
|
556
|
+
data = ioxml.parameter_to_xml_string(param)
|
|
557
|
+
grabber_socket.check_sended_with_serializer(data)
|
|
558
|
+
|
|
559
|
+
def ini_detector(self, controller=None):
|
|
560
|
+
"""
|
|
561
|
+
| Initialisation procedure of the detector updating the status dictionary.
|
|
562
|
+
|
|
|
563
|
+
| Init axes from image , here returns only None values (to tricky to di it with the server and not really
|
|
564
|
+
necessary for images anyway)
|
|
565
|
+
|
|
566
|
+
See Also
|
|
567
|
+
--------
|
|
568
|
+
utility_classes.DAQ_TCP_server.init_server, get_xaxis, get_yaxis
|
|
569
|
+
"""
|
|
570
|
+
self.settings.child('infos').addChildren(self.params_GRABBER)
|
|
571
|
+
|
|
572
|
+
self.init_server()
|
|
573
|
+
self.controller = self.serversocket
|
|
574
|
+
# %%%%%%% init axes from image , here returns only None values (to tricky to di it with the server and not really necessary for images anyway)
|
|
575
|
+
self.x_axis = self.get_xaxis()
|
|
576
|
+
self.y_axis = self.get_yaxis()
|
|
577
|
+
|
|
578
|
+
initialized = True
|
|
579
|
+
info = "Server ready"
|
|
580
|
+
return info, initialized
|
|
581
|
+
|
|
582
|
+
def close(self):
|
|
583
|
+
"""
|
|
584
|
+
Should be used to uninitialize hardware.
|
|
585
|
+
|
|
586
|
+
See Also
|
|
587
|
+
--------
|
|
588
|
+
utility_classes.DAQ_TCP_server.close_server
|
|
589
|
+
"""
|
|
590
|
+
self.listening = False
|
|
591
|
+
self.close_server()
|
|
592
|
+
|
|
593
|
+
def get_xaxis(self):
|
|
594
|
+
"""
|
|
595
|
+
Obtain the horizontal axis of the image.
|
|
596
|
+
|
|
597
|
+
Returns
|
|
598
|
+
-------
|
|
599
|
+
1D numpy array
|
|
600
|
+
Contains a vector of integer corresponding to the horizontal camera pixels.
|
|
601
|
+
"""
|
|
602
|
+
pass
|
|
603
|
+
return self.x_axis
|
|
604
|
+
|
|
605
|
+
def get_yaxis(self):
|
|
606
|
+
"""
|
|
607
|
+
Obtain the vertical axis of the image.
|
|
608
|
+
|
|
609
|
+
Returns
|
|
610
|
+
-------
|
|
611
|
+
1D numpy array
|
|
612
|
+
Contains a vector of integer corresponding to the vertical camera pixels.
|
|
613
|
+
"""
|
|
614
|
+
pass
|
|
615
|
+
return self.y_axis
|
|
616
|
+
|
|
617
|
+
def grab_data(self, Naverage=1, **kwargs):
|
|
618
|
+
"""
|
|
619
|
+
Start new acquisition.
|
|
620
|
+
Grabbed indice is used to keep track of the current image in the average.
|
|
621
|
+
|
|
622
|
+
============== ========== ==============================
|
|
623
|
+
**Parameters** **Type** **Description**
|
|
624
|
+
|
|
625
|
+
*Naverage* int Number of images to average
|
|
626
|
+
============== ========== ==============================
|
|
627
|
+
|
|
628
|
+
See Also
|
|
629
|
+
--------
|
|
630
|
+
utility_classes.DAQ_TCP_server.process_cmds
|
|
631
|
+
"""
|
|
632
|
+
try:
|
|
633
|
+
self.ind_grabbed = 0 # to keep track of the current image in the average
|
|
634
|
+
self.Naverage = Naverage
|
|
635
|
+
self.process_cmds("Send Data {:s}".format(self.grabber_type))
|
|
636
|
+
# self.command_server.emit(["process_cmds","Send Data 2D"])
|
|
637
|
+
|
|
638
|
+
except Exception as e:
|
|
639
|
+
self.emit_status(ThreadCommand(ThreadStatus.UPDATE_STATUS, str(e)))
|
|
640
|
+
|
|
641
|
+
def stop(self):
|
|
642
|
+
"""
|
|
643
|
+
not implemented.
|
|
644
|
+
"""
|
|
645
|
+
pass
|
|
646
|
+
return ""
|
|
647
|
+
|
|
648
|
+
def set_0D_Mock_data(self):
|
|
649
|
+
x = np.linspace(0, 99, 100)
|
|
650
|
+
data_tmp = 10 * gauss1D(x, 50, 10, 1) + 1 * np.random.rand((100))
|
|
651
|
+
self.ind_data += 1
|
|
652
|
+
self.data_mock = DataToExport('mocktcp',
|
|
653
|
+
data=[DataRaw('mock',
|
|
654
|
+
data=[np.atleast_1d(np.roll(data_tmp, self.ind_data)[0])])])
|
|
655
|
+
|
|
656
|
+
def set_1D_Mock_data(self):
|
|
657
|
+
x = np.linspace(0, 99, 100)
|
|
658
|
+
data_tmp = 10 * gauss1D(x, 50, 10, 1) + 1 * np.random.rand((100))
|
|
659
|
+
self.ind_data += 1
|
|
660
|
+
self.data_mock = DataToExport('mocktcp', data=[DataRaw('mock', data=[np.roll(data_tmp, self.ind_data)])])
|
|
661
|
+
|
|
662
|
+
def set_2D_Mock_data(self):
|
|
663
|
+
self.x_axis = np.linspace(0, 50, 50, endpoint=False)
|
|
664
|
+
self.y_axis = np.linspace(0, 30, 30, endpoint=False)
|
|
665
|
+
data_tmp = 10 * gauss2D(self.x_axis, 20, 10,
|
|
666
|
+
self.y_axis, 15, 7, 1) + 2 * np.random.rand(len(self.y_axis), len(self.x_axis))
|
|
667
|
+
self.data_mock = DataToExport('mocktcp', data=[DataRaw('mock', data=[data_tmp])])
|
|
668
|
+
|
|
669
|
+
if __name__ == '__main__':
|
|
670
|
+
prog = DAQ_Viewer_TCP_server()
|
|
File without changes
|