datalab-platform 0.0.1.dev0__py3-none-any.whl → 1.0.0__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.0.dist-info/METADATA +121 -0
  490. datalab_platform-1.0.0.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.0.dist-info}/WHEEL +0 -0
  494. {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.0.dist-info}/entry_points.txt +0 -0
  495. {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.0.dist-info}/licenses/LICENSE +0 -0
  496. {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,788 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """Curve fitting dialog widgets"""
4
+
5
+ # pylint: disable=invalid-name # Allows short reference names like x, y, ...
6
+
7
+ import numpy as np
8
+ from guidata.configtools import get_icon
9
+ from guidata.qthelpers import exec_dialog
10
+ from plotpy.plot import PlotOptions
11
+ from plotpy.widgets.fit import FitDialog, FitParam
12
+ from scipy.special import erf # pylint: disable=no-name-in-module
13
+ from sigima.tools.checks import check_1d_arrays
14
+ from sigima.tools.signal import fitting, fourier, pulse
15
+
16
+ from datalab.config import Conf, _
17
+
18
+ DEFAULT_FORMAT = "%g"
19
+
20
+
21
+ def guifit(
22
+ x,
23
+ y,
24
+ fitfunc,
25
+ fitparams,
26
+ fitargs=None,
27
+ fitkwargs=None,
28
+ wintitle=None,
29
+ title=None,
30
+ xlabel=None,
31
+ ylabel=None,
32
+ param_cols=1,
33
+ auto_fit=True,
34
+ winsize=None,
35
+ winpos=None,
36
+ parent=None,
37
+ name=None,
38
+ ): # pylint: disable=too-many-positional-arguments
39
+ """GUI-based curve fitting tool"""
40
+ win = FitDialog(
41
+ edit=True,
42
+ title=wintitle,
43
+ icon=None,
44
+ toolbar=True,
45
+ options=PlotOptions(
46
+ title=title,
47
+ xlabel=xlabel,
48
+ ylabel=ylabel,
49
+ curve_antialiasing=True,
50
+ show_axes_tab=False,
51
+ autoscale_margin_percent=Conf.view.sig_autoscale_margin_percent.get(),
52
+ ),
53
+ parent=parent,
54
+ param_cols=param_cols,
55
+ auto_fit=auto_fit,
56
+ )
57
+ win.setObjectName(name)
58
+ win.set_data(x, y, fitfunc, fitparams, fitargs, fitkwargs)
59
+ try:
60
+ win.autofit() # TODO: [P3] make this optional
61
+ except ValueError:
62
+ pass
63
+ if parent is None:
64
+ win.setWindowIcon(get_icon("DataLab.svg"))
65
+ if winsize is not None:
66
+ win.resize(*winsize)
67
+ if winpos is not None:
68
+ win.move(*winpos)
69
+ win.get_plot().do_autoscale()
70
+ if exec_dialog(win):
71
+ return win.get_values()
72
+ return None
73
+
74
+
75
+ # --- Polynomial fitting curve -------------------------------------------------
76
+ def polynomial_fit(x, y, degree, parent=None, name=None):
77
+ """Compute polynomial fit
78
+
79
+ Returns (yfit, params), where yfit is the fitted curve and params are
80
+ the fitting parameters"""
81
+ ivals = np.polyfit(x, y, degree)
82
+
83
+ params = []
84
+ for index in range(degree + 1):
85
+ val = ivals[index]
86
+ vmax = max(1.0, np.abs(val))
87
+ param = FitParam(
88
+ f"c{(len(ivals) - index - 1):d}",
89
+ val,
90
+ -2 * vmax,
91
+ 2 * vmax,
92
+ format=DEFAULT_FORMAT,
93
+ )
94
+ params.append(param)
95
+
96
+ def fitfunc(x, params):
97
+ return np.polyval(params, x)
98
+
99
+ values = guifit(
100
+ x, y, fitfunc, params, parent=parent, wintitle=_("Polymomial fit"), name=name
101
+ )
102
+ if values:
103
+ return fitfunc(x, values), params
104
+
105
+
106
+ def linear_fit(x: np.ndarray, y: np.ndarray, parent=None, name=None):
107
+ """Compute linear fit using polynomialfit.
108
+
109
+ Returns (yfit, params), where yfit is the fitted curve and params are
110
+ the fitting parameters
111
+ """
112
+ return polynomial_fit(x, y, 1, parent=parent, name=name)
113
+
114
+
115
+ # --- Gaussian fitting curve ---------------------------------------------------
116
+ def gaussian_fit(x, y, parent=None, name=None):
117
+ """Compute Gaussian fit
118
+
119
+ Returns (yfit, params), where yfit is the fitted curve and params are
120
+ the fitting parameters"""
121
+ # Get initial parameter estimates from Sigima GaussianFitComputer
122
+ computer = fitting.GaussianFitComputer(x, y)
123
+ initial_params = computer.compute_initial_params()
124
+ amp_guess = initial_params["amp"]
125
+ sigma_guess = initial_params["sigma"]
126
+ mu_guess = initial_params["x0"]
127
+ b_guess = initial_params["y0"]
128
+
129
+ dy = np.max(y) - np.min(y)
130
+ max_amp = amp_guess * 2.0 if amp_guess > 0 else dy
131
+ a = FitParam(_("Amplitude"), amp_guess, 0.0, max_amp, format=DEFAULT_FORMAT)
132
+ b = FitParam(
133
+ _("Base line"), b_guess, np.min(y) - 0.1 * dy, np.max(y), format=DEFAULT_FORMAT
134
+ )
135
+ sigma = FitParam(
136
+ _("Std-dev") + " (σ)",
137
+ sigma_guess,
138
+ sigma_guess * 0.1,
139
+ sigma_guess * 10,
140
+ format=DEFAULT_FORMAT,
141
+ )
142
+ mu = FitParam(
143
+ _("Mean") + " (μ)", mu_guess, np.min(x), np.max(x), format=DEFAULT_FORMAT
144
+ )
145
+
146
+ params = [a, sigma, mu, b]
147
+
148
+ def fitfunc(x, params):
149
+ return pulse.GaussianModel.func(x, *params)
150
+
151
+ values = guifit(
152
+ x, y, fitfunc, params, parent=parent, wintitle=_("Gaussian fit"), name=name
153
+ )
154
+ if values:
155
+ return fitfunc(x, values), params
156
+
157
+
158
+ # --- Lorentzian fitting curve -------------------------------------------------
159
+ def lorentzian_fit(x, y, parent=None, name=None):
160
+ """Compute Lorentzian fit
161
+
162
+ Returns (yfit, params), where yfit is the fitted curve and params are
163
+ the fitting parameters"""
164
+ # Get initial parameter estimates from Sigima LorentzianFitComputer
165
+ computer = fitting.LorentzianFitComputer(x, y)
166
+ initial_params = computer.compute_initial_params()
167
+ amp_guess = initial_params["amp"]
168
+ sigma_guess = initial_params["sigma"]
169
+ mu_guess = initial_params["x0"]
170
+ b_guess = initial_params["y0"]
171
+
172
+ # Create parameter bounds
173
+ dy = np.max(y) - np.min(y)
174
+
175
+ max_amp = amp_guess * 2.0 if amp_guess > 0 else dy
176
+ a = FitParam(_("Amplitude"), amp_guess, 0.0, max_amp, format=DEFAULT_FORMAT)
177
+ b = FitParam(
178
+ _("Base line"), b_guess, np.min(y) - 0.1 * dy, np.max(y), format=DEFAULT_FORMAT
179
+ )
180
+ sigma = FitParam(
181
+ _("Std-dev") + " (σ)",
182
+ sigma_guess,
183
+ sigma_guess * 0.1,
184
+ sigma_guess * 10,
185
+ format=DEFAULT_FORMAT,
186
+ )
187
+ mu = FitParam(
188
+ _("Mean") + " (μ)", mu_guess, np.min(x), np.max(x), format=DEFAULT_FORMAT
189
+ )
190
+
191
+ params = [a, sigma, mu, b]
192
+
193
+ def fitfunc(x, params):
194
+ return pulse.LorentzianModel.func(x, *params)
195
+
196
+ values = guifit(
197
+ x, y, fitfunc, params, parent=parent, wintitle=_("Lorentzian fit"), name=name
198
+ )
199
+ if values:
200
+ return fitfunc(x, values), params
201
+
202
+
203
+ # --- Voigt fitting curve ------------------------------------------------------
204
+ def voigt_fit(x, y, parent=None, name=None):
205
+ """Compute Voigt fit
206
+
207
+ Returns (yfit, params), where yfit is the fitted curve and params are
208
+ the fitting parameters"""
209
+ # Get initial parameter estimates from Sigima VoigtFitComputer
210
+ computer = fitting.VoigtFitComputer(x, y)
211
+ initial_params = computer.compute_initial_params()
212
+ amp_guess = initial_params["amp"]
213
+ sigma_guess = initial_params["sigma"]
214
+ mu_guess = initial_params["x0"]
215
+ b_guess = initial_params["y0"]
216
+
217
+ # Create parameter bounds
218
+ dy = np.max(y) - np.min(y)
219
+
220
+ max_amp = amp_guess * 2.0 if amp_guess > 0 else dy
221
+ a = FitParam(_("Amplitude"), amp_guess, 0.0, max_amp, format=DEFAULT_FORMAT)
222
+ b = FitParam(
223
+ _("Base line"), b_guess, np.min(y) - 0.1 * dy, np.max(y), format=DEFAULT_FORMAT
224
+ )
225
+ sigma = FitParam(
226
+ _("Std-dev") + " (σ)",
227
+ sigma_guess,
228
+ sigma_guess * 0.1,
229
+ sigma_guess * 10,
230
+ format=DEFAULT_FORMAT,
231
+ )
232
+ mu = FitParam(
233
+ _("Mean") + " (μ)", mu_guess, np.min(x), np.max(x), format=DEFAULT_FORMAT
234
+ )
235
+
236
+ params = [a, sigma, mu, b]
237
+
238
+ def fitfunc(x, params):
239
+ return pulse.VoigtModel.func(x, *params)
240
+
241
+ values = guifit(
242
+ x, y, fitfunc, params, parent=parent, wintitle=_("Voigt fit"), name=name
243
+ )
244
+ if values:
245
+ return fitfunc(x, values), params
246
+
247
+
248
+ # --- Multi-Gaussian fitting curve ---------------------------------------------
249
+ def multigaussian(x, *values, **kwargs):
250
+ """Return a 1-dimensional multi-Gaussian function."""
251
+ a_amp = values[0::2]
252
+ a_sigma = values[1::2]
253
+ y0 = values[-1]
254
+ a_x0 = kwargs["a_x0"]
255
+ y = np.zeros_like(x) + y0
256
+ for amp, sigma, x0 in zip(a_amp, a_sigma, a_x0):
257
+ y += amp * np.exp(-0.5 * ((x - x0) / sigma) ** 2)
258
+ return y
259
+
260
+
261
+ def multigaussian_fit(x, y, peak_indices, parent=None, name=None):
262
+ """Compute Multi-Gaussian fit
263
+
264
+ Returns (yfit, params), where yfit is the fitted curve and params are
265
+ the fitting parameters"""
266
+ # Get initial parameter estimates from Sigima MultiGaussianFitComputer
267
+ computer = fitting.MultiGaussianFitComputer(x, y, peak_indices)
268
+ initial_params = computer.compute_initial_params()
269
+ # Use Sigima parameters to populate DataLab params
270
+ params = []
271
+ for index, i0 in enumerate(peak_indices):
272
+ stri = f"{index + 1:02d}"
273
+ amp_key = f"amp_{index + 1}"
274
+ sigma_key = f"sigma_{index + 1}"
275
+ amp_val = initial_params[amp_key] if amp_key in initial_params else y[i0]
276
+ sigma_val = (
277
+ initial_params[sigma_key]
278
+ if sigma_key in initial_params
279
+ else (x.max() - x.min()) / 100
280
+ )
281
+
282
+ # Calculate bounds based on local data
283
+ istart = 0
284
+ iend = len(x) - 1
285
+ if index > 0:
286
+ istart = (peak_indices[index - 1] + i0) // 2
287
+ if index < len(peak_indices) - 1:
288
+ iend = (peak_indices[index + 1] + i0) // 2
289
+ dx = 0.5 * (x[iend] - x[istart])
290
+ dy = np.max(y[istart:iend]) - np.min(y[istart:iend])
291
+
292
+ params += [
293
+ FitParam(
294
+ ("A") + stri,
295
+ amp_val,
296
+ 0.0,
297
+ max(dy * 2, amp_val * 2),
298
+ format=DEFAULT_FORMAT,
299
+ ),
300
+ FitParam("σ" + stri, sigma_val, dx / 100, dx, format=DEFAULT_FORMAT),
301
+ ]
302
+
303
+ y0_val = initial_params.get("y0", np.min(y))
304
+ params.append(
305
+ FitParam(
306
+ _("Y0"),
307
+ y0_val,
308
+ np.min(y) - 0.1 * (np.max(y) - np.min(y)),
309
+ np.max(y),
310
+ format=DEFAULT_FORMAT,
311
+ )
312
+ )
313
+
314
+ kwargs = {"a_x0": x[peak_indices]}
315
+
316
+ def fitfunc(xi, params):
317
+ return multigaussian(xi, *params, **kwargs)
318
+
319
+ param_cols = 1
320
+ if len(params) > 8:
321
+ param_cols = 4
322
+ values = guifit(
323
+ x,
324
+ y,
325
+ fitfunc,
326
+ params,
327
+ param_cols=param_cols,
328
+ winsize=(900, 600),
329
+ parent=parent,
330
+ name=name,
331
+ wintitle=_("Multi-Gaussian fit"),
332
+ )
333
+ if values:
334
+ return fitfunc(x, values), params
335
+
336
+
337
+ # --- Multi-Lorentzian fitting curve -------------------------------------------
338
+ def multilorentzian(x, *values, **kwargs):
339
+ """Return a 1-dimensional multi-Lorentzian function."""
340
+ a_amp = values[0::2]
341
+ a_sigma = values[1::2]
342
+ y0 = values[-1]
343
+ a_x0 = kwargs["a_x0"]
344
+ y = np.zeros_like(x) + y0
345
+ for amp, sigma, x0 in zip(a_amp, a_sigma, a_x0):
346
+ y += pulse.LorentzianModel.func(x, amp, sigma, x0, 0)
347
+ return y
348
+
349
+
350
+ def multilorentzian_fit(
351
+ x: np.ndarray, y: np.ndarray, peak_indices, parent=None, name=None
352
+ ):
353
+ """Compute Multi-Lorentzian fit
354
+
355
+ Returns (yfit, params), where yfit is the fitted curve and params are
356
+ the fitting parameters"""
357
+ # Get initial parameter estimates from Sigima MultiLorentzianFitComputer
358
+ computer = fitting.MultiLorentzianFitComputer(x, y, peak_indices)
359
+ initial_params = computer.compute_initial_params()
360
+ # Use Sigima parameters to populate DataLab params
361
+ params = []
362
+ for index, i0 in enumerate(peak_indices):
363
+ stri = f"{index + 1:02d}"
364
+ amp_key = f"amp_{index + 1}"
365
+ sigma_key = f"sigma_{index + 1}"
366
+ amp_val = (
367
+ initial_params[amp_key]
368
+ if amp_key in initial_params
369
+ else pulse.LorentzianModel.get_amp_from_amplitude(
370
+ y[i0] - np.min(y), (x.max() - x.min()) / 100
371
+ )
372
+ )
373
+ sigma_val = (
374
+ initial_params[sigma_key]
375
+ if sigma_key in initial_params
376
+ else (x.max() - x.min()) / 100
377
+ )
378
+
379
+ params += [
380
+ FitParam(
381
+ ("A") + stri,
382
+ amp_val,
383
+ 0.0,
384
+ max(amp_val * 1.2, y[i0] * 1.2),
385
+ format=DEFAULT_FORMAT,
386
+ ),
387
+ FitParam(
388
+ "σ" + stri,
389
+ sigma_val,
390
+ sigma_val * 0.2,
391
+ sigma_val * 10,
392
+ format=DEFAULT_FORMAT,
393
+ ),
394
+ ]
395
+
396
+ y0_val = initial_params.get("y0", np.min(y))
397
+ params.append(
398
+ FitParam(
399
+ _("Y0"),
400
+ y0_val,
401
+ np.min(y) - 0.1 * (np.max(y) - np.min(y)),
402
+ np.max(y),
403
+ format=DEFAULT_FORMAT,
404
+ )
405
+ )
406
+
407
+ kwargs = {"a_x0": x[peak_indices]}
408
+
409
+ def fitfunc(xi, params):
410
+ return multilorentzian(xi, *params, **kwargs)
411
+
412
+ param_cols = 1
413
+ if len(params) > 8:
414
+ param_cols = 4
415
+ values = guifit(
416
+ x,
417
+ y,
418
+ fitfunc,
419
+ params,
420
+ param_cols=param_cols,
421
+ winsize=(900, 600),
422
+ parent=parent,
423
+ name=name,
424
+ wintitle=_("Multi-Lorentzian fit"),
425
+ )
426
+ if values:
427
+ return fitfunc(x, values), params
428
+
429
+
430
+ # --- Exponential fitting curve ------------------------------------------------
431
+
432
+
433
+ def exponential_fit(x: np.ndarray, y: np.ndarray, parent=None, name=None):
434
+ """Compute exponential fit
435
+
436
+ Returns (yfit, params), where yfit is the fitted curve and params are
437
+ the fitting parameters"""
438
+ # Get initial parameter estimates from Sigima ExponentialFitComputer
439
+ computer = fitting.ExponentialFitComputer(x, y)
440
+ initial_params = computer.compute_initial_params()
441
+ oa = initial_params["a"]
442
+ ob = initial_params["b"]
443
+ oc = initial_params["y0"]
444
+
445
+ # Create parameter bounds
446
+ moa, mob, moc = np.maximum(1, [abs(oa), abs(ob), abs(oc)])
447
+ a_p = FitParam(
448
+ _("A coefficient"), oa, -2 * moa, 2 * moa, logscale=True, format=DEFAULT_FORMAT
449
+ )
450
+ b_p = FitParam(_("B coefficient"), ob, 0.5 * mob, 1.5 * mob, format=DEFAULT_FORMAT)
451
+ c_p = FitParam(_("y0 constant"), oc, -2 * moc, 2 * moc, format=DEFAULT_FORMAT)
452
+
453
+ params = [a_p, b_p, c_p]
454
+
455
+ def modelfunc(x, a, b, c):
456
+ return a * np.exp(b * x) + c
457
+
458
+ def fitfunc(x, params):
459
+ return modelfunc(x, *params)
460
+
461
+ values = guifit(
462
+ x, y, fitfunc, params, parent=parent, wintitle=_("Exponential fit"), name=name
463
+ )
464
+ if values:
465
+ return fitfunc(x, values), params
466
+
467
+
468
+ # --- Sinusoidal fitting curve ------------------------------------------------
469
+
470
+
471
+ @check_1d_arrays(x_evenly_spaced=True)
472
+ def dominant_frequency(x: np.ndarray, y: np.ndarray) -> np.floating:
473
+ """Find the dominant frequency.
474
+
475
+ Args:
476
+ x: 1-D x values.
477
+ y: 1-D y values.
478
+
479
+ Returns:
480
+ Dominant frequency.
481
+ """
482
+ f, spectrum = fourier.magnitude_spectrum(x, y)
483
+ return np.abs(f[np.argmax(spectrum)])
484
+
485
+
486
+ def sinusoidal_fit(x: np.ndarray, y: np.ndarray, parent=None, name=None):
487
+ """Compute sinusoidal fit
488
+
489
+ Returns (yfit, params), where yfit is the fitted curve and params are
490
+ the fitting parameters"""
491
+ # Get initial parameter estimates from Sigima SinusoidalFitComputer
492
+ computer = fitting.SinusoidalFitComputer(x, y)
493
+ initial_params = computer.compute_initial_params()
494
+ guess_a = initial_params["amplitude"]
495
+ guess_f = initial_params["frequency"]
496
+ guess_ph = np.rad2deg(initial_params["phase"]) # Convert to degrees
497
+ guess_c = initial_params["offset"]
498
+
499
+ # Create parameter bounds
500
+ abs_values = [abs(guess_a), abs(guess_f), abs(guess_ph), abs(guess_c)]
501
+ moa, mof, _mop, moc = np.maximum(1, abs_values)
502
+ a_p = FitParam(_("Amplitude"), guess_a, -2 * moa, 2 * moa, format=DEFAULT_FORMAT)
503
+ f_p = FitParam(_("Frequency"), guess_f, 0, 2 * mof, format=DEFAULT_FORMAT)
504
+ p_p = FitParam(_("Phase"), guess_ph, -360, 360, format=DEFAULT_FORMAT)
505
+ c_p = FitParam(
506
+ _("Continuous component"), guess_c, -2 * moc, 2 * moc, format=DEFAULT_FORMAT
507
+ )
508
+
509
+ params = [a_p, f_p, p_p, c_p]
510
+
511
+ def modelfunc(x, a, f, p, c):
512
+ return a * np.sin(2 * np.pi * f * x + np.deg2rad(p)) + c
513
+
514
+ def fitfunc(x, params):
515
+ return modelfunc(x, *params)
516
+
517
+ values = guifit(
518
+ x, y, fitfunc, params, parent=parent, wintitle=_("Sinusoidal fit"), name=name
519
+ )
520
+ if values:
521
+ return fitfunc(x, values), params
522
+
523
+
524
+ # --- Cumulative distribution function fitting curve -----------------------------------
525
+
526
+
527
+ def cdf_fit(x: np.ndarray, y: np.ndarray, parent=None, name=None):
528
+ """Compute Cumulative Distribution Function (CDF) fit
529
+
530
+ Returns (yfit, params), where yfit is the fitted curve and params are
531
+ the fitting parameters"""
532
+ # Get initial parameter estimates from Sigima CDFFitComputer
533
+ computer = fitting.CDFFitComputer(x, y)
534
+ initial_params = computer.compute_initial_params()
535
+ a_guess = initial_params["amplitude"]
536
+ mu_guess = initial_params["mu"]
537
+ sigma_guess = initial_params["sigma"]
538
+ b_guess = initial_params["baseline"]
539
+
540
+ # Create parameter bounds
541
+ dy = np.max(y) - np.min(y)
542
+ abs_values = [abs(a_guess), abs(mu_guess), abs(sigma_guess), abs(b_guess)]
543
+ iamp, ix0, islope, _ioff = np.maximum(1, abs_values)
544
+ a = FitParam(_("Amplitude"), a_guess, 0, iamp * 2.0, format=DEFAULT_FORMAT)
545
+ b = FitParam(
546
+ _("Base line"), b_guess, np.min(y) - 0.1 * dy, np.max(y), format=DEFAULT_FORMAT
547
+ )
548
+ sigma = FitParam(
549
+ _("Std-dev") + " (σ)",
550
+ sigma_guess,
551
+ islope * 0.1,
552
+ islope * 2,
553
+ format=DEFAULT_FORMAT,
554
+ )
555
+ mu = FitParam(
556
+ _("Mean") + " (μ)", mu_guess, ix0 * 0.2, ix0 * 2, format=DEFAULT_FORMAT
557
+ )
558
+
559
+ params = [a, mu, sigma, b]
560
+
561
+ def modelfunc(x, a, mu, sigma, b):
562
+ return a * erf((x - mu) / (sigma * np.sqrt(2))) + b
563
+
564
+ def fitfunc(x, params):
565
+ return modelfunc(x, *params)
566
+
567
+ values = guifit(
568
+ x,
569
+ y,
570
+ fitfunc,
571
+ params,
572
+ parent=parent,
573
+ wintitle=_("CDF fit"),
574
+ name=name,
575
+ )
576
+ if values:
577
+ return fitfunc(x, values), params
578
+
579
+
580
+ # --- Planckian fitting curve --------------------------------------------------
581
+ def planckian_fit(x: np.ndarray, y: np.ndarray, parent=None, name=None):
582
+ """Compute Planckian (blackbody radiation) fit
583
+
584
+ Returns (yfit, params), where yfit is the fitted curve and params are
585
+ the fitting parameters"""
586
+ # Get initial parameter estimates from Sigima PlanckianFitComputer
587
+ computer = fitting.PlanckianFitComputer(x, y)
588
+ initial_params = computer.compute_initial_params()
589
+ amp_guess = initial_params["amp"]
590
+ x0_guess = initial_params["x0"]
591
+ sigma_guess = initial_params["sigma"]
592
+ y0_guess = initial_params["y0"]
593
+
594
+ # Create parameter bounds
595
+ dy = np.max(y) - np.min(y)
596
+
597
+ # Parameter bounds with appropriate ranges for Planckian fitting
598
+ amp = FitParam(
599
+ _("Amplitude"),
600
+ amp_guess,
601
+ amp_guess * 0.01,
602
+ amp_guess * 100,
603
+ format=DEFAULT_FORMAT,
604
+ )
605
+ x0 = FitParam(
606
+ _("Peak wavelength"), x0_guess, np.min(x), np.max(x), format=DEFAULT_FORMAT
607
+ )
608
+ sigma = FitParam(_("Width factor"), sigma_guess, 0.1, 5.0, format=DEFAULT_FORMAT)
609
+ y0 = FitParam(
610
+ _("Base line"),
611
+ y0_guess,
612
+ y0_guess - 0.2 * dy,
613
+ y0_guess + 0.2 * dy,
614
+ format=DEFAULT_FORMAT,
615
+ )
616
+
617
+ params = [amp, x0, sigma, y0]
618
+
619
+ def fitfunc(x, params: list[float]) -> np.ndarray:
620
+ """Evaluate Planckian function with given parameters."""
621
+ return fitting.PlanckianFitComputer.evaluate(x, *params)
622
+
623
+ values = guifit(
624
+ x, y, fitfunc, params, parent=parent, wintitle=_("Planckian fit"), name=name
625
+ )
626
+ if values:
627
+ return fitfunc(x, values), params
628
+
629
+
630
+ # --- Two half-Gaussian fitting curve ------------------------------------------
631
+ def twohalfgaussian_fit(x: np.ndarray, y: np.ndarray, parent=None, name=None):
632
+ """Compute two half-Gaussian fit for asymmetric peaks
633
+
634
+ Returns (yfit, params), where yfit is the fitted curve and params are
635
+ the fitting parameters"""
636
+ # Get initial parameter estimates from Sigima TwoHalfGaussianFitComputer
637
+ computer = fitting.TwoHalfGaussianFitComputer(x, y)
638
+ initial_params = computer.compute_initial_params()
639
+ amp_left_guess = initial_params["amp_left"]
640
+ amp_right_guess = initial_params["amp_right"]
641
+ sigma_left_guess = initial_params["sigma_left"]
642
+ sigma_right_guess = initial_params["sigma_right"]
643
+ x0_guess = initial_params["x0"]
644
+ y0_left_guess = initial_params["y0_left"]
645
+ y0_right_guess = initial_params["y0_right"]
646
+
647
+ # Create parameter bounds
648
+ dx = np.max(x) - np.min(x)
649
+ dy = np.max(y) - np.min(y)
650
+
651
+ # Parameter bounds with better ranges
652
+ # New model signature: func(x, amp_left, amp_right, sigma_left,
653
+ # sigma_right, x0, y0_left, y0_right)
654
+ amp_left = FitParam(
655
+ _("Left amplitude"), amp_left_guess, dy * 0.1, dy * 3, format=DEFAULT_FORMAT
656
+ )
657
+ amp_right = FitParam(
658
+ _("Right amplitude"), amp_right_guess, dy * 0.1, dy * 3, format=DEFAULT_FORMAT
659
+ )
660
+ sigma_left = FitParam(
661
+ _("Left width") + " (σL)",
662
+ sigma_left_guess,
663
+ dx * 0.001, # Very small minimum
664
+ dx * 0.5, # Reasonable maximum
665
+ format=DEFAULT_FORMAT,
666
+ )
667
+ sigma_right = FitParam(
668
+ _("Right width") + " (σR)",
669
+ sigma_right_guess,
670
+ dx * 0.001, # Very small minimum
671
+ dx * 0.5, # Reasonable maximum
672
+ format=DEFAULT_FORMAT,
673
+ )
674
+ x0 = FitParam(
675
+ _("Center") + " (x₀)", x0_guess, np.min(x), np.max(x), format=DEFAULT_FORMAT
676
+ )
677
+ y0_left = FitParam(
678
+ _("Left baseline"),
679
+ y0_left_guess,
680
+ y0_left_guess - 0.2 * dy,
681
+ y0_left_guess + 0.2 * dy,
682
+ format=DEFAULT_FORMAT,
683
+ )
684
+ y0_right = FitParam(
685
+ _("Right baseline"),
686
+ y0_right_guess,
687
+ y0_right_guess - 0.2 * dy,
688
+ y0_right_guess + 0.2 * dy,
689
+ format=DEFAULT_FORMAT,
690
+ )
691
+
692
+ params = [amp_left, amp_right, sigma_left, sigma_right, x0, y0_left, y0_right]
693
+
694
+ def fitfunc(x, params):
695
+ return fitting.TwoHalfGaussianFitComputer.evaluate(x, *params)
696
+
697
+ values = guifit(
698
+ x,
699
+ y,
700
+ fitfunc,
701
+ params,
702
+ parent=parent,
703
+ wintitle=_("Two half-Gaussian fit"),
704
+ name=name,
705
+ )
706
+ if values:
707
+ return fitfunc(x, values), params
708
+
709
+
710
+ # --- Piecewise exponential (raise-decay) fitting curve ------------------------
711
+ def piecewiseexponential_fit(x: np.ndarray, y: np.ndarray, parent=None, name=None):
712
+ """Compute piecewise exponential fit (raise-decay)
713
+
714
+ Returns (yfit, params), where yfit is the fitted curve and params are
715
+ the fitting parameters"""
716
+ # Get initial parameter estimates from Sigima DoubleExponentialFitComputer
717
+ computer = fitting.DoubleExponentialFitComputer(x, y)
718
+ initial_params = computer.compute_initial_params()
719
+ x_center_guess = initial_params["x_center"]
720
+ a_left_guess = initial_params["a_left"]
721
+ b_left_guess = initial_params["b_left"]
722
+ a_right_guess = initial_params["a_right"]
723
+ b_right_guess = initial_params["b_right"]
724
+ y0_guess = initial_params["y0"]
725
+
726
+ # Create parameter bounds
727
+ x_min, x_max = float(x.min()), float(x.max())
728
+ y_min, y_max = float(y.min()), float(y.max())
729
+ y_range = y_max - y_min
730
+ x_range = x_max - x_min
731
+
732
+ # Parameter bounds with more realistic ranges
733
+ # New model signature: func(x, x_center, a_left, b_left, a_right, b_right, y0)
734
+ x_center = FitParam(
735
+ _("Center position"), x_center_guess, x_min, x_max, format=DEFAULT_FORMAT
736
+ )
737
+ a_left = FitParam(
738
+ _("Left amplitude"),
739
+ a_left_guess,
740
+ 0.0,
741
+ a_left_guess * 10.0,
742
+ format=DEFAULT_FORMAT,
743
+ )
744
+ b_left = FitParam(
745
+ _("Left time constant") + " (bL)",
746
+ b_left_guess, # Already in coefficient form
747
+ 0.001 / x_range, # Slow decay
748
+ 100.0 / x_range, # Fast decay
749
+ format=DEFAULT_FORMAT,
750
+ )
751
+ a_right = FitParam(
752
+ _("Right amplitude"),
753
+ a_right_guess,
754
+ 0.0,
755
+ a_right_guess * 10.0,
756
+ format=DEFAULT_FORMAT,
757
+ )
758
+ b_right = FitParam(
759
+ _("Right time constant") + " (bR)",
760
+ b_right_guess, # Already in coefficient form
761
+ -100.0 / x_range, # Fast decay
762
+ -0.001 / x_range, # Slow decay
763
+ format=DEFAULT_FORMAT,
764
+ )
765
+ y0 = FitParam(
766
+ _("Base line"),
767
+ y0_guess,
768
+ y0_guess - 0.2 * y_range,
769
+ y0_guess + 0.2 * y_range,
770
+ format=DEFAULT_FORMAT,
771
+ )
772
+
773
+ params = [x_center, a_left, b_left, a_right, b_right, y0]
774
+
775
+ def fitfunc(x, params):
776
+ return fitting.DoubleExponentialFitComputer.evaluate(x, *params)
777
+
778
+ values = guifit(
779
+ x,
780
+ y,
781
+ fitfunc,
782
+ params,
783
+ parent=parent,
784
+ wintitle=_("Piecewise exponential (raise-decay) fit"),
785
+ name=name,
786
+ )
787
+ if values:
788
+ return fitfunc(x, values), params