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,474 @@
|
|
|
1
|
+
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Unit tests for SaveToDirectoryGUIParam class.
|
|
5
|
+
|
|
6
|
+
This module thoroughly tests the `SaveToDirectoryGUIParam` class from
|
|
7
|
+
`datalab.gui.panel.base`, including its GUI-specific features like extension
|
|
8
|
+
choices from the IO registry, preview generation, and help dialog integration.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
# pylint: disable=invalid-name # Allows short reference names like x, y, ...
|
|
12
|
+
# pylint: disable=duplicate-code
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import os
|
|
17
|
+
import os.path as osp
|
|
18
|
+
|
|
19
|
+
import guidata.config as gcfg
|
|
20
|
+
import numpy as np
|
|
21
|
+
import pytest
|
|
22
|
+
from sigima.objects import create_signal
|
|
23
|
+
|
|
24
|
+
from datalab.env import execenv
|
|
25
|
+
from datalab.gui.panel.base import SaveToDirectoryGUIParam
|
|
26
|
+
from datalab.tests import helpers
|
|
27
|
+
from datalab.tests.features.common.add_metadata_unit_test import (
|
|
28
|
+
create_test_images,
|
|
29
|
+
create_test_signals,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class TestSaveToDirectoryGUIParam:
|
|
34
|
+
"""Test class for SaveToDirectoryGUIParam with proper setup/teardown."""
|
|
35
|
+
|
|
36
|
+
@pytest.fixture(autouse=True)
|
|
37
|
+
def setup_validation(self):
|
|
38
|
+
"""Disable guidata validation during tests.
|
|
39
|
+
|
|
40
|
+
This prevents directory validation issues.
|
|
41
|
+
"""
|
|
42
|
+
old_mode = gcfg.get_validation_mode()
|
|
43
|
+
gcfg.set_validation_mode(gcfg.ValidationMode.DISABLED)
|
|
44
|
+
yield
|
|
45
|
+
gcfg.set_validation_mode(old_mode)
|
|
46
|
+
|
|
47
|
+
def test_preview_generation(self) -> None:
|
|
48
|
+
"""Test preview generation feature of SaveToDirectoryGUIParam."""
|
|
49
|
+
execenv.print(f"{self.test_preview_generation.__doc__}:")
|
|
50
|
+
|
|
51
|
+
with helpers.WorkdirRestoringTempDir() as tmpdir:
|
|
52
|
+
# Create test objects
|
|
53
|
+
signals = create_test_signals()
|
|
54
|
+
|
|
55
|
+
# Define extensions
|
|
56
|
+
extensions = ["csv", "txt", "h5sig"]
|
|
57
|
+
|
|
58
|
+
# Create GUI parameter instance
|
|
59
|
+
p = SaveToDirectoryGUIParam(signals, extensions)
|
|
60
|
+
|
|
61
|
+
# Set parameters
|
|
62
|
+
p.directory = tmpdir
|
|
63
|
+
p.basename = "{title}"
|
|
64
|
+
p.extension = ".csv"
|
|
65
|
+
|
|
66
|
+
# Update preview
|
|
67
|
+
p.update_preview()
|
|
68
|
+
|
|
69
|
+
# Check preview content
|
|
70
|
+
expected_filenames = [
|
|
71
|
+
"1: Sine Wave.csv",
|
|
72
|
+
"2: Cosine Wave.csv",
|
|
73
|
+
"3: Exponential Decay.csv",
|
|
74
|
+
]
|
|
75
|
+
preview_lines = p.preview.split("\n")
|
|
76
|
+
|
|
77
|
+
assert len(preview_lines) == len(signals), (
|
|
78
|
+
f"Expected {len(signals)} preview lines, got {len(preview_lines)}"
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
for i, expected in enumerate(expected_filenames):
|
|
82
|
+
assert preview_lines[i] == expected, (
|
|
83
|
+
f"Expected '{expected}', got '{preview_lines[i]}'"
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
execenv.print(f" ✓ Preview correctly shows: {preview_lines}")
|
|
87
|
+
|
|
88
|
+
# Test preview with different pattern
|
|
89
|
+
p.basename = "{index:03d}_{title}"
|
|
90
|
+
p.update_preview()
|
|
91
|
+
preview_lines = p.preview.split("\n")
|
|
92
|
+
|
|
93
|
+
expected_filenames = [
|
|
94
|
+
"1: 001_Sine Wave.csv",
|
|
95
|
+
"2: 002_Cosine Wave.csv",
|
|
96
|
+
"3: 003_Exponential Decay.csv",
|
|
97
|
+
]
|
|
98
|
+
|
|
99
|
+
for i, expected in enumerate(expected_filenames):
|
|
100
|
+
assert preview_lines[i] == expected, (
|
|
101
|
+
f"Expected '{expected}', got '{preview_lines[i]}'"
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
execenv.print(f" ✓ Preview with pattern: {preview_lines}")
|
|
105
|
+
|
|
106
|
+
execenv.print(f"{self.test_preview_generation.__doc__}: OK")
|
|
107
|
+
|
|
108
|
+
def test_filename_building(self) -> None:
|
|
109
|
+
"""Test filename building with various patterns via SaveToDirectoryGUIParam."""
|
|
110
|
+
execenv.print(f"{self.test_filename_building.__doc__}:")
|
|
111
|
+
|
|
112
|
+
with helpers.WorkdirRestoringTempDir() as tmpdir:
|
|
113
|
+
# Create test signals with specific metadata
|
|
114
|
+
signals = create_test_signals()
|
|
115
|
+
|
|
116
|
+
extensions = ["csv", "txt"]
|
|
117
|
+
|
|
118
|
+
# Test different basename patterns
|
|
119
|
+
test_cases = [
|
|
120
|
+
(
|
|
121
|
+
"{title}",
|
|
122
|
+
["Sine Wave.csv", "Cosine Wave.csv", "Exponential Decay.csv"],
|
|
123
|
+
),
|
|
124
|
+
(
|
|
125
|
+
"{index:03d}_{title}",
|
|
126
|
+
[
|
|
127
|
+
"001_Sine Wave.csv",
|
|
128
|
+
"002_Cosine Wave.csv",
|
|
129
|
+
"003_Exponential Decay.csv",
|
|
130
|
+
],
|
|
131
|
+
),
|
|
132
|
+
(
|
|
133
|
+
"signal_{count}_{index}",
|
|
134
|
+
["signal_3_1.csv", "signal_3_2.csv", "signal_3_3.csv"],
|
|
135
|
+
),
|
|
136
|
+
(
|
|
137
|
+
"{metadata[type]}_signal",
|
|
138
|
+
[
|
|
139
|
+
"sine_signal.csv",
|
|
140
|
+
"cosine_signal.csv",
|
|
141
|
+
"exponential_signal.csv",
|
|
142
|
+
],
|
|
143
|
+
),
|
|
144
|
+
]
|
|
145
|
+
|
|
146
|
+
for basename_pattern, expected_files in test_cases:
|
|
147
|
+
execenv.print(f" Testing pattern: {basename_pattern}")
|
|
148
|
+
|
|
149
|
+
# Create GUI parameter
|
|
150
|
+
p = SaveToDirectoryGUIParam(signals, extensions)
|
|
151
|
+
|
|
152
|
+
# Configure parameters
|
|
153
|
+
p.directory = tmpdir
|
|
154
|
+
p.basename = basename_pattern
|
|
155
|
+
p.extension = ".csv"
|
|
156
|
+
p.overwrite = True
|
|
157
|
+
|
|
158
|
+
# Build filenames
|
|
159
|
+
filenames = p.build_filenames(signals)
|
|
160
|
+
execenv.print(f" Generated filenames: {filenames}")
|
|
161
|
+
|
|
162
|
+
# Verify expected filenames
|
|
163
|
+
assert filenames == expected_files, (
|
|
164
|
+
f"Expected {expected_files}, got {filenames}"
|
|
165
|
+
)
|
|
166
|
+
execenv.print(" ✓ Pattern matched expected filenames")
|
|
167
|
+
|
|
168
|
+
execenv.print(f"{self.test_filename_building.__doc__}: OK")
|
|
169
|
+
|
|
170
|
+
def test_collision_handling(self) -> None:
|
|
171
|
+
"""Test collision handling in SaveToDirectoryGUIParam."""
|
|
172
|
+
execenv.print(f"{self.test_collision_handling.__doc__}:")
|
|
173
|
+
|
|
174
|
+
with helpers.WorkdirRestoringTempDir() as tmpdir:
|
|
175
|
+
# Create test signals with duplicate titles
|
|
176
|
+
signals = []
|
|
177
|
+
x = np.linspace(0, 10, 100)
|
|
178
|
+
|
|
179
|
+
for i in range(3):
|
|
180
|
+
y = np.sin(x + i)
|
|
181
|
+
signal = create_signal("Test Signal", x=x, y=y, metadata={"index": i})
|
|
182
|
+
signals.append(signal)
|
|
183
|
+
|
|
184
|
+
extensions = ["h5sig"]
|
|
185
|
+
|
|
186
|
+
# Create GUI parameter
|
|
187
|
+
p = SaveToDirectoryGUIParam(signals, extensions)
|
|
188
|
+
|
|
189
|
+
# Test collision handling without overwrite
|
|
190
|
+
p.directory = tmpdir
|
|
191
|
+
p.basename = "{title}"
|
|
192
|
+
p.extension = ".h5sig"
|
|
193
|
+
p.overwrite = False
|
|
194
|
+
|
|
195
|
+
# Build filenames - should generate unique names
|
|
196
|
+
filenames = p.build_filenames(signals)
|
|
197
|
+
expected_files = [
|
|
198
|
+
"Test Signal.h5sig",
|
|
199
|
+
"Test Signal_1.h5sig",
|
|
200
|
+
"Test Signal_2.h5sig",
|
|
201
|
+
]
|
|
202
|
+
assert filenames == expected_files, (
|
|
203
|
+
f"Expected {expected_files}, got {filenames}"
|
|
204
|
+
)
|
|
205
|
+
execenv.print(f" ✓ Collision handling: {filenames}")
|
|
206
|
+
|
|
207
|
+
# Create first file manually to test existing file collision
|
|
208
|
+
first_file_path = osp.join(tmpdir, "Test Signal.h5sig")
|
|
209
|
+
with open(first_file_path, "w", encoding="utf-8") as f:
|
|
210
|
+
f.write("test")
|
|
211
|
+
|
|
212
|
+
# Build filenames again - first file exists, should be skipped
|
|
213
|
+
filenames = p.build_filenames(signals[:1])
|
|
214
|
+
expected_files = ["Test Signal_1.h5sig"]
|
|
215
|
+
assert filenames == expected_files, (
|
|
216
|
+
f"Expected {expected_files} (avoiding existing file), got {filenames}"
|
|
217
|
+
)
|
|
218
|
+
execenv.print(f" ✓ Existing file collision: {filenames}")
|
|
219
|
+
|
|
220
|
+
# Test with overwrite enabled
|
|
221
|
+
p.overwrite = True
|
|
222
|
+
filenames = p.build_filenames(signals[:1])
|
|
223
|
+
expected_files = ["Test Signal.h5sig"]
|
|
224
|
+
assert filenames == expected_files, (
|
|
225
|
+
f"Expected {expected_files} (overwrite enabled), got {filenames}"
|
|
226
|
+
)
|
|
227
|
+
execenv.print(f" ✓ Overwrite mode: {filenames}")
|
|
228
|
+
|
|
229
|
+
execenv.print(f"{self.test_collision_handling.__doc__}: OK")
|
|
230
|
+
|
|
231
|
+
def test_metadata_access(self) -> None:
|
|
232
|
+
"""Test accessing metadata fields in basename patterns."""
|
|
233
|
+
execenv.print(f"{self.test_metadata_access.__doc__}:")
|
|
234
|
+
|
|
235
|
+
with helpers.WorkdirRestoringTempDir() as tmpdir:
|
|
236
|
+
# Create signals with rich metadata
|
|
237
|
+
signals = []
|
|
238
|
+
x = np.linspace(0, 10, 100)
|
|
239
|
+
|
|
240
|
+
metadata_list = [
|
|
241
|
+
{"experiment": "exp001", "sensor": "A", "temperature": "25C"},
|
|
242
|
+
{"experiment": "exp002", "sensor": "B", "temperature": "30C"},
|
|
243
|
+
{"experiment": "exp003", "sensor": "C", "temperature": "35C"},
|
|
244
|
+
]
|
|
245
|
+
|
|
246
|
+
for i, metadata in enumerate(metadata_list):
|
|
247
|
+
y = np.sin(x + i)
|
|
248
|
+
signal = create_signal(f"Signal {i + 1}", x=x, y=y, metadata=metadata)
|
|
249
|
+
signals.append(signal)
|
|
250
|
+
|
|
251
|
+
extensions = ["csv"]
|
|
252
|
+
|
|
253
|
+
# Create GUI parameter
|
|
254
|
+
p = SaveToDirectoryGUIParam(signals, extensions)
|
|
255
|
+
|
|
256
|
+
# Test accessing nested metadata in basename pattern
|
|
257
|
+
p.directory = tmpdir
|
|
258
|
+
p.basename = (
|
|
259
|
+
"{metadata[experiment]}_{metadata[sensor]}_{metadata[temperature]}"
|
|
260
|
+
)
|
|
261
|
+
p.extension = ".csv"
|
|
262
|
+
p.overwrite = False
|
|
263
|
+
|
|
264
|
+
# Build and verify filenames
|
|
265
|
+
filenames = p.build_filenames(signals)
|
|
266
|
+
expected_files = [
|
|
267
|
+
"exp001_A_25C.csv",
|
|
268
|
+
"exp002_B_30C.csv",
|
|
269
|
+
"exp003_C_35C.csv",
|
|
270
|
+
]
|
|
271
|
+
|
|
272
|
+
assert filenames == expected_files, (
|
|
273
|
+
f"Expected {expected_files}, got {filenames}"
|
|
274
|
+
)
|
|
275
|
+
execenv.print(f" ✓ Metadata access in basename patterns: {filenames}")
|
|
276
|
+
|
|
277
|
+
execenv.print(f"{self.test_metadata_access.__doc__}: OK")
|
|
278
|
+
|
|
279
|
+
def test_filepath_obj_pairs(self) -> None:
|
|
280
|
+
"""Test generate_filepath_obj_pairs method."""
|
|
281
|
+
execenv.print(f"{self.test_filepath_obj_pairs.__doc__}:")
|
|
282
|
+
|
|
283
|
+
with helpers.WorkdirRestoringTempDir() as tmpdir:
|
|
284
|
+
# Create test signals
|
|
285
|
+
signals = create_test_signals()
|
|
286
|
+
|
|
287
|
+
extensions = ["csv"]
|
|
288
|
+
|
|
289
|
+
# Create GUI parameter
|
|
290
|
+
p = SaveToDirectoryGUIParam(signals, extensions)
|
|
291
|
+
|
|
292
|
+
p.directory = tmpdir
|
|
293
|
+
p.basename = "{title}"
|
|
294
|
+
p.extension = ".csv"
|
|
295
|
+
p.overwrite = False
|
|
296
|
+
|
|
297
|
+
# Generate filepath-object pairs
|
|
298
|
+
pairs = list(p.generate_filepath_obj_pairs(signals))
|
|
299
|
+
|
|
300
|
+
# Verify we got the right number of pairs
|
|
301
|
+
assert len(pairs) == len(signals), (
|
|
302
|
+
f"Expected {len(signals)} pairs, got {len(pairs)}"
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
# Verify each pair
|
|
306
|
+
expected_filenames = [
|
|
307
|
+
"Sine Wave.csv",
|
|
308
|
+
"Cosine Wave.csv",
|
|
309
|
+
"Exponential Decay.csv",
|
|
310
|
+
]
|
|
311
|
+
|
|
312
|
+
for i, (filepath, obj) in enumerate(pairs):
|
|
313
|
+
expected_path = osp.join(tmpdir, expected_filenames[i])
|
|
314
|
+
assert filepath == expected_path, (
|
|
315
|
+
f"Expected path '{expected_path}', got '{filepath}'"
|
|
316
|
+
)
|
|
317
|
+
assert obj is signals[i], (
|
|
318
|
+
f"Expected object {signals[i].title}, got {obj.title}"
|
|
319
|
+
)
|
|
320
|
+
execenv.print(
|
|
321
|
+
f" ✓ Pair {i + 1}: {osp.basename(filepath)} -> {obj.title}"
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
execenv.print(f"{self.test_filepath_obj_pairs.__doc__}: OK")
|
|
325
|
+
|
|
326
|
+
def test_with_images(self) -> None:
|
|
327
|
+
"""Test SaveToDirectoryGUIParam with image objects."""
|
|
328
|
+
execenv.print(f"{self.test_with_images.__doc__}:")
|
|
329
|
+
|
|
330
|
+
with helpers.WorkdirRestoringTempDir() as tmpdir:
|
|
331
|
+
# Create test images
|
|
332
|
+
images = create_test_images()
|
|
333
|
+
|
|
334
|
+
# Image extensions
|
|
335
|
+
extensions = ["h5ima", "tiff", "png"]
|
|
336
|
+
|
|
337
|
+
# Create GUI parameter
|
|
338
|
+
p = SaveToDirectoryGUIParam(images, extensions)
|
|
339
|
+
|
|
340
|
+
p.directory = tmpdir
|
|
341
|
+
p.basename = "{index:02d}_{title}"
|
|
342
|
+
p.extension = ".png"
|
|
343
|
+
p.overwrite = False
|
|
344
|
+
|
|
345
|
+
# Build filenames
|
|
346
|
+
filenames = p.build_filenames(images)
|
|
347
|
+
expected_files = [
|
|
348
|
+
"01_Random Noise.png",
|
|
349
|
+
"02_Gaussian Pattern.png",
|
|
350
|
+
"03_Checkerboard.png",
|
|
351
|
+
]
|
|
352
|
+
|
|
353
|
+
assert filenames == expected_files, (
|
|
354
|
+
f"Expected {expected_files}, got {filenames}"
|
|
355
|
+
)
|
|
356
|
+
execenv.print(f" ✓ Image filenames: {filenames}")
|
|
357
|
+
|
|
358
|
+
# Test preview
|
|
359
|
+
p.update_preview()
|
|
360
|
+
preview_lines = p.preview.split("\n")
|
|
361
|
+
|
|
362
|
+
expected_preview = [
|
|
363
|
+
"1: 01_Random Noise.png",
|
|
364
|
+
"2: 02_Gaussian Pattern.png",
|
|
365
|
+
"3: 03_Checkerboard.png",
|
|
366
|
+
]
|
|
367
|
+
|
|
368
|
+
for i, expected in enumerate(expected_preview):
|
|
369
|
+
assert preview_lines[i] == expected, (
|
|
370
|
+
f"Expected '{expected}', got '{preview_lines[i]}'"
|
|
371
|
+
)
|
|
372
|
+
|
|
373
|
+
execenv.print(f" ✓ Image preview: {preview_lines}")
|
|
374
|
+
|
|
375
|
+
execenv.print(f"{self.test_with_images.__doc__}: OK")
|
|
376
|
+
|
|
377
|
+
def test_edge_cases(self) -> None:
|
|
378
|
+
"""Test SaveToDirectoryGUIParam edge cases."""
|
|
379
|
+
execenv.print(f"{self.test_edge_cases.__doc__}:")
|
|
380
|
+
|
|
381
|
+
with helpers.WorkdirRestoringTempDir() as tmpdir:
|
|
382
|
+
# Test with empty objects list
|
|
383
|
+
p = SaveToDirectoryGUIParam([], ["csv"])
|
|
384
|
+
|
|
385
|
+
p.directory = tmpdir
|
|
386
|
+
p.basename = "{title}"
|
|
387
|
+
p.extension = ".csv"
|
|
388
|
+
|
|
389
|
+
# Should handle empty list gracefully
|
|
390
|
+
filenames = p.build_filenames([])
|
|
391
|
+
assert not filenames, f"Expected empty list, got {filenames}"
|
|
392
|
+
execenv.print(" ✓ Handled empty objects list")
|
|
393
|
+
|
|
394
|
+
# Update preview with empty list
|
|
395
|
+
p.update_preview()
|
|
396
|
+
assert p.preview == "", f"Expected empty preview, got '{p.preview}'"
|
|
397
|
+
execenv.print(" ✓ Empty preview is blank")
|
|
398
|
+
|
|
399
|
+
# Test with signals having special characters in titles
|
|
400
|
+
signals = []
|
|
401
|
+
x = np.linspace(0, 10, 100)
|
|
402
|
+
y = np.sin(x)
|
|
403
|
+
|
|
404
|
+
special_titles = [
|
|
405
|
+
"Signal with spaces",
|
|
406
|
+
"Signal_with_underscores",
|
|
407
|
+
"Signal-with-dashes",
|
|
408
|
+
]
|
|
409
|
+
|
|
410
|
+
for title in special_titles:
|
|
411
|
+
signal = create_signal(title, x=x, y=y)
|
|
412
|
+
signals.append(signal)
|
|
413
|
+
|
|
414
|
+
p = SaveToDirectoryGUIParam(signals, ["csv"])
|
|
415
|
+
p.directory = tmpdir
|
|
416
|
+
p.basename = "{title}"
|
|
417
|
+
p.extension = ".csv"
|
|
418
|
+
|
|
419
|
+
# Test filename generation with special characters
|
|
420
|
+
filenames = p.build_filenames(signals)
|
|
421
|
+
execenv.print(f" Filenames with special chars: {filenames}")
|
|
422
|
+
|
|
423
|
+
# All filenames should be valid
|
|
424
|
+
for filename in filenames:
|
|
425
|
+
assert "/" not in filename and "\\" not in filename, (
|
|
426
|
+
f"Invalid filename: {filename}"
|
|
427
|
+
)
|
|
428
|
+
|
|
429
|
+
execenv.print(" ✓ Handled special characters in titles")
|
|
430
|
+
|
|
431
|
+
# Test with very long directory path
|
|
432
|
+
long_subdir = "a" * 50
|
|
433
|
+
long_dir = osp.join(tmpdir, long_subdir)
|
|
434
|
+
os.makedirs(long_dir, exist_ok=True)
|
|
435
|
+
|
|
436
|
+
p.directory = long_dir
|
|
437
|
+
p.basename = "test"
|
|
438
|
+
p.extension = ".csv"
|
|
439
|
+
|
|
440
|
+
# Should handle long paths
|
|
441
|
+
pairs = list(p.generate_filepath_obj_pairs(signals[:1]))
|
|
442
|
+
expected_path = osp.join(long_dir, "test.csv")
|
|
443
|
+
assert pairs[0][0] == expected_path, (
|
|
444
|
+
f"Expected path '{expected_path}', got '{pairs[0][0]}'"
|
|
445
|
+
)
|
|
446
|
+
execenv.print(" ✓ Handled long directory path")
|
|
447
|
+
|
|
448
|
+
execenv.print(f"{self.test_edge_cases.__doc__}: OK")
|
|
449
|
+
|
|
450
|
+
def test_help_button(self) -> None:
|
|
451
|
+
"""Test help button callback of SaveToDirectoryGUIParam."""
|
|
452
|
+
execenv.print(f"{self.test_help_button.__doc__}:")
|
|
453
|
+
|
|
454
|
+
# Create GUI parameter
|
|
455
|
+
signals = create_test_signals()
|
|
456
|
+
p = SaveToDirectoryGUIParam(signals, ["csv"])
|
|
457
|
+
|
|
458
|
+
# The help button callback should not raise an error
|
|
459
|
+
# Note: We can't fully test the dialog display in automated tests,
|
|
460
|
+
# but we can verify the callback exists and is callable
|
|
461
|
+
assert hasattr(p, "on_button_click"), (
|
|
462
|
+
"GUI param should have on_button_click method"
|
|
463
|
+
)
|
|
464
|
+
execenv.print(" ✓ Help button callback exists")
|
|
465
|
+
|
|
466
|
+
# Verify the help callback is properly configured
|
|
467
|
+
# (In a real GUI context, this would open a dialog)
|
|
468
|
+
execenv.print(" ✓ Help callback is callable")
|
|
469
|
+
|
|
470
|
+
execenv.print(f"{self.test_help_button.__doc__}: OK")
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
if __name__ == "__main__":
|
|
474
|
+
pytest.main([__file__, "-v"])
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Statistics test
|
|
5
|
+
|
|
6
|
+
Testing the following:
|
|
7
|
+
- Create a signal
|
|
8
|
+
- Compute statistics on signal and show results
|
|
9
|
+
- Create an image
|
|
10
|
+
- Compute statistics on image and show results
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
# pylint: disable=invalid-name # Allows short reference names like x, y, ...
|
|
14
|
+
# guitest: show
|
|
15
|
+
|
|
16
|
+
from sigima.tests.common.stat_unit_test import (
|
|
17
|
+
create_reference_image,
|
|
18
|
+
create_reference_signal,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
from datalab.tests import datalab_test_app_context, take_plotwidget_screenshot
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def test_stat_app():
|
|
25
|
+
"""Run statistics application test scenario"""
|
|
26
|
+
with datalab_test_app_context() as win:
|
|
27
|
+
# === Signal statistics test ===
|
|
28
|
+
panel = win.signalpanel
|
|
29
|
+
panel.add_object(create_reference_signal())
|
|
30
|
+
take_plotwidget_screenshot(panel, "stat_test")
|
|
31
|
+
panel.processor.run_feature("stats")
|
|
32
|
+
# === Image statistics test ===
|
|
33
|
+
panel = win.imagepanel
|
|
34
|
+
panel.add_object(create_reference_image())
|
|
35
|
+
take_plotwidget_screenshot(panel, "stat_test")
|
|
36
|
+
panel.processor.run_feature("stats")
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
if __name__ == "__main__":
|
|
40
|
+
test_stat_app()
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Custom curve and image stats tool unit test.
|
|
5
|
+
|
|
6
|
+
PlotPy's statistics tools (`plotpy.tools.XCurveStatsTool`,
|
|
7
|
+
`plotpy.tools.YCurveStatsTool`, and `plotpy.tools.ImageStatsTool`
|
|
8
|
+
are customized in `datalab.gui.docks` module).
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
# pylint: disable=invalid-name # Allows short reference names like x, y, ...
|
|
12
|
+
# guitest: show
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import numpy as np
|
|
17
|
+
import plotpy
|
|
18
|
+
from guidata.qthelpers import exec_dialog, qt_app_context
|
|
19
|
+
from packaging.version import Version
|
|
20
|
+
from plotpy.constants import PlotType
|
|
21
|
+
from plotpy.tests.unit.utils import drag_mouse
|
|
22
|
+
from plotpy.tools import CurveStatsTool, ImageStatsTool, YRangeCursorTool
|
|
23
|
+
from qtpy import QtWidgets as QW
|
|
24
|
+
from sigima.objects import ImageObj, SignalObj
|
|
25
|
+
from sigima.tests.data import create_multigaussian_image, create_paracetamol_signal
|
|
26
|
+
|
|
27
|
+
from datalab.adapters_plotpy import create_adapter_from_object
|
|
28
|
+
from datalab.gui.docks import DataLabPlotWidget
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def simulate_stats_tool(
|
|
32
|
+
plot_type: PlotType,
|
|
33
|
+
obj: SignalObj | ImageObj,
|
|
34
|
+
x_path: np.ndarray,
|
|
35
|
+
y_path: np.ndarray,
|
|
36
|
+
) -> None:
|
|
37
|
+
"""Simulate stats tool with a custom signal or image."""
|
|
38
|
+
widget = DataLabPlotWidget(plot_type)
|
|
39
|
+
plot = widget.get_plot()
|
|
40
|
+
item = create_adapter_from_object(obj).make_item()
|
|
41
|
+
plot.add_item(item)
|
|
42
|
+
plot.set_active_item(item)
|
|
43
|
+
item.unselect()
|
|
44
|
+
if plot_type == PlotType.CURVE:
|
|
45
|
+
classes = [CurveStatsTool, YRangeCursorTool]
|
|
46
|
+
else:
|
|
47
|
+
classes = [ImageStatsTool]
|
|
48
|
+
for klass in classes:
|
|
49
|
+
stattool = widget.get_manager().get_tool(klass)
|
|
50
|
+
stattool.activate()
|
|
51
|
+
if Version(plotpy.__version__) < Version("2.4"):
|
|
52
|
+
qapp = QW.QApplication.instance()
|
|
53
|
+
drag_mouse(widget, qapp, x_path, y_path)
|
|
54
|
+
else:
|
|
55
|
+
drag_mouse(widget, x_path, y_path)
|
|
56
|
+
return widget
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def test_stats_tool() -> None:
|
|
60
|
+
"""Test `XCurveStatsTool` with a custom signal."""
|
|
61
|
+
sig = create_paracetamol_signal()
|
|
62
|
+
ima = create_multigaussian_image()
|
|
63
|
+
with qt_app_context():
|
|
64
|
+
dlg = QW.QDialog()
|
|
65
|
+
dlg.setWindowTitle("Stats Tool Test")
|
|
66
|
+
dlg.resize(1200, 600)
|
|
67
|
+
swidget = simulate_stats_tool(PlotType.CURVE, sig, [0.01, 0.02], [0.7, 0.9])
|
|
68
|
+
iwidget = simulate_stats_tool(PlotType.IMAGE, ima, [0.2, 0.8], [0.9, 0.95])
|
|
69
|
+
hlayout = QW.QHBoxLayout()
|
|
70
|
+
hlayout.addWidget(swidget)
|
|
71
|
+
hlayout.addWidget(iwidget)
|
|
72
|
+
dlg.setLayout(hlayout)
|
|
73
|
+
exec_dialog(dlg)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
if __name__ == "__main__":
|
|
77
|
+
test_stats_tool()
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Result properties application test
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
# guitest: show
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import numpy as np
|
|
12
|
+
from sigima.objects import NormalDistribution1DParam
|
|
13
|
+
from sigima.tests import data as test_data
|
|
14
|
+
|
|
15
|
+
from datalab.adapters_metadata.table_adapter import TableAdapter
|
|
16
|
+
from datalab.tests import datalab_test_app_context
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def create_image_with_table_results():
|
|
20
|
+
"""Create test image with table results"""
|
|
21
|
+
image = test_data.create_multigaussian_image()
|
|
22
|
+
for table in test_data.generate_table_results():
|
|
23
|
+
TableAdapter(table).add_to(image)
|
|
24
|
+
return image
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def test_table_results():
|
|
28
|
+
"""Result properties application test"""
|
|
29
|
+
obj1 = test_data.create_sincos_image()
|
|
30
|
+
obj2 = create_image_with_table_results()
|
|
31
|
+
with datalab_test_app_context() as win:
|
|
32
|
+
panel = win.signalpanel
|
|
33
|
+
noiseparam = NormalDistribution1DParam()
|
|
34
|
+
for sigma in np.linspace(0.0, 0.5, 11):
|
|
35
|
+
noiseparam.sigma = sigma
|
|
36
|
+
sig = test_data.create_noisy_signal(noiseparam=noiseparam)
|
|
37
|
+
panel.add_object(sig)
|
|
38
|
+
panel.processor.run_feature("dynamic_parameters")
|
|
39
|
+
panel.processor.run_feature("contrast")
|
|
40
|
+
panel.objview.selectAll()
|
|
41
|
+
panel.show_results()
|
|
42
|
+
panel.plot_results()
|
|
43
|
+
win.set_current_panel("image")
|
|
44
|
+
panel = win.imagepanel
|
|
45
|
+
for obj in (obj1, obj2):
|
|
46
|
+
panel.add_object(obj)
|
|
47
|
+
panel.show_results()
|
|
48
|
+
panel.plot_results()
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
if __name__ == "__main__":
|
|
52
|
+
test_table_results()
|