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
@@ -0,0 +1,147 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ GDI objects loading test
5
+ ========================
6
+
7
+ This test is specific to Windows. It is not relevant for other platforms.
8
+
9
+ This test aims at checking that all GDI objects are released when the
10
+ widget are closed (i.e. when the Python object is garbage collected).
11
+ """
12
+
13
+ # pylint: disable=invalid-name # Allows short reference names like x, y, ...
14
+ # pylint: disable=duplicate-code
15
+
16
+ # guitest: skip
17
+
18
+ from __future__ import annotations
19
+
20
+ import ctypes
21
+ import os
22
+
23
+ from sigima.objects import NewImageParam
24
+ from sigima.tests.data import create_sincos_image, iterate_image_creation
25
+
26
+ from datalab.env import execenv
27
+ from datalab.gui.main import DLMainWindow
28
+ from datalab.tests import datalab_test_app_context, helpers
29
+ from datalab.tests.scenarios.common import compute_common_operations
30
+
31
+ if os.name == "nt":
32
+ from ctypes import WinDLL
33
+
34
+ def get_gdi_count() -> int:
35
+ """Get the number of GDI objects for the current process.
36
+
37
+ This function uses the Windows API to get the count of GDI (Graphical
38
+ Device Interface) objects used by the current process.
39
+
40
+ Note: This function will only work on Windows.
41
+
42
+ Returns:
43
+ int: The count of GDI objects for the current process.
44
+ """
45
+ # Constants
46
+ GR_GDIOBJECTS: int = 0
47
+
48
+ # Load the User32 DLL
49
+ user32: WinDLL = ctypes.windll.user32
50
+
51
+ # Get the current process id
52
+ pid: int = os.getpid()
53
+
54
+ # Get handle of the process
55
+ handle: int = ctypes.windll.kernel32.OpenProcess(1040, 0, pid)
56
+
57
+ # Call the function and get the GDI count
58
+ gdi_count: int = user32.GetGuiResources(handle, GR_GDIOBJECTS)
59
+
60
+ # Close the handle
61
+ ctypes.windll.kernel32.CloseHandle(handle)
62
+
63
+ return gdi_count
64
+
65
+ else:
66
+
67
+ def get_gdi_count() -> int:
68
+ """Dumb function that always returns 0."""
69
+ return 0
70
+
71
+
72
+ def test_various_image_features(win: DLMainWindow):
73
+ """Run image related tests."""
74
+ win.set_current_panel("image")
75
+ panel = win.imagepanel
76
+ param = NewImageParam.create(height=150, width=150)
77
+ for image in iterate_image_creation(param.width, non_zero=True, verbose=False):
78
+ panel.add_object(create_sincos_image(param))
79
+ panel.add_object(image)
80
+ compute_common_operations(panel)
81
+ panel.remove_all_objects()
82
+ break
83
+
84
+
85
+ def test_gdi_count(win: DLMainWindow) -> int | None:
86
+ """Test the GDI count.
87
+
88
+ This function will create a DataSetGroup, show the widget, and then
89
+ close the widget. It will then check that the GDI count has not
90
+ increased.
91
+
92
+ Raises:
93
+ AssertionError: If the GDI count has increased.
94
+
95
+ Returns:
96
+ int: The GDI count after creating the widget.
97
+ """
98
+ # Get the GDI count before creating the widget
99
+ gdi_count_before: int = get_gdi_count()
100
+
101
+ execenv.print(f" GDI count: {gdi_count_before} --> ", end="")
102
+
103
+ # Create widgets during the test
104
+ test_various_image_features(win)
105
+
106
+ # Import HDF5 file using the HDF5 browser
107
+ win.open_h5_files(
108
+ helpers.get_test_fnames("*.h5")[:5], import_all=True, reset_all=False
109
+ )
110
+ for panel in (win.signalpanel, win.imagepanel):
111
+ panel.remove_all_objects()
112
+
113
+ # Get the GDI count after creating the widget
114
+ gdi_count_after: int = get_gdi_count()
115
+
116
+ execenv.print(gdi_count_after)
117
+
118
+ # # Check that the GDI count has not increased
119
+ # assert gdi_count_before == gdi_count_after
120
+ # assert gdi_count_before == gdi_count_after_close
121
+
122
+ return gdi_count_after
123
+
124
+
125
+ def load_test():
126
+ """Load test."""
127
+ with execenv.context(unattended=True):
128
+ with datalab_test_app_context() as win:
129
+ gdi_count = []
130
+ for iteration in range(4):
131
+ execenv.print(f"Test iteration: {iteration}")
132
+ count = test_gdi_count(win)
133
+ if count is None:
134
+ execenv.print("Test aborted")
135
+ break
136
+ gdi_count.append(count)
137
+ if iteration > 0:
138
+ increase = gdi_count[-1] - gdi_count[-2]
139
+ assert increase <= 0, "GDI count should not increase (memory leak)"
140
+ increase_pct = increase / gdi_count[0] * 100
141
+ execenv.print(
142
+ f" GDI count increase: {increase:+d} ({increase_pct:.2f}%)"
143
+ )
144
+
145
+
146
+ if __name__ == "__main__":
147
+ load_test()
@@ -0,0 +1,96 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ Long callback test
5
+ ------------------
6
+
7
+ This test is not meant to be executed as part of the `pytest` suite, hence the
8
+ name of the script.
9
+ """
10
+
11
+ # guitest: show,skip
12
+
13
+ import time
14
+
15
+ from guidata.qthelpers import qt_app_context
16
+ from qtpy import QtWidgets as QW
17
+
18
+ from datalab.utils.qthelpers import CallbackWorker, qt_long_callback
19
+
20
+
21
+ def long_computation_func(delay: float) -> str:
22
+ """Simulate long computation
23
+
24
+ Args:
25
+ delay: Delay in seconds
26
+
27
+ Returns:
28
+ str: Result message
29
+ """
30
+ time.sleep(delay)
31
+ return "OK"
32
+
33
+
34
+ def long_computation_progress_func(worker: CallbackWorker, delay: float) -> str:
35
+ """Simulate long computation, with progress
36
+
37
+ Args:
38
+ worker: Callback worker
39
+ delay: Delay in seconds
40
+
41
+ Returns:
42
+ str: Result message
43
+ """
44
+ step_delay = 2.0
45
+ maxiter = int(delay / step_delay)
46
+ for idx in range(maxiter):
47
+ worker.set_progress(idx / maxiter)
48
+ if worker.was_canceled():
49
+ return f"Interrupted at iteration #{idx}"
50
+ time.sleep(step_delay)
51
+ return "Done"
52
+
53
+
54
+ class TestWindow(QW.QMainWindow):
55
+ """Test window"""
56
+
57
+ def __init__(self):
58
+ super().__init__()
59
+ self.setWindowTitle("Test window")
60
+ btn1 = QW.QPushButton("Run long computation")
61
+ btn1.clicked.connect(self.run_long_computation)
62
+ btn2 = QW.QPushButton("Run long computation with progress bar")
63
+ btn2.clicked.connect(self.run_long_computation_with_progress)
64
+ mainwidget = QW.QWidget()
65
+ layout = QW.QHBoxLayout()
66
+ mainwidget.setLayout(layout)
67
+ layout.addWidget(btn1)
68
+ layout.addWidget(btn2)
69
+ self.setCentralWidget(mainwidget)
70
+
71
+ def __execute_worker(self, worker: CallbackWorker, progress: bool) -> None:
72
+ """Execute worker"""
73
+ ret = qt_long_callback(self, "Doing stuff...", worker, progress)
74
+ QW.QMessageBox.information(self, "Result", f"Long computation result: {ret}")
75
+
76
+ def run_long_computation(self) -> None:
77
+ """Run long computation"""
78
+ worker = CallbackWorker(long_computation_func, delay=5.0)
79
+ self.__execute_worker(worker, progress=False)
80
+
81
+ def run_long_computation_with_progress(self) -> None:
82
+ """Run long computation with progress"""
83
+ worker = CallbackWorker(long_computation_progress_func, delay=10.0)
84
+ self.__execute_worker(worker, progress=True)
85
+
86
+
87
+ def testing_long_callback() -> None:
88
+ """Test long callback function"""
89
+ with qt_app_context(exec_loop=True):
90
+ win = TestWindow()
91
+ win.resize(800, 600)
92
+ win.show()
93
+
94
+
95
+ if __name__ == "__main__":
96
+ testing_long_callback()
@@ -0,0 +1,137 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ Application test for main window
5
+ --------------------------------
6
+
7
+ Testing the features of the main window of the application that are not
8
+ covered by other tests.
9
+ """
10
+
11
+ # guitest: show
12
+
13
+ import os
14
+
15
+ import sigima.params
16
+ import sigima.proc.signal as sips
17
+ from sigima.tests.data import create_paracetamol_signal
18
+
19
+ from datalab.env import execenv
20
+ from datalab.objectmodel import get_short_id, get_uuid
21
+ from datalab.tests import datalab_test_app_context
22
+
23
+
24
+ def test_main_app():
25
+ """Main window test"""
26
+ with datalab_test_app_context(console=False) as win:
27
+ # Switch from panel to panel
28
+ for panelname in ("macro", "image", "signal"):
29
+ win.set_current_panel(panelname)
30
+ # Switch to an unknown panel
31
+ try:
32
+ win.set_current_panel("unknown_panel")
33
+ raise RuntimeError("Unknown panel should have raised an exception")
34
+ except ValueError:
35
+ pass
36
+
37
+ panel = win.signalpanel
38
+
39
+ # Create new groups
40
+ grp1 = panel.add_group("Group 1")
41
+ panel.add_group("Group 2")
42
+ # Add group using different levels of the API
43
+ panel.add_group("Group 3", select=True)
44
+ panel.remove_object(force=True)
45
+ win.add_group("Group 4", select=True)
46
+ panel.remove_object(force=True)
47
+ win.add_group("Group 5", panel="signal", select=True)
48
+ panel.remove_object(force=True)
49
+ # Rename group
50
+ panel.objview.select_groups([2])
51
+ panel.rename_selected_object_or_group("Group xxx")
52
+ panel.remove_object(force=True)
53
+
54
+ # Add signals to signal panel
55
+ sig1 = create_paracetamol_signal(500)
56
+ panel.add_object(sig1)
57
+ panel.rename_selected_object_or_group("Paracetamol Signal 1")
58
+ panel.processor.run_feature(sips.derivative)
59
+ panel.processor.run_feature(sips.wiener)
60
+
61
+ # Get object titles
62
+ titles = win.get_object_titles()
63
+ execenv.print(f"Object titles:{os.linesep}{titles}")
64
+
65
+ # Get object uuids
66
+ uuids = win.get_object_uuids()
67
+ uuids2 = win.get_object_uuids(group=1)
68
+ uuids3 = win.get_object_uuids(group="Group 1")
69
+ uuids4 = win.get_object_uuids(group=get_uuid(grp1))
70
+ assert uuids == uuids2 == uuids3 == uuids4, "Group UUIDs should be the same"
71
+ execenv.print(f"Object uuids:{os.linesep}{uuids}")
72
+
73
+ # Testing `get_object`
74
+ execenv.print("*** Testing `get_object` ***")
75
+ # Get object from title
76
+ obj = win.get_object(titles[-1])
77
+ execenv.print(f" Object (from title) '{get_short_id(obj)}':{os.linesep}{obj}")
78
+ # Get object
79
+ obj = win.get_object(1)
80
+ execenv.print(
81
+ f" Object (from number) '{get_short_id(obj)}':{os.linesep}{obj}"
82
+ )
83
+ # Get object by uuid
84
+ obj = win.get_object(uuids[-1])
85
+ execenv.print(f" Object (from uuid) '{get_short_id(obj)}':{os.linesep}{obj}")
86
+
87
+ # Testing dict-like interface of main window:
88
+ execenv.print("*** Testing dict-like interface of proxy ***")
89
+ # Get object from title
90
+ obj = win[titles[-1]]
91
+ execenv.print(f" Object (from title) '{get_short_id(obj)}':{os.linesep}{obj}")
92
+ # Get object
93
+ obj = win[1]
94
+ execenv.print(
95
+ f" Object (from number) '{get_short_id(obj)}':{os.linesep}{obj}"
96
+ )
97
+ # Get object by uuid
98
+ obj = win[uuids[-1]]
99
+ execenv.print(f" Object (from uuid) '{get_short_id(obj)}':{os.linesep}{obj}")
100
+
101
+ # Use "calc" method with parameters
102
+ param = sigima.params.MovingMedianParam.create(n=5)
103
+ win.calc("moving_median", param)
104
+ # Use "calc" method without parameters
105
+ win.calc("integral")
106
+ # Use "calc" and choose an unknown computation method
107
+ try:
108
+ win.calc("unknown_method")
109
+ raise RuntimeError("Unknown method should have raised an exception")
110
+ except ValueError:
111
+ pass
112
+
113
+ # Force application menus to pop-up
114
+ for menu in (
115
+ win.file_menu,
116
+ win.create_menu,
117
+ win.edit_menu,
118
+ win.roi_menu,
119
+ win.operation_menu,
120
+ win.processing_menu,
121
+ win.analysis_menu,
122
+ win.view_menu,
123
+ win.help_menu,
124
+ ):
125
+ # Just access the menu to ensure it's created and initialized
126
+ assert menu is not None, f"Menu {menu.title()} should exist"
127
+ # Trigger aboutToShow to populate dynamic menus without showing the popup
128
+ menu.aboutToShow.emit()
129
+ # Verify menu has actions (optional, but good sanity check)
130
+ assert len(menu.actions()) > 0, f"Menu {menu.title()} should have actions"
131
+
132
+ # Open settings dialog
133
+ win.settings_action.trigger()
134
+
135
+
136
+ if __name__ == "__main__":
137
+ test_main_app()
@@ -0,0 +1,43 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ Memory leak test
5
+
6
+ DataLab application memory leak test.
7
+ """
8
+
9
+ # guitest: skip
10
+
11
+ import os
12
+
13
+ import numpy as np
14
+ import psutil
15
+ from guidata.qthelpers import qt_app_context
16
+ from sigima.tests.vistools import view_curves
17
+
18
+ from datalab.env import execenv
19
+ from datalab.tests.features.control.embedded1_unit_test import HostWindow
20
+
21
+
22
+ def memory_leak_test(iterations=100):
23
+ """Test for memory leak"""
24
+ with qt_app_context():
25
+ proc = psutil.Process(os.getpid())
26
+ mainview = HostWindow()
27
+ mainview.show()
28
+ memlist = []
29
+ for i in range(iterations):
30
+ mainview.init_cdl()
31
+ mainview.close_datalab()
32
+ memdata = proc.memory_info().vms / 1024**2
33
+ memlist.append(memdata)
34
+ execenv.print(i + 1, ":", memdata, "MB")
35
+ view_curves(
36
+ np.array(memlist),
37
+ title="Memory leak test for DataLab application",
38
+ ylabel="Memory (MB)",
39
+ )
40
+
41
+
42
+ if __name__ == "__main__":
43
+ memory_leak_test()
@@ -0,0 +1,128 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ Process isolation unit test
5
+ ---------------------------
6
+ """
7
+
8
+ # pylint: disable=invalid-name # Allows short reference names like x, y, ...
9
+ # pylint: disable=duplicate-code
10
+ # guitest: skip
11
+
12
+ from __future__ import annotations
13
+
14
+ import time
15
+ from collections.abc import Callable
16
+ from multiprocessing.pool import AsyncResult, Pool
17
+ from typing import Any
18
+
19
+ import numpy as np
20
+ import scipy.signal as sps
21
+ from guidata.qthelpers import qt_app_context
22
+ from plotpy.plot import PlotWindow
23
+ from qtpy import QtWidgets as QW
24
+ from sigima.objects import ImageDatatypes, NewImageParam
25
+ from sigima.tests.data import create_2d_random, create_noisy_gaussian_image
26
+
27
+ from datalab.adapters_plotpy import create_adapter_from_object
28
+ from datalab.env import execenv
29
+ from datalab.utils.qthelpers import create_progress_bar
30
+
31
+ POOL: Pool | None = None
32
+
33
+
34
+ class Worker:
35
+ """Multiprocessing worker, to run long-running tasks in a separate process"""
36
+
37
+ def __init__(self) -> None:
38
+ self.asyncresult: AsyncResult = None
39
+ self.result: Any = None
40
+
41
+ @staticmethod
42
+ def create_pool() -> None:
43
+ """Create multiprocessing pool"""
44
+ global POOL # pylint: disable=global-statement
45
+ # Create a pool with one process
46
+ POOL = Pool(processes=1) # pylint: disable=not-callable,consider-using-with
47
+
48
+ @staticmethod
49
+ def terminate_pool() -> None:
50
+ """Terminate multiprocessing pool"""
51
+ global POOL # pylint: disable=global-statement
52
+ if POOL is not None:
53
+ POOL.terminate()
54
+ POOL.join()
55
+ POOL = None
56
+
57
+ def run(self, func: Callable, args: tuple[Any]) -> None:
58
+ """Run computation"""
59
+ global POOL # pylint: disable=global-statement,global-variable-not-assigned
60
+ assert POOL is not None
61
+ self.asyncresult = POOL.apply_async(func, args)
62
+
63
+ def terminate(self) -> None:
64
+ """Terminate worker"""
65
+ # Terminate the process and stop the timer
66
+ self.terminate_pool()
67
+ execenv.print("Computation cancelled!")
68
+ # Recreate the pool for the next computation
69
+ self.create_pool()
70
+
71
+ def is_computation_finished(self) -> bool:
72
+ """Return True if computation is finished"""
73
+ return self.asyncresult.ready()
74
+
75
+ def get_result(self) -> Any:
76
+ """Return computation result"""
77
+ self.result = self.asyncresult.get()
78
+ self.asyncresult = None
79
+ return self.result
80
+
81
+
82
+ def testfunc(data: np.ndarray, size: int, error: bool) -> np.ndarray:
83
+ """Test function"""
84
+ if error:
85
+ raise ValueError("Test error")
86
+ return sps.medfilt(data, size) + create_2d_random(data.shape[0], data.dtype)
87
+
88
+
89
+ def test_multiprocessing1(iterations: int = 4) -> None:
90
+ """Multiprocessing test"""
91
+ Worker.create_pool()
92
+ with qt_app_context(exec_loop=True):
93
+ win = PlotWindow(title="Multiprocessing test", icon="datalab.svg", toolbar=True)
94
+ win.resize(800, 600)
95
+ win.show()
96
+ param = NewImageParam.create(
97
+ height=1000, width=1000, dtype=ImageDatatypes.UINT16
98
+ )
99
+ image = create_noisy_gaussian_image(param, add_annotations=True)
100
+ win.get_plot().add_item(create_adapter_from_object(image).make_item())
101
+ worker = Worker()
102
+ with create_progress_bar(win, "Computing", max_=iterations) as progress:
103
+ for index in range(iterations):
104
+ progress.setValue(index)
105
+ progress.setLabelText(f"Computing {index}")
106
+ test_error = index == 2
107
+ worker.run(testfunc, (image.data, 3, test_error))
108
+ while not worker.is_computation_finished():
109
+ QW.QApplication.processEvents()
110
+ time.sleep(0.1)
111
+ if progress.wasCanceled():
112
+ worker.terminate()
113
+ break
114
+ if worker.is_computation_finished():
115
+ try:
116
+ image.data = worker.get_result()
117
+ except Exception as exc: # pylint: disable=broad-except
118
+ execenv.print(f"Intercepted exception: {exc}")
119
+ win.get_plot().add_item(
120
+ create_adapter_from_object(image).make_item()
121
+ )
122
+ else:
123
+ break
124
+ worker.terminate_pool()
125
+
126
+
127
+ if __name__ == "__main__":
128
+ test_multiprocessing1()