datalab-platform 0.0.1.dev0__py3-none-any.whl → 1.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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.1.dist-info/METADATA +121 -0
- datalab_platform-1.0.1.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.1.dist-info}/WHEEL +0 -0
- {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.1.dist-info}/entry_points.txt +0 -0
- {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.1.dist-info}/licenses/LICENSE +0 -0
- {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,1214 @@
|
|
|
1
|
+
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
.. Image processor object (see parent package :mod:`datalab.gui.processor`)
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
# pylint: disable=invalid-name # Allows short reference names like x, y, ...
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import importlib
|
|
12
|
+
from typing import Literal
|
|
13
|
+
|
|
14
|
+
import numpy as np
|
|
15
|
+
import sigima.params
|
|
16
|
+
import sigima.proc.base as sipb
|
|
17
|
+
import sigima.proc.image as sipi
|
|
18
|
+
from guidata.qthelpers import exec_dialog
|
|
19
|
+
from plotpy.widgets.resizedialog import ResizeDialog
|
|
20
|
+
from qtpy import QtWidgets as QW
|
|
21
|
+
from sigima.objects import (
|
|
22
|
+
ImageObj,
|
|
23
|
+
ImageROI,
|
|
24
|
+
NormalDistributionParam,
|
|
25
|
+
PoissonDistributionParam,
|
|
26
|
+
ROI2DParam,
|
|
27
|
+
UniformDistributionParam,
|
|
28
|
+
)
|
|
29
|
+
from sigima.objects.scalar import GeometryResult, TableResult
|
|
30
|
+
from sigima.proc.decorator import ComputationMetadata
|
|
31
|
+
|
|
32
|
+
from datalab.adapters_metadata import GeometryAdapter
|
|
33
|
+
from datalab.config import APP_NAME, _
|
|
34
|
+
from datalab.gui.processor.base import BaseProcessor
|
|
35
|
+
from datalab.gui.profiledialog import ProfileExtractionDialog
|
|
36
|
+
from datalab.gui.roigrideditor import ImageGridROIEditor
|
|
37
|
+
from datalab.objectmodel import get_uuid
|
|
38
|
+
from datalab.utils.qthelpers import create_progress_bar, qt_try_except
|
|
39
|
+
from datalab.widgets import imagebackground
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def apply_geometry_transform(
|
|
43
|
+
obj: ImageObj,
|
|
44
|
+
operation: Literal[
|
|
45
|
+
"translate", "scale", "rotate90", "rotate270", "fliph", "flipv", "transpose"
|
|
46
|
+
],
|
|
47
|
+
**kwargs,
|
|
48
|
+
) -> None:
|
|
49
|
+
"""Apply a geometric transformation to all geometry results in an object.
|
|
50
|
+
|
|
51
|
+
This uses the Sigima transformation system for proper geometric operations.
|
|
52
|
+
For image objects, rotations are performed around the image center to match
|
|
53
|
+
how the image data is transformed.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
obj: The object containing geometry results to transform
|
|
57
|
+
operation: The transformation operation name
|
|
58
|
+
**kwargs: Optional parameters for the transformation (e.g., angle for rotate)
|
|
59
|
+
"""
|
|
60
|
+
assert operation in [
|
|
61
|
+
"translate",
|
|
62
|
+
"scale",
|
|
63
|
+
"rotate90",
|
|
64
|
+
"rotate270",
|
|
65
|
+
"fliph",
|
|
66
|
+
"flipv",
|
|
67
|
+
"transpose",
|
|
68
|
+
], f"Unknown operation: {operation}"
|
|
69
|
+
if operation == "translate":
|
|
70
|
+
if not kwargs or "dx" not in kwargs or "dy" not in kwargs:
|
|
71
|
+
raise ValueError("translate operation requires 'dx' and 'dy' parameters")
|
|
72
|
+
dx, dy = kwargs["dx"], kwargs["dy"]
|
|
73
|
+
elif operation == "scale":
|
|
74
|
+
if not kwargs or "sx" not in kwargs or "sy" not in kwargs:
|
|
75
|
+
raise ValueError("scale operation requires 'sx' and 'sy' parameters")
|
|
76
|
+
sx, sy = kwargs["sx"], kwargs["sy"]
|
|
77
|
+
for adapter in list(GeometryAdapter.iterate_from_obj(obj)):
|
|
78
|
+
geom = adapter.result
|
|
79
|
+
assert geom is not None, "Geometry should not be None"
|
|
80
|
+
assert len(geom.coords) > 0, "Geometry coordinates should not be empty"
|
|
81
|
+
if operation == "translate":
|
|
82
|
+
tr_geom = sipi.transformer.translate(geom, dx, dy)
|
|
83
|
+
elif operation == "scale":
|
|
84
|
+
tr_geom = sipi.transformer.scale(geom, sx, sy, (obj.xc, obj.yc))
|
|
85
|
+
elif operation == "rotate90":
|
|
86
|
+
tr_geom = sipi.transformer.rotate(geom, -np.pi / 2, (obj.xc, obj.yc))
|
|
87
|
+
elif operation == "rotate270":
|
|
88
|
+
tr_geom = sipi.transformer.rotate(geom, np.pi / 2, (obj.xc, obj.yc))
|
|
89
|
+
elif operation == "fliph":
|
|
90
|
+
tr_geom = sipi.transformer.fliph(geom, obj.xc)
|
|
91
|
+
elif operation == "flipv":
|
|
92
|
+
tr_geom = sipi.transformer.flipv(geom, obj.yc)
|
|
93
|
+
elif operation == "transpose":
|
|
94
|
+
tr_geom = sipi.transformer.transpose(geom)
|
|
95
|
+
else:
|
|
96
|
+
raise ValueError(f"Unknown operation: {operation}")
|
|
97
|
+
|
|
98
|
+
# Remove the old geometry and add the transformed one
|
|
99
|
+
adapter.remove_from(obj)
|
|
100
|
+
tr_adapter = GeometryAdapter(tr_geom)
|
|
101
|
+
tr_adapter.add_to(obj)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class GeometricTransformWrapper:
|
|
105
|
+
"""Pickleable wrapper for geometric transformation functions.
|
|
106
|
+
|
|
107
|
+
This class creates a callable wrapper that can be pickled, unlike nested functions.
|
|
108
|
+
Instead of storing the function directly, it stores the module path and function
|
|
109
|
+
name to allow proper pickling.
|
|
110
|
+
"""
|
|
111
|
+
|
|
112
|
+
def __init__(self, func, operation: str):
|
|
113
|
+
self.operation = operation
|
|
114
|
+
|
|
115
|
+
# Store function reference for execution
|
|
116
|
+
self.func = func
|
|
117
|
+
|
|
118
|
+
# Store function module and name for pickling
|
|
119
|
+
self.__module__ = func.__module__
|
|
120
|
+
self.__qualname__ = func.__qualname__
|
|
121
|
+
self.__annotations__ = getattr(func, "__annotations__", {})
|
|
122
|
+
self.__name__ = getattr(func, "__name__", str(func))
|
|
123
|
+
|
|
124
|
+
# Copy the __wrapped__ attribute if it exists (for Sigima compatibility)
|
|
125
|
+
# Note: We don't copy __wrapped__ as it may contain unpickleable references
|
|
126
|
+
# The wrapper functionality will still work without it
|
|
127
|
+
|
|
128
|
+
# Copy Sigima computation metadata (required for validation)
|
|
129
|
+
computation_metadata_attr = "__computation_function_metadata"
|
|
130
|
+
if hasattr(func, computation_metadata_attr):
|
|
131
|
+
setattr(
|
|
132
|
+
self,
|
|
133
|
+
computation_metadata_attr,
|
|
134
|
+
getattr(func, computation_metadata_attr),
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
def __call__(self, src_obj, param=None):
|
|
138
|
+
"""Call the wrapped function and apply geometry transformations."""
|
|
139
|
+
# Call the original function
|
|
140
|
+
if param is not None:
|
|
141
|
+
dst_obj = self.func(src_obj, param)
|
|
142
|
+
else:
|
|
143
|
+
dst_obj = self.func(src_obj)
|
|
144
|
+
apply_geometry_transform(dst_obj, operation=self.operation)
|
|
145
|
+
return dst_obj
|
|
146
|
+
|
|
147
|
+
def __getstate__(self):
|
|
148
|
+
"""Custom pickling: exclude the function reference."""
|
|
149
|
+
# Build state manually to avoid any problematic attributes
|
|
150
|
+
state = {
|
|
151
|
+
"operation": self.operation,
|
|
152
|
+
"__module__": self.__module__,
|
|
153
|
+
"__qualname__": self.__qualname__,
|
|
154
|
+
"__annotations__": self.__annotations__,
|
|
155
|
+
"__name__": self.__name__,
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
# Store function information for reconstruction
|
|
159
|
+
if hasattr(self, "func"):
|
|
160
|
+
state["_func_module"] = self.func.__module__
|
|
161
|
+
state["_func_name"] = self.func.__name__
|
|
162
|
+
|
|
163
|
+
# Note: We don't copy __wrapped__ as it may contain unpickleable references
|
|
164
|
+
|
|
165
|
+
# Copy computation metadata safely
|
|
166
|
+
computation_metadata_attr = "__computation_function_metadata"
|
|
167
|
+
if hasattr(self, computation_metadata_attr):
|
|
168
|
+
metadata = getattr(self, computation_metadata_attr)
|
|
169
|
+
# Store as a dict to avoid any pickling issues with the object itself
|
|
170
|
+
if hasattr(metadata, "__dict__"):
|
|
171
|
+
state[computation_metadata_attr] = metadata.__dict__.copy()
|
|
172
|
+
else:
|
|
173
|
+
state[computation_metadata_attr] = metadata
|
|
174
|
+
|
|
175
|
+
return state
|
|
176
|
+
|
|
177
|
+
def __setstate__(self, state):
|
|
178
|
+
"""Custom unpickling: restore the function reference."""
|
|
179
|
+
self.__dict__.update(state)
|
|
180
|
+
# Restore function from module and name
|
|
181
|
+
if "_func_module" in state and "_func_name" in state:
|
|
182
|
+
module = importlib.import_module(state["_func_module"])
|
|
183
|
+
self.func = getattr(module, state["_func_name"])
|
|
184
|
+
|
|
185
|
+
# Reconstruct computation metadata if it was stored as dict
|
|
186
|
+
computation_metadata_attr = "__computation_function_metadata"
|
|
187
|
+
if computation_metadata_attr in state:
|
|
188
|
+
metadata_dict = state[computation_metadata_attr]
|
|
189
|
+
if isinstance(metadata_dict, dict):
|
|
190
|
+
metadata = ComputationMetadata(**metadata_dict)
|
|
191
|
+
setattr(self, computation_metadata_attr, metadata)
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
class ImageProcessor(BaseProcessor[ImageROI, ROI2DParam]):
|
|
195
|
+
"""Object handling image processing: operations, processing, analysis"""
|
|
196
|
+
|
|
197
|
+
# pylint: disable=duplicate-code
|
|
198
|
+
|
|
199
|
+
def _wrap_geometric_transform(self, func, operation: str):
|
|
200
|
+
"""Wrap a geometric transformation function to apply geometry transforms.
|
|
201
|
+
|
|
202
|
+
Args:
|
|
203
|
+
func: The original Sigima function
|
|
204
|
+
operation: The operation name for geometry transformation
|
|
205
|
+
|
|
206
|
+
Returns:
|
|
207
|
+
Pickleable wrapped function that applies geometry transformations
|
|
208
|
+
"""
|
|
209
|
+
return GeometricTransformWrapper(func, operation)
|
|
210
|
+
|
|
211
|
+
def postprocess_1_to_0_result(
|
|
212
|
+
self, obj: ImageObj, result: GeometryResult | TableResult
|
|
213
|
+
) -> bool:
|
|
214
|
+
"""Post-process results from 1-to-0 operations for images.
|
|
215
|
+
|
|
216
|
+
For image objects with geometry results, applies detection ROIs if requested
|
|
217
|
+
in the result metadata (via DetectionROIParam).
|
|
218
|
+
|
|
219
|
+
Args:
|
|
220
|
+
obj: The image object that was analyzed
|
|
221
|
+
result: The analysis result (GeometryResult or TableResult)
|
|
222
|
+
|
|
223
|
+
Returns:
|
|
224
|
+
True if the object was modified and needs refresh, False otherwise
|
|
225
|
+
"""
|
|
226
|
+
if isinstance(result, GeometryResult):
|
|
227
|
+
return sipi.apply_detection_rois(obj, result)
|
|
228
|
+
return False
|
|
229
|
+
|
|
230
|
+
def register_operations(self) -> None:
|
|
231
|
+
"""Register operations."""
|
|
232
|
+
self.register_n_to_1(sipi.addition, _("Sum"), icon_name="sum.svg")
|
|
233
|
+
self.register_n_to_1(sipi.average, _("Average"), icon_name="average.svg")
|
|
234
|
+
self.register_n_to_1(
|
|
235
|
+
sipi.standard_deviation,
|
|
236
|
+
_("Standard deviation"),
|
|
237
|
+
icon_name="std.svg",
|
|
238
|
+
)
|
|
239
|
+
self.register_2_to_1(
|
|
240
|
+
sipi.difference,
|
|
241
|
+
_("Difference"),
|
|
242
|
+
icon_name="difference.svg",
|
|
243
|
+
obj2_name=_("image to subtract"),
|
|
244
|
+
)
|
|
245
|
+
self.register_2_to_1(
|
|
246
|
+
sipi.quadratic_difference,
|
|
247
|
+
_("Quadratic Difference"),
|
|
248
|
+
icon_name="quadratic_difference.svg",
|
|
249
|
+
obj2_name=_("image to subtract"),
|
|
250
|
+
)
|
|
251
|
+
self.register_n_to_1(sipi.product, _("Product"), icon_name="product.svg")
|
|
252
|
+
self.register_2_to_1(
|
|
253
|
+
sipi.division,
|
|
254
|
+
_("Division"),
|
|
255
|
+
icon_name="division.svg",
|
|
256
|
+
obj2_name=_("divider"),
|
|
257
|
+
)
|
|
258
|
+
self.register_1_to_1(sipi.inverse, _("Inverse"), icon_name="inverse.svg")
|
|
259
|
+
self.register_2_to_1(
|
|
260
|
+
sipi.arithmetic,
|
|
261
|
+
_("Arithmetic"),
|
|
262
|
+
paramclass=sipb.ArithmeticParam,
|
|
263
|
+
icon_name="arithmetic.svg",
|
|
264
|
+
obj2_name=_("signal to operate with"),
|
|
265
|
+
)
|
|
266
|
+
self.register_1_to_1(
|
|
267
|
+
sipi.addition_constant,
|
|
268
|
+
_("Add constant"),
|
|
269
|
+
paramclass=sipb.ConstantParam,
|
|
270
|
+
icon_name="constant_add.svg",
|
|
271
|
+
)
|
|
272
|
+
self.register_1_to_1(
|
|
273
|
+
sipi.difference_constant,
|
|
274
|
+
_("Subtract constant"),
|
|
275
|
+
paramclass=sipb.ConstantParam,
|
|
276
|
+
icon_name="constant_subtract.svg",
|
|
277
|
+
)
|
|
278
|
+
self.register_1_to_1(
|
|
279
|
+
sipi.product_constant,
|
|
280
|
+
_("Multiply by constant"),
|
|
281
|
+
paramclass=sipb.ConstantParam,
|
|
282
|
+
icon_name="constant_multiply.svg",
|
|
283
|
+
)
|
|
284
|
+
self.register_1_to_1(
|
|
285
|
+
sipi.division_constant,
|
|
286
|
+
_("Divide by constant"),
|
|
287
|
+
paramclass=sipb.ConstantParam,
|
|
288
|
+
icon_name="constant_divide.svg",
|
|
289
|
+
)
|
|
290
|
+
self.register_1_to_1(sipi.absolute, _("Absolute value"), icon_name="abs.svg")
|
|
291
|
+
self.register_1_to_1(
|
|
292
|
+
sipi.phase,
|
|
293
|
+
_("Phase"),
|
|
294
|
+
paramclass=sigima.params.PhaseParam,
|
|
295
|
+
icon_name="phase.svg",
|
|
296
|
+
)
|
|
297
|
+
self.register_2_to_1(
|
|
298
|
+
sipi.complex_from_magnitude_phase,
|
|
299
|
+
_("Combine with phase"),
|
|
300
|
+
paramclass=sipb.AngleUnitParam,
|
|
301
|
+
icon_name="complex_from_magnitude_phase.svg",
|
|
302
|
+
comment=_("Create a complex-valued image from magnitude and phase"),
|
|
303
|
+
obj2_name=_("phase"),
|
|
304
|
+
)
|
|
305
|
+
self.register_1_to_1(sipi.real, _("Real part"), icon_name="re.svg")
|
|
306
|
+
self.register_1_to_1(sipi.imag, _("Imaginary part"), icon_name="im.svg")
|
|
307
|
+
self.register_2_to_1(
|
|
308
|
+
sipi.complex_from_real_imag,
|
|
309
|
+
_("Combine with imaginary part"),
|
|
310
|
+
icon_name="complex_from_real_imag.svg",
|
|
311
|
+
comment=_("Create a complex-valued image from real and imaginary parts"),
|
|
312
|
+
obj2_name=_("imaginary part"),
|
|
313
|
+
)
|
|
314
|
+
self.register_1_to_1(
|
|
315
|
+
sipi.astype,
|
|
316
|
+
_("Convert data type"),
|
|
317
|
+
paramclass=sigima.params.DataTypeIParam,
|
|
318
|
+
icon_name="convert_dtype.svg",
|
|
319
|
+
)
|
|
320
|
+
self.register_1_to_1(sipi.exp, _("Exponential"), icon_name="exp.svg")
|
|
321
|
+
self.register_1_to_1(
|
|
322
|
+
sipi.log10, _("Logarithm (base 10)"), icon_name="log10.svg"
|
|
323
|
+
)
|
|
324
|
+
self.register_1_to_1(
|
|
325
|
+
sipi.log10_z_plus_n,
|
|
326
|
+
"Log10(z+n)",
|
|
327
|
+
paramclass=sigima.params.Log10ZPlusNParam,
|
|
328
|
+
)
|
|
329
|
+
self.register_2_to_1(
|
|
330
|
+
sipi.flatfield,
|
|
331
|
+
_("Flat-field correction"),
|
|
332
|
+
sipi.FlatFieldParam,
|
|
333
|
+
obj2_name=_("flat field image"),
|
|
334
|
+
)
|
|
335
|
+
# Flip or rotation
|
|
336
|
+
self.register_1_to_1(
|
|
337
|
+
self._wrap_geometric_transform(sipi.fliph, "fliph"),
|
|
338
|
+
_("Flip horizontally"),
|
|
339
|
+
icon_name="flip_horizontally.svg",
|
|
340
|
+
)
|
|
341
|
+
self.register_1_to_1(
|
|
342
|
+
self._wrap_geometric_transform(sipi.transpose, "transpose"),
|
|
343
|
+
_("Flip diagonally"),
|
|
344
|
+
icon_name="swap_x_y.svg",
|
|
345
|
+
)
|
|
346
|
+
self.register_1_to_1(
|
|
347
|
+
self._wrap_geometric_transform(sipi.flipv, "flipv"),
|
|
348
|
+
_("Flip vertically"),
|
|
349
|
+
icon_name="flip_vertically.svg",
|
|
350
|
+
)
|
|
351
|
+
self.register_1_to_1(
|
|
352
|
+
self._wrap_geometric_transform(sipi.rotate270, "rotate270"),
|
|
353
|
+
_("Rotate %s right") % "90°",
|
|
354
|
+
icon_name="rotate_right.svg",
|
|
355
|
+
)
|
|
356
|
+
self.register_1_to_1(
|
|
357
|
+
self._wrap_geometric_transform(sipi.rotate90, "rotate90"),
|
|
358
|
+
_("Rotate %s left") % "90°",
|
|
359
|
+
icon_name="rotate_left.svg",
|
|
360
|
+
)
|
|
361
|
+
self.register_1_to_1(sipi.rotate, _("Rotate by"), sipi.RotateParam)
|
|
362
|
+
# Intensity profiles
|
|
363
|
+
self.register_1_to_1(
|
|
364
|
+
sipi.line_profile,
|
|
365
|
+
_("Line profile"),
|
|
366
|
+
sipi.LineProfileParam,
|
|
367
|
+
icon_name="profile.svg",
|
|
368
|
+
edit=False,
|
|
369
|
+
)
|
|
370
|
+
self.register_1_to_1(
|
|
371
|
+
sipi.segment_profile,
|
|
372
|
+
_("Segment profile"),
|
|
373
|
+
sipi.SegmentProfileParam,
|
|
374
|
+
icon_name="profile_segment.svg",
|
|
375
|
+
edit=False,
|
|
376
|
+
)
|
|
377
|
+
self.register_1_to_1(
|
|
378
|
+
sipi.average_profile,
|
|
379
|
+
_("Average profile"),
|
|
380
|
+
sipi.AverageProfileParam,
|
|
381
|
+
icon_name="profile_average.svg",
|
|
382
|
+
edit=False,
|
|
383
|
+
)
|
|
384
|
+
self.register_1_to_1(
|
|
385
|
+
sipi.radial_profile,
|
|
386
|
+
_("Radial profile"),
|
|
387
|
+
sipi.RadialProfileParam,
|
|
388
|
+
icon_name="profile_radial.svg",
|
|
389
|
+
)
|
|
390
|
+
self.register_2_to_1(
|
|
391
|
+
sipi.convolution,
|
|
392
|
+
_("Convolution"),
|
|
393
|
+
icon_name="convolution.svg",
|
|
394
|
+
obj2_name=_("kernel to convolve with"),
|
|
395
|
+
)
|
|
396
|
+
self.register_2_to_1(
|
|
397
|
+
sipi.deconvolution,
|
|
398
|
+
_("Deconvolution"),
|
|
399
|
+
icon_name="deconvolution.svg",
|
|
400
|
+
obj2_name=_("kernel to deconvolve with"),
|
|
401
|
+
)
|
|
402
|
+
|
|
403
|
+
def register_processing(self) -> None:
|
|
404
|
+
"""Register processing functions."""
|
|
405
|
+
# Axis transformation
|
|
406
|
+
self.register_1_to_1(
|
|
407
|
+
sipi.set_uniform_coords,
|
|
408
|
+
_("Set uniform coordinates"),
|
|
409
|
+
sipi.UniformCoordsParam,
|
|
410
|
+
)
|
|
411
|
+
self.register_1_to_1(
|
|
412
|
+
sipi.calibration,
|
|
413
|
+
_("Polynomial calibration"),
|
|
414
|
+
sipi.XYZCalibrateParam,
|
|
415
|
+
comment=_(
|
|
416
|
+
"Apply polynomial calibration to the X, Y or Z axis:\n"
|
|
417
|
+
" • x' = a0 + a1*x + a2*x^2 + ...\n"
|
|
418
|
+
" • y' = a0 + a1*y + a2*y^2 + ...\n"
|
|
419
|
+
" • z' = a0 + a1*z + a2*z^2 + ..."
|
|
420
|
+
),
|
|
421
|
+
)
|
|
422
|
+
self.register_1_to_1(
|
|
423
|
+
sipi.transpose,
|
|
424
|
+
_("Swap X/Y axes"),
|
|
425
|
+
icon_name="swap_x_y.svg",
|
|
426
|
+
)
|
|
427
|
+
# Level adjustment
|
|
428
|
+
self.register_1_to_1(
|
|
429
|
+
sipi.normalize,
|
|
430
|
+
_("Normalize"),
|
|
431
|
+
paramclass=sipb.NormalizeParam,
|
|
432
|
+
icon_name="normalize.svg",
|
|
433
|
+
)
|
|
434
|
+
self.register_1_to_1(sipi.clip, _("Clipping"), sipb.ClipParam, "clip.svg")
|
|
435
|
+
self.register_1_to_1(
|
|
436
|
+
sipi.offset_correction,
|
|
437
|
+
_("Offset correction"),
|
|
438
|
+
ROI2DParam,
|
|
439
|
+
comment=_("Evaluate and subtract the offset value from the data"),
|
|
440
|
+
icon_name="offset_correction.svg",
|
|
441
|
+
)
|
|
442
|
+
# Noise addition
|
|
443
|
+
self.register_1_to_1(
|
|
444
|
+
sipi.add_gaussian_noise, _("Add Gaussian noise"), NormalDistributionParam
|
|
445
|
+
)
|
|
446
|
+
self.register_1_to_1(
|
|
447
|
+
sipi.add_poisson_noise, _("Add Poisson noise"), PoissonDistributionParam
|
|
448
|
+
)
|
|
449
|
+
self.register_1_to_1(
|
|
450
|
+
sipi.add_uniform_noise, _("Add uniform noise"), UniformDistributionParam
|
|
451
|
+
)
|
|
452
|
+
# Noise reduction
|
|
453
|
+
self.register_1_to_1(
|
|
454
|
+
sipi.gaussian_filter,
|
|
455
|
+
_("Gaussian filter"),
|
|
456
|
+
sipb.GaussianParam,
|
|
457
|
+
)
|
|
458
|
+
self.register_1_to_1(
|
|
459
|
+
sipi.moving_average,
|
|
460
|
+
_("Moving average"),
|
|
461
|
+
sipb.MovingAverageParam,
|
|
462
|
+
)
|
|
463
|
+
self.register_1_to_1(
|
|
464
|
+
sipi.moving_median,
|
|
465
|
+
_("Moving median"),
|
|
466
|
+
sipb.MovingMedianParam,
|
|
467
|
+
)
|
|
468
|
+
self.register_1_to_1(sipi.wiener, _("Wiener filter"))
|
|
469
|
+
self.register_1_to_1(
|
|
470
|
+
sipi.erase,
|
|
471
|
+
_("Erase area") + "...",
|
|
472
|
+
ROI2DParam,
|
|
473
|
+
comment=_("Erase area in the image as defined by a region of interest"),
|
|
474
|
+
icon_name="erase.svg",
|
|
475
|
+
)
|
|
476
|
+
# Fourier analysis
|
|
477
|
+
self.register_1_to_1(
|
|
478
|
+
sipi.zero_padding,
|
|
479
|
+
_("Zero padding"),
|
|
480
|
+
sipi.ZeroPadding2DParam,
|
|
481
|
+
comment=_(
|
|
482
|
+
"Zero padding is used to increase the frequency resolution of the FFT"
|
|
483
|
+
),
|
|
484
|
+
)
|
|
485
|
+
self.register_1_to_1(
|
|
486
|
+
sipi.fft,
|
|
487
|
+
_("FFT"),
|
|
488
|
+
sipb.FFTParam,
|
|
489
|
+
comment=_(
|
|
490
|
+
"Fast Fourier Transform (FFT) is an estimation of the "
|
|
491
|
+
"Discrete Fourier Transform (DFT). "
|
|
492
|
+
"Results are complex numbers, but only the real part is plotted."
|
|
493
|
+
),
|
|
494
|
+
edit=False,
|
|
495
|
+
)
|
|
496
|
+
self.register_1_to_1(
|
|
497
|
+
sipi.ifft,
|
|
498
|
+
_("Inverse FFT"),
|
|
499
|
+
sipb.FFTParam,
|
|
500
|
+
comment=_(
|
|
501
|
+
"Inverse Fast Fourier Transform (IFFT) is an estimation of the "
|
|
502
|
+
"Inverse Discrete Fourier Transform (IDFT). "
|
|
503
|
+
"Results are complex numbers, but only the real part is plotted."
|
|
504
|
+
),
|
|
505
|
+
edit=False,
|
|
506
|
+
)
|
|
507
|
+
self.register_1_to_1(
|
|
508
|
+
sipi.magnitude_spectrum,
|
|
509
|
+
_("Magnitude spectrum"),
|
|
510
|
+
paramclass=sigima.params.SpectrumParam,
|
|
511
|
+
comment=_(
|
|
512
|
+
"Magnitude spectrum is the absolute value of the FFT result. "
|
|
513
|
+
"It is a measure of the amplitude of the frequency components."
|
|
514
|
+
),
|
|
515
|
+
)
|
|
516
|
+
self.register_1_to_1(
|
|
517
|
+
sipi.phase_spectrum,
|
|
518
|
+
_("Phase spectrum"),
|
|
519
|
+
comment=_(
|
|
520
|
+
"Phase spectrum is the angle of the FFT result. "
|
|
521
|
+
"It is a measure of the phase of the frequency components."
|
|
522
|
+
),
|
|
523
|
+
)
|
|
524
|
+
self.register_1_to_1(
|
|
525
|
+
sipi.psd,
|
|
526
|
+
_("Power spectral density"),
|
|
527
|
+
paramclass=sigima.params.SpectrumParam,
|
|
528
|
+
comment=_(
|
|
529
|
+
"Power spectral density (PSD) is the square of the magnitude spectrum. "
|
|
530
|
+
"It is a measure of the power of the frequency components."
|
|
531
|
+
),
|
|
532
|
+
)
|
|
533
|
+
# Frequency filters
|
|
534
|
+
self.register_1_to_1(
|
|
535
|
+
sipi.butterworth,
|
|
536
|
+
_("Butterworth"),
|
|
537
|
+
sipi.ButterworthParam,
|
|
538
|
+
)
|
|
539
|
+
self.register_1_to_1(
|
|
540
|
+
sipi.gaussian_freq_filter,
|
|
541
|
+
_("Gaussian bandpass"),
|
|
542
|
+
sipi.GaussianFreqFilterParam,
|
|
543
|
+
)
|
|
544
|
+
# Thresholding
|
|
545
|
+
self.register_1_to_1(
|
|
546
|
+
sipi.threshold,
|
|
547
|
+
_("Parametric thresholding"),
|
|
548
|
+
sipi.ThresholdParam,
|
|
549
|
+
comment=_(
|
|
550
|
+
"Parametric thresholding allows to select a thresholding method "
|
|
551
|
+
"and a threshold value."
|
|
552
|
+
),
|
|
553
|
+
)
|
|
554
|
+
self.register_1_to_1(sipi.threshold_isodata, _("ISODATA thresholding"))
|
|
555
|
+
self.register_1_to_1(sipi.threshold_li, _("Li thresholding"))
|
|
556
|
+
self.register_1_to_1(sipi.threshold_mean, _("Mean thresholding"))
|
|
557
|
+
self.register_1_to_1(sipi.threshold_minimum, _("Minimum thresholding"))
|
|
558
|
+
self.register_1_to_1(sipi.threshold_otsu, _("Otsu thresholding"))
|
|
559
|
+
self.register_1_to_1(sipi.threshold_triangle, _("Triangle thresholding"))
|
|
560
|
+
self.register_1_to_1(sipi.threshold_yen, _("Yen thresholding"))
|
|
561
|
+
# Exposure
|
|
562
|
+
self.register_1_to_1(
|
|
563
|
+
sipi.adjust_gamma,
|
|
564
|
+
_("Gamma correction"),
|
|
565
|
+
sipi.AdjustGammaParam,
|
|
566
|
+
)
|
|
567
|
+
self.register_1_to_1(
|
|
568
|
+
sipi.adjust_log,
|
|
569
|
+
_("Logarithmic correction"),
|
|
570
|
+
sipi.AdjustLogParam,
|
|
571
|
+
)
|
|
572
|
+
self.register_1_to_1(
|
|
573
|
+
sipi.adjust_sigmoid,
|
|
574
|
+
_("Sigmoid correction"),
|
|
575
|
+
sipi.AdjustSigmoidParam,
|
|
576
|
+
)
|
|
577
|
+
self.register_1_to_1(
|
|
578
|
+
sipi.equalize_hist,
|
|
579
|
+
_("Histogram equalization"),
|
|
580
|
+
sipi.EqualizeHistParam,
|
|
581
|
+
)
|
|
582
|
+
self.register_1_to_1(
|
|
583
|
+
sipi.equalize_adapthist,
|
|
584
|
+
_("Adaptive histogram equalization"),
|
|
585
|
+
sipi.EqualizeAdaptHistParam,
|
|
586
|
+
)
|
|
587
|
+
self.register_1_to_1(
|
|
588
|
+
sipi.rescale_intensity,
|
|
589
|
+
_("Intensity rescaling"),
|
|
590
|
+
sipi.RescaleIntensityParam,
|
|
591
|
+
)
|
|
592
|
+
# Restoration
|
|
593
|
+
self.register_1_to_1(
|
|
594
|
+
sipi.denoise_tv,
|
|
595
|
+
_("Total variation denoising"),
|
|
596
|
+
sipi.DenoiseTVParam,
|
|
597
|
+
)
|
|
598
|
+
self.register_1_to_1(
|
|
599
|
+
sipi.denoise_bilateral,
|
|
600
|
+
_("Bilateral filter denoising"),
|
|
601
|
+
sipi.DenoiseBilateralParam,
|
|
602
|
+
)
|
|
603
|
+
self.register_1_to_1(
|
|
604
|
+
sipi.denoise_wavelet,
|
|
605
|
+
_("Wavelet denoising"),
|
|
606
|
+
sipi.DenoiseWaveletParam,
|
|
607
|
+
)
|
|
608
|
+
self.register_1_to_1(
|
|
609
|
+
sipi.denoise_tophat,
|
|
610
|
+
_("White Top-Hat denoising"),
|
|
611
|
+
sipi.MorphologyParam,
|
|
612
|
+
)
|
|
613
|
+
# Morphology
|
|
614
|
+
self.register_1_to_1(
|
|
615
|
+
sipi.white_tophat,
|
|
616
|
+
_("White Top-Hat (disk)"),
|
|
617
|
+
sipi.MorphologyParam,
|
|
618
|
+
)
|
|
619
|
+
self.register_1_to_1(
|
|
620
|
+
sipi.black_tophat,
|
|
621
|
+
_("Black Top-Hat (disk)"),
|
|
622
|
+
sipi.MorphologyParam,
|
|
623
|
+
)
|
|
624
|
+
self.register_1_to_1(
|
|
625
|
+
sipi.erosion,
|
|
626
|
+
_("Erosion (disk)"),
|
|
627
|
+
sipi.MorphologyParam,
|
|
628
|
+
)
|
|
629
|
+
self.register_1_to_1(
|
|
630
|
+
sipi.dilation,
|
|
631
|
+
_("Dilation (disk)"),
|
|
632
|
+
sipi.MorphologyParam,
|
|
633
|
+
)
|
|
634
|
+
self.register_1_to_1(
|
|
635
|
+
sipi.opening,
|
|
636
|
+
_("Opening (disk)"),
|
|
637
|
+
sipi.MorphologyParam,
|
|
638
|
+
)
|
|
639
|
+
self.register_1_to_1(
|
|
640
|
+
sipi.closing,
|
|
641
|
+
_("Closing (disk)"),
|
|
642
|
+
sipi.MorphologyParam,
|
|
643
|
+
)
|
|
644
|
+
# Edge detection
|
|
645
|
+
self.register_1_to_1(sipi.canny, _("Canny filter"), sipi.CannyParam)
|
|
646
|
+
self.register_1_to_1(sipi.farid, _("Farid filter"))
|
|
647
|
+
self.register_1_to_1(sipi.farid_h, _("Farid filter (horizontal)"))
|
|
648
|
+
self.register_1_to_1(sipi.farid_v, _("Farid filter (vertical)"))
|
|
649
|
+
self.register_1_to_1(sipi.laplace, _("Laplace filter"))
|
|
650
|
+
self.register_1_to_1(sipi.prewitt, _("Prewitt filter"))
|
|
651
|
+
self.register_1_to_1(sipi.prewitt_h, _("Prewitt filter (horizontal)"))
|
|
652
|
+
self.register_1_to_1(sipi.prewitt_v, _("Prewitt filter (vertical)"))
|
|
653
|
+
self.register_1_to_1(sipi.roberts, _("Roberts filter"))
|
|
654
|
+
self.register_1_to_1(sipi.scharr, _("Scharr filter"))
|
|
655
|
+
self.register_1_to_1(sipi.scharr_h, _("Scharr filter (horizontal)"))
|
|
656
|
+
self.register_1_to_1(sipi.scharr_v, _("Scharr filter (vertical)"))
|
|
657
|
+
self.register_1_to_1(sipi.sobel, _("Sobel filter"))
|
|
658
|
+
self.register_1_to_1(sipi.sobel_h, _("Sobel filter (horizontal)"))
|
|
659
|
+
self.register_1_to_1(sipi.sobel_v, _("Sobel filter (vertical)"))
|
|
660
|
+
|
|
661
|
+
# Other processing
|
|
662
|
+
self.register_1_to_n(sipi.extract_roi, "ROI", icon_name="roi.svg")
|
|
663
|
+
self.register_1_to_1(
|
|
664
|
+
sipi.resize,
|
|
665
|
+
_("Resize"),
|
|
666
|
+
sipi.ResizeParam,
|
|
667
|
+
icon_name="resize.svg",
|
|
668
|
+
)
|
|
669
|
+
self.register_1_to_1(
|
|
670
|
+
sipi.binning,
|
|
671
|
+
_("Pixel binning"),
|
|
672
|
+
sipi.BinningParam,
|
|
673
|
+
icon_name="binning.svg",
|
|
674
|
+
)
|
|
675
|
+
self.register_1_to_1(
|
|
676
|
+
sipi.resampling,
|
|
677
|
+
_("Resampling"),
|
|
678
|
+
sipi.Resampling2DParam,
|
|
679
|
+
icon_name="resampling2d.svg",
|
|
680
|
+
)
|
|
681
|
+
|
|
682
|
+
def register_analysis(self) -> None:
|
|
683
|
+
"""Register analysis functions."""
|
|
684
|
+
self.register_1_to_0(sipi.stats, _("Statistics"), icon_name="stats.svg")
|
|
685
|
+
self.register_1_to_1(
|
|
686
|
+
sipi.horizontal_projection,
|
|
687
|
+
_("Horizontal projection"),
|
|
688
|
+
# icon_name="horizontal_projection.svg",
|
|
689
|
+
comment=_(
|
|
690
|
+
"Compute the sum of pixel intensities along each column "
|
|
691
|
+
"(projection on the x-axis)"
|
|
692
|
+
),
|
|
693
|
+
)
|
|
694
|
+
self.register_1_to_1(
|
|
695
|
+
sipi.vertical_projection,
|
|
696
|
+
# icon_name="vertical_projection.svg",
|
|
697
|
+
_("Vertical projection"),
|
|
698
|
+
comment=_(
|
|
699
|
+
"Compute the sum of pixel intensities along each row "
|
|
700
|
+
"(projection on the y-axis)"
|
|
701
|
+
),
|
|
702
|
+
)
|
|
703
|
+
|
|
704
|
+
self.register_1_to_1(
|
|
705
|
+
sipi.histogram,
|
|
706
|
+
_("Histogram"),
|
|
707
|
+
paramclass=sipb.HistogramParam,
|
|
708
|
+
icon_name="histogram.svg",
|
|
709
|
+
)
|
|
710
|
+
self.register_1_to_0(
|
|
711
|
+
sipi.centroid,
|
|
712
|
+
_("Centroid"),
|
|
713
|
+
comment=_("Compute image centroid"),
|
|
714
|
+
)
|
|
715
|
+
self.register_1_to_0(
|
|
716
|
+
sipi.enclosing_circle,
|
|
717
|
+
_("Minimum enclosing circle center"),
|
|
718
|
+
comment=_("Compute smallest enclosing circle center"),
|
|
719
|
+
)
|
|
720
|
+
self.register_1_to_0(
|
|
721
|
+
sipi.contour_shape,
|
|
722
|
+
_("Contour detection"),
|
|
723
|
+
sipi.ContourShapeParam,
|
|
724
|
+
comment=_("Compute contour shape fit"),
|
|
725
|
+
)
|
|
726
|
+
self.register_1_to_0(
|
|
727
|
+
sipi.peak_detection,
|
|
728
|
+
_("Peak detection"),
|
|
729
|
+
sipi.Peak2DDetectionParam,
|
|
730
|
+
comment=_("Detect peaks in the image"),
|
|
731
|
+
)
|
|
732
|
+
self.register_1_to_0(
|
|
733
|
+
sipi.hough_circle_peaks,
|
|
734
|
+
_("Circle Hough transform"),
|
|
735
|
+
sipi.HoughCircleParam,
|
|
736
|
+
comment=_("Detect circular shapes using circle Hough transform"),
|
|
737
|
+
)
|
|
738
|
+
# Blob detection
|
|
739
|
+
self.register_1_to_0(
|
|
740
|
+
sipi.blob_dog,
|
|
741
|
+
_("Blob detection (DOG)"),
|
|
742
|
+
sipi.BlobDOGParam,
|
|
743
|
+
comment=_("Detect blobs using Difference of Gaussian (DOG) method"),
|
|
744
|
+
)
|
|
745
|
+
self.register_1_to_0(
|
|
746
|
+
sipi.blob_doh,
|
|
747
|
+
_("Blob detection (DOH)"),
|
|
748
|
+
sipi.BlobDOHParam,
|
|
749
|
+
comment=_("Detect blobs using Difference of Gaussian (DOH) method"),
|
|
750
|
+
)
|
|
751
|
+
self.register_1_to_0(
|
|
752
|
+
sipi.blob_log,
|
|
753
|
+
_("Blob detection (LOG)"),
|
|
754
|
+
sipi.BlobLOGParam,
|
|
755
|
+
comment=_("Detect blobs using Laplacian of Gaussian (LOG) method"),
|
|
756
|
+
)
|
|
757
|
+
self.register_1_to_0(
|
|
758
|
+
sipi.blob_opencv,
|
|
759
|
+
_("Blob detection (OpenCV)"),
|
|
760
|
+
sipi.BlobOpenCVParam,
|
|
761
|
+
comment=_("Detect blobs using OpenCV SimpleBlobDetector"),
|
|
762
|
+
)
|
|
763
|
+
|
|
764
|
+
def create_roi_grid(self) -> None:
|
|
765
|
+
"""Create a grid of regions of interest"""
|
|
766
|
+
obj0 = self.panel.objview.get_sel_objects(include_groups=True)[0]
|
|
767
|
+
if any(obj.roi is not None for obj in self.panel.objview.get_sel_objects()):
|
|
768
|
+
if (
|
|
769
|
+
QW.QMessageBox.question(
|
|
770
|
+
self.mainwindow,
|
|
771
|
+
_("Warning"),
|
|
772
|
+
_(
|
|
773
|
+
"Creating a ROI grid will overwrite any existing ROI.<br><br>"
|
|
774
|
+
"Do you want to continue?"
|
|
775
|
+
),
|
|
776
|
+
QW.QMessageBox.Yes | QW.QMessageBox.No,
|
|
777
|
+
QW.QMessageBox.No,
|
|
778
|
+
)
|
|
779
|
+
== QW.QMessageBox.No
|
|
780
|
+
):
|
|
781
|
+
return
|
|
782
|
+
editor = ImageGridROIEditor(parent=self.parent(), obj=obj0)
|
|
783
|
+
if exec_dialog(editor):
|
|
784
|
+
for obj in self.panel.objview.get_sel_objects():
|
|
785
|
+
obj.roi = editor.get_roi()
|
|
786
|
+
self.SIG_ADD_SHAPE.emit(get_uuid(obj0))
|
|
787
|
+
self.panel.selection_changed(update_items=True)
|
|
788
|
+
self.panel.refresh_plot(
|
|
789
|
+
"selected",
|
|
790
|
+
update_items=True,
|
|
791
|
+
only_visible=False,
|
|
792
|
+
only_existing=True,
|
|
793
|
+
)
|
|
794
|
+
# Now, we ask the user if we shall extract the freshly defined ROI:
|
|
795
|
+
if (
|
|
796
|
+
QW.QMessageBox.question(
|
|
797
|
+
self.mainwindow,
|
|
798
|
+
_("Extract ROI"),
|
|
799
|
+
_("Do you want to extract images from the defined ROI?"),
|
|
800
|
+
QW.QMessageBox.Yes | QW.QMessageBox.No,
|
|
801
|
+
QW.QMessageBox.No,
|
|
802
|
+
)
|
|
803
|
+
== QW.QMessageBox.Yes
|
|
804
|
+
):
|
|
805
|
+
self.compute_roi_extraction(editor.get_roi())
|
|
806
|
+
|
|
807
|
+
@qt_try_except()
|
|
808
|
+
def compute_resize(self, param: sigima.params.ResizeParam | None = None) -> None:
|
|
809
|
+
"""Resize image with :py:func:`sigima.proc.image.resize`"""
|
|
810
|
+
obj0 = self.panel.objview.get_sel_objects(include_groups=True)[0]
|
|
811
|
+
for obj in self.panel.objview.get_sel_objects():
|
|
812
|
+
if obj.data.shape != obj0.data.shape:
|
|
813
|
+
QW.QMessageBox.warning(
|
|
814
|
+
self.mainwindow,
|
|
815
|
+
APP_NAME,
|
|
816
|
+
_("Warning:")
|
|
817
|
+
+ "\n"
|
|
818
|
+
+ _("Selected images do not have the same size"),
|
|
819
|
+
)
|
|
820
|
+
edit, param = self.init_param(param, sipi.ResizeParam, _("Resize"))
|
|
821
|
+
if edit:
|
|
822
|
+
original_size = obj0.data.shape
|
|
823
|
+
dlg = ResizeDialog(
|
|
824
|
+
self.plotwidget,
|
|
825
|
+
new_size=original_size,
|
|
826
|
+
old_size=original_size,
|
|
827
|
+
text=_("Destination size:"),
|
|
828
|
+
)
|
|
829
|
+
if not exec_dialog(dlg):
|
|
830
|
+
return
|
|
831
|
+
param.zoom = dlg.get_zoom()
|
|
832
|
+
self.run_feature("resize", param, title=_("Resize"), edit=edit)
|
|
833
|
+
|
|
834
|
+
@qt_try_except()
|
|
835
|
+
def compute_binning(self, param: sigima.params.BinningParam | None = None) -> None:
|
|
836
|
+
"""Binning image with :py:func:`sigima.proc.image.binning`"""
|
|
837
|
+
edit = param is None
|
|
838
|
+
obj0 = self.panel.objview.get_sel_objects(include_groups=True)[0]
|
|
839
|
+
input_dtype_str = str(obj0.data.dtype)
|
|
840
|
+
title = _("Binning")
|
|
841
|
+
edit, param = self.init_param(param, sipi.BinningParam, title)
|
|
842
|
+
if edit:
|
|
843
|
+
param.dtype_str = input_dtype_str
|
|
844
|
+
if param.dtype_str is None:
|
|
845
|
+
param.dtype_str = input_dtype_str
|
|
846
|
+
self.run_feature("binning", param, title=title, edit=edit)
|
|
847
|
+
|
|
848
|
+
@qt_try_except()
|
|
849
|
+
def compute_line_profile(
|
|
850
|
+
self, param: sigima.params.LineProfileParam | None = None
|
|
851
|
+
) -> None:
|
|
852
|
+
"""Compute profile along a vertical or horizontal line
|
|
853
|
+
with :py:func:`sigima.proc.image.line_profile`"""
|
|
854
|
+
title = _("Profile")
|
|
855
|
+
add_initial_shape = self.has_param_defaults(sigima.params.LineProfileParam)
|
|
856
|
+
edit, param = self.init_param(param, sipi.LineProfileParam, title)
|
|
857
|
+
if edit:
|
|
858
|
+
options = self.panel.plothandler.get_plot_options()
|
|
859
|
+
dlg = ProfileExtractionDialog(
|
|
860
|
+
"line", param, options, self.mainwindow, add_initial_shape
|
|
861
|
+
)
|
|
862
|
+
obj = self.panel.objview.get_sel_objects(include_groups=True)[0]
|
|
863
|
+
dlg.set_obj(obj)
|
|
864
|
+
if not exec_dialog(dlg):
|
|
865
|
+
return
|
|
866
|
+
self.run_feature("line_profile", param, title=title, edit=False)
|
|
867
|
+
|
|
868
|
+
@qt_try_except()
|
|
869
|
+
def compute_segment_profile(
|
|
870
|
+
self, param: sigima.params.SegmentProfileParam | None = None
|
|
871
|
+
):
|
|
872
|
+
"""Compute profile along a segment
|
|
873
|
+
with :py:func:`sigima.proc.image.segment_profile`"""
|
|
874
|
+
title = _("Profile")
|
|
875
|
+
add_initial_shape = self.has_param_defaults(sigima.params.SegmentProfileParam)
|
|
876
|
+
edit, param = self.init_param(param, sipi.SegmentProfileParam, title)
|
|
877
|
+
if edit:
|
|
878
|
+
options = self.panel.plothandler.get_plot_options()
|
|
879
|
+
dlg = ProfileExtractionDialog(
|
|
880
|
+
"segment", param, options, self.mainwindow, add_initial_shape
|
|
881
|
+
)
|
|
882
|
+
obj = self.panel.objview.get_sel_objects(include_groups=True)[0]
|
|
883
|
+
dlg.set_obj(obj)
|
|
884
|
+
if not exec_dialog(dlg):
|
|
885
|
+
return
|
|
886
|
+
self.run_feature("segment_profile", param, title=title, edit=False)
|
|
887
|
+
|
|
888
|
+
@qt_try_except()
|
|
889
|
+
def compute_average_profile(
|
|
890
|
+
self, param: sigima.params.AverageProfileParam | None = None
|
|
891
|
+
) -> None:
|
|
892
|
+
"""Compute average profile
|
|
893
|
+
with :py:func:`sigima.proc.image.average_profile`"""
|
|
894
|
+
title = _("Average profile")
|
|
895
|
+
add_initial_shape = self.has_param_defaults(sigima.params.AverageProfileParam)
|
|
896
|
+
edit, param = self.init_param(param, sipi.AverageProfileParam, title)
|
|
897
|
+
if edit:
|
|
898
|
+
options = self.panel.plothandler.get_plot_options()
|
|
899
|
+
dlg = ProfileExtractionDialog(
|
|
900
|
+
"rectangle",
|
|
901
|
+
param,
|
|
902
|
+
options,
|
|
903
|
+
self.mainwindow,
|
|
904
|
+
add_initial_shape,
|
|
905
|
+
)
|
|
906
|
+
obj = self.panel.objview.get_sel_objects(include_groups=True)[0]
|
|
907
|
+
dlg.set_obj(obj)
|
|
908
|
+
if not exec_dialog(dlg):
|
|
909
|
+
return
|
|
910
|
+
self.run_feature("average_profile", param, title=title, edit=False)
|
|
911
|
+
|
|
912
|
+
@qt_try_except()
|
|
913
|
+
def compute_radial_profile(
|
|
914
|
+
self, param: sigima.params.RadialProfileParam | None = None
|
|
915
|
+
) -> None:
|
|
916
|
+
"""Compute radial profile
|
|
917
|
+
with :py:func:`sigima.proc.image.radial_profile`"""
|
|
918
|
+
title = _("Radial profile")
|
|
919
|
+
edit, param = self.init_param(param, sipi.RadialProfileParam, title)
|
|
920
|
+
if edit:
|
|
921
|
+
obj = self.panel.objview.get_sel_objects(include_groups=True)[0]
|
|
922
|
+
param.update_from_obj(obj)
|
|
923
|
+
self.run_feature("radial_profile", param, title=title, edit=edit)
|
|
924
|
+
|
|
925
|
+
@qt_try_except()
|
|
926
|
+
def distribute_on_grid(self, param: sigima.params.GridParam | None = None) -> None:
|
|
927
|
+
"""Distribute images on a grid"""
|
|
928
|
+
title = _("Distribute on grid")
|
|
929
|
+
edit, param = self.init_param(param, sipi.GridParam, title)
|
|
930
|
+
if edit and not param.edit(parent=self.mainwindow):
|
|
931
|
+
return
|
|
932
|
+
objs = self.panel.objview.get_sel_objects(include_groups=True)
|
|
933
|
+
g_row, g_col, x0, y0, x0_0, y0_0 = 0, 0, 0.0, 0.0, 0.0, 0.0
|
|
934
|
+
dx0, dy0 = 0.0, 0.0
|
|
935
|
+
with create_progress_bar(self.panel, title, max_=len(objs)) as progress:
|
|
936
|
+
for i_row, obj in enumerate(objs):
|
|
937
|
+
progress.setValue(i_row + 1)
|
|
938
|
+
QW.QApplication.processEvents()
|
|
939
|
+
if progress.wasCanceled():
|
|
940
|
+
break
|
|
941
|
+
if i_row == 0:
|
|
942
|
+
if obj.is_uniform_coords:
|
|
943
|
+
x0_0, y0_0 = x0, y0 = obj.x0, obj.y0
|
|
944
|
+
else:
|
|
945
|
+
x0_0, y0_0 = x0, y0 = obj.xcoords[0], obj.ycoords[0]
|
|
946
|
+
else:
|
|
947
|
+
if obj.is_uniform_coords:
|
|
948
|
+
dx0, dy0 = x0 - obj.x0, y0 - obj.y0
|
|
949
|
+
obj.x0 += dx0
|
|
950
|
+
obj.y0 += dy0
|
|
951
|
+
else:
|
|
952
|
+
dx0, dy0 = x0 - obj.xcoords[0], y0 - obj.ycoords[0]
|
|
953
|
+
obj.xcoords += dx0
|
|
954
|
+
obj.ycoords += dy0
|
|
955
|
+
apply_geometry_transform(obj, "translate", dx=dx0, dy=dy0)
|
|
956
|
+
sipi.transformer.transform_roi(obj, "translate", dx=dx0, dy=dy0)
|
|
957
|
+
|
|
958
|
+
# Get image width and height
|
|
959
|
+
if obj.is_uniform_coords:
|
|
960
|
+
img_width, img_height = obj.width, obj.height
|
|
961
|
+
else:
|
|
962
|
+
img_width = obj.xcoords[-1] - obj.xcoords[0]
|
|
963
|
+
img_height = obj.ycoords[-1] - obj.ycoords[0]
|
|
964
|
+
|
|
965
|
+
if param.direction == "row":
|
|
966
|
+
# Distributing images over rows
|
|
967
|
+
sign = np.sign(param.rows)
|
|
968
|
+
g_row = (g_row + sign) % param.rows
|
|
969
|
+
y0 += (img_height + param.rowspac) * sign
|
|
970
|
+
if g_row == 0:
|
|
971
|
+
g_col += 1
|
|
972
|
+
x0 += img_width + param.colspac
|
|
973
|
+
y0 = y0_0
|
|
974
|
+
else:
|
|
975
|
+
# Distributing images over columns
|
|
976
|
+
sign = np.sign(param.cols)
|
|
977
|
+
g_col = (g_col + sign) % param.cols
|
|
978
|
+
x0 += (img_width + param.colspac) * sign
|
|
979
|
+
if g_col == 0:
|
|
980
|
+
g_row += 1
|
|
981
|
+
x0 = x0_0
|
|
982
|
+
y0 += img_height + param.rowspac
|
|
983
|
+
self.panel.refresh_plot("selected", True, False)
|
|
984
|
+
|
|
985
|
+
@qt_try_except()
|
|
986
|
+
def reset_positions(self) -> None:
|
|
987
|
+
"""Reset image positions"""
|
|
988
|
+
x0_0, y0_0 = 0.0, 0.0
|
|
989
|
+
dx0, dy0 = 0.0, 0.0
|
|
990
|
+
objs = self.panel.objview.get_sel_objects(include_groups=True)
|
|
991
|
+
for i_row, obj in enumerate(objs):
|
|
992
|
+
if i_row == 0:
|
|
993
|
+
if obj.is_uniform_coords:
|
|
994
|
+
x0_0, y0_0 = obj.x0, obj.y0
|
|
995
|
+
else:
|
|
996
|
+
x0_0, y0_0 = obj.xcoords[0], obj.ycoords[0]
|
|
997
|
+
else:
|
|
998
|
+
if obj.is_uniform_coords:
|
|
999
|
+
dx0, dy0 = x0_0 - obj.x0, y0_0 - obj.y0
|
|
1000
|
+
obj.x0 += dx0
|
|
1001
|
+
obj.y0 += dy0
|
|
1002
|
+
else:
|
|
1003
|
+
dx0, dy0 = x0_0 - obj.xcoords[0], y0_0 - obj.ycoords[0]
|
|
1004
|
+
obj.xcoords += dx0
|
|
1005
|
+
obj.ycoords += dy0
|
|
1006
|
+
apply_geometry_transform(obj, "translate", dx=dx0, dy=dy0)
|
|
1007
|
+
sipi.transformer.transform_roi(obj, "translate", dx=dx0, dy=dy0)
|
|
1008
|
+
self.panel.refresh_plot("selected", True, False)
|
|
1009
|
+
|
|
1010
|
+
# ------Image Processing
|
|
1011
|
+
@qt_try_except()
|
|
1012
|
+
def compute_offset_correction(self, param: ROI2DParam | None = None) -> None:
|
|
1013
|
+
"""Compute offset correction
|
|
1014
|
+
with :py:func:`sigima.proc.image.offset_correction`"""
|
|
1015
|
+
obj = self.panel.objview.get_sel_objects(include_groups=True)[0]
|
|
1016
|
+
if param is None:
|
|
1017
|
+
dlg = imagebackground.ImageBackgroundDialog(obj, parent=self.mainwindow)
|
|
1018
|
+
if exec_dialog(dlg):
|
|
1019
|
+
x0, y0, x1, y1 = dlg.get_rect_coords()
|
|
1020
|
+
param = ROI2DParam.create(
|
|
1021
|
+
geometry="rectangle",
|
|
1022
|
+
x0=int(x0),
|
|
1023
|
+
y0=int(y0),
|
|
1024
|
+
dx=int(x1 - x0),
|
|
1025
|
+
dy=int(y1 - y0),
|
|
1026
|
+
)
|
|
1027
|
+
else:
|
|
1028
|
+
return
|
|
1029
|
+
self.run_feature("offset_correction", param)
|
|
1030
|
+
|
|
1031
|
+
@qt_try_except()
|
|
1032
|
+
def compute_erase(self, roi: ImageROI | None = None) -> None:
|
|
1033
|
+
"""Erase area in the image as defined by a region of interest
|
|
1034
|
+
|
|
1035
|
+
Args:
|
|
1036
|
+
roi: Region of interest to erase
|
|
1037
|
+
"""
|
|
1038
|
+
if roi is None or roi.is_empty():
|
|
1039
|
+
roi = self.edit_roi_graphically(mode="define")
|
|
1040
|
+
if roi is None or roi.is_empty():
|
|
1041
|
+
return
|
|
1042
|
+
obj = self.panel.objview.get_sel_objects(include_groups=True)[0]
|
|
1043
|
+
params = roi.to_params(obj)
|
|
1044
|
+
|
|
1045
|
+
# TODO: This `compute_1_to_1` call is not ideal, as it passes a list of
|
|
1046
|
+
# parameter sets (`params` is a list of `DataSet` objects) instead of a single
|
|
1047
|
+
# parameter set as expected by the method. Currently, the method implementation
|
|
1048
|
+
# is compatible with this call, and it simply passes the second argument through
|
|
1049
|
+
# to the `extract_rois` function. However, this should be rectified in the
|
|
1050
|
+
# future to ensure that the method signature and its usage are consistent.
|
|
1051
|
+
# The question is: should we pass a list of `DataSet` objects or directly a
|
|
1052
|
+
# `ImageROI` object?
|
|
1053
|
+
# (same as `_extract_multiple_roi_in_single_object`)
|
|
1054
|
+
self.compute_1_to_1(sipi.erase, params, title=_("Erase area"), edit=False)
|
|
1055
|
+
|
|
1056
|
+
@qt_try_except()
|
|
1057
|
+
def compute_all_threshold(self) -> None:
|
|
1058
|
+
"""Compute all threshold algorithms
|
|
1059
|
+
using the following functions:
|
|
1060
|
+
|
|
1061
|
+
- :py:func:`sigima.proc.image.threshold_isodata`
|
|
1062
|
+
- :py:func:`sigima.proc.image.threshold_li`
|
|
1063
|
+
- :py:func:`sigima.proc.image.threshold_mean`
|
|
1064
|
+
- :py:func:`sigima.proc.image.threshold_minimum`
|
|
1065
|
+
- :py:func:`sigima.proc.image.threshold_otsu`
|
|
1066
|
+
- :py:func:`sigima.proc.image.threshold_triangle`
|
|
1067
|
+
- :py:func:`sigima.proc.image.threshold_yen`
|
|
1068
|
+
"""
|
|
1069
|
+
self.compute_multiple_1_to_1(
|
|
1070
|
+
[
|
|
1071
|
+
sipi.threshold_isodata,
|
|
1072
|
+
sipi.threshold_li,
|
|
1073
|
+
sipi.threshold_mean,
|
|
1074
|
+
sipi.threshold_minimum,
|
|
1075
|
+
sipi.threshold_otsu,
|
|
1076
|
+
sipi.threshold_triangle,
|
|
1077
|
+
sipi.threshold_yen,
|
|
1078
|
+
],
|
|
1079
|
+
None,
|
|
1080
|
+
"Threshold",
|
|
1081
|
+
edit=False,
|
|
1082
|
+
)
|
|
1083
|
+
|
|
1084
|
+
@qt_try_except()
|
|
1085
|
+
def compute_all_denoise(self, params: list | None = None) -> None:
|
|
1086
|
+
"""Compute all denoising filters
|
|
1087
|
+
using the following functions:
|
|
1088
|
+
|
|
1089
|
+
- :py:func:`sigima.proc.image.denoise_tv`
|
|
1090
|
+
- :py:func:`sigima.proc.image.denoise_bilateral`
|
|
1091
|
+
- :py:func:`sigima.proc.image.denoise_wavelet`
|
|
1092
|
+
- :py:func:`sigima.proc.image.denoise_tophat`
|
|
1093
|
+
"""
|
|
1094
|
+
if params is not None:
|
|
1095
|
+
assert len(params) == 4, "Wrong number of parameters (4 expected)"
|
|
1096
|
+
funcs = [
|
|
1097
|
+
sipi.denoise_tv,
|
|
1098
|
+
sipi.denoise_bilateral,
|
|
1099
|
+
sipi.denoise_wavelet,
|
|
1100
|
+
sipi.denoise_tophat,
|
|
1101
|
+
]
|
|
1102
|
+
edit = params is None
|
|
1103
|
+
if edit:
|
|
1104
|
+
params = []
|
|
1105
|
+
for paramclass, title in (
|
|
1106
|
+
(sipi.DenoiseTVParam, _("Total variation denoising")),
|
|
1107
|
+
(sipi.DenoiseBilateralParam, _("Bilateral filter denoising")),
|
|
1108
|
+
(sipi.DenoiseWaveletParam, _("Wavelet denoising")),
|
|
1109
|
+
(sipi.MorphologyParam, _("Denoise / Top-Hat")),
|
|
1110
|
+
):
|
|
1111
|
+
param = paramclass(title)
|
|
1112
|
+
self.update_param_defaults(param)
|
|
1113
|
+
params.append(param)
|
|
1114
|
+
self.compute_multiple_1_to_1(funcs, params, "Denoise", edit=edit)
|
|
1115
|
+
|
|
1116
|
+
@qt_try_except()
|
|
1117
|
+
def compute_all_morphology(
|
|
1118
|
+
self, param: sigima.params.MorphologyParam | None = None
|
|
1119
|
+
) -> None:
|
|
1120
|
+
"""Compute all morphology filters
|
|
1121
|
+
using the following functions:
|
|
1122
|
+
|
|
1123
|
+
- :py:func:`sigima.proc.image.white_tophat`
|
|
1124
|
+
- :py:func:`sigima.proc.image.black_tophat`
|
|
1125
|
+
- :py:func:`sigima.proc.image.erosion`
|
|
1126
|
+
- :py:func:`sigima.proc.image.dilation`
|
|
1127
|
+
- :py:func:`sigima.proc.image.opening`
|
|
1128
|
+
- :py:func:`sigima.proc.image.closing`
|
|
1129
|
+
"""
|
|
1130
|
+
if param is None:
|
|
1131
|
+
param = sipi.MorphologyParam()
|
|
1132
|
+
if not param.edit(parent=self.mainwindow):
|
|
1133
|
+
return
|
|
1134
|
+
funcs = [
|
|
1135
|
+
sipi.white_tophat,
|
|
1136
|
+
sipi.black_tophat,
|
|
1137
|
+
sipi.erosion,
|
|
1138
|
+
sipi.dilation,
|
|
1139
|
+
sipi.opening,
|
|
1140
|
+
sipi.closing,
|
|
1141
|
+
]
|
|
1142
|
+
self.compute_multiple_1_to_1(funcs, [param] * len(funcs), "Morph", edit=False)
|
|
1143
|
+
|
|
1144
|
+
@qt_try_except()
|
|
1145
|
+
def compute_all_edges(self) -> None:
|
|
1146
|
+
"""Compute all edge detection algorithms.
|
|
1147
|
+
|
|
1148
|
+
This function calls the following edge detection algorithms:
|
|
1149
|
+
|
|
1150
|
+
- :py:func:`sigima.proc.image.canny`
|
|
1151
|
+
- :py:func:`sigima.proc.image.farid`
|
|
1152
|
+
- :py:func:`sigima.proc.image.farid_h`
|
|
1153
|
+
- :py:func:`sigima.proc.image.farid_v`
|
|
1154
|
+
- :py:func:`sigima.proc.image.laplace`
|
|
1155
|
+
- :py:func:`sigima.proc.image.prewitt`
|
|
1156
|
+
- :py:func:`sigima.proc.image.prewitt_h`
|
|
1157
|
+
- :py:func:`sigima.proc.image.prewitt_v`
|
|
1158
|
+
- :py:func:`sigima.proc.image.roberts`
|
|
1159
|
+
- :py:func:`sigima.proc.image.scharr`
|
|
1160
|
+
- :py:func:`sigima.proc.image.scharr_h`
|
|
1161
|
+
- :py:func:`sigima.proc.image.scharr_v`
|
|
1162
|
+
- :py:func:`sigima.proc.image.sobel`
|
|
1163
|
+
- :py:func:`sigima.proc.image.sobel_h`
|
|
1164
|
+
- :py:func:`sigima.proc.image.sobel_v`
|
|
1165
|
+
"""
|
|
1166
|
+
funcs = [
|
|
1167
|
+
sipi.canny,
|
|
1168
|
+
sipi.farid,
|
|
1169
|
+
sipi.farid_h,
|
|
1170
|
+
sipi.farid_v,
|
|
1171
|
+
sipi.laplace,
|
|
1172
|
+
sipi.prewitt,
|
|
1173
|
+
sipi.prewitt_h,
|
|
1174
|
+
sipi.prewitt_v,
|
|
1175
|
+
sipi.roberts,
|
|
1176
|
+
sipi.scharr,
|
|
1177
|
+
sipi.scharr_h,
|
|
1178
|
+
sipi.scharr_v,
|
|
1179
|
+
sipi.sobel,
|
|
1180
|
+
sipi.sobel_h,
|
|
1181
|
+
sipi.sobel_v,
|
|
1182
|
+
]
|
|
1183
|
+
self.compute_multiple_1_to_1(funcs, None, "Edges")
|
|
1184
|
+
|
|
1185
|
+
@qt_try_except()
|
|
1186
|
+
def _extract_multiple_roi_in_single_object(self, params: list[ROI2DParam]) -> None:
|
|
1187
|
+
"""Extract multiple Regions Of Interest (ROIs) from data in a single object"""
|
|
1188
|
+
# TODO: This `compute_1_to_1` call is not ideal, as it passes a list of
|
|
1189
|
+
# parameter sets (`params` is a list of `DataSet` objects) instead of a single
|
|
1190
|
+
# parameter set as expected by the method. Currently, the method implementation
|
|
1191
|
+
# is compatible with this call, and it simply passes the second argument through
|
|
1192
|
+
# to the `extract_rois` function. However, this should be rectified in the
|
|
1193
|
+
# future to ensure that the method signature and its usage are consistent.
|
|
1194
|
+
# The question is: should we pass a list of `DataSet` objects or directly a
|
|
1195
|
+
# `ImageROI` object?
|
|
1196
|
+
# (same as `compute_erase`)
|
|
1197
|
+
self.compute_1_to_1(sipi.extract_rois, params, title=_("Extract ROI"))
|
|
1198
|
+
|
|
1199
|
+
# ------Image Analysis
|
|
1200
|
+
@qt_try_except()
|
|
1201
|
+
def compute_peak_detection(
|
|
1202
|
+
self, param: sigima.params.Peak2DDetectionParam | None = None
|
|
1203
|
+
) -> dict[str, GeometryResult]:
|
|
1204
|
+
"""Compute 2D peak detection
|
|
1205
|
+
with :py:func:`sigima.proc.image.peak_detection`"""
|
|
1206
|
+
edit, param = self.init_param(
|
|
1207
|
+
param, sipi.Peak2DDetectionParam, _("Peak detection")
|
|
1208
|
+
)
|
|
1209
|
+
if edit:
|
|
1210
|
+
data = self.panel.objview.get_sel_objects(include_groups=True)[0].data
|
|
1211
|
+
param.size = max(min(data.shape) // 40, 50)
|
|
1212
|
+
|
|
1213
|
+
# Run peak detection (ROI creation is handled automatically by base class)
|
|
1214
|
+
return self.run_feature("peak_detection", param, edit=edit)
|