pymodaq 4.2.3__py3-none-any.whl → 5.0.0__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 (399) hide show
  1. pymodaq/__init__.py +30 -23
  2. pymodaq/control_modules/daq_move.py +27 -14
  3. pymodaq/control_modules/daq_move_ui.py +33 -16
  4. pymodaq/control_modules/daq_viewer.py +38 -28
  5. pymodaq/control_modules/daq_viewer_ui.py +6 -6
  6. pymodaq/control_modules/mocks.py +1 -1
  7. pymodaq/control_modules/move_utility_classes.py +19 -10
  8. pymodaq/control_modules/utils.py +18 -12
  9. pymodaq/control_modules/viewer_utility_classes.py +13 -4
  10. pymodaq/dashboard.py +166 -118
  11. pymodaq/examples/custom_app.py +13 -16
  12. pymodaq/examples/custom_viewer.py +7 -7
  13. pymodaq/examples/function_plotter.py +13 -12
  14. pymodaq/examples/parameter_ex.py +50 -25
  15. pymodaq/examples/tcp_client.py +1 -1
  16. pymodaq/extensions/__init__.py +1 -1
  17. pymodaq/extensions/bayesian/bayesian_optimisation.py +15 -12
  18. pymodaq/extensions/bayesian/utils.py +10 -10
  19. pymodaq/extensions/console.py +10 -13
  20. pymodaq/extensions/{daq_logger.py → daq_logger/daq_logger.py} +36 -56
  21. pymodaq/{utils/db/db_logger → extensions/daq_logger/db}/db_logger.py +16 -15
  22. pymodaq/{utils/db/db_logger → extensions/daq_logger/db}/db_logger_models.py +2 -0
  23. pymodaq/{utils/h5modules → extensions/daq_logger}/h5logging.py +7 -8
  24. pymodaq/extensions/daq_scan.py +153 -247
  25. pymodaq/extensions/daq_scan_ui.py +11 -9
  26. pymodaq/extensions/h5browser.py +8 -8
  27. pymodaq/extensions/pid/__init__.py +6 -3
  28. pymodaq/extensions/pid/daq_move_PID.py +4 -2
  29. pymodaq/extensions/pid/pid_controller.py +15 -12
  30. pymodaq/extensions/pid/utils.py +10 -5
  31. pymodaq/extensions/utils.py +5 -3
  32. pymodaq/post_treatment/load_and_plot.py +10 -7
  33. pymodaq/resources/preset_default.xml +1 -1
  34. pymodaq/utils/array_manipulation.py +4 -384
  35. pymodaq/utils/calibration_camera.py +12 -9
  36. pymodaq/utils/chrono_timer.py +7 -5
  37. pymodaq/utils/config.py +3 -450
  38. pymodaq/utils/daq_utils.py +6 -664
  39. pymodaq/utils/data.py +9 -2774
  40. pymodaq/utils/exceptions.py +0 -4
  41. pymodaq/utils/gui_utils/__init__.py +8 -8
  42. pymodaq/utils/gui_utils/loader_utils.py +38 -0
  43. pymodaq/utils/gui_utils/utils.py +6 -138
  44. pymodaq/utils/h5modules/__init__.py +0 -4
  45. pymodaq/utils/h5modules/module_saving.py +15 -8
  46. pymodaq/utils/leco/__init__.py +2 -2
  47. pymodaq/utils/leco/daq_move_LECODirector.py +2 -2
  48. pymodaq/utils/leco/daq_xDviewer_LECODirector.py +2 -2
  49. pymodaq/utils/leco/director_utils.py +2 -2
  50. pymodaq/utils/leco/leco_director.py +3 -3
  51. pymodaq/utils/leco/pymodaq_listener.py +2 -2
  52. pymodaq/utils/leco/utils.py +1 -1
  53. pymodaq/utils/logger.py +4 -76
  54. pymodaq/utils/managers/batchscan_manager.py +16 -19
  55. pymodaq/utils/managers/modules_manager.py +10 -7
  56. pymodaq/utils/managers/overshoot_manager.py +3 -5
  57. pymodaq/utils/managers/preset_manager.py +37 -15
  58. pymodaq/utils/managers/preset_manager_utils.py +11 -9
  59. pymodaq/utils/managers/remote_manager.py +12 -10
  60. pymodaq/utils/math_utils.py +4 -572
  61. pymodaq/utils/parameter/__init__.py +4 -11
  62. pymodaq/utils/parameter/utils.py +4 -299
  63. pymodaq/utils/scanner/scan_config.py +1 -1
  64. pymodaq/utils/scanner/scan_factory.py +16 -12
  65. pymodaq/utils/{plotting → scanner}/scan_selector.py +19 -20
  66. pymodaq/utils/scanner/scanner.py +10 -8
  67. pymodaq/utils/scanner/scanners/_1d_scanners.py +8 -5
  68. pymodaq/utils/scanner/scanners/_2d_scanners.py +5 -5
  69. pymodaq/utils/scanner/scanners/sequential.py +8 -8
  70. pymodaq/utils/scanner/scanners/tabular.py +9 -9
  71. pymodaq/utils/scanner/utils.py +6 -4
  72. pymodaq/utils/svg/svg_viewer2D.py +3 -4
  73. pymodaq/utils/tcp_ip/serializer.py +64 -16
  74. pymodaq/utils/tcp_ip/tcp_server_client.py +10 -8
  75. {pymodaq-4.2.3.dist-info → pymodaq-5.0.0.dist-info}/METADATA +5 -3
  76. pymodaq-5.0.0.dist-info/RECORD +123 -0
  77. {pymodaq-4.2.3.dist-info → pymodaq-5.0.0.dist-info}/WHEEL +1 -1
  78. pymodaq/post_treatment/process_to_scalar.py +0 -263
  79. pymodaq/resources/QtDesigner_Ressources/Icon_Library/1d.png +0 -0
  80. pymodaq/resources/QtDesigner_Ressources/Icon_Library/2d.png +0 -0
  81. pymodaq/resources/QtDesigner_Ressources/Icon_Library/3d.png +0 -0
  82. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Add2.png +0 -0
  83. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Add_Step.png +0 -0
  84. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Approve.png +0 -0
  85. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Approve_All.png +0 -0
  86. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Browse_Dir_Path.png +0 -0
  87. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Calculator.png +0 -0
  88. pymodaq/resources/QtDesigner_Ressources/Icon_Library/ChnGroup.png +0 -0
  89. pymodaq/resources/QtDesigner_Ressources/Icon_Library/ChnNum.png +0 -0
  90. pymodaq/resources/QtDesigner_Ressources/Icon_Library/ChnText.png +0 -0
  91. pymodaq/resources/QtDesigner_Ressources/Icon_Library/ChnTime.png +0 -0
  92. pymodaq/resources/QtDesigner_Ressources/Icon_Library/ChnWave.png +0 -0
  93. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Close3.png +0 -0
  94. pymodaq/resources/QtDesigner_Ressources/Icon_Library/CollapseAll.png +0 -0
  95. pymodaq/resources/QtDesigner_Ressources/Icon_Library/CollapseAll_32.png +0 -0
  96. pymodaq/resources/QtDesigner_Ressources/Icon_Library/ColorPicker.png +0 -0
  97. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Contract.png +0 -0
  98. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Create.png +0 -0
  99. pymodaq/resources/QtDesigner_Ressources/Icon_Library/DeleteLayer.png +0 -0
  100. pymodaq/resources/QtDesigner_Ressources/Icon_Library/EditOpen.png +0 -0
  101. pymodaq/resources/QtDesigner_Ressources/Icon_Library/EditRedo.png +0 -0
  102. pymodaq/resources/QtDesigner_Ressources/Icon_Library/EditUndo.png +0 -0
  103. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Ellipse.png +0 -0
  104. pymodaq/resources/QtDesigner_Ressources/Icon_Library/EllipseFilled.png +0 -0
  105. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Error.png +0 -0
  106. pymodaq/resources/QtDesigner_Ressources/Icon_Library/ErrorMessage.png +0 -0
  107. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Error_16.png +0 -0
  108. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Exit.png +0 -0
  109. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Expand.png +0 -0
  110. pymodaq/resources/QtDesigner_Ressources/Icon_Library/ExpandAll.png +0 -0
  111. pymodaq/resources/QtDesigner_Ressources/Icon_Library/ExpandAll_32.png +0 -0
  112. pymodaq/resources/QtDesigner_Ressources/Icon_Library/FFT.png +0 -0
  113. pymodaq/resources/QtDesigner_Ressources/Icon_Library/HLM.ico +0 -0
  114. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Help.png +0 -0
  115. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Help_32.png +0 -0
  116. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Histogram.png +0 -0
  117. pymodaq/resources/QtDesigner_Ressources/Icon_Library/LUT_LookUpTable.png +0 -0
  118. pymodaq/resources/QtDesigner_Ressources/Icon_Library/MagnifyingGlass.png +0 -0
  119. pymodaq/resources/QtDesigner_Ressources/Icon_Library/MagnifyingGlass_24.png +0 -0
  120. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Marker.png +0 -0
  121. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Math.png +0 -0
  122. pymodaq/resources/QtDesigner_Ressources/Icon_Library/MeasurementStudio_32.png +0 -0
  123. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Move.png +0 -0
  124. pymodaq/resources/QtDesigner_Ressources/Icon_Library/MoveDown.png +0 -0
  125. pymodaq/resources/QtDesigner_Ressources/Icon_Library/MoveUp.png +0 -0
  126. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Multiply.png +0 -0
  127. pymodaq/resources/QtDesigner_Ressources/Icon_Library/NewFile.png +0 -0
  128. pymodaq/resources/QtDesigner_Ressources/Icon_Library/NewLayer.png +0 -0
  129. pymodaq/resources/QtDesigner_Ressources/Icon_Library/New_File.png +0 -0
  130. pymodaq/resources/QtDesigner_Ressources/Icon_Library/New_Folder.png +0 -0
  131. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Open.png +0 -0
  132. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Open_1D.png +0 -0
  133. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Open_2D.png +0 -0
  134. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Open_File.png +0 -0
  135. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Open_File_32.png +0 -0
  136. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Open_sim.png +0 -0
  137. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Options.png +0 -0
  138. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Oscilloscope.png +0 -0
  139. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Oscilloscope_16.png +0 -0
  140. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Pass.png +0 -0
  141. pymodaq/resources/QtDesigner_Ressources/Icon_Library/RGB.png +0 -0
  142. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Rectangle.png +0 -0
  143. pymodaq/resources/QtDesigner_Ressources/Icon_Library/RectangleFilled.png +0 -0
  144. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Redo.png +0 -0
  145. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Refresh.png +0 -0
  146. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Refresh2.png +0 -0
  147. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Refresh_32.png +0 -0
  148. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Region.png +0 -0
  149. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Rendezvous.png +0 -0
  150. pymodaq/resources/QtDesigner_Ressources/Icon_Library/SELECT.png +0 -0
  151. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Save.png +0 -0
  152. pymodaq/resources/QtDesigner_Ressources/Icon_Library/SaveAll.png +0 -0
  153. pymodaq/resources/QtDesigner_Ressources/Icon_Library/SaveAll_32.png +0 -0
  154. pymodaq/resources/QtDesigner_Ressources/Icon_Library/SaveAs.png +0 -0
  155. pymodaq/resources/QtDesigner_Ressources/Icon_Library/SaveAs_32.png +0 -0
  156. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Save_24.png +0 -0
  157. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Save_32.png +0 -0
  158. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Search.png +0 -0
  159. pymodaq/resources/QtDesigner_Ressources/Icon_Library/SelectPolygon.png +0 -0
  160. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Select_24.png +0 -0
  161. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Settings.png +0 -0
  162. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Snap&Save.png +0 -0
  163. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Snapshot.png +0 -0
  164. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Snapshot2.png +0 -0
  165. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Snapshot2_16.png +0 -0
  166. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Snapshot2_32.png +0 -0
  167. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Spreadsheet.png +0 -0
  168. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Statistics.png +0 -0
  169. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Statistics2.png +0 -0
  170. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Status.png +0 -0
  171. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Subtract.png +0 -0
  172. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Vision.png +0 -0
  173. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Volts.png +0 -0
  174. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Wait2.png +0 -0
  175. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Zoom_1_1.png +0 -0
  176. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Zoom_in.png +0 -0
  177. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Zoom_out.png +0 -0
  178. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Zoom_to_Selection.png +0 -0
  179. pymodaq/resources/QtDesigner_Ressources/Icon_Library/abort.png +0 -0
  180. pymodaq/resources/QtDesigner_Ressources/Icon_Library/advanced2.png +0 -0
  181. pymodaq/resources/QtDesigner_Ressources/Icon_Library/autoscale.png +0 -0
  182. pymodaq/resources/QtDesigner_Ressources/Icon_Library/b_icon.png +0 -0
  183. pymodaq/resources/QtDesigner_Ressources/Icon_Library/back.png +0 -0
  184. pymodaq/resources/QtDesigner_Ressources/Icon_Library/bg_icon.png +0 -0
  185. pymodaq/resources/QtDesigner_Ressources/Icon_Library/camera.png +0 -0
  186. pymodaq/resources/QtDesigner_Ressources/Icon_Library/camera_snap.png +0 -0
  187. pymodaq/resources/QtDesigner_Ressources/Icon_Library/cartesian.png +0 -0
  188. pymodaq/resources/QtDesigner_Ressources/Icon_Library/clear2.png +0 -0
  189. pymodaq/resources/QtDesigner_Ressources/Icon_Library/clear_ROI.png +0 -0
  190. pymodaq/resources/QtDesigner_Ressources/Icon_Library/close2.png +0 -0
  191. pymodaq/resources/QtDesigner_Ressources/Icon_Library/cluster2.png +0 -0
  192. pymodaq/resources/QtDesigner_Ressources/Icon_Library/color.png +0 -0
  193. pymodaq/resources/QtDesigner_Ressources/Icon_Library/color2.png +0 -0
  194. pymodaq/resources/QtDesigner_Ressources/Icon_Library/continuous.png +0 -0
  195. pymodaq/resources/QtDesigner_Ressources/Icon_Library/data.png +0 -0
  196. pymodaq/resources/QtDesigner_Ressources/Icon_Library/delay.png +0 -0
  197. pymodaq/resources/QtDesigner_Ressources/Icon_Library/download.png +0 -0
  198. pymodaq/resources/QtDesigner_Ressources/Icon_Library/download2.png +0 -0
  199. pymodaq/resources/QtDesigner_Ressources/Icon_Library/error2.png +0 -0
  200. pymodaq/resources/QtDesigner_Ressources/Icon_Library/ethernet.png +0 -0
  201. pymodaq/resources/QtDesigner_Ressources/Icon_Library/exit2.png +0 -0
  202. pymodaq/resources/QtDesigner_Ressources/Icon_Library/fan.png +0 -0
  203. pymodaq/resources/QtDesigner_Ressources/Icon_Library/filter2.png +0 -0
  204. pymodaq/resources/QtDesigner_Ressources/Icon_Library/g_icon.png +0 -0
  205. pymodaq/resources/QtDesigner_Ressources/Icon_Library/gear2.png +0 -0
  206. pymodaq/resources/QtDesigner_Ressources/Icon_Library/go_to.png +0 -0
  207. pymodaq/resources/QtDesigner_Ressources/Icon_Library/go_to_1.png +0 -0
  208. pymodaq/resources/QtDesigner_Ressources/Icon_Library/go_to_2.png +0 -0
  209. pymodaq/resources/QtDesigner_Ressources/Icon_Library/grab.png +0 -0
  210. pymodaq/resources/QtDesigner_Ressources/Icon_Library/graph.png +0 -0
  211. pymodaq/resources/QtDesigner_Ressources/Icon_Library/greenLight2.png +0 -0
  212. pymodaq/resources/QtDesigner_Ressources/Icon_Library/greenLight2_32.png +0 -0
  213. pymodaq/resources/QtDesigner_Ressources/Icon_Library/green_light.png +0 -0
  214. pymodaq/resources/QtDesigner_Ressources/Icon_Library/grey_icon.png +0 -0
  215. pymodaq/resources/QtDesigner_Ressources/Icon_Library/greyscale.png +0 -0
  216. pymodaq/resources/QtDesigner_Ressources/Icon_Library/help1.png +0 -0
  217. pymodaq/resources/QtDesigner_Ressources/Icon_Library/help1_32.png +0 -0
  218. pymodaq/resources/QtDesigner_Ressources/Icon_Library/home2.png +0 -0
  219. pymodaq/resources/QtDesigner_Ressources/Icon_Library/information2.png +0 -0
  220. pymodaq/resources/QtDesigner_Ressources/Icon_Library/ini.png +0 -0
  221. pymodaq/resources/QtDesigner_Ressources/Icon_Library/integrator.png +0 -0
  222. pymodaq/resources/QtDesigner_Ressources/Icon_Library/joystick.png +0 -0
  223. pymodaq/resources/QtDesigner_Ressources/Icon_Library/light_green.png +0 -0
  224. pymodaq/resources/QtDesigner_Ressources/Icon_Library/light_green_16.png +0 -0
  225. pymodaq/resources/QtDesigner_Ressources/Icon_Library/light_red.png +0 -0
  226. pymodaq/resources/QtDesigner_Ressources/Icon_Library/light_red_16.png +0 -0
  227. pymodaq/resources/QtDesigner_Ressources/Icon_Library/light_yellow.png +0 -0
  228. pymodaq/resources/QtDesigner_Ressources/Icon_Library/light_yellow_16.png +0 -0
  229. pymodaq/resources/QtDesigner_Ressources/Icon_Library/limiter.png +0 -0
  230. pymodaq/resources/QtDesigner_Ressources/Icon_Library/load_ROI.png +0 -0
  231. pymodaq/resources/QtDesigner_Ressources/Icon_Library/meshPlot.png +0 -0
  232. pymodaq/resources/QtDesigner_Ressources/Icon_Library/meter.png +0 -0
  233. pymodaq/resources/QtDesigner_Ressources/Icon_Library/meter2.png +0 -0
  234. pymodaq/resources/QtDesigner_Ressources/Icon_Library/meter_32.png +0 -0
  235. pymodaq/resources/QtDesigner_Ressources/Icon_Library/move_contour.png +0 -0
  236. pymodaq/resources/QtDesigner_Ressources/Icon_Library/move_straight_line.png +0 -0
  237. pymodaq/resources/QtDesigner_Ressources/Icon_Library/movie.png +0 -0
  238. pymodaq/resources/QtDesigner_Ressources/Icon_Library/multi_point.png +0 -0
  239. pymodaq/resources/QtDesigner_Ressources/Icon_Library/multiplexer.png +0 -0
  240. pymodaq/resources/QtDesigner_Ressources/Icon_Library/new.png +0 -0
  241. pymodaq/resources/QtDesigner_Ressources/Icon_Library/openArrow.png +0 -0
  242. pymodaq/resources/QtDesigner_Ressources/Icon_Library/openTree.png +0 -0
  243. pymodaq/resources/QtDesigner_Ressources/Icon_Library/oscilloscope2.png +0 -0
  244. pymodaq/resources/QtDesigner_Ressources/Icon_Library/oscilloscope3.png +0 -0
  245. pymodaq/resources/QtDesigner_Ressources/Icon_Library/overlay.png +0 -0
  246. pymodaq/resources/QtDesigner_Ressources/Icon_Library/pass2.png +0 -0
  247. pymodaq/resources/QtDesigner_Ressources/Icon_Library/pass2_16.png +0 -0
  248. pymodaq/resources/QtDesigner_Ressources/Icon_Library/pass_32.png +0 -0
  249. pymodaq/resources/QtDesigner_Ressources/Icon_Library/pause.png +0 -0
  250. pymodaq/resources/QtDesigner_Ressources/Icon_Library/permute.png +0 -0
  251. pymodaq/resources/QtDesigner_Ressources/Icon_Library/phase.png +0 -0
  252. pymodaq/resources/QtDesigner_Ressources/Icon_Library/play.png +0 -0
  253. pymodaq/resources/QtDesigner_Ressources/Icon_Library/polar.png +0 -0
  254. pymodaq/resources/QtDesigner_Ressources/Icon_Library/pole_zero.png +0 -0
  255. pymodaq/resources/QtDesigner_Ressources/Icon_Library/powerMeter.png +0 -0
  256. pymodaq/resources/QtDesigner_Ressources/Icon_Library/powerSwitch.png +0 -0
  257. pymodaq/resources/QtDesigner_Ressources/Icon_Library/powerSwitch_16.png +0 -0
  258. pymodaq/resources/QtDesigner_Ressources/Icon_Library/print2.png +0 -0
  259. pymodaq/resources/QtDesigner_Ressources/Icon_Library/print2_32.png +0 -0
  260. pymodaq/resources/QtDesigner_Ressources/Icon_Library/properties.png +0 -0
  261. pymodaq/resources/QtDesigner_Ressources/Icon_Library/r_icon.png +0 -0
  262. pymodaq/resources/QtDesigner_Ressources/Icon_Library/radiocontrolbutton.png +0 -0
  263. pymodaq/resources/QtDesigner_Ressources/Icon_Library/read2.png +0 -0
  264. pymodaq/resources/QtDesigner_Ressources/Icon_Library/red_light.png +0 -0
  265. pymodaq/resources/QtDesigner_Ressources/Icon_Library/remove.png +0 -0
  266. pymodaq/resources/QtDesigner_Ressources/Icon_Library/reset.png +0 -0
  267. pymodaq/resources/QtDesigner_Ressources/Icon_Library/rgb_icon.png +0 -0
  268. pymodaq/resources/QtDesigner_Ressources/Icon_Library/robot.png +0 -0
  269. pymodaq/resources/QtDesigner_Ressources/Icon_Library/rotation2.png +0 -0
  270. pymodaq/resources/QtDesigner_Ressources/Icon_Library/run2.png +0 -0
  271. pymodaq/resources/QtDesigner_Ressources/Icon_Library/run_all.png +0 -0
  272. pymodaq/resources/QtDesigner_Ressources/Icon_Library/saturation.png +0 -0
  273. pymodaq/resources/QtDesigner_Ressources/Icon_Library/saveTree.png +0 -0
  274. pymodaq/resources/QtDesigner_Ressources/Icon_Library/save_ROI.png +0 -0
  275. pymodaq/resources/QtDesigner_Ressources/Icon_Library/scale_horizontally.png +0 -0
  276. pymodaq/resources/QtDesigner_Ressources/Icon_Library/scale_vertically.png +0 -0
  277. pymodaq/resources/QtDesigner_Ressources/Icon_Library/search2.png +0 -0
  278. pymodaq/resources/QtDesigner_Ressources/Icon_Library/select2.png +0 -0
  279. pymodaq/resources/QtDesigner_Ressources/Icon_Library/select_all.png +0 -0
  280. pymodaq/resources/QtDesigner_Ressources/Icon_Library/select_all2.png +0 -0
  281. pymodaq/resources/QtDesigner_Ressources/Icon_Library/select_none.png +0 -0
  282. pymodaq/resources/QtDesigner_Ressources/Icon_Library/sequence.png +0 -0
  283. pymodaq/resources/QtDesigner_Ressources/Icon_Library/sequence2.png +0 -0
  284. pymodaq/resources/QtDesigner_Ressources/Icon_Library/snap.png +0 -0
  285. pymodaq/resources/QtDesigner_Ressources/Icon_Library/sort_ascend.png +0 -0
  286. pymodaq/resources/QtDesigner_Ressources/Icon_Library/spectrumAnalyzer.png +0 -0
  287. pymodaq/resources/QtDesigner_Ressources/Icon_Library/start.png +0 -0
  288. pymodaq/resources/QtDesigner_Ressources/Icon_Library/status_cancelled.png +0 -0
  289. pymodaq/resources/QtDesigner_Ressources/Icon_Library/stop.png +0 -0
  290. pymodaq/resources/QtDesigner_Ressources/Icon_Library/stop2.png +0 -0
  291. pymodaq/resources/QtDesigner_Ressources/Icon_Library/stop3.png +0 -0
  292. pymodaq/resources/QtDesigner_Ressources/Icon_Library/stop_all.png +0 -0
  293. pymodaq/resources/QtDesigner_Ressources/Icon_Library/sum.png +0 -0
  294. pymodaq/resources/QtDesigner_Ressources/Icon_Library/surfacePlot.png +0 -0
  295. pymodaq/resources/QtDesigner_Ressources/Icon_Library/tree.png +0 -0
  296. pymodaq/resources/QtDesigner_Ressources/Icon_Library/updateTree.png +0 -0
  297. pymodaq/resources/QtDesigner_Ressources/Icon_Library/utility2.png +0 -0
  298. pymodaq/resources/QtDesigner_Ressources/Icon_Library/utility_small.png +0 -0
  299. pymodaq/resources/QtDesigner_Ressources/Icon_Library/vector.png +0 -0
  300. pymodaq/resources/QtDesigner_Ressources/Icon_Library/verify.png +0 -0
  301. pymodaq/resources/QtDesigner_Ressources/Icon_Library/video.png +0 -0
  302. pymodaq/resources/QtDesigner_Ressources/Icon_Library/wait.png +0 -0
  303. pymodaq/resources/QtDesigner_Ressources/Icon_Library/waterfallPlot.png +0 -0
  304. pymodaq/resources/QtDesigner_Ressources/Icon_Library/watershed.png +0 -0
  305. pymodaq/resources/QtDesigner_Ressources/Icon_Library/yellow_light.png +0 -0
  306. pymodaq/resources/QtDesigner_Ressources/Icon_Library/zip_file.png +0 -0
  307. pymodaq/resources/QtDesigner_Ressources/Icon_Library/zoomAuto.png +0 -0
  308. pymodaq/resources/QtDesigner_Ressources/Icon_Library/zoomReset.png +0 -0
  309. pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources.bat +0 -2
  310. pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources.qrc +0 -234
  311. pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources_rc.py +0 -127150
  312. pymodaq/resources/QtDesigner_Ressources/icons.svg +0 -142
  313. pymodaq/resources/VERSION +0 -1
  314. pymodaq/resources/config_template.toml +0 -90
  315. pymodaq/resources/triangulation_data.npy +0 -0
  316. pymodaq/utils/abstract/__init__.py +0 -48
  317. pymodaq/utils/db/__init__.py +0 -0
  318. pymodaq/utils/db/db_logger/__init__.py +0 -0
  319. pymodaq/utils/enums.py +0 -76
  320. pymodaq/utils/factory.py +0 -82
  321. pymodaq/utils/gui_utils/custom_app.py +0 -133
  322. pymodaq/utils/gui_utils/dock.py +0 -107
  323. pymodaq/utils/gui_utils/file_io.py +0 -93
  324. pymodaq/utils/gui_utils/layout.py +0 -34
  325. pymodaq/utils/gui_utils/list_picker.py +0 -38
  326. pymodaq/utils/gui_utils/widgets/__init__.py +0 -5
  327. pymodaq/utils/gui_utils/widgets/label.py +0 -24
  328. pymodaq/utils/gui_utils/widgets/lcd.py +0 -111
  329. pymodaq/utils/gui_utils/widgets/push.py +0 -149
  330. pymodaq/utils/gui_utils/widgets/qled.py +0 -62
  331. pymodaq/utils/gui_utils/widgets/spinbox.py +0 -24
  332. pymodaq/utils/gui_utils/widgets/table.py +0 -263
  333. pymodaq/utils/gui_utils/widgets/tree_layout.py +0 -188
  334. pymodaq/utils/gui_utils/widgets/tree_toml.py +0 -102
  335. pymodaq/utils/h5modules/backends.py +0 -1022
  336. pymodaq/utils/h5modules/browsing.py +0 -625
  337. pymodaq/utils/h5modules/data_saving.py +0 -1101
  338. pymodaq/utils/h5modules/exporter.py +0 -119
  339. pymodaq/utils/h5modules/exporters/__init__.py +0 -0
  340. pymodaq/utils/h5modules/exporters/base.py +0 -111
  341. pymodaq/utils/h5modules/exporters/flimj.py +0 -63
  342. pymodaq/utils/h5modules/exporters/hyperspy.py +0 -143
  343. pymodaq/utils/h5modules/saving.py +0 -866
  344. pymodaq/utils/h5modules/utils.py +0 -115
  345. pymodaq/utils/managers/action_manager.py +0 -489
  346. pymodaq/utils/managers/parameter_manager.py +0 -282
  347. pymodaq/utils/managers/roi_manager.py +0 -726
  348. pymodaq/utils/messenger.py +0 -66
  349. pymodaq/utils/parameter/ioxml.py +0 -542
  350. pymodaq/utils/parameter/pymodaq_ptypes/__init__.py +0 -38
  351. pymodaq/utils/parameter/pymodaq_ptypes/bool.py +0 -31
  352. pymodaq/utils/parameter/pymodaq_ptypes/date.py +0 -126
  353. pymodaq/utils/parameter/pymodaq_ptypes/filedir.py +0 -143
  354. pymodaq/utils/parameter/pymodaq_ptypes/itemselect.py +0 -265
  355. pymodaq/utils/parameter/pymodaq_ptypes/led.py +0 -44
  356. pymodaq/utils/parameter/pymodaq_ptypes/list.py +0 -150
  357. pymodaq/utils/parameter/pymodaq_ptypes/numeric.py +0 -18
  358. pymodaq/utils/parameter/pymodaq_ptypes/pixmap.py +0 -175
  359. pymodaq/utils/parameter/pymodaq_ptypes/slide.py +0 -145
  360. pymodaq/utils/parameter/pymodaq_ptypes/table.py +0 -135
  361. pymodaq/utils/parameter/pymodaq_ptypes/tableview.py +0 -149
  362. pymodaq/utils/parameter/pymodaq_ptypes/text.py +0 -142
  363. pymodaq/utils/plotting/__init__.py +0 -0
  364. pymodaq/utils/plotting/data_viewers/__init__.py +0 -10
  365. pymodaq/utils/plotting/data_viewers/base.py +0 -286
  366. pymodaq/utils/plotting/data_viewers/viewer.py +0 -274
  367. pymodaq/utils/plotting/data_viewers/viewer0D.py +0 -298
  368. pymodaq/utils/plotting/data_viewers/viewer1D.py +0 -820
  369. pymodaq/utils/plotting/data_viewers/viewer1Dbasic.py +0 -231
  370. pymodaq/utils/plotting/data_viewers/viewer2D.py +0 -1118
  371. pymodaq/utils/plotting/data_viewers/viewer2D_basic.py +0 -146
  372. pymodaq/utils/plotting/data_viewers/viewerND.py +0 -800
  373. pymodaq/utils/plotting/gant_chart.py +0 -123
  374. pymodaq/utils/plotting/image_viewer.py +0 -97
  375. pymodaq/utils/plotting/items/__init__.py +0 -0
  376. pymodaq/utils/plotting/items/axis_scaled.py +0 -93
  377. pymodaq/utils/plotting/items/crosshair.py +0 -94
  378. pymodaq/utils/plotting/items/image.py +0 -388
  379. pymodaq/utils/plotting/navigator.py +0 -353
  380. pymodaq/utils/plotting/plotter/plotter.py +0 -94
  381. pymodaq/utils/plotting/plotter/plotters/__init__.py +0 -0
  382. pymodaq/utils/plotting/plotter/plotters/matplotlib_plotters.py +0 -134
  383. pymodaq/utils/plotting/plotter/plotters/qt_plotters.py +0 -78
  384. pymodaq/utils/plotting/utils/__init__.py +0 -0
  385. pymodaq/utils/plotting/utils/axes_viewer.py +0 -88
  386. pymodaq/utils/plotting/utils/filter.py +0 -585
  387. pymodaq/utils/plotting/utils/lineout.py +0 -226
  388. pymodaq/utils/plotting/utils/plot_utils.py +0 -579
  389. pymodaq/utils/plotting/utils/signalND.py +0 -1347
  390. pymodaq/utils/plotting/widgets.py +0 -76
  391. pymodaq/utils/qvariant.py +0 -12
  392. pymodaq/utils/slicing.py +0 -63
  393. pymodaq/utils/units.py +0 -216
  394. pymodaq-4.2.3.dist-info/RECORD +0 -438
  395. /pymodaq/{post_treatment/daq_analysis → extensions/daq_logger}/__init__.py +0 -0
  396. /pymodaq/{utils/abstract/logger.py → extensions/daq_logger/abstract.py} +0 -0
  397. /pymodaq/{resources/QtDesigner_Ressources → extensions/daq_logger/db}/__init__.py +0 -0
  398. {pymodaq-4.2.3.dist-info → pymodaq-5.0.0.dist-info}/entry_points.txt +0 -0
  399. {pymodaq-4.2.3.dist-info → pymodaq-5.0.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,866 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- """
3
- Created the 15/11/2022
4
-
5
- @author: Sebastien Weber
6
- """
7
- import copy
8
- import datetime
9
- from dateutil import parser
10
- from numbers import Number
11
- import os
12
- from pathlib import Path
13
- from typing import Union, Iterable
14
-
15
-
16
- import numpy as np
17
- from qtpy.QtCore import QObject, Signal
18
- from qtpy import QtWidgets
19
-
20
- from pymodaq.utils.logger import set_logger, get_module_name
21
- from pymodaq.utils.parameter import Parameter, ParameterTree
22
- from pymodaq.utils.parameter import utils as putils
23
- from pymodaq.utils.managers.parameter_manager import ParameterManager
24
- from pymodaq.utils.gui_utils.file_io import select_file
25
-
26
- from pymodaq.utils.gui_utils.utils import dashboard_submodules_params
27
- from pymodaq.utils import daq_utils as utils
28
- from pymodaq.utils.config import Config
29
- from pymodaq.utils.data import DataDim, DataToExport, Axis, DataWithAxes
30
- from pymodaq.utils.enums import BaseEnum, enum_checker
31
- from pymodaq.utils.scanner.utils import ScanType
32
- from pymodaq.utils.messenger import deprecation_msg
33
-
34
-
35
- from .backends import (H5Backend, backends_available, SaveType, InvalidSave, InvalidExport, InvalidDataType,
36
- InvalidGroupType, InvalidGroupDataType, Node, GroupType, InvalidDataDimension, InvalidScanType,
37
- GROUP, VLARRAY)
38
- from . import browsing
39
-
40
-
41
- config = Config()
42
- logger = set_logger(get_module_name(__file__))
43
-
44
-
45
- class FileType(BaseEnum):
46
- detector = 0
47
- actuator = 1
48
- axis = 2
49
- scan = 3
50
-
51
-
52
- class DataType(BaseEnum):
53
- data = 'Data'
54
- axis = 'Axis'
55
- live_scan = 'Live'
56
- external_h5 = 'ExtData'
57
- strings = 'Strings'
58
- bkg = 'Bkg'
59
- data_enlargeable = 'EnlData'
60
- error = 'ErrorBar'
61
-
62
-
63
- class H5SaverLowLevel(H5Backend):
64
- """Object containing basic methods in order to structure and interact with a h5file compatible with the h5browser
65
-
66
- See Also
67
- --------
68
- H5Browser
69
-
70
- Attributes
71
- ----------
72
- h5_file: pytables hdf5 file
73
- object used to save all datas and metadas
74
- h5_file_path: str or Path
75
- The file path
76
- """
77
-
78
- def __init__(self, save_type: SaveType = 'scan', backend='tables'):
79
- H5Backend.__init__(self, backend)
80
-
81
- self.save_type = enum_checker(SaveType, save_type)
82
-
83
- self.h5_file_path = None
84
- self.h5_file_name = None
85
- self.file_loaded = False
86
-
87
- self._current_group = None
88
- self._raw_group: Union[GROUP, str] = '/RawData'
89
- self._logger_array = None
90
-
91
- @property
92
- def raw_group(self):
93
- return self._raw_group
94
-
95
- @property
96
- def h5_file(self):
97
- return self._h5file
98
-
99
- def init_file(self, file_name: Path, raw_group_name='RawData', new_file=False, metadata: dict = None):
100
- """Initializes a new h5 file.
101
-
102
- Parameters
103
- ----------
104
- file_name: Path
105
- a complete Path pointing to a h5 file
106
- raw_group_name: str
107
- Base node name
108
- new_file: bool
109
- If True create a new file, otherwise append to a potential existing one
110
-
111
- Returns
112
- -------
113
- bool
114
- True if new file has been created, False otherwise
115
- """
116
- datetime_now = datetime.datetime.now()
117
-
118
- if file_name is not None and isinstance(file_name, Path):
119
- self.h5_file_name = file_name.stem + ".h5"
120
- self.h5_file_path = file_name.parent
121
- if not self.h5_file_path.joinpath(self.h5_file_name).is_file():
122
- new_file = True
123
-
124
- else:
125
- self.h5_file_name = select_file(save=True, ext='h5')
126
- self.h5_file_path = self.h5_file_name.parent
127
- new_file = True
128
-
129
- self.close_file()
130
- self.open_file(self.h5_file_path.joinpath(self.h5_file_name), 'w' if new_file else 'a', title='PyMoDAQ file')
131
-
132
- self._raw_group = self.get_set_group(self.root(), raw_group_name, title='Data from PyMoDAQ modules')
133
- self.get_set_logger(self._raw_group)
134
-
135
- if new_file:
136
- self._raw_group.attrs['type'] = self.save_type.name # first possibility to set a node attribute
137
- self.root().set_attr('file', self.h5_file_name) # second possibility
138
-
139
- self.set_attr(self.root(), 'date', datetime_now.date().isoformat())
140
- self.set_attr(self.root(), 'time', datetime_now.time().isoformat())
141
-
142
- if metadata is not None:
143
- for metadata_key in metadata:
144
- self._raw_group.attrs[metadata_key] = metadata[metadata_key]
145
-
146
- def save_file(self, filename=None):
147
- if filename is None:
148
- filename = select_file(None, save=True, ext='h5')
149
- if filename != '':
150
- super().save_file_as(filename)
151
-
152
- def get_set_logger(self, where: Node = None) -> VLARRAY:
153
- """ Retrieve or create (if absent) a logger enlargeable array to store logs
154
- Get attributed to the class attribute ``logger_array``
155
- Parameters
156
- ----------
157
- where: node
158
- location within the tree where to save or retrieve the array
159
-
160
- Returns
161
- -------
162
- vlarray
163
- enlargeable array accepting strings as elements
164
- """
165
- if where is None:
166
- where = self.raw_group
167
- if isinstance(where, Node):
168
- where = where.node
169
- logger = 'Logger'
170
- if logger not in list(self.get_children(where)):
171
- # check if logger node exist
172
- self._logger_array = self.add_string_array(where, logger)
173
- self._logger_array.attrs['type'] = 'log'
174
- else:
175
- self._logger_array = self.get_node(where, name=logger)
176
- return self._logger_array
177
-
178
- def add_log(self, msg):
179
- self._logger_array.append(msg)
180
-
181
- def add_string_array(self, where, name, title='', metadata=dict([])):
182
- array = self.create_vlarray(where, name, dtype='string', title=title)
183
- array.attrs['shape'] = (0,)
184
- array.attrs['data_type'] = 'strings'
185
-
186
- for metadat in metadata:
187
- array.attrs[metadat] = metadata[metadat]
188
- return array
189
-
190
- def add_array(self, where: Union[GROUP, str], name: str, data_type: DataType, array_to_save: np.ndarray = None,
191
- data_shape: tuple = None, array_type: np.dtype = None, data_dimension: DataDim = None,
192
- scan_shape: tuple = tuple([]), add_scan_dim=False, enlargeable: bool = False,
193
- title: str = '', metadata=dict([]), ):
194
-
195
- """save data arrays on the hdf5 file together with metadata
196
- Parameters
197
- ----------
198
- where: GROUP
199
- node where to save the array
200
- name: str
201
- name of the array in the hdf5 file
202
- data_type: DataType
203
- mandatory so that the h5Browser can interpret correctly the array
204
- data_shape: Iterable
205
- the shape of the array to save, mandatory if array_to_save is None
206
- data_dimension: DataDim
207
- The data's dimension
208
- scan_shape: Iterable
209
- the shape of the scan dimensions
210
- title: str
211
- the title attribute of the array node
212
- array_to_save: ndarray or None
213
- data to be saved in the array. If None, array_type and data_shape should be specified in order to init
214
- correctly the memory
215
- array_type: np.dtype or numpy types
216
- eg np.float, np.int32 ...
217
- enlargeable: bool
218
- if False, data are saved as a CARRAY, otherwise as a EARRAY (for ragged data, see add_string_array)
219
- metadata: dict
220
- dictionnary whose keys will be saved as the array attributes
221
- add_scan_dim: if True, the scan axes dimension (scan_shape iterable) is prepended to the array shape on the hdf5
222
- In that case, the array is usually initialized as zero and further populated
223
-
224
- Returns
225
- -------
226
- array (CARRAY or EARRAY)
227
-
228
- See Also
229
- --------
230
- add_data, add_string_array
231
- """
232
- if array_type is None:
233
- if array_to_save is None:
234
- array_type = config('data_saving', 'data_type', 'dynamic')
235
- else:
236
- array_type = array_to_save.dtype
237
-
238
- data_type = enum_checker(DataType, data_type)
239
- data_dimension = enum_checker(DataDim, data_dimension)
240
-
241
- if enlargeable:
242
- # if data_shape == (1,):
243
- # data_shape = None
244
- array = self.create_earray(where, utils.capitalize(name), dtype=np.dtype(array_type),
245
- data_shape=data_shape, title=title)
246
- else:
247
- if add_scan_dim: # means it is an array initialization to zero
248
- shape = list(scan_shape[:])
249
- if not(len(data_shape) == 1 and data_shape[0] == 1): # means data are not ndarrays of scalars
250
- shape.extend(data_shape)
251
- if array_to_save is None:
252
- array_to_save = np.zeros(shape, dtype=np.dtype(array_type))
253
-
254
- array = self.create_carray(where, utils.capitalize(name), obj=array_to_save, title=title)
255
- self.set_attr(array, 'data_type', data_type.name)
256
- self.set_attr(array, 'data_dimension', data_dimension.name)
257
-
258
- for metadat in metadata:
259
- self.set_attr(array, metadat, metadata[metadat])
260
- return array
261
-
262
- def get_set_group(self, where, name, title=''):
263
- """Get the group located at where if it exists otherwise creates it
264
-
265
- This also set the _current_group property
266
- """
267
- self._current_group = super().get_set_group(where, name, title)
268
- return self._current_group
269
-
270
- def get_groups(self, where: Union[str, GROUP], group_type: GroupType):
271
- """Get all groups hanging from a Group and of a certain type"""
272
- groups = []
273
- for node_name in list(self.get_children(where)):
274
- group = self.get_node(where, node_name)
275
- if 'type' in group.attrs and group.attrs['type'] == group_type.name:
276
- groups.append(group)
277
- return groups
278
-
279
- def get_last_group(self, where: GROUP, group_type: GroupType):
280
- groups = self.get_groups(where, group_type)
281
- if len(groups) != 0:
282
- return groups[-1]
283
- else:
284
- return None
285
-
286
- def get_node_from_attribute_match(self, where, attr_name, attr_value):
287
- """Get a Node starting from a given node (Group) matching a pair of node attribute name and value"""
288
- for node in self.walk_nodes(where):
289
- if attr_name in node.attrs and node.attrs[attr_name] == attr_value:
290
- return node
291
-
292
- def get_node_from_title(self, where, title: str):
293
- """Get a Node starting from a given node (Group) matching the given title"""
294
- return self.get_node_from_attribute_match(where, 'TITLE', title)
295
-
296
- def add_data_group(self, where, data_dim: DataDim, title='', settings_as_xml='', metadata=dict([])):
297
- """Creates a group node at given location in the tree
298
-
299
- Parameters
300
- ----------
301
- where: group node
302
- where to create data group
303
- group_data_type: DataDim
304
- title: str, optional
305
- a title for this node, will be saved as metadata
306
- settings_as_xml: str, optional
307
- XML string created from a Parameter object to be saved as metadata
308
- metadata: dict, optional
309
- will be saved as a new metadata attribute with name: key and value: dict value
310
-
311
- Returns
312
- -------
313
- group: group node
314
-
315
- See Also
316
- --------
317
- :py:meth:`add_group`
318
- """
319
- data_dim = enum_checker(DataDim, data_dim)
320
- metadata.update(settings=settings_as_xml)
321
- group = self.add_group(data_dim.name, 'data_dim', where, title, metadata)
322
- return group
323
-
324
- def add_incremental_group(self, group_type, where, title='', settings_as_xml='', metadata=dict([])):
325
- """
326
- Add a node in the h5 file tree of the group type with an increment in the given name
327
- Parameters
328
- ----------
329
- group_type: str or GroupType enum
330
- one of the possible values of **group_types**
331
- where: str or node
332
- parent node where to create the new group
333
- title: str
334
- node title
335
- settings_as_xml: str
336
- XML string containing Parameter representation
337
- metadata: dict
338
- extra metadata to be saved with this new group node
339
-
340
- Returns
341
- -------
342
- node: newly created group node
343
- """
344
- group_type = enum_checker(GroupType, group_type)
345
-
346
- nodes = [name for name in self.get_children(self.get_node(where))]
347
- nodes_tmp = []
348
- for node in nodes:
349
- if utils.capitalize(group_type.name) in node:
350
- nodes_tmp.append(node)
351
- nodes_tmp.sort()
352
- if len(nodes_tmp) == 0:
353
- ind_group = -1
354
- else:
355
- ind_group = int(nodes_tmp[-1][-3:])
356
- group = self.get_set_group(where, f'{utils.capitalize(group_type.name)}{ind_group + 1:03d}', title)
357
- self.set_attr(group, 'settings', settings_as_xml)
358
- if group_type.name.lower() != 'ch':
359
- self.set_attr(group, 'type', group_type.name.lower())
360
- else:
361
- self.set_attr(group, 'type', '')
362
- for metadat in metadata:
363
- self.set_attr(group, metadat, metadata[metadat])
364
- return group
365
-
366
- def add_act_group(self, where, title='', settings_as_xml='', metadata=dict([])):
367
- """
368
- Add a new group of type detector
369
- See Also
370
- -------
371
- add_incremental_group
372
- """
373
- group = self.add_incremental_group('actuator', where, title, settings_as_xml, metadata)
374
- return group
375
-
376
- def add_det_group(self, where, title='', settings_as_xml='', metadata=dict([])):
377
- """
378
- Add a new group of type detector
379
- See Also
380
- -------
381
- add_incremental_group
382
- """
383
- group = self.add_incremental_group('detector', where, title, settings_as_xml, metadata)
384
- return group
385
-
386
- def add_scan_group(self, where='/RawData', title='', settings_as_xml='', metadata=dict([])):
387
- """Add a new group of type scan
388
-
389
- At creation adds the attributes description and scan_done to be used elsewhere
390
-
391
- See Also
392
- -------
393
- add_incremental_group
394
- """
395
- metadata.update(dict(description='', scan_done=False))
396
- group = self.add_incremental_group(GroupType['scan'], where, title, settings_as_xml, metadata)
397
- return group
398
-
399
- def add_ch_group(self, where, title='', settings_as_xml='', metadata=dict([])):
400
- """
401
- Add a new group of type channel
402
- See Also
403
- -------
404
- add_incremental_group
405
- """
406
- group = self.add_incremental_group('ch', where, title, settings_as_xml, metadata)
407
- return group
408
-
409
-
410
- def add_move_group(self, where, title='', settings_as_xml='', metadata=dict([])):
411
- """
412
- Add a new group of type actuator
413
- See Also
414
- -------
415
- add_incremental_group
416
- """
417
- group = self.add_incremental_group('actuator', where, title, settings_as_xml, metadata)
418
- return group
419
-
420
- def show_file_content(self):
421
- win = QtWidgets.QMainWindow()
422
- if not self.isopen():
423
- if self.h5_file_path is not None:
424
- if self.h5_file_path.exists():
425
- self.analysis_prog = browsing.H5Browser(win, h5file_path=self.h5_file_path)
426
- else:
427
- logger.warning('The h5 file path has not been defined yet')
428
- else:
429
- logger.warning('The h5 file path has not been defined yet')
430
- else:
431
- self.flush()
432
- self.analysis_prog = browsing.H5Browser(win, h5file=self.h5file)
433
- win.show()
434
-
435
-
436
- class H5SaverBase(H5SaverLowLevel, ParameterManager):
437
- """Object containing all methods in order to save datas in a *hdf5 file* with a hierarchy compatible with
438
- the H5Browser. The saving parameters are contained within a **Parameter** object: self.settings that can be displayed
439
- on a UI using the widget self.settings_tree. At the creation of a new file, a node
440
- group named **Raw_datas** and represented by the attribute ``raw_group`` is created and set with a metadata attribute:
441
-
442
- * 'type' given by the **save_type** class parameter
443
-
444
- The root group of the file is then set with a few metadata:
445
-
446
- * 'pymodaq_version' the current pymodaq version, e.g. 1.6.2
447
- * 'file' the file name
448
- * 'date' the current date
449
- * 'time' the current time
450
-
451
- All datas will then be saved under this node in various groups
452
-
453
- See Also
454
- --------
455
- H5Browser
456
-
457
- Parameters
458
- ----------
459
- h5_file: pytables hdf5 file
460
- object used to save all datas and metadas
461
- h5_file_path: str or Path
462
- Signal signal represented by a float. Is emitted each time the hardware reached the target
463
- position within the epsilon precision (see comon_parameters variable)
464
- save_type: str
465
- an element of the enum module attribute SaveType
466
- * 'scan' is used for DAQScan module and should be used for similar application
467
- * 'detector' is used for DAQ_Viewer module and should be used for similar application
468
- * 'custom' should be used for customized applications
469
-
470
- Attributes
471
- ----------
472
-
473
- settings: Parameter
474
- Parameter instance (pyqtgraph) containing all settings (could be represented using the settings_tree widget)
475
-
476
- settings_tree: ParameterTree
477
- Widget representing as a Tree structure, all the settings defined in the class preamble variable ``params``
478
-
479
- """
480
- settings_name = 'h5saver_settings'
481
- params = [
482
- {'title': 'Save type:', 'name': 'save_type', 'type': 'list', 'limits': SaveType.names(), 'readonly': True},
483
- ] + dashboard_submodules_params + \
484
- [{'title': 'Backend:', 'name': 'backend', 'type': 'group', 'children': [
485
- {'title': 'Backend type:', 'name': 'backend_type', 'type': 'list', 'limits': backends_available,
486
- 'readonly': True},
487
- {'title': 'HSDS Server:', 'name': 'hsds_options', 'type': 'group', 'visible': False, 'children': [
488
- {'title': 'Endpoint:', 'name': 'endpoint', 'type': 'str',
489
- 'value': config('data_saving', 'hsds', 'root_url'), 'readonly': False},
490
- {'title': 'User:', 'name': 'user', 'type': 'str',
491
- 'value': config('data_saving', 'hsds', 'username'), 'readonly': False},
492
- {'title': 'password:', 'name': 'password', 'type': 'str',
493
- 'value': config('data_saving', 'hsds', 'pwd'), 'readonly': False},
494
- ]},
495
- ]},
496
-
497
- {'title': 'custom_name?:', 'name': 'custom_name', 'type': 'bool', 'default': False, 'value': False},
498
- {'title': 'show file content?', 'name': 'show_file', 'type': 'bool_push', 'default': False,
499
- 'value': False},
500
- {'title': 'Base path:', 'name': 'base_path', 'type': 'browsepath',
501
- 'value': config('data_saving', 'h5file', 'save_path'), 'filetype': False, 'readonly': True, },
502
- {'title': 'Base name:', 'name': 'base_name', 'type': 'str', 'value': 'Scan', 'readonly': True},
503
- {'title': 'Current scan:', 'name': 'current_scan_name', 'type': 'str', 'value': '', 'readonly': True},
504
- {'title': 'Current path:', 'name': 'current_scan_path', 'type': 'text',
505
- 'value': config('data_saving', 'h5file', 'save_path'), 'readonly': True, 'visible': False},
506
- {'title': 'h5file:', 'name': 'current_h5_file', 'type': 'text', 'value': '', 'readonly': True},
507
- {'title': 'New file', 'name': 'new_file', 'type': 'action'},
508
- {'title': 'Saving dynamic', 'name': 'dynamic', 'type': 'list',
509
- 'limits': config('data_saving', 'data_type', 'dynamics'),
510
- 'value': config('data_saving', 'data_type', 'dynamic')},
511
- {'title': 'Compression options:', 'name': 'compression_options', 'type': 'group', 'children': [
512
- {'title': 'Compression library:', 'name': 'h5comp_library', 'type': 'list', 'value': 'zlib',
513
- 'limits': ['zlib', 'gzip']},
514
- {'title': 'Compression level:', 'name': 'h5comp_level', 'type': 'int',
515
- 'value': config('data_saving', 'h5file', 'compression_level'), 'min': 0, 'max': 9},
516
- ]},
517
- ]
518
-
519
- def __init__(self, save_type='scan', backend='tables'):
520
- """
521
-
522
- Parameters
523
- ----------
524
- save_type (str): one of ['scan', 'detector', 'logger', 'custom']
525
- backend (str): either 'tables' for pytables backend, 'h5py' for h5py backends or 'h5pyd' for HSDS backend
526
-
527
- See Also
528
- --------
529
- https://github.com/HDFGroup/hsds
530
- """
531
- H5SaverLowLevel.__init__(self, save_type, backend)
532
- ParameterManager.__init__(self)
533
-
534
- self.current_scan_group = None
535
- self.current_scan_name = None
536
-
537
- self.settings.child('save_type').setValue(self.save_type.name)
538
-
539
- def show_settings(self, show=True):
540
- self.settings_tree.setVisible(show)
541
-
542
- def init_file(self, update_h5=False, custom_naming=False, addhoc_file_path=None, metadata=dict([])):
543
- """Initializes a new h5 file.
544
- Could set the h5_file attributes as:
545
-
546
- * a file with a name following a template if ``custom_naming`` is ``False`` and ``addhoc_file_path`` is ``None``
547
- * a file within a name set using a file dialog popup if ``custom_naming`` is ``True``
548
- * a file with a custom name if ``addhoc_file_path`` is a ``Path`` object or a path string
549
-
550
- Parameters
551
- ----------
552
- update_h5: bool
553
- create a new h5 file with name specified by other parameters
554
- if false try to open an existing file and will append new data to it
555
- custom_naming: bool
556
- if True, a selection file dialog opens to set a new file name
557
- addhoc_file_path: Path or str
558
- supplied name by the user for the new file
559
- metadata: dict
560
- dictionnary with pair of key, value that should be saved as attributes of the root group
561
- Returns
562
- -------
563
- update_h5: bool
564
- True if new file has been created, False otherwise
565
- """
566
- datetime_now = datetime.datetime.now()
567
- if addhoc_file_path is None:
568
- if not os.path.isdir(self.settings['base_path']):
569
- os.mkdir(self.settings['base_path'])
570
-
571
- # set the filename and path
572
- base_name = self.settings['base_name']
573
-
574
- if not custom_naming:
575
- custom_naming = self.settings['custom_name']
576
-
577
- if not custom_naming:
578
- scan_type = self.settings['save_type'] == 'scan'
579
- scan_path, current_scan_name, save_path = self.update_file_paths(update_h5)
580
- self.current_scan_name = current_scan_name
581
- self.settings.child('current_scan_name').setValue(current_scan_name)
582
- self.settings.child('current_scan_path').setValue(str(scan_path))
583
-
584
- if not scan_type:
585
- self.h5_file_path = save_path.parent # will remove the dataset part used for DAQ_scan datas
586
- self.h5_file_name = base_name + datetime_now.strftime('_%Y%m%d_%H_%M_%S.h5')
587
- else:
588
- self.h5_file_name = save_path.name + ".h5"
589
- self.h5_file_path = save_path.parent
590
-
591
- else:
592
- self.h5_file_name = select_file(start_path=base_name, save=True, ext='h5')
593
- self.h5_file_path = self.h5_file_name.parent
594
-
595
- else:
596
- if isinstance(addhoc_file_path, str):
597
- addhoc_file_path = Path(addhoc_file_path)
598
- self.h5_file_path = addhoc_file_path.parent
599
- self.h5_file_name = addhoc_file_path.name
600
-
601
- fullpathname = self.h5_file_path.joinpath(self.h5_file_name)
602
- self.settings.child('current_h5_file').setValue(str(fullpathname))
603
-
604
- super().init_file(fullpathname, new_file=update_h5, metadata=metadata)
605
-
606
- self.get_set_logger(self.raw_group)
607
-
608
- return update_h5
609
-
610
- def update_file_paths(self, update_h5=False):
611
- """
612
-
613
- Parameters
614
- ----------
615
- update_h5: bool
616
- if True, will increment the file name and eventually the current scan index
617
- if False, get the current scan index in the h5 file
618
-
619
- Returns
620
- -------
621
- scan_path: Path
622
- current_filename: str
623
- dataset_path: Path
624
-
625
- """
626
-
627
- try:
628
- # set the filename and path
629
- base_path = self.settings['base_path']
630
- base_name = self.settings['base_name']
631
- current_scan = self.settings['current_scan_name']
632
- scan_type = self.settings['save_type'] == 'scan'
633
- ind_dataset = None
634
- if current_scan == '' or update_h5:
635
- next_scan_index = 0
636
- update_h5 = True # just started the main program so one should create a new h5
637
- self.file_loaded = False
638
- else:
639
- next_scan_index = self.get_scan_index()
640
- if self.file_loaded:
641
- ind_dataset = int(os.path.splitext(self.h5_file_name)[0][-3:])
642
- try:
643
- curr_date = datetime.date.fromisoformat(self.get_attr(self.root(), 'date'))
644
- except ValueError:
645
- curr_date = parser.parse(self.get_attr(self.root(), 'date')).date()
646
- else:
647
- curr_date = datetime.date.today()
648
-
649
- scan_path, current_filename, dataset_path = self.set_current_scan_path(base_path, base_name, update_h5,
650
- next_scan_index,
651
- create_dataset_folder=False,
652
- curr_date=curr_date,
653
- ind_dataset=ind_dataset)
654
- self.settings.child('current_scan_path').setValue(str(dataset_path))
655
-
656
- return scan_path, current_filename, dataset_path
657
-
658
- except Exception as e:
659
- logger.exception(str(e))
660
-
661
- @classmethod
662
- def find_part_in_path_and_subpath(cls, base_dir, part='', create=False, increment=True):
663
- """
664
- Find path from part time.
665
-
666
- =============== ============ =============================================
667
- **Parameters** **Type** **Description**
668
- *base_dir* Path object The directory to browse
669
- *part* string The date of the directory to find/create
670
- *create* boolean Indicate the creation flag of the directory
671
- =============== ============ =============================================
672
-
673
- Returns
674
- -------
675
- Path object
676
- found path from part
677
- """
678
- found_path = None
679
- if part in base_dir.parts: # check if current year is in the given base path
680
- if base_dir.name == part:
681
- found_path = base_dir
682
- else:
683
- for ind in range(len(base_dir.parts)):
684
- tmp_path = base_dir.parents[ind]
685
- if tmp_path.name == part:
686
- found_path = base_dir.parents[ind]
687
- break
688
- else: # if not check if year is in the subfolders
689
- subfolders_year_name = [x.name for x in base_dir.iterdir() if x.is_dir()]
690
- subfolders_found_path = [x for x in base_dir.iterdir() if x.is_dir()]
691
- if part not in subfolders_year_name:
692
- if increment:
693
- found_path = base_dir.joinpath(part)
694
- else:
695
- found_path = base_dir
696
- if create:
697
- found_path.mkdir()
698
- else:
699
- ind_path = subfolders_year_name.index(part)
700
- found_path = subfolders_found_path[ind_path]
701
- return found_path
702
-
703
- @classmethod
704
- def set_current_scan_path(cls, base_dir, base_name='Scan', update_h5=False, next_scan_index=0,
705
- create_scan_folder=False,
706
- create_dataset_folder=True, curr_date=None, ind_dataset=None):
707
- """
708
-
709
- Parameters
710
- ----------
711
- base_dir
712
- base_name
713
- update_h5
714
- next_scan_index
715
- create_scan_folder
716
- create_dataset_folder
717
-
718
- Returns
719
- -------
720
-
721
- """
722
- base_dir = Path(base_dir)
723
- if curr_date is None:
724
- curr_date = datetime.date.today()
725
-
726
- year_path = cls.find_part_in_path_and_subpath(base_dir, part=str(curr_date.year),
727
- create=True) # create directory of the year if it doen't exist and return it
728
- day_path = cls.find_part_in_path_and_subpath(year_path, part=curr_date.strftime('%Y%m%d'),
729
- create=True) # create directory of the day if it doen't exist and return it
730
- dataset_base_name = curr_date.strftime('Dataset_%Y%m%d')
731
- dataset_paths = sorted([path for path in day_path.glob(dataset_base_name + "*"+".h5") if path.is_file()])
732
-
733
- if ind_dataset is None:
734
- if dataset_paths == []:
735
-
736
- ind_dataset = 0
737
- else:
738
- if update_h5:
739
- ind_dataset = int(dataset_paths[-1].stem.partition(dataset_base_name + "_")[2]) + 1
740
- else:
741
- ind_dataset = int(dataset_paths[-1].stem.partition(dataset_base_name + "_")[2])
742
-
743
- dataset_path = cls.find_part_in_path_and_subpath(day_path,
744
- part=dataset_base_name + "_{:03d}".format(ind_dataset),
745
- create=False, increment=True)
746
- scan_paths = sorted([path for path in dataset_path.glob(base_name + '*') if path.is_dir()])
747
- ind_scan = next_scan_index
748
- return dataset_path, base_name + '{:03d}'.format(ind_scan), dataset_path
749
-
750
- def get_last_scan(self):
751
- """Gets the last scan node within the h5_file and under the **raw_group**
752
-
753
- Returns
754
- -------
755
- scan_group: pytables group or None
756
-
757
-
758
- """
759
- return self.get_last_group(self.raw_group, GroupType['scan'])
760
-
761
- def get_scan_groups(self):
762
- return self.get_groups(self.raw_group, GroupType['scan'])
763
-
764
- def get_scan_index(self):
765
- """ return the scan group index in the "scan templating": Scan000, Scan001 as an integer
766
- """
767
-
768
- last_scan = self.get_last_scan()
769
- return int(last_scan.name[4:]) if last_scan is not None else 0
770
-
771
- def load_file(self, base_path=None, file_path=None):
772
- """Opens a file dialog to select a h5file saved on disk to be used
773
-
774
- Parameters
775
- ----------
776
- base_path
777
- file_path
778
-
779
- See Also
780
- --------
781
- :py:meth:`init_file`
782
-
783
- """
784
- if base_path is None:
785
- base_path = self.settings.child('base_path').value()
786
- if not os.path.isdir(base_path):
787
- base_path = None
788
-
789
- if file_path is None:
790
- file_path = select_file(base_path, save=False, ext='h5')
791
-
792
- if not (file_path is None or file_path == ''):
793
- if not isinstance(file_path, Path):
794
- file_path = Path(file_path)
795
-
796
- if 'h5' not in file_path.suffix:
797
- raise IOError('Invalid file type, should be a h5 file')
798
-
799
- self.init_file(addhoc_file_path=file_path)
800
- self.file_loaded = True
801
-
802
- def save_file(self, filename=None):
803
- if filename is None:
804
- filename = select_file(None, save=True, ext='h5')
805
- if filename != '':
806
- super().save_file_as(filename)
807
-
808
- def value_changed(self, param):
809
- if param.name() == 'show_file':
810
- if param.value():
811
- param.setValue(False)
812
- self.show_file_content()
813
-
814
- elif param.name() == 'base_path':
815
- try:
816
- if not os.path.isdir(param.value()):
817
- os.mkdir(param.value())
818
- except Exception as e:
819
- self.update_status(f"The base path couldn't be set, please check your options: {str(e)}")
820
-
821
- elif param.name() in putils.iter_children(self.settings.child('compression_options'), []):
822
- compression = self.settings.child('compression_options', 'h5comp_library').value()
823
- compression_opts = self.settings.child('compression_options', 'h5comp_level').value()
824
- self.define_compression(compression, compression_opts)
825
-
826
- def update_status(self, status):
827
- logger.warning(status)
828
-
829
-
830
- class H5Saver(H5SaverBase, QObject):
831
- """
832
- status_sig: Signal
833
- emits a signal of type Threadcommand in order to senf log information to a main UI
834
- new_file_sig: Signal
835
- emits a boolean signal to let the program know when the user pressed the new file button on the UI
836
- """
837
-
838
- status_sig = Signal(utils.ThreadCommand)
839
- new_file_sig = Signal(bool)
840
-
841
- def __init__(self, *args, **kwargs):
842
- """
843
-
844
- Parameters
845
- ----------
846
- args
847
- kwargs
848
- """
849
- QObject.__init__(self)
850
- H5SaverBase.__init__(self, *args, **kwargs)
851
-
852
- self.settings.child('new_file').sigActivated.connect(lambda: self.emit_new_file(True))
853
-
854
- def close(self):
855
- self.close_file()
856
-
857
- def emit_new_file(self, status):
858
- """Emits the new_file_sig
859
-
860
- Parameters
861
- ----------
862
- status: bool
863
- emits True if a new file has been asked by the user pressing the new file button on the UI
864
- """
865
- self.new_file_sig.emit(status)
866
-