pymodaq 3.6.13__py3-none-any.whl → 4.0.1__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (233) hide show
  1. pymodaq/__init__.py +13 -6
  2. pymodaq/control_modules/__init__.py +0 -7
  3. pymodaq/control_modules/daq_move.py +965 -2
  4. pymodaq/control_modules/daq_move_ui.py +319 -0
  5. pymodaq/control_modules/daq_viewer.py +1573 -3
  6. pymodaq/control_modules/daq_viewer_ui.py +393 -0
  7. pymodaq/control_modules/mocks.py +51 -0
  8. pymodaq/control_modules/move_utility_classes.py +709 -8
  9. pymodaq/control_modules/utils.py +256 -0
  10. pymodaq/control_modules/viewer_utility_classes.py +663 -6
  11. pymodaq/daq_utils.py +89 -0
  12. pymodaq/dashboard.py +91 -72
  13. pymodaq/examples/custom_app.py +12 -11
  14. pymodaq/examples/custom_viewer.py +10 -10
  15. pymodaq/examples/function_plotter.py +16 -13
  16. pymodaq/examples/nonlinearscanner.py +8 -6
  17. pymodaq/examples/parameter_ex.py +7 -7
  18. pymodaq/examples/preset_MockCamera.xml +1 -0
  19. pymodaq/extensions/__init__.py +16 -0
  20. pymodaq/extensions/console.py +76 -0
  21. pymodaq/{daq_logger.py → extensions/daq_logger.py} +115 -65
  22. pymodaq/extensions/daq_scan.py +1339 -0
  23. pymodaq/extensions/daq_scan_ui.py +240 -0
  24. pymodaq/extensions/h5browser.py +23 -0
  25. pymodaq/{pid → extensions/pid}/__init__.py +4 -2
  26. pymodaq/{pid → extensions/pid}/daq_move_PID.py +2 -2
  27. pymodaq/{pid → extensions/pid}/pid_controller.py +48 -36
  28. pymodaq/{pid → extensions/pid}/utils.py +52 -6
  29. pymodaq/extensions/utils.py +40 -0
  30. pymodaq/post_treatment/__init__.py +6 -0
  31. pymodaq/{daq_analysis → post_treatment/daq_analysis}/daq_analysis_main.py +17 -17
  32. pymodaq/{daq_measurement → post_treatment/daq_measurement}/daq_measurement_main.py +8 -14
  33. pymodaq/post_treatment/load_and_plot.py +219 -0
  34. pymodaq/post_treatment/process_to_scalar.py +263 -0
  35. pymodaq/resources/QtDesigner_Ressources/Icon_Library/run_all.png +0 -0
  36. pymodaq/resources/QtDesigner_Ressources/Icon_Library/stop_all.png +0 -0
  37. pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources.bat +1 -1
  38. pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources.qrc +1 -0
  39. pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources_rc.py +109784 -109173
  40. pymodaq/resources/QtDesigner_Ressources/icons.svg +142 -0
  41. pymodaq/resources/VERSION +1 -1
  42. pymodaq/resources/config_template.toml +32 -13
  43. pymodaq/resources/preset_default.xml +1 -1
  44. pymodaq/{daq_utils → utils}/Tuto innosetup/script_full_setup.iss +1 -1
  45. pymodaq/utils/__init__.py +0 -29
  46. pymodaq/utils/abstract/__init__.py +48 -0
  47. pymodaq/{daq_utils → utils}/abstract/logger.py +7 -3
  48. pymodaq/utils/array_manipulation.py +379 -8
  49. pymodaq/{daq_utils → utils}/calibration_camera.py +6 -6
  50. pymodaq/{daq_utils → utils}/chrono_timer.py +1 -1
  51. pymodaq/utils/config.py +448 -0
  52. pymodaq/utils/conftests.py +5 -0
  53. pymodaq/utils/daq_utils.py +828 -8
  54. pymodaq/utils/data.py +1873 -7
  55. pymodaq/{daq_utils → utils}/db/db_logger/db_logger.py +86 -47
  56. pymodaq/{daq_utils → utils}/db/db_logger/db_logger_models.py +31 -10
  57. pymodaq/{daq_utils → utils}/enums.py +12 -7
  58. pymodaq/utils/exceptions.py +37 -0
  59. pymodaq/utils/factory.py +82 -0
  60. pymodaq/{daq_utils → utils}/gui_utils/__init__.py +1 -1
  61. pymodaq/utils/gui_utils/custom_app.py +129 -0
  62. pymodaq/utils/gui_utils/file_io.py +66 -0
  63. pymodaq/{daq_utils → utils}/gui_utils/layout.py +2 -2
  64. pymodaq/{daq_utils → utils}/gui_utils/utils.py +13 -3
  65. pymodaq/{daq_utils → utils}/gui_utils/widgets/__init__.py +2 -2
  66. pymodaq/utils/gui_utils/widgets/label.py +24 -0
  67. pymodaq/{daq_utils → utils}/gui_utils/widgets/lcd.py +12 -7
  68. pymodaq/{daq_utils → utils}/gui_utils/widgets/push.py +66 -2
  69. pymodaq/{daq_utils → utils}/gui_utils/widgets/qled.py +6 -4
  70. pymodaq/utils/gui_utils/widgets/spinbox.py +24 -0
  71. pymodaq/{daq_utils → utils}/gui_utils/widgets/table.py +2 -2
  72. pymodaq/utils/h5modules/__init__.py +1 -0
  73. pymodaq/{daq_utils/h5backend.py → utils/h5modules/backends.py} +200 -112
  74. pymodaq/utils/h5modules/browsing.py +683 -0
  75. pymodaq/utils/h5modules/data_saving.py +839 -0
  76. pymodaq/utils/h5modules/h5logging.py +110 -0
  77. pymodaq/utils/h5modules/module_saving.py +350 -0
  78. pymodaq/utils/h5modules/saving.py +914 -0
  79. pymodaq/utils/h5modules/utils.py +85 -0
  80. pymodaq/utils/logger.py +64 -6
  81. pymodaq/utils/managers/action_manager.py +460 -0
  82. pymodaq/{daq_utils → utils}/managers/batchscan_manager.py +144 -112
  83. pymodaq/{daq_utils → utils}/managers/modules_manager.py +188 -114
  84. pymodaq/{daq_utils → utils}/managers/overshoot_manager.py +3 -3
  85. pymodaq/utils/managers/parameter_manager.py +110 -0
  86. pymodaq/{daq_utils → utils}/managers/preset_manager.py +17 -13
  87. pymodaq/{daq_utils → utils}/managers/preset_manager_utils.py +8 -7
  88. pymodaq/{daq_utils → utils}/managers/remote_manager.py +7 -6
  89. pymodaq/{daq_utils → utils}/managers/roi_manager.py +148 -57
  90. pymodaq/utils/math_utils.py +546 -10
  91. pymodaq/{daq_utils → utils}/messenger.py +5 -1
  92. pymodaq/utils/parameter/__init__.py +2 -15
  93. pymodaq/{daq_utils → utils}/parameter/ioxml.py +12 -6
  94. pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/__init__.py +1 -3
  95. pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/filedir.py +1 -1
  96. pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/itemselect.py +3 -0
  97. pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/led.py +1 -1
  98. pymodaq/utils/parameter/pymodaq_ptypes/pixmap.py +161 -0
  99. pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/slide.py +1 -1
  100. pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/table.py +1 -1
  101. pymodaq/utils/parameter/utils.py +206 -11
  102. pymodaq/utils/plotting/data_viewers/__init__.py +6 -0
  103. pymodaq/utils/plotting/data_viewers/viewer.py +393 -0
  104. pymodaq/utils/plotting/data_viewers/viewer0D.py +251 -0
  105. pymodaq/utils/plotting/data_viewers/viewer1D.py +574 -0
  106. pymodaq/{daq_utils → utils}/plotting/data_viewers/viewer1Dbasic.py +8 -3
  107. pymodaq/{daq_utils → utils}/plotting/data_viewers/viewer2D.py +292 -357
  108. pymodaq/{daq_utils → utils}/plotting/data_viewers/viewer2D_basic.py +58 -75
  109. pymodaq/utils/plotting/data_viewers/viewerND.py +738 -0
  110. pymodaq/{daq_utils → utils}/plotting/gant_chart.py +2 -2
  111. pymodaq/{daq_utils → utils}/plotting/items/axis_scaled.py +4 -2
  112. pymodaq/{daq_utils → utils}/plotting/items/image.py +8 -6
  113. pymodaq/utils/plotting/navigator.py +355 -0
  114. pymodaq/utils/plotting/scan_selector.py +480 -0
  115. pymodaq/utils/plotting/utils/axes_viewer.py +88 -0
  116. pymodaq/utils/plotting/utils/filter.py +538 -0
  117. pymodaq/utils/plotting/utils/lineout.py +224 -0
  118. pymodaq/{daq_utils → utils}/plotting/utils/plot_utils.py +196 -84
  119. pymodaq/{daq_utils → utils}/plotting/utils/signalND.py +21 -13
  120. pymodaq/utils/plotting/widgets.py +76 -0
  121. pymodaq/utils/scanner/__init__.py +10 -0
  122. pymodaq/utils/scanner/scan_factory.py +204 -0
  123. pymodaq/utils/scanner/scanner.py +271 -0
  124. pymodaq/utils/scanner/scanners/_1d_scanners.py +117 -0
  125. pymodaq/utils/scanner/scanners/_2d_scanners.py +293 -0
  126. pymodaq/utils/scanner/scanners/sequential.py +192 -0
  127. pymodaq/utils/scanner/scanners/tabular.py +294 -0
  128. pymodaq/utils/scanner/utils.py +83 -0
  129. pymodaq/utils/slicing.py +47 -0
  130. pymodaq/utils/svg/__init__.py +6 -0
  131. pymodaq/utils/svg/svg_renderer.py +20 -0
  132. pymodaq/utils/svg/svg_view.py +35 -0
  133. pymodaq/utils/svg/svg_viewer2D.py +51 -0
  134. pymodaq/{daq_utils → utils}/tcp_server_client.py +36 -37
  135. pymodaq/{daq_utils → utils}/tree_layout/tree_layout_main.py +50 -35
  136. pymodaq/utils/units.py +216 -0
  137. pymodaq-4.0.1.dist-info/METADATA +159 -0
  138. {pymodaq-3.6.13.dist-info → pymodaq-4.0.1.dist-info}/RECORD +167 -170
  139. {pymodaq-3.6.13.dist-info → pymodaq-4.0.1.dist-info}/WHEEL +1 -2
  140. pymodaq-4.0.1.dist-info/entry_points.txt +8 -0
  141. pymodaq/daq_move/daq_move_gui.py +0 -279
  142. pymodaq/daq_move/daq_move_gui.ui +0 -534
  143. pymodaq/daq_move/daq_move_main.py +0 -1042
  144. pymodaq/daq_move/process_from_QtDesigner_DAQ_Move_GUI.bat +0 -2
  145. pymodaq/daq_move/utility_classes.py +0 -686
  146. pymodaq/daq_scan.py +0 -2160
  147. pymodaq/daq_utils/array_manipulation.py +0 -386
  148. pymodaq/daq_utils/config.py +0 -273
  149. pymodaq/daq_utils/conftests.py +0 -7
  150. pymodaq/daq_utils/custom_parameter_tree.py +0 -9
  151. pymodaq/daq_utils/daq_enums.py +0 -133
  152. pymodaq/daq_utils/daq_utils.py +0 -1402
  153. pymodaq/daq_utils/exceptions.py +0 -71
  154. pymodaq/daq_utils/gui_utils/custom_app.py +0 -103
  155. pymodaq/daq_utils/gui_utils/file_io.py +0 -75
  156. pymodaq/daq_utils/gui_utils/widgets/spinbox.py +0 -9
  157. pymodaq/daq_utils/h5exporter_hyperspy.py +0 -115
  158. pymodaq/daq_utils/h5exporters.py +0 -242
  159. pymodaq/daq_utils/h5modules.py +0 -1559
  160. pymodaq/daq_utils/h5utils.py +0 -241
  161. pymodaq/daq_utils/managers/action_manager.py +0 -236
  162. pymodaq/daq_utils/managers/parameter_manager.py +0 -57
  163. pymodaq/daq_utils/math_utils.py +0 -705
  164. pymodaq/daq_utils/parameter/__init__.py +0 -1
  165. pymodaq/daq_utils/parameter/oldpymodaq_ptypes.py +0 -1626
  166. pymodaq/daq_utils/parameter/pymodaq_ptypes/pixmap.py +0 -85
  167. pymodaq/daq_utils/parameter/utils.py +0 -136
  168. pymodaq/daq_utils/plotting/data_viewers/__init__.py +0 -0
  169. pymodaq/daq_utils/plotting/data_viewers/process_from_QtDesigner_0DViewer_GUI.bat +0 -2
  170. pymodaq/daq_utils/plotting/data_viewers/viewer0D.py +0 -204
  171. pymodaq/daq_utils/plotting/data_viewers/viewer0D_GUI.py +0 -89
  172. pymodaq/daq_utils/plotting/data_viewers/viewer0D_GUI.ui +0 -131
  173. pymodaq/daq_utils/plotting/data_viewers/viewer1D.py +0 -781
  174. pymodaq/daq_utils/plotting/data_viewers/viewerND.py +0 -894
  175. pymodaq/daq_utils/plotting/data_viewers/viewerbase.py +0 -64
  176. pymodaq/daq_utils/plotting/items/__init__.py +0 -0
  177. pymodaq/daq_utils/plotting/navigator.py +0 -500
  178. pymodaq/daq_utils/plotting/scan_selector.py +0 -289
  179. pymodaq/daq_utils/plotting/utils/__init__.py +0 -0
  180. pymodaq/daq_utils/plotting/utils/filter.py +0 -236
  181. pymodaq/daq_utils/plotting/viewer0D/__init__.py +0 -0
  182. pymodaq/daq_utils/plotting/viewer0D/viewer0D_main.py +0 -4
  183. pymodaq/daq_utils/plotting/viewer1D/__init__.py +0 -0
  184. pymodaq/daq_utils/plotting/viewer1D/viewer1D_main.py +0 -4
  185. pymodaq/daq_utils/plotting/viewer1D/viewer1Dbasic.py +0 -4
  186. pymodaq/daq_utils/plotting/viewer2D/viewer_2D_basic.py +0 -4
  187. pymodaq/daq_utils/plotting/viewer2D/viewer_2D_main.py +0 -4
  188. pymodaq/daq_utils/plotting/viewerND/__init__.py +0 -0
  189. pymodaq/daq_utils/plotting/viewerND/viewerND_main.py +0 -4
  190. pymodaq/daq_utils/scanner.py +0 -1289
  191. pymodaq/daq_utils/tree_layout/__init__.py +0 -0
  192. pymodaq/daq_viewer/__init__.py +0 -0
  193. pymodaq/daq_viewer/daq_gui_settings.py +0 -237
  194. pymodaq/daq_viewer/daq_gui_settings.ui +0 -441
  195. pymodaq/daq_viewer/daq_viewer_main.py +0 -2225
  196. pymodaq/daq_viewer/process_from_QtDesigner_DAQ_GUI_settings.bat +0 -2
  197. pymodaq/daq_viewer/utility_classes.py +0 -673
  198. pymodaq/examples/logger_image/__init__.py +0 -0
  199. pymodaq/examples/logger_image/logger_displayer.py +0 -121
  200. pymodaq/examples/logger_image/setup.svg +0 -3119
  201. pymodaq/examples/logger_image/setup_svg.py +0 -114
  202. pymodaq/h5browser.py +0 -39
  203. pymodaq/utils/scanner.py +0 -15
  204. pymodaq-3.6.13.dist-info/METADATA +0 -39
  205. pymodaq-3.6.13.dist-info/entry_points.txt +0 -8
  206. pymodaq-3.6.13.dist-info/top_level.txt +0 -1
  207. /pymodaq/{daq_analysis → post_treatment/daq_analysis}/__init__.py +0 -0
  208. /pymodaq/{daq_measurement → post_treatment/daq_measurement}/__init__.py +0 -0
  209. /pymodaq/{daq_measurement → post_treatment/daq_measurement}/daq_measurement_GUI.py +0 -0
  210. /pymodaq/{daq_measurement → post_treatment/daq_measurement}/daq_measurement_GUI.ui +0 -0
  211. /pymodaq/{daq_measurement → post_treatment/daq_measurement}/process_from_QtDesigner_DAQ_Measurement_GUI.bat +0 -0
  212. /pymodaq/{daq_utils → utils}/Tuto innosetup/Tuto innosetup.odt +0 -0
  213. /pymodaq/{daq_utils → utils}/Tuto innosetup/Tuto innosetup.pdf +0 -0
  214. /pymodaq/{daq_move → utils/db}/__init__.py +0 -0
  215. /pymodaq/{daq_utils → utils/db/db_logger}/__init__.py +0 -0
  216. /pymodaq/{daq_utils → utils}/gui_utils/dock.py +0 -0
  217. /pymodaq/{daq_utils → utils}/gui_utils/list_picker.py +0 -0
  218. /pymodaq/{daq_utils/abstract → utils/managers}/__init__.py +0 -0
  219. /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/bool.py +0 -0
  220. /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/date.py +0 -0
  221. /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/list.py +0 -0
  222. /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/numeric.py +0 -0
  223. /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/tableview.py +0 -0
  224. /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/text.py +0 -0
  225. /pymodaq/{daq_utils/db → utils/plotting}/__init__.py +0 -0
  226. /pymodaq/{daq_utils → utils}/plotting/image_viewer.py +0 -0
  227. /pymodaq/{daq_utils/db/db_logger → utils/plotting/items}/__init__.py +0 -0
  228. /pymodaq/{daq_utils → utils}/plotting/items/crosshair.py +0 -0
  229. /pymodaq/{daq_utils/managers → utils/plotting/utils}/__init__.py +0 -0
  230. /pymodaq/{daq_utils → utils}/qvariant.py +0 -0
  231. /pymodaq/{daq_utils/plotting/viewer2D → utils/scanner/scanners}/__init__.py +0 -0
  232. /pymodaq/{daq_utils/plotting → utils/tree_layout}/__init__.py +0 -0
  233. {pymodaq-3.6.13.dist-info → pymodaq-4.0.1.dist-info/licenses}/LICENSE +0 -0
@@ -1,7 +1,664 @@
1
- # -*- coding: utf-8 -*-
2
- """
3
- Created the 21/10/2022
1
+ from qtpy import QtWidgets
2
+ from qtpy.QtCore import QObject, Slot, Signal
4
3
 
5
- @author: Sebastien Weber
6
- """
7
- from pymodaq.daq_viewer.utility_classes import DAQ_Viewer_base, comon_parameters, main, DAQ_Viewer_TCP_server
4
+ from pymodaq.utils.parameter import ioxml
5
+ from pymodaq.utils.parameter.utils import get_param_path, get_param_from_name, iter_children
6
+ from pyqtgraph.parametertree import Parameter
7
+ from easydict import EasyDict as edict
8
+
9
+ import numpy as np
10
+ from pymodaq.utils.math_utils import gauss1D, gauss2D
11
+ from pymodaq.utils.daq_utils import ThreadCommand, getLineInfo
12
+ from pymodaq.utils.config import Config, get_set_local_dir
13
+ #from pymodaq.utils.scanner import ScanParameters
14
+ from pymodaq.utils.tcp_server_client import TCPServer, tcp_parameters
15
+
16
+ comon_parameters = [{'title': 'Controller Status:', 'name': 'controller_status', 'type': 'list', 'value': 'Master',
17
+ 'limits': ['Master', 'Slave']}, ]
18
+
19
+ local_path = get_set_local_dir()
20
+ # look for eventual calibration files
21
+ calibs = ['None']
22
+ if local_path.joinpath('camera_calibrations').is_dir():
23
+ for ind_file, file in enumerate(local_path.joinpath('camera_calibrations').iterdir()):
24
+ if 'xml' in file.suffix:
25
+ calibs.append(file.stem)
26
+
27
+
28
+ config = Config()
29
+
30
+ params = [
31
+ {'title': 'Main Settings:', 'name': 'main_settings', 'expanded': False, 'type': 'group', 'children': [
32
+ {'title': 'DAQ type:', 'name': 'DAQ_type', 'type': 'list', 'limits': ['DAQ0D', 'DAQ1D', 'DAQ2D', 'DAQND'],
33
+ 'readonly': True},
34
+ {'title': 'Detector type:', 'name': 'detector_type', 'type': 'str', 'value': '', 'readonly': True},
35
+ {'title': 'Detector Name:', 'name': 'module_name', 'type': 'str', 'value': '', 'readonly': True},
36
+ {'title': 'Nviewers:', 'name': 'Nviewers', 'type': 'int', 'value': 1, 'min': 1, 'default': 1, 'readonly': True},
37
+ {'title': 'Controller ID:', 'name': 'controller_ID', 'type': 'int', 'value': 0, 'default': 0, 'readonly': False},
38
+ {'title': 'Show data and process:', 'name': 'show_data', 'type': 'bool', 'value': True, },
39
+ {'title': 'Refresh time (ms):', 'name': 'refresh_time', 'type': 'float', 'value': 50., 'min': 0.},
40
+ {'title': 'Naverage', 'name': 'Naverage', 'type': 'int', 'default': 1, 'value': 1, 'min': 1},
41
+ {'title': 'Show averaging:', 'name': 'show_averaging', 'type': 'bool', 'default': False, 'value': False},
42
+ {'title': 'Live averaging:', 'name': 'live_averaging', 'type': 'bool', 'default': False, 'value': False},
43
+ {'title': 'N Live aver.:', 'name': 'N_live_averaging', 'type': 'int', 'default': 0, 'value': 0,
44
+ 'visible': False},
45
+ {'title': 'Wait time (ms):', 'name': 'wait_time', 'type': 'int', 'default': 0, 'value': 00, 'min': 0},
46
+ {'title': 'Continuous saving:', 'name': 'continuous_saving_opt', 'type': 'bool', 'default': False,
47
+ 'value': False},
48
+ {'title': 'TCP/IP options:', 'name': 'tcpip', 'type': 'group', 'visible': True, 'expanded': False, 'children': [
49
+ {'title': 'Connect to server:', 'name': 'connect_server', 'type': 'bool_push', 'label': 'Connect',
50
+ 'value': False},
51
+ {'title': 'Connected?:', 'name': 'tcp_connected', 'type': 'led', 'value': False},
52
+ {'title': 'IP address:', 'name': 'ip_address', 'type': 'str',
53
+ 'value': config('network', 'tcp-server', 'ip')},
54
+ {'title': 'Port:', 'name': 'port', 'type': 'int', 'value': config('network', 'tcp-server', 'port')},
55
+ ]},
56
+ {'title': 'Overshoot options:', 'name': 'overshoot', 'type': 'group', 'visible': True, 'expanded': False,
57
+ 'children': [
58
+ {'title': 'Overshoot:', 'name': 'stop_overshoot', 'type': 'bool', 'value': False},
59
+ {'title': 'Overshoot value:', 'name': 'overshoot_value', 'type': 'float', 'value': 0}]},
60
+ {'title': 'Axis options:', 'name': 'axes', 'type': 'group', 'visible': False, 'expanded': False, 'children': [
61
+ {'title': 'Use calibration?:', 'name': 'use_calib', 'type': 'list', 'limits': calibs},
62
+ {'title': 'X axis:', 'name': 'xaxis', 'type': 'group', 'children': [
63
+ {'title': 'Label:', 'name': 'xlabel', 'type': 'str', 'value': "x axis"},
64
+ {'title': 'Units:', 'name': 'xunits', 'type': 'str', 'value': "pxls"},
65
+ {'title': 'Offset:', 'name': 'xoffset', 'type': 'float', 'default': 0., 'value': 0.},
66
+ {'title': 'Scaling', 'name': 'xscaling', 'type': 'float', 'default': 1., 'value': 1.},
67
+ ]},
68
+ {'title': 'Y axis:', 'name': 'yaxis', 'type': 'group', 'children': [
69
+ {'title': 'Label:', 'name': 'ylabel', 'type': 'str', 'value': "y axis"},
70
+ {'title': 'Units:', 'name': 'yunits', 'type': 'str', 'value': "pxls"},
71
+ {'title': 'Offset:', 'name': 'yoffset', 'type': 'float', 'default': 0., 'value': 0.},
72
+ {'title': 'Scaling', 'name': 'yscaling', 'type': 'float', 'default': 1., 'value': 1.},
73
+ ]},
74
+ ]},
75
+
76
+ ]},
77
+ {'title': 'Detector Settings', 'name': 'detector_settings', 'type': 'group', 'children': []}
78
+ ]
79
+
80
+
81
+ def main(plugin_file=None, init=True):
82
+ """
83
+ this method start a DAQ_Viewer object with this defined plugin as detector
84
+ Returns
85
+ -------
86
+ """
87
+ import sys
88
+ from qtpy import QtWidgets
89
+ from pymodaq.utils.gui_utils import DockArea
90
+ from pymodaq.control_modules.daq_viewer import DAQ_Viewer
91
+ from pathlib import Path
92
+
93
+ app = QtWidgets.QApplication(sys.argv)
94
+ if config('style', 'darkstyle'):
95
+ import qdarkstyle
96
+ app.setStyleSheet(qdarkstyle.load_stylesheet())
97
+
98
+ win = QtWidgets.QMainWindow()
99
+ area = DockArea()
100
+ win.setCentralWidget(area)
101
+ win.resize(1000, 500)
102
+ win.setWindowTitle('PyMoDAQ Viewer')
103
+ if plugin_file is None:
104
+ detector = 'Mock'
105
+ det_type = f'DAQ0D'
106
+ else:
107
+ detector = Path(plugin_file).stem[13:]
108
+ det_type = f'DAQ{Path(plugin_file).stem[4:6].upper()}'
109
+ prog = DAQ_Viewer(area, title="Testing")
110
+ win.show()
111
+ prog.daq_type = det_type
112
+ prog.detector = detector
113
+ if init:
114
+ prog.init_det()
115
+
116
+ sys.exit(app.exec_())
117
+
118
+
119
+ class DAQ_Viewer_base(QObject):
120
+ """
121
+ ===================== ===================================
122
+ **Attributes** **Type**
123
+ *hardware_averaging* boolean
124
+ *data_grabed_signal* instance of Signal
125
+ *params* list
126
+ *settings* instance of pyqtgraph Parameter
127
+ *parent* ???
128
+ *status* dictionnary
129
+ ===================== ===================================
130
+
131
+ See Also
132
+ --------
133
+ send_param_status
134
+ """
135
+ hardware_averaging = False
136
+ live_mode_available = False
137
+ data_grabed_signal = Signal(list)
138
+ data_grabed_signal_temp = Signal(list)
139
+
140
+ params = []
141
+
142
+ def __init__(self, parent=None, params_state=None):
143
+ QObject.__init__(self)
144
+ self.parent_parameters_path = [] # this is to be added in the send_param_status to take into account when the current class instance parameter list is a child of some other class
145
+ self.settings = Parameter.create(name='Settings', type='group', children=self.params)
146
+ if params_state is not None:
147
+ if isinstance(params_state, dict):
148
+ self.settings.restoreState(params_state)
149
+ elif isinstance(params_state, Parameter):
150
+ self.settings.restoreState(params_state.saveState())
151
+
152
+ if '0D' in str(self.__class__):
153
+ self.plugin_type = '0D'
154
+ elif '1D' in str(self.__class__):
155
+ self.plugin_type = '1D'
156
+ else:
157
+ self.plugin_type = '2D'
158
+
159
+ self.settings.sigTreeStateChanged.connect(self.send_param_status)
160
+
161
+ self.parent = parent
162
+ self.status = edict(info="", controller=None, initialized=False)
163
+ self.scan_parameters = None
164
+
165
+ self.x_axis = None
166
+ self.y_axis = None
167
+
168
+ self.ini_attributes()
169
+
170
+ def ini_attributes(self):
171
+ """
172
+ To be reimplemented in subclass
173
+ """
174
+ pass
175
+
176
+ def ini_detector_init(self, old_controller=None, new_controller=None):
177
+ """Manage the Master/Slave controller issue
178
+
179
+ First initialize the status dictionnary
180
+ Then check whether this stage is controlled by a multiaxe controller (to be defined for each plugin)
181
+ if it is a multiaxes controller then:
182
+ * if it is Master: init the controller here
183
+ * if it is Slave: use an already initialized controller (defined in the preset of the dashboard)
184
+
185
+ Parameters
186
+ ----------
187
+ old_controller: object
188
+ The particular object that allow the communication with the hardware, in general a python wrapper around the
189
+ hardware library. In case of Slave this one comes from a previously initialized plugin
190
+ new_controller: object
191
+ The particular object that allow the communication with the hardware, in general a python wrapper around the
192
+ hardware library. In case of Master it is the new instance of your plugin controller
193
+ """
194
+ self.status.update(edict(info="", controller=None, initialized=False))
195
+ if self.settings.child('controller_status').value() == "Slave":
196
+ if old_controller is None:
197
+ raise Exception('no controller has been defined externally while this axe is a slave one')
198
+ else:
199
+ controller = old_controller
200
+ else: # Master stage
201
+ controller = new_controller
202
+ self.controller = controller
203
+ return controller
204
+
205
+ def ini_detector(self, controller=None):
206
+ """
207
+ Mandatory
208
+ To be reimplemented in subclass
209
+ """
210
+ raise NotImplemented
211
+
212
+ def close(self):
213
+ """
214
+ Mandatory
215
+ To be reimplemented in subclass
216
+ """
217
+ raise NotImplemented
218
+
219
+ def grab_data(self, Naverage=1, **kwargs):
220
+ """
221
+ Mandatory
222
+ To be reimplemented in subclass
223
+ """
224
+ raise NotImplemented
225
+
226
+ def stop(self):
227
+ """
228
+ Mandatory
229
+ To be reimplemented in subclass
230
+ """
231
+ raise NotImplemented
232
+
233
+ def commit_settings(self, param):
234
+ """
235
+ To be reimplemented in subclass
236
+ """
237
+ pass
238
+
239
+ def update_com(self):
240
+ """
241
+ If some communications settings have to be re init
242
+ To be reimplemented in subclass
243
+ -------
244
+
245
+ """
246
+ pass
247
+
248
+ def get_axis(self):
249
+ if self.plugin_type == '1D' or self.plugin_type == '2D':
250
+ self.emit_x_axis()
251
+
252
+ if self.plugin_type == '2D':
253
+ self.emit_y_axis()
254
+
255
+ def emit_status(self, status):
256
+ """
257
+ Emit the status signal from the given status.
258
+
259
+ =============== ============ =====================================
260
+ **Parameters** **Type** **Description**
261
+ *status* the status information to transmit
262
+ =============== ============ =====================================
263
+ """
264
+ if self.parent is not None:
265
+ self.parent.status_sig.emit(status)
266
+ QtWidgets.QApplication.processEvents()
267
+ else:
268
+ print(*status)
269
+
270
+ def update_scanner(self, scan_parameters):
271
+ #todo check this because ScanParameters has been removed
272
+ self.scan_parameters = scan_parameters
273
+
274
+ @Slot(edict)
275
+ def update_settings(self, settings_parameter_dict):
276
+ """
277
+ Update the settings tree from settings_parameter_dict.
278
+ Finally do a commit to activate changes.
279
+
280
+ ========================== ============= =====================================================
281
+ **Parameters** **Type** **Description**
282
+ *settings_parameter_dict* dictionnnary a dictionnary listing path and associated parameter
283
+ ========================== ============= =====================================================
284
+
285
+ See Also
286
+ --------
287
+ send_param_status, commit_settings
288
+ """
289
+ # settings_parameter_dict=edict(path=path,param=param)
290
+ try:
291
+ path = settings_parameter_dict['path']
292
+ param = settings_parameter_dict['param']
293
+ change = settings_parameter_dict['change']
294
+ try:
295
+ self.settings.sigTreeStateChanged.disconnect(self.send_param_status)
296
+ except Exception:
297
+ pass
298
+ if change == 'value':
299
+ self.settings.child(*path[1:]).setValue(param.value()) # blocks signal back to main UI
300
+ elif change == 'childAdded':
301
+ child = Parameter.create(name='tmp')
302
+ child.restoreState(param.saveState())
303
+ self.settings.child(*path[1:]).addChild(child) # blocks signal back to main UI
304
+ param = child
305
+
306
+ elif change == 'parent':
307
+ children = get_param_from_name(self.settings, param.name())
308
+
309
+ if children is not None:
310
+ path = get_param_path(children)
311
+ self.settings.child(*path[1:-1]).removeChild(children)
312
+
313
+ self.settings.sigTreeStateChanged.connect(self.send_param_status)
314
+
315
+ self.commit_settings(param)
316
+ except Exception as e:
317
+ self.emit_status(ThreadCommand("Update_Status", [str(e), 'log']))
318
+
319
+
320
+
321
+ def send_param_status(self, param, changes):
322
+ """
323
+ Check for changes in the given (parameter,change,information) tuple list.
324
+ In case of value changed, send the 'update_settings' ThreadCommand with concerned path,data and change as attribute.
325
+
326
+ =============== ============================================ ============================
327
+ **Parameters** **Type** **Description**
328
+ *param* instance of pyqtgraph parameter The parameter to check
329
+ *changes* (parameter,change,information) tuple list The changes list to course
330
+ =============== ============================================ ============================
331
+
332
+ See Also
333
+ --------
334
+ daq_utils.ThreadCommand
335
+ """
336
+ for param, change, data in changes:
337
+ path = self.settings.childPath(param)
338
+ if change == 'childAdded':
339
+ # first create a "copy" of the actual parameter and send this "copy", to be restored in the main UI
340
+ self.emit_status(ThreadCommand('update_settings',
341
+ [self.parent_parameters_path + path, [data[0].saveState(), data[1]],
342
+ 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
343
+
344
+ elif change == 'value' or change == 'limits' or change == 'options':
345
+ self.emit_status(ThreadCommand('update_settings', [self.parent_parameters_path + path, data,
346
+ change])) # send parameters values/limits back to the GUI
347
+ elif change == 'parent':
348
+ pass
349
+
350
+ pass
351
+
352
+ def emit_x_axis(self, x_axis=None):
353
+ """
354
+ Convenience function
355
+ Emit the thread command "x_axis" with x_axis as an attribute.
356
+
357
+ See Also
358
+ --------
359
+ daq_utils.ThreadCommand
360
+ """
361
+ if x_axis is None:
362
+ x_axis = self.x_axis
363
+ self.emit_status(ThreadCommand("x_axis", [x_axis]))
364
+
365
+ def emit_y_axis(self):
366
+ """
367
+ Emit the thread command "y_axis" with y_axis as an attribute.
368
+
369
+ See Also
370
+ --------
371
+ daq_utils.ThreadCommand
372
+ """
373
+ self.emit_status(ThreadCommand("y_axis", [self.y_axis]))
374
+
375
+
376
+ class DAQ_Viewer_TCP_server(DAQ_Viewer_base, TCPServer):
377
+ """
378
+ ================= ==============================
379
+ **Attributes** **Type**
380
+ *command_server* instance of Signal
381
+ *x_axis* 1D numpy array
382
+ *y_axis* 1D numpy array
383
+ *data* double precision float array
384
+ ================= ==============================
385
+
386
+ See Also
387
+ --------
388
+ utility_classes.DAQ_TCP_server
389
+ """
390
+ params_GRABBER = [] # parameters of a client grabber
391
+ command_server = Signal(list)
392
+
393
+ message_list = ["Quit", "Send Data 0D", "Send Data 1D", "Send Data 2D", "Send Data ND", "Status", "Done",
394
+ "Server Closed", "Info",
395
+ "Infos",
396
+ "Info_xml", 'x_axis', 'y_axis']
397
+ socket_types = ["GRABBER"]
398
+ params = comon_parameters + tcp_parameters
399
+
400
+ def __init__(self, parent=None, params_state=None, grabber_type='2D'):
401
+ """
402
+
403
+ Parameters
404
+ ----------
405
+ parent
406
+ params_state
407
+ grabber_type: (str) either '0D', '1D' or '2D'
408
+ """
409
+ self.client_type = "GRABBER"
410
+ DAQ_Viewer_base.__init__(self, parent, params_state) # initialize base class with commom attribute and methods
411
+ TCPServer.__init__(self, self.client_type)
412
+
413
+ self.x_axis = None
414
+ self.y_axis = None
415
+ self.data = None
416
+ self.grabber_type = grabber_type
417
+ self.ind_data = 0
418
+ self.data_mock = None
419
+
420
+ def command_to_from_client(self, command):
421
+ sock = self.find_socket_within_connected_clients(self.client_type)
422
+ if sock is not None: # if client self.client_type is connected then send it the command
423
+
424
+ if command == 'x_axis':
425
+ x_axis = dict(data=sock.get_array())
426
+ x_axis['label'] = sock.get_string()
427
+ x_axis['units'] = sock.get_string()
428
+ self.x_axis = x_axis.copy()
429
+ self.emit_x_axis()
430
+ elif command == 'y_axis':
431
+ y_axis = dict(data=sock.get_array())
432
+ y_axis['label'] = sock.get_string()
433
+ y_axis['units'] = sock.get_string()
434
+ self.y_axis = y_axis.copy()
435
+ self.emit_y_axis()
436
+
437
+ else:
438
+ self.send_command(sock, command)
439
+
440
+ else: # else simulate mock data
441
+ if command == "Send Data 0D":
442
+ self.set_1D_Mock_data()
443
+ self.data_mock = np.array([self.data_mock[0]])
444
+ elif command == "Send Data 1D":
445
+ self.set_1D_Mock_data()
446
+ data = self.data_mock
447
+ elif command == "Send Data 2D":
448
+ self.set_2D_Mock_data()
449
+ data = self.data_mock
450
+ self.process_cmds('Done')
451
+
452
+ def send_data(self, sock, data):
453
+ """
454
+ To match digital and labview, send again a command.
455
+
456
+ =============== ============================== ====================
457
+ **Parameters** **Type** **Description**
458
+ *sock* the socket receipt
459
+ *data* double precision float array the data to be sent
460
+ =============== ============================== ====================
461
+
462
+ See Also
463
+ --------
464
+ send_command, check_send_data
465
+ """
466
+ self.send_command(sock, 'Done')
467
+
468
+ sock.send_array(data)
469
+ # if len(data.shape) == 0:
470
+ # Nrow = 1
471
+ # Ncol = 0
472
+ # elif len(data.shape) == 1:
473
+ # Nrow = data.shape[0]
474
+ # Ncol = 0
475
+ # elif len(data.shape) == 2:
476
+ # Nrow = data.shape[0]
477
+ # Ncol = data.shape[1]
478
+ # data_bytes = data.tobytes()
479
+ # check_sended(sock, np.array([len(data_bytes)],
480
+ # dtype='>i4').tobytes()) # first send length of data after reshaping as 1D bytes array
481
+ # check_sended(sock, np.array([Nrow], dtype='>i4').tobytes()) # then send dimension of lines
482
+ # check_sended(sock, np.array([Ncol], dtype='>i4').tobytes()) # then send dimensions of columns
483
+ #
484
+ # check_sended(sock, data_bytes) # then send data
485
+
486
+ def read_data(self, sock):
487
+ """
488
+ Read the unsigned 32bits int data contained in the given socket in five steps :
489
+ * get back the message
490
+ * get the list length
491
+ * get the data length
492
+ * get the number of row
493
+ * get the number of column
494
+ * get data
495
+
496
+ =============== ===================== =========================
497
+ **Parameters** **Type** **Description**
498
+ *sock* ??? the socket to be readed
499
+ *dtype* numpy unint 32bits ???
500
+ =============== ===================== =========================
501
+
502
+ See Also
503
+ --------
504
+ check_received_length
505
+ """
506
+
507
+ data_list = sock.get_list()
508
+
509
+ return data_list
510
+
511
+ def data_ready(self, data):
512
+ """
513
+ Send the grabed data signal. to be written in the detailed plugin using this base class
514
+
515
+ for instance:
516
+ self.data_grabed_signal.emit([OrderedDict(name=self.client_type,data=[data], type='Data2D')]) #to be overloaded
517
+ """
518
+ pass
519
+
520
+ def command_done(self, command_sock):
521
+ try:
522
+ sock = self.find_socket_within_connected_clients(self.client_type)
523
+ if sock is not None: # if client self.client_type is connected then send it the command
524
+ data = self.read_data(sock)
525
+ else:
526
+ data = self.data_mock
527
+
528
+ if command_sock is None:
529
+ # self.data_grabed_signal.emit([OrderedDict(data=[data],name='TCP GRABBER', type='Data2D')]) #to be directly send to a viewer
530
+ self.data_ready(data)
531
+ # print(data)
532
+ else:
533
+ self.send_data(command_sock, data) # to be send to a client
534
+
535
+ except Exception as e:
536
+ self.emit_status(ThreadCommand("Update_Status", [str(e), 'log']))
537
+
538
+ def commit_settings(self, param):
539
+
540
+ if param.name() in iter_children(self.settings.child(('settings_client')), []):
541
+ grabber_socket = \
542
+ [client['socket'] for client in self.connected_clients if client['type'] == self.client_type][0]
543
+ grabber_socket.send_string('set_info')
544
+
545
+ path = get_param_path(param)[2:] # get the path of this param as a list starting at parent 'infos'
546
+ grabber_socket.send_list(path)
547
+
548
+ # send value
549
+ data = ioxml.parameter_to_xml_string(param)
550
+ grabber_socket.send_string(data)
551
+
552
+ def ini_detector(self, controller=None):
553
+ """
554
+ | Initialisation procedure of the detector updating the status dictionnary.
555
+ |
556
+ | Init axes from image , here returns only None values (to tricky to di it with the server and not really
557
+ necessary for images anyway)
558
+
559
+ See Also
560
+ --------
561
+ utility_classes.DAQ_TCP_server.init_server, get_xaxis, get_yaxis
562
+ """
563
+ self.status.update(edict(initialized=False, info="", x_axis=None, y_axis=None, controller=None))
564
+ try:
565
+ self.settings.child(('infos')).addChildren(self.params_GRABBER)
566
+
567
+ self.init_server()
568
+
569
+ # %%%%%%% init axes from image , here returns only None values (to tricky to di it with the server and not really necessary for images anyway)
570
+ self.x_axis = self.get_xaxis()
571
+ self.y_axis = self.get_yaxis()
572
+ self.status.x_axis = self.x_axis
573
+ self.status.y_axis = self.y_axis
574
+ self.status.initialized = True
575
+ self.status.controller = self.serversocket
576
+ return self.status
577
+
578
+ except Exception as e:
579
+ self.status.info = getLineInfo() + str(e)
580
+ self.status.initialized = False
581
+ return self.status
582
+
583
+ def close(self):
584
+ """
585
+ Should be used to uninitialize hardware.
586
+
587
+ See Also
588
+ --------
589
+ utility_classes.DAQ_TCP_server.close_server
590
+ """
591
+ self.listening = False
592
+ self.close_server()
593
+
594
+ def get_xaxis(self):
595
+ """
596
+ Obtain the horizontal axis of the image.
597
+
598
+ Returns
599
+ -------
600
+ 1D numpy array
601
+ Contains a vector of integer corresponding to the horizontal camera pixels.
602
+ """
603
+ pass
604
+ return self.x_axis
605
+
606
+ def get_yaxis(self):
607
+ """
608
+ Obtain the vertical axis of the image.
609
+
610
+ Returns
611
+ -------
612
+ 1D numpy array
613
+ Contains a vector of integer corresponding to the vertical camera pixels.
614
+ """
615
+ pass
616
+ return self.y_axis
617
+
618
+ def grab_data(self, Naverage=1, **kwargs):
619
+ """
620
+ Start new acquisition.
621
+ Grabbed indice is used to keep track of the current image in the average.
622
+
623
+ ============== ========== ==============================
624
+ **Parameters** **Type** **Description**
625
+
626
+ *Naverage* int Number of images to average
627
+ ============== ========== ==============================
628
+
629
+ See Also
630
+ --------
631
+ utility_classes.DAQ_TCP_server.process_cmds
632
+ """
633
+ try:
634
+ self.ind_grabbed = 0 # to keep track of the current image in the average
635
+ self.Naverage = Naverage
636
+ self.process_cmds("Send Data {:s}".format(self.grabber_type))
637
+ # self.command_server.emit(["process_cmds","Send Data 2D"])
638
+
639
+ except Exception as e:
640
+ self.emit_status(ThreadCommand('Update_Status', [getLineInfo() + str(e), "log"]))
641
+
642
+ def stop(self):
643
+ """
644
+ not implemented.
645
+ """
646
+ pass
647
+ return ""
648
+
649
+ def set_1D_Mock_data(self):
650
+ self.data_mock
651
+ x = np.linspace(0, 99, 100)
652
+ data_tmp = 10 * gauss1D(x, 50, 10, 1) + 1 * np.random.rand((100))
653
+ self.ind_data += 1
654
+ self.data_mock = np.roll(data_tmp, self.ind_data)
655
+
656
+ def set_2D_Mock_data(self):
657
+ self.x_axis = np.linspace(0, 50, 50, endpoint=False)
658
+ self.y_axis = np.linspace(0, 30, 30, endpoint=False)
659
+ self.data_mock = 10 * gauss2D(self.x_axis, 20, 10,
660
+ self.y_axis, 15, 7, 1) + 2 * np.random.rand(len(self.y_axis), len(self.x_axis))
661
+
662
+
663
+ if __name__ == '__main__':
664
+ prog = DAQ_Viewer_TCP_server()