pymodaq 4.2.4__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 +28 -12
  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 +164 -115
  11. pymodaq/examples/custom_app.py +13 -16
  12. pymodaq/examples/custom_viewer.py +6 -6
  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 -708
  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.4.dist-info → pymodaq-5.0.0.dist-info}/METADATA +5 -3
  76. pymodaq-5.0.0.dist-info/RECORD +123 -0
  77. pymodaq/post_treatment/process_to_scalar.py +0 -263
  78. pymodaq/resources/QtDesigner_Ressources/Icon_Library/1d.png +0 -0
  79. pymodaq/resources/QtDesigner_Ressources/Icon_Library/2d.png +0 -0
  80. pymodaq/resources/QtDesigner_Ressources/Icon_Library/3d.png +0 -0
  81. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Add2.png +0 -0
  82. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Add_Step.png +0 -0
  83. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Approve.png +0 -0
  84. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Approve_All.png +0 -0
  85. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Browse_Dir_Path.png +0 -0
  86. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Calculator.png +0 -0
  87. pymodaq/resources/QtDesigner_Ressources/Icon_Library/ChnGroup.png +0 -0
  88. pymodaq/resources/QtDesigner_Ressources/Icon_Library/ChnNum.png +0 -0
  89. pymodaq/resources/QtDesigner_Ressources/Icon_Library/ChnText.png +0 -0
  90. pymodaq/resources/QtDesigner_Ressources/Icon_Library/ChnTime.png +0 -0
  91. pymodaq/resources/QtDesigner_Ressources/Icon_Library/ChnWave.png +0 -0
  92. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Close3.png +0 -0
  93. pymodaq/resources/QtDesigner_Ressources/Icon_Library/CollapseAll.png +0 -0
  94. pymodaq/resources/QtDesigner_Ressources/Icon_Library/CollapseAll_32.png +0 -0
  95. pymodaq/resources/QtDesigner_Ressources/Icon_Library/ColorPicker.png +0 -0
  96. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Contract.png +0 -0
  97. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Create.png +0 -0
  98. pymodaq/resources/QtDesigner_Ressources/Icon_Library/DeleteLayer.png +0 -0
  99. pymodaq/resources/QtDesigner_Ressources/Icon_Library/EditOpen.png +0 -0
  100. pymodaq/resources/QtDesigner_Ressources/Icon_Library/EditRedo.png +0 -0
  101. pymodaq/resources/QtDesigner_Ressources/Icon_Library/EditUndo.png +0 -0
  102. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Ellipse.png +0 -0
  103. pymodaq/resources/QtDesigner_Ressources/Icon_Library/EllipseFilled.png +0 -0
  104. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Error.png +0 -0
  105. pymodaq/resources/QtDesigner_Ressources/Icon_Library/ErrorMessage.png +0 -0
  106. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Error_16.png +0 -0
  107. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Exit.png +0 -0
  108. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Expand.png +0 -0
  109. pymodaq/resources/QtDesigner_Ressources/Icon_Library/ExpandAll.png +0 -0
  110. pymodaq/resources/QtDesigner_Ressources/Icon_Library/ExpandAll_32.png +0 -0
  111. pymodaq/resources/QtDesigner_Ressources/Icon_Library/FFT.png +0 -0
  112. pymodaq/resources/QtDesigner_Ressources/Icon_Library/HLM.ico +0 -0
  113. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Help.png +0 -0
  114. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Help_32.png +0 -0
  115. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Histogram.png +0 -0
  116. pymodaq/resources/QtDesigner_Ressources/Icon_Library/LUT_LookUpTable.png +0 -0
  117. pymodaq/resources/QtDesigner_Ressources/Icon_Library/MagnifyingGlass.png +0 -0
  118. pymodaq/resources/QtDesigner_Ressources/Icon_Library/MagnifyingGlass_24.png +0 -0
  119. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Marker.png +0 -0
  120. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Math.png +0 -0
  121. pymodaq/resources/QtDesigner_Ressources/Icon_Library/MeasurementStudio_32.png +0 -0
  122. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Move.png +0 -0
  123. pymodaq/resources/QtDesigner_Ressources/Icon_Library/MoveDown.png +0 -0
  124. pymodaq/resources/QtDesigner_Ressources/Icon_Library/MoveUp.png +0 -0
  125. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Multiply.png +0 -0
  126. pymodaq/resources/QtDesigner_Ressources/Icon_Library/NewFile.png +0 -0
  127. pymodaq/resources/QtDesigner_Ressources/Icon_Library/NewLayer.png +0 -0
  128. pymodaq/resources/QtDesigner_Ressources/Icon_Library/New_File.png +0 -0
  129. pymodaq/resources/QtDesigner_Ressources/Icon_Library/New_Folder.png +0 -0
  130. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Open.png +0 -0
  131. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Open_1D.png +0 -0
  132. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Open_2D.png +0 -0
  133. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Open_File.png +0 -0
  134. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Open_File_32.png +0 -0
  135. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Open_sim.png +0 -0
  136. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Options.png +0 -0
  137. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Oscilloscope.png +0 -0
  138. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Oscilloscope_16.png +0 -0
  139. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Pass.png +0 -0
  140. pymodaq/resources/QtDesigner_Ressources/Icon_Library/RGB.png +0 -0
  141. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Rectangle.png +0 -0
  142. pymodaq/resources/QtDesigner_Ressources/Icon_Library/RectangleFilled.png +0 -0
  143. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Redo.png +0 -0
  144. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Refresh.png +0 -0
  145. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Refresh2.png +0 -0
  146. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Refresh_32.png +0 -0
  147. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Region.png +0 -0
  148. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Rendezvous.png +0 -0
  149. pymodaq/resources/QtDesigner_Ressources/Icon_Library/SELECT.png +0 -0
  150. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Save.png +0 -0
  151. pymodaq/resources/QtDesigner_Ressources/Icon_Library/SaveAll.png +0 -0
  152. pymodaq/resources/QtDesigner_Ressources/Icon_Library/SaveAll_32.png +0 -0
  153. pymodaq/resources/QtDesigner_Ressources/Icon_Library/SaveAs.png +0 -0
  154. pymodaq/resources/QtDesigner_Ressources/Icon_Library/SaveAs_32.png +0 -0
  155. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Save_24.png +0 -0
  156. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Save_32.png +0 -0
  157. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Search.png +0 -0
  158. pymodaq/resources/QtDesigner_Ressources/Icon_Library/SelectPolygon.png +0 -0
  159. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Select_24.png +0 -0
  160. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Settings.png +0 -0
  161. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Snap&Save.png +0 -0
  162. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Snapshot.png +0 -0
  163. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Snapshot2.png +0 -0
  164. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Snapshot2_16.png +0 -0
  165. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Snapshot2_32.png +0 -0
  166. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Spreadsheet.png +0 -0
  167. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Statistics.png +0 -0
  168. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Statistics2.png +0 -0
  169. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Status.png +0 -0
  170. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Subtract.png +0 -0
  171. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Vision.png +0 -0
  172. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Volts.png +0 -0
  173. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Wait2.png +0 -0
  174. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Zoom_1_1.png +0 -0
  175. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Zoom_in.png +0 -0
  176. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Zoom_out.png +0 -0
  177. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Zoom_to_Selection.png +0 -0
  178. pymodaq/resources/QtDesigner_Ressources/Icon_Library/abort.png +0 -0
  179. pymodaq/resources/QtDesigner_Ressources/Icon_Library/advanced2.png +0 -0
  180. pymodaq/resources/QtDesigner_Ressources/Icon_Library/autoscale.png +0 -0
  181. pymodaq/resources/QtDesigner_Ressources/Icon_Library/b_icon.png +0 -0
  182. pymodaq/resources/QtDesigner_Ressources/Icon_Library/back.png +0 -0
  183. pymodaq/resources/QtDesigner_Ressources/Icon_Library/bg_icon.png +0 -0
  184. pymodaq/resources/QtDesigner_Ressources/Icon_Library/camera.png +0 -0
  185. pymodaq/resources/QtDesigner_Ressources/Icon_Library/camera_snap.png +0 -0
  186. pymodaq/resources/QtDesigner_Ressources/Icon_Library/cartesian.png +0 -0
  187. pymodaq/resources/QtDesigner_Ressources/Icon_Library/clear2.png +0 -0
  188. pymodaq/resources/QtDesigner_Ressources/Icon_Library/clear_ROI.png +0 -0
  189. pymodaq/resources/QtDesigner_Ressources/Icon_Library/close2.png +0 -0
  190. pymodaq/resources/QtDesigner_Ressources/Icon_Library/cluster2.png +0 -0
  191. pymodaq/resources/QtDesigner_Ressources/Icon_Library/color.png +0 -0
  192. pymodaq/resources/QtDesigner_Ressources/Icon_Library/color2.png +0 -0
  193. pymodaq/resources/QtDesigner_Ressources/Icon_Library/continuous.png +0 -0
  194. pymodaq/resources/QtDesigner_Ressources/Icon_Library/data.png +0 -0
  195. pymodaq/resources/QtDesigner_Ressources/Icon_Library/delay.png +0 -0
  196. pymodaq/resources/QtDesigner_Ressources/Icon_Library/download.png +0 -0
  197. pymodaq/resources/QtDesigner_Ressources/Icon_Library/download2.png +0 -0
  198. pymodaq/resources/QtDesigner_Ressources/Icon_Library/error2.png +0 -0
  199. pymodaq/resources/QtDesigner_Ressources/Icon_Library/ethernet.png +0 -0
  200. pymodaq/resources/QtDesigner_Ressources/Icon_Library/exit2.png +0 -0
  201. pymodaq/resources/QtDesigner_Ressources/Icon_Library/fan.png +0 -0
  202. pymodaq/resources/QtDesigner_Ressources/Icon_Library/filter2.png +0 -0
  203. pymodaq/resources/QtDesigner_Ressources/Icon_Library/g_icon.png +0 -0
  204. pymodaq/resources/QtDesigner_Ressources/Icon_Library/gear2.png +0 -0
  205. pymodaq/resources/QtDesigner_Ressources/Icon_Library/go_to.png +0 -0
  206. pymodaq/resources/QtDesigner_Ressources/Icon_Library/go_to_1.png +0 -0
  207. pymodaq/resources/QtDesigner_Ressources/Icon_Library/go_to_2.png +0 -0
  208. pymodaq/resources/QtDesigner_Ressources/Icon_Library/grab.png +0 -0
  209. pymodaq/resources/QtDesigner_Ressources/Icon_Library/graph.png +0 -0
  210. pymodaq/resources/QtDesigner_Ressources/Icon_Library/greenLight2.png +0 -0
  211. pymodaq/resources/QtDesigner_Ressources/Icon_Library/greenLight2_32.png +0 -0
  212. pymodaq/resources/QtDesigner_Ressources/Icon_Library/green_light.png +0 -0
  213. pymodaq/resources/QtDesigner_Ressources/Icon_Library/grey_icon.png +0 -0
  214. pymodaq/resources/QtDesigner_Ressources/Icon_Library/greyscale.png +0 -0
  215. pymodaq/resources/QtDesigner_Ressources/Icon_Library/help1.png +0 -0
  216. pymodaq/resources/QtDesigner_Ressources/Icon_Library/help1_32.png +0 -0
  217. pymodaq/resources/QtDesigner_Ressources/Icon_Library/home2.png +0 -0
  218. pymodaq/resources/QtDesigner_Ressources/Icon_Library/information2.png +0 -0
  219. pymodaq/resources/QtDesigner_Ressources/Icon_Library/ini.png +0 -0
  220. pymodaq/resources/QtDesigner_Ressources/Icon_Library/integrator.png +0 -0
  221. pymodaq/resources/QtDesigner_Ressources/Icon_Library/joystick.png +0 -0
  222. pymodaq/resources/QtDesigner_Ressources/Icon_Library/light_green.png +0 -0
  223. pymodaq/resources/QtDesigner_Ressources/Icon_Library/light_green_16.png +0 -0
  224. pymodaq/resources/QtDesigner_Ressources/Icon_Library/light_red.png +0 -0
  225. pymodaq/resources/QtDesigner_Ressources/Icon_Library/light_red_16.png +0 -0
  226. pymodaq/resources/QtDesigner_Ressources/Icon_Library/light_yellow.png +0 -0
  227. pymodaq/resources/QtDesigner_Ressources/Icon_Library/light_yellow_16.png +0 -0
  228. pymodaq/resources/QtDesigner_Ressources/Icon_Library/limiter.png +0 -0
  229. pymodaq/resources/QtDesigner_Ressources/Icon_Library/load_ROI.png +0 -0
  230. pymodaq/resources/QtDesigner_Ressources/Icon_Library/meshPlot.png +0 -0
  231. pymodaq/resources/QtDesigner_Ressources/Icon_Library/meter.png +0 -0
  232. pymodaq/resources/QtDesigner_Ressources/Icon_Library/meter2.png +0 -0
  233. pymodaq/resources/QtDesigner_Ressources/Icon_Library/meter_32.png +0 -0
  234. pymodaq/resources/QtDesigner_Ressources/Icon_Library/move_contour.png +0 -0
  235. pymodaq/resources/QtDesigner_Ressources/Icon_Library/move_straight_line.png +0 -0
  236. pymodaq/resources/QtDesigner_Ressources/Icon_Library/movie.png +0 -0
  237. pymodaq/resources/QtDesigner_Ressources/Icon_Library/multi_point.png +0 -0
  238. pymodaq/resources/QtDesigner_Ressources/Icon_Library/multiplexer.png +0 -0
  239. pymodaq/resources/QtDesigner_Ressources/Icon_Library/new.png +0 -0
  240. pymodaq/resources/QtDesigner_Ressources/Icon_Library/openArrow.png +0 -0
  241. pymodaq/resources/QtDesigner_Ressources/Icon_Library/openTree.png +0 -0
  242. pymodaq/resources/QtDesigner_Ressources/Icon_Library/oscilloscope2.png +0 -0
  243. pymodaq/resources/QtDesigner_Ressources/Icon_Library/oscilloscope3.png +0 -0
  244. pymodaq/resources/QtDesigner_Ressources/Icon_Library/overlay.png +0 -0
  245. pymodaq/resources/QtDesigner_Ressources/Icon_Library/pass2.png +0 -0
  246. pymodaq/resources/QtDesigner_Ressources/Icon_Library/pass2_16.png +0 -0
  247. pymodaq/resources/QtDesigner_Ressources/Icon_Library/pass_32.png +0 -0
  248. pymodaq/resources/QtDesigner_Ressources/Icon_Library/pause.png +0 -0
  249. pymodaq/resources/QtDesigner_Ressources/Icon_Library/permute.png +0 -0
  250. pymodaq/resources/QtDesigner_Ressources/Icon_Library/phase.png +0 -0
  251. pymodaq/resources/QtDesigner_Ressources/Icon_Library/play.png +0 -0
  252. pymodaq/resources/QtDesigner_Ressources/Icon_Library/polar.png +0 -0
  253. pymodaq/resources/QtDesigner_Ressources/Icon_Library/pole_zero.png +0 -0
  254. pymodaq/resources/QtDesigner_Ressources/Icon_Library/powerMeter.png +0 -0
  255. pymodaq/resources/QtDesigner_Ressources/Icon_Library/powerSwitch.png +0 -0
  256. pymodaq/resources/QtDesigner_Ressources/Icon_Library/powerSwitch_16.png +0 -0
  257. pymodaq/resources/QtDesigner_Ressources/Icon_Library/print2.png +0 -0
  258. pymodaq/resources/QtDesigner_Ressources/Icon_Library/print2_32.png +0 -0
  259. pymodaq/resources/QtDesigner_Ressources/Icon_Library/properties.png +0 -0
  260. pymodaq/resources/QtDesigner_Ressources/Icon_Library/r_icon.png +0 -0
  261. pymodaq/resources/QtDesigner_Ressources/Icon_Library/radiocontrolbutton.png +0 -0
  262. pymodaq/resources/QtDesigner_Ressources/Icon_Library/read2.png +0 -0
  263. pymodaq/resources/QtDesigner_Ressources/Icon_Library/red_light.png +0 -0
  264. pymodaq/resources/QtDesigner_Ressources/Icon_Library/remove.png +0 -0
  265. pymodaq/resources/QtDesigner_Ressources/Icon_Library/reset.png +0 -0
  266. pymodaq/resources/QtDesigner_Ressources/Icon_Library/rgb_icon.png +0 -0
  267. pymodaq/resources/QtDesigner_Ressources/Icon_Library/robot.png +0 -0
  268. pymodaq/resources/QtDesigner_Ressources/Icon_Library/rotation2.png +0 -0
  269. pymodaq/resources/QtDesigner_Ressources/Icon_Library/run2.png +0 -0
  270. pymodaq/resources/QtDesigner_Ressources/Icon_Library/run_all.png +0 -0
  271. pymodaq/resources/QtDesigner_Ressources/Icon_Library/saturation.png +0 -0
  272. pymodaq/resources/QtDesigner_Ressources/Icon_Library/saveTree.png +0 -0
  273. pymodaq/resources/QtDesigner_Ressources/Icon_Library/save_ROI.png +0 -0
  274. pymodaq/resources/QtDesigner_Ressources/Icon_Library/scale_horizontally.png +0 -0
  275. pymodaq/resources/QtDesigner_Ressources/Icon_Library/scale_vertically.png +0 -0
  276. pymodaq/resources/QtDesigner_Ressources/Icon_Library/search2.png +0 -0
  277. pymodaq/resources/QtDesigner_Ressources/Icon_Library/select2.png +0 -0
  278. pymodaq/resources/QtDesigner_Ressources/Icon_Library/select_all.png +0 -0
  279. pymodaq/resources/QtDesigner_Ressources/Icon_Library/select_all2.png +0 -0
  280. pymodaq/resources/QtDesigner_Ressources/Icon_Library/select_none.png +0 -0
  281. pymodaq/resources/QtDesigner_Ressources/Icon_Library/sequence.png +0 -0
  282. pymodaq/resources/QtDesigner_Ressources/Icon_Library/sequence2.png +0 -0
  283. pymodaq/resources/QtDesigner_Ressources/Icon_Library/snap.png +0 -0
  284. pymodaq/resources/QtDesigner_Ressources/Icon_Library/sort_ascend.png +0 -0
  285. pymodaq/resources/QtDesigner_Ressources/Icon_Library/spectrumAnalyzer.png +0 -0
  286. pymodaq/resources/QtDesigner_Ressources/Icon_Library/start.png +0 -0
  287. pymodaq/resources/QtDesigner_Ressources/Icon_Library/status_cancelled.png +0 -0
  288. pymodaq/resources/QtDesigner_Ressources/Icon_Library/stop.png +0 -0
  289. pymodaq/resources/QtDesigner_Ressources/Icon_Library/stop2.png +0 -0
  290. pymodaq/resources/QtDesigner_Ressources/Icon_Library/stop3.png +0 -0
  291. pymodaq/resources/QtDesigner_Ressources/Icon_Library/stop_all.png +0 -0
  292. pymodaq/resources/QtDesigner_Ressources/Icon_Library/sum.png +0 -0
  293. pymodaq/resources/QtDesigner_Ressources/Icon_Library/surfacePlot.png +0 -0
  294. pymodaq/resources/QtDesigner_Ressources/Icon_Library/tree.png +0 -0
  295. pymodaq/resources/QtDesigner_Ressources/Icon_Library/updateTree.png +0 -0
  296. pymodaq/resources/QtDesigner_Ressources/Icon_Library/utility2.png +0 -0
  297. pymodaq/resources/QtDesigner_Ressources/Icon_Library/utility_small.png +0 -0
  298. pymodaq/resources/QtDesigner_Ressources/Icon_Library/vector.png +0 -0
  299. pymodaq/resources/QtDesigner_Ressources/Icon_Library/verify.png +0 -0
  300. pymodaq/resources/QtDesigner_Ressources/Icon_Library/video.png +0 -0
  301. pymodaq/resources/QtDesigner_Ressources/Icon_Library/wait.png +0 -0
  302. pymodaq/resources/QtDesigner_Ressources/Icon_Library/waterfallPlot.png +0 -0
  303. pymodaq/resources/QtDesigner_Ressources/Icon_Library/watershed.png +0 -0
  304. pymodaq/resources/QtDesigner_Ressources/Icon_Library/yellow_light.png +0 -0
  305. pymodaq/resources/QtDesigner_Ressources/Icon_Library/zip_file.png +0 -0
  306. pymodaq/resources/QtDesigner_Ressources/Icon_Library/zoomAuto.png +0 -0
  307. pymodaq/resources/QtDesigner_Ressources/Icon_Library/zoomReset.png +0 -0
  308. pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources.bat +0 -2
  309. pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources.qrc +0 -234
  310. pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources_rc.py +0 -127150
  311. pymodaq/resources/QtDesigner_Ressources/icons.svg +0 -142
  312. pymodaq/resources/VERSION +0 -1
  313. pymodaq/resources/config_template.toml +0 -94
  314. pymodaq/resources/triangulation_data.npy +0 -0
  315. pymodaq/utils/abstract/__init__.py +0 -48
  316. pymodaq/utils/db/__init__.py +0 -0
  317. pymodaq/utils/db/db_logger/__init__.py +0 -0
  318. pymodaq/utils/enums.py +0 -76
  319. pymodaq/utils/factory.py +0 -82
  320. pymodaq/utils/gui_utils/custom_app.py +0 -133
  321. pymodaq/utils/gui_utils/dock.py +0 -107
  322. pymodaq/utils/gui_utils/file_io.py +0 -93
  323. pymodaq/utils/gui_utils/layout.py +0 -34
  324. pymodaq/utils/gui_utils/list_picker.py +0 -38
  325. pymodaq/utils/gui_utils/widgets/__init__.py +0 -5
  326. pymodaq/utils/gui_utils/widgets/label.py +0 -24
  327. pymodaq/utils/gui_utils/widgets/lcd.py +0 -111
  328. pymodaq/utils/gui_utils/widgets/push.py +0 -149
  329. pymodaq/utils/gui_utils/widgets/qled.py +0 -62
  330. pymodaq/utils/gui_utils/widgets/spinbox.py +0 -24
  331. pymodaq/utils/gui_utils/widgets/table.py +0 -263
  332. pymodaq/utils/gui_utils/widgets/tree_layout.py +0 -188
  333. pymodaq/utils/gui_utils/widgets/tree_toml.py +0 -102
  334. pymodaq/utils/h5modules/backends.py +0 -1022
  335. pymodaq/utils/h5modules/browsing.py +0 -625
  336. pymodaq/utils/h5modules/data_saving.py +0 -1105
  337. pymodaq/utils/h5modules/exporter.py +0 -119
  338. pymodaq/utils/h5modules/exporters/__init__.py +0 -0
  339. pymodaq/utils/h5modules/exporters/base.py +0 -111
  340. pymodaq/utils/h5modules/exporters/flimj.py +0 -63
  341. pymodaq/utils/h5modules/exporters/hyperspy.py +0 -143
  342. pymodaq/utils/h5modules/saving.py +0 -866
  343. pymodaq/utils/h5modules/utils.py +0 -115
  344. pymodaq/utils/managers/action_manager.py +0 -489
  345. pymodaq/utils/managers/parameter_manager.py +0 -282
  346. pymodaq/utils/managers/roi_manager.py +0 -726
  347. pymodaq/utils/messenger.py +0 -66
  348. pymodaq/utils/parameter/ioxml.py +0 -542
  349. pymodaq/utils/parameter/pymodaq_ptypes/__init__.py +0 -38
  350. pymodaq/utils/parameter/pymodaq_ptypes/bool.py +0 -31
  351. pymodaq/utils/parameter/pymodaq_ptypes/date.py +0 -126
  352. pymodaq/utils/parameter/pymodaq_ptypes/filedir.py +0 -143
  353. pymodaq/utils/parameter/pymodaq_ptypes/itemselect.py +0 -265
  354. pymodaq/utils/parameter/pymodaq_ptypes/led.py +0 -44
  355. pymodaq/utils/parameter/pymodaq_ptypes/list.py +0 -150
  356. pymodaq/utils/parameter/pymodaq_ptypes/numeric.py +0 -18
  357. pymodaq/utils/parameter/pymodaq_ptypes/pixmap.py +0 -175
  358. pymodaq/utils/parameter/pymodaq_ptypes/slide.py +0 -145
  359. pymodaq/utils/parameter/pymodaq_ptypes/table.py +0 -135
  360. pymodaq/utils/parameter/pymodaq_ptypes/tableview.py +0 -149
  361. pymodaq/utils/parameter/pymodaq_ptypes/text.py +0 -142
  362. pymodaq/utils/plotting/__init__.py +0 -0
  363. pymodaq/utils/plotting/data_viewers/__init__.py +0 -10
  364. pymodaq/utils/plotting/data_viewers/base.py +0 -286
  365. pymodaq/utils/plotting/data_viewers/viewer.py +0 -274
  366. pymodaq/utils/plotting/data_viewers/viewer0D.py +0 -298
  367. pymodaq/utils/plotting/data_viewers/viewer1D.py +0 -826
  368. pymodaq/utils/plotting/data_viewers/viewer1Dbasic.py +0 -231
  369. pymodaq/utils/plotting/data_viewers/viewer2D.py +0 -1118
  370. pymodaq/utils/plotting/data_viewers/viewer2D_basic.py +0 -146
  371. pymodaq/utils/plotting/data_viewers/viewerND.py +0 -800
  372. pymodaq/utils/plotting/gant_chart.py +0 -123
  373. pymodaq/utils/plotting/image_viewer.py +0 -97
  374. pymodaq/utils/plotting/items/__init__.py +0 -0
  375. pymodaq/utils/plotting/items/axis_scaled.py +0 -93
  376. pymodaq/utils/plotting/items/crosshair.py +0 -94
  377. pymodaq/utils/plotting/items/image.py +0 -388
  378. pymodaq/utils/plotting/navigator.py +0 -353
  379. pymodaq/utils/plotting/plotter/plotter.py +0 -94
  380. pymodaq/utils/plotting/plotter/plotters/__init__.py +0 -0
  381. pymodaq/utils/plotting/plotter/plotters/matplotlib_plotters.py +0 -134
  382. pymodaq/utils/plotting/plotter/plotters/qt_plotters.py +0 -78
  383. pymodaq/utils/plotting/utils/__init__.py +0 -0
  384. pymodaq/utils/plotting/utils/axes_viewer.py +0 -88
  385. pymodaq/utils/plotting/utils/filter.py +0 -585
  386. pymodaq/utils/plotting/utils/lineout.py +0 -226
  387. pymodaq/utils/plotting/utils/plot_utils.py +0 -579
  388. pymodaq/utils/plotting/utils/signalND.py +0 -1347
  389. pymodaq/utils/plotting/widgets.py +0 -76
  390. pymodaq/utils/qvariant.py +0 -12
  391. pymodaq/utils/slicing.py +0 -63
  392. pymodaq/utils/units.py +0 -216
  393. pymodaq-4.2.4.dist-info/RECORD +0 -438
  394. /pymodaq/{post_treatment/daq_analysis → extensions/daq_logger}/__init__.py +0 -0
  395. /pymodaq/{utils/abstract/logger.py → extensions/daq_logger/abstract.py} +0 -0
  396. /pymodaq/{resources/QtDesigner_Ressources → extensions/daq_logger/db}/__init__.py +0 -0
  397. {pymodaq-4.2.4.dist-info → pymodaq-5.0.0.dist-info}/WHEEL +0 -0
  398. {pymodaq-4.2.4.dist-info → pymodaq-5.0.0.dist-info}/entry_points.txt +0 -0
  399. {pymodaq-4.2.4.dist-info → pymodaq-5.0.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,1022 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- """
3
- Created the 15/11/2022
4
-
5
- @author: Sebastien Weber
6
- """
7
- import numpy as np
8
- import importlib
9
- import pickle
10
- from typing import Dict
11
-
12
- from pymodaq.utils.logger import set_logger, get_module_name
13
- from pymodaq.utils.config import Config
14
- from pymodaq.utils.daq_utils import capitalize, JsonConverter
15
- from pymodaq.utils import daq_utils as utils
16
- from pymodaq.utils.enums import BaseEnum, enum_checker
17
-
18
-
19
- config = Config()
20
- logger = set_logger(get_module_name(__file__))
21
-
22
- backends_available = []
23
-
24
- # default backend
25
- is_tables = True
26
- try:
27
- import tables
28
- backends_available.append('tables')
29
- except Exception as e: # pragma: no cover
30
- logger.warning(str(e))
31
- is_tables = False
32
-
33
- is_h5py = True
34
- # other possibility
35
- try:
36
- import h5py
37
- backends_available.append('h5py')
38
- except Exception as e: # pragma: no cover
39
- logger.warning(str(e))
40
- is_h5py = False
41
-
42
- is_h5pyd = True
43
- # this one is to be used for remote reading/writing towards a HSDS server (or h5serv), see HDFGroup
44
- try:
45
- import h5pyd
46
- backends_available.append('h5pyd')
47
- except Exception as e: # pragma: no cover
48
- logger.warning(str(e))
49
- is_h5pyd = False
50
-
51
- if not (is_tables or is_h5py or is_h5pyd):
52
- logger.exception('No valid hdf5 backend has been installed, please install either pytables or h5py')
53
-
54
-
55
- class NodeError(Exception):
56
- pass
57
-
58
-
59
- class SaveType(BaseEnum):
60
- scan = 0
61
- detector = 1
62
- logger = 2
63
- custom = 3
64
- actuator = 4
65
-
66
-
67
- class GroupType(BaseEnum):
68
- detector = 0
69
- actuator = 1
70
- data = 2
71
- ch = 3
72
- scan = 4
73
- external_h5 = 5
74
- data_dim = 6
75
- data_logger = 7
76
-
77
-
78
- class InvalidExport(Exception):
79
- pass
80
-
81
-
82
- def check_mandatory_attrs(attr_name, attr):
83
- """for cross compatibility between different backends. If these attributes have binary value, then decode them
84
-
85
- Parameters
86
- ----------
87
- attr_name
88
- attr
89
-
90
- Returns
91
- -------
92
-
93
- """
94
- if attr_name == 'TITLE' or attr_name == 'CLASS' or attr_name == 'EXTDIM':
95
- if isinstance(attr, bytes):
96
- return attr.decode()
97
- else:
98
- return attr
99
- else:
100
- return attr
101
-
102
-
103
- def get_attr(node, attr_name, backend='tables'):
104
- if backend == 'tables':
105
- if attr_name is not None:
106
- attr = node._v_attrs[attr_name]
107
- attr = check_mandatory_attrs(attr_name, attr)
108
- return JsonConverter.json2object(attr)
109
- else:
110
- attrs = dict([])
111
- for attr_name in node._v_attrs._v_attrnames:
112
- attrval = node._v_attrs[attr_name]
113
- attrval = check_mandatory_attrs(attr_name, attrval)
114
- attrs[attr_name] = JsonConverter.json2object(attrval)
115
- return attrs
116
- else:
117
- if attr_name is not None:
118
- attr = node.attrs[attr_name]
119
- attr = check_mandatory_attrs(attr_name, attr)
120
- return JsonConverter.json2object(attr)
121
- else:
122
- attrs = dict([])
123
- for attr_name in node.attrs.keys():
124
- attrval = node.attrs[attr_name]
125
- attrval = check_mandatory_attrs(attr_name, attrval)
126
- attrs[attr_name] = JsonConverter.json2object(attrval)
127
- return attrs
128
-
129
-
130
- def set_attr(node, attr_name, attr_value, backend='tables'):
131
- if backend == 'tables':
132
- node._v_attrs[attr_name] = JsonConverter.object2json(attr_value)
133
- else:
134
- node.attrs[attr_name] = JsonConverter.object2json(attr_value)
135
-
136
-
137
- class InvalidGroupType(Exception):
138
- pass
139
-
140
-
141
- class InvalidSave(Exception):
142
- pass
143
-
144
-
145
- class InvalidGroupDataType(Exception):
146
- pass
147
-
148
-
149
- class InvalidDataType(Exception):
150
- pass
151
-
152
-
153
- class InvalidDataDimension(Exception):
154
- pass
155
-
156
-
157
- class InvalidScanType(Exception):
158
- pass
159
-
160
-
161
- class Node(object):
162
- def __init__(self, node, backend):
163
- if isinstance(node, Node): # to ovoid recursion if one call Node(Node()) or even more
164
- self._node = node.node
165
- else:
166
- self._node = node
167
- self.backend = backend
168
- self._attrs = Attributes(self, backend)
169
-
170
- def __str__(self):
171
- # Get this class name
172
- classname = self.__class__.__name__
173
- # The title
174
- title = self.attrs['TITLE']
175
- return "%s (%s) %r" % \
176
- (self.path, classname, title)
177
-
178
- @property
179
- def node(self):
180
- return self._node
181
-
182
- def __eq__(self, other):
183
- return self.node == other.node
184
-
185
- @property
186
- def parent_node(self) -> 'GROUP':
187
- if self.path == '/':
188
- return None
189
- mod = importlib.import_module('.backends', 'pymodaq.utils.h5modules')
190
-
191
- if self.backend == 'tables':
192
- p = self.node._v_parent
193
- else:
194
- p = self.node.parent
195
- klass = get_attr(p, 'CLASS', self.backend)
196
- _cls = getattr(mod, klass)
197
- return _cls(p, self.backend)
198
-
199
- @property
200
- def h5file(self):
201
- if self.backend == 'tables':
202
- return self.node._v_file
203
- else:
204
- return self.node.file
205
-
206
- def to_h5_backend(self) -> 'H5Backend':
207
- h5_backend = H5Backend(self.backend)
208
- h5_backend.h5file = self.h5file
209
- return h5_backend
210
-
211
- def set_attr(self, key, value):
212
- self.attrs[key] = value
213
-
214
- def get_attr(self, item):
215
- return self.attrs[item]
216
-
217
- @property
218
- def attrs(self):
219
- return self._attrs
220
-
221
- @property
222
- def name(self):
223
- """return node name
224
- """
225
- if self.backend == 'tables':
226
- return self._node._v_name
227
- else:
228
- path = self._node.name
229
- if path == '/':
230
- return path
231
- else:
232
- return path.split('/')[-1]
233
-
234
- @property
235
- def title(self):
236
- return self.attrs['TITLE']
237
-
238
- @property
239
- def path(self):
240
- """return node path
241
- Parameters
242
- ----------
243
- node (str or node instance), see h5py and pytables documentation on nodes
244
-
245
- Returns
246
- -------
247
- str : full path of the node
248
- """
249
- if self.backend == 'tables':
250
- return self._node._v_pathname
251
- else:
252
- return self._node.name
253
-
254
-
255
- class GROUP(Node):
256
- def __init__(self, node, backend):
257
- super().__init__(node, backend)
258
-
259
- def __str__(self):
260
- """Return a short string representation of the group.
261
- """
262
-
263
- pathname = self.path
264
- classname = self.__class__.__name__
265
- title = self.attrs['TITLE']
266
- return "%s (%s) %r" % (pathname, classname, title)
267
-
268
- def __repr__(self):
269
- """Return a detailed string representation of the group.
270
- """
271
-
272
- rep = [
273
- '%r (%s)' % (childname, child.__class__.__name__)
274
- for (childname, child) in self.children().items()
275
- ]
276
- childlist = '[%s]' % (', '.join(rep))
277
-
278
- return "%s\n children := %s" % (str(self), childlist)
279
-
280
- def children(self) -> Dict[str, Node]:
281
- """Get a dict containing all children node hanging from self whith their name as keys
282
-
283
- Returns
284
- -------
285
- dict: keys are children node names, values are the children nodes
286
-
287
- See Also
288
- --------
289
- children_name
290
- """
291
- mod = importlib.import_module('.backends', 'pymodaq.utils.h5modules')
292
- children = dict([])
293
- if self.backend == 'tables':
294
- for child_name, child in self.node._v_children.items():
295
- klass = get_attr(child, 'CLASS', self.backend)
296
- if 'ARRAY' in klass:
297
- _cls = getattr(mod, klass)
298
- else:
299
- _cls = GROUP
300
- children[child_name] = _cls(child, self.backend)
301
- else:
302
- for child_name, child in self.node.items():
303
-
304
- klass = get_attr(child, 'CLASS', self.backend)
305
- if 'ARRAY' in klass:
306
- _cls = getattr(mod, klass)
307
- else:
308
- _cls = GROUP
309
- children[child_name] = _cls(child, self.backend)
310
- return children
311
-
312
- def get_child(self, name: str) -> Node:
313
- return self.children()[name]
314
-
315
- def children_name(self):
316
- """Gets the sorted list of children name hanging from self
317
-
318
- Returns
319
- -------
320
- list: list of name of the children
321
- """
322
- if self.backend == 'tables':
323
- return sorted(list(self.node._v_children.keys()))
324
- else:
325
- return sorted(list(self.node.keys()))
326
- pass
327
-
328
- def remove_children(self):
329
- children_dict = self.children()
330
- for child_name in children_dict:
331
- if self.backend == 'tables':
332
- children_dict[child_name].node._f_remove(recursive=True)
333
- else:
334
- self.node.__delitem__(child_name)
335
-
336
-
337
- class CARRAY(Node):
338
- def __init__(self, node, backend):
339
- super().__init__(node, backend)
340
- self._array = node
341
-
342
- @property
343
- def array(self):
344
- return self._array
345
-
346
- def __repr__(self):
347
- """This provides more metainfo in addition to standard __str__"""
348
-
349
- return """%s
350
- shape := %s
351
- dtype := %s""" % (self, str(self.attrs['shape']), self.attrs['dtype'])
352
-
353
- def __getitem__(self, item):
354
- return self._array.__getitem__(item)
355
-
356
- def __setitem__(self, key, value):
357
- self._array.__setitem__(key, value)
358
-
359
- def read(self):
360
- if self.backend == 'tables':
361
- return self._array.read()
362
- else:
363
- return self._array[:]
364
-
365
- def __len__(self):
366
- if self.backend == 'tables':
367
- return self.array.nrows
368
- else:
369
- return len(self.array)
370
-
371
-
372
- class EARRAY(CARRAY):
373
- def __init__(self, array, backend):
374
- super().__init__(array, backend)
375
-
376
- def append(self, data: np.ndarray, expand=True):
377
- """ appends a ndarray after the current data in the enlargeable array
378
-
379
- Considering the shape length of the enlargeable array is n+1
380
-
381
- The data to append could be:
382
-
383
- * a single element (without the enlargeable shape index that is always the first
384
- index, that is of shape length n). In that case the first index of the enlargeable array
385
- is increased by one.
386
- * an ensemble of elements (a ndarray) of shape length of (n+1).
387
-
388
- Parameters
389
- ----------
390
- data: np.ndarray
391
- the data array to append to the enlargeable node
392
- expand: bool
393
- If True the data array will have its shape expanded by one dim
394
-
395
- """
396
- if not isinstance(data, np.ndarray):
397
- raise TypeError('The appended object should be a ndarray')
398
- if len(self.attrs['shape']) > 1 and data.shape == self.attrs['shape'][1:]:
399
- shape = [1]
400
- shape.extend(data.shape)
401
- data = data.reshape(shape)
402
- extended_first_index = 1
403
- else:
404
- extended_first_index = data.shape[0]
405
- if expand and (len(data.shape) == 1 and not data.shape == (1, )):
406
- data = np.expand_dims(data, 1)
407
- self.append_backend(data)
408
-
409
- sh = list(self.attrs['shape'])
410
- sh[0] += extended_first_index
411
- self.attrs['shape'] = tuple(sh)
412
-
413
- def append_backend(self, data):
414
- if self.backend == 'tables':
415
- self.array.append(data)
416
- else:
417
- self.array.resize(self.array.len() + 1, axis=0)
418
- self.array[-1] = data
419
-
420
-
421
- class VLARRAY(EARRAY):
422
- def __init__(self, array, backend):
423
- super().__init__(array, backend)
424
-
425
- def append(self, data):
426
- self.append_backend(data)
427
-
428
- sh = list(self.attrs['shape'])
429
- sh[0] += 1
430
- self.attrs['shape'] = tuple(sh)
431
-
432
-
433
- class StringARRAY(VLARRAY):
434
- def __init__(self, array, backend):
435
- super().__init__(array, backend)
436
-
437
- def __getitem__(self, item):
438
- return self.array_to_string(super().__getitem__(item))
439
-
440
- def read(self):
441
- data_list = super().read()
442
- return [self.array_to_string(data) for data in data_list]
443
-
444
- def append(self, string):
445
- data = self.string_to_array(string)
446
- super().append(data)
447
-
448
- def array_to_string(self, array):
449
- return pickle.loads(array)
450
-
451
- def string_to_array(self, string):
452
- return np.frombuffer(pickle.dumps(string), np.uint8)
453
-
454
-
455
- class Attributes(object):
456
- def __init__(self, node, backend='tables'):
457
- self._node = node
458
- self.backend = backend
459
-
460
- def __getitem__(self, item):
461
- if item == 'title':
462
- item = item.upper()
463
- attr = get_attr(self._node.node, item, backend=self.backend)
464
- # if isinstance(attr, bytes):
465
- # attr = attr.decode()
466
- return attr
467
-
468
- def __setitem__(self, key, value):
469
- if key == 'title':
470
- key = key.upper()
471
- set_attr(self._node.node, key, value, backend=self.backend)
472
-
473
- def __iter__(self):
474
- self._iter_index = 0
475
- return self
476
-
477
- def __next__(self):
478
- if self._iter_index < len(self):
479
- self._iter_index += 1
480
- return self.attrs_name[self._iter_index-1]
481
- else:
482
- raise StopIteration
483
-
484
- def __len__(self):
485
- return len(self.attrs_name)
486
-
487
- def to_dict(self) -> dict:
488
- """Returns attributes name/value as a dict"""
489
- attrs_dict = dict()
490
- for name in self.attrs_name:
491
- attrs_dict[name] = self[name]
492
- return attrs_dict
493
-
494
- @property
495
- def node(self):
496
- return self._node
497
-
498
- @property
499
- def attrs_name(self):
500
- if self.backend == 'tables':
501
- return [k for k in self.node.node._v_attrs._v_attrnames]
502
- else:
503
- return [k for k in self.node.node.attrs.keys()]
504
-
505
- def __str__(self):
506
- """The string representation for this object."""
507
-
508
- # The pathname
509
- if self.backend == 'tables':
510
- pathname = self._node.node._v_pathname
511
- else:
512
- pathname = self._node.node.name
513
- # Get this class name
514
- classname = self.__class__.__name__
515
- # The attribute names
516
- attrnumber = len([n for n in self.attrs_name])
517
- return "%s.attrs (%s), %s attributes" % \
518
- (pathname, classname, attrnumber)
519
-
520
- def __repr__(self):
521
- attrnames = self.attrs_name
522
- if len(attrnames):
523
- rep = ['%s := %s' % (attr, str(self[attr]))
524
- for attr in attrnames]
525
- attrlist = '[%s]' % (',\n '.join(rep))
526
-
527
- return "%s:\n %s" % (str(self), attrlist)
528
- else:
529
- return str(self)
530
-
531
-
532
- class H5Backend:
533
- def __init__(self, backend='tables'):
534
-
535
- self._h5file = None
536
- self.backend = backend
537
- self.file_path = None
538
- self.compression = None
539
- if backend == 'tables':
540
- if is_tables:
541
- self.h5_library = tables
542
- else:
543
- raise ImportError('the pytables module is not present')
544
- elif backend == 'h5py':
545
- if is_h5py:
546
- self.h5_library = h5py
547
- else:
548
- raise ImportError('the h5py module is not present')
549
- elif backend == 'h5pyd':
550
- if is_h5pyd:
551
- self.h5_library = h5pyd
552
- else:
553
- raise ImportError('the h5pyd module is not present')
554
-
555
- @property
556
- def h5file(self):
557
- return self._h5file
558
-
559
- @h5file.setter
560
- def h5file(self, file):
561
- self.file_path = file.filename
562
- self._h5file = file
563
-
564
- @property
565
- def filename(self):
566
- return self._h5file.filename
567
-
568
- def isopen(self):
569
- if self._h5file is None:
570
- return False
571
- if self.backend == 'tables':
572
- return bool(self._h5file.isopen)
573
- elif self.backend == 'h5py':
574
- return bool(self._h5file.id.valid)
575
- else:
576
- return self._h5file.id.http_conn is not None
577
-
578
- def close_file(self):
579
- """Flush data and close the h5file
580
- """
581
- try:
582
- if self._h5file is not None:
583
- self.flush()
584
- if self.isopen():
585
- self._h5file.close()
586
- except Exception as e:
587
- print(e) # no big deal
588
-
589
- def open_file(self, fullpathname, mode='r', title='PyMoDAQ file', **kwargs):
590
- self.file_path = fullpathname
591
- if self.backend == 'tables':
592
- self._h5file = self.h5_library.open_file(str(fullpathname), mode=mode, title=title, **kwargs)
593
- if mode == 'w':
594
- self.root().attrs['pymodaq_version'] = utils.get_version()
595
- return self._h5file
596
- else:
597
- self._h5file = self.h5_library.File(str(fullpathname), mode=mode, **kwargs)
598
-
599
- if mode == 'w':
600
- self.root().attrs['TITLE'] = title
601
- self.root().attrs['pymodaq_version'] = utils.get_version()
602
- return self._h5file
603
-
604
- def save_file_as(self, filenamepath='h5copy.txt'):
605
- if self.backend == 'tables':
606
- self.h5file.copy_file(str(filenamepath))
607
- else:
608
- raise Warning(f'Not possible to copy the file with the "{self.backend}" backend')
609
-
610
- def root(self):
611
- if self.backend == 'tables':
612
- return GROUP(self._h5file.get_node('/'), self.backend)
613
- else:
614
- return GROUP(self._h5file, self.backend)
615
-
616
- def get_attr(self, node, attr_name=None):
617
- if isinstance(node, Node):
618
- node = node.node
619
- return get_attr(node, attr_name, self.backend)
620
-
621
- def set_attr(self, node, attr_name, attr_value):
622
- if isinstance(node, Node):
623
- node = node.node
624
- return set_attr(node, attr_name, attr_value, self.backend)
625
-
626
- def has_attr(self, node, attr_name):
627
- return attr_name in self.get_node(node).attrs.attrs_name
628
-
629
- def flush(self):
630
- if self._h5file is not None:
631
- self._h5file.flush()
632
-
633
- def define_compression(self, compression, compression_opts):
634
- """Define cmpression library and level of compression
635
- Parameters
636
- ----------
637
- compression: (str) either gzip and zlib are supported here as they are compatible
638
- but zlib is used by pytables while gzip is used by h5py
639
- compression_opts (int) : 0 to 9 0: None, 9: maximum compression
640
- """
641
- #
642
- if self.backend == 'tables':
643
- if compression == 'gzip':
644
- compression = 'zlib'
645
- self.compression = self.h5_library.Filters(complevel=compression_opts, complib=compression)
646
- else:
647
- if compression == 'zlib':
648
- compression = 'gzip'
649
- self.compression = dict(compression=compression, compression_opts=compression_opts)
650
-
651
- def get_set_group(self, where, name, title=''):
652
- """Retrieve or create (if absent) a node group
653
- Get attributed to the class attribute ``current_group``
654
-
655
- Parameters
656
- ----------
657
- where: str or node
658
- path or parent node instance
659
- name: str
660
- group node name
661
- title: str
662
- node title
663
-
664
- Returns
665
- -------
666
- group: group node
667
- """
668
- if isinstance(where, Node):
669
- where = where.node
670
-
671
- if name not in list(self.get_children(where)):
672
- if self.backend == 'tables':
673
- group = self._h5file.create_group(where, name, title)
674
- else:
675
- group = self.get_node(where).node.create_group(name)
676
- group.attrs['TITLE'] = title
677
- group.attrs['CLASS'] = 'GROUP'
678
-
679
- else:
680
- group = self.get_node(where, name)
681
- return GROUP(group, self.backend)
682
-
683
- def get_group_by_title(self, where, title):
684
- if isinstance(where, Node):
685
- where = where.node
686
-
687
- node = self.get_node(where).node
688
- for child_name in self.get_children(node):
689
- child = node[child_name]
690
- if 'TITLE' in self.get_attr(child):
691
- if self.get_attr(child, 'TITLE') == title and self.get_attr(child, 'CLASS') == 'GROUP':
692
- return GROUP(child, self.backend)
693
- return None
694
-
695
- def is_node_in_group(self, where, name):
696
- """
697
- Check if a given node with name is in the group defined by where (comparison on lower case strings)
698
- Parameters
699
- ----------
700
- where: (str or node)
701
- path or parent node instance
702
- name: (str)
703
- group node name
704
-
705
- Returns
706
- -------
707
- bool
708
- True if node exists, False otherwise
709
- """
710
- if isinstance(where, Node):
711
- where = where.node
712
-
713
- return name.lower() in [name.lower() for name in self.get_children(where)]
714
-
715
- def get_node(self, where, name=None) -> Node:
716
- if isinstance(where, Node):
717
- where = where.node
718
- try:
719
- if self.backend == 'tables':
720
- node = self._h5file.get_node(where, name)
721
- else:
722
- if name is not None:
723
- if isinstance(where, str):
724
- where += f'/{name}'
725
- node = self._h5file.get(where)
726
- else:
727
- where = where.get(name)
728
- node = where
729
- else:
730
- if isinstance(where, str):
731
- node = self._h5file.get(where)
732
- else:
733
- node = where
734
- except Exception as e:
735
- raise NodeError(str(e))
736
-
737
- if 'CLASS' not in self.get_attr(node):
738
- self.set_attr(node, 'CLASS', 'GROUP')
739
- return GROUP(node, self.backend)
740
- else:
741
- attr = self.get_attr(node, 'CLASS')
742
- if 'ARRAY' not in attr:
743
- return GROUP(node, self.backend)
744
- elif attr == 'CARRAY':
745
- return CARRAY(node, self.backend)
746
- elif attr == 'EARRAY':
747
- return EARRAY(node, self.backend)
748
- elif attr == 'VLARRAY':
749
- if self.get_attr(node, 'subdtype') == 'string':
750
- return StringARRAY(node, self.backend)
751
- else:
752
- return VLARRAY(node, self.backend)
753
-
754
- def get_node_name(self, node):
755
- """return node name
756
- Parameters
757
- ----------
758
- node (str or node instance), see h5py and pytables documentation on nodes
759
-
760
- Returns
761
- -------
762
- str: name of the node
763
- """
764
- if isinstance(node, Node):
765
- node = node.node
766
- return self.get_node(node).name
767
-
768
- def get_node_path(self, node):
769
- """return node path
770
- Parameters
771
- ----------
772
- node (str or node instance), see h5py and pytables documentation on nodes
773
-
774
- Returns
775
- -------
776
- str : full path of the node
777
- """
778
- if isinstance(node, Node):
779
- node = node.node
780
- return self.get_node(node).path
781
-
782
- def get_parent_node(self, node):
783
- if node == self.root():
784
- return None
785
- if isinstance(node, Node):
786
- node = node.node
787
-
788
- if self.backend == 'tables':
789
- return self.get_node(node._v_parent)
790
- else:
791
- return self.get_node(node.parent)
792
-
793
- def get_children(self, where):
794
- """Get a dict containing all children node hanging from where with their name as keys and types among Node,
795
- CARRAY, EARRAY, VLARRAY or StringARRAY
796
-
797
- Parameters
798
- ----------
799
- where (str or node instance)
800
- see h5py and pytables documentation on nodes, and Node objects of this module
801
-
802
- Returns
803
- -------
804
- dict: keys are children node names, values are the children nodes
805
-
806
- See Also
807
- --------
808
- :meth:`.GROUP.children_name`
809
-
810
- """
811
- where = self.get_node(where) # return a node object in case where is a string
812
- if isinstance(where, Node):
813
- where = where.node
814
-
815
- mod = importlib.import_module('.backends', 'pymodaq.utils.h5modules')
816
- children = dict([])
817
- if self.backend == 'tables':
818
- for child_name, child in where._v_children.items():
819
- klass = get_attr(child, 'CLASS', self.backend)
820
- if 'ARRAY' in klass:
821
- _cls = getattr(mod, klass)
822
- else:
823
- _cls = GROUP
824
- children[child_name] = _cls(child, self.backend)
825
- else:
826
- for child_name, child in where.items():
827
- klass = get_attr(child, 'CLASS', self.backend)
828
- if 'ARRAY' in klass:
829
- _cls = getattr(mod, klass)
830
- else:
831
- _cls = GROUP
832
- children[child_name] = _cls(child, self.backend)
833
- return children
834
-
835
- def walk_nodes(self, where):
836
- where = self.get_node(where) # return a node object in case where is a string
837
- yield where
838
- for gr in self.walk_groups(where):
839
- for child in self.get_children(gr).values():
840
- yield child
841
-
842
- def walk_groups(self, where):
843
- where = self.get_node(where) # return a node object in case where is a string
844
- if where.attrs['CLASS'] != 'GROUP':
845
- return None
846
- if self.backend == 'tables':
847
- for ch in self.h5file.walk_groups(where.node):
848
- yield self.get_node(ch)
849
- else:
850
- stack = [where]
851
- yield where
852
- while stack:
853
- obj = stack.pop()
854
- children = [child for child in self.get_children(obj).values() if child.attrs['CLASS'] == 'GROUP']
855
- for child in children:
856
- stack.append(child)
857
- yield child
858
-
859
- def read(self, array, *args, **kwargs):
860
- if isinstance(array, CARRAY):
861
- array = array.array
862
- if self.backend == 'tables':
863
- return array.read()
864
- else:
865
- return array[:]
866
-
867
- def create_carray(self, where, name, obj=None, title=''):
868
- if isinstance(where, Node):
869
- where = where.node
870
- if obj is None:
871
- raise ValueError('Data to be saved as carray cannot be None')
872
- dtype = obj.dtype
873
- if self.backend == 'tables':
874
- array = CARRAY(self._h5file.create_carray(where, name, obj=obj,
875
- title=title,
876
- filters=self.compression), self.backend)
877
- else:
878
- if self.compression is not None:
879
- array = CARRAY(self.get_node(where).node.create_dataset(name, data=obj, **self.compression),
880
- self.backend)
881
- else:
882
- array = CARRAY(self.get_node(where).node.create_dataset(name, data=obj), self.backend)
883
- array.array.attrs['TITLE'] = title
884
- array.array.attrs[
885
- 'CLASS'] = 'CARRAY' # direct writing using h5py to be compatible with pytable automatic class writing as binary
886
- array.attrs['shape'] = obj.shape
887
- array.attrs['dtype'] = dtype.name
888
- array.attrs['subdtype'] = ''
889
- array.attrs['backend'] = self.backend
890
- return array
891
-
892
- def create_earray(self, where, name, dtype, data_shape=None, title=''):
893
- """create enlargeable arrays from data with a given shape and of a given type. The array is enlargeable along
894
- the first dimension
895
- """
896
- if isinstance(where, Node):
897
- where = where.node
898
- dtype = np.dtype(dtype)
899
- shape = [0]
900
- if data_shape is not None:
901
- shape.extend(list(data_shape))
902
- shape = tuple(shape)
903
-
904
- if self.backend == 'tables':
905
- atom = self.h5_library.Atom.from_dtype(dtype)
906
- array = EARRAY(self._h5file.create_earray(where, name, atom, shape=shape, title=title,
907
- filters=self.compression), self.backend)
908
- else:
909
- maxshape = [None]
910
- if data_shape is not None:
911
- maxshape.extend(list(data_shape))
912
- maxshape = tuple(maxshape)
913
- if self.compression is not None:
914
- array = EARRAY(
915
- self.get_node(where).node.create_dataset(name, shape=shape, dtype=dtype, maxshape=maxshape,
916
- **self.compression), self.backend)
917
- else:
918
- array = EARRAY(
919
- self.get_node(where).node.create_dataset(name, shape=shape, dtype=dtype, maxshape=maxshape),
920
- self.backend)
921
- array.array.attrs['TITLE'] = title
922
- array.array.attrs[
923
- 'CLASS'] = 'EARRAY' # direct writing using h5py to be compatible with pytable automatic class writing as binary
924
- array.array.attrs['EXTDIM'] = 0
925
- array.attrs['shape'] = shape
926
- array.attrs['dtype'] = dtype.name
927
- array.attrs['subdtype'] = ''
928
- array.attrs['backend'] = self.backend
929
- return array
930
-
931
- def create_vlarray(self, where, name, dtype, title=''):
932
- """create variable data length and type and enlargeable 1D arrays
933
-
934
- Parameters
935
- ----------
936
- where: (str) group location in the file where to create the array node
937
- name: (str) name of the array
938
- dtype: (dtype) numpy dtype style, for particular case of strings, use dtype='string'
939
- title: (str) node title attribute (written in capitals)
940
-
941
- Returns
942
- -------
943
- array
944
-
945
- """
946
- if isinstance(where, Node):
947
- where = where.node
948
- if dtype == 'string':
949
- dtype = np.dtype(np.uint8)
950
- subdtype = 'string'
951
- else:
952
- dtype = np.dtype(dtype)
953
- subdtype = ''
954
- if self.backend == 'tables':
955
- atom = self.h5_library.Atom.from_dtype(dtype)
956
- if subdtype == 'string':
957
- array = StringARRAY(self._h5file.create_vlarray(where, name, atom, title=title,
958
- filters=self.compression), self.backend)
959
- else:
960
- array = VLARRAY(self._h5file.create_vlarray(where, name, atom, title=title,
961
- filters=self.compression), self.backend)
962
- else:
963
- maxshape = (None,)
964
- if self.backend == 'h5py':
965
- dt = self.h5_library.vlen_dtype(dtype)
966
- else:
967
- dt = h5pyd.special_dtype(dtype)
968
- if self.compression is not None:
969
- if subdtype == 'string':
970
- array = StringARRAY(self.get_node(where).node.create_dataset(name, (0,), dtype=dt,
971
- **self.compression, maxshape=maxshape),
972
- self.backend)
973
- else:
974
- array = VLARRAY(self.get_node(where).node.create_dataset(name, (0,), dtype=dt, **self.compression,
975
- maxshape=maxshape), self.backend)
976
- else:
977
- if subdtype == 'string':
978
- array = StringARRAY(self.get_node(where).node.create_dataset(name, (0,), dtype=dt,
979
- maxshape=maxshape), self.backend)
980
- else:
981
- array = VLARRAY(self.get_node(where).node.create_dataset(name, (0,), dtype=dt,
982
- maxshape=maxshape), self.backend)
983
- array.array.attrs['TITLE'] = title
984
- array.array.attrs[
985
- 'CLASS'] = 'VLARRAY' # direct writing using h5py to be compatible with pytable automatic class writing as binary
986
- array.array.attrs['EXTDIM'] = 0
987
- array.attrs['shape'] = (0,)
988
- array.attrs['dtype'] = dtype.name
989
- array.attrs['subdtype'] = subdtype
990
- array.attrs['backend'] = self.backend
991
- return array
992
-
993
- def add_group(self, group_name, group_type: GroupType, where, title='', metadata=dict([])) -> GROUP:
994
- """
995
- Add a node in the h5 file tree of the group type
996
- Parameters
997
- ----------
998
- group_name: (str) a custom name for this group
999
- group_type: str or GroupType enum
1000
- one of the possible values of GroupType
1001
- where: (str or node) parent node where to create the new group
1002
- metadata: (dict) extra metadata to be saved with this new group node
1003
-
1004
- Returns
1005
- -------
1006
- (node): newly created group node
1007
- """
1008
- if isinstance(where, Node):
1009
- where = where.node
1010
-
1011
- group_type = enum_checker(GroupType, group_type)
1012
-
1013
- if group_name in self.get_children(self.get_node(where)):
1014
- node = self.get_node(where, group_name)
1015
-
1016
- else:
1017
- node = self.get_set_group(where, utils.capitalize(group_name), title)
1018
- node.attrs['type'] = group_type.name.lower()
1019
- for metadat in metadata:
1020
- node.attrs[metadat] = metadata[metadat]
1021
- node.attrs['backend'] = self.backend
1022
- return node