datalab-platform 0.0.1.dev0__py3-none-any.whl → 1.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.
Files changed (496) hide show
  1. datalab/__init__.py +35 -2
  2. datalab/adapters_metadata/__init__.py +31 -0
  3. datalab/adapters_metadata/base_adapter.py +316 -0
  4. datalab/adapters_metadata/common.py +422 -0
  5. datalab/adapters_metadata/geometry_adapter.py +98 -0
  6. datalab/adapters_metadata/table_adapter.py +84 -0
  7. datalab/adapters_plotpy/__init__.py +54 -0
  8. datalab/adapters_plotpy/annotations.py +124 -0
  9. datalab/adapters_plotpy/base.py +110 -0
  10. datalab/adapters_plotpy/converters.py +86 -0
  11. datalab/adapters_plotpy/factories.py +80 -0
  12. datalab/adapters_plotpy/objects/__init__.py +0 -0
  13. datalab/adapters_plotpy/objects/base.py +197 -0
  14. datalab/adapters_plotpy/objects/image.py +157 -0
  15. datalab/adapters_plotpy/objects/scalar.py +565 -0
  16. datalab/adapters_plotpy/objects/signal.py +264 -0
  17. datalab/adapters_plotpy/roi/__init__.py +0 -0
  18. datalab/adapters_plotpy/roi/base.py +146 -0
  19. datalab/adapters_plotpy/roi/factory.py +93 -0
  20. datalab/adapters_plotpy/roi/image.py +207 -0
  21. datalab/adapters_plotpy/roi/signal.py +72 -0
  22. datalab/app.py +98 -0
  23. datalab/config.py +817 -0
  24. datalab/control/__init__.py +0 -0
  25. datalab/control/baseproxy.py +776 -0
  26. datalab/control/proxy.py +343 -0
  27. datalab/control/remote.py +1005 -0
  28. datalab/data/doc/DataLab_en.pdf +0 -0
  29. datalab/data/doc/DataLab_fr.pdf +0 -0
  30. datalab/data/icons/analysis/delete_results.svg +109 -0
  31. datalab/data/icons/analysis/fw1e2.svg +156 -0
  32. datalab/data/icons/analysis/fwhm.svg +156 -0
  33. datalab/data/icons/analysis/histogram.svg +49 -0
  34. datalab/data/icons/analysis/peak_detect.svg +160 -0
  35. datalab/data/icons/analysis/plot_results.svg +151 -0
  36. datalab/data/icons/analysis/show_results.svg +83 -0
  37. datalab/data/icons/analysis/stats.svg +49 -0
  38. datalab/data/icons/analysis.svg +120 -0
  39. datalab/data/icons/apply.svg +3 -0
  40. datalab/data/icons/check_all.svg +15 -0
  41. datalab/data/icons/collapse.svg +44 -0
  42. datalab/data/icons/collapse_selection.svg +63 -0
  43. datalab/data/icons/console.svg +101 -0
  44. datalab/data/icons/create/1d-normal.svg +8 -0
  45. datalab/data/icons/create/1d-poisson.svg +9 -0
  46. datalab/data/icons/create/1d-uniform.svg +8 -0
  47. datalab/data/icons/create/1d-zero.svg +57 -0
  48. datalab/data/icons/create/2d-gaussian.svg +56 -0
  49. datalab/data/icons/create/2d-normal.svg +38 -0
  50. datalab/data/icons/create/2d-poisson.svg +38 -0
  51. datalab/data/icons/create/2d-ramp.svg +90 -0
  52. datalab/data/icons/create/2d-sinc.svg +62 -0
  53. datalab/data/icons/create/2d-uniform.svg +38 -0
  54. datalab/data/icons/create/2d-zero.svg +13 -0
  55. datalab/data/icons/create/checkerboard.svg +39 -0
  56. datalab/data/icons/create/cosine.svg +12 -0
  57. datalab/data/icons/create/exponential.svg +55 -0
  58. datalab/data/icons/create/gaussian.svg +12 -0
  59. datalab/data/icons/create/grating.svg +29 -0
  60. datalab/data/icons/create/linear_chirp.svg +7 -0
  61. datalab/data/icons/create/logistic.svg +7 -0
  62. datalab/data/icons/create/lorentzian.svg +12 -0
  63. datalab/data/icons/create/planck.svg +12 -0
  64. datalab/data/icons/create/polynomial.svg +7 -0
  65. datalab/data/icons/create/pulse.svg +12 -0
  66. datalab/data/icons/create/ring.svg +18 -0
  67. datalab/data/icons/create/sawtooth.svg +7 -0
  68. datalab/data/icons/create/siemens.svg +35 -0
  69. datalab/data/icons/create/sinc.svg +12 -0
  70. datalab/data/icons/create/sine.svg +7 -0
  71. datalab/data/icons/create/square.svg +7 -0
  72. datalab/data/icons/create/square_pulse.svg +7 -0
  73. datalab/data/icons/create/step.svg +7 -0
  74. datalab/data/icons/create/step_pulse.svg +12 -0
  75. datalab/data/icons/create/triangle.svg +7 -0
  76. datalab/data/icons/create/voigt.svg +12 -0
  77. datalab/data/icons/edit/annotations.svg +72 -0
  78. datalab/data/icons/edit/annotations_copy.svg +114 -0
  79. datalab/data/icons/edit/annotations_delete.svg +83 -0
  80. datalab/data/icons/edit/annotations_edit.svg +98 -0
  81. datalab/data/icons/edit/annotations_export.svg +85 -0
  82. datalab/data/icons/edit/annotations_import.svg +85 -0
  83. datalab/data/icons/edit/annotations_paste.svg +100 -0
  84. datalab/data/icons/edit/copy_titles.svg +109 -0
  85. datalab/data/icons/edit/delete.svg +84 -0
  86. datalab/data/icons/edit/delete_all.svg +214 -0
  87. datalab/data/icons/edit/duplicate.svg +64 -0
  88. datalab/data/icons/edit/goto_source.svg +60 -0
  89. datalab/data/icons/edit/metadata.svg +60 -0
  90. datalab/data/icons/edit/metadata_add.svg +80 -0
  91. datalab/data/icons/edit/metadata_copy.svg +96 -0
  92. datalab/data/icons/edit/metadata_delete.svg +62 -0
  93. datalab/data/icons/edit/metadata_export.svg +68 -0
  94. datalab/data/icons/edit/metadata_import.svg +68 -0
  95. datalab/data/icons/edit/metadata_paste.svg +79 -0
  96. datalab/data/icons/edit/move_down.svg +55 -0
  97. datalab/data/icons/edit/move_up.svg +54 -0
  98. datalab/data/icons/edit/new_group.svg +76 -0
  99. datalab/data/icons/edit/recompute.svg +60 -0
  100. datalab/data/icons/edit/rename.svg +49 -0
  101. datalab/data/icons/edit.svg +16 -0
  102. datalab/data/icons/expand.svg +44 -0
  103. datalab/data/icons/expand_selection.svg +63 -0
  104. datalab/data/icons/fit/cdf_fit.svg +56 -0
  105. datalab/data/icons/fit/exponential_fit.svg +55 -0
  106. datalab/data/icons/fit/gaussian_fit.svg +62 -0
  107. datalab/data/icons/fit/interactive_fit.svg +101 -0
  108. datalab/data/icons/fit/linear_fit.svg +57 -0
  109. datalab/data/icons/fit/lorentzian_fit.svg +209 -0
  110. datalab/data/icons/fit/multigaussian_fit.svg +85 -0
  111. datalab/data/icons/fit/multilorentzian_fit.svg +85 -0
  112. datalab/data/icons/fit/piecewiseexponential_fit.svg +209 -0
  113. datalab/data/icons/fit/planckian_fit.svg +62 -0
  114. datalab/data/icons/fit/polynomial_fit.svg +59 -0
  115. datalab/data/icons/fit/sigmoid_fit.svg +56 -0
  116. datalab/data/icons/fit/sinusoidal_fit.svg +72 -0
  117. datalab/data/icons/fit/twohalfgaussian_fit.svg +63 -0
  118. datalab/data/icons/fit/voigt_fit.svg +57 -0
  119. datalab/data/icons/group.svg +56 -0
  120. datalab/data/icons/h5/h5array.svg +59 -0
  121. datalab/data/icons/h5/h5attrs.svg +75 -0
  122. datalab/data/icons/h5/h5browser.svg +133 -0
  123. datalab/data/icons/h5/h5file.svg +69 -0
  124. datalab/data/icons/h5/h5group.svg +49 -0
  125. datalab/data/icons/h5/h5scalar.svg +1 -0
  126. datalab/data/icons/help_pdf.svg +46 -0
  127. datalab/data/icons/history.svg +7 -0
  128. datalab/data/icons/image.svg +135 -0
  129. datalab/data/icons/io/fileopen_directory.svg +60 -0
  130. datalab/data/icons/io/fileopen_h5.svg +84 -0
  131. datalab/data/icons/io/fileopen_ima.svg +187 -0
  132. datalab/data/icons/io/fileopen_py.svg +123 -0
  133. datalab/data/icons/io/fileopen_sig.svg +138 -0
  134. datalab/data/icons/io/filesave_h5.svg +97 -0
  135. datalab/data/icons/io/filesave_ima.svg +200 -0
  136. datalab/data/icons/io/filesave_py.svg +136 -0
  137. datalab/data/icons/io/filesave_sig.svg +151 -0
  138. datalab/data/icons/io/import_text.svg +144 -0
  139. datalab/data/icons/io/save_to_directory.svg +134 -0
  140. datalab/data/icons/io.svg +84 -0
  141. datalab/data/icons/libre-camera-flash-off.svg +1 -0
  142. datalab/data/icons/libre-camera-flash-on.svg +1 -0
  143. datalab/data/icons/libre-gui-about.svg +1 -0
  144. datalab/data/icons/libre-gui-action-delete.svg +1 -0
  145. datalab/data/icons/libre-gui-add.svg +1 -0
  146. datalab/data/icons/libre-gui-arrow-down.svg +1 -0
  147. datalab/data/icons/libre-gui-arrow-left.svg +1 -0
  148. datalab/data/icons/libre-gui-arrow-right.svg +1 -0
  149. datalab/data/icons/libre-gui-arrow-up.svg +1 -0
  150. datalab/data/icons/libre-gui-close.svg +40 -0
  151. datalab/data/icons/libre-gui-cogs.svg +1 -0
  152. datalab/data/icons/libre-gui-globe.svg +1 -0
  153. datalab/data/icons/libre-gui-help.svg +1 -0
  154. datalab/data/icons/libre-gui-link.svg +1 -0
  155. datalab/data/icons/libre-gui-menu.svg +1 -0
  156. datalab/data/icons/libre-gui-pencil.svg +1 -0
  157. datalab/data/icons/libre-gui-plugin.svg +1 -0
  158. datalab/data/icons/libre-gui-questions.svg +1 -0
  159. datalab/data/icons/libre-gui-settings.svg +1 -0
  160. datalab/data/icons/libre-gui-unlink.svg +1 -0
  161. datalab/data/icons/libre-tech-ram.svg +1 -0
  162. datalab/data/icons/libre-toolbox.svg +1 -0
  163. datalab/data/icons/logs.svg +1 -0
  164. datalab/data/icons/markers.svg +74 -0
  165. datalab/data/icons/menu.svg +13 -0
  166. datalab/data/icons/new_ima.svg +148 -0
  167. datalab/data/icons/new_sig.svg +123 -0
  168. datalab/data/icons/operations/abs.svg +116 -0
  169. datalab/data/icons/operations/arithmetic.svg +123 -0
  170. datalab/data/icons/operations/average.svg +124 -0
  171. datalab/data/icons/operations/complex_from_magnitude_phase.svg +116 -0
  172. datalab/data/icons/operations/complex_from_real_imag.svg +124 -0
  173. datalab/data/icons/operations/constant.svg +116 -0
  174. datalab/data/icons/operations/constant_add.svg +109 -0
  175. datalab/data/icons/operations/constant_divide.svg +109 -0
  176. datalab/data/icons/operations/constant_multiply.svg +109 -0
  177. datalab/data/icons/operations/constant_subtract.svg +109 -0
  178. datalab/data/icons/operations/convert_dtype.svg +117 -0
  179. datalab/data/icons/operations/convolution.svg +46 -0
  180. datalab/data/icons/operations/deconvolution.svg +57 -0
  181. datalab/data/icons/operations/derivative.svg +127 -0
  182. datalab/data/icons/operations/difference.svg +52 -0
  183. datalab/data/icons/operations/division.svg +139 -0
  184. datalab/data/icons/operations/exp.svg +116 -0
  185. datalab/data/icons/operations/flip_horizontally.svg +69 -0
  186. datalab/data/icons/operations/flip_vertically.svg +74 -0
  187. datalab/data/icons/operations/im.svg +124 -0
  188. datalab/data/icons/operations/integral.svg +50 -0
  189. datalab/data/icons/operations/inverse.svg +143 -0
  190. datalab/data/icons/operations/log10.svg +109 -0
  191. datalab/data/icons/operations/phase.svg +116 -0
  192. datalab/data/icons/operations/power.svg +118 -0
  193. datalab/data/icons/operations/product.svg +124 -0
  194. datalab/data/icons/operations/profile.svg +379 -0
  195. datalab/data/icons/operations/profile_average.svg +399 -0
  196. datalab/data/icons/operations/profile_radial.svg +261 -0
  197. datalab/data/icons/operations/profile_segment.svg +262 -0
  198. datalab/data/icons/operations/quadratic_difference.svg +84 -0
  199. datalab/data/icons/operations/re.svg +124 -0
  200. datalab/data/icons/operations/rotate_left.svg +72 -0
  201. datalab/data/icons/operations/rotate_right.svg +72 -0
  202. datalab/data/icons/operations/signals_to_image.svg +314 -0
  203. datalab/data/icons/operations/sqrt.svg +110 -0
  204. datalab/data/icons/operations/std.svg +124 -0
  205. datalab/data/icons/operations/sum.svg +102 -0
  206. datalab/data/icons/play_demo.svg +9 -0
  207. datalab/data/icons/processing/axis_transform.svg +62 -0
  208. datalab/data/icons/processing/bandpass.svg +79 -0
  209. datalab/data/icons/processing/bandstop.svg +71 -0
  210. datalab/data/icons/processing/binning.svg +126 -0
  211. datalab/data/icons/processing/clip.svg +119 -0
  212. datalab/data/icons/processing/detrending.svg +173 -0
  213. datalab/data/icons/processing/distribute_on_grid.svg +769 -0
  214. datalab/data/icons/processing/edge_detection.svg +46 -0
  215. datalab/data/icons/processing/erase.svg +1 -0
  216. datalab/data/icons/processing/exposure.svg +143 -0
  217. datalab/data/icons/processing/fourier.svg +104 -0
  218. datalab/data/icons/processing/highpass.svg +59 -0
  219. datalab/data/icons/processing/interpolation.svg +71 -0
  220. datalab/data/icons/processing/level_adjustment.svg +70 -0
  221. datalab/data/icons/processing/lowpass.svg +60 -0
  222. datalab/data/icons/processing/morphology.svg +49 -0
  223. datalab/data/icons/processing/noise_addition.svg +114 -0
  224. datalab/data/icons/processing/noise_reduction.svg +38 -0
  225. datalab/data/icons/processing/normalize.svg +84 -0
  226. datalab/data/icons/processing/offset_correction.svg +131 -0
  227. datalab/data/icons/processing/resampling1d.svg +101 -0
  228. datalab/data/icons/processing/resampling2d.svg +240 -0
  229. datalab/data/icons/processing/reset_positions.svg +185 -0
  230. datalab/data/icons/processing/resize.svg +9 -0
  231. datalab/data/icons/processing/reverse_signal_x.svg +171 -0
  232. datalab/data/icons/processing/stability.svg +11 -0
  233. datalab/data/icons/processing/swap_x_y.svg +65 -0
  234. datalab/data/icons/processing/thresholding.svg +63 -0
  235. datalab/data/icons/processing/windowing.svg +45 -0
  236. datalab/data/icons/properties.svg +26 -0
  237. datalab/data/icons/reset.svg +9 -0
  238. datalab/data/icons/restore.svg +40 -0
  239. datalab/data/icons/roi/roi.svg +76 -0
  240. datalab/data/icons/roi/roi_coordinate.svg +78 -0
  241. datalab/data/icons/roi/roi_copy.svg +112 -0
  242. datalab/data/icons/roi/roi_delete.svg +81 -0
  243. datalab/data/icons/roi/roi_export.svg +87 -0
  244. datalab/data/icons/roi/roi_graphical.svg +78 -0
  245. datalab/data/icons/roi/roi_grid.svg +67 -0
  246. datalab/data/icons/roi/roi_ima.svg +188 -0
  247. datalab/data/icons/roi/roi_import.svg +87 -0
  248. datalab/data/icons/roi/roi_new.svg +81 -0
  249. datalab/data/icons/roi/roi_new_circle.svg +95 -0
  250. datalab/data/icons/roi/roi_new_polygon.svg +110 -0
  251. datalab/data/icons/roi/roi_new_rectangle.svg +70 -0
  252. datalab/data/icons/roi/roi_paste.svg +98 -0
  253. datalab/data/icons/roi/roi_sig.svg +124 -0
  254. datalab/data/icons/shapes.svg +134 -0
  255. datalab/data/icons/signal.svg +103 -0
  256. datalab/data/icons/table.svg +85 -0
  257. datalab/data/icons/table_unavailable.svg +102 -0
  258. datalab/data/icons/to_signal.svg +124 -0
  259. datalab/data/icons/tour/next.svg +44 -0
  260. datalab/data/icons/tour/previous.svg +44 -0
  261. datalab/data/icons/tour/rewind.svg +51 -0
  262. datalab/data/icons/tour/stop.svg +47 -0
  263. datalab/data/icons/tour/tour.svg +16 -0
  264. datalab/data/icons/uncheck_all.svg +78 -0
  265. datalab/data/icons/view/curve_antialiasing.svg +50 -0
  266. datalab/data/icons/view/new_window.svg +98 -0
  267. datalab/data/icons/view/refresh-auto.svg +57 -0
  268. datalab/data/icons/view/refresh-manual.svg +51 -0
  269. datalab/data/icons/view/reset_curve_styles.svg +96 -0
  270. datalab/data/icons/view/show_first.svg +55 -0
  271. datalab/data/icons/view/show_titles.svg +46 -0
  272. datalab/data/icons/visualization.svg +51 -0
  273. datalab/data/logo/DataLab-Banner-150.png +0 -0
  274. datalab/data/logo/DataLab-Banner-200.png +0 -0
  275. datalab/data/logo/DataLab-Banner2-100.png +0 -0
  276. datalab/data/logo/DataLab-Splash.png +0 -0
  277. datalab/data/logo/DataLab-watermark.png +0 -0
  278. datalab/data/logo/DataLab.svg +83 -0
  279. datalab/data/tests/reordering_test.h5 +0 -0
  280. datalab/data/tutorials/fabry_perot/fabry-perot1.jpg +0 -0
  281. datalab/data/tutorials/fabry_perot/fabry-perot2.jpg +0 -0
  282. datalab/data/tutorials/laser_beam/TEM00_z_13.jpg +0 -0
  283. datalab/data/tutorials/laser_beam/TEM00_z_18.jpg +0 -0
  284. datalab/data/tutorials/laser_beam/TEM00_z_23.jpg +0 -0
  285. datalab/data/tutorials/laser_beam/TEM00_z_30.jpg +0 -0
  286. datalab/data/tutorials/laser_beam/TEM00_z_35.jpg +0 -0
  287. datalab/data/tutorials/laser_beam/TEM00_z_40.jpg +0 -0
  288. datalab/data/tutorials/laser_beam/TEM00_z_45.jpg +0 -0
  289. datalab/data/tutorials/laser_beam/TEM00_z_50.jpg +0 -0
  290. datalab/data/tutorials/laser_beam/TEM00_z_55.jpg +0 -0
  291. datalab/data/tutorials/laser_beam/TEM00_z_60.jpg +0 -0
  292. datalab/data/tutorials/laser_beam/TEM00_z_65.jpg +0 -0
  293. datalab/data/tutorials/laser_beam/TEM00_z_70.jpg +0 -0
  294. datalab/data/tutorials/laser_beam/TEM00_z_75.jpg +0 -0
  295. datalab/data/tutorials/laser_beam/TEM00_z_80.jpg +0 -0
  296. datalab/env.py +542 -0
  297. datalab/gui/__init__.py +89 -0
  298. datalab/gui/actionhandler.py +1701 -0
  299. datalab/gui/docks.py +473 -0
  300. datalab/gui/h5io.py +150 -0
  301. datalab/gui/macroeditor.py +310 -0
  302. datalab/gui/main.py +2081 -0
  303. datalab/gui/newobject.py +217 -0
  304. datalab/gui/objectview.py +766 -0
  305. datalab/gui/panel/__init__.py +48 -0
  306. datalab/gui/panel/base.py +3254 -0
  307. datalab/gui/panel/image.py +157 -0
  308. datalab/gui/panel/macro.py +607 -0
  309. datalab/gui/panel/signal.py +164 -0
  310. datalab/gui/plothandler.py +800 -0
  311. datalab/gui/processor/__init__.py +84 -0
  312. datalab/gui/processor/base.py +2456 -0
  313. datalab/gui/processor/catcher.py +75 -0
  314. datalab/gui/processor/image.py +1214 -0
  315. datalab/gui/processor/signal.py +755 -0
  316. datalab/gui/profiledialog.py +333 -0
  317. datalab/gui/roieditor.py +633 -0
  318. datalab/gui/roigrideditor.py +208 -0
  319. datalab/gui/settings.py +612 -0
  320. datalab/gui/tour.py +908 -0
  321. datalab/h5/__init__.py +12 -0
  322. datalab/h5/common.py +314 -0
  323. datalab/h5/generic.py +580 -0
  324. datalab/h5/native.py +39 -0
  325. datalab/h5/utils.py +95 -0
  326. datalab/objectmodel.py +640 -0
  327. datalab/plugins/_readme_.txt +9 -0
  328. datalab/plugins/datalab_imageformats.py +175 -0
  329. datalab/plugins/datalab_testdata.py +190 -0
  330. datalab/plugins.py +355 -0
  331. datalab/tests/__init__.py +199 -0
  332. datalab/tests/backbone/__init__.py +1 -0
  333. datalab/tests/backbone/config_unit_test.py +170 -0
  334. datalab/tests/backbone/config_versioning_unit_test.py +34 -0
  335. datalab/tests/backbone/dictlistserial_app_test.py +38 -0
  336. datalab/tests/backbone/errorcatcher_unit_test.py +69 -0
  337. datalab/tests/backbone/errormsgbox_unit_test.py +50 -0
  338. datalab/tests/backbone/execenv_unit.py +262 -0
  339. datalab/tests/backbone/loadtest_gdi.py +147 -0
  340. datalab/tests/backbone/long_callback.py +96 -0
  341. datalab/tests/backbone/main_app_test.py +137 -0
  342. datalab/tests/backbone/memory_leak.py +43 -0
  343. datalab/tests/backbone/procisolation1_unit.py +128 -0
  344. datalab/tests/backbone/procisolation2_unit.py +171 -0
  345. datalab/tests/backbone/procisolation_unit_test.py +22 -0
  346. datalab/tests/backbone/profiling_app.py +27 -0
  347. datalab/tests/backbone/strings_unit_test.py +65 -0
  348. datalab/tests/backbone/title_formatting_unit_test.py +82 -0
  349. datalab/tests/conftest.py +131 -0
  350. datalab/tests/features/__init__.py +1 -0
  351. datalab/tests/features/applauncher/__init__.py +1 -0
  352. datalab/tests/features/applauncher/launcher1_app_test.py +28 -0
  353. datalab/tests/features/applauncher/launcher2_app_test.py +30 -0
  354. datalab/tests/features/common/__init__.py +1 -0
  355. datalab/tests/features/common/add_metadata_app_test.py +134 -0
  356. datalab/tests/features/common/add_metadata_unit_test.py +267 -0
  357. datalab/tests/features/common/annotations_management_unit_test.py +152 -0
  358. datalab/tests/features/common/auto_analysis_recompute_unit_test.py +240 -0
  359. datalab/tests/features/common/createobject_unit_test.py +50 -0
  360. datalab/tests/features/common/geometry_results_app_test.py +135 -0
  361. datalab/tests/features/common/interactive_processing_test.py +1109 -0
  362. datalab/tests/features/common/io_app_test.py +75 -0
  363. datalab/tests/features/common/large_results_app_test.py +187 -0
  364. datalab/tests/features/common/metadata_all_patterns_test.py +103 -0
  365. datalab/tests/features/common/metadata_app_test.py +139 -0
  366. datalab/tests/features/common/metadata_io_unit_test.py +60 -0
  367. datalab/tests/features/common/misc_app_test.py +236 -0
  368. datalab/tests/features/common/multiple_geometry_results_unit_test.py +122 -0
  369. datalab/tests/features/common/multiple_table_results_unit_test.py +64 -0
  370. datalab/tests/features/common/operation_modes_app_test.py +392 -0
  371. datalab/tests/features/common/plot_results_app_test.py +278 -0
  372. datalab/tests/features/common/reorder_app_test.py +75 -0
  373. datalab/tests/features/common/result_deletion_unit_test.py +96 -0
  374. datalab/tests/features/common/result_merged_label_unit_test.py +154 -0
  375. datalab/tests/features/common/result_shape_settings_unit_test.py +223 -0
  376. datalab/tests/features/common/roi_plotitem_unit_test.py +64 -0
  377. datalab/tests/features/common/roieditor_unit_test.py +102 -0
  378. datalab/tests/features/common/save_to_dir_app_test.py +163 -0
  379. datalab/tests/features/common/save_to_dir_unit_test.py +474 -0
  380. datalab/tests/features/common/stat_app_test.py +40 -0
  381. datalab/tests/features/common/stats_tools_unit_test.py +77 -0
  382. datalab/tests/features/common/table_results_app_test.py +52 -0
  383. datalab/tests/features/common/textimport_unit_test.py +131 -0
  384. datalab/tests/features/common/uuid_preservation_test.py +281 -0
  385. datalab/tests/features/common/worker_unit_test.py +402 -0
  386. datalab/tests/features/control/__init__.py +1 -0
  387. datalab/tests/features/control/connect_dialog.py +28 -0
  388. datalab/tests/features/control/embedded1_unit_test.py +304 -0
  389. datalab/tests/features/control/embedded2_unit_test.py +52 -0
  390. datalab/tests/features/control/remoteclient_app_test.py +219 -0
  391. datalab/tests/features/control/remoteclient_unit.py +75 -0
  392. datalab/tests/features/control/simpleclient_unit_test.py +321 -0
  393. datalab/tests/features/hdf5/__init__.py +1 -0
  394. datalab/tests/features/hdf5/h5browser1_unit_test.py +31 -0
  395. datalab/tests/features/hdf5/h5browser2_unit.py +55 -0
  396. datalab/tests/features/hdf5/h5browser_app_test.py +77 -0
  397. datalab/tests/features/hdf5/h5import_app_test.py +25 -0
  398. datalab/tests/features/hdf5/h5importer_app_test.py +34 -0
  399. datalab/tests/features/image/__init__.py +1 -0
  400. datalab/tests/features/image/annotations_app_test.py +28 -0
  401. datalab/tests/features/image/annotations_unit_test.py +80 -0
  402. datalab/tests/features/image/average_app_test.py +46 -0
  403. datalab/tests/features/image/background_dialog_test.py +70 -0
  404. datalab/tests/features/image/blobs_app_test.py +50 -0
  405. datalab/tests/features/image/contour_app_test.py +42 -0
  406. datalab/tests/features/image/contour_fabryperot_app_test.py +51 -0
  407. datalab/tests/features/image/denoise_app_test.py +31 -0
  408. datalab/tests/features/image/distribute_on_grid_app_test.py +95 -0
  409. datalab/tests/features/image/edges_app_test.py +31 -0
  410. datalab/tests/features/image/erase_app_test.py +21 -0
  411. datalab/tests/features/image/fft2d_app_test.py +27 -0
  412. datalab/tests/features/image/flatfield_app_test.py +40 -0
  413. datalab/tests/features/image/geometry_transform_unit_test.py +396 -0
  414. datalab/tests/features/image/imagetools_app_test.py +51 -0
  415. datalab/tests/features/image/imagetools_unit_test.py +27 -0
  416. datalab/tests/features/image/load_app_test.py +73 -0
  417. datalab/tests/features/image/morph_app_test.py +32 -0
  418. datalab/tests/features/image/offsetcorrection_app_test.py +30 -0
  419. datalab/tests/features/image/peak2d_app_test.py +53 -0
  420. datalab/tests/features/image/profile_app_test.py +73 -0
  421. datalab/tests/features/image/profile_dialog_test.py +56 -0
  422. datalab/tests/features/image/roi_app_test.py +98 -0
  423. datalab/tests/features/image/roi_circ_app_test.py +62 -0
  424. datalab/tests/features/image/roi_manipulation_app_test.py +268 -0
  425. datalab/tests/features/image/roigrid_unit_test.py +60 -0
  426. datalab/tests/features/image/side_by_side_app_test.py +52 -0
  427. datalab/tests/features/macro/__init__.py +1 -0
  428. datalab/tests/features/macro/macro_app_test.py +28 -0
  429. datalab/tests/features/macro/macroeditor_unit_test.py +102 -0
  430. datalab/tests/features/signal/__init__.py +1 -0
  431. datalab/tests/features/signal/baseline_dialog_test.py +53 -0
  432. datalab/tests/features/signal/deltax_dialog_unit_test.py +34 -0
  433. datalab/tests/features/signal/fft1d_app_test.py +26 -0
  434. datalab/tests/features/signal/filter_app_test.py +44 -0
  435. datalab/tests/features/signal/fitdialog_unit_test.py +50 -0
  436. datalab/tests/features/signal/interpolation_app_test.py +110 -0
  437. datalab/tests/features/signal/loadbigsignal_app_test.py +80 -0
  438. datalab/tests/features/signal/multiple_rois_unit_test.py +132 -0
  439. datalab/tests/features/signal/pulse_features_app_test.py +118 -0
  440. datalab/tests/features/signal/pulse_features_roi_app_test.py +55 -0
  441. datalab/tests/features/signal/roi_app_test.py +78 -0
  442. datalab/tests/features/signal/roi_manipulation_app_test.py +261 -0
  443. datalab/tests/features/signal/select_xy_cursor_unit_test.py +46 -0
  444. datalab/tests/features/signal/signalpeakdetection_dialog_test.py +33 -0
  445. datalab/tests/features/signal/signals_to_image_app_test.py +98 -0
  446. datalab/tests/features/signal/xarray_compat_app_test.py +128 -0
  447. datalab/tests/features/tour_unit_test.py +22 -0
  448. datalab/tests/features/utilities/__init__.py +1 -0
  449. datalab/tests/features/utilities/installconf_unit_test.py +21 -0
  450. datalab/tests/features/utilities/logview_app_test.py +21 -0
  451. datalab/tests/features/utilities/logview_error.py +24 -0
  452. datalab/tests/features/utilities/logview_unit_test.py +21 -0
  453. datalab/tests/features/utilities/memstatus_app_test.py +42 -0
  454. datalab/tests/features/utilities/settings_unit_test.py +88 -0
  455. datalab/tests/scenarios/__init__.py +1 -0
  456. datalab/tests/scenarios/beautiful_app.py +121 -0
  457. datalab/tests/scenarios/common.py +463 -0
  458. datalab/tests/scenarios/demo.py +212 -0
  459. datalab/tests/scenarios/example_app_test.py +47 -0
  460. datalab/tests/scenarios/scenario_h5_app_test.py +75 -0
  461. datalab/tests/scenarios/scenario_ima1_app_test.py +34 -0
  462. datalab/tests/scenarios/scenario_ima2_app_test.py +34 -0
  463. datalab/tests/scenarios/scenario_mac_app_test.py +58 -0
  464. datalab/tests/scenarios/scenario_sig1_app_test.py +36 -0
  465. datalab/tests/scenarios/scenario_sig2_app_test.py +35 -0
  466. datalab/utils/__init__.py +1 -0
  467. datalab/utils/conf.py +304 -0
  468. datalab/utils/dephash.py +105 -0
  469. datalab/utils/qthelpers.py +633 -0
  470. datalab/utils/strings.py +34 -0
  471. datalab/utils/tests.py +0 -0
  472. datalab/widgets/__init__.py +1 -0
  473. datalab/widgets/connection.py +138 -0
  474. datalab/widgets/filedialog.py +91 -0
  475. datalab/widgets/fileviewer.py +84 -0
  476. datalab/widgets/fitdialog.py +788 -0
  477. datalab/widgets/h5browser.py +1048 -0
  478. datalab/widgets/imagebackground.py +111 -0
  479. datalab/widgets/instconfviewer.py +175 -0
  480. datalab/widgets/logviewer.py +80 -0
  481. datalab/widgets/signalbaseline.py +90 -0
  482. datalab/widgets/signalcursor.py +208 -0
  483. datalab/widgets/signaldeltax.py +151 -0
  484. datalab/widgets/signalpeak.py +199 -0
  485. datalab/widgets/status.py +249 -0
  486. datalab/widgets/textimport.py +786 -0
  487. datalab/widgets/warningerror.py +223 -0
  488. datalab/widgets/wizard.py +286 -0
  489. datalab_platform-1.0.1.dist-info/METADATA +121 -0
  490. datalab_platform-1.0.1.dist-info/RECORD +494 -0
  491. datalab_platform-0.0.1.dev0.dist-info/METADATA +0 -67
  492. datalab_platform-0.0.1.dev0.dist-info/RECORD +0 -7
  493. {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.1.dist-info}/WHEEL +0 -0
  494. {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.1.dist-info}/entry_points.txt +0 -0
  495. {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.1.dist-info}/licenses/LICENSE +0 -0
  496. {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.1.dist-info}/top_level.txt +0 -0
datalab/gui/docks.py ADDED
@@ -0,0 +1,473 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ Docks
5
+ =====
6
+
7
+ The :mod:`datalab.gui.docks` module provides the dockable widgets for the
8
+ DataLab main window.
9
+
10
+ Plot widget
11
+ -----------
12
+
13
+ .. autoclass:: DataLabPlotWidget
14
+
15
+ Dockable plot widget
16
+ --------------------
17
+
18
+ .. autoclass:: DockablePlotWidget
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ import warnings
24
+ from typing import TYPE_CHECKING
25
+
26
+ import numpy as np
27
+ import scipy.integrate as spt
28
+ from guidata.configtools import get_icon, get_image_file_path
29
+ from guidata.qthelpers import create_action, is_dark_theme
30
+ from guidata.widgets.dockable import DockableWidget
31
+ from plotpy.constants import PlotType
32
+ from plotpy.items import CurveItem
33
+ from plotpy.panels import XCrossSection, YCrossSection
34
+ from plotpy.plot import PlotOptions, PlotWidget
35
+ from plotpy.tools import (
36
+ BasePlotMenuTool,
37
+ CurveStatsTool,
38
+ DeleteItemTool,
39
+ DisplayCoordsTool,
40
+ DoAutoscaleTool,
41
+ EditItemDataTool,
42
+ ExportItemDataTool,
43
+ ImageStatsTool,
44
+ ItemCenterTool,
45
+ RectangularSelectionTool,
46
+ RectZoomTool,
47
+ SelectTool,
48
+ YRangeCursorTool,
49
+ )
50
+ from plotpy.tools.image import get_stats as get_image_stats
51
+ from qtpy import QtCore as QC
52
+ from qtpy import QtGui as QG
53
+ from qtpy import QtWidgets as QW
54
+ from qtpy.QtWidgets import QApplication, QMainWindow
55
+ from sigima.objects import create_signal
56
+ from sigima.tools.signal import pulse
57
+ from skimage import measure
58
+
59
+ from datalab.config import APP_NAME, Conf, _
60
+
61
+ if TYPE_CHECKING:
62
+ from plotpy.items.image.base import BaseImageItem
63
+ from plotpy.plot import BasePlot
64
+ from plotpy.styles import BaseImageParam
65
+
66
+
67
+ class CurveStatsToolFunctions:
68
+ """Statistical functions for `CurveStatsTool` and `YRangeCursorTool`"""
69
+
70
+ @classmethod
71
+ def set_labelfuncs(cls, statstool: CurveStatsTool) -> None:
72
+ """Set label functions for the statistics tool"""
73
+ if isinstance(statstool, CurveStatsTool):
74
+ labelfuncs = (
75
+ ("%g < x < %g", lambda *args: cls.nan_min_max(args[0])),
76
+ ("%g < y < %g", lambda *args: cls.nan_min_max(args[1])),
77
+ ("∆x=%g", lambda *args: cls.nan_delta(args[0])),
78
+ ("∆y=%g", lambda *args: cls.nan_delta(args[1])),
79
+ ("<y>=%g", lambda *args: cls.nan_mean(args[1])),
80
+ ("σ(y)=%g", lambda *args: cls.nan_std(args[1])),
81
+ ("∑(y)=%g", lambda *args: spt.trapezoid(args[1])),
82
+ ("∫ydx=%g<br>", lambda *args: spt.trapezoid(args[1], args[0])),
83
+ ("FWHM=%s", cls.fwhm_info),
84
+ ("∆x<sub>RISE 10-90</sub>=%s", cls.rise_time_info),
85
+ (
86
+ "∆x<sub>RISE 20-80</sub>=%s",
87
+ lambda x, y: cls.rise_time_info(x, y, 0.2, 0.8),
88
+ ),
89
+ ("∆x<sub>FALL 90-10</sub>=%s", cls.fall_time_info),
90
+ (
91
+ "∆x<sub>FALL 80-20</sub>=%s",
92
+ lambda x, y: cls.fall_time_info(x, y, 0.8, 0.2),
93
+ ),
94
+ )
95
+ else: # YRangeCursorTool
96
+ labelfuncs = (
97
+ ("%g &lt; y &lt; %g", lambda ymin, ymax: (ymin, ymax)),
98
+ ("∆y=%g", lambda ymin, ymax: ymax - ymin),
99
+ )
100
+ statstool.set_labelfuncs(labelfuncs)
101
+
102
+ @staticmethod
103
+ def nan_min_max(arr: np.ndarray) -> tuple[float, float]:
104
+ """Return min/max tuple"""
105
+ with warnings.catch_warnings():
106
+ warnings.simplefilter("ignore", RuntimeWarning)
107
+ min_val = np.nanmin(arr)
108
+ max_val = np.nanmax(arr)
109
+ return (min_val, max_val)
110
+
111
+ @staticmethod
112
+ def nan_delta(arr: np.ndarray) -> float:
113
+ """Return delta value, ignoring NaNs"""
114
+ with warnings.catch_warnings():
115
+ warnings.simplefilter("ignore", RuntimeWarning)
116
+ delta_val = np.nanmax(arr) - np.nanmin(arr)
117
+ return delta_val
118
+
119
+ @staticmethod
120
+ def nan_mean(arr: np.ndarray) -> float:
121
+ """Return mean value, ignoring NaNs"""
122
+ with warnings.catch_warnings():
123
+ warnings.simplefilter("ignore", RuntimeWarning)
124
+ mean_val = np.nanmean(arr)
125
+ return mean_val
126
+
127
+ @staticmethod
128
+ def nan_std(arr: np.ndarray) -> float:
129
+ """Return standard deviation, ignoring NaNs"""
130
+ with warnings.catch_warnings():
131
+ warnings.simplefilter("ignore", RuntimeWarning)
132
+ std_val = np.nanstd(arr)
133
+ return std_val
134
+
135
+ @staticmethod
136
+ def fwhm_info(x, y):
137
+ """Return FWHM information string"""
138
+ try:
139
+ with warnings.catch_warnings(record=True) as w:
140
+ x0, _y0, x1, _y1 = pulse.fwhm(x, y, "zero-crossing")
141
+ wstr = " ⚠️" if w else ""
142
+ except (ValueError, ZeroDivisionError, pulse.InvalidSignalError):
143
+ return "🛑"
144
+ return f"{x1 - x0:g}{wstr}"
145
+
146
+ @staticmethod
147
+ def rise_time_info(x, y, start_ratio=0.1, end_ratio=0.9):
148
+ """Return rise time information string"""
149
+ try:
150
+ with warnings.catch_warnings(record=True) as w:
151
+ dt = pulse.get_rise_time(x, y, start_ratio, end_ratio)
152
+ wstr = " ⚠️" if w else ""
153
+ if dt is None:
154
+ return "🛑"
155
+ except (ValueError, ZeroDivisionError, pulse.InvalidSignalError):
156
+ return "🛑"
157
+ return f"{dt:g}{wstr}"
158
+
159
+ @staticmethod
160
+ def fall_time_info(x, y, start_ratio=0.9, end_ratio=0.1):
161
+ """Return fall time information string"""
162
+ try:
163
+ with warnings.catch_warnings(record=True) as w:
164
+ dt = pulse.get_fall_time(x, y, start_ratio, end_ratio)
165
+ wstr = " ⚠️" if w else ""
166
+ if dt is None:
167
+ return "🛑"
168
+ except (ValueError, ZeroDivisionError, pulse.InvalidSignalError):
169
+ return "🛑"
170
+ return f"{dt:g}{wstr}"
171
+
172
+
173
+ def get_more_image_stats(
174
+ item: BaseImageItem,
175
+ x0: float,
176
+ y0: float,
177
+ x1: float,
178
+ y1: float,
179
+ ) -> str:
180
+ """Return formatted string with stats on image rectangular area
181
+ (output should be compatible with AnnotatedShape.get_info)
182
+
183
+ Args:
184
+ item: image item
185
+ x0: X0
186
+ y0: Y0
187
+ x1: X1
188
+ y1: Y1
189
+ """
190
+ with warnings.catch_warnings():
191
+ warnings.simplefilter("ignore", UserWarning)
192
+ info = get_image_stats(item, x0, y0, x1, y1)
193
+
194
+ ix0, iy0, ix1, iy1 = item.get_closest_index_rect(x0, y0, x1, y1)
195
+ data = item.data[iy0:iy1, ix0:ix1]
196
+ p: BaseImageParam = item.param
197
+ xunit, yunit, zunit = p.get_units()
198
+
199
+ integral = np.nansum(data)
200
+ integral_fmt = r"%.3e " + zunit
201
+ info += f"<br>∑ = {integral_fmt % integral}"
202
+
203
+ if xunit == yunit:
204
+ surfacefmt = p.xformat.split()[0] + " " + xunit
205
+ if xunit != "":
206
+ surfacefmt = surfacefmt + "²"
207
+ surface = abs((x1 - x0) * (y1 - y0))
208
+ info += f"<br>A = {surfacefmt % surface}"
209
+ if xunit is not None and zunit is not None:
210
+ if surface != 0:
211
+ density = integral / surface
212
+ densityfmt = r"%.3e"
213
+ if xunit and zunit:
214
+ densityfmt += " " + zunit + "/" + xunit + "²"
215
+ info = info + f"<br>ρ = {densityfmt % density}"
216
+
217
+ c_i, c_j = measure.centroid(data)
218
+ c_x, c_y = item.get_plot_coordinates(c_j + ix0, c_i + iy0)
219
+ info += "<br>" + "<br>".join(
220
+ [
221
+ "C|x = " + p.xformat % c_x,
222
+ "C|y = " + p.yformat % c_y,
223
+ ]
224
+ )
225
+
226
+ return info
227
+
228
+
229
+ def profile_to_signal(plot: BasePlot, panel: XCrossSection | YCrossSection) -> None:
230
+ """Send cross section curve to DataLab's signal list
231
+
232
+ Args:
233
+ panel: Cross section panel
234
+ """
235
+ win = None
236
+ for win in QApplication.topLevelWidgets():
237
+ if isinstance(win, QMainWindow):
238
+ break
239
+ if win is None or win.objectName() != APP_NAME:
240
+ # pylint: disable=import-outside-toplevel
241
+ # pylint: disable=cyclic-import
242
+ from datalab.gui import main
243
+
244
+ # Note : this is the only way to retrieve the DataLab main window instance
245
+ # when the CrossSectionItem object is embedded into an image widget
246
+ # parented to another main window.
247
+ win = main.DLMainWindow.get_instance()
248
+ assert win is not None # Should never happen
249
+
250
+ for item in panel.cs_plot.get_items():
251
+ if not isinstance(item, CurveItem):
252
+ continue
253
+ x, y, _dx, _dy = item.get_data()
254
+ if x is None or y is None or x.size == 0 or y.size == 0:
255
+ continue
256
+
257
+ signal = create_signal(item.param.label)
258
+
259
+ if isinstance(panel, YCrossSection):
260
+ signal.set_xydata(y, x)
261
+ xaxis_name = "left"
262
+ xunit = plot.get_axis_unit("bottom")
263
+ if xunit:
264
+ signal.title += " " + xunit
265
+ else:
266
+ signal.set_xydata(x, y)
267
+ xaxis_name = "bottom"
268
+ yunit = plot.get_axis_unit("left")
269
+ if yunit:
270
+ signal.title += " " + yunit
271
+
272
+ signal.ylabel = plot.get_axis_title("right")
273
+ signal.yunit = plot.get_axis_unit("right")
274
+ signal.xlabel = plot.get_axis_title(xaxis_name)
275
+ signal.xunit = plot.get_axis_unit(xaxis_name)
276
+
277
+ win.signalpanel.add_object(signal)
278
+
279
+ # Show DataLab main window on top, if not already visible
280
+ win.show()
281
+ win.raise_()
282
+
283
+
284
+ class DataLabPlotWidget(PlotWidget):
285
+ """DataLab PlotWidget
286
+
287
+ This class is a subclass of `plotpy.plot.PlotWidget` that provides a
288
+ customized widget for DataLab, with a specific set of tools and a
289
+ customized appearance.
290
+
291
+ Args:
292
+ plot_type: Plot type
293
+ """
294
+
295
+ def __init__(self, plot_type: PlotType) -> None:
296
+ # Get autoscale margin from configuration based on plot type
297
+ if plot_type == PlotType.CURVE:
298
+ autoscale_margin = Conf.view.sig_autoscale_margin_percent.get()
299
+ elif plot_type == PlotType.IMAGE:
300
+ autoscale_margin = Conf.view.ima_autoscale_margin_percent.get()
301
+ else:
302
+ # For AUTO or MANUAL types, use signal margin as default
303
+ autoscale_margin = Conf.view.sig_autoscale_margin_percent.get()
304
+
305
+ super().__init__(
306
+ options=PlotOptions(
307
+ type=plot_type,
308
+ show_axes_tab=False,
309
+ autoscale_margin_percent=autoscale_margin,
310
+ ),
311
+ toolbar=True,
312
+ )
313
+
314
+ def __register_standard_tools(self) -> None:
315
+ """Register standard tools
316
+
317
+ The only differences with the `manager.register_standard_tools` method are
318
+ the following:
319
+
320
+ 1. We don't register the `BasePlotMenuTool, "axes"` tool, because it is not
321
+ compatible with DataLab's approach to axes management.
322
+ 2. We don't register the `ItemListPanelTool` tool (this intends to prevent
323
+ the user from accessing the item list panel, and thus, the parameters of all
324
+ the items - some of them are read-only and should not be modified, like the
325
+ annotations for example).
326
+ """
327
+ mgr = self.manager
328
+ select_tool = mgr.add_tool(SelectTool)
329
+ mgr.set_default_tool(select_tool)
330
+ mgr.add_tool(RectangularSelectionTool, intersect=False)
331
+ mgr.add_tool(RectZoomTool)
332
+ mgr.add_tool(DoAutoscaleTool)
333
+ mgr.add_tool(BasePlotMenuTool, "item")
334
+ mgr.add_tool(ExportItemDataTool)
335
+ mgr.add_tool(EditItemDataTool)
336
+ mgr.add_tool(ItemCenterTool)
337
+ mgr.add_tool(DeleteItemTool)
338
+ mgr.add_separator_tool()
339
+ mgr.add_tool(BasePlotMenuTool, "grid")
340
+ mgr.add_tool(DisplayCoordsTool)
341
+
342
+ def __register_other_tools(self) -> None:
343
+ """Register other tools"""
344
+ mgr = self.manager
345
+ mgr.add_separator_tool()
346
+ if self.options.type == PlotType.CURVE:
347
+ mgr.register_curve_tools()
348
+ xstatstool = mgr.get_tool(CurveStatsTool)
349
+ CurveStatsToolFunctions.set_labelfuncs(xstatstool)
350
+ ystatstool = mgr.get_tool(YRangeCursorTool)
351
+ CurveStatsToolFunctions.set_labelfuncs(ystatstool)
352
+ else:
353
+ mgr.register_image_tools()
354
+ # Customizing the ImageStatsTool
355
+ statstool = mgr.get_tool(ImageStatsTool)
356
+ statstool.set_stats_func(get_more_image_stats, replace=True)
357
+ # Customizing the X and Y cross section panels
358
+ plot = mgr.get_plot()
359
+ for panel in (mgr.get_xcs_panel(), mgr.get_ycs_panel()):
360
+ to_signal_action = create_action(
361
+ panel,
362
+ _("Process signal"),
363
+ icon=get_icon("to_signal.svg"),
364
+ triggered=lambda panel=panel: profile_to_signal(plot, panel),
365
+ )
366
+ tb = panel.toolbar
367
+ tb.insertSeparator(tb.actions()[0])
368
+ tb.insertAction(tb.actions()[0], to_signal_action)
369
+
370
+ mgr.add_separator_tool()
371
+ mgr.register_other_tools()
372
+ mgr.add_separator_tool()
373
+ mgr.update_tools_status()
374
+ mgr.get_default_tool().activate()
375
+
376
+ def register_tools(self) -> None:
377
+ """Register the plotting tools according to the plot type"""
378
+ self.__register_standard_tools()
379
+ self.__register_other_tools()
380
+
381
+
382
+ class DockablePlotWidget(DockableWidget):
383
+ """Docked plotting widget
384
+
385
+ Args:
386
+ parent: Parent widget
387
+ plot_type: Plot type
388
+ """
389
+
390
+ LOCATION = QC.Qt.RightDockWidgetArea
391
+
392
+ def __init__(
393
+ self,
394
+ parent: QW.QWidget,
395
+ plot_type: PlotType,
396
+ ) -> None:
397
+ super().__init__(parent)
398
+ self.plotwidget = DataLabPlotWidget(plot_type)
399
+ self.toolbar = self.plotwidget.get_toolbar()
400
+ self.watermark = QW.QLabel()
401
+ original_image = QG.QPixmap(get_image_file_path("DataLab-watermark.png"))
402
+ self.watermark.setPixmap(original_image)
403
+ self.setup_layout()
404
+ self.setup_plotwidget()
405
+
406
+ def __get_toolbar_row_col(self) -> tuple[int, int]:
407
+ """Return toolbar row and column"""
408
+ tb_pos = Conf.view.plot_toolbar_position.get()
409
+ tb_col, tb_row = 1, 1
410
+ if tb_pos in ("left", "right"):
411
+ self.toolbar.setOrientation(QC.Qt.Vertical)
412
+ tb_col = 0 if tb_pos == "left" else 2
413
+ else:
414
+ self.toolbar.setOrientation(QC.Qt.Horizontal)
415
+ tb_row = 0 if tb_pos == "top" else 2
416
+ return tb_row, tb_col
417
+
418
+ def setup_layout(self) -> None:
419
+ """Setup layout"""
420
+ tb_row, tb_col = self.__get_toolbar_row_col()
421
+ layout = QW.QGridLayout()
422
+ layout.addWidget(self.toolbar, tb_row, tb_col)
423
+ layout.addWidget(self.plotwidget, 1, 1)
424
+ layout.addWidget(self.watermark, 1, 1, QC.Qt.AlignCenter)
425
+ self.setLayout(layout)
426
+
427
+ def update_toolbar_position(self) -> None:
428
+ """Update toolbar position"""
429
+ tb_row, tb_col = self.__get_toolbar_row_col()
430
+ layout = self.layout()
431
+ layout.removeWidget(self.toolbar)
432
+ layout.addWidget(self.toolbar, tb_row, tb_col)
433
+
434
+ def setup_plotwidget(self) -> None:
435
+ """Setup plotting widget"""
436
+ title = self.toolbar.windowTitle()
437
+ self.plotwidget.get_manager().add_toolbar(self.toolbar, title)
438
+ # Customizing widget appearances
439
+ self.update_color_mode()
440
+ plot = self.plotwidget.get_plot()
441
+ canvas = plot.canvas()
442
+ canvas.setFrameStyle(canvas.Plain | canvas.NoFrame)
443
+ plot.SIG_ITEMS_CHANGED.connect(self.update_watermark)
444
+
445
+ def update_color_mode(self) -> None:
446
+ """Update plot widget styles according to application color mode"""
447
+ if is_dark_theme():
448
+ palette = QApplication.instance().palette()
449
+ else:
450
+ palette = QG.QPalette(QC.Qt.white)
451
+ for widget in (self.plotwidget, self.plotwidget.get_plot(), self):
452
+ widget.setBackgroundRole(QG.QPalette.Window)
453
+ widget.setAutoFillBackground(True)
454
+ widget.setPalette(palette)
455
+
456
+ def get_plot(self) -> BasePlot:
457
+ """Return plot instance"""
458
+ return self.plotwidget.get_plot()
459
+
460
+ def update_watermark(self, plot: BasePlot) -> None:
461
+ """Update watermark visibility"""
462
+ items = plot.get_items()
463
+ if self.plotwidget.options.type == PlotType.IMAGE:
464
+ enabled = len(items) <= 1
465
+ else:
466
+ enabled = len(items) <= 2
467
+ self.watermark.setVisible(enabled)
468
+
469
+ # ------DockableWidget API
470
+ def visibility_changed(self, enable: bool) -> None:
471
+ """DockWidget visibility has changed"""
472
+ DockableWidget.visibility_changed(self, enable)
473
+ self.toolbar.setVisible(enable)
datalab/gui/h5io.py ADDED
@@ -0,0 +1,150 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ HDF5 I/O
5
+ ========
6
+
7
+ The :mod:`datalab.gui.h5io` module provides the HDF5 file open/save into/from
8
+ DataLab data model/main window.
9
+
10
+ .. autoclass:: H5InputOutput
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import os.path as osp
16
+ from typing import TYPE_CHECKING
17
+
18
+ from guidata.qthelpers import exec_dialog
19
+ from qtpy import QtWidgets as QW
20
+ from sigima.objects import SignalObj
21
+
22
+ from datalab.config import _
23
+ from datalab.env import execenv
24
+ from datalab.h5 import H5Importer
25
+ from datalab.h5.native import NativeH5Reader, NativeH5Writer
26
+ from datalab.utils.qthelpers import create_progress_bar, qt_try_loadsave_file
27
+ from datalab.widgets.h5browser import H5BrowserDialog
28
+
29
+ if TYPE_CHECKING:
30
+ from datalab.gui.main import DLMainWindow
31
+ from datalab.h5.common import BaseNode
32
+
33
+
34
+ class H5InputOutput:
35
+ """Object handling HDF5 file open/save into/from DataLab data model/main window
36
+
37
+ Args:
38
+ mainwindow: Main window
39
+ """
40
+
41
+ def __init__(self, mainwindow: DLMainWindow) -> None:
42
+ self.mainwindow = mainwindow
43
+ self.uint32_wng: bool = None
44
+
45
+ @staticmethod
46
+ def __progbartitle(fname: str) -> str:
47
+ """Return progress bar title"""
48
+ return _("Loading data from %s...") % osp.basename(fname)
49
+
50
+ def save_file(self, filename: str) -> None:
51
+ """Save all signals and images from DataLab model into a HDF5 file"""
52
+ writer = NativeH5Writer(filename)
53
+ for panel in self.mainwindow.panels:
54
+ panel.serialize_to_hdf5(writer)
55
+ writer.close()
56
+
57
+ def open_file(self, filename: str, import_all: bool, reset_all: bool) -> None:
58
+ """Open HDF5 file"""
59
+ progress = None
60
+ try:
61
+ reader = NativeH5Reader(filename)
62
+ if reset_all:
63
+ self.mainwindow.reset_all()
64
+ with create_progress_bar(
65
+ self.mainwindow, self.__progbartitle(filename), 2
66
+ ) as progress:
67
+ for idx, panel in enumerate(self.mainwindow.panels):
68
+ progress.setValue(idx + 1)
69
+ QW.QApplication.processEvents()
70
+ panel.deserialize_from_hdf5(reader, reset_all)
71
+ if progress.wasCanceled():
72
+ break
73
+ reader.close()
74
+ except KeyError:
75
+ if progress is not None:
76
+ # KeyError was encoutered when deserializing datasets (DataLab data
77
+ # model is not compatible with this version)
78
+ progress.close()
79
+ self.import_files([filename], import_all, reset_all)
80
+
81
+ def __add_object_from_node(self, node: BaseNode) -> None:
82
+ """Add DataLab object from h5 node"""
83
+ obj = node.get_native_object()
84
+ if obj is None:
85
+ return
86
+ self.uint32_wng = self.uint32_wng or node.uint32_wng
87
+ if isinstance(obj, SignalObj):
88
+ self.mainwindow.signalpanel.add_object(obj)
89
+ else:
90
+ self.mainwindow.imagepanel.add_object(obj)
91
+
92
+ def __eventually_show_warnings(self) -> None:
93
+ """Eventually show warnings after everything is imported"""
94
+ if self.uint32_wng:
95
+ QW.QMessageBox.warning(
96
+ self.mainwindow, _("Warning"), _("Clipping uint32 data to int32.")
97
+ )
98
+
99
+ def import_files(
100
+ self, filenames: list[str], import_all: bool, reset_all: bool
101
+ ) -> None:
102
+ """Import HDF5 files"""
103
+ h5browser = H5BrowserDialog(self.mainwindow)
104
+ for filename in filenames:
105
+ with qt_try_loadsave_file(self.mainwindow, filename, "load"):
106
+ h5browser.open_file(filename)
107
+ if h5browser.is_empty():
108
+ h5browser.cleanup()
109
+ if not execenv.unattended:
110
+ QW.QMessageBox.warning(
111
+ self.mainwindow,
112
+ _("Warning"),
113
+ _("No supported data available in HDF5 file(s)."),
114
+ )
115
+ return
116
+ if execenv.unattended:
117
+ # Unattended mode: import all datasets (for testing)
118
+ import_all = True
119
+ if import_all or exec_dialog(h5browser):
120
+ if import_all:
121
+ nodes = h5browser.get_all_nodes()
122
+ else:
123
+ nodes = h5browser.get_nodes()
124
+ if nodes is not None:
125
+ if reset_all:
126
+ self.mainwindow.reset_all()
127
+ with qt_try_loadsave_file(self.mainwindow, "*.h5", "load"):
128
+ with create_progress_bar(self.mainwindow, "", len(nodes)) as prog:
129
+ self.uint32_wng = False
130
+ for idx, node in enumerate(nodes):
131
+ prog.setLabelText(self.__progbartitle(node.h5file.filename))
132
+ prog.setValue(idx + 1)
133
+ QW.QApplication.processEvents()
134
+ if prog.wasCanceled():
135
+ break
136
+ self.__add_object_from_node(node)
137
+ self.__eventually_show_warnings()
138
+ h5browser.cleanup()
139
+
140
+ def import_dataset_from_file(self, filename: str, dsetname: str) -> None:
141
+ """Import dataset from HDF5 file"""
142
+ h5importer = H5Importer(filename)
143
+ try:
144
+ node = h5importer.get(dsetname)
145
+ self.uint32_wng = False
146
+ self.__add_object_from_node(node)
147
+ self.__eventually_show_warnings()
148
+ except KeyError as exc:
149
+ raise KeyError(f"Dataset not found: {dsetname}") from exc
150
+ h5importer.close()