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,75 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ Groups/signals/images reorder test:
5
+
6
+ - Testing groups/signals reorder (images are not tested but the code is the same)
7
+ - When executed in unattended mode, the test only covers the "move up" and
8
+ "move down" actions
9
+ - When executed in interactive mode, the user has to test the "drag and
10
+ drop" actions manually
11
+ - In unattended mode only, we take the opportunity to test other methods of
12
+ the `ObjectModel` class (e.g. `get_group`, `remove_group`, ...) for maximizing
13
+ the code coverage
14
+ """
15
+
16
+ # guitest: show
17
+
18
+ from datalab import app
19
+ from datalab.env import execenv
20
+ from datalab.objectmodel import get_uuid
21
+ from datalab.tests import helpers
22
+ from datalab.utils.qthelpers import datalab_app_context
23
+
24
+
25
+ def test_reorder():
26
+ """Run signals/images reorder test scenario"""
27
+ with datalab_app_context(exec_loop=True):
28
+ win = app.create(h5files=[helpers.get_test_fnames("reorder*")[0]])
29
+ panel = win.signalpanel
30
+ view, model = panel.objview, panel.objmodel
31
+
32
+ # Select multiple signals
33
+ objs = [model.get_object_from_number(idx) for idx in (2, 4, 5, 9)]
34
+ view.select_objects(objs)
35
+ # Move up
36
+ view.move_up()
37
+ # Check that the order is correct (note: objects 4 and 5 are not affected
38
+ # by the move up action because they are moved up from the top of their group
39
+ # to the bottom of the previous group)
40
+ assert [model.get_number(obj) for obj in objs] == [1, 4, 5, 8]
41
+ # Move down
42
+ view.move_down()
43
+ # Check that the order is correct (note: objects 4 and 5 are not affected
44
+ # by the move down action because they are moved down from the bottom of their
45
+ # group to the top of the next group)
46
+ assert [model.get_number(obj) for obj in objs] == [2, 4, 5, 9]
47
+
48
+ # Select multiple groups
49
+ groups = [model.get_group_from_number(idx) for idx in (2, 3)]
50
+ view.select_groups(groups)
51
+ # Move up
52
+ view.move_up()
53
+ assert [model.get_number(group) for group in groups] == [1, 2]
54
+ # Move down
55
+ view.move_down()
56
+ assert [model.get_number(group) for group in groups] == [2, 3]
57
+
58
+ # Testing other methods of the `ObjectModel` class in unattended mode only
59
+ if execenv.unattended:
60
+ # Get group
61
+ group = model.get_group_from_number(2)
62
+ assert model.get_number(group) == 2
63
+ # Get the same group from its uuid
64
+ group = model.get_group(get_uuid(group))
65
+ assert model.get_number(group) == 2
66
+ group = model.get_object_or_group(get_uuid(group))
67
+ assert model.get_number(group) == 2
68
+ # Remove group
69
+ n_groups = len(model.get_groups())
70
+ model.remove_group(group)
71
+ assert len(model.get_groups()) == n_groups - 1
72
+
73
+
74
+ if __name__ == "__main__":
75
+ test_reorder()
@@ -0,0 +1,96 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ Result deletion unit test
5
+ --------------------------
6
+
7
+ Test the deletion of analysis results from objects.
8
+ """
9
+
10
+ # pylint: disable=invalid-name # Allows short reference names like x, y, ...
11
+ # guitest: show
12
+
13
+ from __future__ import annotations
14
+
15
+ from sigima.objects import Gauss2DParam, create_image_from_param
16
+ from sigima.tests.data import create_paracetamol_signal
17
+
18
+ from datalab.adapters_metadata import GeometryAdapter, TableAdapter
19
+ from datalab.config import Conf
20
+ from datalab.env import execenv
21
+ from datalab.objectmodel import get_uuid
22
+ from datalab.tests import datalab_test_app_context
23
+
24
+
25
+ def test_delete_results_image():
26
+ """Test deletion of analysis results from images"""
27
+ with datalab_test_app_context(console=False) as win:
28
+ execenv.print("Image result deletion test:")
29
+ panel = win.imagepanel
30
+
31
+ # Create a test image
32
+ param = Gauss2DParam.create(height=200, width=200, sigma=20)
33
+ img = create_image_from_param(param)
34
+ panel.add_object(img)
35
+
36
+ # Run centroid analysis to create results
37
+ execenv.print(" Running centroid analysis...")
38
+ with Conf.proc.show_result_dialog.temp(False):
39
+ panel.processor.run_feature("centroid")
40
+
41
+ # Verify that results exist
42
+ img_refreshed = panel.objmodel[get_uuid(img)]
43
+ adapter_before = GeometryAdapter.from_obj(img_refreshed, "centroid")
44
+ assert adapter_before is not None, (
45
+ "Centroid result should exist before deletion"
46
+ )
47
+ execenv.print(" ✓ Centroid result created")
48
+
49
+ # Delete all results
50
+ execenv.print(" Deleting all results...")
51
+ panel.objview.select_objects([get_uuid(img)])
52
+ panel.delete_results()
53
+
54
+ # Verify that results were deleted
55
+ img_after = panel.objmodel[get_uuid(img)]
56
+ adapter_after = GeometryAdapter.from_obj(img_after, "centroid")
57
+ assert adapter_after is None, "Centroid result should be deleted"
58
+ execenv.print(" ✓ Centroid result deleted")
59
+
60
+
61
+ def test_delete_results_signal():
62
+ """Test deletion of analysis results from signals"""
63
+ with datalab_test_app_context(console=False) as win:
64
+ execenv.print("Signal result deletion test:")
65
+ panel = win.signalpanel
66
+
67
+ # Create a test signal
68
+ sig = create_paracetamol_signal()
69
+ panel.add_object(sig)
70
+
71
+ # Run stats analysis to create table results
72
+ execenv.print(" Running stats analysis...")
73
+ with Conf.proc.show_result_dialog.temp(False):
74
+ panel.processor.run_feature("stats")
75
+
76
+ # Verify that results exist
77
+ sig_refreshed = panel.objmodel[get_uuid(sig)]
78
+ tables_before = list(TableAdapter.iterate_from_obj(sig_refreshed))
79
+ assert len(tables_before) > 0, "Stats result should exist before deletion"
80
+ execenv.print(" ✓ Stats result created")
81
+
82
+ # Delete all results
83
+ execenv.print(" Deleting all results...")
84
+ panel.objview.select_objects([get_uuid(sig)])
85
+ panel.delete_results()
86
+
87
+ # Verify that results were deleted
88
+ sig_after = panel.objmodel[get_uuid(sig)]
89
+ tables_after = list(TableAdapter.iterate_from_obj(sig_after))
90
+ assert len(tables_after) == 0, "Stats result should be deleted"
91
+ execenv.print(" ✓ Stats result deleted")
92
+
93
+
94
+ if __name__ == "__main__":
95
+ test_delete_results_image()
96
+ test_delete_results_signal()
@@ -0,0 +1,154 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ Merged result label test:
5
+
6
+ Test that multiple results are merged into a single label that displays all results.
7
+
8
+ This test verifies that:
9
+ 1. Computing FWHM adds a result to the merged label
10
+ 2. Computing FW1e2 adds another result to the same merged label
11
+ 3. The merged label contains both results
12
+ 4. The merged label is read-only (cannot be deleted to remove individual results)
13
+ 5. De-selecting and re-selecting the signal maintains the merged label
14
+ """
15
+
16
+ # pylint: disable=invalid-name # Allows short reference names like x, y, ...
17
+ # guitest: show
18
+
19
+ import sigima.params
20
+ import sigima.proc.signal as sips
21
+ from sigima.tests.data import create_paracetamol_signal
22
+
23
+ from datalab.adapters_metadata.geometry_adapter import GeometryAdapter
24
+ from datalab.env import execenv
25
+ from datalab.tests import datalab_test_app_context
26
+
27
+
28
+ def test_merged_result_label() -> None:
29
+ """Test that multiple results are merged into a single label"""
30
+ with datalab_test_app_context() as win:
31
+ panel = win.signalpanel
32
+
33
+ # Create a Gaussian curve
34
+ execenv.print("Creating paracetamol signal...")
35
+ sig = create_paracetamol_signal()
36
+ panel.add_object(sig)
37
+ execenv.print(f" Added signal: {sig.title}")
38
+
39
+ # Compute the FWHM (this adds a result to metadata)
40
+ execenv.print("Computing FWHM...")
41
+ panel.processor.run_feature(sips.fwhm, sigima.params.FWHMParam())
42
+
43
+ # Force refresh to ensure shapes are added
44
+ panel.plothandler.refresh_plot("selected", force=True)
45
+
46
+ # Check that the result metadata exists
47
+ sig = panel.objview.get_sel_objects()[0]
48
+ geometry_results_1 = list(GeometryAdapter.iterate_from_obj(sig))
49
+ execenv.print(f" Geometry results after FWHM: {len(geometry_results_1)}")
50
+ assert len(geometry_results_1) == 1, "Should have one geometry result"
51
+
52
+ # Get the plot and find the merged result label item
53
+ plot = panel.plothandler.plot
54
+ label_items = [item for item in plot.items if hasattr(item, "labelparam")]
55
+
56
+ # Find the merged result label - it should be on the plot
57
+ merged_label = None
58
+ for item in label_items:
59
+ if hasattr(item, "is_readonly") and item.is_readonly():
60
+ merged_label = item
61
+ break
62
+
63
+ assert merged_label is not None, "Should find the merged result label"
64
+ execenv.print(f" Found merged result label: {merged_label.title()}")
65
+
66
+ # Check that the label is read-only
67
+ assert merged_label.is_readonly(), "Merged label should be read-only"
68
+ execenv.print(" ✓ Merged label is read-only")
69
+
70
+ # Get the label text to verify it contains FWHM result
71
+ label_text_1 = merged_label.text_string
72
+ assert "fwhm" in label_text_1.lower(), "Label should contain FWHM result"
73
+ execenv.print(" ✓ Label contains FWHM result")
74
+
75
+ # Compute FW1e2 (this adds another result to metadata)
76
+ execenv.print("Computing FW1e2...")
77
+ panel.processor.run_feature(sips.fw1e2)
78
+
79
+ # Check that we now have two results
80
+ sig = panel.objview.get_sel_objects()[0]
81
+ geometry_results_2 = list(GeometryAdapter.iterate_from_obj(sig))
82
+ execenv.print(f" Geometry results after FW1e2: {len(geometry_results_2)}")
83
+ assert len(geometry_results_2) == 2, "Should have two geometry results"
84
+
85
+ # Verify the merged label now contains both results
86
+ merged_labels = [
87
+ item
88
+ for item in plot.items
89
+ if hasattr(item, "labelparam")
90
+ and hasattr(item, "is_readonly")
91
+ and item.is_readonly()
92
+ ]
93
+
94
+ execenv.print(f" Merged result labels on plot: {len(merged_labels)}")
95
+ assert len(merged_labels) == 1, "Should have exactly one merged result label"
96
+
97
+ merged_label_2 = merged_labels[0]
98
+ label_text_2 = merged_label_2.text_string
99
+ assert "fwhm" in label_text_2.lower(), "Label should contain FWHM result"
100
+ assert "fw1e2" in label_text_2.lower(), "Label should contain FW1e2 result"
101
+ assert "<hr>" in label_text_2, "Should contain separator between results"
102
+ execenv.print(" ✓ Merged label contains both FWHM and FW1e2 results")
103
+
104
+ # Create another signal and select it (to deselect the first one)
105
+ execenv.print("Creating second signal to deselect first...")
106
+ sig2 = create_paracetamol_signal()
107
+ sig2.title = "Paracetamol 2"
108
+ panel.add_object(sig2)
109
+
110
+ # Re-select the first signal
111
+ execenv.print("Re-selecting first signal...")
112
+ panel.objview.select_objects([1])
113
+
114
+ # Check that the merged label still exists and contains both results
115
+ sig = panel.objview.get_sel_objects()[0]
116
+ geometry_results_after = list(GeometryAdapter.iterate_from_obj(sig))
117
+ execenv.print(
118
+ f" Geometry results after reselect: {len(geometry_results_after)}"
119
+ )
120
+ assert len(geometry_results_after) == 2, (
121
+ "Should still have two geometry results after re-selection"
122
+ )
123
+
124
+ # Check that the merged label is still present
125
+ merged_labels_after = [
126
+ item
127
+ for item in plot.items
128
+ if hasattr(item, "labelparam")
129
+ and hasattr(item, "is_readonly")
130
+ and item.is_readonly()
131
+ ]
132
+
133
+ execenv.print(
134
+ f" Merged result labels on plot after reselect: {len(merged_labels_after)}"
135
+ )
136
+ assert len(merged_labels_after) == 1, (
137
+ "Should still have one merged result label after re-selection"
138
+ )
139
+
140
+ merged_label_final = merged_labels_after[0]
141
+ label_text_final = merged_label_final.text_string
142
+ assert "fwhm" in label_text_final.lower(), (
143
+ "Label should still contain FWHM result"
144
+ )
145
+ assert "fw1e2" in label_text_final.lower(), (
146
+ "Label should still contain FW1e2 result"
147
+ )
148
+ execenv.print(" ✓ Merged label persists after re-selection")
149
+
150
+ execenv.print("✓ Test passed: Merged result label works correctly")
151
+
152
+
153
+ if __name__ == "__main__":
154
+ test_merged_result_label()
@@ -0,0 +1,223 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ Unit test for visualization settings for annotated shapes and markers.
5
+
6
+ This test verifies that visualization settings (configured in Settings dialog)
7
+ are properly applied when creating geometry results:
8
+ 1. Centroid produces a marker (MARKER kind from sigima)
9
+ 2. Contour detection produces annotated shapes (CIRCLE, ELLIPSE, or POLYGON kind)
10
+
11
+ The test uses the Conf.view.def*.temp() context manager to temporarily modify
12
+ settings and verify they're applied to new results.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ from plotpy.items import AnnotatedCircle, Marker
18
+ from plotpy.styles import MarkerParam, ShapeParam
19
+ from sigima.objects import Gauss2DParam, create_image_from_param
20
+
21
+ from datalab.adapters_metadata import GeometryAdapter
22
+ from datalab.adapters_plotpy import GeometryPlotPyAdapter
23
+ from datalab.config import Conf
24
+ from datalab.env import execenv
25
+ from datalab.tests import datalab_test_app_context
26
+
27
+
28
+ def test_ima_shape_param():
29
+ """Test that annotated shape settings are applied to
30
+ enclosing_circle results on images."""
31
+ with datalab_test_app_context(console=False) as win:
32
+ panel = win.imagepanel
33
+
34
+ # Create a Gaussian image for testing (simple peak for enclosing circle)
35
+ size = 200
36
+ param = Gauss2DParam.create(height=size, width=size, sigma=20)
37
+ img = create_image_from_param(param)
38
+ img.title = "Test Gaussian"
39
+ panel.add_object(img)
40
+
41
+ # Test: Verify annotated shape settings for enclosing circle
42
+ # ----------------------------------------------------------
43
+ execenv.print("\n=== Test: Enclosing Circle (Annotated Shapes) ===")
44
+
45
+ # Create custom annotated shape settings
46
+ def_param = ShapeParam()
47
+ def_param.line.width = 3
48
+ def_param.line.color = "#852727"
49
+
50
+ # Temporarily set the annotated shape settings
51
+ # Note: enclosing_circle is an image feature, so we use ima_shape_param
52
+ with Conf.view.ima_shape_param.temp(def_param):
53
+ # Compute enclosing circle with the custom settings
54
+ with Conf.proc.show_result_dialog.temp(False):
55
+ panel.processor.run_feature("enclosing_circle")
56
+
57
+ # Get the geometry adapter and create plot items
58
+ adapter = GeometryAdapter.from_obj(img, "enclosing_circle")
59
+ assert adapter is not None, "Enclosing circle should be computed"
60
+
61
+ # Create a plotpy adapter to get the shape items
62
+ plotpy_adapter = GeometryPlotPyAdapter(adapter)
63
+ items = list(plotpy_adapter.iterate_shape_items("%.1f", True, "i"))
64
+
65
+ # Verify we got annotated shapes
66
+ assert len(items) > 0, "Should have at least one shape"
67
+
68
+ shape_item = items[0]
69
+ assert isinstance(shape_item, AnnotatedCircle), (
70
+ f"Expected AnnotatedCircle, got {type(shape_item)}"
71
+ )
72
+
73
+ # Verify the annotation settings were applied
74
+ param: ShapeParam = shape_item.shape.shapeparam
75
+ execenv.print(f"Line width: {param.line.width}")
76
+ execenv.print(f"Line color: {param.line.color}")
77
+ assert param.line.width == def_param.line.width, (
78
+ f"Expected line.width={def_param.line.width}, got {param.line.width}"
79
+ )
80
+ assert param.line.color == def_param.line.color, (
81
+ f"Expected line.color={def_param.line.color}, got {param.line.color}"
82
+ )
83
+ execenv.print(
84
+ "✓ Enclosing circle annotated shape settings correctly applied"
85
+ )
86
+
87
+ execenv.print("\n=== Test passed ===")
88
+
89
+
90
+ def test_ima_marker_param():
91
+ """Test that shape settings are applied to geometry results."""
92
+ with datalab_test_app_context(console=False) as win:
93
+ panel = win.imagepanel
94
+
95
+ # Create a 2D Gaussian image for testing
96
+ size = 200
97
+ param = Gauss2DParam.create(height=size, width=size, sigma=20)
98
+ img = create_image_from_param(param)
99
+ img.title = "Test Gaussian"
100
+ panel.add_object(img)
101
+
102
+ # Test: Verify marker settings for centroid
103
+ # ------------------------------------------
104
+ execenv.print("\n=== Test: Centroid (Marker) ===")
105
+
106
+ # Create custom marker settings
107
+ def_param = MarkerParam()
108
+ def_symbol = def_param.symbol
109
+ def_symbol.marker = "XCross"
110
+ def_symbol.size = 15
111
+ def_symbol.edgecolor = "#316331"
112
+ def_symbol.facecolor = "#291b6b"
113
+ def_symbol.alpha = 0.87
114
+
115
+ # Temporarily set the marker settings
116
+ with Conf.view.ima_marker_param.temp(def_param):
117
+ # Compute centroid with the custom settings
118
+ with Conf.proc.show_result_dialog.temp(False):
119
+ panel.processor.run_feature("centroid")
120
+
121
+ # Get the geometry adapter and create plot items
122
+ adapter = GeometryAdapter.from_obj(img, "centroid")
123
+ assert adapter is not None, "Centroid should be computed"
124
+
125
+ # Create a plotpy adapter to get the marker item
126
+ plotpy_adapter = GeometryPlotPyAdapter(adapter)
127
+ items = list(plotpy_adapter.iterate_shape_items("%.1f", True, "i"))
128
+
129
+ # Verify we got a marker
130
+ assert len(items) > 0, "Should have at least one marker"
131
+
132
+ marker = items[0]
133
+ assert isinstance(marker, Marker), f"Expected Marker, got {type(marker)}"
134
+
135
+ # Verify the marker settings were applied
136
+ symbol = marker.markerparam.symbol
137
+ execenv.print(f"Marker symbol: {symbol.marker}")
138
+ execenv.print(f"Marker size: {symbol.size}")
139
+ execenv.print(f"Marker edge color: {symbol.edgecolor}")
140
+ assert symbol.marker == def_symbol.marker, (
141
+ f"Expected marker='XCross', got '{symbol.marker}'"
142
+ )
143
+ assert symbol.size == def_symbol.size, (
144
+ f"Expected size={def_symbol.size}, got {symbol.size}"
145
+ )
146
+ assert symbol.edgecolor == def_symbol.edgecolor, (
147
+ f"Expected edgecolor={def_symbol.edgecolor}, got {symbol.edgecolor}"
148
+ )
149
+ assert symbol.facecolor == def_symbol.facecolor, (
150
+ f"Expected facecolor={def_symbol.facecolor}, got {symbol.facecolor}"
151
+ )
152
+ execenv.print("✓ Centroid marker settings correctly applied")
153
+
154
+ execenv.print("\n=== Test passed ===")
155
+
156
+
157
+ def test_refresh_shape_items_after_settings_change():
158
+ """Test that shape items are refreshed when settings change.
159
+
160
+ This test verifies the fix for the issue where result shapes were not
161
+ updated when refreshing the Image View after changing shape
162
+ parameters in the Settings dialog.
163
+ """
164
+ with datalab_test_app_context(console=False) as win:
165
+ panel = win.imagepanel
166
+
167
+ # Create a Gaussian image with a result
168
+ size = 200
169
+ param = Gauss2DParam.create(height=size, width=size, sigma=20)
170
+ img = create_image_from_param(param)
171
+ img.title = "Test Gaussian"
172
+ panel.add_object(img)
173
+
174
+ # Compute enclosing circle with initial settings
175
+ with Conf.proc.show_result_dialog.temp(False):
176
+ panel.processor.run_feature("enclosing_circle")
177
+
178
+ # Get initial shape item styling
179
+ plot = panel.plothandler.plot
180
+ shape_items = [item for item in plot.items if isinstance(item, AnnotatedCircle)]
181
+ assert len(shape_items) > 0, "Should have at least one shape item"
182
+
183
+ initial_width = shape_items[0].shape.shapeparam.line.width
184
+ initial_color = shape_items[0].shape.shapeparam.line.color
185
+
186
+ execenv.print(f"Initial shape: width={initial_width}, color={initial_color}")
187
+
188
+ # Change temporarily the shape parameters
189
+ new_param = ShapeParam()
190
+ new_param.line.width = 5
191
+ new_param.line.color = "#00ff00"
192
+ with Conf.view.ima_shape_param.temp(new_param):
193
+ # Call refresh_all_shape_items() to apply new settings
194
+ panel.plothandler.refresh_all_shape_items()
195
+
196
+ # Get updated shape items
197
+ shape_items_after = [
198
+ item for item in plot.items if isinstance(item, AnnotatedCircle)
199
+ ]
200
+ assert len(shape_items_after) > 0, (
201
+ "Should still have shape items after refresh"
202
+ )
203
+
204
+ updated_width = shape_items_after[0].shape.shapeparam.line.width
205
+ updated_color = shape_items_after[0].shape.shapeparam.line.color
206
+
207
+ execenv.print(
208
+ f"Updated shape: width={updated_width}, color={updated_color}"
209
+ )
210
+
211
+ # Verify the shape was updated with new settings
212
+ assert updated_width == 5, f"Expected width 5, got {updated_width}"
213
+ assert updated_color == "#00ff00", (
214
+ f"Expected color #00ff00, got {updated_color}"
215
+ )
216
+
217
+ execenv.print("✓ Shape items correctly refreshed after settings change\n")
218
+
219
+
220
+ if __name__ == "__main__":
221
+ test_ima_shape_param()
222
+ test_ima_marker_param()
223
+ test_refresh_shape_items_after_settings_change()
@@ -0,0 +1,64 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ ROI to plot item conversion unit tests
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
+ from guidata.qthelpers import qt_app_context
15
+ from sigima.tests.data import (
16
+ create_multigaussian_image,
17
+ create_paracetamol_signal,
18
+ create_test_image_rois,
19
+ create_test_signal_rois,
20
+ )
21
+
22
+ from datalab.adapters_plotpy import create_adapter_from_object, plotitem_to_singleroi
23
+ from datalab.env import execenv
24
+
25
+
26
+ def __conversion_methods(
27
+ roi: sigima.objects.SignalROI | sigima.objects.ImageROI,
28
+ obj: sigima.objects.SignalObj | sigima.objects.ImageObj,
29
+ ) -> None:
30
+ """Test conversion methods for single ROI objects"""
31
+ execenv.print(" test `to_plot_item` and `from_plot_item` methods: ", end="")
32
+ single_roi = roi.get_single_roi(0)
33
+ with qt_app_context(exec_loop=False):
34
+ plot_item = create_adapter_from_object(single_roi).to_plot_item(obj)
35
+ sroi_new = plotitem_to_singleroi(plot_item)
36
+ orig_coords = [float(val) for val in single_roi.get_physical_coords(obj)]
37
+ new_coords = [float(val) for val in sroi_new.get_physical_coords(obj)]
38
+ execenv.print(f"{orig_coords} --> {new_coords}")
39
+ assert np.array_equal(orig_coords, new_coords)
40
+
41
+
42
+ def test_signal_roi_plotitem_conversion() -> None:
43
+ """Test signal ROIs conversion to/from plot items"""
44
+ execenv.print("==============================================")
45
+ execenv.print("Test signal ROIs conversion to/from plot items")
46
+ execenv.print("==============================================")
47
+ obj = create_paracetamol_signal()
48
+ for roi in create_test_signal_rois(obj):
49
+ __conversion_methods(roi, obj)
50
+
51
+
52
+ def test_image_roi_plotitem_conversion() -> None:
53
+ """Test image ROIs conversion to/from plot items"""
54
+ execenv.print("==============================================")
55
+ execenv.print("Test image ROIs conversion to/from plot items")
56
+ execenv.print("==============================================")
57
+ obj = create_multigaussian_image()
58
+ for roi in create_test_image_rois(obj):
59
+ __conversion_methods(roi, obj)
60
+
61
+
62
+ if __name__ == "__main__":
63
+ test_signal_roi_plotitem_conversion()
64
+ test_image_roi_plotitem_conversion()