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,223 @@
|
|
|
1
|
+
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Module providing a warning/error message box
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import os.path as osp
|
|
8
|
+
import re
|
|
9
|
+
import subprocess
|
|
10
|
+
import traceback
|
|
11
|
+
|
|
12
|
+
from guidata.config import CONF
|
|
13
|
+
from guidata.configtools import get_font
|
|
14
|
+
from guidata.qthelpers import exec_dialog, get_std_icon
|
|
15
|
+
from guidata.widgets.console.shell import PythonShellWidget
|
|
16
|
+
from qtpy import QtCore as QC
|
|
17
|
+
from qtpy import QtWidgets as QW
|
|
18
|
+
|
|
19
|
+
from datalab.config import Conf, _, get_mod_source_dir
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def go_to_error(text: str) -> None:
|
|
23
|
+
"""Go to error: open file with external editor, and go to line number
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
text (str): Error text
|
|
27
|
+
"""
|
|
28
|
+
pattern = r'File "(.+)", line (\d+),'
|
|
29
|
+
match = re.search(pattern, text)
|
|
30
|
+
if match:
|
|
31
|
+
path = match.group(1)
|
|
32
|
+
line_number = match.group(2)
|
|
33
|
+
mod_src_dir = get_mod_source_dir()
|
|
34
|
+
if not osp.isfile(path) and mod_src_dir is not None:
|
|
35
|
+
otherpath = osp.join(mod_src_dir, path)
|
|
36
|
+
if not osp.isfile(otherpath):
|
|
37
|
+
# TODO: [P3] For frozen app, go to error is implemented only when the
|
|
38
|
+
# source code is available locally (development mode).
|
|
39
|
+
# How about using a web browser to open the source code on github?
|
|
40
|
+
return
|
|
41
|
+
path = otherpath
|
|
42
|
+
if not osp.isfile(path):
|
|
43
|
+
return # File not found (unhandled case)
|
|
44
|
+
fdict = {"path": path, "line_number": line_number}
|
|
45
|
+
args = Conf.console.external_editor_args.get().format(**fdict).split(" ")
|
|
46
|
+
editor_path = Conf.console.external_editor_path.get()
|
|
47
|
+
subprocess.run([editor_path] + args, shell=True, check=False)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def insert_spaces(text: str, nbchars: int) -> str:
|
|
51
|
+
"""
|
|
52
|
+
Inserts spaces regularly in a string, every nbchars characters, after certain
|
|
53
|
+
characters (",", ";", "-", "+", "*", ")"), and keeps searching until detecting
|
|
54
|
+
one of those characters.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
text (str): The input string.
|
|
58
|
+
nbchars (int): The number of characters after which a space should be inserted.
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
str: The modified string with spaces inserted.
|
|
62
|
+
"""
|
|
63
|
+
special_chars = (",", ";", "-", "+", "*", ")", "_")
|
|
64
|
+
new_text = ""
|
|
65
|
+
index = 0
|
|
66
|
+
while index < len(text):
|
|
67
|
+
if (
|
|
68
|
+
index + nbchars < len(text)
|
|
69
|
+
and text[index + nbchars] not in special_chars
|
|
70
|
+
and not any(c in special_chars for c in text[index : index + nbchars + 1])
|
|
71
|
+
):
|
|
72
|
+
new_text += text[index : index + nbchars] # Append characters
|
|
73
|
+
index += nbchars
|
|
74
|
+
else:
|
|
75
|
+
new_text += text[index : index + nbchars] + " " # Insert space
|
|
76
|
+
index += nbchars
|
|
77
|
+
return new_text
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class WarningErrorMessageBox(QW.QDialog):
|
|
81
|
+
"""Warning/Error message box
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
parent (QW.QWidget): parent widget
|
|
85
|
+
category (str): message category ("error" or "warning")
|
|
86
|
+
context (str | None): context. Defaults to None.
|
|
87
|
+
message (str | None): message. Defaults to None.
|
|
88
|
+
tip (str | None): tip. Defaults to None.
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
def __init__(
|
|
92
|
+
self,
|
|
93
|
+
parent: QW.QWidget,
|
|
94
|
+
category: str,
|
|
95
|
+
context: str = None,
|
|
96
|
+
message: str = None,
|
|
97
|
+
tip: str = None,
|
|
98
|
+
) -> None:
|
|
99
|
+
super().__init__(parent)
|
|
100
|
+
assert category in ("error", "warning")
|
|
101
|
+
self.setWindowTitle(parent.window().objectName())
|
|
102
|
+
|
|
103
|
+
self.shell = PythonShellWidget(self, read_only=True)
|
|
104
|
+
self.shell.go_to_error.connect(go_to_error)
|
|
105
|
+
font = get_font(CONF, "console")
|
|
106
|
+
font.setPointSize(9)
|
|
107
|
+
self.shell.set_font(font)
|
|
108
|
+
message = traceback.format_exc() if message is None else message
|
|
109
|
+
self.shell.insert_text(message, at_end=True, error=True)
|
|
110
|
+
|
|
111
|
+
bbox = QW.QDialogButtonBox(QW.QDialogButtonBox.Ok)
|
|
112
|
+
bbox.accepted.connect(self.accept)
|
|
113
|
+
if category == "warning":
|
|
114
|
+
bbox.addButton(QW.QDialogButtonBox.Ignore).clicked.connect(self.ignore)
|
|
115
|
+
|
|
116
|
+
layout = QW.QVBoxLayout()
|
|
117
|
+
|
|
118
|
+
if category == "error":
|
|
119
|
+
width, height = 725, 400
|
|
120
|
+
icon = "MessageBoxCritical"
|
|
121
|
+
tb_title = _("Error message")
|
|
122
|
+
tb_text = _("The following traceback may help to understand the problem:")
|
|
123
|
+
else:
|
|
124
|
+
width, height = 725, 200
|
|
125
|
+
icon = "MessageBoxWarning"
|
|
126
|
+
tb_title = _("Warning message")
|
|
127
|
+
tb_text = _("Please take into account the following warning message:")
|
|
128
|
+
|
|
129
|
+
if context is not None:
|
|
130
|
+
context = insert_spaces(context, 80)
|
|
131
|
+
msgprefix = _("An error has occured during the following context:")
|
|
132
|
+
text = "<br>".join([msgprefix, f"<b>{context}</b>"])
|
|
133
|
+
ct_groupbox = QW.QGroupBox(_("Context"), self)
|
|
134
|
+
ct_layout = QW.QHBoxLayout()
|
|
135
|
+
ct_image_layout = QW.QVBoxLayout()
|
|
136
|
+
ct_image = QW.QLabel()
|
|
137
|
+
ct_image.setPixmap(get_std_icon(icon).pixmap(24, 24))
|
|
138
|
+
ct_image.setSizePolicy(QW.QSizePolicy.Fixed, QW.QSizePolicy.Fixed)
|
|
139
|
+
ct_image_layout.addWidget(ct_image)
|
|
140
|
+
ct_image_layout.addStretch()
|
|
141
|
+
ct_layout.addLayout(ct_image_layout)
|
|
142
|
+
ct_label = QW.QLabel(text)
|
|
143
|
+
ct_label.setWordWrap(True)
|
|
144
|
+
ct_label.setAlignment(QC.Qt.AlignLeft | QC.Qt.AlignTop)
|
|
145
|
+
ct_layout.addWidget(ct_label)
|
|
146
|
+
ct_groupbox.setLayout(ct_layout)
|
|
147
|
+
ct_groupbox.setSizePolicy(
|
|
148
|
+
QW.QSizePolicy.MinimumExpanding, QW.QSizePolicy.Fixed
|
|
149
|
+
)
|
|
150
|
+
layout.addWidget(ct_groupbox)
|
|
151
|
+
|
|
152
|
+
tb_groupbox = QW.QGroupBox(tb_title, self)
|
|
153
|
+
tb_layout = QW.QVBoxLayout()
|
|
154
|
+
tb_layout.addWidget(QW.QLabel(tb_text))
|
|
155
|
+
tb_layout.addWidget(self.shell)
|
|
156
|
+
tb_groupbox.setLayout(tb_layout)
|
|
157
|
+
layout.addWidget(tb_groupbox)
|
|
158
|
+
|
|
159
|
+
if tip is not None:
|
|
160
|
+
tip_groupbox = QW.QGroupBox(_("Tip"), self)
|
|
161
|
+
tip_layout = QW.QHBoxLayout()
|
|
162
|
+
tip_image_layout = QW.QVBoxLayout()
|
|
163
|
+
tip_image = QW.QLabel()
|
|
164
|
+
tip_image.setPixmap(get_std_icon("MessageBoxInformation").pixmap(24, 24))
|
|
165
|
+
tip_image.setSizePolicy(QW.QSizePolicy.Fixed, QW.QSizePolicy.Fixed)
|
|
166
|
+
tip_image_layout.addWidget(tip_image)
|
|
167
|
+
tip_image_layout.addStretch()
|
|
168
|
+
tip_layout.addLayout(tip_image_layout)
|
|
169
|
+
tip_label = QW.QLabel(tip)
|
|
170
|
+
tip_label.setWordWrap(True)
|
|
171
|
+
tip_label.setAlignment(QC.Qt.AlignLeft | QC.Qt.AlignTop)
|
|
172
|
+
tip_layout.addWidget(tip_label)
|
|
173
|
+
tip_groupbox.setLayout(tip_layout)
|
|
174
|
+
tip_groupbox.setSizePolicy(
|
|
175
|
+
QW.QSizePolicy.MinimumExpanding, QW.QSizePolicy.Fixed
|
|
176
|
+
)
|
|
177
|
+
layout.addWidget(tip_groupbox)
|
|
178
|
+
|
|
179
|
+
layout.addSpacing(10)
|
|
180
|
+
if category == "warning":
|
|
181
|
+
layout.addWidget(
|
|
182
|
+
QW.QLabel(
|
|
183
|
+
_(
|
|
184
|
+
"Please click on the 'Ignore' button to "
|
|
185
|
+
"ignore this warning next time."
|
|
186
|
+
)
|
|
187
|
+
)
|
|
188
|
+
)
|
|
189
|
+
layout.addSpacing(10)
|
|
190
|
+
|
|
191
|
+
layout.addWidget(bbox)
|
|
192
|
+
|
|
193
|
+
self.setLayout(layout)
|
|
194
|
+
self.resize(width, height)
|
|
195
|
+
|
|
196
|
+
bbox.button(QW.QDialogButtonBox.Ok).setFocus()
|
|
197
|
+
|
|
198
|
+
def ignore(self):
|
|
199
|
+
"""Ignore warning next time"""
|
|
200
|
+
Conf.proc.ignore_warnings.set(True)
|
|
201
|
+
self.accept()
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def show_warning_error(
|
|
205
|
+
parent: QW.QWidget,
|
|
206
|
+
category: str,
|
|
207
|
+
context: str = None,
|
|
208
|
+
message: str = None,
|
|
209
|
+
tip: str = None,
|
|
210
|
+
) -> None:
|
|
211
|
+
"""Show error message
|
|
212
|
+
|
|
213
|
+
Args:
|
|
214
|
+
parent (QW.QWidget): parent widget
|
|
215
|
+
category (str): message category ("error" or "warning")
|
|
216
|
+
context (str | None): context. Defaults to None.
|
|
217
|
+
message (str | None): message. Defaults to None.
|
|
218
|
+
tip (str | None): tip. Defaults to None.
|
|
219
|
+
"""
|
|
220
|
+
if category == "warning" and Conf.proc.ignore_warnings.get():
|
|
221
|
+
return
|
|
222
|
+
dlg = WarningErrorMessageBox(parent, category, context, message, tip)
|
|
223
|
+
exec_dialog(dlg)
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
DataLab Wizard Widget
|
|
5
|
+
---------------------
|
|
6
|
+
|
|
7
|
+
The DataLab Wizard is a widget that guides the user through a series of steps
|
|
8
|
+
to complete a task. It is implemented as a series of pages, each of which is
|
|
9
|
+
a separate widget.
|
|
10
|
+
|
|
11
|
+
The `Wizard` class is the main widget that contains the pages. The `WizardPage`
|
|
12
|
+
class is the base class for the pages.
|
|
13
|
+
|
|
14
|
+
This module is strongly inspired from Qt's `QWizard` and `QWizardPage` classes.
|
|
15
|
+
|
|
16
|
+
.. note::
|
|
17
|
+
|
|
18
|
+
The only motivation for reimplementing the wizard widget is to
|
|
19
|
+
support complete styling with `QPalette` and `QStyle` (e.g. `guidata`'s
|
|
20
|
+
dark mode is not supported on Windows).
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from __future__ import annotations
|
|
24
|
+
|
|
25
|
+
from qtpy import QtCore as QC
|
|
26
|
+
from qtpy import QtWidgets as QW
|
|
27
|
+
from qtpy.compat import getopenfilename
|
|
28
|
+
from qtpy.QtWidgets import QWidget
|
|
29
|
+
|
|
30
|
+
from datalab.config import _
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class WizardPage(QW.QWidget):
|
|
34
|
+
"""Wizard page base class
|
|
35
|
+
|
|
36
|
+
We create our own wizard page class instead of using QWizardPage because
|
|
37
|
+
the latter does not support complete styling with `QPalette` and `QStyle`
|
|
38
|
+
(e.g. `guidata`'s dark mode is not supported on Windows).
|
|
39
|
+
|
|
40
|
+
This class reimplements the `QWizardPage` features.
|
|
41
|
+
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
SIG_INITIALIZE_PAGE = QC.Signal()
|
|
45
|
+
SIG_VALID_STATE_CHANGED = QC.Signal()
|
|
46
|
+
|
|
47
|
+
def __init__(self, parent: QW.QWidget | None = None) -> None:
|
|
48
|
+
super().__init__(parent)
|
|
49
|
+
self.__is_valid: bool = True
|
|
50
|
+
self.wizard: Wizard | None = None
|
|
51
|
+
self._main_layout = QW.QVBoxLayout()
|
|
52
|
+
self._user_layout = QW.QVBoxLayout()
|
|
53
|
+
self._title_label = QW.QLabel("")
|
|
54
|
+
font = self._title_label.font()
|
|
55
|
+
font.setPointSize(font.pointSize() + 4)
|
|
56
|
+
font.setBold(True)
|
|
57
|
+
self._title_label.setFont(font)
|
|
58
|
+
self._title_label.setStyleSheet("color: #1E90FF")
|
|
59
|
+
horiz_line = QW.QFrame()
|
|
60
|
+
horiz_line.setFrameShape(QW.QFrame.HLine)
|
|
61
|
+
horiz_line.setFrameShadow(QW.QFrame.Sunken)
|
|
62
|
+
self._subtitle_label = QW.QLabel("")
|
|
63
|
+
self._main_layout.addWidget(self._title_label)
|
|
64
|
+
self._main_layout.addWidget(self._subtitle_label)
|
|
65
|
+
self._main_layout.addWidget(horiz_line)
|
|
66
|
+
self._main_layout.addLayout(self._user_layout)
|
|
67
|
+
self.setLayout(self._main_layout)
|
|
68
|
+
|
|
69
|
+
def set_wizard(self, wizard: Wizard) -> None:
|
|
70
|
+
"""Set the wizard"""
|
|
71
|
+
self.wizard = wizard
|
|
72
|
+
|
|
73
|
+
def get_wizard(self) -> Wizard:
|
|
74
|
+
"""Return the wizard"""
|
|
75
|
+
return self.wizard
|
|
76
|
+
|
|
77
|
+
def set_title(self, title: str) -> None:
|
|
78
|
+
"""Set the title of the page"""
|
|
79
|
+
self._title_label.setText(title)
|
|
80
|
+
|
|
81
|
+
def set_subtitle(self, subtitle: str) -> None:
|
|
82
|
+
"""Set the subtitle of the page"""
|
|
83
|
+
self._subtitle_label.setText(subtitle)
|
|
84
|
+
|
|
85
|
+
def set_valid(self, is_valid: bool) -> None:
|
|
86
|
+
"""Set the page as valid"""
|
|
87
|
+
self.__is_valid = is_valid
|
|
88
|
+
self.SIG_VALID_STATE_CHANGED.emit()
|
|
89
|
+
|
|
90
|
+
def is_valid(self) -> bool:
|
|
91
|
+
"""Return whether the page is valid"""
|
|
92
|
+
return self.__is_valid
|
|
93
|
+
|
|
94
|
+
def add_to_layout(self, layout: QW.QLayout | QW.QWidget) -> None:
|
|
95
|
+
"""Add a layout to the user layout"""
|
|
96
|
+
if isinstance(layout, QW.QWidget):
|
|
97
|
+
self._user_layout.addWidget(layout)
|
|
98
|
+
else:
|
|
99
|
+
self._user_layout.addLayout(layout)
|
|
100
|
+
|
|
101
|
+
def add_stretch(self) -> None:
|
|
102
|
+
"""Add a stretch to the user layout"""
|
|
103
|
+
self._user_layout.addStretch()
|
|
104
|
+
|
|
105
|
+
def initialize_page(self) -> None:
|
|
106
|
+
"""Initialize the page"""
|
|
107
|
+
self.SIG_INITIALIZE_PAGE.emit()
|
|
108
|
+
|
|
109
|
+
def validate_page(self) -> bool:
|
|
110
|
+
"""Validate the page"""
|
|
111
|
+
return self.is_valid()
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
class Wizard(QW.QDialog):
|
|
115
|
+
"""Wizard base class"""
|
|
116
|
+
|
|
117
|
+
def __init__(self, parent: QWidget | None = None) -> None:
|
|
118
|
+
super().__init__(parent)
|
|
119
|
+
|
|
120
|
+
_main_layout = QW.QVBoxLayout()
|
|
121
|
+
self.setLayout(_main_layout)
|
|
122
|
+
|
|
123
|
+
self._pages_widget = QW.QStackedWidget()
|
|
124
|
+
_main_layout.addWidget(self._pages_widget)
|
|
125
|
+
|
|
126
|
+
btn_layout = QW.QHBoxLayout()
|
|
127
|
+
self._back_btn = QW.QPushButton(_("Back"))
|
|
128
|
+
self._back_btn.clicked.connect(self.go_to_previous_page)
|
|
129
|
+
self._next_btn = QW.QPushButton(_("Next"))
|
|
130
|
+
self._next_btn.clicked.connect(self.go_to_next_page)
|
|
131
|
+
self._finish_btn = QW.QPushButton(_("Finish"))
|
|
132
|
+
self._finish_btn.clicked.connect(self.accept)
|
|
133
|
+
self._cancel_btn = QW.QPushButton(_("Cancel"))
|
|
134
|
+
self._cancel_btn.clicked.connect(self.reject)
|
|
135
|
+
btn_layout.addWidget(self._back_btn)
|
|
136
|
+
btn_layout.addWidget(self._next_btn)
|
|
137
|
+
btn_layout.addWidget(self._finish_btn)
|
|
138
|
+
btn_layout.addWidget(self._cancel_btn)
|
|
139
|
+
_main_layout.addLayout(btn_layout)
|
|
140
|
+
|
|
141
|
+
self.setSizePolicy(
|
|
142
|
+
QW.QSizePolicy(QW.QSizePolicy.Minimum, QW.QSizePolicy.Minimum)
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
def add_page(self, page: WizardPage, last_page: bool = False) -> None:
|
|
146
|
+
"""Add a page to the wizard"""
|
|
147
|
+
page.set_wizard(self)
|
|
148
|
+
page.SIG_INITIALIZE_PAGE.connect(self.__update_button_states)
|
|
149
|
+
page.SIG_VALID_STATE_CHANGED.connect(self.__update_button_states)
|
|
150
|
+
self._pages_widget.addWidget(page)
|
|
151
|
+
if last_page:
|
|
152
|
+
self._pages_widget.widget(0).initialize_page()
|
|
153
|
+
|
|
154
|
+
def __update_button_states(self, index: int | None = None) -> None:
|
|
155
|
+
"""Update button states"""
|
|
156
|
+
if index is None:
|
|
157
|
+
index = self._pages_widget.currentIndex()
|
|
158
|
+
self._back_btn.setEnabled(index > 0)
|
|
159
|
+
not_last_page = index < self._pages_widget.count() - 1
|
|
160
|
+
page_valid = self._pages_widget.currentWidget().is_valid()
|
|
161
|
+
self._next_btn.setEnabled(not_last_page and page_valid)
|
|
162
|
+
is_last_page = index == self._pages_widget.count() - 1
|
|
163
|
+
self._finish_btn.setEnabled(is_last_page and page_valid)
|
|
164
|
+
|
|
165
|
+
def go_to_previous_page(self) -> None:
|
|
166
|
+
"""Go to the previous page"""
|
|
167
|
+
self._pages_widget.setCurrentIndex(self._pages_widget.currentIndex() - 1)
|
|
168
|
+
self.__update_button_states()
|
|
169
|
+
|
|
170
|
+
def go_to_next_page(self) -> None:
|
|
171
|
+
"""Go to the next page"""
|
|
172
|
+
if self.validate_page():
|
|
173
|
+
self._pages_widget.setCurrentIndex(self._pages_widget.currentIndex() + 1)
|
|
174
|
+
self.initialize_page()
|
|
175
|
+
|
|
176
|
+
def initialize_page(self) -> None:
|
|
177
|
+
"""Initialize the page"""
|
|
178
|
+
self._pages_widget.currentWidget().initialize_page()
|
|
179
|
+
|
|
180
|
+
def validate_page(self) -> bool:
|
|
181
|
+
"""Validate the page"""
|
|
182
|
+
return self._pages_widget.currentWidget().validate_page()
|
|
183
|
+
|
|
184
|
+
def accept(self) -> None:
|
|
185
|
+
"""Accept the wizard"""
|
|
186
|
+
if self.validate_page():
|
|
187
|
+
super().accept()
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
class ExamplePage1(WizardPage):
|
|
191
|
+
"""Example wizard page 1"""
|
|
192
|
+
|
|
193
|
+
def __init__(self) -> None:
|
|
194
|
+
super().__init__()
|
|
195
|
+
self.set_title(_("Welcome to the Example Wizard"))
|
|
196
|
+
self.set_subtitle(
|
|
197
|
+
_("This wizard will guide you through the process of importing data.")
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
def initialize_page(self) -> None:
|
|
201
|
+
"""Initialize the page"""
|
|
202
|
+
print("ExamplePage1 initialized")
|
|
203
|
+
super().initialize_page()
|
|
204
|
+
|
|
205
|
+
def validate_page(self) -> bool:
|
|
206
|
+
"""Validate the page"""
|
|
207
|
+
print("ExamplePage1 validated")
|
|
208
|
+
return super().validate_page()
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
class ExamplePage2(WizardPage):
|
|
212
|
+
"""Example wizard page 2"""
|
|
213
|
+
|
|
214
|
+
def __init__(self) -> None:
|
|
215
|
+
super().__init__()
|
|
216
|
+
self.set_title(_("Select the Source of the Data"))
|
|
217
|
+
self.set_subtitle(
|
|
218
|
+
_("Select the source of the data to be imported (clipboard or file).")
|
|
219
|
+
)
|
|
220
|
+
self._clipboard_rb = QW.QRadioButton(_("Clipboard"))
|
|
221
|
+
self._file_rb = QW.QRadioButton(_("File"))
|
|
222
|
+
self._file_rb.toggled.connect(self.file_rb_toggled)
|
|
223
|
+
self._file_le = QW.QLineEdit()
|
|
224
|
+
self._file_btn = QW.QPushButton(_("Browse..."))
|
|
225
|
+
self._file_btn.clicked.connect(self.browse_file)
|
|
226
|
+
self.add_to_layout(self._clipboard_rb)
|
|
227
|
+
self.add_to_layout(self._file_rb)
|
|
228
|
+
self.add_to_layout(self._file_le)
|
|
229
|
+
self.add_to_layout(self._file_btn)
|
|
230
|
+
|
|
231
|
+
def initialize_page(self) -> None:
|
|
232
|
+
"""Initialize the page"""
|
|
233
|
+
print("ExamplePage2 initialized")
|
|
234
|
+
super().initialize_page()
|
|
235
|
+
|
|
236
|
+
def file_rb_toggled(self, checked: bool) -> None:
|
|
237
|
+
"""File radio button toggled"""
|
|
238
|
+
self._file_le.setEnabled(checked)
|
|
239
|
+
self._file_btn.setEnabled(checked)
|
|
240
|
+
|
|
241
|
+
def browse_file(self) -> None:
|
|
242
|
+
"""Browse file"""
|
|
243
|
+
file_name, _filt = getopenfilename(
|
|
244
|
+
self,
|
|
245
|
+
_("Select the File to Import"),
|
|
246
|
+
"",
|
|
247
|
+
_("CSV Files (*.csv);;Text Files (*.txt);;All Files (*)"),
|
|
248
|
+
)
|
|
249
|
+
if file_name:
|
|
250
|
+
self._file_le.setText(file_name)
|
|
251
|
+
|
|
252
|
+
def validate_page(self) -> bool:
|
|
253
|
+
"""Validate the page"""
|
|
254
|
+
if self._file_rb.isChecked() and not self._file_le.text():
|
|
255
|
+
QW.QMessageBox.critical(
|
|
256
|
+
self,
|
|
257
|
+
_("Error"),
|
|
258
|
+
_("Please select the file to import."),
|
|
259
|
+
QW.QMessageBox.Ok,
|
|
260
|
+
)
|
|
261
|
+
return False
|
|
262
|
+
return True
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
class ExampleWizard(Wizard):
|
|
266
|
+
"""Example wizard widget"""
|
|
267
|
+
|
|
268
|
+
def __init__(self) -> None:
|
|
269
|
+
super().__init__()
|
|
270
|
+
self.setWindowTitle(_("Example Wizard"))
|
|
271
|
+
self.add_page(ExamplePage1())
|
|
272
|
+
self.add_page(ExamplePage2(), last_page=True)
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
def test_example_wizard():
|
|
276
|
+
"""Test the import wizard"""
|
|
277
|
+
# pylint: disable=import-outside-toplevel
|
|
278
|
+
from guidata.qthelpers import qt_app_context
|
|
279
|
+
|
|
280
|
+
with qt_app_context():
|
|
281
|
+
wizard = ExampleWizard()
|
|
282
|
+
wizard.exec()
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
if __name__ == "__main__":
|
|
286
|
+
test_example_wizard()
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: datalab-platform
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: DataLab is a data processing and analysis software for scientific and industrial applications
|
|
5
|
+
Author-email: Pierre Raybaut <p.raybaut@codra.fr>
|
|
6
|
+
Maintainer-email: DataLab Platform Developers <p.raybaut@codra.fr>
|
|
7
|
+
License-Expression: BSD-3-Clause
|
|
8
|
+
Project-URL: Homepage, https://datalab-platform.com/
|
|
9
|
+
Project-URL: Documentation, https://datalab-platform.com/
|
|
10
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Intended Audience :: Education
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
15
|
+
Classifier: Operating System :: MacOS :: MacOS X
|
|
16
|
+
Classifier: Operating System :: Microsoft :: Windows :: Windows 7
|
|
17
|
+
Classifier: Operating System :: Microsoft :: Windows :: Windows 8
|
|
18
|
+
Classifier: Operating System :: Microsoft :: Windows :: Windows 10
|
|
19
|
+
Classifier: Operating System :: Microsoft :: Windows :: Windows 11
|
|
20
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
26
|
+
Classifier: Topic :: Scientific/Engineering
|
|
27
|
+
Classifier: Topic :: Scientific/Engineering :: Image Processing
|
|
28
|
+
Classifier: Topic :: Scientific/Engineering :: Human Machine Interfaces
|
|
29
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
30
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
31
|
+
Classifier: Topic :: Software Development :: Widget Sets
|
|
32
|
+
Requires-Python: <4,>=3.9
|
|
33
|
+
Description-Content-Type: text/markdown
|
|
34
|
+
License-File: LICENSE
|
|
35
|
+
Requires-Dist: guidata>=3.13.3
|
|
36
|
+
Requires-Dist: PlotPy>=2.8.2
|
|
37
|
+
Requires-Dist: Sigima>=1.0.2
|
|
38
|
+
Requires-Dist: NumPy>=1.22
|
|
39
|
+
Requires-Dist: SciPy>=1.10.1
|
|
40
|
+
Requires-Dist: scikit-image>=0.19.2
|
|
41
|
+
Requires-Dist: pandas>=1.4
|
|
42
|
+
Requires-Dist: PyWavelets>=1.2
|
|
43
|
+
Requires-Dist: psutil>=5.8
|
|
44
|
+
Requires-Dist: packaging>=21.3
|
|
45
|
+
Provides-Extra: qt
|
|
46
|
+
Requires-Dist: PyQt5>=5.15.6; extra == "qt"
|
|
47
|
+
Provides-Extra: opencv
|
|
48
|
+
Requires-Dist: opencv-python-headless>=4.8.1.78; extra == "opencv"
|
|
49
|
+
Provides-Extra: exe
|
|
50
|
+
Requires-Dist: pyinstaller==6.16.0; extra == "exe"
|
|
51
|
+
Requires-Dist: opencv-python-headless>=4.8.1.78; extra == "exe"
|
|
52
|
+
Requires-Dist: PyQt5>=5.15.6; extra == "exe"
|
|
53
|
+
Provides-Extra: dev
|
|
54
|
+
Requires-Dist: build; extra == "dev"
|
|
55
|
+
Requires-Dist: babel; extra == "dev"
|
|
56
|
+
Requires-Dist: Coverage; extra == "dev"
|
|
57
|
+
Requires-Dist: pylint; extra == "dev"
|
|
58
|
+
Requires-Dist: ruff; extra == "dev"
|
|
59
|
+
Requires-Dist: pre-commit; extra == "dev"
|
|
60
|
+
Provides-Extra: doc
|
|
61
|
+
Requires-Dist: sphinx; extra == "doc"
|
|
62
|
+
Requires-Dist: sphinx_intl; extra == "doc"
|
|
63
|
+
Requires-Dist: sphinx-sitemap; extra == "doc"
|
|
64
|
+
Requires-Dist: myst_parser; extra == "doc"
|
|
65
|
+
Requires-Dist: sphinx_design; extra == "doc"
|
|
66
|
+
Requires-Dist: sphinx-copybutton; extra == "doc"
|
|
67
|
+
Requires-Dist: pydata-sphinx-theme; extra == "doc"
|
|
68
|
+
Provides-Extra: test
|
|
69
|
+
Requires-Dist: pytest; extra == "test"
|
|
70
|
+
Requires-Dist: pytest-xvfb; extra == "test"
|
|
71
|
+
Dynamic: license-file
|
|
72
|
+
|
|
73
|
+

|
|
74
|
+
|
|
75
|
+
[](./LICENSE)
|
|
76
|
+
[](https://pypi.org/project/datalab-platform/)
|
|
77
|
+
[](https://github.com/DataLab-Platform/DataLab)
|
|
78
|
+
[](https://pypi.python.org/pypi/datalab-platform/)
|
|
79
|
+
|
|
80
|
+
DataLab is an **open-source platform for scientific and technical data processing
|
|
81
|
+
and visualization** with unique features designed to meet industrial requirements.
|
|
82
|
+
|
|
83
|
+
See [DataLab website](https://datalab-platform.com/) for more details.
|
|
84
|
+
|
|
85
|
+
> **Note:** This project (DataLab Platform) should not be confused with the [datalab-org](https://datalab-org.io/) project, which is a separate and unrelated initiative focused on materials science databases and computational tools.
|
|
86
|
+
|
|
87
|
+
ℹ️ Created by [CODRA](https://codra.net/)/[Pierre Raybaut](https://github.com/PierreRaybaut) in 2023, developed and maintained by DataLab Platform Developers.
|
|
88
|
+
|
|
89
|
+

|
|
90
|
+
|
|
91
|
+
🧮 DataLab's processing power comes from the advanced algorithms of the object-oriented signal and image processing library [Sigima](https://github.com/DataLab-Platform/Sigima) 🚀 which is part of the DataLab Platform.
|
|
92
|
+
|
|
93
|
+

|
|
94
|
+
|
|
95
|
+
ℹ️ DataLab is powered by [PlotPyStack](https://github.com/PlotPyStack) 🚀 for curve plotting and fast image visualization.
|
|
96
|
+
|
|
97
|
+

|
|
98
|
+
|
|
99
|
+
ℹ️ DataLab is built on Python and scientific libraries.
|
|
100
|
+
|
|
101
|
+
      
|
|
102
|
+
|
|
103
|
+
----
|
|
104
|
+
|
|
105
|
+
Try DataLab online, without installing anything, using Binder:
|
|
106
|
+
|
|
107
|
+
[](https://mybinder.org/v2/gh/DataLab-Platform/DataLab/binder-environments?urlpath=git-pull%3Frepo%3Dhttps%253A%252F%252Fgithub.com%252FDataLab-Platform%252FDataLab%26urlpath%3Ddesktop%252F%26branch%3Dbinder-environments)
|
|
108
|
+
|
|
109
|
+
----
|
|
110
|
+
|
|
111
|
+
✨ Add features to DataLab by writing your own [plugin](https://datalab-platform.com/en/features/general/plugins.html)
|
|
112
|
+
(see [plugin examples](https://github.com/DataLab-Platform/DataLab/tree/main/plugins/examples))
|
|
113
|
+
or macro (see [macro examples](https://github.com/DataLab-Platform/DataLab/tree/main/macros/examples))
|
|
114
|
+
|
|
115
|
+
✨ DataLab may be remotely controlled from a third-party application (such as Jupyter,
|
|
116
|
+
Spyder or any IDE):
|
|
117
|
+
|
|
118
|
+
* Using the integrated [remote control](https://datalab-platform.com/en/features/advanced/remote.html)
|
|
119
|
+
feature (this requires to install DataLab as a Python package)
|
|
120
|
+
|
|
121
|
+
* Using the lightweight client integrated in [Sigima](https://github.com/DataLab-Platform/Sigima) (`pip install sigima`)
|