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,111 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """Image background selection dialog."""
4
+
5
+ # pylint: disable=invalid-name # Allows short reference names like x, y, ...
6
+
7
+ from __future__ import annotations
8
+
9
+ from typing import TYPE_CHECKING
10
+
11
+ import numpy as np
12
+ from guidata.configtools import get_icon
13
+ from plotpy.builder import make
14
+ from plotpy.plot import PlotDialog
15
+
16
+ from datalab.adapters_plotpy import create_adapter_from_object
17
+ from datalab.config import _
18
+ from datalab.utils.qthelpers import resize_widget_to_parent
19
+
20
+ if TYPE_CHECKING:
21
+ from plotpy.items import MaskedXYImageItem, RangeComputation2d, RectangleShape
22
+ from qtpy.QtWidgets import QWidget
23
+ from sigima.objects import ImageObj
24
+
25
+
26
+ class ImageBackgroundDialog(PlotDialog):
27
+ """Image background selection dialog.
28
+
29
+ Args:
30
+ image: image object
31
+ parent: parent widget. Defaults to None.
32
+ """
33
+
34
+ def __init__(self, image: ImageObj, parent: QWidget | None = None) -> None:
35
+ self.__background: float | None = None
36
+ self.__rect_coords: tuple[float, float, float, float] | None = None
37
+ self.imageitem: MaskedXYImageItem | None = None
38
+ self.rectarea: RectangleShape | None = None
39
+ self.comput2d: RangeComputation2d | None = None
40
+ super().__init__(
41
+ title=_("Image background selection"), edit=True, parent=parent
42
+ )
43
+ self.setObjectName("backgroundselection")
44
+ if parent is None:
45
+ self.setWindowIcon(get_icon("DataLab.svg"))
46
+ else:
47
+ resize_widget_to_parent(self, aspect_ratio=1.0)
48
+ self.__image = image.copy()
49
+ self.__setup_dialog()
50
+
51
+ def test_compute_background(self) -> None:
52
+ """Method to test background computation."""
53
+ # Instead of waiting for Qt events, directly test the computation method
54
+ # by simulating what RangeComputation2d would do
55
+ x0, y0, x1, y1 = self.rectarea.get_rect()
56
+ x, y, z = self.imageitem.get_data(x0, y0, x1, y1)
57
+ self.__compute_background(x, y, z)
58
+
59
+ def __compute_background(
60
+ self,
61
+ x: np.ndarray, # pylint: disable=unused-argument
62
+ y: np.ndarray, # pylint: disable=unused-argument
63
+ z: np.ndarray,
64
+ ) -> float:
65
+ """Compute background value"""
66
+ self.__rect_coords = self.rectarea.get_rect()
67
+ self.__background = z.mean()
68
+ return self.__background
69
+
70
+ def __setup_dialog(self) -> None:
71
+ """Setup dialog box"""
72
+ obj = self.__image
73
+ self.imageitem = create_adapter_from_object(obj).make_item()
74
+ plot = self.get_plot()
75
+ if obj.is_uniform_coords:
76
+ x0, y0 = obj.x0, obj.y0
77
+ x1, y1 = obj.xc + obj.dx, obj.yc + obj.dy
78
+ else:
79
+ x0, y0 = obj.xcoords[0], obj.ycoords[0]
80
+ xc = (obj.xcoords[0] + obj.xcoords[-1]) / 2
81
+ yc = (obj.ycoords[0] + obj.ycoords[-1]) / 2
82
+ x1, y1 = xc, yc
83
+ self.rectarea = make.rectangle(x0, y0, x1, y1, _("Background area"))
84
+ self.comput2d = make.computation2d(
85
+ self.rectarea,
86
+ "TL",
87
+ _("Background value:") + " %g",
88
+ self.imageitem,
89
+ self.__compute_background,
90
+ )
91
+ for item in (self.imageitem, self.rectarea, self.comput2d):
92
+ plot.add_item(item)
93
+ plot.replot()
94
+ plot.set_active_item(self.rectarea)
95
+
96
+ def get_background(self) -> float:
97
+ """Get background value"""
98
+ return self.__background
99
+
100
+ def get_rect_coords(self) -> tuple[float, float, float, float]:
101
+ """Get rectangle coordinates
102
+
103
+ Returns:
104
+ tuple: rectangle coordinates (x0, y0, x1, y1)
105
+
106
+ Raises:
107
+ ValueError: if rectangle coordinates are not set
108
+ """
109
+ if self.__rect_coords is None:
110
+ raise ValueError("Rectangle coordinates not set")
111
+ return self.__rect_coords
@@ -0,0 +1,175 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ Module providing DataLab Installation configuration widget
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import json
10
+ import locale
11
+ import os
12
+ import platform
13
+ import sys
14
+ from importlib.metadata import distributions
15
+ from pathlib import Path
16
+
17
+ from guidata.configtools import get_icon
18
+ from guidata.qthelpers import exec_dialog
19
+ from qtpy import QtWidgets as QW
20
+ from sigima.io.image import ImageIORegistry
21
+ from sigima.io.signal import SignalIORegistry
22
+
23
+ import datalab
24
+ from datalab.config import APP_NAME, IS_FROZEN, Conf, _
25
+ from datalab.plugins import PluginRegistry
26
+ from datalab.widgets.fileviewer import FileViewerWidget, get_title_contents
27
+
28
+
29
+ def decode_fs_string(string: bytes) -> str:
30
+ """Convert string from file system charset to unicode"""
31
+ charset = sys.getfilesystemencoding()
32
+ if charset is None:
33
+ charset = locale.getpreferredencoding()
34
+ return string.decode(charset)
35
+
36
+
37
+ def get_installed_package_info() -> str:
38
+ """Get the list of installed packages with their versions"""
39
+ packages = [(dist.metadata["Name"], dist.version) for dist in distributions()]
40
+
41
+ # Sort alphabetically by package name
42
+ packages.sort(key=lambda x: x[0].lower())
43
+
44
+ # Determine column widths
45
+ name_width = max(len(name) for name, _ in packages)
46
+ version_width = max(len(version) for _, version in packages)
47
+
48
+ header = f"{'Package':{name_width}} {'Version':{version_width}}"
49
+ separator = f"{'-' * name_width} {'-' * version_width}"
50
+ result_lines = [header, separator]
51
+ for name, version in packages:
52
+ result_lines.append(f"{name:{name_width}} {version:{version_width}}")
53
+
54
+ return os.linesep.join(result_lines)
55
+
56
+
57
+ def get_manifest_package_info(manifest_path: Path) -> str:
58
+ """Get the list of packages from the build manifest file
59
+
60
+ Args:
61
+ manifest_path: Path to the manifest.json file
62
+
63
+ Returns:
64
+ Formatted string with package list and build information
65
+ """
66
+ try:
67
+ with open(manifest_path, "r", encoding="utf-8") as f:
68
+ manifest = json.load(f)
69
+
70
+ packages = list(manifest["packages"].items())
71
+ packages.sort(key=lambda x: x[0].lower())
72
+
73
+ # Determine column widths
74
+ name_width = max(len(name) for name, _ in packages)
75
+ version_width = max(len(version) for _, version in packages)
76
+
77
+ header = f"{'Package':{name_width}} {'Version':{version_width}}"
78
+ separator = f"{'-' * name_width} {'-' * version_width}"
79
+ result_lines = [
80
+ f"Build time: {manifest['build_time']}",
81
+ f"Python version: {manifest['python_version']}",
82
+ f"Build system: {manifest['system']} {manifest['release']}",
83
+ f"Architecture: {manifest['architecture']}",
84
+ "",
85
+ header,
86
+ separator,
87
+ ]
88
+ for name, version in packages:
89
+ result_lines.append(f"{name:{name_width}} {version:{version_width}}")
90
+
91
+ return os.linesep.join(result_lines)
92
+ except Exception as e:
93
+ return f"Error reading manifest file: {e}"
94
+
95
+
96
+ def get_install_info() -> str:
97
+ """Get DataLab installation informations
98
+
99
+ Returns:
100
+ str: installation informations
101
+ """
102
+ if IS_FROZEN:
103
+ # Stand-alone version
104
+ more_info = "This is the Stand-alone version of DataLab."
105
+ more_info += os.linesep * 2
106
+
107
+ # Try to read manifest file from executable root directory
108
+ manifest_path = Path(sys.executable).parent / "manifest.json"
109
+ if manifest_path.exists():
110
+ more_info += get_manifest_package_info(manifest_path)
111
+ else:
112
+ more_info += "Manifest file not found."
113
+ else:
114
+ more_info = get_installed_package_info()
115
+ info = os.linesep.join(
116
+ [
117
+ f"DataLab v{datalab.__version__}",
118
+ "",
119
+ f"Machine type: {platform.machine()}",
120
+ f"Platform: {platform.platform()}",
121
+ f"Python v{sys.version}",
122
+ "",
123
+ more_info,
124
+ ]
125
+ )
126
+ return info
127
+
128
+
129
+ class InstallConfigViewerWindow(QW.QDialog):
130
+ """Installation configuration window"""
131
+
132
+ def __init__(self, parent: QW.QWidget | None = None) -> None:
133
+ super().__init__(parent)
134
+ self.setObjectName("instviewer")
135
+ self.setWindowTitle(APP_NAME + " - " + _("Installation and configuration"))
136
+ self.setWindowIcon(get_icon("DataLab.svg"))
137
+ self.tabs = QW.QTabWidget(self)
138
+ uc_title, uc_contents = get_title_contents(Conf.get_filename())
139
+ plugins_io_contents = PluginRegistry.get_plugin_info(html=False)
140
+ for registry in (SignalIORegistry, ImageIORegistry):
141
+ plugins_io_contents += os.linesep + ("_" * 80) + os.linesep * 2
142
+ plugins_io_contents += registry.get_format_info(mode="text")
143
+ for title, contents, tab_icon, tab_title in (
144
+ (
145
+ _("Installation configuration"),
146
+ get_install_info(),
147
+ get_icon("libre-toolbox.svg"),
148
+ _("Installation configuration"),
149
+ ),
150
+ (
151
+ uc_title,
152
+ uc_contents,
153
+ get_icon("libre-gui-settings.svg"),
154
+ _("User configuration"),
155
+ ),
156
+ (
157
+ _("Plugins and I/O features"),
158
+ plugins_io_contents,
159
+ get_icon("libre-gui-plugin.svg"),
160
+ _("Plugins and I/O features"),
161
+ ),
162
+ ):
163
+ viewer = FileViewerWidget()
164
+ viewer.set_data(title, contents)
165
+ self.tabs.addTab(viewer, tab_icon, tab_title)
166
+ layout = QW.QVBoxLayout()
167
+ layout.addWidget(self.tabs)
168
+ self.setLayout(layout)
169
+ self.resize(800, 500)
170
+
171
+
172
+ def exec_datalab_installconfig_dialog(parent: QW.QWidget | None = None) -> None:
173
+ """View DataLab installation configuration"""
174
+ dlg = InstallConfigViewerWindow(parent=parent)
175
+ exec_dialog(dlg)
@@ -0,0 +1,80 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ Module providing a log viewer widget, a log viewer window and DataLab's log viewer
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import os.path as osp
10
+
11
+ from guidata.configtools import get_icon
12
+ from guidata.qthelpers import exec_dialog
13
+ from qtpy import QtWidgets as QW
14
+
15
+ from datalab.config import APP_NAME, Conf, _, get_old_log_fname
16
+ from datalab.env import execenv
17
+ from datalab.widgets.fileviewer import FileViewerWidget, get_title_contents
18
+
19
+
20
+ class LogViewerWindow(QW.QDialog):
21
+ """Log viewer window"""
22
+
23
+ def __init__(self, fnames: list[str], parent: QW.QWidget | None = None) -> None:
24
+ super().__init__(parent)
25
+ self.setObjectName("logviewer")
26
+ self.setWindowTitle(APP_NAME + " - " + _("Log files"))
27
+ self.setWindowIcon(get_icon("DataLab.svg"))
28
+ self.tabs = QW.QTabWidget(self)
29
+ for fname in fnames:
30
+ if osp.isfile(fname):
31
+ title, contents = get_title_contents(fname)
32
+ if not contents.strip():
33
+ continue
34
+ viewer = FileViewerWidget(language="Python")
35
+ viewer.set_data(title, contents)
36
+ self.tabs.addTab(viewer, get_icon("logs.svg"), osp.basename(fname))
37
+ layout = QW.QVBoxLayout()
38
+ layout.addWidget(self.tabs)
39
+ self.setLayout(layout)
40
+ self.resize(900, 400)
41
+
42
+ @property
43
+ def is_empty(self) -> bool:
44
+ """Return True if there is no log available"""
45
+ return self.tabs.count() == 0
46
+
47
+
48
+ def get_log_filenames() -> list[str]:
49
+ """Return log filenames"""
50
+ return [
51
+ Conf.main.traceback_log_path.get(),
52
+ Conf.main.faulthandler_log_path.get(),
53
+ get_old_log_fname(Conf.main.traceback_log_path.get()),
54
+ get_old_log_fname(Conf.main.faulthandler_log_path.get()),
55
+ ]
56
+
57
+
58
+ def get_log_prompt_message() -> str | None:
59
+ """Return prompt message for log files, i.e. a message informing the user
60
+ whether log files were generated during last session or current session."""
61
+ avail = [osp.isfile(fname) for fname in get_log_filenames()]
62
+ if avail[0] or avail[1]:
63
+ return _("Log files were generated during current session.")
64
+ if avail[2] or avail[3]:
65
+ return _("Log files were generated during last session.")
66
+ return None
67
+
68
+
69
+ def exec_datalab_logviewer_dialog(parent: QW.QWidget | None = None) -> None:
70
+ """View DataLab logs"""
71
+ fnames = [osp.normpath(fname) for fname in get_log_filenames() if osp.isfile(fname)]
72
+ dlg = LogViewerWindow(fnames, parent=parent)
73
+ if dlg.is_empty:
74
+ if not execenv.unattended:
75
+ QW.QMessageBox.information(
76
+ dlg, APP_NAME, _("Log files are currently empty.")
77
+ )
78
+ dlg.close()
79
+ else:
80
+ exec_dialog(dlg)
@@ -0,0 +1,90 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """Signal base line selection dialog."""
4
+
5
+ # pylint: disable=invalid-name # Allows short reference names like x, y, ...
6
+
7
+ from __future__ import annotations
8
+
9
+ from typing import TYPE_CHECKING
10
+
11
+ import numpy as np
12
+ from guidata.configtools import get_icon
13
+ from plotpy.builder import make
14
+ from plotpy.plot import PlotDialog
15
+
16
+ from datalab.adapters_plotpy import CURVESTYLES, create_adapter_from_object
17
+ from datalab.config import _
18
+ from datalab.utils.qthelpers import resize_widget_to_parent
19
+
20
+ if TYPE_CHECKING:
21
+ from plotpy.items import CurveItem, Marker, XRangeSelection
22
+ from qtpy.QtWidgets import QWidget
23
+ from sigima.objects import SignalObj
24
+
25
+
26
+ class SignalBaselineDialog(PlotDialog):
27
+ """Signal baseline selection dialog.
28
+
29
+ Args:
30
+ signal: signal object
31
+ parent: parent widget. Defaults to None.
32
+ """
33
+
34
+ def __init__(self, signal: SignalObj, parent: QWidget | None = None) -> None:
35
+ self.__curve_styles = CURVESTYLES.style_generator()
36
+ self.__baseline: float | None = None
37
+ self.__x_range: tuple[float, float] = [np.nan, np.nan]
38
+ self.curve: CurveItem | None = None
39
+ self.cursor: Marker | None = None
40
+ self.xrange: XRangeSelection | None = None
41
+ super().__init__(title=_("Signal baseline selection"), edit=True, parent=parent)
42
+ self.setObjectName("baselineselection")
43
+ if parent is None:
44
+ self.setWindowIcon(get_icon("DataLab.svg"))
45
+ legend = make.legend("TR")
46
+ self.get_plot().add_item(legend)
47
+ self.__signal = signal.copy()
48
+ self.__setup_dialog()
49
+ resize_widget_to_parent(self, aspect_ratio=1.0)
50
+
51
+ def __setup_dialog(self) -> None:
52
+ """Setup dialog box"""
53
+ obj = self.__signal
54
+ with CURVESTYLES.alternative(self.__curve_styles):
55
+ self.curve = create_adapter_from_object(obj).make_item()
56
+ plot = self.get_plot()
57
+ plot.set_antialiasing(True)
58
+ plot.SIG_RANGE_CHANGED.connect(self.xrange_changed)
59
+ plot.SIG_MARKER_CHANGED.connect(self.cursor_changed)
60
+ self.cursor = make.hcursor(0.0, _("Base line") + " = %g")
61
+ self.cursor.set_movable(False)
62
+ self.xrange = make.xrange(obj.x[0], obj.x[int(0.2 * len(obj.x))])
63
+ for item in (self.curve, self.cursor, self.xrange):
64
+ plot.add_item(item)
65
+ plot.replot()
66
+ plot.set_active_item(self.xrange)
67
+ self.xrange_changed(self.xrange, *self.xrange.get_range())
68
+
69
+ # pylint: disable=unused-argument
70
+ def xrange_changed(self, item: XRangeSelection, xmin: float, xmax: float) -> None:
71
+ """X range changed"""
72
+ self.__x_range = sorted([xmin, xmax])
73
+ imin, imax = np.searchsorted(self.__signal.x, self.__x_range)
74
+ if imin == imax:
75
+ return
76
+ self.cursor.set_pos(0, np.mean(self.__signal.y[imin:imax]))
77
+ plot = self.get_plot()
78
+ plot.replot()
79
+
80
+ def cursor_changed(self, item: Marker) -> None:
81
+ """Cursor changed"""
82
+ _x, self.__baseline = item.get_pos()
83
+
84
+ def get_baseline(self) -> float:
85
+ """Get baseline"""
86
+ return self.__baseline
87
+
88
+ def get_x_range(self) -> tuple[float, float]:
89
+ """Get x range"""
90
+ return self.__x_range
@@ -0,0 +1,208 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """Signal horizontal or vertical cursor selection dialog."""
4
+
5
+ # pylint: disable=invalid-name # Allows short reference names like x, y, ...
6
+
7
+ from __future__ import annotations
8
+
9
+ from typing import TYPE_CHECKING, Literal
10
+
11
+ import numpy as np
12
+ from guidata.configtools import get_icon
13
+ from plotpy.builder import make
14
+ from plotpy.plot import PlotDialog
15
+ from qtpy import QtGui as QG
16
+ from qtpy import QtWidgets as QW
17
+ from sigima.tools.signal.features import find_x_values_at_y
18
+
19
+ from datalab.adapters_plotpy import CURVESTYLES, create_adapter_from_object
20
+ from datalab.config import _
21
+ from datalab.utils.qthelpers import block_signals, resize_widget_to_parent
22
+
23
+ if TYPE_CHECKING:
24
+ from plotpy.items import CurveItem, Marker
25
+ from qtpy.QtWidgets import QWidget
26
+ from sigima.objects import SignalObj
27
+
28
+
29
+ class SignalCursorDialog(PlotDialog):
30
+ """Signal horizontal or vertical cursor selection dialog.
31
+
32
+ Args:
33
+ signal: signal object
34
+ parent: parent widget. Defaults to None.
35
+ """
36
+
37
+ def __init__(
38
+ self,
39
+ signal: SignalObj,
40
+ cursor_orientation: Literal["horizontal", "vertical"],
41
+ parent: QWidget | None = None,
42
+ ) -> None:
43
+ assert cursor_orientation in (
44
+ "horizontal",
45
+ "vertical",
46
+ ), "cursor_orientation must be 'horizontal' or 'vertical'"
47
+ self.__curve_styles = CURVESTYLES.style_generator()
48
+ self.__cursor_orientation = cursor_orientation
49
+ self.__signal = signal
50
+ self.__x_value: float | None = None
51
+ self.__y_value: float | None = None
52
+ self.curve: CurveItem | None = None
53
+ self.hcursor: Marker | None = None
54
+ self.vcursor: Marker | None = None
55
+ self.xlineedit: QW.QLineEdit | None = None
56
+ self.ylineedit: QW.QLineEdit | None = None
57
+ if cursor_orientation == "horizontal":
58
+ title = _("Select X value with cursor")
59
+ else:
60
+ title = _("Select Y value with cursor")
61
+ super().__init__(title=title, edit=True, parent=parent)
62
+ self.setObjectName("SignalCursorDialog")
63
+ if parent is None:
64
+ self.setWindowIcon(get_icon("DataLab.svg"))
65
+ legend = make.legend("TR")
66
+ self.get_plot().add_item(legend)
67
+ self.__setup_dialog()
68
+ resize_widget_to_parent(self, aspect_ratio=1.0)
69
+
70
+ def __setup_dialog(self) -> None:
71
+ """Setup dialog box"""
72
+ apply_button = QW.QPushButton(_("Apply"))
73
+ apply_button.setIcon(get_icon("apply.svg"))
74
+ apply_button.setToolTip(_("Apply cursor position"))
75
+ xlabel = QW.QLabel("X=")
76
+ ylabel = QW.QLabel("Y=")
77
+ self.xlineedit = QW.QLineEdit()
78
+ self.xlineedit.editingFinished.connect(self.xlineedit_editing_finished)
79
+ self.xlineedit.setValidator(QG.QDoubleValidator())
80
+ self.ylineedit = QW.QLineEdit()
81
+ self.ylineedit.editingFinished.connect(self.ylineedit_editing_finished)
82
+ self.ylineedit.setValidator(QG.QDoubleValidator())
83
+ self.xlineedit.setReadOnly(self.__cursor_orientation == "horizontal")
84
+ self.xlineedit.setDisabled(self.__cursor_orientation == "horizontal")
85
+ self.ylineedit.setReadOnly(self.__cursor_orientation == "vertical")
86
+ self.ylineedit.setDisabled(self.__cursor_orientation == "vertical")
87
+ xygroup = QW.QGroupBox(_("Cursor position"))
88
+ xylayout = QW.QHBoxLayout()
89
+ xylayout.addWidget(xlabel)
90
+ xylayout.addWidget(self.xlineedit)
91
+ if self.__cursor_orientation == "vertical":
92
+ xylayout.addWidget(apply_button)
93
+ apply_button.clicked.connect(self.xlineedit_editing_finished)
94
+ xylayout.addStretch()
95
+ xylayout.addSpacing(10)
96
+ xylayout.addWidget(ylabel)
97
+ xylayout.addWidget(self.ylineedit)
98
+ if self.__cursor_orientation == "horizontal":
99
+ xylayout.addWidget(apply_button)
100
+ apply_button.clicked.connect(self.ylineedit_editing_finished)
101
+ xygroup.setLayout(xylayout)
102
+ self.button_layout.insertWidget(0, xygroup)
103
+
104
+ obj = self.__signal
105
+ with CURVESTYLES.alternative(self.__curve_styles):
106
+ self.curve = create_adapter_from_object(obj).make_item()
107
+ plot = self.get_plot()
108
+ plot.set_antialiasing(True)
109
+
110
+ xcursor = make.xcursor(np.mean(obj.x), np.mean(obj.y), "X = %g, Y = %g")
111
+ xcursor.set_selectable(False)
112
+ param = xcursor.markerparam
113
+ param.symbol.facecolor = "blue"
114
+ param.symbol.edgecolor = "cyan"
115
+ param.symbol.size = 9
116
+ param.line.style = "DotLine"
117
+ param.line.color = "blue"
118
+ param.line.width = 2.0
119
+ param.update_item(xcursor)
120
+
121
+ plot.SIG_MARKER_CHANGED.connect(self.cursor_changed)
122
+ if self.__cursor_orientation == "horizontal":
123
+ self.hcursor = make.hcursor(np.mean(obj.y), "Y = %g")
124
+ self.vcursor = xcursor
125
+ self.vcursor.setVisible(False)
126
+ else:
127
+ self.vcursor = make.vcursor(np.mean(obj.x), "X = %g")
128
+ self.hcursor = xcursor
129
+ self.hcursor.setVisible(False)
130
+ for item in (self.curve, self.vcursor, self.hcursor):
131
+ plot.add_item(item)
132
+ plot.replot()
133
+ if self.__cursor_orientation == "horizontal":
134
+ plot.set_active_item(self.hcursor)
135
+ self.cursor_changed(self.hcursor)
136
+ else:
137
+ plot.set_active_item(self.vcursor)
138
+ self.cursor_changed(self.vcursor)
139
+
140
+ def cursor_changed(self, item: Marker) -> None:
141
+ """Cursor changed"""
142
+ sig = self.__signal
143
+ plot = self.get_plot()
144
+ if self.__cursor_orientation == "horizontal" and item is self.hcursor:
145
+ _x, y = item.get_pos()
146
+ x = None
147
+ x_values = find_x_values_at_y(sig.x, sig.y, y)
148
+ if len(x_values) > 0:
149
+ x = x_values[0]
150
+ with block_signals(plot):
151
+ self.vcursor.set_pos(x, y)
152
+ self.vcursor.setVisible(x is not None)
153
+ self.button_box.button(QW.QDialogButtonBox.Ok).setEnabled(x is not None)
154
+ elif self.__cursor_orientation == "vertical" and item is self.vcursor:
155
+ x, _y = item.get_pos()
156
+ y_index = np.searchsorted(self.__signal.x, x)
157
+ if x < self.__signal.x[0] or y_index >= len(self.__signal.y):
158
+ y = None
159
+ else:
160
+ y = self.__signal.y[y_index]
161
+ with block_signals(plot):
162
+ self.hcursor.set_pos(x, y)
163
+ self.hcursor.setVisible(True)
164
+ self.hcursor.setVisible(y is not None)
165
+ self.button_box.button(QW.QDialogButtonBox.Ok).setEnabled(y is not None)
166
+ self.xlineedit.setText(f"{x:g}" if x is not None else "")
167
+ self.ylineedit.setText(f"{y:g}" if y is not None else "")
168
+ self.__x_value, self.__y_value = x, y
169
+
170
+ def xlineedit_editing_finished(self) -> None:
171
+ """X line edit editing finished"""
172
+ try:
173
+ x = float(self.xlineedit.text())
174
+ _x, y = self.vcursor.get_pos()
175
+ if self.__cursor_orientation == "horizontal":
176
+ self.hcursor.set_pos(x, y)
177
+ else:
178
+ self.vcursor.set_pos(x, y)
179
+ except ValueError:
180
+ pass
181
+ plot = self.get_plot()
182
+ plot.replot()
183
+
184
+ def ylineedit_editing_finished(self) -> None:
185
+ """Y line edit editing finished"""
186
+ try:
187
+ y = float(self.ylineedit.text())
188
+ x, _y = self.hcursor.get_pos()
189
+ if self.__cursor_orientation == "horizontal":
190
+ self.hcursor.set_pos(x, y)
191
+ else:
192
+ self.vcursor.set_pos(x, y)
193
+ except ValueError:
194
+ pass
195
+ plot = self.get_plot()
196
+ plot.replot()
197
+
198
+ def get_cursor_position(self) -> tuple[float, float]:
199
+ """Get cursor position"""
200
+ return self.__x_value, self.__y_value
201
+
202
+ def get_x_value(self) -> float:
203
+ """Get cursor x value"""
204
+ return self.__x_value
205
+
206
+ def get_y_value(self) -> float:
207
+ """Get cursor y value"""
208
+ return self.__y_value