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.
Files changed (154) hide show
  1. pymodaq/__init__.py +98 -0
  2. pymodaq/control_modules/__init__.py +1 -0
  3. pymodaq/control_modules/daq_move.py +1238 -0
  4. pymodaq/control_modules/daq_move_ui/__init__.py +0 -0
  5. pymodaq/control_modules/daq_move_ui/factory.py +48 -0
  6. pymodaq/control_modules/daq_move_ui/ui_base.py +359 -0
  7. pymodaq/control_modules/daq_move_ui/uis/__init__.py +0 -0
  8. pymodaq/control_modules/daq_move_ui/uis/binary.py +139 -0
  9. pymodaq/control_modules/daq_move_ui/uis/original.py +120 -0
  10. pymodaq/control_modules/daq_move_ui/uis/relative.py +124 -0
  11. pymodaq/control_modules/daq_move_ui/uis/simple.py +126 -0
  12. pymodaq/control_modules/daq_viewer.py +1517 -0
  13. pymodaq/control_modules/daq_viewer_ui.py +407 -0
  14. pymodaq/control_modules/mocks.py +57 -0
  15. pymodaq/control_modules/move_utility_classes.py +1141 -0
  16. pymodaq/control_modules/thread_commands.py +137 -0
  17. pymodaq/control_modules/ui_utils.py +72 -0
  18. pymodaq/control_modules/utils.py +591 -0
  19. pymodaq/control_modules/viewer_utility_classes.py +670 -0
  20. pymodaq/daq_utils/__init__.py +0 -0
  21. pymodaq/daq_utils/daq_utils.py +6 -0
  22. pymodaq/dashboard.py +2396 -0
  23. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.aliases +3 -0
  24. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.lvlps +3 -0
  25. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.lvproj +32 -0
  26. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.vi +0 -0
  27. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Server_1Dgaussian.vi +0 -0
  28. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Server_2Dgaussian.vi +0 -0
  29. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_read_cmd.vi +0 -0
  30. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_read_float.vi +0 -0
  31. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_read_int.vi +0 -0
  32. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_data.vi +0 -0
  33. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_int.vi +0 -0
  34. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_scalar.vi +0 -0
  35. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_string.vi +0 -0
  36. pymodaq/examples/Labview_TCP_Client/client_state.ctl +0 -0
  37. pymodaq/examples/Labview_TCP_Client/cmd_types.ctl +0 -0
  38. pymodaq/examples/__init__.py +0 -0
  39. pymodaq/examples/function_plotter.py +160 -0
  40. pymodaq/examples/nonlinearscanner.py +126 -0
  41. pymodaq/examples/qt_less_standalone_module.py +165 -0
  42. pymodaq/examples/tcp_client.py +97 -0
  43. pymodaq/extensions/__init__.py +25 -0
  44. pymodaq/extensions/adaptive/__init__.py +2 -0
  45. pymodaq/extensions/adaptive/adaptive_optimization.py +179 -0
  46. pymodaq/extensions/adaptive/loss_function/_1d_loss_functions.py +73 -0
  47. pymodaq/extensions/adaptive/loss_function/_2d_loss_functions.py +73 -0
  48. pymodaq/extensions/adaptive/loss_function/__init__.py +3 -0
  49. pymodaq/extensions/adaptive/loss_function/loss_factory.py +110 -0
  50. pymodaq/extensions/adaptive/utils.py +123 -0
  51. pymodaq/extensions/bayesian/__init__.py +2 -0
  52. pymodaq/extensions/bayesian/acquisition/__init__.py +2 -0
  53. pymodaq/extensions/bayesian/acquisition/acquisition_function_factory.py +80 -0
  54. pymodaq/extensions/bayesian/acquisition/base_acquisition_function.py +105 -0
  55. pymodaq/extensions/bayesian/bayesian_optimization.py +143 -0
  56. pymodaq/extensions/bayesian/utils.py +180 -0
  57. pymodaq/extensions/console.py +73 -0
  58. pymodaq/extensions/daq_logger/__init__.py +1 -0
  59. pymodaq/extensions/daq_logger/abstract.py +52 -0
  60. pymodaq/extensions/daq_logger/daq_logger.py +519 -0
  61. pymodaq/extensions/daq_logger/db/__init__.py +0 -0
  62. pymodaq/extensions/daq_logger/db/db_logger.py +300 -0
  63. pymodaq/extensions/daq_logger/db/db_logger_models.py +100 -0
  64. pymodaq/extensions/daq_logger/h5logging.py +84 -0
  65. pymodaq/extensions/daq_scan.py +1218 -0
  66. pymodaq/extensions/daq_scan_ui.py +241 -0
  67. pymodaq/extensions/data_mixer/__init__.py +0 -0
  68. pymodaq/extensions/data_mixer/daq_0Dviewer_DataMixer.py +97 -0
  69. pymodaq/extensions/data_mixer/data_mixer.py +262 -0
  70. pymodaq/extensions/data_mixer/model.py +108 -0
  71. pymodaq/extensions/data_mixer/models/__init__.py +0 -0
  72. pymodaq/extensions/data_mixer/models/equation_model.py +91 -0
  73. pymodaq/extensions/data_mixer/models/gaussian_fit_model.py +65 -0
  74. pymodaq/extensions/data_mixer/parser.py +53 -0
  75. pymodaq/extensions/data_mixer/utils.py +23 -0
  76. pymodaq/extensions/h5browser.py +9 -0
  77. pymodaq/extensions/optimizers_base/__init__.py +0 -0
  78. pymodaq/extensions/optimizers_base/optimizer.py +1016 -0
  79. pymodaq/extensions/optimizers_base/thread_commands.py +22 -0
  80. pymodaq/extensions/optimizers_base/utils.py +427 -0
  81. pymodaq/extensions/pid/__init__.py +16 -0
  82. pymodaq/extensions/pid/actuator_controller.py +14 -0
  83. pymodaq/extensions/pid/daq_move_PID.py +154 -0
  84. pymodaq/extensions/pid/pid_controller.py +1016 -0
  85. pymodaq/extensions/pid/utils.py +189 -0
  86. pymodaq/extensions/utils.py +111 -0
  87. pymodaq/icon.ico +0 -0
  88. pymodaq/post_treatment/__init__.py +6 -0
  89. pymodaq/post_treatment/load_and_plot.py +352 -0
  90. pymodaq/resources/__init__.py +0 -0
  91. pymodaq/resources/config_template.toml +57 -0
  92. pymodaq/resources/preset_default.xml +1 -0
  93. pymodaq/resources/setup_plugin.py +73 -0
  94. pymodaq/splash.png +0 -0
  95. pymodaq/utils/__init__.py +0 -0
  96. pymodaq/utils/array_manipulation.py +6 -0
  97. pymodaq/utils/calibration_camera.py +180 -0
  98. pymodaq/utils/chrono_timer.py +203 -0
  99. pymodaq/utils/config.py +53 -0
  100. pymodaq/utils/conftests.py +5 -0
  101. pymodaq/utils/daq_utils.py +158 -0
  102. pymodaq/utils/data.py +128 -0
  103. pymodaq/utils/enums.py +6 -0
  104. pymodaq/utils/exceptions.py +38 -0
  105. pymodaq/utils/gui_utils/__init__.py +10 -0
  106. pymodaq/utils/gui_utils/loader_utils.py +75 -0
  107. pymodaq/utils/gui_utils/utils.py +18 -0
  108. pymodaq/utils/gui_utils/widgets/lcd.py +8 -0
  109. pymodaq/utils/h5modules/__init__.py +2 -0
  110. pymodaq/utils/h5modules/module_saving.py +526 -0
  111. pymodaq/utils/leco/__init__.py +25 -0
  112. pymodaq/utils/leco/daq_move_LECODirector.py +217 -0
  113. pymodaq/utils/leco/daq_xDviewer_LECODirector.py +163 -0
  114. pymodaq/utils/leco/director_utils.py +74 -0
  115. pymodaq/utils/leco/leco_director.py +166 -0
  116. pymodaq/utils/leco/pymodaq_listener.py +364 -0
  117. pymodaq/utils/leco/rpc_method_definitions.py +43 -0
  118. pymodaq/utils/leco/utils.py +74 -0
  119. pymodaq/utils/logger.py +6 -0
  120. pymodaq/utils/managers/__init__.py +0 -0
  121. pymodaq/utils/managers/batchscan_manager.py +346 -0
  122. pymodaq/utils/managers/modules_manager.py +589 -0
  123. pymodaq/utils/managers/overshoot_manager.py +242 -0
  124. pymodaq/utils/managers/preset_manager.py +229 -0
  125. pymodaq/utils/managers/preset_manager_utils.py +262 -0
  126. pymodaq/utils/managers/remote_manager.py +484 -0
  127. pymodaq/utils/math_utils.py +6 -0
  128. pymodaq/utils/messenger.py +6 -0
  129. pymodaq/utils/parameter/__init__.py +10 -0
  130. pymodaq/utils/parameter/utils.py +6 -0
  131. pymodaq/utils/scanner/__init__.py +5 -0
  132. pymodaq/utils/scanner/scan_config.py +16 -0
  133. pymodaq/utils/scanner/scan_factory.py +259 -0
  134. pymodaq/utils/scanner/scan_selector.py +477 -0
  135. pymodaq/utils/scanner/scanner.py +324 -0
  136. pymodaq/utils/scanner/scanners/_1d_scanners.py +174 -0
  137. pymodaq/utils/scanner/scanners/_2d_scanners.py +299 -0
  138. pymodaq/utils/scanner/scanners/__init__.py +1 -0
  139. pymodaq/utils/scanner/scanners/sequential.py +224 -0
  140. pymodaq/utils/scanner/scanners/tabular.py +319 -0
  141. pymodaq/utils/scanner/utils.py +110 -0
  142. pymodaq/utils/svg/__init__.py +6 -0
  143. pymodaq/utils/svg/svg_renderer.py +20 -0
  144. pymodaq/utils/svg/svg_view.py +35 -0
  145. pymodaq/utils/svg/svg_viewer2D.py +50 -0
  146. pymodaq/utils/tcp_ip/__init__.py +6 -0
  147. pymodaq/utils/tcp_ip/mysocket.py +12 -0
  148. pymodaq/utils/tcp_ip/serializer.py +13 -0
  149. pymodaq/utils/tcp_ip/tcp_server_client.py +772 -0
  150. pymodaq-5.1.6.dist-info/METADATA +238 -0
  151. pymodaq-5.1.6.dist-info/RECORD +154 -0
  152. pymodaq-5.1.6.dist-info/WHEEL +4 -0
  153. pymodaq-5.1.6.dist-info/entry_points.txt +7 -0
  154. 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
@@ -0,0 +1,6 @@
1
+ from pymodaq_utils import utils as daq_utils
2
+
3
+ from pymodaq_utils.warnings import deprecation_msg
4
+
5
+ deprecation_msg('Importing daq_utils stuff from pymodaq is deprecated in pymodaq>5.0.0,'
6
+ 'please use the pymodaq_utils.utils module')