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,73 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ Profile extraction test
5
+ =======================
6
+
7
+ Testing the profile extraction features of the image panel:
8
+
9
+ - Compute a profile along a horizontal line
10
+ - Compute a profile along a vertical line
11
+ - Compute an average profile between two points along a horizontal line
12
+ - Compute an average profile between two points along a vertical line
13
+ - Compute a radial profile
14
+ """
15
+
16
+ # pylint: disable=invalid-name # Allows short reference names like x, y, ...
17
+ # guitest: show
18
+
19
+ import sigima.params
20
+ from sigima.tests.data import create_noisy_gaussian_image, get_test_image
21
+
22
+ from datalab.tests import datalab_test_app_context
23
+
24
+
25
+ def test_profile():
26
+ """Run profile extraction test scenario"""
27
+ with datalab_test_app_context() as win:
28
+ panel = win.imagepanel
29
+ panel.add_object(get_test_image("flower.npy"))
30
+ proc = panel.processor
31
+ for direction, row, col in (
32
+ ("horizontal", 102, 131),
33
+ ("vertical", 102, 131),
34
+ ):
35
+ profparam = sigima.params.LineProfileParam.create(
36
+ direction=direction, row=row, col=col
37
+ )
38
+ proc.compute_line_profile(profparam)
39
+ for direction, row1, col1, row2, col2 in (
40
+ ("horizontal", 10, 10, 102, 131),
41
+ ("vertical", 10, 10, 102, 131),
42
+ ):
43
+ avgprofparam = sigima.params.AverageProfileParam.create(
44
+ direction=direction,
45
+ row1=row1,
46
+ col1=col1,
47
+ row2=row2,
48
+ col2=col2,
49
+ )
50
+ proc.compute_average_profile(avgprofparam)
51
+ segprofparam = sigima.params.SegmentProfileParam.create(
52
+ row1=10, col1=10, row2=102, col2=131
53
+ )
54
+ proc.compute_segment_profile(segprofparam)
55
+ image2 = create_noisy_gaussian_image(center=(0.0, 0.0), add_annotations=False)
56
+ panel.add_object(image2)
57
+ for center, x0, y0 in (
58
+ (None, 0.0, 0.0),
59
+ ("centroid", 0.0, 0.0),
60
+ ("center", 0.0, 0.0),
61
+ ("user", 800.0, 900.0),
62
+ ):
63
+ if center is None:
64
+ proc.compute_radial_profile()
65
+ else:
66
+ param = sigima.params.RadialProfileParam.create(
67
+ center=center, x0=x0, y0=y0
68
+ )
69
+ proc.compute_radial_profile(param)
70
+
71
+
72
+ if __name__ == "__main__":
73
+ test_profile()
@@ -0,0 +1,56 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ Profile extraction unit test
5
+ """
6
+
7
+ # pylint: disable=invalid-name # Allows short reference names like x, y, ...
8
+ # guitest: show
9
+
10
+ import sigima.params
11
+ from guidata.qthelpers import exec_dialog, qt_app_context
12
+ from sigima.tests.data import create_noisy_gaussian_image
13
+
14
+ from datalab.env import execenv
15
+ from datalab.gui.profiledialog import ProfileExtractionDialog
16
+
17
+
18
+ def test_profile_unit():
19
+ """Run profile extraction test"""
20
+ with qt_app_context():
21
+ obj = create_noisy_gaussian_image(center=(0.0, 0.0), add_annotations=False)
22
+ for mode in ("line", "segment", "rectangle"):
23
+ for initial_param in (True, False):
24
+ if initial_param:
25
+ if mode == "line":
26
+ param = sigima.params.LineProfileParam.create(row=100, col=200)
27
+ elif mode == "segment":
28
+ param = sigima.params.SegmentProfileParam.create(
29
+ row1=10, col1=20, row2=200, col2=300
30
+ )
31
+ else:
32
+ param = sigima.params.AverageProfileParam.create(
33
+ row1=10, col1=20, row2=200, col2=300
34
+ )
35
+ else:
36
+ if mode == "line":
37
+ param = sigima.params.LineProfileParam()
38
+ elif mode == "segment":
39
+ param = sigima.params.SegmentProfileParam()
40
+ else:
41
+ param = sigima.params.AverageProfileParam()
42
+ execenv.print("-" * 80)
43
+ execenv.print(f"Testing mode: {mode} - initial_param: {initial_param}")
44
+ dialog = ProfileExtractionDialog(
45
+ mode, param, add_initial_shape=initial_param
46
+ )
47
+ dialog.set_obj(obj)
48
+ if initial_param:
49
+ dialog.edit_values()
50
+ ok = exec_dialog(dialog)
51
+ execenv.print(f"Returned code: {ok}")
52
+ execenv.print(f"Param: {param}")
53
+
54
+
55
+ if __name__ == "__main__":
56
+ test_profile_unit()
@@ -0,0 +1,98 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """Image ROI application test"""
4
+
5
+ # pylint: disable=invalid-name # Allows short reference names like x, y, ...
6
+ # guitest: show
7
+
8
+ from __future__ import annotations
9
+
10
+ from typing import TYPE_CHECKING
11
+
12
+ import pytest
13
+ import sigima.params as sigima_param
14
+ from sigima.objects import ImageObj, ImageROI, NewImageParam, create_image_roi
15
+ from sigima.tests.data import create_multigaussian_image
16
+
17
+ from datalab.config import Conf
18
+ from datalab.env import execenv
19
+ from datalab.tests import datalab_test_app_context, helpers
20
+
21
+ if TYPE_CHECKING:
22
+ from datalab.gui.panel.image import ImagePanel
23
+
24
+ SIZE = 200
25
+
26
+ # Image ROIs:
27
+ IROI1 = [100, 100, 75, 100] # Rectangle
28
+ IROI2 = [66, 100, 50] # Circle
29
+ # Polygon (triangle, that is intentionally inside the rectangle, so that this ROI
30
+ # has no impact on the mask calculations in the tests)
31
+ IROI3 = [100, 100, 100, 150, 150, 133]
32
+
33
+
34
+ def __run_image_computations(panel: ImagePanel):
35
+ """Test all image features related to ROI"""
36
+ panel.processor.run_feature("centroid")
37
+ panel.processor.run_feature("histogram", sigima_param.HistogramParam())
38
+ panel.processor.run_feature(
39
+ "peak_detection", sigima_param.Peak2DDetectionParam.create(create_rois=False)
40
+ )
41
+ roi = ImageROI()
42
+ panel.processor.compute_roi_extraction(roi)
43
+
44
+
45
+ def create_test_image_with_roi(newimageparam: NewImageParam) -> ImageObj:
46
+ """Create test image with ROIs
47
+
48
+ Args:
49
+ newimageparam (sigima.NewImageParam): Image parameters
50
+
51
+ Returns:
52
+ sigima.ImageObj: Image object with ROIs
53
+ """
54
+ ima = create_multigaussian_image(newimageparam)
55
+ ima.data += 1 # Ensure that the image has non-zero values (for ROI check tests)
56
+ roi = create_image_roi("rectangle", IROI1)
57
+ roi.add_roi(create_image_roi("circle", IROI2))
58
+ roi.add_roi(create_image_roi("polygon", IROI3))
59
+ ima.roi = roi
60
+ return ima
61
+
62
+
63
+ def test_image_roi_app(screenshots: bool = False):
64
+ """Run Image ROI application test scenario"""
65
+ with datalab_test_app_context(console=False) as win:
66
+ execenv.print("Image ROI application test:")
67
+ panel = win.imagepanel
68
+ param = NewImageParam.create(height=SIZE, width=SIZE)
69
+ ima1 = create_multigaussian_image(param)
70
+ panel.add_object(ima1)
71
+ __run_image_computations(panel)
72
+ ima2 = create_test_image_with_roi(param)
73
+ for singleobj in (False, True):
74
+ with Conf.proc.extract_roi_singleobj.temp(singleobj):
75
+ ima2_i = ima2.copy()
76
+ panel.add_object(ima2_i)
77
+ helpers.print_obj_data_dimensions(ima2_i)
78
+ panel.processor.edit_roi_graphically()
79
+ if screenshots:
80
+ win.statusBar().hide()
81
+ win.take_screenshot("i_roi_image")
82
+ __run_image_computations(panel)
83
+
84
+
85
+ @pytest.mark.skip(reason="This test is only for manual testing")
86
+ def test_image_roi_basic_app():
87
+ """Run Image ROI basic application test scenario"""
88
+ with datalab_test_app_context(console=False) as win:
89
+ panel = win.imagepanel
90
+ param = NewImageParam.create(height=SIZE, width=SIZE)
91
+ ima1 = create_multigaussian_image(param)
92
+ panel.add_object(ima1)
93
+ panel.processor.edit_roi_graphically()
94
+
95
+
96
+ if __name__ == "__main__":
97
+ test_image_roi_app(screenshots=True)
98
+ test_image_roi_basic_app()
@@ -0,0 +1,62 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ Circular ROI test
5
+ """
6
+
7
+ # pylint: disable=invalid-name # Allows short reference names like x, y, ...
8
+ # guitest: show
9
+
10
+ from __future__ import annotations
11
+
12
+ from typing import Literal
13
+
14
+ import numpy as np
15
+ import sigima.objects
16
+ from skimage import draw
17
+
18
+ from datalab.env import execenv
19
+ from datalab.tests import datalab_test_app_context, helpers
20
+
21
+
22
+ def create_test_image_with_roi(
23
+ geometry: Literal["rectangle", "circle", "polygon"],
24
+ ) -> sigima.objects.ImageObj:
25
+ """Create test image with ROIs"""
26
+ data = np.zeros((500, 750), dtype=np.uint16)
27
+ xc, yc, r = 500, 200, 100
28
+ rr, cc = draw.disk((yc, xc), r)
29
+ data[rr, cc] = 10000
30
+ data[yc + r - 20 : yc + r, xc + r - 30 : xc + r - 10] = 50000
31
+ if geometry == "rectangle":
32
+ coords = [xc - r, yc - r, 2 * r, 2 * r]
33
+ elif geometry == "circle":
34
+ coords = [xc, yc, r]
35
+ else:
36
+ raise NotImplementedError(f"Geometry {geometry} not implemented")
37
+ ima = sigima.objects.create_image(f"Test image with ROI/{geometry}", data)
38
+ ima.roi = sigima.objects.create_image_roi(geometry, coords, indices=True)
39
+ return ima
40
+
41
+
42
+ def test_roi_circ() -> None:
43
+ """Run circular ROI application test scenario"""
44
+ with datalab_test_app_context() as win:
45
+ execenv.print("Circular ROI test:")
46
+ panel = win.imagepanel
47
+ for geometry in ("rectangle", "circle"): # model.ROI2DParam.geometries:
48
+ ima = create_test_image_with_roi(geometry)
49
+ panel.add_object(ima)
50
+ helpers.print_obj_data_dimensions(ima)
51
+ panel.processor.run_feature("stats")
52
+ panel.processor.run_feature("centroid")
53
+ # Extracting ROIs:
54
+ for obj_nb in (1, 2):
55
+ obj = panel[obj_nb]
56
+ panel.objview.set_current_object(obj)
57
+ params = obj.roi.to_params(obj)
58
+ panel.processor.run_feature("extract_roi", params=params)
59
+
60
+
61
+ if __name__ == "__main__":
62
+ test_roi_circ()
@@ -0,0 +1,268 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """Image ROI manipulation application test (copy/paste, import/export)"""
4
+
5
+ # pylint: disable=invalid-name # Allows short reference names like x, y, ...
6
+ # guitest: show
7
+
8
+ from __future__ import annotations
9
+
10
+ import os
11
+ import tempfile
12
+ from typing import TYPE_CHECKING
13
+
14
+ from sigima.io import read_roi
15
+ from sigima.objects import NewImageParam, create_image_roi
16
+ from sigima.tests.data import create_multigaussian_image
17
+
18
+ from datalab.env import execenv
19
+ from datalab.objectmodel import get_uuid
20
+ from datalab.tests import datalab_test_app_context
21
+
22
+ if TYPE_CHECKING:
23
+ from datalab.gui.panel.image import ImagePanel
24
+
25
+ SIZE = 200
26
+
27
+ # Image ROIs:
28
+ IROI1 = [100, 100, 75, 100] # Rectangle
29
+ IROI2 = [66, 100, 50] # Circle
30
+ IROI3 = [100, 100, 100, 150, 150, 133] # Polygon
31
+
32
+
33
+ def test_image_roi_copy_paste():
34
+ """Test image ROI copy and paste functionality"""
35
+ with datalab_test_app_context(console=False) as win:
36
+ execenv.print("Image ROI Copy/Paste test:")
37
+ panel: ImagePanel = win.imagepanel
38
+ param = NewImageParam.create(height=SIZE, width=SIZE)
39
+
40
+ # Create first image with ROI
41
+ ima1 = create_multigaussian_image(param)
42
+ ima1.title = "Image with ROI"
43
+ roi1 = create_image_roi("rectangle", IROI1)
44
+ roi1.add_roi(create_image_roi("circle", IROI2))
45
+ ima1.roi = roi1
46
+ panel.add_object(ima1)
47
+
48
+ # Create second image without ROI
49
+ ima2 = create_multigaussian_image(param)
50
+ ima2.title = "Image without ROI"
51
+ panel.add_object(ima2)
52
+
53
+ # Create third image without ROI
54
+ ima3 = create_multigaussian_image(param)
55
+ ima3.title = "Image without ROI 2"
56
+ panel.add_object(ima3)
57
+
58
+ execenv.print(" Initial state:")
59
+ execenv.print(f" Image 1 ROI: {ima1.roi is not None}")
60
+ execenv.print(f" Image 2 ROI: {ima2.roi is not None}")
61
+ execenv.print(f" Image 3 ROI: {ima3.roi is not None}")
62
+
63
+ # Select first image and copy its ROI
64
+ panel.objview.set_current_item_id(get_uuid(ima1))
65
+ panel.copy_roi()
66
+ execenv.print(" Copied ROI from Image 1")
67
+
68
+ # Select second image and paste ROI
69
+ panel.objview.set_current_item_id(get_uuid(ima2))
70
+ panel.paste_roi()
71
+ execenv.print(" Pasted ROI to Image 2")
72
+
73
+ # Verify that ima2 now has the same ROI as ima1
74
+ assert ima2.roi is not None, "Image 2 should have ROI after paste"
75
+ assert len(ima2.roi) == len(ima1.roi), "ROI should have same number of regions"
76
+ execenv.print(f" Image 2 now has {len(ima2.roi)} ROI regions")
77
+
78
+ # Select third image and paste ROI (should create new ROI)
79
+ panel.objview.set_current_item_id(get_uuid(ima3))
80
+ panel.paste_roi()
81
+ execenv.print(" Pasted ROI to Image 3")
82
+
83
+ assert ima3.roi is not None, "Image 3 should have ROI after paste"
84
+ assert len(ima3.roi) == len(ima1.roi), "ROI should have same number of regions"
85
+ execenv.print(f" Image 3 now has {len(ima3.roi)} ROI regions")
86
+
87
+ # Test pasting to image that already has ROI (should combine)
88
+ panel.objview.set_current_item_id(get_uuid(ima2))
89
+ panel.copy_roi()
90
+ execenv.print(" Copied ROI from Image 2")
91
+
92
+ # Add a different ROI to ima1
93
+ roi_new = create_image_roi("polygon", IROI3)
94
+ ima1.roi.add_roi(roi_new)
95
+ original_roi_count = len(ima1.roi)
96
+ execenv.print(f" Image 1 now has {original_roi_count} ROI regions")
97
+
98
+ # Paste the ROI from ima2 into ima1 (should combine)
99
+ panel.objview.set_current_item_id(get_uuid(ima1))
100
+ panel.paste_roi()
101
+ execenv.print(" Pasted ROI to Image 1 (should combine)")
102
+
103
+ # Get fresh reference to ima1 from panel
104
+ ima1_updated = panel.objmodel[get_uuid(ima1)]
105
+ assert ima1_updated.roi is not None, "Image 1 should still have ROI"
106
+ # After combining, ima1 should have more regions than before
107
+ assert len(ima1_updated.roi) >= original_roi_count, (
108
+ f"Expected at least {original_roi_count} ROI regions, "
109
+ f"got {len(ima1_updated.roi)}"
110
+ )
111
+ execenv.print(
112
+ f" Image 1 now has {len(ima1_updated.roi)} ROI regions (combined)"
113
+ )
114
+
115
+ execenv.print(" ✓ Image ROI copy/paste test passed")
116
+
117
+
118
+ def test_image_roi_copy_paste_multiple_selection():
119
+ """Test image ROI paste to multiple selected images"""
120
+ with datalab_test_app_context(console=False) as win:
121
+ execenv.print("Image ROI Copy/Paste with multiple selection test:")
122
+ panel: ImagePanel = win.imagepanel
123
+ param = NewImageParam.create(height=SIZE, width=SIZE)
124
+
125
+ # Create source image with ROI
126
+ ima_src = create_multigaussian_image(param)
127
+ ima_src.title = "Source with ROI"
128
+ roi = create_image_roi("rectangle", IROI1)
129
+ roi.add_roi(create_image_roi("circle", IROI2))
130
+ ima_src.roi = roi
131
+ panel.add_object(ima_src)
132
+
133
+ # Create multiple target images without ROI
134
+ target_images = []
135
+ for i in range(3):
136
+ ima = create_multigaussian_image(param)
137
+ ima.title = f"Target image {i + 1}"
138
+ panel.add_object(ima)
139
+ target_images.append(ima)
140
+
141
+ execenv.print(f" Created {len(target_images)} target images")
142
+
143
+ # Copy ROI from source
144
+ panel.objview.set_current_item_id(get_uuid(ima_src))
145
+ panel.copy_roi()
146
+ execenv.print(" Copied ROI from source image")
147
+
148
+ # Select all target images
149
+ target_uuids = [get_uuid(img) for img in target_images]
150
+ panel.objview.set_current_item_id(target_uuids[0])
151
+ for uuid in target_uuids[1:]:
152
+ panel.objview.set_current_item_id(uuid, extend=True)
153
+
154
+ execenv.print(f" Selected {len(target_uuids)} target images")
155
+
156
+ # Paste ROI to all selected images
157
+ panel.paste_roi()
158
+ execenv.print(" Pasted ROI to all selected images")
159
+
160
+ # Verify all target images have ROI
161
+ for i, img in enumerate(target_images):
162
+ assert img.roi is not None, f"Target image {i + 1} should have ROI"
163
+ assert len(img.roi) == len(ima_src.roi), (
164
+ f"Target image {i + 1} should have {len(ima_src.roi)} ROI regions"
165
+ )
166
+ execenv.print(f" Target image {i + 1}: {len(img.roi)} ROI regions ✓")
167
+
168
+ execenv.print(" ✓ Multiple selection paste test passed")
169
+
170
+
171
+ def test_image_roi_import_export():
172
+ """Test image ROI import and export to/from file functionality"""
173
+ with datalab_test_app_context(console=False) as win:
174
+ execenv.print("Image ROI Import/Export test:")
175
+ panel: ImagePanel = win.imagepanel
176
+ param = NewImageParam.create(height=SIZE, width=SIZE)
177
+
178
+ # Create first image with ROI
179
+ ima1 = create_multigaussian_image(param)
180
+ ima1.title = "Image with ROI"
181
+ roi1 = create_image_roi("rectangle", IROI1)
182
+ roi1.add_roi(create_image_roi("circle", IROI2))
183
+ roi1.add_roi(create_image_roi("polygon", IROI3))
184
+ ima1.roi = roi1
185
+ panel.add_object(ima1)
186
+
187
+ original_roi_count = len(ima1.roi)
188
+ execenv.print(f" Image 1 has {original_roi_count} ROI regions")
189
+
190
+ # Export ROI to file
191
+ roi_file = tempfile.mktemp(suffix=".dlabroi")
192
+ try:
193
+ execenv.print(" Exporting ROI to temporary file")
194
+
195
+ # Select first image and export its ROI
196
+ panel.objview.set_current_item_id(get_uuid(ima1))
197
+ panel.export_roi_to_file(roi_file)
198
+ execenv.print(" ✓ ROI exported")
199
+
200
+ # Verify file was created
201
+ assert os.path.exists(roi_file), "ROI file should have been created"
202
+
203
+ # Read the exported ROI directly to verify content
204
+ exported_roi = read_roi(roi_file)
205
+ assert len(exported_roi) == original_roi_count, (
206
+ f"Exported ROI should have {original_roi_count} regions"
207
+ )
208
+ execenv.print(f" ✓ Exported ROI has {len(exported_roi)} regions")
209
+
210
+ # Create second image without ROI
211
+ ima2 = create_multigaussian_image(param)
212
+ ima2.title = "Image without ROI"
213
+ panel.add_object(ima2)
214
+ assert ima2.roi is None, "Image 2 should not have ROI initially"
215
+
216
+ # Import ROI from file to second image
217
+ panel.objview.set_current_item_id(get_uuid(ima2))
218
+ panel.import_roi_from_file(roi_file)
219
+ execenv.print(" Imported ROI to Image 2")
220
+
221
+ # Get fresh reference to ima2 from panel
222
+ ima2_updated = panel.objmodel[get_uuid(ima2)]
223
+ assert ima2_updated.roi is not None, "Image 2 should have ROI after import"
224
+ assert len(ima2_updated.roi) == original_roi_count, (
225
+ f"Imported ROI should have {original_roi_count} regions"
226
+ )
227
+ execenv.print(f" ✓ Image 2 now has {len(ima2_updated.roi)} ROI regions")
228
+
229
+ # Test importing ROI to image that already has ROI (should combine)
230
+ ima3 = create_multigaussian_image(param)
231
+ ima3.title = "Image with existing ROI"
232
+ roi3 = create_image_roi("circle", [150, 150, 40])
233
+ ima3.roi = roi3
234
+ panel.add_object(ima3)
235
+ initial_roi_count = len(ima3.roi)
236
+ execenv.print(f" Image 3 has {initial_roi_count} ROI region initially")
237
+
238
+ # Import ROI (should combine with existing)
239
+ panel.objview.set_current_item_id(get_uuid(ima3))
240
+ panel.import_roi_from_file(roi_file)
241
+ execenv.print(" Imported ROI to Image 3 (should combine)")
242
+
243
+ # Get fresh reference to ima3 from panel
244
+ ima3_updated = panel.objmodel[get_uuid(ima3)]
245
+ assert ima3_updated.roi is not None, "Image 3 should still have ROI"
246
+ # After combining, should have more regions
247
+ assert len(ima3_updated.roi) >= initial_roi_count, (
248
+ f"Expected at least {initial_roi_count} ROI regions, "
249
+ f"got {len(ima3_updated.roi)}"
250
+ )
251
+ execenv.print(
252
+ f" ✓ Image 3 now has {len(ima3_updated.roi)} ROI regions (combined)"
253
+ )
254
+ finally:
255
+ # Clean up temporary file
256
+ if os.path.exists(roi_file):
257
+ try:
258
+ os.unlink(roi_file)
259
+ except (PermissionError, OSError):
260
+ pass # Ignore cleanup errors on Windows
261
+
262
+ execenv.print(" ✓ Image ROI import/export test passed")
263
+
264
+
265
+ if __name__ == "__main__":
266
+ test_image_roi_copy_paste()
267
+ test_image_roi_copy_paste_multiple_selection()
268
+ test_image_roi_import_export()
@@ -0,0 +1,60 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """ROI grid unit test."""
4
+
5
+ # pylint: disable=invalid-name # Allows short reference names like x, y, ...
6
+ # guitest: show
7
+
8
+ from __future__ import annotations
9
+
10
+ from guidata.qthelpers import exec_dialog, qt_app_context
11
+ from sigima.proc.image import Direction, ROIGridParam
12
+ from sigima.tests.data import create_grid_of_gaussian_images
13
+
14
+ from datalab.gui.roigrideditor import ImageGridROIEditor
15
+ from datalab.utils import qthelpers as qth
16
+
17
+
18
+ def test_roi_grid(screenshots: bool = False) -> None:
19
+ """ROI grid test."""
20
+ with qt_app_context():
21
+ roi_editor = ImageGridROIEditor(
22
+ parent=None, obj=create_grid_of_gaussian_images()
23
+ )
24
+ if screenshots:
25
+ roi_editor.show()
26
+ qth.grab_save_window(roi_editor)
27
+ exec_dialog(roi_editor)
28
+
29
+
30
+ def test_roi_grid_geometry_headless() -> None:
31
+ """Test ROI grid geometry in headless mode."""
32
+ img = create_grid_of_gaussian_images()
33
+
34
+ # Create grid parameters
35
+ gp = ROIGridParam()
36
+ gp.nx, gp.ny = 2, 2
37
+ gp.xsize = gp.ysize = 50
38
+ gp.xtranslation = gp.ytranslation = 50
39
+ gp.xdirection = gp.ydirection = Direction.INCREASING
40
+
41
+ with qt_app_context():
42
+ dlg = ImageGridROIEditor(parent=None, obj=img, gridparam=gp)
43
+ # Set a small grid and sizes
44
+ dlg.update_obj(update_item=False)
45
+ roi = dlg.get_roi()
46
+ assert roi is not None
47
+ # 4 ROIs, centered in each cell
48
+ assert len(list(roi)) == 4
49
+ titles = [r.title for r in roi]
50
+ assert "ROI(1,1)" in titles and "ROI(2,2)" in titles
51
+ # Check one ROI position approximately
52
+ r00 = next(r for r in roi if r.title == "ROI(1,1)")
53
+ _x0, _y0, dx, dy = r00.get_physical_coords(img)
54
+ assert dx == img.width / 2 * 0.5
55
+ assert dy == img.height / 2 * 0.5
56
+
57
+
58
+ if __name__ == "__main__":
59
+ test_roi_grid_geometry_headless()
60
+ test_roi_grid(screenshots=True)
@@ -0,0 +1,52 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ View images side-by-side test
5
+ """
6
+
7
+ # pylint: disable=invalid-name # Allows short reference names like x, y, ...
8
+ # guitest: show
9
+
10
+ from __future__ import annotations
11
+
12
+ import numpy as np
13
+ import sigima.objects
14
+
15
+ from datalab.tests import datalab_test_app_context
16
+
17
+
18
+ def test_view_images_side_by_side() -> None:
19
+ """Test viewing multiple images side-by-side."""
20
+ with datalab_test_app_context() as win:
21
+ panel = win.imagepanel
22
+
23
+ # Create several test images with different content
24
+ for i in range(5):
25
+ x = np.linspace(-5, 5, 100)
26
+ y = np.linspace(-5, 5, 100)
27
+ xx, yy = np.meshgrid(x, y)
28
+
29
+ # Different patterns for each image
30
+ if i == 0:
31
+ data = np.exp(-(xx**2 + yy**2) / (2 * (i + 1)))
32
+ elif i == 1:
33
+ data = np.sin(xx) * np.cos(yy)
34
+ elif i == 2:
35
+ data = np.abs(xx) + np.abs(yy)
36
+ elif i == 3:
37
+ data = xx**2 - yy**2
38
+ else:
39
+ data = np.random.randn(100, 100)
40
+
41
+ image = sigima.objects.create_image(f"Test Image {i + 1}", data)
42
+ panel.add_object(image)
43
+
44
+ # Select all images (1 to 5)
45
+ panel.objview.select_objects(list(range(1, 6)))
46
+
47
+ # Open side-by-side view
48
+ panel.view_images_side_by_side()
49
+
50
+
51
+ if __name__ == "__main__":
52
+ test_view_images_side_by_side()
@@ -0,0 +1 @@
1
+ #