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,151 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ GUI dialog for analyzing signals and calculating full width at Y.
5
+ """
6
+
7
+ # pylint: disable=invalid-name # Allows short reference names like x, y, ...
8
+
9
+ from __future__ import annotations
10
+
11
+ import warnings
12
+ from typing import TYPE_CHECKING
13
+
14
+ import numpy as np
15
+ from guidata.configtools import get_icon
16
+ from plotpy.builder import make
17
+ from plotpy.plot import PlotDialog
18
+ from qtpy import QtGui as QG
19
+ from qtpy import QtWidgets as QW
20
+ from sigima.tools.signal.pulse import full_width_at_y
21
+
22
+ from datalab.adapters_plotpy import CURVESTYLES, create_adapter_from_object
23
+ from datalab.config import _
24
+ from datalab.utils.qthelpers import resize_widget_to_parent
25
+
26
+ if TYPE_CHECKING:
27
+ from plotpy.items import CurveItem, Marker, XRangeSelection
28
+ from qtpy.QtWidgets import QWidget
29
+ from sigima.objects import SignalObj
30
+
31
+
32
+ class SignalDeltaXDialog(PlotDialog):
33
+ """Signal Delta X dialog.
34
+
35
+ Args:
36
+ signal: signal object
37
+ parent: parent widget. Defaults to None.
38
+ """
39
+
40
+ def __init__(self, signal: SignalObj, parent: QWidget | None = None) -> None:
41
+ self.__curve_styles = CURVESTYLES.style_generator()
42
+ self.__signal = signal
43
+ self.__coords: list[float, float, float, float] | None = None
44
+ self.curve: CurveItem | None = None
45
+ self.hcursor: Marker | None = None
46
+ self.delta_xrange: XRangeSelection | None = None
47
+ self.deltaxlineedit: QW.QLineEdit | None = None
48
+ self.ylineedit: QW.QLineEdit | None = None
49
+ title = _("Select Y value with cursor")
50
+ super().__init__(title=title, edit=True, parent=parent)
51
+ self.setObjectName("SignalCursorDialog")
52
+ if parent is None:
53
+ self.setWindowIcon(get_icon("DataLab.svg"))
54
+ legend = make.legend("TR")
55
+ self.get_plot().add_item(legend)
56
+ self.__setup_dialog()
57
+ resize_widget_to_parent(self, aspect_ratio=1.0)
58
+
59
+ def __setup_dialog(self) -> None:
60
+ """Setup dialog box"""
61
+ apply_button = QW.QPushButton(_("Apply"))
62
+ apply_button.setIcon(get_icon("apply.svg"))
63
+ apply_button.setToolTip(_("Apply cursor position"))
64
+ xlabel = QW.QLabel("∆X=")
65
+ ylabel = QW.QLabel("Y=")
66
+ self.deltaxlineedit = QW.QLineEdit()
67
+ self.deltaxlineedit.setReadOnly(True)
68
+ self.deltaxlineedit.setDisabled(True)
69
+ self.ylineedit = QW.QLineEdit()
70
+ self.ylineedit.editingFinished.connect(self.ylineedit_editing_finished)
71
+ self.ylineedit.setValidator(QG.QDoubleValidator())
72
+ xygroup = QW.QGroupBox(_("Cursor position"))
73
+ xylayout = QW.QHBoxLayout()
74
+ xylayout.addWidget(xlabel)
75
+ xylayout.addWidget(self.deltaxlineedit)
76
+ xylayout.addWidget(ylabel)
77
+ xylayout.addWidget(self.ylineedit)
78
+ xylayout.addWidget(apply_button)
79
+ vlayout = QW.QVBoxLayout()
80
+ vlayout.addLayout(xylayout)
81
+ self.warning_label = QW.QLabel()
82
+ vlayout.addWidget(self.warning_label)
83
+ apply_button.clicked.connect(self.ylineedit_editing_finished)
84
+ xygroup.setLayout(vlayout)
85
+ self.button_layout.insertWidget(0, xygroup)
86
+
87
+ obj = self.__signal
88
+ with CURVESTYLES.alternative(self.__curve_styles):
89
+ self.curve = create_adapter_from_object(obj).make_item()
90
+ plot = self.get_plot()
91
+ plot.set_antialiasing(True)
92
+
93
+ self.delta_xrange = make.xrange(0.0, 1.0)
94
+ self.delta_xrange.setVisible(False)
95
+ self.delta_xrange.set_style("roi", "s/readonly")
96
+ self.delta_xrange.set_selectable(False)
97
+
98
+ plot.SIG_MARKER_CHANGED.connect(self.cursor_changed)
99
+ self.hcursor = make.hcursor(np.mean(obj.y), "Y = %g")
100
+ for item in (self.curve, self.delta_xrange, self.hcursor):
101
+ plot.add_item(item)
102
+ plot.replot()
103
+ plot.set_active_item(self.hcursor)
104
+ self.cursor_changed(self.hcursor)
105
+
106
+ def cursor_changed(self, item: Marker) -> None:
107
+ """Cursor changed"""
108
+ sig = self.__signal
109
+ _x, y = item.get_pos()
110
+
111
+ try:
112
+ with warnings.catch_warnings(record=True) as w:
113
+ self.__coords = full_width_at_y(sig.x, sig.y, y)
114
+ if np.nan in self.__coords:
115
+ raise ValueError("Invalid coordinates")
116
+ delta_str = f"{self.__coords[2] - self.__coords[0]:g}"
117
+ ok = True
118
+ if len(w) > 0:
119
+ self.warning_label.setText("⚠️ " + str(w[-1].message))
120
+ else:
121
+ self.warning_label.setText("")
122
+ self.delta_xrange.setVisible(True)
123
+ self.delta_xrange.set_range(self.__coords[0], self.__coords[2])
124
+ except ValueError:
125
+ delta_str = ""
126
+ ok = False
127
+ self.delta_xrange.setVisible(False)
128
+
129
+ self.button_box.button(QW.QDialogButtonBox.Ok).setEnabled(ok)
130
+ self.deltaxlineedit.setText(delta_str)
131
+ self.ylineedit.setText(f"{y:g}" if y is not None else "")
132
+
133
+ def ylineedit_editing_finished(self) -> None:
134
+ """Y line edit editing finished"""
135
+ try:
136
+ y = float(self.ylineedit.text())
137
+ x, _y = self.hcursor.get_pos()
138
+ self.hcursor.set_pos(x, y)
139
+ except ValueError:
140
+ pass
141
+ plot = self.get_plot()
142
+ plot.replot()
143
+
144
+ def get_coords(self) -> tuple[float, float, float, float]:
145
+ """Return coordinates of segment associated to the width at Y"""
146
+ return self.__coords
147
+
148
+ def get_y_value(self) -> float:
149
+ """Get cursor y value"""
150
+ _x, y = self.hcursor.get_pos()
151
+ return y
@@ -0,0 +1,199 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """Signal peak detection feature"""
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
+ from qtpy import QtCore as QC
16
+ from qtpy import QtWidgets as QW
17
+ from sigima.tools.signal.peakdetection import peak_indices
18
+
19
+ from datalab.adapters_plotpy import CURVESTYLES, create_adapter_from_object
20
+ from datalab.config import _
21
+ from datalab.utils.qthelpers import resize_widget_to_parent
22
+
23
+ if TYPE_CHECKING:
24
+ from plotpy.items import Marker
25
+ from qtpy.QtWidgets import QWidget
26
+ from sigima.objects import SignalObj
27
+
28
+
29
+ class DistanceSlider(QW.QWidget):
30
+ """Minimum distance slider
31
+
32
+ Args:
33
+ parent: parent widget. Defaults to None.
34
+ """
35
+
36
+ TITLE = _("Minimum distance:")
37
+ SIG_VALUE_CHANGED = QC.Signal(int)
38
+
39
+ def __init__(self, parent: QWidget | None = None) -> None:
40
+ super().__init__(parent)
41
+ self.slider = QW.QSlider(QC.Qt.Horizontal)
42
+ self.label = QW.QLabel()
43
+ layout = QW.QHBoxLayout()
44
+ layout.addWidget(self.label)
45
+ layout.addWidget(self.slider)
46
+ self.setLayout(layout)
47
+
48
+ def value_changed(self, value: int) -> None:
49
+ """Slider value has changed
50
+
51
+ Args:
52
+ value: slider value
53
+ """
54
+ plural = "s" if value > 1 else ""
55
+ self.label.setText(f"{self.TITLE} {value} point{plural}")
56
+ self.SIG_VALUE_CHANGED.emit(value)
57
+
58
+ def setup_slider(self, value: int, maxval: int) -> None:
59
+ """Setup slider
60
+
61
+ Args:
62
+ value: initial value
63
+ maxval: maximum value
64
+ """
65
+ self.slider.setMinimum(1)
66
+ self.slider.setMaximum(maxval)
67
+ self.slider.setValue(value)
68
+ self.slider.setTickPosition(QW.QSlider.TicksBothSides)
69
+ self.value_changed(value)
70
+ self.slider.valueChanged.connect(self.value_changed)
71
+
72
+
73
+ class SignalPeakDetectionDialog(PlotDialog):
74
+ """Signal Peak detection dialog
75
+
76
+ Args:
77
+ signal: signal object
78
+ parent: parent widget. Defaults to None.
79
+ """
80
+
81
+ def __init__(self, signal: SignalObj, parent: QWidget | None = None) -> None:
82
+ self.__curve_styles = CURVESTYLES.style_generator()
83
+ self.peaks = None
84
+ self.peak_indices = None
85
+ self.in_curve = None
86
+ self.in_threshold = None
87
+ self.in_threshold_cursor = None
88
+ self.co_results = None
89
+ self.co_positions = None
90
+ self.co_markers = None
91
+ self.min_distance = None
92
+ self.distance_slider: DistanceSlider | None = None
93
+ super().__init__(title=_("Signal peak detection"), edit=True, parent=parent)
94
+ self.setObjectName("peakdetection")
95
+ if parent is None:
96
+ self.setWindowIcon(get_icon("DataLab.svg"))
97
+ legend = make.legend("TR")
98
+ self.get_plot().add_item(legend)
99
+ self.__signal = signal.copy()
100
+ self.__setup_dialog()
101
+ resize_widget_to_parent(self, parent, aspect_ratio=1.0)
102
+
103
+ def populate_plot_layout(self) -> None: # Reimplement PlotDialog method
104
+ """Populate the plot layout"""
105
+ super().populate_plot_layout()
106
+ self.distance_slider = DistanceSlider(self)
107
+ self.add_widget(self.distance_slider, 1, 0, 1, 1)
108
+
109
+ def __setup_dialog(self) -> None:
110
+ """Setup dialog box"""
111
+ obj = self.__signal
112
+ with CURVESTYLES.alternative(self.__curve_styles):
113
+ self.in_curve = create_adapter_from_object(obj).make_item()
114
+ plot = self.get_plot()
115
+ plot.set_antialiasing(True)
116
+ plot.add_item(self.in_curve)
117
+ self.in_threshold = 0.5 * (np.max(obj.y) - np.min(obj.y)) + np.min(obj.y)
118
+ cursor = make.hcursor(self.in_threshold)
119
+ self.in_threshold_cursor = cursor
120
+ plot.add_item(self.in_threshold_cursor)
121
+ self.co_results = make.label("", "TL", (0, 0), "TL")
122
+ plot.add_item(self.co_results)
123
+ plot.SIG_MARKER_CHANGED.connect(self.hcursor_changed)
124
+ self.min_distance = 1
125
+ self.distance_slider.setup_slider(self.min_distance, len(obj.y) // 4)
126
+ self.distance_slider.SIG_VALUE_CHANGED.connect(self.minimum_distance_changed)
127
+ self.compute_peaks()
128
+ # Replot, otherwise, it's not possible to set active item:
129
+ plot.replot()
130
+ plot.set_active_item(cursor)
131
+
132
+ def get_peaks(self) -> list[tuple[float, float]]:
133
+ """Return peaks coordinates"""
134
+ return self.peaks
135
+
136
+ def get_peak_indices(self) -> list[int]:
137
+ """Return peak indices"""
138
+ return self.peak_indices
139
+
140
+ def get_threshold(self) -> float:
141
+ """Return relative threshold"""
142
+ y = self.__signal.y
143
+ return (self.in_threshold - np.min(y)) / (np.max(y) - np.min(y))
144
+
145
+ def get_min_dist(self) -> int:
146
+ """Return minimum distance"""
147
+ return self.min_distance
148
+
149
+ def compute_peaks(self) -> None:
150
+ """Compute peak detection"""
151
+ x, y = self.__signal.xydata
152
+ plot = self.get_plot()
153
+ self.peak_indices = peak_indices(
154
+ y,
155
+ thres=self.in_threshold,
156
+ min_dist=self.min_distance,
157
+ thres_abs=True,
158
+ )
159
+ self.peaks = [(x[index], y[index]) for index in self.peak_indices]
160
+ markers = [
161
+ make.marker(
162
+ pos,
163
+ movable=False,
164
+ color="orange",
165
+ markerstyle="|",
166
+ linewidth=1,
167
+ marker="NoSymbol",
168
+ linestyle="DashLine",
169
+ )
170
+ for pos in self.peaks
171
+ ]
172
+ if self.co_markers is not None:
173
+ plot.del_items(self.co_markers)
174
+ self.co_markers = markers
175
+ for item in self.co_markers:
176
+ plot.add_item(item)
177
+ positions = [str(marker.get_pos()[0]) for marker in markers]
178
+ prefix = f"<b>{_('Peaks:')}</b><br>"
179
+ self.co_results.set_text(prefix + "<br>".join(positions))
180
+
181
+ def hcursor_changed(self, marker: Marker) -> None:
182
+ """Horizontal cursor position has changed
183
+
184
+ Args:
185
+ marker: marker item
186
+ """
187
+ _x, y = marker.get_pos()
188
+ self.in_threshold = y
189
+ self.compute_peaks()
190
+
191
+ def minimum_distance_changed(self, value: int) -> None:
192
+ """Minimum distance changed
193
+
194
+ Args:
195
+ value: minimum distance value
196
+ """
197
+ self.min_distance = value
198
+ self.compute_peaks()
199
+ self.get_plot().replot()
@@ -0,0 +1,249 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ DataLab main window status bar widgets
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import os
10
+
11
+ import psutil
12
+ from guidata.configtools import get_icon
13
+ from guidata.qthelpers import get_std_icon
14
+ from qtpy import QtCore as QC
15
+ from qtpy import QtGui as QG
16
+ from qtpy import QtWidgets as QW
17
+
18
+ from datalab.config import DEBUG, Conf, _
19
+ from datalab.env import execenv
20
+ from datalab.plugins import PluginRegistry
21
+
22
+
23
+ class BaseStatus(QW.QWidget):
24
+ """Base status widget.
25
+
26
+ Args:
27
+ delay (int | None): update interval (s). If None, widget will not be updated.
28
+ parent (QWidget): parent widget
29
+ """
30
+
31
+ def __init__(
32
+ self, delay: int | None = None, parent: QW.QWidget | None = None
33
+ ) -> None:
34
+ super().__init__(parent)
35
+ layout = QW.QHBoxLayout()
36
+ layout.setContentsMargins(0, 0, 0, 0)
37
+ self.setLayout(layout)
38
+ self.icon = QW.QLabel()
39
+ self.label = QW.QLabel()
40
+ layout.addWidget(self.icon)
41
+ layout.addWidget(self.label)
42
+ if delay is not None:
43
+ self.timer = QC.QTimer()
44
+ self.timer.timeout.connect(self.update_status)
45
+ self.timer.start(delay * 1000)
46
+
47
+ def set_icon(self, icon: QG.QIcon | str | None) -> None:
48
+ """Set icon.
49
+
50
+ Args:
51
+ icon (QIcon | None): icon
52
+ """
53
+ size = self.label.sizeHint().height()
54
+ if isinstance(icon, str):
55
+ icon = get_icon(icon)
56
+ pixmap = QG.QPixmap() if icon is None else icon.pixmap(size, size)
57
+ self.icon.setPixmap(pixmap)
58
+
59
+ def update_status(self) -> None:
60
+ """Update status widget"""
61
+ raise NotImplementedError
62
+
63
+
64
+ class ConsoleStatus(BaseStatus):
65
+ """Console status widget.
66
+
67
+ Shows a message if an error or warning has been logged to the console.
68
+ Shows a button to show the console, only if the console is hidden.
69
+
70
+ Args:
71
+ parent (QWidget): parent widget
72
+ """
73
+
74
+ SIG_SHOW_CONSOLE = QC.Signal()
75
+
76
+ def __init__(self, parent: QW.QWidget | None = None) -> None:
77
+ super().__init__(None, parent)
78
+ self.label.setText(_("Internal console"))
79
+ self.label.setToolTip(
80
+ _(
81
+ "Click to show the internal console.\n"
82
+ "The icon will turn red if an error or warning is logged."
83
+ )
84
+ )
85
+ self.label.setCursor(QG.QCursor(QC.Qt.PointingHandCursor))
86
+ self.label.mouseReleaseEvent = self.on_click
87
+ self.ok_icon = get_std_icon("MessageBoxInformation")
88
+ self.ko_icon = get_std_icon("MessageBoxWarning")
89
+ self.has_errors = False
90
+ self.update_status()
91
+
92
+ def on_click(self, event: QG.QMouseEvent) -> None:
93
+ """Handle mouse click event on label.
94
+
95
+ Args:
96
+ event: mouse event
97
+ """
98
+ if event.button() == QC.Qt.LeftButton:
99
+ self.SIG_SHOW_CONSOLE.emit()
100
+
101
+ def console_visibility_changed(self, visible: bool) -> None:
102
+ """Handle console visibility changed event.
103
+
104
+ Args:
105
+ visible (bool): console visibility
106
+ """
107
+ if visible:
108
+ # Hide this status widget when console is visible
109
+ self.hide()
110
+ else:
111
+ self.show()
112
+ self.update_status()
113
+
114
+ def exception_occurred(self) -> None:
115
+ """Handle exception occurred event"""
116
+ self.has_errors = True
117
+ self.update_status()
118
+
119
+ def update_status(self) -> None:
120
+ """Update status widget"""
121
+ if self.has_errors:
122
+ self.set_icon(self.ko_icon)
123
+ self.label.setStyleSheet("color: red")
124
+ self.label.setToolTip(
125
+ _(
126
+ "Click to show the internal console.\n"
127
+ "An error or warning has been logged."
128
+ )
129
+ )
130
+ else:
131
+ self.set_icon(self.ok_icon)
132
+ self.label.setStyleSheet("")
133
+ self.label.setToolTip(
134
+ _(
135
+ "Click to show the internal console.\n"
136
+ "No error or warning has been logged."
137
+ )
138
+ )
139
+
140
+
141
+ class MemoryStatus(BaseStatus):
142
+ """Memory status widget.
143
+
144
+ Args:
145
+ threshold (int): available memory thresold (MB)
146
+ delay (int): update interval (s)
147
+ parent (QWidget): parent widget
148
+ """
149
+
150
+ SIG_MEMORY_ALARM = QC.Signal(bool)
151
+
152
+ def __init__(
153
+ self, threshold: int = 500, delay: int = 2, parent: QW.QWidget | None = None
154
+ ) -> None:
155
+ super().__init__(delay, parent)
156
+ self.demo_mode = False
157
+ self.ko_icon = get_std_icon("MessageBoxWarning")
158
+ self.__threshold = threshold * (1024**2)
159
+ self.label.setMinimumWidth(self.label.fontMetrics().width("000%"))
160
+ self.update_status()
161
+
162
+ def set_demo_mode(self, state: bool) -> None:
163
+ """Set demo mode state (used when taking screenshots).
164
+ The demo mode allows to take screenshots which always look the same.
165
+ (this will set memory usage to a constant value).
166
+ If demo mode is set to False, memory usage will be set to actual value.
167
+
168
+ Args:
169
+ state (bool): demo mode state
170
+ """
171
+ self.demo_mode = state
172
+ self.update_status()
173
+
174
+ def update_status(self) -> None:
175
+ """Update status widget"""
176
+ mem = psutil.virtual_memory()
177
+ memok = mem.available > self.__threshold
178
+ self.SIG_MEMORY_ALARM.emit(not memok)
179
+ txtlist = [
180
+ f"%s {mem.available // (1024**2)} MB" % _("Memory available:"),
181
+ f"%s {mem.used // (1024**2)} MB" % _("Memory used:"),
182
+ f"%s {self.__threshold // (1024**2)} MB" % _("Alarm threshold:"),
183
+ ]
184
+ txt = os.linesep.join(txtlist)
185
+ self.setToolTip(txt)
186
+ if DEBUG and not memok:
187
+ execenv.log(self, txt)
188
+ self.label.setStyleSheet("" if memok else "color: red")
189
+ self.set_icon("libre-tech-ram.svg" if memok else self.ko_icon)
190
+ mem_percent = 65 if self.demo_mode else int(mem.percent)
191
+ self.label.setText(_("Memory:") + f" {mem_percent}%")
192
+
193
+
194
+ class PluginStatus(BaseStatus):
195
+ """Plugin status widget.
196
+ Shows the number of plugins loaded.
197
+
198
+ Args:
199
+ parent (QWidget): parent widget
200
+ """
201
+
202
+ def __init__(self, parent: QW.QWidget | None = None) -> None:
203
+ super().__init__(None, parent)
204
+ self.set_icon("libre-gui-plugin.svg")
205
+ self.update_status()
206
+
207
+ def update_status(self) -> None:
208
+ """Update status widget"""
209
+ text = _("Plugins:") + " "
210
+ if Conf.main.plugins_enabled.get():
211
+ nplugins = len(PluginRegistry.get_plugins())
212
+ text += str(nplugins)
213
+ else:
214
+ text += "-"
215
+ self.label.setText(text)
216
+ self.setToolTip(PluginRegistry.get_plugin_info())
217
+
218
+
219
+ class XMLRPCStatus(BaseStatus):
220
+ """XML-RPC status widget.
221
+ Shows the XML-RPC server status and port number.
222
+
223
+ Args:
224
+ parent (QWidget): parent widget
225
+ """
226
+
227
+ def __init__(self, parent: QW.QWidget | None = None) -> None:
228
+ super().__init__(None, parent)
229
+ self.port: int | None = None
230
+
231
+ def set_port(self, port: int | None):
232
+ """Set XML-RPC server port number.
233
+
234
+ Args:
235
+ port (int | None): XML-RPC server port number.
236
+ If None, XML-RPC server is disabled.
237
+ """
238
+ self.port = port
239
+ self.update_status()
240
+
241
+ def update_status(self) -> None:
242
+ """Update status widget"""
243
+ text = _("XML-RPC:") + " "
244
+ if self.port is None:
245
+ self.label.setText(text + "-")
246
+ self.set_icon("libre-gui-unlink.svg")
247
+ else:
248
+ self.label.setText(text + str(self.port))
249
+ self.set_icon("libre-gui-link.svg")