pymodaq 4.4.7__py3-none-any.whl → 5.0.1__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (415) hide show
  1. pymodaq/__init__.py +57 -91
  2. pymodaq/control_modules/daq_move.py +64 -46
  3. pymodaq/control_modules/daq_move_ui.py +34 -12
  4. pymodaq/control_modules/daq_viewer.py +55 -30
  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 +51 -43
  8. pymodaq/control_modules/utils.py +43 -20
  9. pymodaq/control_modules/viewer_utility_classes.py +54 -18
  10. pymodaq/daq_utils/daq_utils.py +6 -0
  11. pymodaq/dashboard.py +639 -323
  12. pymodaq/examples/function_plotter.py +13 -12
  13. pymodaq/examples/tcp_client.py +1 -1
  14. pymodaq/extensions/__init__.py +1 -1
  15. pymodaq/extensions/bayesian/bayesian_optimisation.py +44 -32
  16. pymodaq/extensions/bayesian/utils.py +10 -10
  17. pymodaq/extensions/console.py +7 -6
  18. pymodaq/extensions/daq_logger/__init__.py +1 -0
  19. pymodaq/extensions/{daq_logger.py → daq_logger/daq_logger.py} +30 -30
  20. pymodaq/{utils/db/db_logger → extensions/daq_logger/db}/db_logger.py +16 -15
  21. pymodaq/{utils/db/db_logger → extensions/daq_logger/db}/db_logger_models.py +2 -0
  22. pymodaq/{utils/h5modules → extensions/daq_logger}/h5logging.py +7 -8
  23. pymodaq/extensions/daq_scan.py +42 -34
  24. pymodaq/extensions/daq_scan_ui.py +18 -18
  25. pymodaq/extensions/h5browser.py +2 -3
  26. pymodaq/extensions/pid/__init__.py +4 -2
  27. pymodaq/extensions/pid/daq_move_PID.py +3 -3
  28. pymodaq/extensions/pid/pid_controller.py +59 -50
  29. pymodaq/extensions/pid/utils.py +10 -5
  30. pymodaq/extensions/utils.py +33 -3
  31. pymodaq/post_treatment/load_and_plot.py +10 -7
  32. pymodaq/resources/preset_default.xml +1 -1
  33. pymodaq/updater.py +107 -0
  34. pymodaq/utils/array_manipulation.py +4 -384
  35. pymodaq/utils/calibration_camera.py +12 -9
  36. pymodaq/utils/chrono_timer.py +11 -10
  37. pymodaq/utils/config.py +3 -458
  38. pymodaq/utils/daq_utils.py +9 -715
  39. pymodaq/utils/data.py +17 -2959
  40. pymodaq/utils/enums.py +4 -74
  41. pymodaq/utils/exceptions.py +0 -4
  42. pymodaq/utils/gui_utils/__init__.py +8 -8
  43. pymodaq/utils/gui_utils/loader_utils.py +26 -1
  44. pymodaq/utils/gui_utils/utils.py +8 -162
  45. pymodaq/utils/gui_utils/widgets/lcd.py +6 -109
  46. pymodaq/utils/h5modules/__init__.py +0 -4
  47. pymodaq/utils/h5modules/module_saving.py +9 -8
  48. pymodaq/utils/leco/__init__.py +2 -2
  49. pymodaq/utils/leco/daq_move_LECODirector.py +3 -6
  50. pymodaq/utils/leco/daq_xDviewer_LECODirector.py +5 -5
  51. pymodaq/utils/leco/director_utils.py +2 -2
  52. pymodaq/utils/leco/leco_director.py +3 -3
  53. pymodaq/utils/leco/pymodaq_listener.py +4 -3
  54. pymodaq/utils/leco/utils.py +11 -9
  55. pymodaq/utils/logger.py +4 -76
  56. pymodaq/utils/managers/batchscan_manager.py +16 -19
  57. pymodaq/utils/managers/modules_manager.py +30 -17
  58. pymodaq/utils/managers/overshoot_manager.py +48 -6
  59. pymodaq/utils/managers/preset_manager.py +39 -59
  60. pymodaq/utils/managers/preset_manager_utils.py +28 -22
  61. pymodaq/utils/managers/remote_manager.py +12 -10
  62. pymodaq/utils/math_utils.py +4 -582
  63. pymodaq/utils/messenger.py +4 -64
  64. pymodaq/utils/parameter/__init__.py +6 -9
  65. pymodaq/utils/parameter/utils.py +4 -328
  66. pymodaq/utils/scanner/scan_config.py +1 -1
  67. pymodaq/utils/scanner/scan_factory.py +16 -12
  68. pymodaq/utils/{plotting → scanner}/scan_selector.py +19 -20
  69. pymodaq/utils/scanner/scanner.py +10 -8
  70. pymodaq/utils/scanner/scanners/_1d_scanners.py +8 -5
  71. pymodaq/utils/scanner/scanners/_2d_scanners.py +5 -5
  72. pymodaq/utils/scanner/scanners/sequential.py +8 -8
  73. pymodaq/utils/scanner/scanners/tabular.py +9 -9
  74. pymodaq/utils/scanner/utils.py +6 -4
  75. pymodaq/utils/svg/svg_viewer2D.py +3 -4
  76. pymodaq/utils/tcp_ip/mysocket.py +4 -110
  77. pymodaq/utils/tcp_ip/serializer.py +4 -801
  78. pymodaq/utils/tcp_ip/tcp_server_client.py +15 -13
  79. pymodaq-5.0.1.dist-info/METADATA +242 -0
  80. pymodaq-5.0.1.dist-info/RECORD +122 -0
  81. {pymodaq-4.4.7.dist-info → pymodaq-5.0.1.dist-info}/WHEEL +1 -1
  82. {pymodaq-4.4.7.dist-info → pymodaq-5.0.1.dist-info}/entry_points.txt +1 -0
  83. pymodaq/examples/custom_app.py +0 -258
  84. pymodaq/examples/custom_viewer.py +0 -112
  85. pymodaq/examples/parameter_ex.py +0 -138
  86. pymodaq/examples/preset_MockCamera.xml +0 -1
  87. pymodaq/post_treatment/daq_measurement/daq_measurement_GUI.py +0 -142
  88. pymodaq/post_treatment/daq_measurement/daq_measurement_GUI.ui +0 -232
  89. pymodaq/post_treatment/daq_measurement/daq_measurement_main.py +0 -391
  90. pymodaq/post_treatment/daq_measurement/process_from_QtDesigner_DAQ_Measurement_GUI.bat +0 -2
  91. pymodaq/post_treatment/process_to_scalar.py +0 -263
  92. pymodaq/resources/QtDesigner_Ressources/Icon_Library/1d.png +0 -0
  93. pymodaq/resources/QtDesigner_Ressources/Icon_Library/2d.png +0 -0
  94. pymodaq/resources/QtDesigner_Ressources/Icon_Library/3d.png +0 -0
  95. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Add2.png +0 -0
  96. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Add_Step.png +0 -0
  97. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Approve.png +0 -0
  98. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Approve_All.png +0 -0
  99. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Browse_Dir_Path.png +0 -0
  100. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Calculator.png +0 -0
  101. pymodaq/resources/QtDesigner_Ressources/Icon_Library/ChnGroup.png +0 -0
  102. pymodaq/resources/QtDesigner_Ressources/Icon_Library/ChnNum.png +0 -0
  103. pymodaq/resources/QtDesigner_Ressources/Icon_Library/ChnText.png +0 -0
  104. pymodaq/resources/QtDesigner_Ressources/Icon_Library/ChnTime.png +0 -0
  105. pymodaq/resources/QtDesigner_Ressources/Icon_Library/ChnWave.png +0 -0
  106. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Close3.png +0 -0
  107. pymodaq/resources/QtDesigner_Ressources/Icon_Library/CollapseAll.png +0 -0
  108. pymodaq/resources/QtDesigner_Ressources/Icon_Library/CollapseAll_32.png +0 -0
  109. pymodaq/resources/QtDesigner_Ressources/Icon_Library/ColorPicker.png +0 -0
  110. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Contract.png +0 -0
  111. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Create.png +0 -0
  112. pymodaq/resources/QtDesigner_Ressources/Icon_Library/DeleteLayer.png +0 -0
  113. pymodaq/resources/QtDesigner_Ressources/Icon_Library/EditOpen.png +0 -0
  114. pymodaq/resources/QtDesigner_Ressources/Icon_Library/EditRedo.png +0 -0
  115. pymodaq/resources/QtDesigner_Ressources/Icon_Library/EditUndo.png +0 -0
  116. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Ellipse.png +0 -0
  117. pymodaq/resources/QtDesigner_Ressources/Icon_Library/EllipseFilled.png +0 -0
  118. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Error.png +0 -0
  119. pymodaq/resources/QtDesigner_Ressources/Icon_Library/ErrorMessage.png +0 -0
  120. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Error_16.png +0 -0
  121. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Exit.png +0 -0
  122. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Expand.png +0 -0
  123. pymodaq/resources/QtDesigner_Ressources/Icon_Library/ExpandAll.png +0 -0
  124. pymodaq/resources/QtDesigner_Ressources/Icon_Library/ExpandAll_32.png +0 -0
  125. pymodaq/resources/QtDesigner_Ressources/Icon_Library/FFT.png +0 -0
  126. pymodaq/resources/QtDesigner_Ressources/Icon_Library/HLM.ico +0 -0
  127. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Help.png +0 -0
  128. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Help_32.png +0 -0
  129. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Histogram.png +0 -0
  130. pymodaq/resources/QtDesigner_Ressources/Icon_Library/LUT_LookUpTable.png +0 -0
  131. pymodaq/resources/QtDesigner_Ressources/Icon_Library/MagnifyingGlass.png +0 -0
  132. pymodaq/resources/QtDesigner_Ressources/Icon_Library/MagnifyingGlass_24.png +0 -0
  133. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Marker.png +0 -0
  134. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Math.png +0 -0
  135. pymodaq/resources/QtDesigner_Ressources/Icon_Library/MeasurementStudio_32.png +0 -0
  136. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Move.png +0 -0
  137. pymodaq/resources/QtDesigner_Ressources/Icon_Library/MoveDown.png +0 -0
  138. pymodaq/resources/QtDesigner_Ressources/Icon_Library/MoveUp.png +0 -0
  139. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Multiply.png +0 -0
  140. pymodaq/resources/QtDesigner_Ressources/Icon_Library/NewFile.png +0 -0
  141. pymodaq/resources/QtDesigner_Ressources/Icon_Library/NewLayer.png +0 -0
  142. pymodaq/resources/QtDesigner_Ressources/Icon_Library/New_File.png +0 -0
  143. pymodaq/resources/QtDesigner_Ressources/Icon_Library/New_Folder.png +0 -0
  144. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Open.png +0 -0
  145. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Open_1D.png +0 -0
  146. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Open_2D.png +0 -0
  147. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Open_File.png +0 -0
  148. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Open_File_32.png +0 -0
  149. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Open_sim.png +0 -0
  150. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Options.png +0 -0
  151. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Oscilloscope.png +0 -0
  152. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Oscilloscope_16.png +0 -0
  153. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Pass.png +0 -0
  154. pymodaq/resources/QtDesigner_Ressources/Icon_Library/RGB.png +0 -0
  155. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Rectangle.png +0 -0
  156. pymodaq/resources/QtDesigner_Ressources/Icon_Library/RectangleFilled.png +0 -0
  157. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Redo.png +0 -0
  158. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Refresh.png +0 -0
  159. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Refresh2.png +0 -0
  160. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Refresh_32.png +0 -0
  161. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Region.png +0 -0
  162. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Rendezvous.png +0 -0
  163. pymodaq/resources/QtDesigner_Ressources/Icon_Library/SELECT.png +0 -0
  164. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Save.png +0 -0
  165. pymodaq/resources/QtDesigner_Ressources/Icon_Library/SaveAll.png +0 -0
  166. pymodaq/resources/QtDesigner_Ressources/Icon_Library/SaveAll_32.png +0 -0
  167. pymodaq/resources/QtDesigner_Ressources/Icon_Library/SaveAs.png +0 -0
  168. pymodaq/resources/QtDesigner_Ressources/Icon_Library/SaveAs_32.png +0 -0
  169. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Save_24.png +0 -0
  170. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Save_32.png +0 -0
  171. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Search.png +0 -0
  172. pymodaq/resources/QtDesigner_Ressources/Icon_Library/SelectPolygon.png +0 -0
  173. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Select_24.png +0 -0
  174. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Settings.png +0 -0
  175. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Snap&Save.png +0 -0
  176. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Snapshot.png +0 -0
  177. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Snapshot2.png +0 -0
  178. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Snapshot2_16.png +0 -0
  179. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Snapshot2_32.png +0 -0
  180. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Spreadsheet.png +0 -0
  181. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Statistics.png +0 -0
  182. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Statistics2.png +0 -0
  183. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Status.png +0 -0
  184. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Subtract.png +0 -0
  185. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Vision.png +0 -0
  186. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Volts.png +0 -0
  187. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Wait2.png +0 -0
  188. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Zoom_1_1.png +0 -0
  189. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Zoom_in.png +0 -0
  190. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Zoom_out.png +0 -0
  191. pymodaq/resources/QtDesigner_Ressources/Icon_Library/Zoom_to_Selection.png +0 -0
  192. pymodaq/resources/QtDesigner_Ressources/Icon_Library/abort.png +0 -0
  193. pymodaq/resources/QtDesigner_Ressources/Icon_Library/advanced2.png +0 -0
  194. pymodaq/resources/QtDesigner_Ressources/Icon_Library/algo.png +0 -0
  195. pymodaq/resources/QtDesigner_Ressources/Icon_Library/autoscale.png +0 -0
  196. pymodaq/resources/QtDesigner_Ressources/Icon_Library/b_icon.png +0 -0
  197. pymodaq/resources/QtDesigner_Ressources/Icon_Library/back.png +0 -0
  198. pymodaq/resources/QtDesigner_Ressources/Icon_Library/bg_icon.png +0 -0
  199. pymodaq/resources/QtDesigner_Ressources/Icon_Library/camera.png +0 -0
  200. pymodaq/resources/QtDesigner_Ressources/Icon_Library/camera_snap.png +0 -0
  201. pymodaq/resources/QtDesigner_Ressources/Icon_Library/cartesian.png +0 -0
  202. pymodaq/resources/QtDesigner_Ressources/Icon_Library/clear2.png +0 -0
  203. pymodaq/resources/QtDesigner_Ressources/Icon_Library/clear_ROI.png +0 -0
  204. pymodaq/resources/QtDesigner_Ressources/Icon_Library/close2.png +0 -0
  205. pymodaq/resources/QtDesigner_Ressources/Icon_Library/cluster2.png +0 -0
  206. pymodaq/resources/QtDesigner_Ressources/Icon_Library/color.png +0 -0
  207. pymodaq/resources/QtDesigner_Ressources/Icon_Library/color2.png +0 -0
  208. pymodaq/resources/QtDesigner_Ressources/Icon_Library/continuous.png +0 -0
  209. pymodaq/resources/QtDesigner_Ressources/Icon_Library/data.png +0 -0
  210. pymodaq/resources/QtDesigner_Ressources/Icon_Library/delay.png +0 -0
  211. pymodaq/resources/QtDesigner_Ressources/Icon_Library/download.png +0 -0
  212. pymodaq/resources/QtDesigner_Ressources/Icon_Library/download2.png +0 -0
  213. pymodaq/resources/QtDesigner_Ressources/Icon_Library/error2.png +0 -0
  214. pymodaq/resources/QtDesigner_Ressources/Icon_Library/ethernet.png +0 -0
  215. pymodaq/resources/QtDesigner_Ressources/Icon_Library/exit2.png +0 -0
  216. pymodaq/resources/QtDesigner_Ressources/Icon_Library/fan.png +0 -0
  217. pymodaq/resources/QtDesigner_Ressources/Icon_Library/filter2.png +0 -0
  218. pymodaq/resources/QtDesigner_Ressources/Icon_Library/g_icon.png +0 -0
  219. pymodaq/resources/QtDesigner_Ressources/Icon_Library/gear2.png +0 -0
  220. pymodaq/resources/QtDesigner_Ressources/Icon_Library/go_to.png +0 -0
  221. pymodaq/resources/QtDesigner_Ressources/Icon_Library/go_to_1.png +0 -0
  222. pymodaq/resources/QtDesigner_Ressources/Icon_Library/go_to_2.png +0 -0
  223. pymodaq/resources/QtDesigner_Ressources/Icon_Library/grab.png +0 -0
  224. pymodaq/resources/QtDesigner_Ressources/Icon_Library/graph.png +0 -0
  225. pymodaq/resources/QtDesigner_Ressources/Icon_Library/greenLight2.png +0 -0
  226. pymodaq/resources/QtDesigner_Ressources/Icon_Library/greenLight2_32.png +0 -0
  227. pymodaq/resources/QtDesigner_Ressources/Icon_Library/green_light.png +0 -0
  228. pymodaq/resources/QtDesigner_Ressources/Icon_Library/grey_icon.png +0 -0
  229. pymodaq/resources/QtDesigner_Ressources/Icon_Library/greyscale.png +0 -0
  230. pymodaq/resources/QtDesigner_Ressources/Icon_Library/help1.png +0 -0
  231. pymodaq/resources/QtDesigner_Ressources/Icon_Library/help1_32.png +0 -0
  232. pymodaq/resources/QtDesigner_Ressources/Icon_Library/home2.png +0 -0
  233. pymodaq/resources/QtDesigner_Ressources/Icon_Library/information2.png +0 -0
  234. pymodaq/resources/QtDesigner_Ressources/Icon_Library/ini.png +0 -0
  235. pymodaq/resources/QtDesigner_Ressources/Icon_Library/input.png +0 -0
  236. pymodaq/resources/QtDesigner_Ressources/Icon_Library/integrator.png +0 -0
  237. pymodaq/resources/QtDesigner_Ressources/Icon_Library/joystick.png +0 -0
  238. pymodaq/resources/QtDesigner_Ressources/Icon_Library/light_green.png +0 -0
  239. pymodaq/resources/QtDesigner_Ressources/Icon_Library/light_green_16.png +0 -0
  240. pymodaq/resources/QtDesigner_Ressources/Icon_Library/light_red.png +0 -0
  241. pymodaq/resources/QtDesigner_Ressources/Icon_Library/light_red_16.png +0 -0
  242. pymodaq/resources/QtDesigner_Ressources/Icon_Library/light_yellow.png +0 -0
  243. pymodaq/resources/QtDesigner_Ressources/Icon_Library/light_yellow_16.png +0 -0
  244. pymodaq/resources/QtDesigner_Ressources/Icon_Library/limiter.png +0 -0
  245. pymodaq/resources/QtDesigner_Ressources/Icon_Library/load_ROI.png +0 -0
  246. pymodaq/resources/QtDesigner_Ressources/Icon_Library/meshPlot.png +0 -0
  247. pymodaq/resources/QtDesigner_Ressources/Icon_Library/meter.png +0 -0
  248. pymodaq/resources/QtDesigner_Ressources/Icon_Library/meter2.png +0 -0
  249. pymodaq/resources/QtDesigner_Ressources/Icon_Library/meter_32.png +0 -0
  250. pymodaq/resources/QtDesigner_Ressources/Icon_Library/move_contour.png +0 -0
  251. pymodaq/resources/QtDesigner_Ressources/Icon_Library/move_straight_line.png +0 -0
  252. pymodaq/resources/QtDesigner_Ressources/Icon_Library/movie.png +0 -0
  253. pymodaq/resources/QtDesigner_Ressources/Icon_Library/multi_point.png +0 -0
  254. pymodaq/resources/QtDesigner_Ressources/Icon_Library/multiplexer.png +0 -0
  255. pymodaq/resources/QtDesigner_Ressources/Icon_Library/new.png +0 -0
  256. pymodaq/resources/QtDesigner_Ressources/Icon_Library/openArrow.png +0 -0
  257. pymodaq/resources/QtDesigner_Ressources/Icon_Library/openTree.png +0 -0
  258. pymodaq/resources/QtDesigner_Ressources/Icon_Library/oscilloscope2.png +0 -0
  259. pymodaq/resources/QtDesigner_Ressources/Icon_Library/oscilloscope3.png +0 -0
  260. pymodaq/resources/QtDesigner_Ressources/Icon_Library/overlay.png +0 -0
  261. pymodaq/resources/QtDesigner_Ressources/Icon_Library/pass2.png +0 -0
  262. pymodaq/resources/QtDesigner_Ressources/Icon_Library/pass2_16.png +0 -0
  263. pymodaq/resources/QtDesigner_Ressources/Icon_Library/pass_32.png +0 -0
  264. pymodaq/resources/QtDesigner_Ressources/Icon_Library/pause.png +0 -0
  265. pymodaq/resources/QtDesigner_Ressources/Icon_Library/permute.png +0 -0
  266. pymodaq/resources/QtDesigner_Ressources/Icon_Library/phase.png +0 -0
  267. pymodaq/resources/QtDesigner_Ressources/Icon_Library/play.png +0 -0
  268. pymodaq/resources/QtDesigner_Ressources/Icon_Library/polar.png +0 -0
  269. pymodaq/resources/QtDesigner_Ressources/Icon_Library/pole_zero.png +0 -0
  270. pymodaq/resources/QtDesigner_Ressources/Icon_Library/powerMeter.png +0 -0
  271. pymodaq/resources/QtDesigner_Ressources/Icon_Library/powerSwitch.png +0 -0
  272. pymodaq/resources/QtDesigner_Ressources/Icon_Library/powerSwitch_16.png +0 -0
  273. pymodaq/resources/QtDesigner_Ressources/Icon_Library/print2.png +0 -0
  274. pymodaq/resources/QtDesigner_Ressources/Icon_Library/print2_32.png +0 -0
  275. pymodaq/resources/QtDesigner_Ressources/Icon_Library/properties.png +0 -0
  276. pymodaq/resources/QtDesigner_Ressources/Icon_Library/r_icon.png +0 -0
  277. pymodaq/resources/QtDesigner_Ressources/Icon_Library/radiocontrolbutton.png +0 -0
  278. pymodaq/resources/QtDesigner_Ressources/Icon_Library/random.png +0 -0
  279. pymodaq/resources/QtDesigner_Ressources/Icon_Library/read2.png +0 -0
  280. pymodaq/resources/QtDesigner_Ressources/Icon_Library/red_light.png +0 -0
  281. pymodaq/resources/QtDesigner_Ressources/Icon_Library/remove.png +0 -0
  282. pymodaq/resources/QtDesigner_Ressources/Icon_Library/reset.png +0 -0
  283. pymodaq/resources/QtDesigner_Ressources/Icon_Library/rgb_icon.png +0 -0
  284. pymodaq/resources/QtDesigner_Ressources/Icon_Library/robot.png +0 -0
  285. pymodaq/resources/QtDesigner_Ressources/Icon_Library/rotation2.png +0 -0
  286. pymodaq/resources/QtDesigner_Ressources/Icon_Library/run2.png +0 -0
  287. pymodaq/resources/QtDesigner_Ressources/Icon_Library/run_all.png +0 -0
  288. pymodaq/resources/QtDesigner_Ressources/Icon_Library/saturation.png +0 -0
  289. pymodaq/resources/QtDesigner_Ressources/Icon_Library/saveTree.png +0 -0
  290. pymodaq/resources/QtDesigner_Ressources/Icon_Library/save_ROI.png +0 -0
  291. pymodaq/resources/QtDesigner_Ressources/Icon_Library/scale_horizontally.png +0 -0
  292. pymodaq/resources/QtDesigner_Ressources/Icon_Library/scale_vertically.png +0 -0
  293. pymodaq/resources/QtDesigner_Ressources/Icon_Library/search2.png +0 -0
  294. pymodaq/resources/QtDesigner_Ressources/Icon_Library/select2.png +0 -0
  295. pymodaq/resources/QtDesigner_Ressources/Icon_Library/select_all.png +0 -0
  296. pymodaq/resources/QtDesigner_Ressources/Icon_Library/select_all2.png +0 -0
  297. pymodaq/resources/QtDesigner_Ressources/Icon_Library/select_none.png +0 -0
  298. pymodaq/resources/QtDesigner_Ressources/Icon_Library/sequence.png +0 -0
  299. pymodaq/resources/QtDesigner_Ressources/Icon_Library/sequence2.png +0 -0
  300. pymodaq/resources/QtDesigner_Ressources/Icon_Library/snap.png +0 -0
  301. pymodaq/resources/QtDesigner_Ressources/Icon_Library/sort_ascend.png +0 -0
  302. pymodaq/resources/QtDesigner_Ressources/Icon_Library/spectrumAnalyzer.png +0 -0
  303. pymodaq/resources/QtDesigner_Ressources/Icon_Library/start.png +0 -0
  304. pymodaq/resources/QtDesigner_Ressources/Icon_Library/status_cancelled.png +0 -0
  305. pymodaq/resources/QtDesigner_Ressources/Icon_Library/stop.png +0 -0
  306. pymodaq/resources/QtDesigner_Ressources/Icon_Library/stop2.png +0 -0
  307. pymodaq/resources/QtDesigner_Ressources/Icon_Library/stop3.png +0 -0
  308. pymodaq/resources/QtDesigner_Ressources/Icon_Library/stop_all.png +0 -0
  309. pymodaq/resources/QtDesigner_Ressources/Icon_Library/sum.png +0 -0
  310. pymodaq/resources/QtDesigner_Ressources/Icon_Library/surfacePlot.png +0 -0
  311. pymodaq/resources/QtDesigner_Ressources/Icon_Library/target.png +0 -0
  312. pymodaq/resources/QtDesigner_Ressources/Icon_Library/tree.png +0 -0
  313. pymodaq/resources/QtDesigner_Ressources/Icon_Library/updateTree.png +0 -0
  314. pymodaq/resources/QtDesigner_Ressources/Icon_Library/utility2.png +0 -0
  315. pymodaq/resources/QtDesigner_Ressources/Icon_Library/utility_small.png +0 -0
  316. pymodaq/resources/QtDesigner_Ressources/Icon_Library/vector.png +0 -0
  317. pymodaq/resources/QtDesigner_Ressources/Icon_Library/verify.png +0 -0
  318. pymodaq/resources/QtDesigner_Ressources/Icon_Library/video.png +0 -0
  319. pymodaq/resources/QtDesigner_Ressources/Icon_Library/wait.png +0 -0
  320. pymodaq/resources/QtDesigner_Ressources/Icon_Library/waterfallPlot.png +0 -0
  321. pymodaq/resources/QtDesigner_Ressources/Icon_Library/watershed.png +0 -0
  322. pymodaq/resources/QtDesigner_Ressources/Icon_Library/yellow_light.png +0 -0
  323. pymodaq/resources/QtDesigner_Ressources/Icon_Library/zip_file.png +0 -0
  324. pymodaq/resources/QtDesigner_Ressources/Icon_Library/zoomAuto.png +0 -0
  325. pymodaq/resources/QtDesigner_Ressources/Icon_Library/zoomReset.png +0 -0
  326. pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources.bat +0 -2
  327. pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources.qrc +0 -238
  328. pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources_rc.py +0 -127453
  329. pymodaq/resources/QtDesigner_Ressources/__init__.py +0 -0
  330. pymodaq/resources/QtDesigner_Ressources/credit.rst +0 -7
  331. pymodaq/resources/QtDesigner_Ressources/icons.svg +0 -142
  332. pymodaq/resources/VERSION +0 -2
  333. pymodaq/resources/config_template.toml +0 -96
  334. pymodaq/resources/triangulation_data.npy +0 -0
  335. pymodaq/utils/abstract/__init__.py +0 -48
  336. pymodaq/utils/db/__init__.py +0 -0
  337. pymodaq/utils/db/db_logger/__init__.py +0 -0
  338. pymodaq/utils/factory.py +0 -82
  339. pymodaq/utils/gui_utils/custom_app.py +0 -133
  340. pymodaq/utils/gui_utils/dock.py +0 -107
  341. pymodaq/utils/gui_utils/file_io.py +0 -94
  342. pymodaq/utils/gui_utils/layout.py +0 -34
  343. pymodaq/utils/gui_utils/list_picker.py +0 -38
  344. pymodaq/utils/gui_utils/widgets/__init__.py +0 -5
  345. pymodaq/utils/gui_utils/widgets/label.py +0 -24
  346. pymodaq/utils/gui_utils/widgets/push.py +0 -149
  347. pymodaq/utils/gui_utils/widgets/qled.py +0 -62
  348. pymodaq/utils/gui_utils/widgets/spinbox.py +0 -24
  349. pymodaq/utils/gui_utils/widgets/table.py +0 -263
  350. pymodaq/utils/gui_utils/widgets/tree_layout.py +0 -188
  351. pymodaq/utils/gui_utils/widgets/tree_toml.py +0 -110
  352. pymodaq/utils/h5modules/backends.py +0 -1022
  353. pymodaq/utils/h5modules/browsing.py +0 -627
  354. pymodaq/utils/h5modules/data_saving.py +0 -1107
  355. pymodaq/utils/h5modules/exporter.py +0 -119
  356. pymodaq/utils/h5modules/exporters/__init__.py +0 -0
  357. pymodaq/utils/h5modules/exporters/base.py +0 -111
  358. pymodaq/utils/h5modules/exporters/flimj.py +0 -63
  359. pymodaq/utils/h5modules/exporters/hyperspy.py +0 -143
  360. pymodaq/utils/h5modules/saving.py +0 -866
  361. pymodaq/utils/h5modules/utils.py +0 -115
  362. pymodaq/utils/managers/action_manager.py +0 -489
  363. pymodaq/utils/managers/parameter_manager.py +0 -279
  364. pymodaq/utils/managers/roi_manager.py +0 -740
  365. pymodaq/utils/parameter/ioxml.py +0 -545
  366. pymodaq/utils/parameter/pymodaq_ptypes/__init__.py +0 -38
  367. pymodaq/utils/parameter/pymodaq_ptypes/bool.py +0 -31
  368. pymodaq/utils/parameter/pymodaq_ptypes/date.py +0 -126
  369. pymodaq/utils/parameter/pymodaq_ptypes/filedir.py +0 -143
  370. pymodaq/utils/parameter/pymodaq_ptypes/itemselect.py +0 -265
  371. pymodaq/utils/parameter/pymodaq_ptypes/led.py +0 -44
  372. pymodaq/utils/parameter/pymodaq_ptypes/list.py +0 -150
  373. pymodaq/utils/parameter/pymodaq_ptypes/numeric.py +0 -18
  374. pymodaq/utils/parameter/pymodaq_ptypes/pixmap.py +0 -175
  375. pymodaq/utils/parameter/pymodaq_ptypes/slide.py +0 -166
  376. pymodaq/utils/parameter/pymodaq_ptypes/table.py +0 -135
  377. pymodaq/utils/parameter/pymodaq_ptypes/tableview.py +0 -149
  378. pymodaq/utils/parameter/pymodaq_ptypes/text.py +0 -142
  379. pymodaq/utils/plotting/__init__.py +0 -0
  380. pymodaq/utils/plotting/data_viewers/__init__.py +0 -10
  381. pymodaq/utils/plotting/data_viewers/base.py +0 -286
  382. pymodaq/utils/plotting/data_viewers/viewer.py +0 -275
  383. pymodaq/utils/plotting/data_viewers/viewer0D.py +0 -298
  384. pymodaq/utils/plotting/data_viewers/viewer1D.py +0 -826
  385. pymodaq/utils/plotting/data_viewers/viewer1Dbasic.py +0 -231
  386. pymodaq/utils/plotting/data_viewers/viewer2D.py +0 -1118
  387. pymodaq/utils/plotting/data_viewers/viewer2D_basic.py +0 -146
  388. pymodaq/utils/plotting/data_viewers/viewerND.py +0 -800
  389. pymodaq/utils/plotting/gant_chart.py +0 -123
  390. pymodaq/utils/plotting/image_viewer.py +0 -97
  391. pymodaq/utils/plotting/items/__init__.py +0 -0
  392. pymodaq/utils/plotting/items/axis_scaled.py +0 -93
  393. pymodaq/utils/plotting/items/crosshair.py +0 -94
  394. pymodaq/utils/plotting/items/image.py +0 -388
  395. pymodaq/utils/plotting/navigator.py +0 -353
  396. pymodaq/utils/plotting/plotter/plotter.py +0 -94
  397. pymodaq/utils/plotting/plotter/plotters/__init__.py +0 -0
  398. pymodaq/utils/plotting/plotter/plotters/matplotlib_plotters.py +0 -134
  399. pymodaq/utils/plotting/plotter/plotters/qt_plotters.py +0 -78
  400. pymodaq/utils/plotting/utils/__init__.py +0 -0
  401. pymodaq/utils/plotting/utils/axes_viewer.py +0 -88
  402. pymodaq/utils/plotting/utils/filter.py +0 -585
  403. pymodaq/utils/plotting/utils/lineout.py +0 -226
  404. pymodaq/utils/plotting/utils/plot_utils.py +0 -579
  405. pymodaq/utils/plotting/utils/signalND.py +0 -1347
  406. pymodaq/utils/plotting/widgets.py +0 -76
  407. pymodaq/utils/qvariant.py +0 -12
  408. pymodaq/utils/slicing.py +0 -63
  409. pymodaq/utils/units.py +0 -216
  410. pymodaq-4.4.7.dist-info/METADATA +0 -163
  411. pymodaq-4.4.7.dist-info/RECORD +0 -446
  412. /pymodaq/{post_treatment/daq_analysis → daq_utils}/__init__.py +0 -0
  413. /pymodaq/{utils/abstract/logger.py → extensions/daq_logger/abstract.py} +0 -0
  414. /pymodaq/{post_treatment/daq_measurement → extensions/daq_logger/db}/__init__.py +0 -0
  415. {pymodaq-4.4.7.dist-info → pymodaq-5.0.1.dist-info}/licenses/LICENSE +0 -0
pymodaq/dashboard.py CHANGED
@@ -8,66 +8,162 @@ import logging
8
8
  from pathlib import Path
9
9
  from importlib import import_module
10
10
  from packaging import version as version_mod
11
- from typing import Tuple, List
11
+ from typing import Tuple, List, Any, TYPE_CHECKING
12
12
 
13
13
 
14
14
  from qtpy import QtGui, QtWidgets, QtCore
15
- from qtpy.QtCore import Qt, QObject, Slot, QThread, Signal
15
+ from qtpy.QtCore import Qt, QObject, Slot, QThread, Signal, QSize
16
+ from qtpy.QtWidgets import QTableWidget, QTableWidgetItem, QCheckBox, QWidget, QLabel, QDialogButtonBox, QDialog
16
17
  from time import perf_counter
17
18
  import numpy as np
18
19
 
19
- from pymodaq.utils.logger import set_logger, get_module_name
20
- from pymodaq.utils.gui_utils import DockArea, Dock, select_file
21
- import pymodaq.utils.gui_utils.layout as layout_mod
22
- from pymodaq.utils.gui_utils.utils import start_qapplication
23
- from pymodaq.utils.messenger import messagebox
24
- from pymodaq.utils.parameter import utils as putils
25
- from pymodaq.utils import daq_utils as utils
20
+ from pymodaq_plugin_manager.manager import PluginManager
21
+ from pymodaq_plugin_manager.validate import get_pypi_pymodaq
22
+
23
+ from pymodaq_utils.logger import set_logger, get_module_name
24
+ from pymodaq_utils import utils
25
+ from pymodaq_utils.utils import get_version, find_dict_in_list_from_key_val
26
+ from pymodaq_utils import config as configmod
27
+ from pymodaq_utils.enums import BaseEnum
28
+
29
+ from pymodaq_gui.parameter import ParameterTree, Parameter
30
+ from pymodaq_gui.utils import DockArea, Dock, select_file
31
+ import pymodaq_gui.utils.layout as layout_mod
32
+ from pymodaq_gui.messenger import messagebox
33
+ from pymodaq_gui.parameter import utils as putils
34
+ from pymodaq_gui.managers.roi_manager import ROISaver
35
+ from pymodaq_gui.utils.custom_app import CustomApp
36
+
26
37
  from pymodaq.utils.managers.modules_manager import ModulesManager
27
- from pymodaq.utils.daq_utils import get_version, find_dict_in_list_from_key_val
28
38
  from pymodaq.utils.managers.preset_manager import PresetManager
29
39
  from pymodaq.utils.managers.overshoot_manager import OvershootManager
30
40
  from pymodaq.utils.managers.remote_manager import RemoteManager
31
- from pymodaq.utils.managers.roi_manager import ROISaver
32
- from pymodaq.utils.exceptions import DetectorError, ActuatorError, PIDError, MasterSlaveError
33
- from pymodaq.utils import config as configmod
34
- from pymodaq.utils.parameter import ParameterTree, Parameter
41
+ from pymodaq.utils.exceptions import DetectorError, ActuatorError, MasterSlaveError
42
+ from pymodaq.utils.daq_utils import get_instrument_plugins
35
43
  from pymodaq.utils.leco.utils import start_coordinator
44
+ from pymodaq.utils import config as config_mod_pymodaq
45
+
36
46
  from pymodaq.control_modules.daq_move import DAQ_Move
37
47
  from pymodaq.control_modules.daq_viewer import DAQ_Viewer
38
- from pymodaq.extensions.pid.actuator_controller import PIDController
39
- from pymodaq import extensions as extmod
40
-
41
- from pymodaq_plugin_manager.manager import PluginManager
42
- from pymodaq_plugin_manager.validate import get_pypi_pymodaq
43
- from pymodaq.utils.daq_utils import get_instrument_plugins
48
+ from pymodaq.utils.gui_utils import get_splash_sc
44
49
 
45
- get_instrument_plugins()
50
+ from pymodaq import extensions as extmod
46
51
 
47
52
  logger = set_logger(get_module_name(__file__))
53
+ config = configmod.Config()
48
54
 
55
+ get_instrument_plugins()
56
+ extensions = extmod.get_extensions()
49
57
 
50
- config = configmod.Config()
51
58
 
52
59
  local_path = configmod.get_set_local_dir()
53
60
  now = datetime.datetime.now()
54
- preset_path = configmod.get_set_preset_path()
61
+ preset_path = config_mod_pymodaq.get_set_preset_path()
55
62
  log_path = configmod.get_set_log_path()
56
- layout_path = configmod.get_set_layout_path()
57
- overshoot_path = configmod.get_set_overshoot_path()
58
- roi_path = configmod.get_set_roi_path()
59
- remote_path = configmod.get_set_remote_path()
63
+ layout_path = config_mod_pymodaq.get_set_layout_path()
64
+ overshoot_path = config_mod_pymodaq.get_set_overshoot_path()
65
+ roi_path = config_mod_pymodaq.get_set_roi_path()
66
+ remote_path = config_mod_pymodaq.get_set_remote_path()
67
+
68
+
69
+ class ManagerEnums(BaseEnum):
70
+ preset = 0
71
+ remote = 1
72
+ overshoot = 2
73
+ roi = 3
74
+
75
+ class PymodaqUpdateTableWidget(QTableWidget):
76
+ '''
77
+ A class to represent PyMoDAQ and its subpackages'
78
+ available updates as a table.
79
+ '''
80
+ def __init__(self):
81
+ super().__init__()
60
82
 
61
- extensions = extmod.get_extensions()
83
+ self._checkboxes = []
84
+ self._package_versions = []
85
+
86
+ def setHorizontalHeaderLabels(self, labels):
87
+ super().setHorizontalHeaderLabels(labels)
88
+ self.setColumnCount(len(labels))
89
+
90
+ def append_row(self, checkbox, package, current_version, available_version):
91
+ row = len(self._checkboxes)
92
+
93
+ self._checkboxes.append(checkbox)
94
+ self._package_versions.append(f'{package}=={available_version}')
95
+
96
+ checkbox_widget = QWidget()
97
+
98
+ checkbox.setChecked(True)
99
+ checkbox.setToolTip("Check to install update")
100
+
101
+ checkbox_layout = QtWidgets.QHBoxLayout()
102
+ checkbox_layout.addWidget(checkbox)
103
+ checkbox_layout.setAlignment(Qt.AlignCenter)
104
+ checkbox_layout.setContentsMargins(0, 0, 0, 0)
105
+
106
+ checkbox_widget.setLayout(checkbox_layout)
107
+
108
+ # Add the checkbox widget to the table
109
+ self.setCellWidget(row, 0, checkbox_widget)
62
110
 
111
+ # Add labels in the other columns
112
+ self.setItem(row, 1, QTableWidgetItem(str(package)))
113
+ self.setItem(row, 2, QTableWidgetItem(str(current_version)))
114
+ self.setItem(row, 3, QTableWidgetItem(str(available_version)))
63
115
 
64
- class DashBoard(QObject):
116
+
117
+ def get_checked_data(self):
118
+ checked = list(map(lambda c : c.isChecked(), self._checkboxes))
119
+ return list(np.array(self._package_versions)[checked])
120
+
121
+ def sizeHint(self):
122
+ self.resizeColumnsToContents()
123
+ self.resizeRowsToContents()
124
+
125
+ # Compute the size to adapt the window (header + borders + sum of all the elements)
126
+ width = self.verticalHeader().width() \
127
+ + self.frameWidth() * 2 \
128
+ + sum([self.columnWidth(i) for i in range(self.columnCount())])
129
+
130
+ height = self.horizontalHeader().height() \
131
+ + self.frameWidth() * 2 \
132
+ + sum([self.rowHeight(i) for i in range(self.rowCount())])
133
+
134
+ return QSize(width, height)
135
+
136
+ class DashBoard(CustomApp):
65
137
  """
66
138
  Main class initializing a DashBoard interface to display det and move modules and logger """
67
139
  status_signal = Signal(str)
68
140
  preset_loaded_signal = Signal(bool)
69
141
  new_preset_created = Signal()
70
142
 
143
+ settings_name = 'dashboard_settings'
144
+ _splash_sc = None
145
+
146
+ params = [
147
+ {'title': 'Log level', 'name': 'log_level', 'type': 'list',
148
+ 'value': config('general', 'debug_level'),
149
+ 'limits': config('general', 'debug_levels')},
150
+
151
+ {'title': 'Loaded presets', 'name': 'loaded_files', 'type': 'group', 'children': [
152
+ {'title': 'Preset file', 'name': 'preset_file', 'type': 'str', 'value': '',
153
+ 'readonly': True},
154
+ {'title': 'Overshoot file', 'name': 'overshoot_file', 'type': 'str', 'value': '',
155
+ 'readonly': True},
156
+ {'title': 'Layout file', 'name': 'layout_file', 'type': 'str', 'value': '',
157
+ 'readonly': True},
158
+ {'title': 'ROI file', 'name': 'roi_file', 'type': 'str', 'value': '',
159
+ 'readonly': True},
160
+ {'title': 'Remote file', 'name': 'remote_file', 'type': 'str', 'value': '',
161
+ 'readonly': True},
162
+ ]},
163
+ {'title': 'Actuators Init.', 'name': 'actuators', 'type': 'group', 'children': []},
164
+ {'title': 'Detectors Init.', 'name': 'detectors', 'type': 'group', 'children': []},
165
+ ]
166
+
71
167
  def __init__(self, dockarea):
72
168
  """
73
169
 
@@ -76,7 +172,8 @@ class DashBoard(QObject):
76
172
  parent: (dockarea) instance of the modified pyqtgraph Dockarea (see daq_utils)
77
173
  """
78
174
 
79
- super().__init__()
175
+ super().__init__(dockarea)
176
+
80
177
  logger.info('Initializing Dashboard')
81
178
  self.extra_params = []
82
179
  self.preset_path = preset_path
@@ -90,14 +187,10 @@ class DashBoard(QObject):
90
187
  self.extensions = dict([])
91
188
  self.extension_windows = []
92
189
 
93
- self.dockarea = dockarea
94
190
  self.dockarea.dock_signal.connect(self.save_layout_state_auto)
95
- self.mainwindow = dockarea.parent()
191
+
96
192
  self.title = ''
97
- splash_path = Path(__file__).parent.joinpath('splash.png')
98
193
 
99
- splash = QtGui.QPixmap(str(splash_path))
100
- self.splash_sc = QtWidgets.QSplashScreen(splash, Qt.WindowStaysOnTopHint)
101
194
  self.overshoot_manager = None
102
195
  self.preset_manager = None
103
196
  self.roi_saver: ROISaver = None
@@ -114,12 +207,23 @@ class DashBoard(QObject):
114
207
  self.preset_file = None
115
208
  self.actuators_modules = []
116
209
  self.detector_modules = []
117
- self.setupUI()
210
+
211
+ self.setup_ui()
212
+
213
+ self.mainwindow.setVisible(True)
118
214
 
119
215
  logger.info('Dashboard Initialized')
120
216
 
121
217
  if config('general', 'check_version'):
122
- self.check_version(show=False)
218
+ if self.check_update(show=False):
219
+ sys.exit(0)
220
+
221
+ @classmethod
222
+ @property
223
+ def splash_sc(cls) -> QtWidgets.QSplashScreen:
224
+ if cls._splash_sc is None:
225
+ cls._splash_sc = get_splash_sc()
226
+ return cls._splash_sc
123
227
 
124
228
  def set_preset_path(self, path):
125
229
  self.preset_path = path
@@ -128,11 +232,13 @@ class DashBoard(QObject):
128
232
 
129
233
  def set_extra_preset_params(self, params, param_options=[]):
130
234
  self.extra_params = params
131
- self.preset_manager = PresetManager(path=self.preset_path, extra_params=params, param_options=param_options)
235
+ self.preset_manager = PresetManager(path=self.preset_path, extra_params=params,
236
+ param_options=param_options)
132
237
 
133
238
  def add_status(self, txt):
134
239
  """
135
- Add the QListWisgetItem initialized with txt informations to the User Interface logger_list and to the save_parameters.logger array.
240
+ Add the QListWisgetItem initialized with txt informations to the User Interface
241
+ logger_list and to the save_parameters.logger array.
136
242
 
137
243
  =============== =========== ======================
138
244
  **Parameters** **Type** **Description**
@@ -179,6 +285,7 @@ class DashBoard(QObject):
179
285
  self.scan_module = extmod.DAQScan(dockarea=area, dashboard=self)
180
286
  self.extensions['DAQScan'] = self.scan_module
181
287
  self.scan_module.status_signal.connect(self.add_status)
288
+ #win.setWindowTitle("DAQScan")
182
289
  win.show()
183
290
  return self.scan_module
184
291
 
@@ -239,7 +346,8 @@ class DashBoard(QObject):
239
346
  """ Init and load an extension from a plugin package
240
347
 
241
348
  ext: dict
242
- dictionary containing info on the extension plugin package and class to be loaded, it contains four
349
+ dictionary containing info on the extension plugin package and class to be loaded,
350
+ it contains four
243
351
  keys:
244
352
 
245
353
  * pkg: the name of the plugin package
@@ -263,7 +371,159 @@ class DashBoard(QObject):
263
371
  self.extension_windows[-1].show()
264
372
  return self.extensions[ext['class_name']]
265
373
 
266
- def create_menu(self, menubar):
374
+ def setup_actions(self):
375
+ self.add_action('log', 'Log File', '', "Show Log File in default editor",
376
+ auto_toolbar=False)
377
+ self.add_action('quit', 'Quit', 'close2', "Quit program")
378
+ self.toolbar.addSeparator()
379
+ self.add_action('config', 'Configuration file', 'tree', "General Settings")
380
+ self.add_action('restart', 'Restart', '', "Restart the Dashboard",
381
+ auto_toolbar=False)
382
+ self.add_action('leco', 'Run Leco Coordinator', '', 'Run a Coordinator on this localhost',
383
+ auto_toolbar=False)
384
+ self.add_action('load_layout', 'Load Layout', '',
385
+ 'Load the Saved Docks layout corresponding to the current preset',
386
+ auto_toolbar=False)
387
+ self.add_action('save_layout', 'Save Layout', '',
388
+ 'Save the Saved Docks layout corresponding to the current preset',
389
+ auto_toolbar=False)
390
+ self.add_action('log_window', 'Show/hide log window', '', checkable=True,
391
+ auto_toolbar=False)
392
+ self.add_action('new_preset', 'New Preset', '',
393
+ 'Create a new experimental setup configuration file: a "preset"',
394
+ auto_toolbar=False)
395
+ self.add_action('modify_preset', 'Modify Preset', '',
396
+ 'Modify an existing experimental setup configuration file: a "preset"',
397
+ auto_toolbar=False)
398
+ self.add_action('load_preset', 'LOAD', 'Open',
399
+ tip='Load the selected Preset: ')
400
+ self.add_widget('preset_list', QtWidgets.QComboBox, toolbar=self.toolbar,
401
+ signal_str='currentTextChanged', slot=self.update_preset_action)
402
+
403
+ self.update_preset_action_list()
404
+
405
+ self.add_action('new_overshoot', 'New Overshoot', '',
406
+ 'Create a new experimental setup overshoot configuration file',
407
+ auto_toolbar=False)
408
+ self.add_action('modify_overshoot', 'Modify Overshoot', '',
409
+ 'Modify an existing experimental setup overshoot configuration file',
410
+ auto_toolbar=False)
411
+
412
+ for ind_file, file in enumerate(config_mod_pymodaq.get_set_overshoot_path().iterdir()):
413
+ if file.suffix == '.xml':
414
+ self.add_action(self.get_action_from_file(file, ManagerEnums.overshoot), file.stem,
415
+ auto_toolbar=False)
416
+
417
+ self.add_action('save_roi', 'Save ROIs as a file', '', auto_toolbar=False)
418
+ self.add_action('modify_roi', 'Modify ROI file', '', auto_toolbar=False)
419
+
420
+ for ind_file, file in enumerate(config_mod_pymodaq.get_set_roi_path().iterdir()):
421
+ if file.suffix == '.xml':
422
+ self.add_action(self.get_action_from_file(file, ManagerEnums.roi), file.stem,
423
+ '', auto_toolbar=False)
424
+
425
+ self.add_action('new_remote', 'Create New Remote', '', auto_toolbar=False)
426
+ self.add_action('modify_remote', 'Modify Remote file', '', auto_toolbar=False)
427
+ for ind_file, file in enumerate(config_mod_pymodaq.get_set_remote_path().iterdir()):
428
+ if file.suffix == '.xml':
429
+ self.add_action(self.get_action_from_file(file, ManagerEnums.remote),
430
+ file.stem, '', auto_toolbar=False)
431
+ self.add_action('activate_overshoot', 'Activate overshoot', 'Error',
432
+ tip='if activated, apply an overshoot if one is configured',
433
+ checkable=True, enabled=False)
434
+ self.toolbar.addSeparator()
435
+ self.add_action('do_scan', 'Do Scans', 'surfacePlot',
436
+ tip='Open the DAQ Scan extension to acquire data as a function of '
437
+ 'one or more parameter')
438
+ self.toolbar.addSeparator()
439
+ self.add_action('do_log', 'Log data', '', auto_toolbar=False)
440
+ self.add_action('do_pid', 'PID module', auto_toolbar=False)
441
+ self.add_action('console', 'IPython Console', auto_toolbar=False)
442
+ self.add_action('bayesian', 'Bayesian Optimisation', auto_toolbar=False)
443
+
444
+ self.add_action('about', 'About', 'information2')
445
+ self.add_action('help', 'Help', 'help1')
446
+ self.get_action('help').setShortcut(QtGui.QKeySequence('F1'))
447
+ self.add_action('check_update', 'Check Updates', '', auto_toolbar=False)
448
+ self.toolbar.addSeparator()
449
+ self.add_action('plugin_manager', 'Plugin Manager', '')
450
+
451
+ def update_preset_action_list(self):
452
+ presets = []
453
+ self.get_action('preset_list').clear()
454
+ for ind_file, file in enumerate(self.preset_path.iterdir()):
455
+ if file.suffix == '.xml':
456
+ filestem = file.stem
457
+ if not self.has_action(self.get_action_from_file(file, ManagerEnums.preset)):
458
+ self.add_action(self.get_action_from_file(file, ManagerEnums.preset),
459
+ filestem, '', f'Load the {filestem}.xml preset',
460
+ auto_toolbar=False)
461
+ presets.append(filestem)
462
+
463
+ self.get_action('preset_list').addItems(presets)
464
+
465
+ def update_preset_action(self, preset_name: str):
466
+ self.get_action('load_preset').setToolTip(f'Load the {preset_name}.xml preset file!')
467
+
468
+ def connect_things(self):
469
+ self.status_signal[str].connect(self.add_status)
470
+ self.connect_action('log', self.show_log)
471
+ self.connect_action('config', self.show_config)
472
+ self.connect_action('quit', self.quit_fun)
473
+ self.connect_action('restart', self.restart_fun)
474
+ self.connect_action('leco', start_coordinator)
475
+ self.connect_action('load_layout', self.load_layout_state)
476
+ self.connect_action('save_layout', self.save_layout_state)
477
+ self.connect_action('log_window', self.logger_dock.setVisible)
478
+ self.connect_action('new_preset', self.create_preset)
479
+ self.connect_action('modify_preset', self.modify_preset)
480
+
481
+ for ind_file, file in enumerate(self.preset_path.iterdir()):
482
+ if file.suffix == '.xml':
483
+ self.connect_action(self.get_action_from_file(file, ManagerEnums.preset),
484
+ self.create_menu_slot(self.preset_path.joinpath(file)))
485
+ self.connect_action('load_preset',
486
+ lambda: self.set_preset_mode(
487
+ self.preset_path.joinpath(
488
+ f"{self.get_action('preset_list').currentText()}.xml")))
489
+ self.connect_action('new_overshoot', self.create_overshoot)
490
+ self.connect_action('modify_overshoot', self.modify_overshoot)
491
+ self.connect_action('activate_overshoot', self.activate_overshoot)
492
+
493
+ for ind_file, file in enumerate(config_mod_pymodaq.get_set_overshoot_path().iterdir()):
494
+ if file.suffix == '.xml':
495
+ self.connect_action(self.get_action_from_file(file, ManagerEnums.overshoot),
496
+ self.create_menu_slot_over(
497
+ config_mod_pymodaq.get_set_overshoot_path().joinpath(file)))
498
+
499
+ self.connect_action('save_roi', self.create_roi_file)
500
+ self.connect_action('modify_roi', self.modify_roi)
501
+
502
+ for ind_file, file in enumerate(config_mod_pymodaq.get_set_roi_path().iterdir()):
503
+ if file.suffix == '.xml':
504
+ self.connect_action(self.get_action_from_file(file, ManagerEnums.roi),
505
+ self.create_menu_slot_roi(config_mod_pymodaq.get_set_roi_path().joinpath(file)))
506
+
507
+ self.connect_action('new_remote', self.create_remote)
508
+ self.connect_action('modify_remote', self.modify_remote)
509
+ for ind_file, file in enumerate(config_mod_pymodaq.get_set_remote_path().iterdir()):
510
+ if file.suffix == '.xml':
511
+ self.connect_action(self.get_action_from_file(file, ManagerEnums.remote),
512
+ self.create_menu_slot_remote(
513
+ config_mod_pymodaq.get_set_remote_path().joinpath(file)))
514
+
515
+ self.connect_action('do_scan', lambda: self.load_scan_module())
516
+ self.connect_action('do_log', lambda: self.load_log_module())
517
+ self.connect_action('do_pid', lambda: self.load_pid_module())
518
+ self.connect_action('console', lambda: self.load_console())
519
+ self.connect_action('bayesian', lambda: self.load_bayesian())
520
+
521
+ self.connect_action('about', self.show_about)
522
+ self.connect_action('help', self.show_help)
523
+ self.connect_action('check_update', lambda: self.check_update(True))
524
+ self.connect_action('plugin_manager', self.start_plugin_manager)
525
+
526
+ def setup_menu(self, menubar: QtWidgets.QMenuBar = None):
267
527
  """
268
528
  Create the menubar object looking like :
269
529
  """
@@ -271,126 +531,95 @@ class DashBoard(QObject):
271
531
 
272
532
  # %% create Settings menu
273
533
  self.file_menu = menubar.addMenu('File')
274
- self.file_menu.addAction('Show log file', self.show_log)
275
- self.file_menu.addAction('Show configuration file', self.show_config)
534
+ self.file_menu.addAction(self.get_action('log'))
535
+ self.file_menu.addAction(self.get_action('config'))
276
536
  self.file_menu.addSeparator()
277
- quit_action = self.file_menu.addAction('Quit')
278
- restart_action = self.file_menu.addAction('Restart')
279
- quit_action.triggered.connect(self.quit_fun)
280
- restart_action.triggered.connect(self.restart_fun)
537
+ self.file_menu.addAction(self.get_action('quit'))
538
+ self.file_menu.addAction(self.get_action('restart'))
281
539
 
282
540
  self.settings_menu = menubar.addMenu('Settings')
283
- action_leco = self.settings_menu.addAction('Run Leco Coordinator')
284
- action_leco.triggered.connect(start_coordinator)
541
+ self.settings_menu.addAction(self.get_action('leco'))
285
542
  docked_menu = self.settings_menu.addMenu('Docked windows')
286
- action_load = docked_menu.addAction('Load Layout')
287
- action_save = docked_menu.addAction('Save Layout')
288
-
289
- action_load.triggered.connect(self.load_layout_state)
290
- action_save.triggered.connect(self.save_layout_state)
543
+ docked_menu.addAction(self.get_action('load_layout'))
544
+ docked_menu.addAction(self.get_action('save_layout'))
291
545
 
292
546
  docked_menu.addSeparator()
293
- action_show_log = docked_menu.addAction('Show/hide log window')
294
- action_show_log.setCheckable(True)
295
- action_show_log.toggled.connect(self.logger_dock.setVisible)
547
+ docked_menu.addAction(self.get_action('log_window'))
296
548
 
297
549
  self.preset_menu = menubar.addMenu('Preset Modes')
298
- action_new_preset = self.preset_menu.addAction('New Preset')
299
- # action.triggered.connect(lambda: self.show_file_attributes(type_info='managers'))
300
- action_new_preset.triggered.connect(self.create_preset)
301
- action_modify_preset = self.preset_menu.addAction('Modify Preset')
302
- action_modify_preset.triggered.connect(self.modify_preset)
550
+ self.preset_menu.addAction(self.get_action('new_preset'))
551
+ self.preset_menu.addAction(self.get_action('modify_preset'))
303
552
  self.preset_menu.addSeparator()
304
- self.load_preset = self.preset_menu.addMenu('Load presets')
553
+ self.load_preset_menu = self.preset_menu.addMenu('Load presets')
305
554
 
306
- slots = dict([])
307
555
  for ind_file, file in enumerate(self.preset_path.iterdir()):
308
556
  if file.suffix == '.xml':
309
- filestem = file.stem
310
- slots[filestem] = self.load_preset.addAction(filestem)
311
- slots[filestem].triggered.connect(
312
- self.create_menu_slot(self.preset_path.joinpath(file)))
557
+ self.load_preset_menu.addAction(
558
+ self.get_action(self.get_action_from_file(file, ManagerEnums.preset)))
313
559
 
314
560
  self.overshoot_menu = menubar.addMenu('Overshoot Modes')
315
- action_new_overshoot = self.overshoot_menu.addAction('New Overshoot')
316
- # action.triggered.connect(lambda: self.show_file_attributes(type_info='managers'))
317
- action_new_overshoot.triggered.connect(self.create_overshoot)
318
- action_modify_overshoot = self.overshoot_menu.addAction('Modify Overshoot')
319
- action_modify_overshoot.triggered.connect(self.modify_overshoot)
561
+ self.overshoot_menu.addAction(self.get_action('new_overshoot'))
562
+ self.overshoot_menu.addAction(self.get_action('modify_overshoot'))
563
+ self.overshoot_menu.addAction(self.get_action('activate_overshoot'))
320
564
  self.overshoot_menu.addSeparator()
321
- load_overshoot = self.overshoot_menu.addMenu('Load Overshoots')
565
+ load_overshoot_menu = self.overshoot_menu.addMenu('Load Overshoots')
322
566
 
323
- slots_over = dict([])
324
- for ind_file, file in enumerate(configmod.get_set_overshoot_path().iterdir()):
567
+ for ind_file, file in enumerate(config_mod_pymodaq.get_set_overshoot_path().iterdir()):
325
568
  if file.suffix == '.xml':
326
- filestem = file.stem
327
- slots_over[filestem] = load_overshoot.addAction(filestem)
328
- slots_over[filestem].triggered.connect(
329
- self.create_menu_slot_over(configmod.get_set_overshoot_path().joinpath(file)))
569
+ load_overshoot_menu.addAction(
570
+ self.get_action(self.get_action_from_file(file, ManagerEnums.overshoot)))
330
571
 
331
572
  self.roi_menu = menubar.addMenu('ROI Modes')
332
- action_new_roi = self.roi_menu.addAction('Save Current ROIs as a file')
333
- action_new_roi.triggered.connect(self.create_roi_file)
334
- action_modify_roi = self.roi_menu.addAction('Modify roi config')
335
- action_modify_roi.triggered.connect(self.modify_roi)
573
+ self.roi_menu.addAction(self.get_action('save_roi'))
574
+ self.roi_menu.addAction(self.get_action('modify_roi'))
336
575
  self.roi_menu.addSeparator()
337
- load_roi = self.roi_menu.addMenu('Load roi configs')
576
+ load_roi_menu = self.roi_menu.addMenu('Load roi configs')
338
577
 
339
- slots = dict([])
340
- for ind_file, file in enumerate(configmod.get_set_roi_path().iterdir()):
578
+ for ind_file, file in enumerate(config_mod_pymodaq.get_set_roi_path().iterdir()):
341
579
  if file.suffix == '.xml':
342
- filestem = file.stem
343
- slots[filestem] = load_roi.addAction(filestem)
344
- slots[filestem].triggered.connect(
345
- self.create_menu_slot_roi(configmod.get_set_roi_path().joinpath(file)))
580
+ load_roi_menu.addAction(
581
+ self.get_action(self.get_action_from_file(file, ManagerEnums.roi)))
346
582
 
347
583
  self.remote_menu = menubar.addMenu('Remote/Shortcuts Control')
348
584
  self.remote_menu.addAction('New remote config.', self.create_remote)
349
585
  self.remote_menu.addAction('Modify remote config.', self.modify_remote)
350
586
  self.remote_menu.addSeparator()
351
- load_remote = self.remote_menu.addMenu('Load remote config.')
587
+ load_remote_menu = self.remote_menu.addMenu('Load remote config.')
352
588
 
353
- slots = dict([])
354
- for ind_file, file in enumerate(configmod.get_set_remote_path().iterdir()):
589
+ for ind_file, file in enumerate(config_mod_pymodaq.get_set_remote_path().iterdir()):
355
590
  if file.suffix == '.xml':
356
- filestem = file.stem
357
- slots[filestem] = load_remote.addAction(filestem)
358
- slots[filestem].triggered.connect(
359
- self.create_menu_slot_remote(configmod.get_set_remote_path().joinpath(file)))
360
-
361
- # actions menu
362
- self.actions_menu = menubar.addMenu('Extensions')
363
- action_scan = self.actions_menu.addAction('Do Scans')
364
- action_scan.triggered.connect(lambda: self.load_scan_module())
365
- action_log = self.actions_menu.addAction('Log data')
366
- action_log.triggered.connect(lambda: self.load_log_module())
367
- action_pid = self.actions_menu.addAction('PID module')
368
- action_pid.triggered.connect(lambda: self.load_pid_module())
369
- action_console = self.actions_menu.addAction('IPython Console')
370
- action_console.triggered.connect(lambda: self.load_console())
371
- action_bayesian = self.actions_menu.addAction('Bayesian Optimisation')
372
- action_bayesian.triggered.connect(lambda: self.load_bayesian())
373
-
591
+ load_remote_menu.addAction(
592
+ self.get_action(self.get_action_from_file(file, ManagerEnums.remote)))
593
+
594
+ # extensions menu
595
+ self.extensions_menu = menubar.addMenu('Extensions')
596
+ self.extensions_menu.addAction(self.get_action('do_scan'))
597
+ self.extensions_menu.addAction(self.get_action('do_log'))
598
+ self.extensions_menu.addAction(self.get_action('do_pid'))
599
+ self.extensions_menu.addAction(self.get_action('console'))
600
+ self.extensions_menu.addAction(self.get_action('bayesian'))
601
+
602
+ # extensions from plugins
374
603
  extensions_actions = []
375
604
  for ext in extensions:
376
- extensions_actions.append(self.actions_menu.addAction(ext['name']))
605
+ extensions_actions.append(self.extensions_menu.addAction(ext['name']))
377
606
  extensions_actions[-1].triggered.connect(self.create_menu_slot_ext(ext))
378
607
 
379
-
380
608
  # help menu
381
609
  help_menu = menubar.addMenu('?')
382
- action_about = help_menu.addAction('About')
383
- action_about.triggered.connect(self.show_about)
384
- action_help = help_menu.addAction('Help')
385
- action_help.triggered.connect(self.show_help)
386
- action_help.setShortcut(QtGui.QKeySequence('F1'))
387
-
610
+ help_menu.addAction(self.get_action('about'))
611
+ help_menu.addAction(self.get_action('help'))
388
612
  help_menu.addSeparator()
389
- action_update = help_menu.addAction('Check Version')
390
- action_update.triggered.connect(lambda: self.check_version(True))
613
+ help_menu.addAction(self.get_action('check_update'))
614
+ help_menu.addAction(self.get_action('plugin_manager'))
391
615
 
392
- action_plugin_manager = help_menu.addAction('Plugin Manager')
393
- action_plugin_manager.triggered.connect(self.start_plugin_manager)
616
+ self.overshoot_menu.setEnabled(False)
617
+ self.roi_menu.setEnabled(False)
618
+ self.remote_menu.setEnabled(False)
619
+ self.extensions_menu.setEnabled(False)
620
+ self.file_menu.setEnabled(True)
621
+ self.settings_menu.setEnabled(True)
622
+ self.preset_menu.setEnabled(True)
394
623
 
395
624
  def start_plugin_manager(self):
396
625
  self.win_plug_manager = QtWidgets.QMainWindow()
@@ -421,7 +650,10 @@ class DashBoard(QObject):
421
650
  try:
422
651
  if self.preset_file is not None:
423
652
  self.roi_saver.set_new_roi(self.preset_file.stem)
424
- self.create_menu(self.menubar)
653
+ self.add_action(self.get_action_from_file(self.preset_file,
654
+ ManagerEnums.roi),
655
+ self.preset_file.stem, '')
656
+ self.setup_menu(self.menubar)
425
657
 
426
658
  except Exception as e:
427
659
  logger.exception(str(e))
@@ -430,7 +662,10 @@ class DashBoard(QObject):
430
662
  try:
431
663
  if self.preset_file is not None:
432
664
  self.remote_manager.set_new_remote(self.preset_file.stem)
433
- self.create_menu(self.menubar)
665
+ self.add_action(self.get_action_from_file(self.preset_file,
666
+ ManagerEnums.remote),
667
+ self.preset_file.stem, '')
668
+ self.setup_menu(self.menubar)
434
669
 
435
670
  except Exception as e:
436
671
  logger.exception(str(e))
@@ -439,21 +674,31 @@ class DashBoard(QObject):
439
674
  try:
440
675
  if self.preset_file is not None:
441
676
  self.overshoot_manager.set_new_overshoot(self.preset_file.stem)
442
- self.create_menu(self.menubar)
677
+ self.add_action(self.get_action_from_file(self.preset_file,
678
+ ManagerEnums.overshoot),
679
+ self.preset_file.stem, '')
680
+ self.setup_menu(self.menubar)
443
681
  except Exception as e:
444
682
  logger.exception(str(e))
445
683
 
446
684
  def create_preset(self):
447
685
  try:
448
- self.preset_manager.set_new_preset()
449
- self.create_menu(self.menubar)
450
- self.new_preset_created.emit()
686
+ status = self.preset_manager.set_new_preset()
687
+ if status:
688
+ self.update_preset_action_list()
689
+ self.setup_menu(self.menubar)
690
+ self.new_preset_created.emit()
451
691
  except Exception as e:
452
692
  logger.exception(str(e))
453
693
 
694
+ @staticmethod
695
+ def get_action_from_file(file: Path, manager: ManagerEnums):
696
+ return f'{file.stem}_{manager.name}'
697
+
454
698
  def modify_remote(self):
455
699
  try:
456
- path = select_file(start_path=configmod.get_set_remote_path(), save=False, ext='xml')
700
+ path = select_file(start_path=config_mod_pymodaq.get_set_remote_path(), save=False,
701
+ ext='xml')
457
702
  if path != '':
458
703
  self.remote_manager.set_file_remote(path)
459
704
 
@@ -464,7 +709,8 @@ class DashBoard(QObject):
464
709
 
465
710
  def modify_overshoot(self):
466
711
  try:
467
- path = select_file(start_path=configmod.get_set_overshoot_path(), save=False, ext='xml')
712
+ path = select_file(start_path=config_mod_pymodaq.get_set_overshoot_path(),
713
+ save=False, ext='xml')
468
714
  if path != '':
469
715
  self.overshoot_manager.set_file_overshoot(path)
470
716
 
@@ -475,7 +721,8 @@ class DashBoard(QObject):
475
721
 
476
722
  def modify_roi(self):
477
723
  try:
478
- path = select_file(start_path=configmod.get_set_roi_path(), save=False, ext='xml')
724
+ path = select_file(start_path=config_mod_pymodaq.get_set_roi_path(),
725
+ save=False, ext='xml')
479
726
  if path != '':
480
727
  self.roi_saver.set_file_roi(path)
481
728
 
@@ -494,9 +741,10 @@ class DashBoard(QObject):
494
741
  self.remove_preset_related_files(path.name)
495
742
  if self.detector_modules:
496
743
  mssg = QtWidgets.QMessageBox()
497
- mssg.setText('You have to restart the application to take the modifications into account!\n\n'
498
- 'The related files: ROI, Layout, Overshoot and Remote will be deleted'
499
- ' if existing!\n\n'
744
+ mssg.setText('You have to restart the application to take the modifications'
745
+ ' into account!\n\n'
746
+ 'The related files: ROI, Layout, Overshoot and Remote will be'
747
+ ' deleted if existing!\n\n'
500
748
  'Quitting the application...')
501
749
  mssg.exec()
502
750
  self.restart_fun()
@@ -507,10 +755,10 @@ class DashBoard(QObject):
507
755
  logger.exception(str(e))
508
756
 
509
757
  def remove_preset_related_files(self, name):
510
- configmod.get_set_roi_path().joinpath(name).unlink(missing_ok=True)
511
- configmod.get_set_layout_path().joinpath(name).unlink(missing_ok=True)
512
- configmod.get_set_overshoot_path().joinpath(name).unlink(missing_ok=True)
513
- configmod.get_set_remote_path().joinpath(name).unlink(missing_ok=True)
758
+ config_mod_pymodaq.get_set_roi_path().joinpath(name).unlink(missing_ok=True)
759
+ config_mod_pymodaq.get_set_layout_path().joinpath(name).unlink(missing_ok=True)
760
+ config_mod_pymodaq.get_set_overshoot_path().joinpath(name).unlink(missing_ok=True)
761
+ config_mod_pymodaq.get_set_remote_path().joinpath(name).unlink(missing_ok=True)
514
762
 
515
763
  def quit_fun(self):
516
764
  """
@@ -568,7 +816,8 @@ class DashBoard(QObject):
568
816
  ret = False
569
817
  mssg = QtWidgets.QMessageBox()
570
818
  if ask:
571
- mssg.setText('You have to restart the application to take the modifications into account!')
819
+ mssg.setText('You have to restart the application to take the'
820
+ ' modifications into account!')
572
821
  mssg.setInformativeText("Do you want to restart?")
573
822
  mssg.setStandardButtons(mssg.Ok | mssg.Cancel)
574
823
  ret = mssg.exec()
@@ -610,7 +859,8 @@ class DashBoard(QObject):
610
859
  path = layout_path.joinpath(self.preset_file.stem + '.dock')
611
860
  self.save_layout_state(path)
612
861
 
613
- def add_move(self, plug_name, plug_settings, plug_type, move_docks, move_forms, actuators_modules):
862
+ def add_move(self, plug_name, plug_settings, plug_type, move_docks, move_forms,
863
+ actuators_modules) -> DAQ_Move:
614
864
 
615
865
  move_docks.append(Dock(plug_name, size=(150, 250)))
616
866
  if len(move_docks) == 1:
@@ -631,21 +881,56 @@ class DashBoard(QObject):
631
881
  mssg = f'Could not set this setting: {str(e)}\n' \
632
882
  f'The Preset is no more compatible with the plugin {plug_type}'
633
883
  logger.warning(mssg)
634
- self.splash_sc.showMessage(mssg, color=Qt.white)
884
+ self.splash_sc.showMessage(mssg)
635
885
  QtWidgets.QApplication.processEvents()
636
886
 
637
887
  mov_mod_tmp.bounds_signal[bool].connect(self.stop_moves)
638
888
  move_docks[-1].addWidget(move_forms[-1])
639
889
  actuators_modules.append(mov_mod_tmp)
890
+ return mov_mod_tmp
891
+
892
+ def add_move_from_extension(self, name: str, instrument_name: str,
893
+ instrument_controller: Any):
894
+ """ Specific method to add a DAQ_Move within the Dashboard. This Particular actuator
895
+ should be defined in the plugin of the extension and is used to mimic an actuator while
896
+ move_abs is actually triggering an action on the extension which loaded it
897
+
898
+ For an exemple, see the PyMoDAQ builtin PID extension
899
+
900
+ Parameters
901
+ ----------
902
+ name: str
903
+ The name to print on the UI title
904
+ instrument_name: str
905
+ The name of the instrument class, for instance PID for the daq_move_PID
906
+ module and the DAQ_Move_PID instrument class
907
+ instrument_controller: object
908
+ whatever object is used to communicate between the instrument module and the extension
909
+ which created it
910
+ """
911
+ actuator = self.add_move(name, None, instrument_name, [], [], [])
912
+ actuator.controller = instrument_controller
913
+ actuator.master = False
914
+ actuator.init_hardware_ui()
915
+ QtWidgets.QApplication.processEvents()
916
+ self.poll_init(actuator)
917
+ QtWidgets.QApplication.processEvents()
640
918
 
641
- def add_det(self, plug_name, plug_settings, det_docks_settings, det_docks_viewer, detector_modules):
919
+ # Update actuators modules and module manager
920
+ self.actuators_modules.append(actuator)
921
+ self.update_module_manager()
642
922
 
643
- plug_type = plug_settings.child('main_settings', 'DAQ_type').value()
644
- plug_subtype = plug_settings.child('main_settings', 'detector_type').value()
923
+ def add_det(self, plug_name, plug_settings, det_docks_settings, det_docks_viewer,
924
+ detector_modules, plug_type: str = None, plug_subtype: str = None) -> DAQ_Viewer:
925
+ if plug_type is None:
926
+ plug_type = plug_settings.child('main_settings', 'DAQ_type').value()
927
+ if plug_subtype is None:
928
+ plug_subtype = plug_settings.child('main_settings', 'detector_type').value()
645
929
  det_docks_settings.append(Dock(plug_name + " settings", size=(150, 250)))
646
930
  det_docks_viewer.append(Dock(plug_name + " viewer", size=(350, 350)))
647
931
  if len(detector_modules) == 0:
648
- self.logger_dock.area.addDock(det_docks_settings[-1], 'bottom') # dockarea of the logger dock
932
+ self.logger_dock.area.addDock(det_docks_settings[-1], 'bottom')
933
+ # dockarea of the logger dock
649
934
  else:
650
935
  self.dockarea.addDock(det_docks_settings[-1], 'right',
651
936
  detector_modules[-1].viewer_docks[-1])
@@ -665,9 +950,52 @@ class DashBoard(QObject):
665
950
  mssg = f'Could not set this setting: {str(e)}\n' \
666
951
  f'The Preset is no more compatible with the plugin {plug_subtype}'
667
952
  logger.warning(mssg)
668
- self.splash_sc.showMessage(mssg, color=Qt.white)
953
+ self.splash_sc.showMessage(mssg)
669
954
 
670
955
  detector_modules.append(det_mod_tmp)
956
+ return det_mod_tmp
957
+
958
+ def add_det_from_extension(self, name: str, daq_type: str, instrument_name: str,
959
+ instrument_controller: Any):
960
+ """ Specific method to add a DAQ_Viewer within the Dashboard. This Particular detector
961
+ should be defined in the plugin of the extension and is used to mimic a grab while data
962
+ are actually coming from the extension which loaded it
963
+
964
+ For an exemple, see the pymodaq_plugins_datamixer plugin and its DataMixer extension
965
+
966
+ Parameters
967
+ ----------
968
+ name: str
969
+ The name to print on the UI title
970
+ daq_type: str
971
+ either DAQ0D, DAQ1D, DAQ2D or DAQND depending the type of the instrument
972
+ instrument_name: str
973
+ The name of the instrument class, for instance DataMixer for the daq_0Dviewer_DataMixer
974
+ module and the DAQ_0DViewer_DataMixer instrument class
975
+ instrument_controller: object
976
+ whatever object is used to communicate between the instrument module and the extension
977
+ which created it
978
+ """
979
+ detector = self.add_det(name, None, [], [], [],
980
+ plug_type=daq_type,
981
+ plug_subtype=instrument_name)
982
+ detector.controller = instrument_controller
983
+ detector.master = False
984
+ detector.init_hardware_ui()
985
+ QtWidgets.QApplication.processEvents()
986
+ self.poll_init(detector)
987
+ QtWidgets.QApplication.processEvents()
988
+
989
+ # Update actuators modules and module manager
990
+ self.detector_modules.append(detector)
991
+ self.update_module_manager()
992
+
993
+ def update_module_manager(self):
994
+ if self.modules_manager is None:
995
+ self.modules_manager = ModulesManager(self.detector_modules, self.actuators_modules)
996
+ else:
997
+ self.modules_manager.actuators_all = self.actuators_modules
998
+ self.modules_manager.detectors_all = self.detector_modules
671
999
 
672
1000
  def set_file_preset(self, filename) -> Tuple[List[DAQ_Move], List[DAQ_Viewer]]:
673
1001
  """
@@ -707,16 +1035,16 @@ class DashBoard(QObject):
707
1035
  self.preset_manager.preset_params.child('Detectors').children()]
708
1036
 
709
1037
  for plug in plugins:
710
- plug['ID'] = plug['value'].child('params', 'main_settings', 'controller_ID').value()
711
1038
  if plug["type"] == 'det':
712
- plug['status'] = plug['value'].child('params', 'detector_settings', 'controller_status').value()
1039
+ plug['ID'] = plug['value']['params', 'detector_settings', 'controller_ID']
1040
+ plug['status'] = plug['value']['params', 'detector_settings',
1041
+ 'controller_status']
713
1042
  else:
714
- if 'multiaxes' in [child.name() for child in plug['value'].child('params',
715
- 'move_settings').children()]:
716
- plug['status'] = plug['value'].child('params', 'move_settings',
717
- 'multiaxes', 'multi_status').value()
718
- else:
719
- plug['status'] = 'Master'
1043
+ plug['ID'] = plug['value']['params', 'move_settings',
1044
+ 'multiaxes', 'controller_ID']
1045
+ plug['status'] = plug['value'][
1046
+ 'params', 'move_settings', 'multiaxes', 'multi_status']
1047
+
720
1048
 
721
1049
  IDs = list(set([plug['ID'] for plug in plugins]))
722
1050
  # %%
@@ -737,8 +1065,8 @@ class DashBoard(QObject):
737
1065
  plug_name = plugin['value'].child('name').value()
738
1066
  plug_init = plugin['value'].child('init').value()
739
1067
  plug_settings = plugin['value'].child('params')
740
- self.splash_sc.showMessage('Loading {:s} module: {:s}'.format(plugin['type'], plug_name),
741
- color=Qt.white)
1068
+ self.splash_sc.showMessage(
1069
+ 'Loading {:s} module: {:s}'.format(plugin['type'], plug_name))
742
1070
 
743
1071
  if plugin['type'] == 'move':
744
1072
  plug_type = plug_settings.child('main_settings', 'move_type').value()
@@ -756,10 +1084,11 @@ class DashBoard(QObject):
756
1084
  QtWidgets.QApplication.processEvents()
757
1085
  master_controller = actuators_modules[-1].controller
758
1086
  elif plugin['status'] == "Master" and len(plug_IDs) > 1:
759
- raise MasterSlaveError(f'The instrument {plug_name} defined as Master has to be '
760
- f'initialized (init checked in the preset) in order to init '
761
- f'its associated slave instrument'
762
- )
1087
+ raise MasterSlaveError(
1088
+ f'The instrument {plug_name} defined as Master has to be '
1089
+ f'initialized (init checked in the preset) in order to init '
1090
+ f'its associated slave instrument'
1091
+ )
763
1092
  else:
764
1093
  if plugin['status'] != "Slave":
765
1094
  raise MasterSlaveError(f'The instrument {plug_name} should'
@@ -787,10 +1116,11 @@ class DashBoard(QObject):
787
1116
  QtWidgets.QApplication.processEvents()
788
1117
  master_controller = detector_modules[-1].controller
789
1118
  elif plugin['status'] == "Master" and len(plug_IDs) > 1:
790
- raise MasterSlaveError(f'The instrument {plug_name} defined as Master has to be '
791
- f'initialized (init checked in the preset) in order to init '
792
- f'its associated slave instrument'
793
- )
1119
+ raise MasterSlaveError(
1120
+ f'The instrument {plug_name} defined as Master has to be '
1121
+ f'initialized (init checked in the preset) in order to init '
1122
+ f'its associated slave instrument'
1123
+ )
794
1124
  else:
795
1125
  if plugin['status'] != "Slave":
796
1126
  raise MasterSlaveError(f'The instrument {plug_name} should'
@@ -879,7 +1209,8 @@ class DashBoard(QObject):
879
1209
  if remote_action['action_type'] == 'shortcut':
880
1210
  if remote_action['action_name'] not in self.shortcuts:
881
1211
  self.shortcuts[remote_action['action_name']] = \
882
- QtWidgets.QShortcut(QtGui.QKeySequence(remote_action['action_dict']['shortcut']), self.dockarea)
1212
+ QtWidgets.QShortcut(
1213
+ QtGui.QKeySequence(remote_action['action_dict']['shortcut']), self.dockarea)
883
1214
  self.activate_shortcut(self.shortcuts[remote_action['action_name']],
884
1215
  remote_action['action_dict'],
885
1216
  activate=remote_action['action_dict']['activated'])
@@ -922,18 +1253,20 @@ class DashBoard(QObject):
922
1253
  contained in self.joysticks
923
1254
  """
924
1255
 
925
- # # Specifi action for axis to get their values even if it doesn't change (in which case it would'nt trigger events)
926
1256
  for action_dict in self.joysticks.values():
927
1257
  if action_dict['activated'] and action_dict['actionner_type'].lower() == 'axis':
928
1258
  if action_dict['module_type'] == 'act':
929
- joy = utils.find_dict_in_list_from_key_val(self.joysticks_obj, 'id', action_dict['joystickID'])
1259
+ joy = utils.find_dict_in_list_from_key_val(self.joysticks_obj, 'id',
1260
+ action_dict['joystickID'])
930
1261
  val = joy['obj'].get_axis(action_dict['actionnerID'])
931
1262
  if abs(val) > 1e-4:
932
- module = self.modules_manager.get_mod_from_name(action_dict['module_name'],
933
- mod=action_dict['module_type'])
1263
+ module = self.modules_manager.get_mod_from_name(
1264
+ action_dict['module_name'],
1265
+ mod=action_dict['module_type'])
934
1266
  action = getattr(module, action_dict['action'])
935
1267
  if module.move_done_bool:
936
- action(val * 1 * module.settings.child('move_settings', 'epsilon').value())
1268
+ action(val * 1 * module.settings.child(
1269
+ 'move_settings', 'epsilon').value())
937
1270
 
938
1271
  # # For other actions use the event loop
939
1272
  for event in self.pygame.event.get(): # User did something.
@@ -949,18 +1282,21 @@ class DashBoard(QObject):
949
1282
  if len(selection) > 1:
950
1283
  for action_dict in self.joysticks.values():
951
1284
  if action_dict['activated']:
952
- module = self.modules_manager.get_mod_from_name(action_dict['module_name'],
953
- mod=action_dict['module_type'])
1285
+ module = self.modules_manager.get_mod_from_name(
1286
+ action_dict['module_name'],
1287
+ mod=action_dict['module_type'])
954
1288
  if action_dict['module_type'] == 'det':
955
1289
  action = getattr(module, action_dict['action'])
956
1290
  else:
957
1291
  action = getattr(module, action_dict['action'])
958
1292
 
959
1293
  if action_dict['joystickID'] == selection['joy']:
960
- if action_dict['actionner_type'].lower() == 'button' and 'button' in selection:
1294
+ if (action_dict['actionner_type'].lower() == 'button' and
1295
+ 'button' in selection):
961
1296
  if action_dict['actionnerID'] == selection['button']:
962
1297
  action()
963
- elif action_dict['actionner_type'].lower() == 'hat' and 'hat' in selection:
1298
+ elif (action_dict['actionner_type'].lower() == 'hat' and
1299
+ 'hat' in selection):
964
1300
  if action_dict['actionnerID'] == selection['hat']:
965
1301
  action(selection['value'])
966
1302
 
@@ -968,7 +1304,8 @@ class DashBoard(QObject):
968
1304
 
969
1305
  def activate_shortcut(self, shortcut, action=None, activate=True):
970
1306
  """
971
- action = dict(shortcut=action.child(('shortcut')).value(), activated=True, name=f'action{ind:02d}',
1307
+ action = dict(shortcut=action.child(('shortcut')).value(), activated=True,
1308
+ name=f'action{ind:02d}',
972
1309
  action=action.child(('action')).value(), module_name=module)
973
1310
  Parameters
974
1311
  ----------
@@ -990,7 +1327,8 @@ class DashBoard(QObject):
990
1327
  pass
991
1328
 
992
1329
  def create_activated_shortcut(self, action):
993
- module = self.modules_manager.get_mod_from_name(action['module_name'], mod=action['module_type'])
1330
+ module = self.modules_manager.get_mod_from_name(action['module_name'],
1331
+ mod=action['module_type'])
994
1332
  if action['module_type'] == 'det':
995
1333
  return lambda: getattr(module, action['action'])()
996
1334
  else:
@@ -1007,29 +1345,22 @@ class DashBoard(QObject):
1007
1345
  self.update_status('Overshoot configuration ({}) has been loaded'.format(file),
1008
1346
  log_type='log')
1009
1347
  self.overshoot_manager.set_file_overshoot(filename, show=False)
1010
-
1011
- det_titles = [det.title for det in self.detector_modules]
1012
- move_titles = [move.title for move in self.actuators_modules]
1013
-
1014
- for det_param in self.overshoot_manager.overshoot_params.child(('Detectors')).children():
1015
- if det_param.child(('trig_overshoot')).value():
1016
- det_index = det_titles.index(det_param.opts['title'])
1017
- det_module = self.detector_modules[det_index]
1018
- det_module.settings.child('main_settings', 'overshoot', 'stop_overshoot').setValue(True)
1019
- det_module.settings.child('main_settings', 'overshoot', 'overshoot_value').setValue(
1020
- det_param.child(('overshoot_value')).value())
1021
- for move_param in det_param.child(('params')).children():
1022
- if move_param.child(('move_overshoot')).value():
1023
- move_index = move_titles.index(move_param.opts['title'])
1024
- move_module = self.actuators_modules[move_index]
1025
- det_module.overshoot_signal.connect(
1026
- self.create_overshoot_fun(move_module, move_param.child(('position')).value()))
1348
+ self.set_action_enabled('activate_overshoot', True)
1349
+ self.set_action_checked('activate_overshoot', False)
1350
+ self.get_action('activate_overshoot').trigger()
1027
1351
 
1028
1352
  except Exception as e:
1029
1353
  logger.exception(str(e))
1030
1354
 
1031
- def create_overshoot_fun(self, move_module, position):
1032
- return lambda: move_module.move_abs(position)
1355
+ def activate_overshoot(self, status: bool):
1356
+ try:
1357
+ self.overshoot_manager.activate_overshoot(self.detector_modules,
1358
+ self.actuators_modules,
1359
+ status)
1360
+ except Exception as e:
1361
+ logger.warning(f'Could not load the overshoot file:\n{str(e)}')
1362
+ self.set_action_checked('activate_overshoot', False)
1363
+ self.set_action_enabled('activate_overshoot', False)
1033
1364
 
1034
1365
  @property
1035
1366
  def move_modules(self):
@@ -1042,10 +1373,12 @@ class DashBoard(QObject):
1042
1373
  """
1043
1374
  | Set the managers mode from the given filename.
1044
1375
  |
1045
- | In case of "mock" or "canon" move, set the corresponding managers calling set_(*)_preset procedure.
1376
+ | In case of "mock" or "canon" move, set the corresponding managers calling
1377
+ set_(*)_preset procedure.
1046
1378
  |
1047
1379
  | Else set the managers file using set_file_preset function.
1048
- | Once done connect the move and detector modules to logger to recipe/transmit informations.
1380
+ | Once done connect the move and detector modules to logger to recipe/transmit
1381
+ informations.
1049
1382
 
1050
1383
  Finally update DAQ_scan_settings tree with :
1051
1384
  * Detectors
@@ -1064,6 +1397,9 @@ class DashBoard(QObject):
1064
1397
  try:
1065
1398
  if not isinstance(filename, Path):
1066
1399
  filename = Path(filename)
1400
+
1401
+ self.get_action('preset_list').setCurrentText(filename.stem)
1402
+
1067
1403
  self.mainwindow.setVisible(False)
1068
1404
  for area in self.dockarea.tempAreas:
1069
1405
  area.window().setVisible(False)
@@ -1071,7 +1407,7 @@ class DashBoard(QObject):
1071
1407
  self.splash_sc.show()
1072
1408
  QtWidgets.QApplication.processEvents()
1073
1409
  self.splash_sc.raise_()
1074
- self.splash_sc.showMessage('Loading Modules, please wait', color=Qt.white)
1410
+ self.splash_sc.showMessage('Loading Modules, please wait')
1075
1411
  QtWidgets.QApplication.processEvents()
1076
1412
  self.clear_move_det_controllers()
1077
1413
  QtWidgets.QApplication.processEvents()
@@ -1080,80 +1416,40 @@ class DashBoard(QObject):
1080
1416
 
1081
1417
  try:
1082
1418
  actuators_modules, detector_modules = self.set_file_preset(filename)
1083
- except (ActuatorError, DetectorError, PIDError, MasterSlaveError) as error:
1419
+ except (ActuatorError, DetectorError, MasterSlaveError) as error:
1084
1420
  self.splash_sc.close()
1085
1421
  self.mainwindow.setVisible(True)
1086
1422
  for area in self.dockarea.tempAreas:
1087
1423
  area.window().setVisible(True)
1088
- messagebox(text=f'{str(error)}\nQuitting the application...', title='Incompatibility')
1424
+ messagebox(text=f'{str(error)}\nQuitting the application...',
1425
+ title='Incompatibility')
1089
1426
  logger.exception(str(error))
1090
1427
 
1091
1428
  self.quit_fun()
1092
1429
  return
1093
1430
 
1094
1431
  if not (not actuators_modules and not detector_modules):
1095
- self.update_status('Preset mode ({}) has been loaded'.format(filename.name), log_type='log')
1432
+ self.update_status('Preset mode ({}) has been loaded'.format(filename.name),
1433
+ log_type='log')
1096
1434
  self.settings.child('loaded_files', 'preset_file').setValue(filename.name)
1097
1435
  self.actuators_modules = actuators_modules
1098
1436
  self.detector_modules = detector_modules
1099
1437
 
1100
- self.modules_manager = ModulesManager(self.detector_modules, self.actuators_modules)
1101
-
1102
- # Now that we have the module manager, load PID if it is checked in managers
1103
- try:
1104
- if self.preset_manager.preset_params.child('use_pid').value():
1105
- self.load_pid_module()
1106
-
1107
- self.pid_module.settings.child('models', 'model_class').setValue(
1108
- self.preset_manager.preset_params.child('pid_models').value())
1109
- QtWidgets.QApplication.processEvents()
1110
- self.pid_module.set_model()
1111
-
1112
- QtWidgets.QApplication.processEvents()
1113
-
1114
- for child in putils.iter_children_params(
1115
- self.preset_manager.preset_params.child('model_settings'),
1116
- []):
1117
- preset_path = self.preset_manager.preset_params.child('model_settings').childPath(child)
1118
- path = ['models', 'model_params']
1119
- path.extend(preset_path)
1120
- self.pid_module.settings.child(*path).setValue(child.value())
1121
-
1122
- model_class = extmod.get_models(
1123
- self.preset_manager.preset_params.child('pid_models').value())['class']
1124
- for setp in model_class.setpoints_names:
1125
- self.add_move(setp, None, 'PID', [], [], actuators_modules)
1126
- actuators_modules[-1].controller = PIDController(self.pid_module)
1127
- actuators_modules[-1].master = False
1128
- actuators_modules[-1].init_hardware_ui()
1129
- QtWidgets.QApplication.processEvents()
1130
- self.poll_init(actuators_modules[-1])
1131
- QtWidgets.QApplication.processEvents()
1132
-
1133
- # Update actuators modules and module manager
1134
- self.actuators_modules = actuators_modules
1135
- self.modules_manager = ModulesManager(self.detector_modules, self.actuators_modules)
1136
-
1137
- except Exception as e:
1138
- raise PIDError('Could not load the PID extension and create setpoints actuators'
1139
- f'{str(e)}')
1140
-
1141
- #
1142
- if self.pid_module is not None:
1143
- self.pid_module.get_action('ini_model').trigger()
1144
- # #
1438
+ self.update_module_manager()
1145
1439
 
1146
1440
  #####################################################
1147
- self.overshoot_manager = OvershootManager(det_modules=[det.title for det in detector_modules],
1148
- actuators_modules=[move.title for move in actuators_modules])
1441
+ self.overshoot_manager = OvershootManager(
1442
+ det_modules=[det.title for det in detector_modules],
1443
+ actuators_modules=[move.title for move in actuators_modules])
1149
1444
  # load overshoot if present
1150
1445
  file = filename.name
1151
1446
  path = overshoot_path.joinpath(file)
1152
1447
  if path.is_file():
1153
1448
  self.set_overshoot_configuration(path)
1154
1449
 
1155
- self.remote_manager = RemoteManager(actuators=[move.title for move in actuators_modules],
1156
- detectors=[det.title for det in detector_modules])
1450
+ self.remote_manager = RemoteManager(
1451
+ actuators=[move.title for move in actuators_modules],
1452
+ detectors=[det.title for det in detector_modules])
1157
1453
  # load remote file if present
1158
1454
  file = filename.name
1159
1455
  path = remote_path.joinpath(file)
@@ -1179,11 +1475,13 @@ class DashBoard(QObject):
1179
1475
  if self.pid_window is not None:
1180
1476
  self.pid_window.show()
1181
1477
 
1182
- self.load_preset.setEnabled(False)
1478
+ self.load_preset_menu.setEnabled(False)
1479
+ self.set_action_enabled('load_preset', False)
1480
+ self.set_action_enabled('preset_list', False)
1183
1481
  self.overshoot_menu.setEnabled(True)
1184
1482
  self.roi_menu.setEnabled(True)
1185
1483
  self.remote_menu.setEnabled(True)
1186
- self.actions_menu.setEnabled(True)
1484
+ self.extensions_menu.setEnabled(True)
1187
1485
  self.file_menu.setEnabled(True)
1188
1486
  self.settings_menu.setEnabled(True)
1189
1487
  self.update_init_tree()
@@ -1198,17 +1496,19 @@ class DashBoard(QObject):
1198
1496
  def update_init_tree(self):
1199
1497
  for act in self.actuators_modules:
1200
1498
  name = ''.join(act.title.split()) # remove empty spaces
1201
- if act.title not in [ac.title() for ac in putils.iter_children_params(self.settings.child(('actuators')), [])]:
1499
+ if act.title not in [ac.title() for ac in putils.iter_children_params(
1500
+ self.settings.child('actuators'), [])]:
1202
1501
 
1203
- self.settings.child(('actuators')).addChild(
1502
+ self.settings.child('actuators').addChild(
1204
1503
  {'title': act.title, 'name': name, 'type': 'led', 'value': False})
1205
1504
  QtWidgets.QApplication.processEvents()
1206
1505
  self.settings.child('actuators', name).setValue(act.initialized_state)
1207
1506
 
1208
1507
  for det in self.detector_modules:
1209
1508
  name = ''.join(det.title.split()) # remove empty spaces
1210
- if det.title not in [de.title() for de in putils.iter_children_params(self.settings.child(('detectors')), [])]:
1211
- self.settings.child(('detectors')).addChild(
1509
+ if det.title not in [de.title() for de in putils.iter_children_params(
1510
+ self.settings.child('detectors'), [])]:
1511
+ self.settings.child('detectors').addChild(
1212
1512
  {'title': det.title, 'name': name, 'type': 'led', 'value': False})
1213
1513
  QtWidgets.QApplication.processEvents()
1214
1514
  self.settings.child('detectors', name).setValue(det.initialized_state)
@@ -1233,38 +1533,22 @@ class DashBoard(QObject):
1233
1533
  webbrowser.open(logging.getLogger('pymodaq').handlers[0].baseFilename)
1234
1534
 
1235
1535
  def show_config(self):
1236
- from pymodaq.utils.gui_utils.widgets.tree_toml import TreeFromToml
1536
+ from pymodaq_gui.utils.widgets.tree_toml import TreeFromToml
1237
1537
  config_tree = TreeFromToml()
1238
1538
  config_tree.show_dialog()
1239
1539
 
1240
- def setupUI(self):
1540
+ def setup_docks(self):
1241
1541
 
1242
1542
  # %% create logger dock
1243
1543
  self.logger_dock = Dock("Logger")
1244
1544
  self.logger_list = QtWidgets.QListWidget()
1245
1545
  self.logger_list.setMinimumWidth(300)
1246
- self.init_tree = ParameterTree()
1247
- self.init_tree.setMinimumWidth(300)
1546
+
1248
1547
  splitter = QtWidgets.QSplitter(Qt.Vertical)
1249
- splitter.addWidget(self.init_tree)
1548
+ splitter.addWidget(self.settings_tree)
1250
1549
  splitter.addWidget(self.logger_list)
1251
1550
  self.logger_dock.addWidget(splitter)
1252
1551
 
1253
- self.settings = Parameter.create(name='init_settings', type='group', children=[
1254
- {'title': 'Log level', 'name': 'log_level', 'type': 'list', 'value': config('general', 'debug_level'),
1255
- 'limits': config('general', 'debug_levels')},
1256
-
1257
- {'title': 'Loaded presets', 'name': 'loaded_files', 'type': 'group', 'children': [
1258
- {'title': 'Preset file', 'name': 'preset_file', 'type': 'str', 'value': '', 'readonly': True},
1259
- {'title': 'Overshoot file', 'name': 'overshoot_file', 'type': 'str', 'value': '', 'readonly': True},
1260
- {'title': 'Layout file', 'name': 'layout_file', 'type': 'str', 'value': '', 'readonly': True},
1261
- {'title': 'ROI file', 'name': 'roi_file', 'type': 'str', 'value': '', 'readonly': True},
1262
- {'title': 'Remote file', 'name': 'remote_file', 'type': 'str', 'value': '', 'readonly': True},
1263
- ]},
1264
- {'title': 'Actuators Init.', 'name': 'actuators', 'type': 'group', 'children': []},
1265
- {'title': 'Detectors Init.', 'name': 'detectors', 'type': 'group', 'children': []},
1266
- ])
1267
- self.init_tree.setParameters(self.settings, showTop=False)
1268
1552
  self.remote_dock = Dock('Remote controls')
1269
1553
  self.dockarea.addDock(self.remote_dock, 'top')
1270
1554
  self.dockarea.addDock(self.logger_dock, 'above', self.remote_dock)
@@ -1273,21 +1557,9 @@ class DashBoard(QObject):
1273
1557
  self.remote_dock.setVisible(False)
1274
1558
  self.preset_manager = PresetManager(path=self.preset_path, extra_params=self.extra_params)
1275
1559
 
1276
- # creating the menubar
1277
- self.menubar = self.mainwindow.menuBar()
1278
- self.create_menu(self.menubar)
1279
- self.overshoot_menu.setEnabled(False)
1280
- self.roi_menu.setEnabled(False)
1281
- self.remote_menu.setEnabled(False)
1282
- self.actions_menu.setEnabled(False)
1283
- # connecting
1284
- self.status_signal[str].connect(self.add_status)
1285
-
1286
- self.file_menu.setEnabled(True)
1287
- # self.actions_menu.setEnabled(True)
1288
- self.settings_menu.setEnabled(True)
1289
- self.preset_menu.setEnabled(True)
1290
- self.mainwindow.setVisible(True)
1560
+ @property
1561
+ def menubar(self):
1562
+ return self._menubar
1291
1563
 
1292
1564
  def parameter_tree_changed(self, param, changes):
1293
1565
  """
@@ -1299,11 +1571,6 @@ class DashBoard(QObject):
1299
1571
 
1300
1572
  Once done emit the update settings signal to link the commit.
1301
1573
 
1302
- =============== =================================== ================================================================
1303
- **Parameters** **Type** **Description**
1304
- *param* instance of ppyqtgraph parameter the parameter to be checked
1305
- *changes* tuple list Contain the (param,changes,info) list listing the changes made
1306
- =============== =================================== ================================================================
1307
1574
 
1308
1575
  """
1309
1576
 
@@ -1324,34 +1591,78 @@ class DashBoard(QObject):
1324
1591
  def show_about(self):
1325
1592
  self.splash_sc.setVisible(True)
1326
1593
  self.splash_sc.showMessage(
1327
- "PyMoDAQ version {:}\nModular Acquisition with Python\nWritten by Sébastien Weber".format(get_version()),
1328
- QtCore.Qt.AlignRight, QtCore.Qt.white)
1594
+ f"PyMoDAQ version {get_version('pymodaq')}\n"
1595
+ f"Modular Acquisition with Python\n"
1596
+ f"Written by Sébastien Weber")
1597
+
1598
+ def check_update(self, show=True):
1329
1599
 
1330
- def check_version(self, show=True):
1331
1600
  try:
1332
- current_version = version_mod.parse(get_version())
1333
- available_version = version_mod.parse(get_pypi_pymodaq('pymodaq')['version'])
1334
- msgBox = QtWidgets.QMessageBox()
1335
- if available_version > current_version:
1336
- msgBox.setText(f"A new version of PyMoDAQ is available, {str(available_version)}!")
1337
- msgBox.setInformativeText("Do you want to install it?")
1338
- msgBox.setStandardButtons(msgBox.Ok | msgBox.Cancel)
1339
- msgBox.setDefaultButton(msgBox.Ok)
1340
-
1341
- ret = msgBox.exec()
1342
-
1343
- if ret == msgBox.Ok:
1344
- command = [sys.executable, '-m', 'pip', 'install', f'pymodaq=={str(available_version)}']
1345
- subprocess.Popen(command)
1346
-
1347
- self.restart_fun()
1601
+ packages = ['pymodaq_utils', 'pymodaq_data', 'pymodaq_gui', 'pymodaq']
1602
+ current_versions = [version_mod.parse(get_version(p)) for p in packages]
1603
+ available_versions = [version_mod.parse(get_pypi_pymodaq(p)['version']) for p in packages]
1604
+ new_versions = np.greater(available_versions, current_versions)
1605
+ # Combine package and version information and select only the ones with a newer version available
1606
+
1607
+
1608
+ packages_data = np.array(list(zip(packages, current_versions, available_versions)))[new_versions]
1609
+
1610
+ #TODO: Remove `or True`
1611
+ if len(packages_data) > 0:
1612
+ #Create a QDialog window and different graphical components
1613
+ dialog = QtWidgets.QDialog()
1614
+ dialog.setWindowTitle("Update check")
1615
+
1616
+ vlayout = QtWidgets.QVBoxLayout()
1617
+
1618
+ message_label = QLabel("New versions of PyMoDAQ packages available!\nPlease select the ones you want to install:")
1619
+ message_label.setAlignment(Qt.AlignCenter)
1620
+
1621
+
1622
+ table = PymodaqUpdateTableWidget()
1623
+ table.setRowCount(len(packages_data))
1624
+ table.setColumnCount(4)
1625
+ table.setHorizontalHeaderLabels(["Select", "Package", "Current version", "New version"])
1626
+
1627
+ for p in packages_data:
1628
+ table.append_row(QCheckBox(), p[0], p[1], p[2])
1629
+
1630
+ button = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
1631
+ button.accepted.connect(dialog.accept)
1632
+ button.rejected.connect(dialog.reject)
1633
+
1634
+ # The vlayout contains the message, the table and the buttons
1635
+ # and is connected to the dialog window
1636
+ vlayout.addWidget(message_label)
1637
+ vlayout.addWidget(table)
1638
+ vlayout.addWidget(button)
1639
+ dialog.setLayout(vlayout)
1640
+
1641
+ ret = dialog.exec()
1642
+
1643
+ if ret == QDialog.Accepted:
1644
+ # If the update is accepted, the checked packages are extracted from the table
1645
+ # and send to the updater
1646
+ packages_to_update = table.get_checked_data()
1647
+ if len(packages_to_update) > 0:
1648
+ packages_to_update_str = ', '.join(packages_to_update)
1649
+ logger.info("Trying to update:")
1650
+ logger.info(f"\t {packages_to_update_str}")
1651
+ subprocess.Popen(['pymodaq_updater', '--wait', '--file', __file__] + packages_to_update, stdin=subprocess.PIPE)
1652
+ self.quit_fun()
1653
+ return True
1654
+ logger.info("Update found but no packages checked for update.")
1348
1655
  else:
1349
1656
  if show:
1350
- msgBox.setText(f"Your version of PyMoDAQ, {str(current_version)}, is up to date!")
1657
+ msgBox = QtWidgets.QMessageBox()
1658
+ msgBox.setWindowTitle("Update check")
1659
+ msgBox.setText("Everything is up to date!")
1351
1660
  ret = msgBox.exec()
1352
1661
  except Exception as e:
1353
1662
  logger.exception("Error while checking the available PyMoDAQ version")
1354
1663
 
1664
+ return False
1665
+
1355
1666
  def show_file_attributes(self, type_info='dataset'):
1356
1667
  """
1357
1668
  Switch the type_info value.
@@ -1359,9 +1670,12 @@ class DashBoard(QObject):
1359
1670
  In case of :
1360
1671
  * *scan* : Set parameters showing top false
1361
1672
  * *dataset* : Set parameters showing top false
1362
- * *managers* : Set parameters showing top false. Add the save/cancel buttons to the accept/reject dialog (to save managers parameters in a xml file).
1673
+ * *managers* : Set parameters showing top false.
1674
+ Add the save/cancel buttons to the accept/reject dialog
1675
+ (to save managers parameters in a xml file).
1363
1676
 
1364
- Finally, in case of accepted managers type info, save the managers parameters in a xml file.
1677
+ Finally, in case of accepted managers type info,
1678
+ save the managers parameters in a xml file.
1365
1679
 
1366
1680
  =============== =========== ====================================
1367
1681
  **Parameters** **Type** **Description**
@@ -1417,7 +1731,8 @@ class DashBoard(QObject):
1417
1731
 
1418
1732
 
1419
1733
  def main():
1420
- from pymodaq.utils.gui_utils.utils import mkQApp
1734
+ from pymodaq_gui.utils.utils import mkQApp
1735
+
1421
1736
  app = mkQApp('Dashboard')
1422
1737
 
1423
1738
  win = QtWidgets.QMainWindow()
@@ -1426,10 +1741,11 @@ def main():
1426
1741
  win.resize(1000, 500)
1427
1742
  win.setWindowTitle('PyMoDAQ Dashboard')
1428
1743
 
1429
- # win.setVisible(False)
1430
1744
  prog = DashBoard(area)
1745
+
1746
+ win.show()
1747
+
1431
1748
  app.exec()
1432
- return prog, win
1433
1749
 
1434
1750
 
1435
1751
  if __name__ == '__main__':