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.
- datalab/__init__.py +35 -2
- datalab/adapters_metadata/__init__.py +31 -0
- datalab/adapters_metadata/base_adapter.py +316 -0
- datalab/adapters_metadata/common.py +422 -0
- datalab/adapters_metadata/geometry_adapter.py +98 -0
- datalab/adapters_metadata/table_adapter.py +84 -0
- datalab/adapters_plotpy/__init__.py +54 -0
- datalab/adapters_plotpy/annotations.py +124 -0
- datalab/adapters_plotpy/base.py +110 -0
- datalab/adapters_plotpy/converters.py +86 -0
- datalab/adapters_plotpy/factories.py +80 -0
- datalab/adapters_plotpy/objects/__init__.py +0 -0
- datalab/adapters_plotpy/objects/base.py +197 -0
- datalab/adapters_plotpy/objects/image.py +157 -0
- datalab/adapters_plotpy/objects/scalar.py +565 -0
- datalab/adapters_plotpy/objects/signal.py +264 -0
- datalab/adapters_plotpy/roi/__init__.py +0 -0
- datalab/adapters_plotpy/roi/base.py +146 -0
- datalab/adapters_plotpy/roi/factory.py +93 -0
- datalab/adapters_plotpy/roi/image.py +207 -0
- datalab/adapters_plotpy/roi/signal.py +72 -0
- datalab/app.py +98 -0
- datalab/config.py +817 -0
- datalab/control/__init__.py +0 -0
- datalab/control/baseproxy.py +776 -0
- datalab/control/proxy.py +343 -0
- datalab/control/remote.py +1005 -0
- datalab/data/doc/DataLab_en.pdf +0 -0
- datalab/data/doc/DataLab_fr.pdf +0 -0
- datalab/data/icons/analysis/delete_results.svg +109 -0
- datalab/data/icons/analysis/fw1e2.svg +156 -0
- datalab/data/icons/analysis/fwhm.svg +156 -0
- datalab/data/icons/analysis/histogram.svg +49 -0
- datalab/data/icons/analysis/peak_detect.svg +160 -0
- datalab/data/icons/analysis/plot_results.svg +151 -0
- datalab/data/icons/analysis/show_results.svg +83 -0
- datalab/data/icons/analysis/stats.svg +49 -0
- datalab/data/icons/analysis.svg +120 -0
- datalab/data/icons/apply.svg +3 -0
- datalab/data/icons/check_all.svg +15 -0
- datalab/data/icons/collapse.svg +44 -0
- datalab/data/icons/collapse_selection.svg +63 -0
- datalab/data/icons/console.svg +101 -0
- datalab/data/icons/create/1d-normal.svg +8 -0
- datalab/data/icons/create/1d-poisson.svg +9 -0
- datalab/data/icons/create/1d-uniform.svg +8 -0
- datalab/data/icons/create/1d-zero.svg +57 -0
- datalab/data/icons/create/2d-gaussian.svg +56 -0
- datalab/data/icons/create/2d-normal.svg +38 -0
- datalab/data/icons/create/2d-poisson.svg +38 -0
- datalab/data/icons/create/2d-ramp.svg +90 -0
- datalab/data/icons/create/2d-sinc.svg +62 -0
- datalab/data/icons/create/2d-uniform.svg +38 -0
- datalab/data/icons/create/2d-zero.svg +13 -0
- datalab/data/icons/create/checkerboard.svg +39 -0
- datalab/data/icons/create/cosine.svg +12 -0
- datalab/data/icons/create/exponential.svg +55 -0
- datalab/data/icons/create/gaussian.svg +12 -0
- datalab/data/icons/create/grating.svg +29 -0
- datalab/data/icons/create/linear_chirp.svg +7 -0
- datalab/data/icons/create/logistic.svg +7 -0
- datalab/data/icons/create/lorentzian.svg +12 -0
- datalab/data/icons/create/planck.svg +12 -0
- datalab/data/icons/create/polynomial.svg +7 -0
- datalab/data/icons/create/pulse.svg +12 -0
- datalab/data/icons/create/ring.svg +18 -0
- datalab/data/icons/create/sawtooth.svg +7 -0
- datalab/data/icons/create/siemens.svg +35 -0
- datalab/data/icons/create/sinc.svg +12 -0
- datalab/data/icons/create/sine.svg +7 -0
- datalab/data/icons/create/square.svg +7 -0
- datalab/data/icons/create/square_pulse.svg +7 -0
- datalab/data/icons/create/step.svg +7 -0
- datalab/data/icons/create/step_pulse.svg +12 -0
- datalab/data/icons/create/triangle.svg +7 -0
- datalab/data/icons/create/voigt.svg +12 -0
- datalab/data/icons/edit/annotations.svg +72 -0
- datalab/data/icons/edit/annotations_copy.svg +114 -0
- datalab/data/icons/edit/annotations_delete.svg +83 -0
- datalab/data/icons/edit/annotations_edit.svg +98 -0
- datalab/data/icons/edit/annotations_export.svg +85 -0
- datalab/data/icons/edit/annotations_import.svg +85 -0
- datalab/data/icons/edit/annotations_paste.svg +100 -0
- datalab/data/icons/edit/copy_titles.svg +109 -0
- datalab/data/icons/edit/delete.svg +84 -0
- datalab/data/icons/edit/delete_all.svg +214 -0
- datalab/data/icons/edit/duplicate.svg +64 -0
- datalab/data/icons/edit/goto_source.svg +60 -0
- datalab/data/icons/edit/metadata.svg +60 -0
- datalab/data/icons/edit/metadata_add.svg +80 -0
- datalab/data/icons/edit/metadata_copy.svg +96 -0
- datalab/data/icons/edit/metadata_delete.svg +62 -0
- datalab/data/icons/edit/metadata_export.svg +68 -0
- datalab/data/icons/edit/metadata_import.svg +68 -0
- datalab/data/icons/edit/metadata_paste.svg +79 -0
- datalab/data/icons/edit/move_down.svg +55 -0
- datalab/data/icons/edit/move_up.svg +54 -0
- datalab/data/icons/edit/new_group.svg +76 -0
- datalab/data/icons/edit/recompute.svg +60 -0
- datalab/data/icons/edit/rename.svg +49 -0
- datalab/data/icons/edit.svg +16 -0
- datalab/data/icons/expand.svg +44 -0
- datalab/data/icons/expand_selection.svg +63 -0
- datalab/data/icons/fit/cdf_fit.svg +56 -0
- datalab/data/icons/fit/exponential_fit.svg +55 -0
- datalab/data/icons/fit/gaussian_fit.svg +62 -0
- datalab/data/icons/fit/interactive_fit.svg +101 -0
- datalab/data/icons/fit/linear_fit.svg +57 -0
- datalab/data/icons/fit/lorentzian_fit.svg +209 -0
- datalab/data/icons/fit/multigaussian_fit.svg +85 -0
- datalab/data/icons/fit/multilorentzian_fit.svg +85 -0
- datalab/data/icons/fit/piecewiseexponential_fit.svg +209 -0
- datalab/data/icons/fit/planckian_fit.svg +62 -0
- datalab/data/icons/fit/polynomial_fit.svg +59 -0
- datalab/data/icons/fit/sigmoid_fit.svg +56 -0
- datalab/data/icons/fit/sinusoidal_fit.svg +72 -0
- datalab/data/icons/fit/twohalfgaussian_fit.svg +63 -0
- datalab/data/icons/fit/voigt_fit.svg +57 -0
- datalab/data/icons/group.svg +56 -0
- datalab/data/icons/h5/h5array.svg +59 -0
- datalab/data/icons/h5/h5attrs.svg +75 -0
- datalab/data/icons/h5/h5browser.svg +133 -0
- datalab/data/icons/h5/h5file.svg +69 -0
- datalab/data/icons/h5/h5group.svg +49 -0
- datalab/data/icons/h5/h5scalar.svg +1 -0
- datalab/data/icons/help_pdf.svg +46 -0
- datalab/data/icons/history.svg +7 -0
- datalab/data/icons/image.svg +135 -0
- datalab/data/icons/io/fileopen_directory.svg +60 -0
- datalab/data/icons/io/fileopen_h5.svg +84 -0
- datalab/data/icons/io/fileopen_ima.svg +187 -0
- datalab/data/icons/io/fileopen_py.svg +123 -0
- datalab/data/icons/io/fileopen_sig.svg +138 -0
- datalab/data/icons/io/filesave_h5.svg +97 -0
- datalab/data/icons/io/filesave_ima.svg +200 -0
- datalab/data/icons/io/filesave_py.svg +136 -0
- datalab/data/icons/io/filesave_sig.svg +151 -0
- datalab/data/icons/io/import_text.svg +144 -0
- datalab/data/icons/io/save_to_directory.svg +134 -0
- datalab/data/icons/io.svg +84 -0
- datalab/data/icons/libre-camera-flash-off.svg +1 -0
- datalab/data/icons/libre-camera-flash-on.svg +1 -0
- datalab/data/icons/libre-gui-about.svg +1 -0
- datalab/data/icons/libre-gui-action-delete.svg +1 -0
- datalab/data/icons/libre-gui-add.svg +1 -0
- datalab/data/icons/libre-gui-arrow-down.svg +1 -0
- datalab/data/icons/libre-gui-arrow-left.svg +1 -0
- datalab/data/icons/libre-gui-arrow-right.svg +1 -0
- datalab/data/icons/libre-gui-arrow-up.svg +1 -0
- datalab/data/icons/libre-gui-close.svg +40 -0
- datalab/data/icons/libre-gui-cogs.svg +1 -0
- datalab/data/icons/libre-gui-globe.svg +1 -0
- datalab/data/icons/libre-gui-help.svg +1 -0
- datalab/data/icons/libre-gui-link.svg +1 -0
- datalab/data/icons/libre-gui-menu.svg +1 -0
- datalab/data/icons/libre-gui-pencil.svg +1 -0
- datalab/data/icons/libre-gui-plugin.svg +1 -0
- datalab/data/icons/libre-gui-questions.svg +1 -0
- datalab/data/icons/libre-gui-settings.svg +1 -0
- datalab/data/icons/libre-gui-unlink.svg +1 -0
- datalab/data/icons/libre-tech-ram.svg +1 -0
- datalab/data/icons/libre-toolbox.svg +1 -0
- datalab/data/icons/logs.svg +1 -0
- datalab/data/icons/markers.svg +74 -0
- datalab/data/icons/menu.svg +13 -0
- datalab/data/icons/new_ima.svg +148 -0
- datalab/data/icons/new_sig.svg +123 -0
- datalab/data/icons/operations/abs.svg +116 -0
- datalab/data/icons/operations/arithmetic.svg +123 -0
- datalab/data/icons/operations/average.svg +124 -0
- datalab/data/icons/operations/complex_from_magnitude_phase.svg +116 -0
- datalab/data/icons/operations/complex_from_real_imag.svg +124 -0
- datalab/data/icons/operations/constant.svg +116 -0
- datalab/data/icons/operations/constant_add.svg +109 -0
- datalab/data/icons/operations/constant_divide.svg +109 -0
- datalab/data/icons/operations/constant_multiply.svg +109 -0
- datalab/data/icons/operations/constant_subtract.svg +109 -0
- datalab/data/icons/operations/convert_dtype.svg +117 -0
- datalab/data/icons/operations/convolution.svg +46 -0
- datalab/data/icons/operations/deconvolution.svg +57 -0
- datalab/data/icons/operations/derivative.svg +127 -0
- datalab/data/icons/operations/difference.svg +52 -0
- datalab/data/icons/operations/division.svg +139 -0
- datalab/data/icons/operations/exp.svg +116 -0
- datalab/data/icons/operations/flip_horizontally.svg +69 -0
- datalab/data/icons/operations/flip_vertically.svg +74 -0
- datalab/data/icons/operations/im.svg +124 -0
- datalab/data/icons/operations/integral.svg +50 -0
- datalab/data/icons/operations/inverse.svg +143 -0
- datalab/data/icons/operations/log10.svg +109 -0
- datalab/data/icons/operations/phase.svg +116 -0
- datalab/data/icons/operations/power.svg +118 -0
- datalab/data/icons/operations/product.svg +124 -0
- datalab/data/icons/operations/profile.svg +379 -0
- datalab/data/icons/operations/profile_average.svg +399 -0
- datalab/data/icons/operations/profile_radial.svg +261 -0
- datalab/data/icons/operations/profile_segment.svg +262 -0
- datalab/data/icons/operations/quadratic_difference.svg +84 -0
- datalab/data/icons/operations/re.svg +124 -0
- datalab/data/icons/operations/rotate_left.svg +72 -0
- datalab/data/icons/operations/rotate_right.svg +72 -0
- datalab/data/icons/operations/signals_to_image.svg +314 -0
- datalab/data/icons/operations/sqrt.svg +110 -0
- datalab/data/icons/operations/std.svg +124 -0
- datalab/data/icons/operations/sum.svg +102 -0
- datalab/data/icons/play_demo.svg +9 -0
- datalab/data/icons/processing/axis_transform.svg +62 -0
- datalab/data/icons/processing/bandpass.svg +79 -0
- datalab/data/icons/processing/bandstop.svg +71 -0
- datalab/data/icons/processing/binning.svg +126 -0
- datalab/data/icons/processing/clip.svg +119 -0
- datalab/data/icons/processing/detrending.svg +173 -0
- datalab/data/icons/processing/distribute_on_grid.svg +769 -0
- datalab/data/icons/processing/edge_detection.svg +46 -0
- datalab/data/icons/processing/erase.svg +1 -0
- datalab/data/icons/processing/exposure.svg +143 -0
- datalab/data/icons/processing/fourier.svg +104 -0
- datalab/data/icons/processing/highpass.svg +59 -0
- datalab/data/icons/processing/interpolation.svg +71 -0
- datalab/data/icons/processing/level_adjustment.svg +70 -0
- datalab/data/icons/processing/lowpass.svg +60 -0
- datalab/data/icons/processing/morphology.svg +49 -0
- datalab/data/icons/processing/noise_addition.svg +114 -0
- datalab/data/icons/processing/noise_reduction.svg +38 -0
- datalab/data/icons/processing/normalize.svg +84 -0
- datalab/data/icons/processing/offset_correction.svg +131 -0
- datalab/data/icons/processing/resampling1d.svg +101 -0
- datalab/data/icons/processing/resampling2d.svg +240 -0
- datalab/data/icons/processing/reset_positions.svg +185 -0
- datalab/data/icons/processing/resize.svg +9 -0
- datalab/data/icons/processing/reverse_signal_x.svg +171 -0
- datalab/data/icons/processing/stability.svg +11 -0
- datalab/data/icons/processing/swap_x_y.svg +65 -0
- datalab/data/icons/processing/thresholding.svg +63 -0
- datalab/data/icons/processing/windowing.svg +45 -0
- datalab/data/icons/properties.svg +26 -0
- datalab/data/icons/reset.svg +9 -0
- datalab/data/icons/restore.svg +40 -0
- datalab/data/icons/roi/roi.svg +76 -0
- datalab/data/icons/roi/roi_coordinate.svg +78 -0
- datalab/data/icons/roi/roi_copy.svg +112 -0
- datalab/data/icons/roi/roi_delete.svg +81 -0
- datalab/data/icons/roi/roi_export.svg +87 -0
- datalab/data/icons/roi/roi_graphical.svg +78 -0
- datalab/data/icons/roi/roi_grid.svg +67 -0
- datalab/data/icons/roi/roi_ima.svg +188 -0
- datalab/data/icons/roi/roi_import.svg +87 -0
- datalab/data/icons/roi/roi_new.svg +81 -0
- datalab/data/icons/roi/roi_new_circle.svg +95 -0
- datalab/data/icons/roi/roi_new_polygon.svg +110 -0
- datalab/data/icons/roi/roi_new_rectangle.svg +70 -0
- datalab/data/icons/roi/roi_paste.svg +98 -0
- datalab/data/icons/roi/roi_sig.svg +124 -0
- datalab/data/icons/shapes.svg +134 -0
- datalab/data/icons/signal.svg +103 -0
- datalab/data/icons/table.svg +85 -0
- datalab/data/icons/table_unavailable.svg +102 -0
- datalab/data/icons/to_signal.svg +124 -0
- datalab/data/icons/tour/next.svg +44 -0
- datalab/data/icons/tour/previous.svg +44 -0
- datalab/data/icons/tour/rewind.svg +51 -0
- datalab/data/icons/tour/stop.svg +47 -0
- datalab/data/icons/tour/tour.svg +16 -0
- datalab/data/icons/uncheck_all.svg +78 -0
- datalab/data/icons/view/curve_antialiasing.svg +50 -0
- datalab/data/icons/view/new_window.svg +98 -0
- datalab/data/icons/view/refresh-auto.svg +57 -0
- datalab/data/icons/view/refresh-manual.svg +51 -0
- datalab/data/icons/view/reset_curve_styles.svg +96 -0
- datalab/data/icons/view/show_first.svg +55 -0
- datalab/data/icons/view/show_titles.svg +46 -0
- datalab/data/icons/visualization.svg +51 -0
- datalab/data/logo/DataLab-Banner-150.png +0 -0
- datalab/data/logo/DataLab-Banner-200.png +0 -0
- datalab/data/logo/DataLab-Banner2-100.png +0 -0
- datalab/data/logo/DataLab-Splash.png +0 -0
- datalab/data/logo/DataLab-watermark.png +0 -0
- datalab/data/logo/DataLab.svg +83 -0
- datalab/data/tests/reordering_test.h5 +0 -0
- datalab/data/tutorials/fabry_perot/fabry-perot1.jpg +0 -0
- datalab/data/tutorials/fabry_perot/fabry-perot2.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_13.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_18.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_23.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_30.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_35.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_40.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_45.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_50.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_55.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_60.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_65.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_70.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_75.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_80.jpg +0 -0
- datalab/env.py +542 -0
- datalab/gui/__init__.py +89 -0
- datalab/gui/actionhandler.py +1701 -0
- datalab/gui/docks.py +473 -0
- datalab/gui/h5io.py +150 -0
- datalab/gui/macroeditor.py +310 -0
- datalab/gui/main.py +2081 -0
- datalab/gui/newobject.py +217 -0
- datalab/gui/objectview.py +766 -0
- datalab/gui/panel/__init__.py +48 -0
- datalab/gui/panel/base.py +3254 -0
- datalab/gui/panel/image.py +157 -0
- datalab/gui/panel/macro.py +607 -0
- datalab/gui/panel/signal.py +164 -0
- datalab/gui/plothandler.py +800 -0
- datalab/gui/processor/__init__.py +84 -0
- datalab/gui/processor/base.py +2456 -0
- datalab/gui/processor/catcher.py +75 -0
- datalab/gui/processor/image.py +1214 -0
- datalab/gui/processor/signal.py +755 -0
- datalab/gui/profiledialog.py +333 -0
- datalab/gui/roieditor.py +633 -0
- datalab/gui/roigrideditor.py +208 -0
- datalab/gui/settings.py +612 -0
- datalab/gui/tour.py +908 -0
- datalab/h5/__init__.py +12 -0
- datalab/h5/common.py +314 -0
- datalab/h5/generic.py +580 -0
- datalab/h5/native.py +39 -0
- datalab/h5/utils.py +95 -0
- datalab/objectmodel.py +640 -0
- datalab/plugins/_readme_.txt +9 -0
- datalab/plugins/datalab_imageformats.py +175 -0
- datalab/plugins/datalab_testdata.py +190 -0
- datalab/plugins.py +355 -0
- datalab/tests/__init__.py +199 -0
- datalab/tests/backbone/__init__.py +1 -0
- datalab/tests/backbone/config_unit_test.py +170 -0
- datalab/tests/backbone/config_versioning_unit_test.py +34 -0
- datalab/tests/backbone/dictlistserial_app_test.py +38 -0
- datalab/tests/backbone/errorcatcher_unit_test.py +69 -0
- datalab/tests/backbone/errormsgbox_unit_test.py +50 -0
- datalab/tests/backbone/execenv_unit.py +262 -0
- datalab/tests/backbone/loadtest_gdi.py +147 -0
- datalab/tests/backbone/long_callback.py +96 -0
- datalab/tests/backbone/main_app_test.py +137 -0
- datalab/tests/backbone/memory_leak.py +43 -0
- datalab/tests/backbone/procisolation1_unit.py +128 -0
- datalab/tests/backbone/procisolation2_unit.py +171 -0
- datalab/tests/backbone/procisolation_unit_test.py +22 -0
- datalab/tests/backbone/profiling_app.py +27 -0
- datalab/tests/backbone/strings_unit_test.py +65 -0
- datalab/tests/backbone/title_formatting_unit_test.py +82 -0
- datalab/tests/conftest.py +131 -0
- datalab/tests/features/__init__.py +1 -0
- datalab/tests/features/applauncher/__init__.py +1 -0
- datalab/tests/features/applauncher/launcher1_app_test.py +28 -0
- datalab/tests/features/applauncher/launcher2_app_test.py +30 -0
- datalab/tests/features/common/__init__.py +1 -0
- datalab/tests/features/common/add_metadata_app_test.py +134 -0
- datalab/tests/features/common/add_metadata_unit_test.py +267 -0
- datalab/tests/features/common/annotations_management_unit_test.py +152 -0
- datalab/tests/features/common/auto_analysis_recompute_unit_test.py +240 -0
- datalab/tests/features/common/createobject_unit_test.py +50 -0
- datalab/tests/features/common/geometry_results_app_test.py +135 -0
- datalab/tests/features/common/interactive_processing_test.py +1109 -0
- datalab/tests/features/common/io_app_test.py +75 -0
- datalab/tests/features/common/large_results_app_test.py +187 -0
- datalab/tests/features/common/metadata_all_patterns_test.py +103 -0
- datalab/tests/features/common/metadata_app_test.py +139 -0
- datalab/tests/features/common/metadata_io_unit_test.py +60 -0
- datalab/tests/features/common/misc_app_test.py +236 -0
- datalab/tests/features/common/multiple_geometry_results_unit_test.py +122 -0
- datalab/tests/features/common/multiple_table_results_unit_test.py +64 -0
- datalab/tests/features/common/operation_modes_app_test.py +392 -0
- datalab/tests/features/common/plot_results_app_test.py +278 -0
- datalab/tests/features/common/reorder_app_test.py +75 -0
- datalab/tests/features/common/result_deletion_unit_test.py +96 -0
- datalab/tests/features/common/result_merged_label_unit_test.py +154 -0
- datalab/tests/features/common/result_shape_settings_unit_test.py +223 -0
- datalab/tests/features/common/roi_plotitem_unit_test.py +64 -0
- datalab/tests/features/common/roieditor_unit_test.py +102 -0
- datalab/tests/features/common/save_to_dir_app_test.py +163 -0
- datalab/tests/features/common/save_to_dir_unit_test.py +474 -0
- datalab/tests/features/common/stat_app_test.py +40 -0
- datalab/tests/features/common/stats_tools_unit_test.py +77 -0
- datalab/tests/features/common/table_results_app_test.py +52 -0
- datalab/tests/features/common/textimport_unit_test.py +131 -0
- datalab/tests/features/common/uuid_preservation_test.py +281 -0
- datalab/tests/features/common/worker_unit_test.py +402 -0
- datalab/tests/features/control/__init__.py +1 -0
- datalab/tests/features/control/connect_dialog.py +28 -0
- datalab/tests/features/control/embedded1_unit_test.py +304 -0
- datalab/tests/features/control/embedded2_unit_test.py +52 -0
- datalab/tests/features/control/remoteclient_app_test.py +219 -0
- datalab/tests/features/control/remoteclient_unit.py +75 -0
- datalab/tests/features/control/simpleclient_unit_test.py +321 -0
- datalab/tests/features/hdf5/__init__.py +1 -0
- datalab/tests/features/hdf5/h5browser1_unit_test.py +31 -0
- datalab/tests/features/hdf5/h5browser2_unit.py +55 -0
- datalab/tests/features/hdf5/h5browser_app_test.py +77 -0
- datalab/tests/features/hdf5/h5import_app_test.py +25 -0
- datalab/tests/features/hdf5/h5importer_app_test.py +34 -0
- datalab/tests/features/image/__init__.py +1 -0
- datalab/tests/features/image/annotations_app_test.py +28 -0
- datalab/tests/features/image/annotations_unit_test.py +80 -0
- datalab/tests/features/image/average_app_test.py +46 -0
- datalab/tests/features/image/background_dialog_test.py +70 -0
- datalab/tests/features/image/blobs_app_test.py +50 -0
- datalab/tests/features/image/contour_app_test.py +42 -0
- datalab/tests/features/image/contour_fabryperot_app_test.py +51 -0
- datalab/tests/features/image/denoise_app_test.py +31 -0
- datalab/tests/features/image/distribute_on_grid_app_test.py +95 -0
- datalab/tests/features/image/edges_app_test.py +31 -0
- datalab/tests/features/image/erase_app_test.py +21 -0
- datalab/tests/features/image/fft2d_app_test.py +27 -0
- datalab/tests/features/image/flatfield_app_test.py +40 -0
- datalab/tests/features/image/geometry_transform_unit_test.py +396 -0
- datalab/tests/features/image/imagetools_app_test.py +51 -0
- datalab/tests/features/image/imagetools_unit_test.py +27 -0
- datalab/tests/features/image/load_app_test.py +73 -0
- datalab/tests/features/image/morph_app_test.py +32 -0
- datalab/tests/features/image/offsetcorrection_app_test.py +30 -0
- datalab/tests/features/image/peak2d_app_test.py +53 -0
- datalab/tests/features/image/profile_app_test.py +73 -0
- datalab/tests/features/image/profile_dialog_test.py +56 -0
- datalab/tests/features/image/roi_app_test.py +98 -0
- datalab/tests/features/image/roi_circ_app_test.py +62 -0
- datalab/tests/features/image/roi_manipulation_app_test.py +268 -0
- datalab/tests/features/image/roigrid_unit_test.py +60 -0
- datalab/tests/features/image/side_by_side_app_test.py +52 -0
- datalab/tests/features/macro/__init__.py +1 -0
- datalab/tests/features/macro/macro_app_test.py +28 -0
- datalab/tests/features/macro/macroeditor_unit_test.py +102 -0
- datalab/tests/features/signal/__init__.py +1 -0
- datalab/tests/features/signal/baseline_dialog_test.py +53 -0
- datalab/tests/features/signal/deltax_dialog_unit_test.py +34 -0
- datalab/tests/features/signal/fft1d_app_test.py +26 -0
- datalab/tests/features/signal/filter_app_test.py +44 -0
- datalab/tests/features/signal/fitdialog_unit_test.py +50 -0
- datalab/tests/features/signal/interpolation_app_test.py +110 -0
- datalab/tests/features/signal/loadbigsignal_app_test.py +80 -0
- datalab/tests/features/signal/multiple_rois_unit_test.py +132 -0
- datalab/tests/features/signal/pulse_features_app_test.py +118 -0
- datalab/tests/features/signal/pulse_features_roi_app_test.py +55 -0
- datalab/tests/features/signal/roi_app_test.py +78 -0
- datalab/tests/features/signal/roi_manipulation_app_test.py +261 -0
- datalab/tests/features/signal/select_xy_cursor_unit_test.py +46 -0
- datalab/tests/features/signal/signalpeakdetection_dialog_test.py +33 -0
- datalab/tests/features/signal/signals_to_image_app_test.py +98 -0
- datalab/tests/features/signal/xarray_compat_app_test.py +128 -0
- datalab/tests/features/tour_unit_test.py +22 -0
- datalab/tests/features/utilities/__init__.py +1 -0
- datalab/tests/features/utilities/installconf_unit_test.py +21 -0
- datalab/tests/features/utilities/logview_app_test.py +21 -0
- datalab/tests/features/utilities/logview_error.py +24 -0
- datalab/tests/features/utilities/logview_unit_test.py +21 -0
- datalab/tests/features/utilities/memstatus_app_test.py +42 -0
- datalab/tests/features/utilities/settings_unit_test.py +88 -0
- datalab/tests/scenarios/__init__.py +1 -0
- datalab/tests/scenarios/beautiful_app.py +121 -0
- datalab/tests/scenarios/common.py +463 -0
- datalab/tests/scenarios/demo.py +212 -0
- datalab/tests/scenarios/example_app_test.py +47 -0
- datalab/tests/scenarios/scenario_h5_app_test.py +75 -0
- datalab/tests/scenarios/scenario_ima1_app_test.py +34 -0
- datalab/tests/scenarios/scenario_ima2_app_test.py +34 -0
- datalab/tests/scenarios/scenario_mac_app_test.py +58 -0
- datalab/tests/scenarios/scenario_sig1_app_test.py +36 -0
- datalab/tests/scenarios/scenario_sig2_app_test.py +35 -0
- datalab/utils/__init__.py +1 -0
- datalab/utils/conf.py +304 -0
- datalab/utils/dephash.py +105 -0
- datalab/utils/qthelpers.py +633 -0
- datalab/utils/strings.py +34 -0
- datalab/utils/tests.py +0 -0
- datalab/widgets/__init__.py +1 -0
- datalab/widgets/connection.py +138 -0
- datalab/widgets/filedialog.py +91 -0
- datalab/widgets/fileviewer.py +84 -0
- datalab/widgets/fitdialog.py +788 -0
- datalab/widgets/h5browser.py +1048 -0
- datalab/widgets/imagebackground.py +111 -0
- datalab/widgets/instconfviewer.py +175 -0
- datalab/widgets/logviewer.py +80 -0
- datalab/widgets/signalbaseline.py +90 -0
- datalab/widgets/signalcursor.py +208 -0
- datalab/widgets/signaldeltax.py +151 -0
- datalab/widgets/signalpeak.py +199 -0
- datalab/widgets/status.py +249 -0
- datalab/widgets/textimport.py +786 -0
- datalab/widgets/warningerror.py +223 -0
- datalab/widgets/wizard.py +286 -0
- datalab_platform-1.0.0.dist-info/METADATA +121 -0
- datalab_platform-1.0.0.dist-info/RECORD +494 -0
- datalab_platform-0.0.1.dev0.dist-info/METADATA +0 -67
- datalab_platform-0.0.1.dev0.dist-info/RECORD +0 -7
- {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.0.dist-info}/WHEEL +0 -0
- {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.0.dist-info}/entry_points.txt +0 -0
- {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.0.dist-info}/licenses/LICENSE +0 -0
- {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
|