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
datalab/gui/docks.py
ADDED
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Docks
|
|
5
|
+
=====
|
|
6
|
+
|
|
7
|
+
The :mod:`datalab.gui.docks` module provides the dockable widgets for the
|
|
8
|
+
DataLab main window.
|
|
9
|
+
|
|
10
|
+
Plot widget
|
|
11
|
+
-----------
|
|
12
|
+
|
|
13
|
+
.. autoclass:: DataLabPlotWidget
|
|
14
|
+
|
|
15
|
+
Dockable plot widget
|
|
16
|
+
--------------------
|
|
17
|
+
|
|
18
|
+
.. autoclass:: DockablePlotWidget
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
import warnings
|
|
24
|
+
from typing import TYPE_CHECKING
|
|
25
|
+
|
|
26
|
+
import numpy as np
|
|
27
|
+
import scipy.integrate as spt
|
|
28
|
+
from guidata.configtools import get_icon, get_image_file_path
|
|
29
|
+
from guidata.qthelpers import create_action, is_dark_theme
|
|
30
|
+
from guidata.widgets.dockable import DockableWidget
|
|
31
|
+
from plotpy.constants import PlotType
|
|
32
|
+
from plotpy.items import CurveItem
|
|
33
|
+
from plotpy.panels import XCrossSection, YCrossSection
|
|
34
|
+
from plotpy.plot import PlotOptions, PlotWidget
|
|
35
|
+
from plotpy.tools import (
|
|
36
|
+
BasePlotMenuTool,
|
|
37
|
+
CurveStatsTool,
|
|
38
|
+
DeleteItemTool,
|
|
39
|
+
DisplayCoordsTool,
|
|
40
|
+
DoAutoscaleTool,
|
|
41
|
+
EditItemDataTool,
|
|
42
|
+
ExportItemDataTool,
|
|
43
|
+
ImageStatsTool,
|
|
44
|
+
ItemCenterTool,
|
|
45
|
+
RectangularSelectionTool,
|
|
46
|
+
RectZoomTool,
|
|
47
|
+
SelectTool,
|
|
48
|
+
YRangeCursorTool,
|
|
49
|
+
)
|
|
50
|
+
from plotpy.tools.image import get_stats as get_image_stats
|
|
51
|
+
from qtpy import QtCore as QC
|
|
52
|
+
from qtpy import QtGui as QG
|
|
53
|
+
from qtpy import QtWidgets as QW
|
|
54
|
+
from qtpy.QtWidgets import QApplication, QMainWindow
|
|
55
|
+
from sigima.objects import create_signal
|
|
56
|
+
from sigima.tools.signal import pulse
|
|
57
|
+
from skimage import measure
|
|
58
|
+
|
|
59
|
+
from datalab.config import APP_NAME, Conf, _
|
|
60
|
+
|
|
61
|
+
if TYPE_CHECKING:
|
|
62
|
+
from plotpy.items.image.base import BaseImageItem
|
|
63
|
+
from plotpy.plot import BasePlot
|
|
64
|
+
from plotpy.styles import BaseImageParam
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class CurveStatsToolFunctions:
|
|
68
|
+
"""Statistical functions for `CurveStatsTool` and `YRangeCursorTool`"""
|
|
69
|
+
|
|
70
|
+
@classmethod
|
|
71
|
+
def set_labelfuncs(cls, statstool: CurveStatsTool) -> None:
|
|
72
|
+
"""Set label functions for the statistics tool"""
|
|
73
|
+
if isinstance(statstool, CurveStatsTool):
|
|
74
|
+
labelfuncs = (
|
|
75
|
+
("%g < x < %g", lambda *args: cls.nan_min_max(args[0])),
|
|
76
|
+
("%g < y < %g", lambda *args: cls.nan_min_max(args[1])),
|
|
77
|
+
("∆x=%g", lambda *args: cls.nan_delta(args[0])),
|
|
78
|
+
("∆y=%g", lambda *args: cls.nan_delta(args[1])),
|
|
79
|
+
("<y>=%g", lambda *args: cls.nan_mean(args[1])),
|
|
80
|
+
("σ(y)=%g", lambda *args: cls.nan_std(args[1])),
|
|
81
|
+
("∑(y)=%g", lambda *args: spt.trapezoid(args[1])),
|
|
82
|
+
("∫ydx=%g<br>", lambda *args: spt.trapezoid(args[1], args[0])),
|
|
83
|
+
("FWHM=%s", cls.fwhm_info),
|
|
84
|
+
("∆x<sub>RISE 10-90</sub>=%s", cls.rise_time_info),
|
|
85
|
+
(
|
|
86
|
+
"∆x<sub>RISE 20-80</sub>=%s",
|
|
87
|
+
lambda x, y: cls.rise_time_info(x, y, 0.2, 0.8),
|
|
88
|
+
),
|
|
89
|
+
("∆x<sub>FALL 90-10</sub>=%s", cls.fall_time_info),
|
|
90
|
+
(
|
|
91
|
+
"∆x<sub>FALL 80-20</sub>=%s",
|
|
92
|
+
lambda x, y: cls.fall_time_info(x, y, 0.8, 0.2),
|
|
93
|
+
),
|
|
94
|
+
)
|
|
95
|
+
else: # YRangeCursorTool
|
|
96
|
+
labelfuncs = (
|
|
97
|
+
("%g < y < %g", lambda ymin, ymax: (ymin, ymax)),
|
|
98
|
+
("∆y=%g", lambda ymin, ymax: ymax - ymin),
|
|
99
|
+
)
|
|
100
|
+
statstool.set_labelfuncs(labelfuncs)
|
|
101
|
+
|
|
102
|
+
@staticmethod
|
|
103
|
+
def nan_min_max(arr: np.ndarray) -> tuple[float, float]:
|
|
104
|
+
"""Return min/max tuple"""
|
|
105
|
+
with warnings.catch_warnings():
|
|
106
|
+
warnings.simplefilter("ignore", RuntimeWarning)
|
|
107
|
+
min_val = np.nanmin(arr)
|
|
108
|
+
max_val = np.nanmax(arr)
|
|
109
|
+
return (min_val, max_val)
|
|
110
|
+
|
|
111
|
+
@staticmethod
|
|
112
|
+
def nan_delta(arr: np.ndarray) -> float:
|
|
113
|
+
"""Return delta value, ignoring NaNs"""
|
|
114
|
+
with warnings.catch_warnings():
|
|
115
|
+
warnings.simplefilter("ignore", RuntimeWarning)
|
|
116
|
+
delta_val = np.nanmax(arr) - np.nanmin(arr)
|
|
117
|
+
return delta_val
|
|
118
|
+
|
|
119
|
+
@staticmethod
|
|
120
|
+
def nan_mean(arr: np.ndarray) -> float:
|
|
121
|
+
"""Return mean value, ignoring NaNs"""
|
|
122
|
+
with warnings.catch_warnings():
|
|
123
|
+
warnings.simplefilter("ignore", RuntimeWarning)
|
|
124
|
+
mean_val = np.nanmean(arr)
|
|
125
|
+
return mean_val
|
|
126
|
+
|
|
127
|
+
@staticmethod
|
|
128
|
+
def nan_std(arr: np.ndarray) -> float:
|
|
129
|
+
"""Return standard deviation, ignoring NaNs"""
|
|
130
|
+
with warnings.catch_warnings():
|
|
131
|
+
warnings.simplefilter("ignore", RuntimeWarning)
|
|
132
|
+
std_val = np.nanstd(arr)
|
|
133
|
+
return std_val
|
|
134
|
+
|
|
135
|
+
@staticmethod
|
|
136
|
+
def fwhm_info(x, y):
|
|
137
|
+
"""Return FWHM information string"""
|
|
138
|
+
try:
|
|
139
|
+
with warnings.catch_warnings(record=True) as w:
|
|
140
|
+
x0, _y0, x1, _y1 = pulse.fwhm(x, y, "zero-crossing")
|
|
141
|
+
wstr = " ⚠️" if w else ""
|
|
142
|
+
except (ValueError, ZeroDivisionError, pulse.InvalidSignalError):
|
|
143
|
+
return "🛑"
|
|
144
|
+
return f"{x1 - x0:g}{wstr}"
|
|
145
|
+
|
|
146
|
+
@staticmethod
|
|
147
|
+
def rise_time_info(x, y, start_ratio=0.1, end_ratio=0.9):
|
|
148
|
+
"""Return rise time information string"""
|
|
149
|
+
try:
|
|
150
|
+
with warnings.catch_warnings(record=True) as w:
|
|
151
|
+
dt = pulse.get_rise_time(x, y, start_ratio, end_ratio)
|
|
152
|
+
wstr = " ⚠️" if w else ""
|
|
153
|
+
if dt is None:
|
|
154
|
+
return "🛑"
|
|
155
|
+
except (ValueError, ZeroDivisionError, pulse.InvalidSignalError):
|
|
156
|
+
return "🛑"
|
|
157
|
+
return f"{dt:g}{wstr}"
|
|
158
|
+
|
|
159
|
+
@staticmethod
|
|
160
|
+
def fall_time_info(x, y, start_ratio=0.9, end_ratio=0.1):
|
|
161
|
+
"""Return fall time information string"""
|
|
162
|
+
try:
|
|
163
|
+
with warnings.catch_warnings(record=True) as w:
|
|
164
|
+
dt = pulse.get_fall_time(x, y, start_ratio, end_ratio)
|
|
165
|
+
wstr = " ⚠️" if w else ""
|
|
166
|
+
if dt is None:
|
|
167
|
+
return "🛑"
|
|
168
|
+
except (ValueError, ZeroDivisionError, pulse.InvalidSignalError):
|
|
169
|
+
return "🛑"
|
|
170
|
+
return f"{dt:g}{wstr}"
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def get_more_image_stats(
|
|
174
|
+
item: BaseImageItem,
|
|
175
|
+
x0: float,
|
|
176
|
+
y0: float,
|
|
177
|
+
x1: float,
|
|
178
|
+
y1: float,
|
|
179
|
+
) -> str:
|
|
180
|
+
"""Return formatted string with stats on image rectangular area
|
|
181
|
+
(output should be compatible with AnnotatedShape.get_info)
|
|
182
|
+
|
|
183
|
+
Args:
|
|
184
|
+
item: image item
|
|
185
|
+
x0: X0
|
|
186
|
+
y0: Y0
|
|
187
|
+
x1: X1
|
|
188
|
+
y1: Y1
|
|
189
|
+
"""
|
|
190
|
+
with warnings.catch_warnings():
|
|
191
|
+
warnings.simplefilter("ignore", UserWarning)
|
|
192
|
+
info = get_image_stats(item, x0, y0, x1, y1)
|
|
193
|
+
|
|
194
|
+
ix0, iy0, ix1, iy1 = item.get_closest_index_rect(x0, y0, x1, y1)
|
|
195
|
+
data = item.data[iy0:iy1, ix0:ix1]
|
|
196
|
+
p: BaseImageParam = item.param
|
|
197
|
+
xunit, yunit, zunit = p.get_units()
|
|
198
|
+
|
|
199
|
+
integral = np.nansum(data)
|
|
200
|
+
integral_fmt = r"%.3e " + zunit
|
|
201
|
+
info += f"<br>∑ = {integral_fmt % integral}"
|
|
202
|
+
|
|
203
|
+
if xunit == yunit:
|
|
204
|
+
surfacefmt = p.xformat.split()[0] + " " + xunit
|
|
205
|
+
if xunit != "":
|
|
206
|
+
surfacefmt = surfacefmt + "²"
|
|
207
|
+
surface = abs((x1 - x0) * (y1 - y0))
|
|
208
|
+
info += f"<br>A = {surfacefmt % surface}"
|
|
209
|
+
if xunit is not None and zunit is not None:
|
|
210
|
+
if surface != 0:
|
|
211
|
+
density = integral / surface
|
|
212
|
+
densityfmt = r"%.3e"
|
|
213
|
+
if xunit and zunit:
|
|
214
|
+
densityfmt += " " + zunit + "/" + xunit + "²"
|
|
215
|
+
info = info + f"<br>ρ = {densityfmt % density}"
|
|
216
|
+
|
|
217
|
+
c_i, c_j = measure.centroid(data)
|
|
218
|
+
c_x, c_y = item.get_plot_coordinates(c_j + ix0, c_i + iy0)
|
|
219
|
+
info += "<br>" + "<br>".join(
|
|
220
|
+
[
|
|
221
|
+
"C|x = " + p.xformat % c_x,
|
|
222
|
+
"C|y = " + p.yformat % c_y,
|
|
223
|
+
]
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
return info
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def profile_to_signal(plot: BasePlot, panel: XCrossSection | YCrossSection) -> None:
|
|
230
|
+
"""Send cross section curve to DataLab's signal list
|
|
231
|
+
|
|
232
|
+
Args:
|
|
233
|
+
panel: Cross section panel
|
|
234
|
+
"""
|
|
235
|
+
win = None
|
|
236
|
+
for win in QApplication.topLevelWidgets():
|
|
237
|
+
if isinstance(win, QMainWindow):
|
|
238
|
+
break
|
|
239
|
+
if win is None or win.objectName() != APP_NAME:
|
|
240
|
+
# pylint: disable=import-outside-toplevel
|
|
241
|
+
# pylint: disable=cyclic-import
|
|
242
|
+
from datalab.gui import main
|
|
243
|
+
|
|
244
|
+
# Note : this is the only way to retrieve the DataLab main window instance
|
|
245
|
+
# when the CrossSectionItem object is embedded into an image widget
|
|
246
|
+
# parented to another main window.
|
|
247
|
+
win = main.DLMainWindow.get_instance()
|
|
248
|
+
assert win is not None # Should never happen
|
|
249
|
+
|
|
250
|
+
for item in panel.cs_plot.get_items():
|
|
251
|
+
if not isinstance(item, CurveItem):
|
|
252
|
+
continue
|
|
253
|
+
x, y, _dx, _dy = item.get_data()
|
|
254
|
+
if x is None or y is None or x.size == 0 or y.size == 0:
|
|
255
|
+
continue
|
|
256
|
+
|
|
257
|
+
signal = create_signal(item.param.label)
|
|
258
|
+
|
|
259
|
+
if isinstance(panel, YCrossSection):
|
|
260
|
+
signal.set_xydata(y, x)
|
|
261
|
+
xaxis_name = "left"
|
|
262
|
+
xunit = plot.get_axis_unit("bottom")
|
|
263
|
+
if xunit:
|
|
264
|
+
signal.title += " " + xunit
|
|
265
|
+
else:
|
|
266
|
+
signal.set_xydata(x, y)
|
|
267
|
+
xaxis_name = "bottom"
|
|
268
|
+
yunit = plot.get_axis_unit("left")
|
|
269
|
+
if yunit:
|
|
270
|
+
signal.title += " " + yunit
|
|
271
|
+
|
|
272
|
+
signal.ylabel = plot.get_axis_title("right")
|
|
273
|
+
signal.yunit = plot.get_axis_unit("right")
|
|
274
|
+
signal.xlabel = plot.get_axis_title(xaxis_name)
|
|
275
|
+
signal.xunit = plot.get_axis_unit(xaxis_name)
|
|
276
|
+
|
|
277
|
+
win.signalpanel.add_object(signal)
|
|
278
|
+
|
|
279
|
+
# Show DataLab main window on top, if not already visible
|
|
280
|
+
win.show()
|
|
281
|
+
win.raise_()
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
class DataLabPlotWidget(PlotWidget):
|
|
285
|
+
"""DataLab PlotWidget
|
|
286
|
+
|
|
287
|
+
This class is a subclass of `plotpy.plot.PlotWidget` that provides a
|
|
288
|
+
customized widget for DataLab, with a specific set of tools and a
|
|
289
|
+
customized appearance.
|
|
290
|
+
|
|
291
|
+
Args:
|
|
292
|
+
plot_type: Plot type
|
|
293
|
+
"""
|
|
294
|
+
|
|
295
|
+
def __init__(self, plot_type: PlotType) -> None:
|
|
296
|
+
# Get autoscale margin from configuration based on plot type
|
|
297
|
+
if plot_type == PlotType.CURVE:
|
|
298
|
+
autoscale_margin = Conf.view.sig_autoscale_margin_percent.get()
|
|
299
|
+
elif plot_type == PlotType.IMAGE:
|
|
300
|
+
autoscale_margin = Conf.view.ima_autoscale_margin_percent.get()
|
|
301
|
+
else:
|
|
302
|
+
# For AUTO or MANUAL types, use signal margin as default
|
|
303
|
+
autoscale_margin = Conf.view.sig_autoscale_margin_percent.get()
|
|
304
|
+
|
|
305
|
+
super().__init__(
|
|
306
|
+
options=PlotOptions(
|
|
307
|
+
type=plot_type,
|
|
308
|
+
show_axes_tab=False,
|
|
309
|
+
autoscale_margin_percent=autoscale_margin,
|
|
310
|
+
),
|
|
311
|
+
toolbar=True,
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
def __register_standard_tools(self) -> None:
|
|
315
|
+
"""Register standard tools
|
|
316
|
+
|
|
317
|
+
The only differences with the `manager.register_standard_tools` method are
|
|
318
|
+
the following:
|
|
319
|
+
|
|
320
|
+
1. We don't register the `BasePlotMenuTool, "axes"` tool, because it is not
|
|
321
|
+
compatible with DataLab's approach to axes management.
|
|
322
|
+
2. We don't register the `ItemListPanelTool` tool (this intends to prevent
|
|
323
|
+
the user from accessing the item list panel, and thus, the parameters of all
|
|
324
|
+
the items - some of them are read-only and should not be modified, like the
|
|
325
|
+
annotations for example).
|
|
326
|
+
"""
|
|
327
|
+
mgr = self.manager
|
|
328
|
+
select_tool = mgr.add_tool(SelectTool)
|
|
329
|
+
mgr.set_default_tool(select_tool)
|
|
330
|
+
mgr.add_tool(RectangularSelectionTool, intersect=False)
|
|
331
|
+
mgr.add_tool(RectZoomTool)
|
|
332
|
+
mgr.add_tool(DoAutoscaleTool)
|
|
333
|
+
mgr.add_tool(BasePlotMenuTool, "item")
|
|
334
|
+
mgr.add_tool(ExportItemDataTool)
|
|
335
|
+
mgr.add_tool(EditItemDataTool)
|
|
336
|
+
mgr.add_tool(ItemCenterTool)
|
|
337
|
+
mgr.add_tool(DeleteItemTool)
|
|
338
|
+
mgr.add_separator_tool()
|
|
339
|
+
mgr.add_tool(BasePlotMenuTool, "grid")
|
|
340
|
+
mgr.add_tool(DisplayCoordsTool)
|
|
341
|
+
|
|
342
|
+
def __register_other_tools(self) -> None:
|
|
343
|
+
"""Register other tools"""
|
|
344
|
+
mgr = self.manager
|
|
345
|
+
mgr.add_separator_tool()
|
|
346
|
+
if self.options.type == PlotType.CURVE:
|
|
347
|
+
mgr.register_curve_tools()
|
|
348
|
+
xstatstool = mgr.get_tool(CurveStatsTool)
|
|
349
|
+
CurveStatsToolFunctions.set_labelfuncs(xstatstool)
|
|
350
|
+
ystatstool = mgr.get_tool(YRangeCursorTool)
|
|
351
|
+
CurveStatsToolFunctions.set_labelfuncs(ystatstool)
|
|
352
|
+
else:
|
|
353
|
+
mgr.register_image_tools()
|
|
354
|
+
# Customizing the ImageStatsTool
|
|
355
|
+
statstool = mgr.get_tool(ImageStatsTool)
|
|
356
|
+
statstool.set_stats_func(get_more_image_stats, replace=True)
|
|
357
|
+
# Customizing the X and Y cross section panels
|
|
358
|
+
plot = mgr.get_plot()
|
|
359
|
+
for panel in (mgr.get_xcs_panel(), mgr.get_ycs_panel()):
|
|
360
|
+
to_signal_action = create_action(
|
|
361
|
+
panel,
|
|
362
|
+
_("Process signal"),
|
|
363
|
+
icon=get_icon("to_signal.svg"),
|
|
364
|
+
triggered=lambda panel=panel: profile_to_signal(plot, panel),
|
|
365
|
+
)
|
|
366
|
+
tb = panel.toolbar
|
|
367
|
+
tb.insertSeparator(tb.actions()[0])
|
|
368
|
+
tb.insertAction(tb.actions()[0], to_signal_action)
|
|
369
|
+
|
|
370
|
+
mgr.add_separator_tool()
|
|
371
|
+
mgr.register_other_tools()
|
|
372
|
+
mgr.add_separator_tool()
|
|
373
|
+
mgr.update_tools_status()
|
|
374
|
+
mgr.get_default_tool().activate()
|
|
375
|
+
|
|
376
|
+
def register_tools(self) -> None:
|
|
377
|
+
"""Register the plotting tools according to the plot type"""
|
|
378
|
+
self.__register_standard_tools()
|
|
379
|
+
self.__register_other_tools()
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
class DockablePlotWidget(DockableWidget):
|
|
383
|
+
"""Docked plotting widget
|
|
384
|
+
|
|
385
|
+
Args:
|
|
386
|
+
parent: Parent widget
|
|
387
|
+
plot_type: Plot type
|
|
388
|
+
"""
|
|
389
|
+
|
|
390
|
+
LOCATION = QC.Qt.RightDockWidgetArea
|
|
391
|
+
|
|
392
|
+
def __init__(
|
|
393
|
+
self,
|
|
394
|
+
parent: QW.QWidget,
|
|
395
|
+
plot_type: PlotType,
|
|
396
|
+
) -> None:
|
|
397
|
+
super().__init__(parent)
|
|
398
|
+
self.plotwidget = DataLabPlotWidget(plot_type)
|
|
399
|
+
self.toolbar = self.plotwidget.get_toolbar()
|
|
400
|
+
self.watermark = QW.QLabel()
|
|
401
|
+
original_image = QG.QPixmap(get_image_file_path("DataLab-watermark.png"))
|
|
402
|
+
self.watermark.setPixmap(original_image)
|
|
403
|
+
self.setup_layout()
|
|
404
|
+
self.setup_plotwidget()
|
|
405
|
+
|
|
406
|
+
def __get_toolbar_row_col(self) -> tuple[int, int]:
|
|
407
|
+
"""Return toolbar row and column"""
|
|
408
|
+
tb_pos = Conf.view.plot_toolbar_position.get()
|
|
409
|
+
tb_col, tb_row = 1, 1
|
|
410
|
+
if tb_pos in ("left", "right"):
|
|
411
|
+
self.toolbar.setOrientation(QC.Qt.Vertical)
|
|
412
|
+
tb_col = 0 if tb_pos == "left" else 2
|
|
413
|
+
else:
|
|
414
|
+
self.toolbar.setOrientation(QC.Qt.Horizontal)
|
|
415
|
+
tb_row = 0 if tb_pos == "top" else 2
|
|
416
|
+
return tb_row, tb_col
|
|
417
|
+
|
|
418
|
+
def setup_layout(self) -> None:
|
|
419
|
+
"""Setup layout"""
|
|
420
|
+
tb_row, tb_col = self.__get_toolbar_row_col()
|
|
421
|
+
layout = QW.QGridLayout()
|
|
422
|
+
layout.addWidget(self.toolbar, tb_row, tb_col)
|
|
423
|
+
layout.addWidget(self.plotwidget, 1, 1)
|
|
424
|
+
layout.addWidget(self.watermark, 1, 1, QC.Qt.AlignCenter)
|
|
425
|
+
self.setLayout(layout)
|
|
426
|
+
|
|
427
|
+
def update_toolbar_position(self) -> None:
|
|
428
|
+
"""Update toolbar position"""
|
|
429
|
+
tb_row, tb_col = self.__get_toolbar_row_col()
|
|
430
|
+
layout = self.layout()
|
|
431
|
+
layout.removeWidget(self.toolbar)
|
|
432
|
+
layout.addWidget(self.toolbar, tb_row, tb_col)
|
|
433
|
+
|
|
434
|
+
def setup_plotwidget(self) -> None:
|
|
435
|
+
"""Setup plotting widget"""
|
|
436
|
+
title = self.toolbar.windowTitle()
|
|
437
|
+
self.plotwidget.get_manager().add_toolbar(self.toolbar, title)
|
|
438
|
+
# Customizing widget appearances
|
|
439
|
+
self.update_color_mode()
|
|
440
|
+
plot = self.plotwidget.get_plot()
|
|
441
|
+
canvas = plot.canvas()
|
|
442
|
+
canvas.setFrameStyle(canvas.Plain | canvas.NoFrame)
|
|
443
|
+
plot.SIG_ITEMS_CHANGED.connect(self.update_watermark)
|
|
444
|
+
|
|
445
|
+
def update_color_mode(self) -> None:
|
|
446
|
+
"""Update plot widget styles according to application color mode"""
|
|
447
|
+
if is_dark_theme():
|
|
448
|
+
palette = QApplication.instance().palette()
|
|
449
|
+
else:
|
|
450
|
+
palette = QG.QPalette(QC.Qt.white)
|
|
451
|
+
for widget in (self.plotwidget, self.plotwidget.get_plot(), self):
|
|
452
|
+
widget.setBackgroundRole(QG.QPalette.Window)
|
|
453
|
+
widget.setAutoFillBackground(True)
|
|
454
|
+
widget.setPalette(palette)
|
|
455
|
+
|
|
456
|
+
def get_plot(self) -> BasePlot:
|
|
457
|
+
"""Return plot instance"""
|
|
458
|
+
return self.plotwidget.get_plot()
|
|
459
|
+
|
|
460
|
+
def update_watermark(self, plot: BasePlot) -> None:
|
|
461
|
+
"""Update watermark visibility"""
|
|
462
|
+
items = plot.get_items()
|
|
463
|
+
if self.plotwidget.options.type == PlotType.IMAGE:
|
|
464
|
+
enabled = len(items) <= 1
|
|
465
|
+
else:
|
|
466
|
+
enabled = len(items) <= 2
|
|
467
|
+
self.watermark.setVisible(enabled)
|
|
468
|
+
|
|
469
|
+
# ------DockableWidget API
|
|
470
|
+
def visibility_changed(self, enable: bool) -> None:
|
|
471
|
+
"""DockWidget visibility has changed"""
|
|
472
|
+
DockableWidget.visibility_changed(self, enable)
|
|
473
|
+
self.toolbar.setVisible(enable)
|
datalab/gui/h5io.py
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
HDF5 I/O
|
|
5
|
+
========
|
|
6
|
+
|
|
7
|
+
The :mod:`datalab.gui.h5io` module provides the HDF5 file open/save into/from
|
|
8
|
+
DataLab data model/main window.
|
|
9
|
+
|
|
10
|
+
.. autoclass:: H5InputOutput
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import os.path as osp
|
|
16
|
+
from typing import TYPE_CHECKING
|
|
17
|
+
|
|
18
|
+
from guidata.qthelpers import exec_dialog
|
|
19
|
+
from qtpy import QtWidgets as QW
|
|
20
|
+
from sigima.objects import SignalObj
|
|
21
|
+
|
|
22
|
+
from datalab.config import _
|
|
23
|
+
from datalab.env import execenv
|
|
24
|
+
from datalab.h5 import H5Importer
|
|
25
|
+
from datalab.h5.native import NativeH5Reader, NativeH5Writer
|
|
26
|
+
from datalab.utils.qthelpers import create_progress_bar, qt_try_loadsave_file
|
|
27
|
+
from datalab.widgets.h5browser import H5BrowserDialog
|
|
28
|
+
|
|
29
|
+
if TYPE_CHECKING:
|
|
30
|
+
from datalab.gui.main import DLMainWindow
|
|
31
|
+
from datalab.h5.common import BaseNode
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class H5InputOutput:
|
|
35
|
+
"""Object handling HDF5 file open/save into/from DataLab data model/main window
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
mainwindow: Main window
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
def __init__(self, mainwindow: DLMainWindow) -> None:
|
|
42
|
+
self.mainwindow = mainwindow
|
|
43
|
+
self.uint32_wng: bool = None
|
|
44
|
+
|
|
45
|
+
@staticmethod
|
|
46
|
+
def __progbartitle(fname: str) -> str:
|
|
47
|
+
"""Return progress bar title"""
|
|
48
|
+
return _("Loading data from %s...") % osp.basename(fname)
|
|
49
|
+
|
|
50
|
+
def save_file(self, filename: str) -> None:
|
|
51
|
+
"""Save all signals and images from DataLab model into a HDF5 file"""
|
|
52
|
+
writer = NativeH5Writer(filename)
|
|
53
|
+
for panel in self.mainwindow.panels:
|
|
54
|
+
panel.serialize_to_hdf5(writer)
|
|
55
|
+
writer.close()
|
|
56
|
+
|
|
57
|
+
def open_file(self, filename: str, import_all: bool, reset_all: bool) -> None:
|
|
58
|
+
"""Open HDF5 file"""
|
|
59
|
+
progress = None
|
|
60
|
+
try:
|
|
61
|
+
reader = NativeH5Reader(filename)
|
|
62
|
+
if reset_all:
|
|
63
|
+
self.mainwindow.reset_all()
|
|
64
|
+
with create_progress_bar(
|
|
65
|
+
self.mainwindow, self.__progbartitle(filename), 2
|
|
66
|
+
) as progress:
|
|
67
|
+
for idx, panel in enumerate(self.mainwindow.panels):
|
|
68
|
+
progress.setValue(idx + 1)
|
|
69
|
+
QW.QApplication.processEvents()
|
|
70
|
+
panel.deserialize_from_hdf5(reader, reset_all)
|
|
71
|
+
if progress.wasCanceled():
|
|
72
|
+
break
|
|
73
|
+
reader.close()
|
|
74
|
+
except KeyError:
|
|
75
|
+
if progress is not None:
|
|
76
|
+
# KeyError was encoutered when deserializing datasets (DataLab data
|
|
77
|
+
# model is not compatible with this version)
|
|
78
|
+
progress.close()
|
|
79
|
+
self.import_files([filename], import_all, reset_all)
|
|
80
|
+
|
|
81
|
+
def __add_object_from_node(self, node: BaseNode) -> None:
|
|
82
|
+
"""Add DataLab object from h5 node"""
|
|
83
|
+
obj = node.get_native_object()
|
|
84
|
+
if obj is None:
|
|
85
|
+
return
|
|
86
|
+
self.uint32_wng = self.uint32_wng or node.uint32_wng
|
|
87
|
+
if isinstance(obj, SignalObj):
|
|
88
|
+
self.mainwindow.signalpanel.add_object(obj)
|
|
89
|
+
else:
|
|
90
|
+
self.mainwindow.imagepanel.add_object(obj)
|
|
91
|
+
|
|
92
|
+
def __eventually_show_warnings(self) -> None:
|
|
93
|
+
"""Eventually show warnings after everything is imported"""
|
|
94
|
+
if self.uint32_wng:
|
|
95
|
+
QW.QMessageBox.warning(
|
|
96
|
+
self.mainwindow, _("Warning"), _("Clipping uint32 data to int32.")
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
def import_files(
|
|
100
|
+
self, filenames: list[str], import_all: bool, reset_all: bool
|
|
101
|
+
) -> None:
|
|
102
|
+
"""Import HDF5 files"""
|
|
103
|
+
h5browser = H5BrowserDialog(self.mainwindow)
|
|
104
|
+
for filename in filenames:
|
|
105
|
+
with qt_try_loadsave_file(self.mainwindow, filename, "load"):
|
|
106
|
+
h5browser.open_file(filename)
|
|
107
|
+
if h5browser.is_empty():
|
|
108
|
+
h5browser.cleanup()
|
|
109
|
+
if not execenv.unattended:
|
|
110
|
+
QW.QMessageBox.warning(
|
|
111
|
+
self.mainwindow,
|
|
112
|
+
_("Warning"),
|
|
113
|
+
_("No supported data available in HDF5 file(s)."),
|
|
114
|
+
)
|
|
115
|
+
return
|
|
116
|
+
if execenv.unattended:
|
|
117
|
+
# Unattended mode: import all datasets (for testing)
|
|
118
|
+
import_all = True
|
|
119
|
+
if import_all or exec_dialog(h5browser):
|
|
120
|
+
if import_all:
|
|
121
|
+
nodes = h5browser.get_all_nodes()
|
|
122
|
+
else:
|
|
123
|
+
nodes = h5browser.get_nodes()
|
|
124
|
+
if nodes is not None:
|
|
125
|
+
if reset_all:
|
|
126
|
+
self.mainwindow.reset_all()
|
|
127
|
+
with qt_try_loadsave_file(self.mainwindow, "*.h5", "load"):
|
|
128
|
+
with create_progress_bar(self.mainwindow, "", len(nodes)) as prog:
|
|
129
|
+
self.uint32_wng = False
|
|
130
|
+
for idx, node in enumerate(nodes):
|
|
131
|
+
prog.setLabelText(self.__progbartitle(node.h5file.filename))
|
|
132
|
+
prog.setValue(idx + 1)
|
|
133
|
+
QW.QApplication.processEvents()
|
|
134
|
+
if prog.wasCanceled():
|
|
135
|
+
break
|
|
136
|
+
self.__add_object_from_node(node)
|
|
137
|
+
self.__eventually_show_warnings()
|
|
138
|
+
h5browser.cleanup()
|
|
139
|
+
|
|
140
|
+
def import_dataset_from_file(self, filename: str, dsetname: str) -> None:
|
|
141
|
+
"""Import dataset from HDF5 file"""
|
|
142
|
+
h5importer = H5Importer(filename)
|
|
143
|
+
try:
|
|
144
|
+
node = h5importer.get(dsetname)
|
|
145
|
+
self.uint32_wng = False
|
|
146
|
+
self.__add_object_from_node(node)
|
|
147
|
+
self.__eventually_show_warnings()
|
|
148
|
+
except KeyError as exc:
|
|
149
|
+
raise KeyError(f"Dataset not found: {dsetname}") from exc
|
|
150
|
+
h5importer.close()
|