datalab-platform 0.0.1.dev0__py3-none-any.whl → 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- datalab/__init__.py +35 -2
- datalab/adapters_metadata/__init__.py +31 -0
- datalab/adapters_metadata/base_adapter.py +316 -0
- datalab/adapters_metadata/common.py +422 -0
- datalab/adapters_metadata/geometry_adapter.py +98 -0
- datalab/adapters_metadata/table_adapter.py +84 -0
- datalab/adapters_plotpy/__init__.py +54 -0
- datalab/adapters_plotpy/annotations.py +124 -0
- datalab/adapters_plotpy/base.py +110 -0
- datalab/adapters_plotpy/converters.py +86 -0
- datalab/adapters_plotpy/factories.py +80 -0
- datalab/adapters_plotpy/objects/__init__.py +0 -0
- datalab/adapters_plotpy/objects/base.py +197 -0
- datalab/adapters_plotpy/objects/image.py +157 -0
- datalab/adapters_plotpy/objects/scalar.py +565 -0
- datalab/adapters_plotpy/objects/signal.py +264 -0
- datalab/adapters_plotpy/roi/__init__.py +0 -0
- datalab/adapters_plotpy/roi/base.py +146 -0
- datalab/adapters_plotpy/roi/factory.py +93 -0
- datalab/adapters_plotpy/roi/image.py +207 -0
- datalab/adapters_plotpy/roi/signal.py +72 -0
- datalab/app.py +98 -0
- datalab/config.py +817 -0
- datalab/control/__init__.py +0 -0
- datalab/control/baseproxy.py +776 -0
- datalab/control/proxy.py +343 -0
- datalab/control/remote.py +1005 -0
- datalab/data/doc/DataLab_en.pdf +0 -0
- datalab/data/doc/DataLab_fr.pdf +0 -0
- datalab/data/icons/analysis/delete_results.svg +109 -0
- datalab/data/icons/analysis/fw1e2.svg +156 -0
- datalab/data/icons/analysis/fwhm.svg +156 -0
- datalab/data/icons/analysis/histogram.svg +49 -0
- datalab/data/icons/analysis/peak_detect.svg +160 -0
- datalab/data/icons/analysis/plot_results.svg +151 -0
- datalab/data/icons/analysis/show_results.svg +83 -0
- datalab/data/icons/analysis/stats.svg +49 -0
- datalab/data/icons/analysis.svg +120 -0
- datalab/data/icons/apply.svg +3 -0
- datalab/data/icons/check_all.svg +15 -0
- datalab/data/icons/collapse.svg +44 -0
- datalab/data/icons/collapse_selection.svg +63 -0
- datalab/data/icons/console.svg +101 -0
- datalab/data/icons/create/1d-normal.svg +8 -0
- datalab/data/icons/create/1d-poisson.svg +9 -0
- datalab/data/icons/create/1d-uniform.svg +8 -0
- datalab/data/icons/create/1d-zero.svg +57 -0
- datalab/data/icons/create/2d-gaussian.svg +56 -0
- datalab/data/icons/create/2d-normal.svg +38 -0
- datalab/data/icons/create/2d-poisson.svg +38 -0
- datalab/data/icons/create/2d-ramp.svg +90 -0
- datalab/data/icons/create/2d-sinc.svg +62 -0
- datalab/data/icons/create/2d-uniform.svg +38 -0
- datalab/data/icons/create/2d-zero.svg +13 -0
- datalab/data/icons/create/checkerboard.svg +39 -0
- datalab/data/icons/create/cosine.svg +12 -0
- datalab/data/icons/create/exponential.svg +55 -0
- datalab/data/icons/create/gaussian.svg +12 -0
- datalab/data/icons/create/grating.svg +29 -0
- datalab/data/icons/create/linear_chirp.svg +7 -0
- datalab/data/icons/create/logistic.svg +7 -0
- datalab/data/icons/create/lorentzian.svg +12 -0
- datalab/data/icons/create/planck.svg +12 -0
- datalab/data/icons/create/polynomial.svg +7 -0
- datalab/data/icons/create/pulse.svg +12 -0
- datalab/data/icons/create/ring.svg +18 -0
- datalab/data/icons/create/sawtooth.svg +7 -0
- datalab/data/icons/create/siemens.svg +35 -0
- datalab/data/icons/create/sinc.svg +12 -0
- datalab/data/icons/create/sine.svg +7 -0
- datalab/data/icons/create/square.svg +7 -0
- datalab/data/icons/create/square_pulse.svg +7 -0
- datalab/data/icons/create/step.svg +7 -0
- datalab/data/icons/create/step_pulse.svg +12 -0
- datalab/data/icons/create/triangle.svg +7 -0
- datalab/data/icons/create/voigt.svg +12 -0
- datalab/data/icons/edit/annotations.svg +72 -0
- datalab/data/icons/edit/annotations_copy.svg +114 -0
- datalab/data/icons/edit/annotations_delete.svg +83 -0
- datalab/data/icons/edit/annotations_edit.svg +98 -0
- datalab/data/icons/edit/annotations_export.svg +85 -0
- datalab/data/icons/edit/annotations_import.svg +85 -0
- datalab/data/icons/edit/annotations_paste.svg +100 -0
- datalab/data/icons/edit/copy_titles.svg +109 -0
- datalab/data/icons/edit/delete.svg +84 -0
- datalab/data/icons/edit/delete_all.svg +214 -0
- datalab/data/icons/edit/duplicate.svg +64 -0
- datalab/data/icons/edit/goto_source.svg +60 -0
- datalab/data/icons/edit/metadata.svg +60 -0
- datalab/data/icons/edit/metadata_add.svg +80 -0
- datalab/data/icons/edit/metadata_copy.svg +96 -0
- datalab/data/icons/edit/metadata_delete.svg +62 -0
- datalab/data/icons/edit/metadata_export.svg +68 -0
- datalab/data/icons/edit/metadata_import.svg +68 -0
- datalab/data/icons/edit/metadata_paste.svg +79 -0
- datalab/data/icons/edit/move_down.svg +55 -0
- datalab/data/icons/edit/move_up.svg +54 -0
- datalab/data/icons/edit/new_group.svg +76 -0
- datalab/data/icons/edit/recompute.svg +60 -0
- datalab/data/icons/edit/rename.svg +49 -0
- datalab/data/icons/edit.svg +16 -0
- datalab/data/icons/expand.svg +44 -0
- datalab/data/icons/expand_selection.svg +63 -0
- datalab/data/icons/fit/cdf_fit.svg +56 -0
- datalab/data/icons/fit/exponential_fit.svg +55 -0
- datalab/data/icons/fit/gaussian_fit.svg +62 -0
- datalab/data/icons/fit/interactive_fit.svg +101 -0
- datalab/data/icons/fit/linear_fit.svg +57 -0
- datalab/data/icons/fit/lorentzian_fit.svg +209 -0
- datalab/data/icons/fit/multigaussian_fit.svg +85 -0
- datalab/data/icons/fit/multilorentzian_fit.svg +85 -0
- datalab/data/icons/fit/piecewiseexponential_fit.svg +209 -0
- datalab/data/icons/fit/planckian_fit.svg +62 -0
- datalab/data/icons/fit/polynomial_fit.svg +59 -0
- datalab/data/icons/fit/sigmoid_fit.svg +56 -0
- datalab/data/icons/fit/sinusoidal_fit.svg +72 -0
- datalab/data/icons/fit/twohalfgaussian_fit.svg +63 -0
- datalab/data/icons/fit/voigt_fit.svg +57 -0
- datalab/data/icons/group.svg +56 -0
- datalab/data/icons/h5/h5array.svg +59 -0
- datalab/data/icons/h5/h5attrs.svg +75 -0
- datalab/data/icons/h5/h5browser.svg +133 -0
- datalab/data/icons/h5/h5file.svg +69 -0
- datalab/data/icons/h5/h5group.svg +49 -0
- datalab/data/icons/h5/h5scalar.svg +1 -0
- datalab/data/icons/help_pdf.svg +46 -0
- datalab/data/icons/history.svg +7 -0
- datalab/data/icons/image.svg +135 -0
- datalab/data/icons/io/fileopen_directory.svg +60 -0
- datalab/data/icons/io/fileopen_h5.svg +84 -0
- datalab/data/icons/io/fileopen_ima.svg +187 -0
- datalab/data/icons/io/fileopen_py.svg +123 -0
- datalab/data/icons/io/fileopen_sig.svg +138 -0
- datalab/data/icons/io/filesave_h5.svg +97 -0
- datalab/data/icons/io/filesave_ima.svg +200 -0
- datalab/data/icons/io/filesave_py.svg +136 -0
- datalab/data/icons/io/filesave_sig.svg +151 -0
- datalab/data/icons/io/import_text.svg +144 -0
- datalab/data/icons/io/save_to_directory.svg +134 -0
- datalab/data/icons/io.svg +84 -0
- datalab/data/icons/libre-camera-flash-off.svg +1 -0
- datalab/data/icons/libre-camera-flash-on.svg +1 -0
- datalab/data/icons/libre-gui-about.svg +1 -0
- datalab/data/icons/libre-gui-action-delete.svg +1 -0
- datalab/data/icons/libre-gui-add.svg +1 -0
- datalab/data/icons/libre-gui-arrow-down.svg +1 -0
- datalab/data/icons/libre-gui-arrow-left.svg +1 -0
- datalab/data/icons/libre-gui-arrow-right.svg +1 -0
- datalab/data/icons/libre-gui-arrow-up.svg +1 -0
- datalab/data/icons/libre-gui-close.svg +40 -0
- datalab/data/icons/libre-gui-cogs.svg +1 -0
- datalab/data/icons/libre-gui-globe.svg +1 -0
- datalab/data/icons/libre-gui-help.svg +1 -0
- datalab/data/icons/libre-gui-link.svg +1 -0
- datalab/data/icons/libre-gui-menu.svg +1 -0
- datalab/data/icons/libre-gui-pencil.svg +1 -0
- datalab/data/icons/libre-gui-plugin.svg +1 -0
- datalab/data/icons/libre-gui-questions.svg +1 -0
- datalab/data/icons/libre-gui-settings.svg +1 -0
- datalab/data/icons/libre-gui-unlink.svg +1 -0
- datalab/data/icons/libre-tech-ram.svg +1 -0
- datalab/data/icons/libre-toolbox.svg +1 -0
- datalab/data/icons/logs.svg +1 -0
- datalab/data/icons/markers.svg +74 -0
- datalab/data/icons/menu.svg +13 -0
- datalab/data/icons/new_ima.svg +148 -0
- datalab/data/icons/new_sig.svg +123 -0
- datalab/data/icons/operations/abs.svg +116 -0
- datalab/data/icons/operations/arithmetic.svg +123 -0
- datalab/data/icons/operations/average.svg +124 -0
- datalab/data/icons/operations/complex_from_magnitude_phase.svg +116 -0
- datalab/data/icons/operations/complex_from_real_imag.svg +124 -0
- datalab/data/icons/operations/constant.svg +116 -0
- datalab/data/icons/operations/constant_add.svg +109 -0
- datalab/data/icons/operations/constant_divide.svg +109 -0
- datalab/data/icons/operations/constant_multiply.svg +109 -0
- datalab/data/icons/operations/constant_subtract.svg +109 -0
- datalab/data/icons/operations/convert_dtype.svg +117 -0
- datalab/data/icons/operations/convolution.svg +46 -0
- datalab/data/icons/operations/deconvolution.svg +57 -0
- datalab/data/icons/operations/derivative.svg +127 -0
- datalab/data/icons/operations/difference.svg +52 -0
- datalab/data/icons/operations/division.svg +139 -0
- datalab/data/icons/operations/exp.svg +116 -0
- datalab/data/icons/operations/flip_horizontally.svg +69 -0
- datalab/data/icons/operations/flip_vertically.svg +74 -0
- datalab/data/icons/operations/im.svg +124 -0
- datalab/data/icons/operations/integral.svg +50 -0
- datalab/data/icons/operations/inverse.svg +143 -0
- datalab/data/icons/operations/log10.svg +109 -0
- datalab/data/icons/operations/phase.svg +116 -0
- datalab/data/icons/operations/power.svg +118 -0
- datalab/data/icons/operations/product.svg +124 -0
- datalab/data/icons/operations/profile.svg +379 -0
- datalab/data/icons/operations/profile_average.svg +399 -0
- datalab/data/icons/operations/profile_radial.svg +261 -0
- datalab/data/icons/operations/profile_segment.svg +262 -0
- datalab/data/icons/operations/quadratic_difference.svg +84 -0
- datalab/data/icons/operations/re.svg +124 -0
- datalab/data/icons/operations/rotate_left.svg +72 -0
- datalab/data/icons/operations/rotate_right.svg +72 -0
- datalab/data/icons/operations/signals_to_image.svg +314 -0
- datalab/data/icons/operations/sqrt.svg +110 -0
- datalab/data/icons/operations/std.svg +124 -0
- datalab/data/icons/operations/sum.svg +102 -0
- datalab/data/icons/play_demo.svg +9 -0
- datalab/data/icons/processing/axis_transform.svg +62 -0
- datalab/data/icons/processing/bandpass.svg +79 -0
- datalab/data/icons/processing/bandstop.svg +71 -0
- datalab/data/icons/processing/binning.svg +126 -0
- datalab/data/icons/processing/clip.svg +119 -0
- datalab/data/icons/processing/detrending.svg +173 -0
- datalab/data/icons/processing/distribute_on_grid.svg +769 -0
- datalab/data/icons/processing/edge_detection.svg +46 -0
- datalab/data/icons/processing/erase.svg +1 -0
- datalab/data/icons/processing/exposure.svg +143 -0
- datalab/data/icons/processing/fourier.svg +104 -0
- datalab/data/icons/processing/highpass.svg +59 -0
- datalab/data/icons/processing/interpolation.svg +71 -0
- datalab/data/icons/processing/level_adjustment.svg +70 -0
- datalab/data/icons/processing/lowpass.svg +60 -0
- datalab/data/icons/processing/morphology.svg +49 -0
- datalab/data/icons/processing/noise_addition.svg +114 -0
- datalab/data/icons/processing/noise_reduction.svg +38 -0
- datalab/data/icons/processing/normalize.svg +84 -0
- datalab/data/icons/processing/offset_correction.svg +131 -0
- datalab/data/icons/processing/resampling1d.svg +101 -0
- datalab/data/icons/processing/resampling2d.svg +240 -0
- datalab/data/icons/processing/reset_positions.svg +185 -0
- datalab/data/icons/processing/resize.svg +9 -0
- datalab/data/icons/processing/reverse_signal_x.svg +171 -0
- datalab/data/icons/processing/stability.svg +11 -0
- datalab/data/icons/processing/swap_x_y.svg +65 -0
- datalab/data/icons/processing/thresholding.svg +63 -0
- datalab/data/icons/processing/windowing.svg +45 -0
- datalab/data/icons/properties.svg +26 -0
- datalab/data/icons/reset.svg +9 -0
- datalab/data/icons/restore.svg +40 -0
- datalab/data/icons/roi/roi.svg +76 -0
- datalab/data/icons/roi/roi_coordinate.svg +78 -0
- datalab/data/icons/roi/roi_copy.svg +112 -0
- datalab/data/icons/roi/roi_delete.svg +81 -0
- datalab/data/icons/roi/roi_export.svg +87 -0
- datalab/data/icons/roi/roi_graphical.svg +78 -0
- datalab/data/icons/roi/roi_grid.svg +67 -0
- datalab/data/icons/roi/roi_ima.svg +188 -0
- datalab/data/icons/roi/roi_import.svg +87 -0
- datalab/data/icons/roi/roi_new.svg +81 -0
- datalab/data/icons/roi/roi_new_circle.svg +95 -0
- datalab/data/icons/roi/roi_new_polygon.svg +110 -0
- datalab/data/icons/roi/roi_new_rectangle.svg +70 -0
- datalab/data/icons/roi/roi_paste.svg +98 -0
- datalab/data/icons/roi/roi_sig.svg +124 -0
- datalab/data/icons/shapes.svg +134 -0
- datalab/data/icons/signal.svg +103 -0
- datalab/data/icons/table.svg +85 -0
- datalab/data/icons/table_unavailable.svg +102 -0
- datalab/data/icons/to_signal.svg +124 -0
- datalab/data/icons/tour/next.svg +44 -0
- datalab/data/icons/tour/previous.svg +44 -0
- datalab/data/icons/tour/rewind.svg +51 -0
- datalab/data/icons/tour/stop.svg +47 -0
- datalab/data/icons/tour/tour.svg +16 -0
- datalab/data/icons/uncheck_all.svg +78 -0
- datalab/data/icons/view/curve_antialiasing.svg +50 -0
- datalab/data/icons/view/new_window.svg +98 -0
- datalab/data/icons/view/refresh-auto.svg +57 -0
- datalab/data/icons/view/refresh-manual.svg +51 -0
- datalab/data/icons/view/reset_curve_styles.svg +96 -0
- datalab/data/icons/view/show_first.svg +55 -0
- datalab/data/icons/view/show_titles.svg +46 -0
- datalab/data/icons/visualization.svg +51 -0
- datalab/data/logo/DataLab-Banner-150.png +0 -0
- datalab/data/logo/DataLab-Banner-200.png +0 -0
- datalab/data/logo/DataLab-Banner2-100.png +0 -0
- datalab/data/logo/DataLab-Splash.png +0 -0
- datalab/data/logo/DataLab-watermark.png +0 -0
- datalab/data/logo/DataLab.svg +83 -0
- datalab/data/tests/reordering_test.h5 +0 -0
- datalab/data/tutorials/fabry_perot/fabry-perot1.jpg +0 -0
- datalab/data/tutorials/fabry_perot/fabry-perot2.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_13.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_18.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_23.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_30.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_35.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_40.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_45.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_50.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_55.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_60.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_65.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_70.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_75.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_80.jpg +0 -0
- datalab/env.py +542 -0
- datalab/gui/__init__.py +89 -0
- datalab/gui/actionhandler.py +1701 -0
- datalab/gui/docks.py +473 -0
- datalab/gui/h5io.py +150 -0
- datalab/gui/macroeditor.py +310 -0
- datalab/gui/main.py +2081 -0
- datalab/gui/newobject.py +217 -0
- datalab/gui/objectview.py +766 -0
- datalab/gui/panel/__init__.py +48 -0
- datalab/gui/panel/base.py +3254 -0
- datalab/gui/panel/image.py +157 -0
- datalab/gui/panel/macro.py +607 -0
- datalab/gui/panel/signal.py +164 -0
- datalab/gui/plothandler.py +800 -0
- datalab/gui/processor/__init__.py +84 -0
- datalab/gui/processor/base.py +2456 -0
- datalab/gui/processor/catcher.py +75 -0
- datalab/gui/processor/image.py +1214 -0
- datalab/gui/processor/signal.py +755 -0
- datalab/gui/profiledialog.py +333 -0
- datalab/gui/roieditor.py +633 -0
- datalab/gui/roigrideditor.py +208 -0
- datalab/gui/settings.py +612 -0
- datalab/gui/tour.py +908 -0
- datalab/h5/__init__.py +12 -0
- datalab/h5/common.py +314 -0
- datalab/h5/generic.py +580 -0
- datalab/h5/native.py +39 -0
- datalab/h5/utils.py +95 -0
- datalab/objectmodel.py +640 -0
- datalab/plugins/_readme_.txt +9 -0
- datalab/plugins/datalab_imageformats.py +175 -0
- datalab/plugins/datalab_testdata.py +190 -0
- datalab/plugins.py +355 -0
- datalab/tests/__init__.py +199 -0
- datalab/tests/backbone/__init__.py +1 -0
- datalab/tests/backbone/config_unit_test.py +170 -0
- datalab/tests/backbone/config_versioning_unit_test.py +34 -0
- datalab/tests/backbone/dictlistserial_app_test.py +38 -0
- datalab/tests/backbone/errorcatcher_unit_test.py +69 -0
- datalab/tests/backbone/errormsgbox_unit_test.py +50 -0
- datalab/tests/backbone/execenv_unit.py +262 -0
- datalab/tests/backbone/loadtest_gdi.py +147 -0
- datalab/tests/backbone/long_callback.py +96 -0
- datalab/tests/backbone/main_app_test.py +137 -0
- datalab/tests/backbone/memory_leak.py +43 -0
- datalab/tests/backbone/procisolation1_unit.py +128 -0
- datalab/tests/backbone/procisolation2_unit.py +171 -0
- datalab/tests/backbone/procisolation_unit_test.py +22 -0
- datalab/tests/backbone/profiling_app.py +27 -0
- datalab/tests/backbone/strings_unit_test.py +65 -0
- datalab/tests/backbone/title_formatting_unit_test.py +82 -0
- datalab/tests/conftest.py +131 -0
- datalab/tests/features/__init__.py +1 -0
- datalab/tests/features/applauncher/__init__.py +1 -0
- datalab/tests/features/applauncher/launcher1_app_test.py +28 -0
- datalab/tests/features/applauncher/launcher2_app_test.py +30 -0
- datalab/tests/features/common/__init__.py +1 -0
- datalab/tests/features/common/add_metadata_app_test.py +134 -0
- datalab/tests/features/common/add_metadata_unit_test.py +267 -0
- datalab/tests/features/common/annotations_management_unit_test.py +152 -0
- datalab/tests/features/common/auto_analysis_recompute_unit_test.py +240 -0
- datalab/tests/features/common/createobject_unit_test.py +50 -0
- datalab/tests/features/common/geometry_results_app_test.py +135 -0
- datalab/tests/features/common/interactive_processing_test.py +1109 -0
- datalab/tests/features/common/io_app_test.py +75 -0
- datalab/tests/features/common/large_results_app_test.py +187 -0
- datalab/tests/features/common/metadata_all_patterns_test.py +103 -0
- datalab/tests/features/common/metadata_app_test.py +139 -0
- datalab/tests/features/common/metadata_io_unit_test.py +60 -0
- datalab/tests/features/common/misc_app_test.py +236 -0
- datalab/tests/features/common/multiple_geometry_results_unit_test.py +122 -0
- datalab/tests/features/common/multiple_table_results_unit_test.py +64 -0
- datalab/tests/features/common/operation_modes_app_test.py +392 -0
- datalab/tests/features/common/plot_results_app_test.py +278 -0
- datalab/tests/features/common/reorder_app_test.py +75 -0
- datalab/tests/features/common/result_deletion_unit_test.py +96 -0
- datalab/tests/features/common/result_merged_label_unit_test.py +154 -0
- datalab/tests/features/common/result_shape_settings_unit_test.py +223 -0
- datalab/tests/features/common/roi_plotitem_unit_test.py +64 -0
- datalab/tests/features/common/roieditor_unit_test.py +102 -0
- datalab/tests/features/common/save_to_dir_app_test.py +163 -0
- datalab/tests/features/common/save_to_dir_unit_test.py +474 -0
- datalab/tests/features/common/stat_app_test.py +40 -0
- datalab/tests/features/common/stats_tools_unit_test.py +77 -0
- datalab/tests/features/common/table_results_app_test.py +52 -0
- datalab/tests/features/common/textimport_unit_test.py +131 -0
- datalab/tests/features/common/uuid_preservation_test.py +281 -0
- datalab/tests/features/common/worker_unit_test.py +402 -0
- datalab/tests/features/control/__init__.py +1 -0
- datalab/tests/features/control/connect_dialog.py +28 -0
- datalab/tests/features/control/embedded1_unit_test.py +304 -0
- datalab/tests/features/control/embedded2_unit_test.py +52 -0
- datalab/tests/features/control/remoteclient_app_test.py +219 -0
- datalab/tests/features/control/remoteclient_unit.py +75 -0
- datalab/tests/features/control/simpleclient_unit_test.py +321 -0
- datalab/tests/features/hdf5/__init__.py +1 -0
- datalab/tests/features/hdf5/h5browser1_unit_test.py +31 -0
- datalab/tests/features/hdf5/h5browser2_unit.py +55 -0
- datalab/tests/features/hdf5/h5browser_app_test.py +77 -0
- datalab/tests/features/hdf5/h5import_app_test.py +25 -0
- datalab/tests/features/hdf5/h5importer_app_test.py +34 -0
- datalab/tests/features/image/__init__.py +1 -0
- datalab/tests/features/image/annotations_app_test.py +28 -0
- datalab/tests/features/image/annotations_unit_test.py +80 -0
- datalab/tests/features/image/average_app_test.py +46 -0
- datalab/tests/features/image/background_dialog_test.py +70 -0
- datalab/tests/features/image/blobs_app_test.py +50 -0
- datalab/tests/features/image/contour_app_test.py +42 -0
- datalab/tests/features/image/contour_fabryperot_app_test.py +51 -0
- datalab/tests/features/image/denoise_app_test.py +31 -0
- datalab/tests/features/image/distribute_on_grid_app_test.py +95 -0
- datalab/tests/features/image/edges_app_test.py +31 -0
- datalab/tests/features/image/erase_app_test.py +21 -0
- datalab/tests/features/image/fft2d_app_test.py +27 -0
- datalab/tests/features/image/flatfield_app_test.py +40 -0
- datalab/tests/features/image/geometry_transform_unit_test.py +396 -0
- datalab/tests/features/image/imagetools_app_test.py +51 -0
- datalab/tests/features/image/imagetools_unit_test.py +27 -0
- datalab/tests/features/image/load_app_test.py +73 -0
- datalab/tests/features/image/morph_app_test.py +32 -0
- datalab/tests/features/image/offsetcorrection_app_test.py +30 -0
- datalab/tests/features/image/peak2d_app_test.py +53 -0
- datalab/tests/features/image/profile_app_test.py +73 -0
- datalab/tests/features/image/profile_dialog_test.py +56 -0
- datalab/tests/features/image/roi_app_test.py +98 -0
- datalab/tests/features/image/roi_circ_app_test.py +62 -0
- datalab/tests/features/image/roi_manipulation_app_test.py +268 -0
- datalab/tests/features/image/roigrid_unit_test.py +60 -0
- datalab/tests/features/image/side_by_side_app_test.py +52 -0
- datalab/tests/features/macro/__init__.py +1 -0
- datalab/tests/features/macro/macro_app_test.py +28 -0
- datalab/tests/features/macro/macroeditor_unit_test.py +102 -0
- datalab/tests/features/signal/__init__.py +1 -0
- datalab/tests/features/signal/baseline_dialog_test.py +53 -0
- datalab/tests/features/signal/deltax_dialog_unit_test.py +34 -0
- datalab/tests/features/signal/fft1d_app_test.py +26 -0
- datalab/tests/features/signal/filter_app_test.py +44 -0
- datalab/tests/features/signal/fitdialog_unit_test.py +50 -0
- datalab/tests/features/signal/interpolation_app_test.py +110 -0
- datalab/tests/features/signal/loadbigsignal_app_test.py +80 -0
- datalab/tests/features/signal/multiple_rois_unit_test.py +132 -0
- datalab/tests/features/signal/pulse_features_app_test.py +118 -0
- datalab/tests/features/signal/pulse_features_roi_app_test.py +55 -0
- datalab/tests/features/signal/roi_app_test.py +78 -0
- datalab/tests/features/signal/roi_manipulation_app_test.py +261 -0
- datalab/tests/features/signal/select_xy_cursor_unit_test.py +46 -0
- datalab/tests/features/signal/signalpeakdetection_dialog_test.py +33 -0
- datalab/tests/features/signal/signals_to_image_app_test.py +98 -0
- datalab/tests/features/signal/xarray_compat_app_test.py +128 -0
- datalab/tests/features/tour_unit_test.py +22 -0
- datalab/tests/features/utilities/__init__.py +1 -0
- datalab/tests/features/utilities/installconf_unit_test.py +21 -0
- datalab/tests/features/utilities/logview_app_test.py +21 -0
- datalab/tests/features/utilities/logview_error.py +24 -0
- datalab/tests/features/utilities/logview_unit_test.py +21 -0
- datalab/tests/features/utilities/memstatus_app_test.py +42 -0
- datalab/tests/features/utilities/settings_unit_test.py +88 -0
- datalab/tests/scenarios/__init__.py +1 -0
- datalab/tests/scenarios/beautiful_app.py +121 -0
- datalab/tests/scenarios/common.py +463 -0
- datalab/tests/scenarios/demo.py +212 -0
- datalab/tests/scenarios/example_app_test.py +47 -0
- datalab/tests/scenarios/scenario_h5_app_test.py +75 -0
- datalab/tests/scenarios/scenario_ima1_app_test.py +34 -0
- datalab/tests/scenarios/scenario_ima2_app_test.py +34 -0
- datalab/tests/scenarios/scenario_mac_app_test.py +58 -0
- datalab/tests/scenarios/scenario_sig1_app_test.py +36 -0
- datalab/tests/scenarios/scenario_sig2_app_test.py +35 -0
- datalab/utils/__init__.py +1 -0
- datalab/utils/conf.py +304 -0
- datalab/utils/dephash.py +105 -0
- datalab/utils/qthelpers.py +633 -0
- datalab/utils/strings.py +34 -0
- datalab/utils/tests.py +0 -0
- datalab/widgets/__init__.py +1 -0
- datalab/widgets/connection.py +138 -0
- datalab/widgets/filedialog.py +91 -0
- datalab/widgets/fileviewer.py +84 -0
- datalab/widgets/fitdialog.py +788 -0
- datalab/widgets/h5browser.py +1048 -0
- datalab/widgets/imagebackground.py +111 -0
- datalab/widgets/instconfviewer.py +175 -0
- datalab/widgets/logviewer.py +80 -0
- datalab/widgets/signalbaseline.py +90 -0
- datalab/widgets/signalcursor.py +208 -0
- datalab/widgets/signaldeltax.py +151 -0
- datalab/widgets/signalpeak.py +199 -0
- datalab/widgets/status.py +249 -0
- datalab/widgets/textimport.py +786 -0
- datalab/widgets/warningerror.py +223 -0
- datalab/widgets/wizard.py +286 -0
- datalab_platform-1.0.0.dist-info/METADATA +121 -0
- datalab_platform-1.0.0.dist-info/RECORD +494 -0
- datalab_platform-0.0.1.dev0.dist-info/METADATA +0 -67
- datalab_platform-0.0.1.dev0.dist-info/RECORD +0 -7
- {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.0.dist-info}/WHEEL +0 -0
- {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.0.dist-info}/entry_points.txt +0 -0
- {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.0.dist-info}/licenses/LICENSE +0 -0
- {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
GDI objects loading test
|
|
5
|
+
========================
|
|
6
|
+
|
|
7
|
+
This test is specific to Windows. It is not relevant for other platforms.
|
|
8
|
+
|
|
9
|
+
This test aims at checking that all GDI objects are released when the
|
|
10
|
+
widget are closed (i.e. when the Python object is garbage collected).
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
# pylint: disable=invalid-name # Allows short reference names like x, y, ...
|
|
14
|
+
# pylint: disable=duplicate-code
|
|
15
|
+
|
|
16
|
+
# guitest: skip
|
|
17
|
+
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
import ctypes
|
|
21
|
+
import os
|
|
22
|
+
|
|
23
|
+
from sigima.objects import NewImageParam
|
|
24
|
+
from sigima.tests.data import create_sincos_image, iterate_image_creation
|
|
25
|
+
|
|
26
|
+
from datalab.env import execenv
|
|
27
|
+
from datalab.gui.main import DLMainWindow
|
|
28
|
+
from datalab.tests import datalab_test_app_context, helpers
|
|
29
|
+
from datalab.tests.scenarios.common import compute_common_operations
|
|
30
|
+
|
|
31
|
+
if os.name == "nt":
|
|
32
|
+
from ctypes import WinDLL
|
|
33
|
+
|
|
34
|
+
def get_gdi_count() -> int:
|
|
35
|
+
"""Get the number of GDI objects for the current process.
|
|
36
|
+
|
|
37
|
+
This function uses the Windows API to get the count of GDI (Graphical
|
|
38
|
+
Device Interface) objects used by the current process.
|
|
39
|
+
|
|
40
|
+
Note: This function will only work on Windows.
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
int: The count of GDI objects for the current process.
|
|
44
|
+
"""
|
|
45
|
+
# Constants
|
|
46
|
+
GR_GDIOBJECTS: int = 0
|
|
47
|
+
|
|
48
|
+
# Load the User32 DLL
|
|
49
|
+
user32: WinDLL = ctypes.windll.user32
|
|
50
|
+
|
|
51
|
+
# Get the current process id
|
|
52
|
+
pid: int = os.getpid()
|
|
53
|
+
|
|
54
|
+
# Get handle of the process
|
|
55
|
+
handle: int = ctypes.windll.kernel32.OpenProcess(1040, 0, pid)
|
|
56
|
+
|
|
57
|
+
# Call the function and get the GDI count
|
|
58
|
+
gdi_count: int = user32.GetGuiResources(handle, GR_GDIOBJECTS)
|
|
59
|
+
|
|
60
|
+
# Close the handle
|
|
61
|
+
ctypes.windll.kernel32.CloseHandle(handle)
|
|
62
|
+
|
|
63
|
+
return gdi_count
|
|
64
|
+
|
|
65
|
+
else:
|
|
66
|
+
|
|
67
|
+
def get_gdi_count() -> int:
|
|
68
|
+
"""Dumb function that always returns 0."""
|
|
69
|
+
return 0
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def test_various_image_features(win: DLMainWindow):
|
|
73
|
+
"""Run image related tests."""
|
|
74
|
+
win.set_current_panel("image")
|
|
75
|
+
panel = win.imagepanel
|
|
76
|
+
param = NewImageParam.create(height=150, width=150)
|
|
77
|
+
for image in iterate_image_creation(param.width, non_zero=True, verbose=False):
|
|
78
|
+
panel.add_object(create_sincos_image(param))
|
|
79
|
+
panel.add_object(image)
|
|
80
|
+
compute_common_operations(panel)
|
|
81
|
+
panel.remove_all_objects()
|
|
82
|
+
break
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def test_gdi_count(win: DLMainWindow) -> int | None:
|
|
86
|
+
"""Test the GDI count.
|
|
87
|
+
|
|
88
|
+
This function will create a DataSetGroup, show the widget, and then
|
|
89
|
+
close the widget. It will then check that the GDI count has not
|
|
90
|
+
increased.
|
|
91
|
+
|
|
92
|
+
Raises:
|
|
93
|
+
AssertionError: If the GDI count has increased.
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
int: The GDI count after creating the widget.
|
|
97
|
+
"""
|
|
98
|
+
# Get the GDI count before creating the widget
|
|
99
|
+
gdi_count_before: int = get_gdi_count()
|
|
100
|
+
|
|
101
|
+
execenv.print(f" GDI count: {gdi_count_before} --> ", end="")
|
|
102
|
+
|
|
103
|
+
# Create widgets during the test
|
|
104
|
+
test_various_image_features(win)
|
|
105
|
+
|
|
106
|
+
# Import HDF5 file using the HDF5 browser
|
|
107
|
+
win.open_h5_files(
|
|
108
|
+
helpers.get_test_fnames("*.h5")[:5], import_all=True, reset_all=False
|
|
109
|
+
)
|
|
110
|
+
for panel in (win.signalpanel, win.imagepanel):
|
|
111
|
+
panel.remove_all_objects()
|
|
112
|
+
|
|
113
|
+
# Get the GDI count after creating the widget
|
|
114
|
+
gdi_count_after: int = get_gdi_count()
|
|
115
|
+
|
|
116
|
+
execenv.print(gdi_count_after)
|
|
117
|
+
|
|
118
|
+
# # Check that the GDI count has not increased
|
|
119
|
+
# assert gdi_count_before == gdi_count_after
|
|
120
|
+
# assert gdi_count_before == gdi_count_after_close
|
|
121
|
+
|
|
122
|
+
return gdi_count_after
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def load_test():
|
|
126
|
+
"""Load test."""
|
|
127
|
+
with execenv.context(unattended=True):
|
|
128
|
+
with datalab_test_app_context() as win:
|
|
129
|
+
gdi_count = []
|
|
130
|
+
for iteration in range(4):
|
|
131
|
+
execenv.print(f"Test iteration: {iteration}")
|
|
132
|
+
count = test_gdi_count(win)
|
|
133
|
+
if count is None:
|
|
134
|
+
execenv.print("Test aborted")
|
|
135
|
+
break
|
|
136
|
+
gdi_count.append(count)
|
|
137
|
+
if iteration > 0:
|
|
138
|
+
increase = gdi_count[-1] - gdi_count[-2]
|
|
139
|
+
assert increase <= 0, "GDI count should not increase (memory leak)"
|
|
140
|
+
increase_pct = increase / gdi_count[0] * 100
|
|
141
|
+
execenv.print(
|
|
142
|
+
f" GDI count increase: {increase:+d} ({increase_pct:.2f}%)"
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
if __name__ == "__main__":
|
|
147
|
+
load_test()
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Long callback test
|
|
5
|
+
------------------
|
|
6
|
+
|
|
7
|
+
This test is not meant to be executed as part of the `pytest` suite, hence the
|
|
8
|
+
name of the script.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
# guitest: show,skip
|
|
12
|
+
|
|
13
|
+
import time
|
|
14
|
+
|
|
15
|
+
from guidata.qthelpers import qt_app_context
|
|
16
|
+
from qtpy import QtWidgets as QW
|
|
17
|
+
|
|
18
|
+
from datalab.utils.qthelpers import CallbackWorker, qt_long_callback
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def long_computation_func(delay: float) -> str:
|
|
22
|
+
"""Simulate long computation
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
delay: Delay in seconds
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
str: Result message
|
|
29
|
+
"""
|
|
30
|
+
time.sleep(delay)
|
|
31
|
+
return "OK"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def long_computation_progress_func(worker: CallbackWorker, delay: float) -> str:
|
|
35
|
+
"""Simulate long computation, with progress
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
worker: Callback worker
|
|
39
|
+
delay: Delay in seconds
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
str: Result message
|
|
43
|
+
"""
|
|
44
|
+
step_delay = 2.0
|
|
45
|
+
maxiter = int(delay / step_delay)
|
|
46
|
+
for idx in range(maxiter):
|
|
47
|
+
worker.set_progress(idx / maxiter)
|
|
48
|
+
if worker.was_canceled():
|
|
49
|
+
return f"Interrupted at iteration #{idx}"
|
|
50
|
+
time.sleep(step_delay)
|
|
51
|
+
return "Done"
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class TestWindow(QW.QMainWindow):
|
|
55
|
+
"""Test window"""
|
|
56
|
+
|
|
57
|
+
def __init__(self):
|
|
58
|
+
super().__init__()
|
|
59
|
+
self.setWindowTitle("Test window")
|
|
60
|
+
btn1 = QW.QPushButton("Run long computation")
|
|
61
|
+
btn1.clicked.connect(self.run_long_computation)
|
|
62
|
+
btn2 = QW.QPushButton("Run long computation with progress bar")
|
|
63
|
+
btn2.clicked.connect(self.run_long_computation_with_progress)
|
|
64
|
+
mainwidget = QW.QWidget()
|
|
65
|
+
layout = QW.QHBoxLayout()
|
|
66
|
+
mainwidget.setLayout(layout)
|
|
67
|
+
layout.addWidget(btn1)
|
|
68
|
+
layout.addWidget(btn2)
|
|
69
|
+
self.setCentralWidget(mainwidget)
|
|
70
|
+
|
|
71
|
+
def __execute_worker(self, worker: CallbackWorker, progress: bool) -> None:
|
|
72
|
+
"""Execute worker"""
|
|
73
|
+
ret = qt_long_callback(self, "Doing stuff...", worker, progress)
|
|
74
|
+
QW.QMessageBox.information(self, "Result", f"Long computation result: {ret}")
|
|
75
|
+
|
|
76
|
+
def run_long_computation(self) -> None:
|
|
77
|
+
"""Run long computation"""
|
|
78
|
+
worker = CallbackWorker(long_computation_func, delay=5.0)
|
|
79
|
+
self.__execute_worker(worker, progress=False)
|
|
80
|
+
|
|
81
|
+
def run_long_computation_with_progress(self) -> None:
|
|
82
|
+
"""Run long computation with progress"""
|
|
83
|
+
worker = CallbackWorker(long_computation_progress_func, delay=10.0)
|
|
84
|
+
self.__execute_worker(worker, progress=True)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def testing_long_callback() -> None:
|
|
88
|
+
"""Test long callback function"""
|
|
89
|
+
with qt_app_context(exec_loop=True):
|
|
90
|
+
win = TestWindow()
|
|
91
|
+
win.resize(800, 600)
|
|
92
|
+
win.show()
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
if __name__ == "__main__":
|
|
96
|
+
testing_long_callback()
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Application test for main window
|
|
5
|
+
--------------------------------
|
|
6
|
+
|
|
7
|
+
Testing the features of the main window of the application that are not
|
|
8
|
+
covered by other tests.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
# guitest: show
|
|
12
|
+
|
|
13
|
+
import os
|
|
14
|
+
|
|
15
|
+
import sigima.params
|
|
16
|
+
import sigima.proc.signal as sips
|
|
17
|
+
from sigima.tests.data import create_paracetamol_signal
|
|
18
|
+
|
|
19
|
+
from datalab.env import execenv
|
|
20
|
+
from datalab.objectmodel import get_short_id, get_uuid
|
|
21
|
+
from datalab.tests import datalab_test_app_context
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def test_main_app():
|
|
25
|
+
"""Main window test"""
|
|
26
|
+
with datalab_test_app_context(console=False) as win:
|
|
27
|
+
# Switch from panel to panel
|
|
28
|
+
for panelname in ("macro", "image", "signal"):
|
|
29
|
+
win.set_current_panel(panelname)
|
|
30
|
+
# Switch to an unknown panel
|
|
31
|
+
try:
|
|
32
|
+
win.set_current_panel("unknown_panel")
|
|
33
|
+
raise RuntimeError("Unknown panel should have raised an exception")
|
|
34
|
+
except ValueError:
|
|
35
|
+
pass
|
|
36
|
+
|
|
37
|
+
panel = win.signalpanel
|
|
38
|
+
|
|
39
|
+
# Create new groups
|
|
40
|
+
grp1 = panel.add_group("Group 1")
|
|
41
|
+
panel.add_group("Group 2")
|
|
42
|
+
# Add group using different levels of the API
|
|
43
|
+
panel.add_group("Group 3", select=True)
|
|
44
|
+
panel.remove_object(force=True)
|
|
45
|
+
win.add_group("Group 4", select=True)
|
|
46
|
+
panel.remove_object(force=True)
|
|
47
|
+
win.add_group("Group 5", panel="signal", select=True)
|
|
48
|
+
panel.remove_object(force=True)
|
|
49
|
+
# Rename group
|
|
50
|
+
panel.objview.select_groups([2])
|
|
51
|
+
panel.rename_selected_object_or_group("Group xxx")
|
|
52
|
+
panel.remove_object(force=True)
|
|
53
|
+
|
|
54
|
+
# Add signals to signal panel
|
|
55
|
+
sig1 = create_paracetamol_signal(500)
|
|
56
|
+
panel.add_object(sig1)
|
|
57
|
+
panel.rename_selected_object_or_group("Paracetamol Signal 1")
|
|
58
|
+
panel.processor.run_feature(sips.derivative)
|
|
59
|
+
panel.processor.run_feature(sips.wiener)
|
|
60
|
+
|
|
61
|
+
# Get object titles
|
|
62
|
+
titles = win.get_object_titles()
|
|
63
|
+
execenv.print(f"Object titles:{os.linesep}{titles}")
|
|
64
|
+
|
|
65
|
+
# Get object uuids
|
|
66
|
+
uuids = win.get_object_uuids()
|
|
67
|
+
uuids2 = win.get_object_uuids(group=1)
|
|
68
|
+
uuids3 = win.get_object_uuids(group="Group 1")
|
|
69
|
+
uuids4 = win.get_object_uuids(group=get_uuid(grp1))
|
|
70
|
+
assert uuids == uuids2 == uuids3 == uuids4, "Group UUIDs should be the same"
|
|
71
|
+
execenv.print(f"Object uuids:{os.linesep}{uuids}")
|
|
72
|
+
|
|
73
|
+
# Testing `get_object`
|
|
74
|
+
execenv.print("*** Testing `get_object` ***")
|
|
75
|
+
# Get object from title
|
|
76
|
+
obj = win.get_object(titles[-1])
|
|
77
|
+
execenv.print(f" Object (from title) '{get_short_id(obj)}':{os.linesep}{obj}")
|
|
78
|
+
# Get object
|
|
79
|
+
obj = win.get_object(1)
|
|
80
|
+
execenv.print(
|
|
81
|
+
f" Object (from number) '{get_short_id(obj)}':{os.linesep}{obj}"
|
|
82
|
+
)
|
|
83
|
+
# Get object by uuid
|
|
84
|
+
obj = win.get_object(uuids[-1])
|
|
85
|
+
execenv.print(f" Object (from uuid) '{get_short_id(obj)}':{os.linesep}{obj}")
|
|
86
|
+
|
|
87
|
+
# Testing dict-like interface of main window:
|
|
88
|
+
execenv.print("*** Testing dict-like interface of proxy ***")
|
|
89
|
+
# Get object from title
|
|
90
|
+
obj = win[titles[-1]]
|
|
91
|
+
execenv.print(f" Object (from title) '{get_short_id(obj)}':{os.linesep}{obj}")
|
|
92
|
+
# Get object
|
|
93
|
+
obj = win[1]
|
|
94
|
+
execenv.print(
|
|
95
|
+
f" Object (from number) '{get_short_id(obj)}':{os.linesep}{obj}"
|
|
96
|
+
)
|
|
97
|
+
# Get object by uuid
|
|
98
|
+
obj = win[uuids[-1]]
|
|
99
|
+
execenv.print(f" Object (from uuid) '{get_short_id(obj)}':{os.linesep}{obj}")
|
|
100
|
+
|
|
101
|
+
# Use "calc" method with parameters
|
|
102
|
+
param = sigima.params.MovingMedianParam.create(n=5)
|
|
103
|
+
win.calc("moving_median", param)
|
|
104
|
+
# Use "calc" method without parameters
|
|
105
|
+
win.calc("integral")
|
|
106
|
+
# Use "calc" and choose an unknown computation method
|
|
107
|
+
try:
|
|
108
|
+
win.calc("unknown_method")
|
|
109
|
+
raise RuntimeError("Unknown method should have raised an exception")
|
|
110
|
+
except ValueError:
|
|
111
|
+
pass
|
|
112
|
+
|
|
113
|
+
# Force application menus to pop-up
|
|
114
|
+
for menu in (
|
|
115
|
+
win.file_menu,
|
|
116
|
+
win.create_menu,
|
|
117
|
+
win.edit_menu,
|
|
118
|
+
win.roi_menu,
|
|
119
|
+
win.operation_menu,
|
|
120
|
+
win.processing_menu,
|
|
121
|
+
win.analysis_menu,
|
|
122
|
+
win.view_menu,
|
|
123
|
+
win.help_menu,
|
|
124
|
+
):
|
|
125
|
+
# Just access the menu to ensure it's created and initialized
|
|
126
|
+
assert menu is not None, f"Menu {menu.title()} should exist"
|
|
127
|
+
# Trigger aboutToShow to populate dynamic menus without showing the popup
|
|
128
|
+
menu.aboutToShow.emit()
|
|
129
|
+
# Verify menu has actions (optional, but good sanity check)
|
|
130
|
+
assert len(menu.actions()) > 0, f"Menu {menu.title()} should have actions"
|
|
131
|
+
|
|
132
|
+
# Open settings dialog
|
|
133
|
+
win.settings_action.trigger()
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
if __name__ == "__main__":
|
|
137
|
+
test_main_app()
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Memory leak test
|
|
5
|
+
|
|
6
|
+
DataLab application memory leak test.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
# guitest: skip
|
|
10
|
+
|
|
11
|
+
import os
|
|
12
|
+
|
|
13
|
+
import numpy as np
|
|
14
|
+
import psutil
|
|
15
|
+
from guidata.qthelpers import qt_app_context
|
|
16
|
+
from sigima.tests.vistools import view_curves
|
|
17
|
+
|
|
18
|
+
from datalab.env import execenv
|
|
19
|
+
from datalab.tests.features.control.embedded1_unit_test import HostWindow
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def memory_leak_test(iterations=100):
|
|
23
|
+
"""Test for memory leak"""
|
|
24
|
+
with qt_app_context():
|
|
25
|
+
proc = psutil.Process(os.getpid())
|
|
26
|
+
mainview = HostWindow()
|
|
27
|
+
mainview.show()
|
|
28
|
+
memlist = []
|
|
29
|
+
for i in range(iterations):
|
|
30
|
+
mainview.init_cdl()
|
|
31
|
+
mainview.close_datalab()
|
|
32
|
+
memdata = proc.memory_info().vms / 1024**2
|
|
33
|
+
memlist.append(memdata)
|
|
34
|
+
execenv.print(i + 1, ":", memdata, "MB")
|
|
35
|
+
view_curves(
|
|
36
|
+
np.array(memlist),
|
|
37
|
+
title="Memory leak test for DataLab application",
|
|
38
|
+
ylabel="Memory (MB)",
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
if __name__ == "__main__":
|
|
43
|
+
memory_leak_test()
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Process isolation unit test
|
|
5
|
+
---------------------------
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
# pylint: disable=invalid-name # Allows short reference names like x, y, ...
|
|
9
|
+
# pylint: disable=duplicate-code
|
|
10
|
+
# guitest: skip
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import time
|
|
15
|
+
from collections.abc import Callable
|
|
16
|
+
from multiprocessing.pool import AsyncResult, Pool
|
|
17
|
+
from typing import Any
|
|
18
|
+
|
|
19
|
+
import numpy as np
|
|
20
|
+
import scipy.signal as sps
|
|
21
|
+
from guidata.qthelpers import qt_app_context
|
|
22
|
+
from plotpy.plot import PlotWindow
|
|
23
|
+
from qtpy import QtWidgets as QW
|
|
24
|
+
from sigima.objects import ImageDatatypes, NewImageParam
|
|
25
|
+
from sigima.tests.data import create_2d_random, create_noisy_gaussian_image
|
|
26
|
+
|
|
27
|
+
from datalab.adapters_plotpy import create_adapter_from_object
|
|
28
|
+
from datalab.env import execenv
|
|
29
|
+
from datalab.utils.qthelpers import create_progress_bar
|
|
30
|
+
|
|
31
|
+
POOL: Pool | None = None
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class Worker:
|
|
35
|
+
"""Multiprocessing worker, to run long-running tasks in a separate process"""
|
|
36
|
+
|
|
37
|
+
def __init__(self) -> None:
|
|
38
|
+
self.asyncresult: AsyncResult = None
|
|
39
|
+
self.result: Any = None
|
|
40
|
+
|
|
41
|
+
@staticmethod
|
|
42
|
+
def create_pool() -> None:
|
|
43
|
+
"""Create multiprocessing pool"""
|
|
44
|
+
global POOL # pylint: disable=global-statement
|
|
45
|
+
# Create a pool with one process
|
|
46
|
+
POOL = Pool(processes=1) # pylint: disable=not-callable,consider-using-with
|
|
47
|
+
|
|
48
|
+
@staticmethod
|
|
49
|
+
def terminate_pool() -> None:
|
|
50
|
+
"""Terminate multiprocessing pool"""
|
|
51
|
+
global POOL # pylint: disable=global-statement
|
|
52
|
+
if POOL is not None:
|
|
53
|
+
POOL.terminate()
|
|
54
|
+
POOL.join()
|
|
55
|
+
POOL = None
|
|
56
|
+
|
|
57
|
+
def run(self, func: Callable, args: tuple[Any]) -> None:
|
|
58
|
+
"""Run computation"""
|
|
59
|
+
global POOL # pylint: disable=global-statement,global-variable-not-assigned
|
|
60
|
+
assert POOL is not None
|
|
61
|
+
self.asyncresult = POOL.apply_async(func, args)
|
|
62
|
+
|
|
63
|
+
def terminate(self) -> None:
|
|
64
|
+
"""Terminate worker"""
|
|
65
|
+
# Terminate the process and stop the timer
|
|
66
|
+
self.terminate_pool()
|
|
67
|
+
execenv.print("Computation cancelled!")
|
|
68
|
+
# Recreate the pool for the next computation
|
|
69
|
+
self.create_pool()
|
|
70
|
+
|
|
71
|
+
def is_computation_finished(self) -> bool:
|
|
72
|
+
"""Return True if computation is finished"""
|
|
73
|
+
return self.asyncresult.ready()
|
|
74
|
+
|
|
75
|
+
def get_result(self) -> Any:
|
|
76
|
+
"""Return computation result"""
|
|
77
|
+
self.result = self.asyncresult.get()
|
|
78
|
+
self.asyncresult = None
|
|
79
|
+
return self.result
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def testfunc(data: np.ndarray, size: int, error: bool) -> np.ndarray:
|
|
83
|
+
"""Test function"""
|
|
84
|
+
if error:
|
|
85
|
+
raise ValueError("Test error")
|
|
86
|
+
return sps.medfilt(data, size) + create_2d_random(data.shape[0], data.dtype)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def test_multiprocessing1(iterations: int = 4) -> None:
|
|
90
|
+
"""Multiprocessing test"""
|
|
91
|
+
Worker.create_pool()
|
|
92
|
+
with qt_app_context(exec_loop=True):
|
|
93
|
+
win = PlotWindow(title="Multiprocessing test", icon="datalab.svg", toolbar=True)
|
|
94
|
+
win.resize(800, 600)
|
|
95
|
+
win.show()
|
|
96
|
+
param = NewImageParam.create(
|
|
97
|
+
height=1000, width=1000, dtype=ImageDatatypes.UINT16
|
|
98
|
+
)
|
|
99
|
+
image = create_noisy_gaussian_image(param, add_annotations=True)
|
|
100
|
+
win.get_plot().add_item(create_adapter_from_object(image).make_item())
|
|
101
|
+
worker = Worker()
|
|
102
|
+
with create_progress_bar(win, "Computing", max_=iterations) as progress:
|
|
103
|
+
for index in range(iterations):
|
|
104
|
+
progress.setValue(index)
|
|
105
|
+
progress.setLabelText(f"Computing {index}")
|
|
106
|
+
test_error = index == 2
|
|
107
|
+
worker.run(testfunc, (image.data, 3, test_error))
|
|
108
|
+
while not worker.is_computation_finished():
|
|
109
|
+
QW.QApplication.processEvents()
|
|
110
|
+
time.sleep(0.1)
|
|
111
|
+
if progress.wasCanceled():
|
|
112
|
+
worker.terminate()
|
|
113
|
+
break
|
|
114
|
+
if worker.is_computation_finished():
|
|
115
|
+
try:
|
|
116
|
+
image.data = worker.get_result()
|
|
117
|
+
except Exception as exc: # pylint: disable=broad-except
|
|
118
|
+
execenv.print(f"Intercepted exception: {exc}")
|
|
119
|
+
win.get_plot().add_item(
|
|
120
|
+
create_adapter_from_object(image).make_item()
|
|
121
|
+
)
|
|
122
|
+
else:
|
|
123
|
+
break
|
|
124
|
+
worker.terminate_pool()
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
if __name__ == "__main__":
|
|
128
|
+
test_multiprocessing1()
|