datalab-platform 0.0.1.dev0__py3-none-any.whl → 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- datalab/__init__.py +35 -2
- datalab/adapters_metadata/__init__.py +31 -0
- datalab/adapters_metadata/base_adapter.py +316 -0
- datalab/adapters_metadata/common.py +422 -0
- datalab/adapters_metadata/geometry_adapter.py +98 -0
- datalab/adapters_metadata/table_adapter.py +84 -0
- datalab/adapters_plotpy/__init__.py +54 -0
- datalab/adapters_plotpy/annotations.py +124 -0
- datalab/adapters_plotpy/base.py +110 -0
- datalab/adapters_plotpy/converters.py +86 -0
- datalab/adapters_plotpy/factories.py +80 -0
- datalab/adapters_plotpy/objects/__init__.py +0 -0
- datalab/adapters_plotpy/objects/base.py +197 -0
- datalab/adapters_plotpy/objects/image.py +157 -0
- datalab/adapters_plotpy/objects/scalar.py +565 -0
- datalab/adapters_plotpy/objects/signal.py +264 -0
- datalab/adapters_plotpy/roi/__init__.py +0 -0
- datalab/adapters_plotpy/roi/base.py +146 -0
- datalab/adapters_plotpy/roi/factory.py +93 -0
- datalab/adapters_plotpy/roi/image.py +207 -0
- datalab/adapters_plotpy/roi/signal.py +72 -0
- datalab/app.py +98 -0
- datalab/config.py +817 -0
- datalab/control/__init__.py +0 -0
- datalab/control/baseproxy.py +776 -0
- datalab/control/proxy.py +343 -0
- datalab/control/remote.py +1005 -0
- datalab/data/doc/DataLab_en.pdf +0 -0
- datalab/data/doc/DataLab_fr.pdf +0 -0
- datalab/data/icons/analysis/delete_results.svg +109 -0
- datalab/data/icons/analysis/fw1e2.svg +156 -0
- datalab/data/icons/analysis/fwhm.svg +156 -0
- datalab/data/icons/analysis/histogram.svg +49 -0
- datalab/data/icons/analysis/peak_detect.svg +160 -0
- datalab/data/icons/analysis/plot_results.svg +151 -0
- datalab/data/icons/analysis/show_results.svg +83 -0
- datalab/data/icons/analysis/stats.svg +49 -0
- datalab/data/icons/analysis.svg +120 -0
- datalab/data/icons/apply.svg +3 -0
- datalab/data/icons/check_all.svg +15 -0
- datalab/data/icons/collapse.svg +44 -0
- datalab/data/icons/collapse_selection.svg +63 -0
- datalab/data/icons/console.svg +101 -0
- datalab/data/icons/create/1d-normal.svg +8 -0
- datalab/data/icons/create/1d-poisson.svg +9 -0
- datalab/data/icons/create/1d-uniform.svg +8 -0
- datalab/data/icons/create/1d-zero.svg +57 -0
- datalab/data/icons/create/2d-gaussian.svg +56 -0
- datalab/data/icons/create/2d-normal.svg +38 -0
- datalab/data/icons/create/2d-poisson.svg +38 -0
- datalab/data/icons/create/2d-ramp.svg +90 -0
- datalab/data/icons/create/2d-sinc.svg +62 -0
- datalab/data/icons/create/2d-uniform.svg +38 -0
- datalab/data/icons/create/2d-zero.svg +13 -0
- datalab/data/icons/create/checkerboard.svg +39 -0
- datalab/data/icons/create/cosine.svg +12 -0
- datalab/data/icons/create/exponential.svg +55 -0
- datalab/data/icons/create/gaussian.svg +12 -0
- datalab/data/icons/create/grating.svg +29 -0
- datalab/data/icons/create/linear_chirp.svg +7 -0
- datalab/data/icons/create/logistic.svg +7 -0
- datalab/data/icons/create/lorentzian.svg +12 -0
- datalab/data/icons/create/planck.svg +12 -0
- datalab/data/icons/create/polynomial.svg +7 -0
- datalab/data/icons/create/pulse.svg +12 -0
- datalab/data/icons/create/ring.svg +18 -0
- datalab/data/icons/create/sawtooth.svg +7 -0
- datalab/data/icons/create/siemens.svg +35 -0
- datalab/data/icons/create/sinc.svg +12 -0
- datalab/data/icons/create/sine.svg +7 -0
- datalab/data/icons/create/square.svg +7 -0
- datalab/data/icons/create/square_pulse.svg +7 -0
- datalab/data/icons/create/step.svg +7 -0
- datalab/data/icons/create/step_pulse.svg +12 -0
- datalab/data/icons/create/triangle.svg +7 -0
- datalab/data/icons/create/voigt.svg +12 -0
- datalab/data/icons/edit/annotations.svg +72 -0
- datalab/data/icons/edit/annotations_copy.svg +114 -0
- datalab/data/icons/edit/annotations_delete.svg +83 -0
- datalab/data/icons/edit/annotations_edit.svg +98 -0
- datalab/data/icons/edit/annotations_export.svg +85 -0
- datalab/data/icons/edit/annotations_import.svg +85 -0
- datalab/data/icons/edit/annotations_paste.svg +100 -0
- datalab/data/icons/edit/copy_titles.svg +109 -0
- datalab/data/icons/edit/delete.svg +84 -0
- datalab/data/icons/edit/delete_all.svg +214 -0
- datalab/data/icons/edit/duplicate.svg +64 -0
- datalab/data/icons/edit/goto_source.svg +60 -0
- datalab/data/icons/edit/metadata.svg +60 -0
- datalab/data/icons/edit/metadata_add.svg +80 -0
- datalab/data/icons/edit/metadata_copy.svg +96 -0
- datalab/data/icons/edit/metadata_delete.svg +62 -0
- datalab/data/icons/edit/metadata_export.svg +68 -0
- datalab/data/icons/edit/metadata_import.svg +68 -0
- datalab/data/icons/edit/metadata_paste.svg +79 -0
- datalab/data/icons/edit/move_down.svg +55 -0
- datalab/data/icons/edit/move_up.svg +54 -0
- datalab/data/icons/edit/new_group.svg +76 -0
- datalab/data/icons/edit/recompute.svg +60 -0
- datalab/data/icons/edit/rename.svg +49 -0
- datalab/data/icons/edit.svg +16 -0
- datalab/data/icons/expand.svg +44 -0
- datalab/data/icons/expand_selection.svg +63 -0
- datalab/data/icons/fit/cdf_fit.svg +56 -0
- datalab/data/icons/fit/exponential_fit.svg +55 -0
- datalab/data/icons/fit/gaussian_fit.svg +62 -0
- datalab/data/icons/fit/interactive_fit.svg +101 -0
- datalab/data/icons/fit/linear_fit.svg +57 -0
- datalab/data/icons/fit/lorentzian_fit.svg +209 -0
- datalab/data/icons/fit/multigaussian_fit.svg +85 -0
- datalab/data/icons/fit/multilorentzian_fit.svg +85 -0
- datalab/data/icons/fit/piecewiseexponential_fit.svg +209 -0
- datalab/data/icons/fit/planckian_fit.svg +62 -0
- datalab/data/icons/fit/polynomial_fit.svg +59 -0
- datalab/data/icons/fit/sigmoid_fit.svg +56 -0
- datalab/data/icons/fit/sinusoidal_fit.svg +72 -0
- datalab/data/icons/fit/twohalfgaussian_fit.svg +63 -0
- datalab/data/icons/fit/voigt_fit.svg +57 -0
- datalab/data/icons/group.svg +56 -0
- datalab/data/icons/h5/h5array.svg +59 -0
- datalab/data/icons/h5/h5attrs.svg +75 -0
- datalab/data/icons/h5/h5browser.svg +133 -0
- datalab/data/icons/h5/h5file.svg +69 -0
- datalab/data/icons/h5/h5group.svg +49 -0
- datalab/data/icons/h5/h5scalar.svg +1 -0
- datalab/data/icons/help_pdf.svg +46 -0
- datalab/data/icons/history.svg +7 -0
- datalab/data/icons/image.svg +135 -0
- datalab/data/icons/io/fileopen_directory.svg +60 -0
- datalab/data/icons/io/fileopen_h5.svg +84 -0
- datalab/data/icons/io/fileopen_ima.svg +187 -0
- datalab/data/icons/io/fileopen_py.svg +123 -0
- datalab/data/icons/io/fileopen_sig.svg +138 -0
- datalab/data/icons/io/filesave_h5.svg +97 -0
- datalab/data/icons/io/filesave_ima.svg +200 -0
- datalab/data/icons/io/filesave_py.svg +136 -0
- datalab/data/icons/io/filesave_sig.svg +151 -0
- datalab/data/icons/io/import_text.svg +144 -0
- datalab/data/icons/io/save_to_directory.svg +134 -0
- datalab/data/icons/io.svg +84 -0
- datalab/data/icons/libre-camera-flash-off.svg +1 -0
- datalab/data/icons/libre-camera-flash-on.svg +1 -0
- datalab/data/icons/libre-gui-about.svg +1 -0
- datalab/data/icons/libre-gui-action-delete.svg +1 -0
- datalab/data/icons/libre-gui-add.svg +1 -0
- datalab/data/icons/libre-gui-arrow-down.svg +1 -0
- datalab/data/icons/libre-gui-arrow-left.svg +1 -0
- datalab/data/icons/libre-gui-arrow-right.svg +1 -0
- datalab/data/icons/libre-gui-arrow-up.svg +1 -0
- datalab/data/icons/libre-gui-close.svg +40 -0
- datalab/data/icons/libre-gui-cogs.svg +1 -0
- datalab/data/icons/libre-gui-globe.svg +1 -0
- datalab/data/icons/libre-gui-help.svg +1 -0
- datalab/data/icons/libre-gui-link.svg +1 -0
- datalab/data/icons/libre-gui-menu.svg +1 -0
- datalab/data/icons/libre-gui-pencil.svg +1 -0
- datalab/data/icons/libre-gui-plugin.svg +1 -0
- datalab/data/icons/libre-gui-questions.svg +1 -0
- datalab/data/icons/libre-gui-settings.svg +1 -0
- datalab/data/icons/libre-gui-unlink.svg +1 -0
- datalab/data/icons/libre-tech-ram.svg +1 -0
- datalab/data/icons/libre-toolbox.svg +1 -0
- datalab/data/icons/logs.svg +1 -0
- datalab/data/icons/markers.svg +74 -0
- datalab/data/icons/menu.svg +13 -0
- datalab/data/icons/new_ima.svg +148 -0
- datalab/data/icons/new_sig.svg +123 -0
- datalab/data/icons/operations/abs.svg +116 -0
- datalab/data/icons/operations/arithmetic.svg +123 -0
- datalab/data/icons/operations/average.svg +124 -0
- datalab/data/icons/operations/complex_from_magnitude_phase.svg +116 -0
- datalab/data/icons/operations/complex_from_real_imag.svg +124 -0
- datalab/data/icons/operations/constant.svg +116 -0
- datalab/data/icons/operations/constant_add.svg +109 -0
- datalab/data/icons/operations/constant_divide.svg +109 -0
- datalab/data/icons/operations/constant_multiply.svg +109 -0
- datalab/data/icons/operations/constant_subtract.svg +109 -0
- datalab/data/icons/operations/convert_dtype.svg +117 -0
- datalab/data/icons/operations/convolution.svg +46 -0
- datalab/data/icons/operations/deconvolution.svg +57 -0
- datalab/data/icons/operations/derivative.svg +127 -0
- datalab/data/icons/operations/difference.svg +52 -0
- datalab/data/icons/operations/division.svg +139 -0
- datalab/data/icons/operations/exp.svg +116 -0
- datalab/data/icons/operations/flip_horizontally.svg +69 -0
- datalab/data/icons/operations/flip_vertically.svg +74 -0
- datalab/data/icons/operations/im.svg +124 -0
- datalab/data/icons/operations/integral.svg +50 -0
- datalab/data/icons/operations/inverse.svg +143 -0
- datalab/data/icons/operations/log10.svg +109 -0
- datalab/data/icons/operations/phase.svg +116 -0
- datalab/data/icons/operations/power.svg +118 -0
- datalab/data/icons/operations/product.svg +124 -0
- datalab/data/icons/operations/profile.svg +379 -0
- datalab/data/icons/operations/profile_average.svg +399 -0
- datalab/data/icons/operations/profile_radial.svg +261 -0
- datalab/data/icons/operations/profile_segment.svg +262 -0
- datalab/data/icons/operations/quadratic_difference.svg +84 -0
- datalab/data/icons/operations/re.svg +124 -0
- datalab/data/icons/operations/rotate_left.svg +72 -0
- datalab/data/icons/operations/rotate_right.svg +72 -0
- datalab/data/icons/operations/signals_to_image.svg +314 -0
- datalab/data/icons/operations/sqrt.svg +110 -0
- datalab/data/icons/operations/std.svg +124 -0
- datalab/data/icons/operations/sum.svg +102 -0
- datalab/data/icons/play_demo.svg +9 -0
- datalab/data/icons/processing/axis_transform.svg +62 -0
- datalab/data/icons/processing/bandpass.svg +79 -0
- datalab/data/icons/processing/bandstop.svg +71 -0
- datalab/data/icons/processing/binning.svg +126 -0
- datalab/data/icons/processing/clip.svg +119 -0
- datalab/data/icons/processing/detrending.svg +173 -0
- datalab/data/icons/processing/distribute_on_grid.svg +769 -0
- datalab/data/icons/processing/edge_detection.svg +46 -0
- datalab/data/icons/processing/erase.svg +1 -0
- datalab/data/icons/processing/exposure.svg +143 -0
- datalab/data/icons/processing/fourier.svg +104 -0
- datalab/data/icons/processing/highpass.svg +59 -0
- datalab/data/icons/processing/interpolation.svg +71 -0
- datalab/data/icons/processing/level_adjustment.svg +70 -0
- datalab/data/icons/processing/lowpass.svg +60 -0
- datalab/data/icons/processing/morphology.svg +49 -0
- datalab/data/icons/processing/noise_addition.svg +114 -0
- datalab/data/icons/processing/noise_reduction.svg +38 -0
- datalab/data/icons/processing/normalize.svg +84 -0
- datalab/data/icons/processing/offset_correction.svg +131 -0
- datalab/data/icons/processing/resampling1d.svg +101 -0
- datalab/data/icons/processing/resampling2d.svg +240 -0
- datalab/data/icons/processing/reset_positions.svg +185 -0
- datalab/data/icons/processing/resize.svg +9 -0
- datalab/data/icons/processing/reverse_signal_x.svg +171 -0
- datalab/data/icons/processing/stability.svg +11 -0
- datalab/data/icons/processing/swap_x_y.svg +65 -0
- datalab/data/icons/processing/thresholding.svg +63 -0
- datalab/data/icons/processing/windowing.svg +45 -0
- datalab/data/icons/properties.svg +26 -0
- datalab/data/icons/reset.svg +9 -0
- datalab/data/icons/restore.svg +40 -0
- datalab/data/icons/roi/roi.svg +76 -0
- datalab/data/icons/roi/roi_coordinate.svg +78 -0
- datalab/data/icons/roi/roi_copy.svg +112 -0
- datalab/data/icons/roi/roi_delete.svg +81 -0
- datalab/data/icons/roi/roi_export.svg +87 -0
- datalab/data/icons/roi/roi_graphical.svg +78 -0
- datalab/data/icons/roi/roi_grid.svg +67 -0
- datalab/data/icons/roi/roi_ima.svg +188 -0
- datalab/data/icons/roi/roi_import.svg +87 -0
- datalab/data/icons/roi/roi_new.svg +81 -0
- datalab/data/icons/roi/roi_new_circle.svg +95 -0
- datalab/data/icons/roi/roi_new_polygon.svg +110 -0
- datalab/data/icons/roi/roi_new_rectangle.svg +70 -0
- datalab/data/icons/roi/roi_paste.svg +98 -0
- datalab/data/icons/roi/roi_sig.svg +124 -0
- datalab/data/icons/shapes.svg +134 -0
- datalab/data/icons/signal.svg +103 -0
- datalab/data/icons/table.svg +85 -0
- datalab/data/icons/table_unavailable.svg +102 -0
- datalab/data/icons/to_signal.svg +124 -0
- datalab/data/icons/tour/next.svg +44 -0
- datalab/data/icons/tour/previous.svg +44 -0
- datalab/data/icons/tour/rewind.svg +51 -0
- datalab/data/icons/tour/stop.svg +47 -0
- datalab/data/icons/tour/tour.svg +16 -0
- datalab/data/icons/uncheck_all.svg +78 -0
- datalab/data/icons/view/curve_antialiasing.svg +50 -0
- datalab/data/icons/view/new_window.svg +98 -0
- datalab/data/icons/view/refresh-auto.svg +57 -0
- datalab/data/icons/view/refresh-manual.svg +51 -0
- datalab/data/icons/view/reset_curve_styles.svg +96 -0
- datalab/data/icons/view/show_first.svg +55 -0
- datalab/data/icons/view/show_titles.svg +46 -0
- datalab/data/icons/visualization.svg +51 -0
- datalab/data/logo/DataLab-Banner-150.png +0 -0
- datalab/data/logo/DataLab-Banner-200.png +0 -0
- datalab/data/logo/DataLab-Banner2-100.png +0 -0
- datalab/data/logo/DataLab-Splash.png +0 -0
- datalab/data/logo/DataLab-watermark.png +0 -0
- datalab/data/logo/DataLab.svg +83 -0
- datalab/data/tests/reordering_test.h5 +0 -0
- datalab/data/tutorials/fabry_perot/fabry-perot1.jpg +0 -0
- datalab/data/tutorials/fabry_perot/fabry-perot2.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_13.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_18.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_23.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_30.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_35.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_40.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_45.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_50.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_55.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_60.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_65.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_70.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_75.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_80.jpg +0 -0
- datalab/env.py +542 -0
- datalab/gui/__init__.py +89 -0
- datalab/gui/actionhandler.py +1701 -0
- datalab/gui/docks.py +473 -0
- datalab/gui/h5io.py +150 -0
- datalab/gui/macroeditor.py +310 -0
- datalab/gui/main.py +2081 -0
- datalab/gui/newobject.py +217 -0
- datalab/gui/objectview.py +766 -0
- datalab/gui/panel/__init__.py +48 -0
- datalab/gui/panel/base.py +3254 -0
- datalab/gui/panel/image.py +157 -0
- datalab/gui/panel/macro.py +607 -0
- datalab/gui/panel/signal.py +164 -0
- datalab/gui/plothandler.py +800 -0
- datalab/gui/processor/__init__.py +84 -0
- datalab/gui/processor/base.py +2456 -0
- datalab/gui/processor/catcher.py +75 -0
- datalab/gui/processor/image.py +1214 -0
- datalab/gui/processor/signal.py +755 -0
- datalab/gui/profiledialog.py +333 -0
- datalab/gui/roieditor.py +633 -0
- datalab/gui/roigrideditor.py +208 -0
- datalab/gui/settings.py +612 -0
- datalab/gui/tour.py +908 -0
- datalab/h5/__init__.py +12 -0
- datalab/h5/common.py +314 -0
- datalab/h5/generic.py +580 -0
- datalab/h5/native.py +39 -0
- datalab/h5/utils.py +95 -0
- datalab/objectmodel.py +640 -0
- datalab/plugins/_readme_.txt +9 -0
- datalab/plugins/datalab_imageformats.py +175 -0
- datalab/plugins/datalab_testdata.py +190 -0
- datalab/plugins.py +355 -0
- datalab/tests/__init__.py +199 -0
- datalab/tests/backbone/__init__.py +1 -0
- datalab/tests/backbone/config_unit_test.py +170 -0
- datalab/tests/backbone/config_versioning_unit_test.py +34 -0
- datalab/tests/backbone/dictlistserial_app_test.py +38 -0
- datalab/tests/backbone/errorcatcher_unit_test.py +69 -0
- datalab/tests/backbone/errormsgbox_unit_test.py +50 -0
- datalab/tests/backbone/execenv_unit.py +262 -0
- datalab/tests/backbone/loadtest_gdi.py +147 -0
- datalab/tests/backbone/long_callback.py +96 -0
- datalab/tests/backbone/main_app_test.py +137 -0
- datalab/tests/backbone/memory_leak.py +43 -0
- datalab/tests/backbone/procisolation1_unit.py +128 -0
- datalab/tests/backbone/procisolation2_unit.py +171 -0
- datalab/tests/backbone/procisolation_unit_test.py +22 -0
- datalab/tests/backbone/profiling_app.py +27 -0
- datalab/tests/backbone/strings_unit_test.py +65 -0
- datalab/tests/backbone/title_formatting_unit_test.py +82 -0
- datalab/tests/conftest.py +131 -0
- datalab/tests/features/__init__.py +1 -0
- datalab/tests/features/applauncher/__init__.py +1 -0
- datalab/tests/features/applauncher/launcher1_app_test.py +28 -0
- datalab/tests/features/applauncher/launcher2_app_test.py +30 -0
- datalab/tests/features/common/__init__.py +1 -0
- datalab/tests/features/common/add_metadata_app_test.py +134 -0
- datalab/tests/features/common/add_metadata_unit_test.py +267 -0
- datalab/tests/features/common/annotations_management_unit_test.py +152 -0
- datalab/tests/features/common/auto_analysis_recompute_unit_test.py +240 -0
- datalab/tests/features/common/createobject_unit_test.py +50 -0
- datalab/tests/features/common/geometry_results_app_test.py +135 -0
- datalab/tests/features/common/interactive_processing_test.py +1109 -0
- datalab/tests/features/common/io_app_test.py +75 -0
- datalab/tests/features/common/large_results_app_test.py +187 -0
- datalab/tests/features/common/metadata_all_patterns_test.py +103 -0
- datalab/tests/features/common/metadata_app_test.py +139 -0
- datalab/tests/features/common/metadata_io_unit_test.py +60 -0
- datalab/tests/features/common/misc_app_test.py +236 -0
- datalab/tests/features/common/multiple_geometry_results_unit_test.py +122 -0
- datalab/tests/features/common/multiple_table_results_unit_test.py +64 -0
- datalab/tests/features/common/operation_modes_app_test.py +392 -0
- datalab/tests/features/common/plot_results_app_test.py +278 -0
- datalab/tests/features/common/reorder_app_test.py +75 -0
- datalab/tests/features/common/result_deletion_unit_test.py +96 -0
- datalab/tests/features/common/result_merged_label_unit_test.py +154 -0
- datalab/tests/features/common/result_shape_settings_unit_test.py +223 -0
- datalab/tests/features/common/roi_plotitem_unit_test.py +64 -0
- datalab/tests/features/common/roieditor_unit_test.py +102 -0
- datalab/tests/features/common/save_to_dir_app_test.py +163 -0
- datalab/tests/features/common/save_to_dir_unit_test.py +474 -0
- datalab/tests/features/common/stat_app_test.py +40 -0
- datalab/tests/features/common/stats_tools_unit_test.py +77 -0
- datalab/tests/features/common/table_results_app_test.py +52 -0
- datalab/tests/features/common/textimport_unit_test.py +131 -0
- datalab/tests/features/common/uuid_preservation_test.py +281 -0
- datalab/tests/features/common/worker_unit_test.py +402 -0
- datalab/tests/features/control/__init__.py +1 -0
- datalab/tests/features/control/connect_dialog.py +28 -0
- datalab/tests/features/control/embedded1_unit_test.py +304 -0
- datalab/tests/features/control/embedded2_unit_test.py +52 -0
- datalab/tests/features/control/remoteclient_app_test.py +219 -0
- datalab/tests/features/control/remoteclient_unit.py +75 -0
- datalab/tests/features/control/simpleclient_unit_test.py +321 -0
- datalab/tests/features/hdf5/__init__.py +1 -0
- datalab/tests/features/hdf5/h5browser1_unit_test.py +31 -0
- datalab/tests/features/hdf5/h5browser2_unit.py +55 -0
- datalab/tests/features/hdf5/h5browser_app_test.py +77 -0
- datalab/tests/features/hdf5/h5import_app_test.py +25 -0
- datalab/tests/features/hdf5/h5importer_app_test.py +34 -0
- datalab/tests/features/image/__init__.py +1 -0
- datalab/tests/features/image/annotations_app_test.py +28 -0
- datalab/tests/features/image/annotations_unit_test.py +80 -0
- datalab/tests/features/image/average_app_test.py +46 -0
- datalab/tests/features/image/background_dialog_test.py +70 -0
- datalab/tests/features/image/blobs_app_test.py +50 -0
- datalab/tests/features/image/contour_app_test.py +42 -0
- datalab/tests/features/image/contour_fabryperot_app_test.py +51 -0
- datalab/tests/features/image/denoise_app_test.py +31 -0
- datalab/tests/features/image/distribute_on_grid_app_test.py +95 -0
- datalab/tests/features/image/edges_app_test.py +31 -0
- datalab/tests/features/image/erase_app_test.py +21 -0
- datalab/tests/features/image/fft2d_app_test.py +27 -0
- datalab/tests/features/image/flatfield_app_test.py +40 -0
- datalab/tests/features/image/geometry_transform_unit_test.py +396 -0
- datalab/tests/features/image/imagetools_app_test.py +51 -0
- datalab/tests/features/image/imagetools_unit_test.py +27 -0
- datalab/tests/features/image/load_app_test.py +73 -0
- datalab/tests/features/image/morph_app_test.py +32 -0
- datalab/tests/features/image/offsetcorrection_app_test.py +30 -0
- datalab/tests/features/image/peak2d_app_test.py +53 -0
- datalab/tests/features/image/profile_app_test.py +73 -0
- datalab/tests/features/image/profile_dialog_test.py +56 -0
- datalab/tests/features/image/roi_app_test.py +98 -0
- datalab/tests/features/image/roi_circ_app_test.py +62 -0
- datalab/tests/features/image/roi_manipulation_app_test.py +268 -0
- datalab/tests/features/image/roigrid_unit_test.py +60 -0
- datalab/tests/features/image/side_by_side_app_test.py +52 -0
- datalab/tests/features/macro/__init__.py +1 -0
- datalab/tests/features/macro/macro_app_test.py +28 -0
- datalab/tests/features/macro/macroeditor_unit_test.py +102 -0
- datalab/tests/features/signal/__init__.py +1 -0
- datalab/tests/features/signal/baseline_dialog_test.py +53 -0
- datalab/tests/features/signal/deltax_dialog_unit_test.py +34 -0
- datalab/tests/features/signal/fft1d_app_test.py +26 -0
- datalab/tests/features/signal/filter_app_test.py +44 -0
- datalab/tests/features/signal/fitdialog_unit_test.py +50 -0
- datalab/tests/features/signal/interpolation_app_test.py +110 -0
- datalab/tests/features/signal/loadbigsignal_app_test.py +80 -0
- datalab/tests/features/signal/multiple_rois_unit_test.py +132 -0
- datalab/tests/features/signal/pulse_features_app_test.py +118 -0
- datalab/tests/features/signal/pulse_features_roi_app_test.py +55 -0
- datalab/tests/features/signal/roi_app_test.py +78 -0
- datalab/tests/features/signal/roi_manipulation_app_test.py +261 -0
- datalab/tests/features/signal/select_xy_cursor_unit_test.py +46 -0
- datalab/tests/features/signal/signalpeakdetection_dialog_test.py +33 -0
- datalab/tests/features/signal/signals_to_image_app_test.py +98 -0
- datalab/tests/features/signal/xarray_compat_app_test.py +128 -0
- datalab/tests/features/tour_unit_test.py +22 -0
- datalab/tests/features/utilities/__init__.py +1 -0
- datalab/tests/features/utilities/installconf_unit_test.py +21 -0
- datalab/tests/features/utilities/logview_app_test.py +21 -0
- datalab/tests/features/utilities/logview_error.py +24 -0
- datalab/tests/features/utilities/logview_unit_test.py +21 -0
- datalab/tests/features/utilities/memstatus_app_test.py +42 -0
- datalab/tests/features/utilities/settings_unit_test.py +88 -0
- datalab/tests/scenarios/__init__.py +1 -0
- datalab/tests/scenarios/beautiful_app.py +121 -0
- datalab/tests/scenarios/common.py +463 -0
- datalab/tests/scenarios/demo.py +212 -0
- datalab/tests/scenarios/example_app_test.py +47 -0
- datalab/tests/scenarios/scenario_h5_app_test.py +75 -0
- datalab/tests/scenarios/scenario_ima1_app_test.py +34 -0
- datalab/tests/scenarios/scenario_ima2_app_test.py +34 -0
- datalab/tests/scenarios/scenario_mac_app_test.py +58 -0
- datalab/tests/scenarios/scenario_sig1_app_test.py +36 -0
- datalab/tests/scenarios/scenario_sig2_app_test.py +35 -0
- datalab/utils/__init__.py +1 -0
- datalab/utils/conf.py +304 -0
- datalab/utils/dephash.py +105 -0
- datalab/utils/qthelpers.py +633 -0
- datalab/utils/strings.py +34 -0
- datalab/utils/tests.py +0 -0
- datalab/widgets/__init__.py +1 -0
- datalab/widgets/connection.py +138 -0
- datalab/widgets/filedialog.py +91 -0
- datalab/widgets/fileviewer.py +84 -0
- datalab/widgets/fitdialog.py +788 -0
- datalab/widgets/h5browser.py +1048 -0
- datalab/widgets/imagebackground.py +111 -0
- datalab/widgets/instconfviewer.py +175 -0
- datalab/widgets/logviewer.py +80 -0
- datalab/widgets/signalbaseline.py +90 -0
- datalab/widgets/signalcursor.py +208 -0
- datalab/widgets/signaldeltax.py +151 -0
- datalab/widgets/signalpeak.py +199 -0
- datalab/widgets/status.py +249 -0
- datalab/widgets/textimport.py +786 -0
- datalab/widgets/warningerror.py +223 -0
- datalab/widgets/wizard.py +286 -0
- datalab_platform-1.0.0.dist-info/METADATA +121 -0
- datalab_platform-1.0.0.dist-info/RECORD +494 -0
- datalab_platform-0.0.1.dev0.dist-info/METADATA +0 -67
- datalab_platform-0.0.1.dev0.dist-info/RECORD +0 -7
- {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.0.dist-info}/WHEEL +0 -0
- {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.0.dist-info}/entry_points.txt +0 -0
- {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.0.dist-info}/licenses/LICENSE +0 -0
- {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.0.dist-info}/top_level.txt +0 -0
datalab/gui/tour.py
ADDED
|
@@ -0,0 +1,908 @@
|
|
|
1
|
+
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
|
|
2
|
+
|
|
3
|
+
# pylint: disable=invalid-name # Allows short reference names like x, y, ...
|
|
4
|
+
|
|
5
|
+
"""
|
|
6
|
+
Tour
|
|
7
|
+
====
|
|
8
|
+
|
|
9
|
+
The :mod:`datalab.gui.tour` module implements a tour of DataLab features.
|
|
10
|
+
|
|
11
|
+
A dialog box is displayed when the user launches DataLab for the first time or
|
|
12
|
+
when the user clicks on the "Show tour" entry in the "?" menu.
|
|
13
|
+
|
|
14
|
+
The tour user experience is the following:
|
|
15
|
+
|
|
16
|
+
- First, the DataLab main window is maximized, and it is grayed out (the whole window
|
|
17
|
+
is covered with a gray area with an opacity of 50%). The user can not interact with
|
|
18
|
+
the DataLab main window while the tour is running.
|
|
19
|
+
|
|
20
|
+
- A first modal dialog box is displayed with a short description of DataLab, and two
|
|
21
|
+
buttons: "Start" and "Close". If the user clicks on "Start", the tour
|
|
22
|
+
starts. If the user clicks on "Close", the tour is not started and the dialog box
|
|
23
|
+
is closed.
|
|
24
|
+
|
|
25
|
+
- The tour is composed of several steps. Each step is a modal dialog box with a short
|
|
26
|
+
description of a DataLab feature, and three buttons: "Previous", "Next" and "Close".
|
|
27
|
+
If the user clicks on "Previous", the previous step is displayed. If the user clicks
|
|
28
|
+
on "Next", the next step is displayed. If the user clicks on "Close", the tour is
|
|
29
|
+
stopped and the dialog box is closed.
|
|
30
|
+
|
|
31
|
+
- At each step, the dialog box is moved to the center of the DataLab main window (i.e.
|
|
32
|
+
the center of the screen), and the feature described in the step is highlighted in
|
|
33
|
+
the DataLab main window. The highlight is a red rectangle around the feature, and
|
|
34
|
+
the feature is the only part of the DataLab main window that is not grayed out.
|
|
35
|
+
|
|
36
|
+
- The last step of the tour is a modal dialog box with a conclusion message and two
|
|
37
|
+
buttons: "Show tour again", "Close", and "Show demo". If the user clicks on "Show
|
|
38
|
+
tour again", the tour starts again. If the user clicks on "Close", the tour is
|
|
39
|
+
stopped and the dialog box is closed. If the user clicks on "Show demo", the demo
|
|
40
|
+
is started.
|
|
41
|
+
|
|
42
|
+
.. autoclass:: Tour
|
|
43
|
+
:members:
|
|
44
|
+
:inherited-members:
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
from __future__ import annotations
|
|
48
|
+
|
|
49
|
+
import abc
|
|
50
|
+
import enum
|
|
51
|
+
import os
|
|
52
|
+
from collections.abc import Callable
|
|
53
|
+
from typing import TYPE_CHECKING
|
|
54
|
+
|
|
55
|
+
import numpy as np
|
|
56
|
+
from guidata.configtools import get_icon, get_image_file_path
|
|
57
|
+
from guidata.qthelpers import is_dark_theme
|
|
58
|
+
from qtpy import QtCore as QC
|
|
59
|
+
from qtpy import QtGui as QG
|
|
60
|
+
from qtpy import QtWidgets as QW
|
|
61
|
+
from sigima.objects import create_image, create_signal
|
|
62
|
+
|
|
63
|
+
from datalab.config import _
|
|
64
|
+
from datalab.env import execenv
|
|
65
|
+
|
|
66
|
+
if TYPE_CHECKING:
|
|
67
|
+
from datalab.gui.main import DLMainWindow
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class Cover(QW.QWidget):
|
|
71
|
+
"""
|
|
72
|
+
Widget that covers the main window with a gray area with an opacity of 50%.
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
def __init__(self, parent: DLMainWindow) -> None:
|
|
76
|
+
super().__init__(parent)
|
|
77
|
+
self.setWindowFlags(QC.Qt.Tool | QC.Qt.FramelessWindowHint)
|
|
78
|
+
self.setAttribute(QC.Qt.WA_TranslucentBackground)
|
|
79
|
+
self.__opacity_factor = 1.0
|
|
80
|
+
# Widgets to be excluded from the grayed out area:
|
|
81
|
+
self.__excluded_widgets: list[QW.QWidget] | None = None
|
|
82
|
+
# Path to be grayed out:
|
|
83
|
+
self.__path: QG.QPainterPath = QG.QPainterPath()
|
|
84
|
+
|
|
85
|
+
def set_opacity_factor(self, opacity_factor: float) -> None:
|
|
86
|
+
"""
|
|
87
|
+
Set the opacity factor of the grayed out area.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
opacity_factor: Opacity factor.
|
|
91
|
+
"""
|
|
92
|
+
self.__opacity_factor = opacity_factor
|
|
93
|
+
|
|
94
|
+
def exclude(self, widgets: list[QW.QWidget]) -> None:
|
|
95
|
+
"""
|
|
96
|
+
Exclude widgets from the grayed out area.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
widgets: Widgets to be excluded.
|
|
100
|
+
"""
|
|
101
|
+
self.__excluded_widgets = widgets
|
|
102
|
+
|
|
103
|
+
def update_geometry(self) -> None:
|
|
104
|
+
"""
|
|
105
|
+
Update the geometry of the widget.
|
|
106
|
+
"""
|
|
107
|
+
if os.name == "nt":
|
|
108
|
+
QW.QApplication.processEvents()
|
|
109
|
+
self.setGeometry(self.parentWidget().geometry())
|
|
110
|
+
self.__path = QG.QPainterPath()
|
|
111
|
+
# Path is defined as the rectangle of the main window minus the rectangles of
|
|
112
|
+
# the excluded widgets:
|
|
113
|
+
self.__path.addRect(QC.QRectF(self.parentWidget().rect()))
|
|
114
|
+
if self.__excluded_widgets is not None:
|
|
115
|
+
for widget in self.__excluded_widgets:
|
|
116
|
+
widget.raise_()
|
|
117
|
+
widget.show()
|
|
118
|
+
geometry = widget.frameGeometry()
|
|
119
|
+
width, height = geometry.width(), geometry.height()
|
|
120
|
+
point = widget.mapTo(self.parentWidget(), QC.QPoint(0, 0))
|
|
121
|
+
x, y = point.x(), point.y()
|
|
122
|
+
widget_path = QG.QPainterPath()
|
|
123
|
+
widget_path.addRect(QC.QRectF(x, y, width, height))
|
|
124
|
+
self.__path -= QG.QPainterPath(widget_path)
|
|
125
|
+
self.repaint()
|
|
126
|
+
|
|
127
|
+
def showEvent(self, a0: QG.QShowEvent | None) -> None:
|
|
128
|
+
"""
|
|
129
|
+
Event handler for the "show" event.
|
|
130
|
+
|
|
131
|
+
Args:
|
|
132
|
+
a0: Show event.
|
|
133
|
+
"""
|
|
134
|
+
super().showEvent(a0)
|
|
135
|
+
self.setGeometry(self.parentWidget().geometry())
|
|
136
|
+
|
|
137
|
+
def paintEvent(self, event: QG.QPaintEvent) -> None:
|
|
138
|
+
"""
|
|
139
|
+
Event handler for the "paint" event.
|
|
140
|
+
|
|
141
|
+
Args:
|
|
142
|
+
event: Paint event.
|
|
143
|
+
"""
|
|
144
|
+
super().paintEvent(event)
|
|
145
|
+
painter = QG.QPainter(self)
|
|
146
|
+
painter.setOpacity((0.75 if is_dark_theme() else 0.5) * self.__opacity_factor)
|
|
147
|
+
painter.setBrush(QG.QBrush(QC.Qt.black))
|
|
148
|
+
painter.setPen(QC.Qt.NoPen)
|
|
149
|
+
painter.drawPath(self.__path)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
class StepResult(enum.Enum):
|
|
153
|
+
"""
|
|
154
|
+
Result of a step.
|
|
155
|
+
"""
|
|
156
|
+
|
|
157
|
+
PREVIOUS = enum.auto()
|
|
158
|
+
NEXT = enum.auto()
|
|
159
|
+
CLOSE = enum.auto()
|
|
160
|
+
DEMO = enum.auto()
|
|
161
|
+
RESTART = enum.auto()
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
class StepDialog(QW.QDialog):
|
|
165
|
+
"""
|
|
166
|
+
Base class for tour dialog boxes.
|
|
167
|
+
|
|
168
|
+
Args:
|
|
169
|
+
parent: Parent widget.
|
|
170
|
+
step: Tour step.
|
|
171
|
+
"""
|
|
172
|
+
|
|
173
|
+
def __init__(
|
|
174
|
+
self,
|
|
175
|
+
parent: QW.QWidget,
|
|
176
|
+
step: TourStep,
|
|
177
|
+
) -> None:
|
|
178
|
+
super().__init__(parent)
|
|
179
|
+
self.setWindowTitle(step.title)
|
|
180
|
+
self.setWindowFlags(QC.Qt.Popup)
|
|
181
|
+
self.setModal(True)
|
|
182
|
+
self.step = step
|
|
183
|
+
self.result: StepResult | None = None
|
|
184
|
+
self.__btnmap: dict[QW.QPushButton, StepResult] = {}
|
|
185
|
+
self.__btnlayout = QW.QHBoxLayout()
|
|
186
|
+
self._setup_ui()
|
|
187
|
+
|
|
188
|
+
def __btn(self, text: str, result: StepResult, default: bool = False) -> None:
|
|
189
|
+
"""
|
|
190
|
+
Create a button.
|
|
191
|
+
|
|
192
|
+
Args:
|
|
193
|
+
text: Button text.
|
|
194
|
+
result: Result of the button.
|
|
195
|
+
default: Default button. Defaults to False.
|
|
196
|
+
"""
|
|
197
|
+
btn = QW.QPushButton(text)
|
|
198
|
+
btn.setAutoDefault(default)
|
|
199
|
+
btn.setDefault(default)
|
|
200
|
+
icon = {
|
|
201
|
+
"<<": "rewind.svg",
|
|
202
|
+
"<": "previous.svg",
|
|
203
|
+
">": "next.svg",
|
|
204
|
+
"X": "stop.svg",
|
|
205
|
+
}.get(text)
|
|
206
|
+
if icon is not None:
|
|
207
|
+
btn.setIcon(get_icon(icon))
|
|
208
|
+
btn.setText("")
|
|
209
|
+
btn.setMinimumWidth(100)
|
|
210
|
+
btn.clicked.connect(lambda: self.button_clicked(btn))
|
|
211
|
+
self.__btnmap[btn] = result
|
|
212
|
+
self.__btnlayout.addWidget(btn)
|
|
213
|
+
|
|
214
|
+
def __btn_spacing(self, spacing: int) -> None:
|
|
215
|
+
"""
|
|
216
|
+
Add spacing between buttons.
|
|
217
|
+
|
|
218
|
+
Args:
|
|
219
|
+
spacing: Spacing.
|
|
220
|
+
"""
|
|
221
|
+
self.__btnlayout.addSpacing(spacing)
|
|
222
|
+
|
|
223
|
+
def __create_label(
|
|
224
|
+
self,
|
|
225
|
+
text: str,
|
|
226
|
+
delta_fontsize: int,
|
|
227
|
+
color: QC.Qt.GlobalColor,
|
|
228
|
+
bold: bool = False,
|
|
229
|
+
) -> QW.QLabel:
|
|
230
|
+
"""
|
|
231
|
+
Create a label.
|
|
232
|
+
|
|
233
|
+
Args:
|
|
234
|
+
text: Label text.
|
|
235
|
+
delta_fontsize: Delta font size.
|
|
236
|
+
color: Text color.
|
|
237
|
+
bold: Bold text.
|
|
238
|
+
|
|
239
|
+
Returns:
|
|
240
|
+
Label.
|
|
241
|
+
"""
|
|
242
|
+
label = QW.QLabel(text)
|
|
243
|
+
label.setWordWrap(True)
|
|
244
|
+
label.setAlignment(QC.Qt.AlignCenter)
|
|
245
|
+
# Change font size for something bigger:
|
|
246
|
+
font = label.font()
|
|
247
|
+
font.setPointSize(font.pointSize() + delta_fontsize)
|
|
248
|
+
label.setFont(font)
|
|
249
|
+
# Set text color:
|
|
250
|
+
palette = label.palette()
|
|
251
|
+
palette.setColor(QG.QPalette.WindowText, color)
|
|
252
|
+
label.setPalette(palette)
|
|
253
|
+
# Set bold text:
|
|
254
|
+
font = label.font()
|
|
255
|
+
font.setBold(bold)
|
|
256
|
+
return label
|
|
257
|
+
|
|
258
|
+
def __create_horizontal_line(self) -> QW.QFrame:
|
|
259
|
+
"""
|
|
260
|
+
Create a horizontal line.
|
|
261
|
+
|
|
262
|
+
Returns:
|
|
263
|
+
Horizontal line.
|
|
264
|
+
"""
|
|
265
|
+
line = QW.QFrame()
|
|
266
|
+
line.setFrameShape(QW.QFrame.HLine)
|
|
267
|
+
line.setFrameShadow(QW.QFrame.Sunken)
|
|
268
|
+
line.setLineWidth(1)
|
|
269
|
+
line.setMidLineWidth(0)
|
|
270
|
+
palette = line.palette()
|
|
271
|
+
palette.setColor(QG.QPalette.WindowText, QC.Qt.lightGray)
|
|
272
|
+
line.setPalette(palette)
|
|
273
|
+
return line
|
|
274
|
+
|
|
275
|
+
def _setup_ui(self) -> None:
|
|
276
|
+
"""
|
|
277
|
+
Setup the user interface.
|
|
278
|
+
"""
|
|
279
|
+
if self.step.step_type == "introduction":
|
|
280
|
+
self.__btn_spacing(50)
|
|
281
|
+
self.__btn(_("Start"), StepResult.NEXT, True)
|
|
282
|
+
self.__btn(_("Close"), StepResult.CLOSE)
|
|
283
|
+
self.__btn_spacing(50)
|
|
284
|
+
elif self.step.step_type == "conclusion":
|
|
285
|
+
self.__btn("<<", StepResult.RESTART)
|
|
286
|
+
self.__btn("<", StepResult.PREVIOUS)
|
|
287
|
+
self.__btn(_("Demo"), StepResult.DEMO)
|
|
288
|
+
self.__btn("X", StepResult.CLOSE, True)
|
|
289
|
+
else:
|
|
290
|
+
self.__btn("<<", StepResult.RESTART)
|
|
291
|
+
self.__btn("<", StepResult.PREVIOUS)
|
|
292
|
+
self.__btn(">", StepResult.NEXT, True)
|
|
293
|
+
self.__btn("X", StepResult.CLOSE)
|
|
294
|
+
self._layout = QW.QVBoxLayout()
|
|
295
|
+
if self.step.step_type in ("introduction", "conclusion"):
|
|
296
|
+
logo = QW.QLabel()
|
|
297
|
+
logo.setPixmap(QG.QPixmap(get_image_file_path("DataLab-Banner2-100.png")))
|
|
298
|
+
logo.setAlignment(QC.Qt.AlignCenter)
|
|
299
|
+
self._layout.addWidget(logo)
|
|
300
|
+
title_color = QC.Qt.lightGray if is_dark_theme() else QC.Qt.darkGray
|
|
301
|
+
title = self.__create_label(self.step.title, 1, title_color, True)
|
|
302
|
+
self._layout.addWidget(title)
|
|
303
|
+
self._layout.addWidget(self.__create_horizontal_line())
|
|
304
|
+
label_color = QC.Qt.cyan if is_dark_theme() else QC.Qt.darkBlue
|
|
305
|
+
label_dsize = 3 if self.step.step_type == "regular" else 4
|
|
306
|
+
label = self.__create_label(self.step.text, label_dsize, label_color)
|
|
307
|
+
if self.step.step_type == "regular":
|
|
308
|
+
label.setAlignment(QC.Qt.AlignLeft)
|
|
309
|
+
self._layout.addWidget(label)
|
|
310
|
+
self._layout.addSpacing(5)
|
|
311
|
+
self._layout.addLayout(self.__btnlayout)
|
|
312
|
+
if self.step.step_type == "introduction":
|
|
313
|
+
self._layout.addSpacing(5)
|
|
314
|
+
help_text = _(
|
|
315
|
+
"Hit <b>Enter</b> to continue to the next step, or "
|
|
316
|
+
"<b>Esc</b> to close the tour."
|
|
317
|
+
)
|
|
318
|
+
help_label = self.__create_label(help_text, -1, title_color)
|
|
319
|
+
help_label.setAlignment(QC.Qt.AlignLeft)
|
|
320
|
+
self._layout.addWidget(help_label)
|
|
321
|
+
self.setLayout(self._layout)
|
|
322
|
+
|
|
323
|
+
def button_clicked(self, button: QW.QPushButton) -> None:
|
|
324
|
+
"""
|
|
325
|
+
Event handler for the "clicked" event on the buttons.
|
|
326
|
+
|
|
327
|
+
Args:
|
|
328
|
+
button: Button that was clicked.
|
|
329
|
+
"""
|
|
330
|
+
self.result = self.__btnmap[button]
|
|
331
|
+
if self.result is StepResult.CLOSE:
|
|
332
|
+
self.reject()
|
|
333
|
+
else:
|
|
334
|
+
self.accept()
|
|
335
|
+
|
|
336
|
+
def reject(self) -> None:
|
|
337
|
+
"""
|
|
338
|
+
Event handler for the "reject" event.
|
|
339
|
+
"""
|
|
340
|
+
self.result = StepResult.CLOSE
|
|
341
|
+
super().reject()
|
|
342
|
+
|
|
343
|
+
def paintEvent(self, event: QG.QPaintEvent) -> None:
|
|
344
|
+
"""
|
|
345
|
+
Event handler for the "paint" event.
|
|
346
|
+
|
|
347
|
+
Args:
|
|
348
|
+
event: Paint event.
|
|
349
|
+
"""
|
|
350
|
+
super().paintEvent(event)
|
|
351
|
+
painter = QG.QPainter(self)
|
|
352
|
+
painter.setOpacity(0.5)
|
|
353
|
+
painter.setBrush(QG.QBrush(QC.Qt.black))
|
|
354
|
+
painter.setPen(QC.Qt.NoPen)
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
class TourStep:
|
|
358
|
+
"""
|
|
359
|
+
Tour step.
|
|
360
|
+
|
|
361
|
+
Args:
|
|
362
|
+
tour: Tour.
|
|
363
|
+
title: Step title.
|
|
364
|
+
text: Step text.
|
|
365
|
+
widgets: Widgets to be highlighted. If None, no widget is highlighted, meaning
|
|
366
|
+
that the step is probably an introduction or a conclusion.
|
|
367
|
+
setup_callback: Callback function to be called before the step is displayed,
|
|
368
|
+
which takes a single argument, the `DLMainWindow` instance.
|
|
369
|
+
teardown_callback: Callback function to be called after the step is displayed,
|
|
370
|
+
which takes a single argument, the `DLMainWindow` instance.
|
|
371
|
+
step_type: Step type. Can be "regular", "introduction" or "conclusion".
|
|
372
|
+
"""
|
|
373
|
+
|
|
374
|
+
def __init__(
|
|
375
|
+
self,
|
|
376
|
+
tour: BaseTour,
|
|
377
|
+
title: str,
|
|
378
|
+
text: str,
|
|
379
|
+
widgets: list[QW.QWidget] | None = None,
|
|
380
|
+
setup_callback: Callable | None = None,
|
|
381
|
+
teardown_callback: Callable | None = None,
|
|
382
|
+
step_type: str = "regular",
|
|
383
|
+
) -> None:
|
|
384
|
+
self.tour = tour
|
|
385
|
+
self.title = title
|
|
386
|
+
self.text = text
|
|
387
|
+
self.widgets = widgets
|
|
388
|
+
self.setup_callback = setup_callback
|
|
389
|
+
self.teardown_callback = teardown_callback
|
|
390
|
+
self.step_type = step_type
|
|
391
|
+
assert step_type in ["regular", "introduction", "conclusion"]
|
|
392
|
+
|
|
393
|
+
def show(self) -> StepResult:
|
|
394
|
+
"""
|
|
395
|
+
Show the step.
|
|
396
|
+
|
|
397
|
+
Returns:
|
|
398
|
+
Result of the step.
|
|
399
|
+
"""
|
|
400
|
+
if self.setup_callback is not None:
|
|
401
|
+
self.setup_callback(self.tour.win)
|
|
402
|
+
self.update_cover(self.tour.cover)
|
|
403
|
+
dialog = StepDialog(self.tour.win, self)
|
|
404
|
+
if not execenv.unattended:
|
|
405
|
+
dialog.exec()
|
|
406
|
+
elif self.step_type != "conclusion":
|
|
407
|
+
dialog.result = StepResult.NEXT
|
|
408
|
+
dialog.accept()
|
|
409
|
+
else:
|
|
410
|
+
dialog.result = StepResult.CLOSE
|
|
411
|
+
dialog.reject()
|
|
412
|
+
if self.teardown_callback is not None:
|
|
413
|
+
self.teardown_callback(self.tour.win)
|
|
414
|
+
return dialog.result
|
|
415
|
+
|
|
416
|
+
def update_cover(self, cover: Cover) -> None:
|
|
417
|
+
"""
|
|
418
|
+
Update the cover widget.
|
|
419
|
+
|
|
420
|
+
Args:
|
|
421
|
+
cover: Cover widget.
|
|
422
|
+
"""
|
|
423
|
+
cover.set_opacity_factor(1.0 if self.step_type == "regular" else 0.7)
|
|
424
|
+
cover.exclude(self.widgets)
|
|
425
|
+
cover.update_geometry()
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
class BaseTourMeta(type(QW.QWidget), abc.ABCMeta):
|
|
429
|
+
"""Mixed metaclass to avoid conflicts"""
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
class BaseTour(QW.QWidget, metaclass=BaseTourMeta):
|
|
433
|
+
"""
|
|
434
|
+
Base class for the tour of DataLab features.
|
|
435
|
+
|
|
436
|
+
Args:
|
|
437
|
+
win: DataLab main window.
|
|
438
|
+
"""
|
|
439
|
+
|
|
440
|
+
def __init__(self, win: DLMainWindow) -> None:
|
|
441
|
+
super().__init__(win)
|
|
442
|
+
self.win = win
|
|
443
|
+
self._steps: list[TourStep] = []
|
|
444
|
+
self._current_step = 0
|
|
445
|
+
self.cover = Cover(win)
|
|
446
|
+
self.cover.show()
|
|
447
|
+
self.__window_geometry: tuple[tuple[int, int], tuple[int, int]] | None = None
|
|
448
|
+
self.__window_prepared = False
|
|
449
|
+
self.setup_tour(win)
|
|
450
|
+
|
|
451
|
+
def __resize_window(self, factor: float) -> None:
|
|
452
|
+
"""
|
|
453
|
+
Resize the window so that it is centered on the screen and its size is
|
|
454
|
+
`factor` times the size of the screen.
|
|
455
|
+
|
|
456
|
+
Args:
|
|
457
|
+
factor: Factor by which the size of the window is multiplied.
|
|
458
|
+
"""
|
|
459
|
+
desktop = QW.QApplication.desktop()
|
|
460
|
+
screen = desktop.screenNumber(desktop.cursor().pos())
|
|
461
|
+
screen_geometry = desktop.screenGeometry(screen)
|
|
462
|
+
width = int(screen_geometry.width() * factor)
|
|
463
|
+
height = int(screen_geometry.height() * factor)
|
|
464
|
+
self.win.resize(width, height)
|
|
465
|
+
self.win.move(screen_geometry.center() - QC.QPoint(width // 2, height // 2))
|
|
466
|
+
|
|
467
|
+
def __save_window_geometry(self) -> None:
|
|
468
|
+
"""Save the window geometry (size and position)."""
|
|
469
|
+
self.__window_geometry = self.win.saveGeometry()
|
|
470
|
+
|
|
471
|
+
def __restore_window_geometry(self) -> None:
|
|
472
|
+
"""Restore the window geometry (size and position)."""
|
|
473
|
+
if self.__window_geometry is not None:
|
|
474
|
+
self.win.restoreGeometry(self.__window_geometry)
|
|
475
|
+
|
|
476
|
+
@abc.abstractmethod
|
|
477
|
+
def setup_tour(self, win: DLMainWindow) -> None:
|
|
478
|
+
"""
|
|
479
|
+
Setup the tour: add steps to the tour.
|
|
480
|
+
"""
|
|
481
|
+
|
|
482
|
+
@abc.abstractmethod
|
|
483
|
+
def cleanup_tour(self, win: DLMainWindow) -> None:
|
|
484
|
+
"""
|
|
485
|
+
Cleanup the tour.
|
|
486
|
+
"""
|
|
487
|
+
|
|
488
|
+
def add_step(
|
|
489
|
+
self,
|
|
490
|
+
title: str,
|
|
491
|
+
text: str,
|
|
492
|
+
widgets: list[QW.QWidget] | None = None,
|
|
493
|
+
setup_callback: Callable | None = None,
|
|
494
|
+
teardown_callback: Callable | None = None,
|
|
495
|
+
step_type: str | None = None,
|
|
496
|
+
) -> None:
|
|
497
|
+
"""
|
|
498
|
+
Add a step to the tour.
|
|
499
|
+
|
|
500
|
+
Args:
|
|
501
|
+
title: Step title.
|
|
502
|
+
text: Step text.
|
|
503
|
+
widgets: Widgets to be highlighted. If None, no widget is highlighted,
|
|
504
|
+
meaning that the step is probably an introduction or a conclusion.
|
|
505
|
+
setup_callback: Callback function to be called before the step is displayed,
|
|
506
|
+
which takes a single argument, the `DLMainWindow` instance.
|
|
507
|
+
teardown_callback: Callback function to be called after the step is
|
|
508
|
+
displayed, which takes a single argument, the `DLMainWindow` instance.
|
|
509
|
+
step_type: Step type. Can be "regular", "introduction" or "conclusion".
|
|
510
|
+
Defaults to None.
|
|
511
|
+
"""
|
|
512
|
+
if step_type is None:
|
|
513
|
+
if self._steps:
|
|
514
|
+
step_type = "regular"
|
|
515
|
+
else:
|
|
516
|
+
step_type = "introduction"
|
|
517
|
+
step = TourStep(
|
|
518
|
+
self, title, text, widgets, setup_callback, teardown_callback, step_type
|
|
519
|
+
)
|
|
520
|
+
self._steps.append(step)
|
|
521
|
+
|
|
522
|
+
def show_current_step(self) -> None:
|
|
523
|
+
"""
|
|
524
|
+
Show the current step.
|
|
525
|
+
"""
|
|
526
|
+
step = self._steps[self._current_step]
|
|
527
|
+
result = step.show()
|
|
528
|
+
if result is StepResult.PREVIOUS:
|
|
529
|
+
self.previous_step()
|
|
530
|
+
elif result is StepResult.NEXT:
|
|
531
|
+
self.next_step()
|
|
532
|
+
elif result is StepResult.CLOSE:
|
|
533
|
+
self.end()
|
|
534
|
+
elif result is StepResult.DEMO:
|
|
535
|
+
self.end()
|
|
536
|
+
# pylint: disable=import-outside-toplevel
|
|
537
|
+
from datalab.tests.scenarios import demo
|
|
538
|
+
|
|
539
|
+
demo.play_demo(self.win)
|
|
540
|
+
elif result is StepResult.RESTART:
|
|
541
|
+
self.start()
|
|
542
|
+
else:
|
|
543
|
+
raise RuntimeError(f"Unknown result: {result}")
|
|
544
|
+
|
|
545
|
+
def start(self) -> None:
|
|
546
|
+
"""
|
|
547
|
+
Start the tour.
|
|
548
|
+
"""
|
|
549
|
+
self._current_step = 0
|
|
550
|
+
self.show_current_step()
|
|
551
|
+
|
|
552
|
+
def end(self) -> None:
|
|
553
|
+
"""
|
|
554
|
+
End the tour.
|
|
555
|
+
"""
|
|
556
|
+
self.cover.close()
|
|
557
|
+
self.cleanup_tour(self.win)
|
|
558
|
+
self.__restore_window_geometry()
|
|
559
|
+
|
|
560
|
+
def next_step(self) -> None:
|
|
561
|
+
"""
|
|
562
|
+
Go to the next step.
|
|
563
|
+
"""
|
|
564
|
+
if self._current_step == 0 and not self.__window_prepared:
|
|
565
|
+
self.__save_window_geometry()
|
|
566
|
+
self.__resize_window(0.7)
|
|
567
|
+
self.cover.update_geometry()
|
|
568
|
+
self.__window_prepared = True
|
|
569
|
+
self._current_step += 1
|
|
570
|
+
self.show_current_step()
|
|
571
|
+
|
|
572
|
+
def previous_step(self) -> None:
|
|
573
|
+
"""
|
|
574
|
+
Go to the previous step.
|
|
575
|
+
"""
|
|
576
|
+
self._current_step -= 1
|
|
577
|
+
self.show_current_step()
|
|
578
|
+
|
|
579
|
+
|
|
580
|
+
class Tour(BaseTour):
|
|
581
|
+
"""
|
|
582
|
+
Tour of DataLab features.
|
|
583
|
+
|
|
584
|
+
Args:
|
|
585
|
+
win: DataLab main window.
|
|
586
|
+
"""
|
|
587
|
+
|
|
588
|
+
def prepare_signalpanel(self, win: DLMainWindow) -> None:
|
|
589
|
+
"""
|
|
590
|
+
Prepare the signal panel.
|
|
591
|
+
|
|
592
|
+
Args:
|
|
593
|
+
win: DataLab main window.
|
|
594
|
+
"""
|
|
595
|
+
# Create a signal:
|
|
596
|
+
x = np.linspace(0, 10, 100)
|
|
597
|
+
y = np.sin(x)
|
|
598
|
+
sig = create_signal(_("Test signal, for the tour"), x, y)
|
|
599
|
+
win.add_object(sig)
|
|
600
|
+
win.set_current_panel("signal")
|
|
601
|
+
|
|
602
|
+
def prepare_imagepanel(self, win: DLMainWindow) -> None:
|
|
603
|
+
"""
|
|
604
|
+
Prepare the image panel.
|
|
605
|
+
|
|
606
|
+
Args:
|
|
607
|
+
win: DataLab main window.
|
|
608
|
+
"""
|
|
609
|
+
# Create an image:
|
|
610
|
+
x = np.linspace(0, 10, 100)
|
|
611
|
+
y = np.linspace(0, 10, 100)
|
|
612
|
+
xx, yy = np.meshgrid(x, y)
|
|
613
|
+
zz = np.sin(xx) * np.cos(yy)
|
|
614
|
+
img = create_image(_("Test image, for the tour"), zz)
|
|
615
|
+
win.add_object(img)
|
|
616
|
+
win.set_current_panel("image")
|
|
617
|
+
|
|
618
|
+
def popup_menu(self, win: DLMainWindow, menu: QW.QMenu) -> None:
|
|
619
|
+
"""
|
|
620
|
+
Popup a menu.
|
|
621
|
+
|
|
622
|
+
Args:
|
|
623
|
+
win: DataLab main window.
|
|
624
|
+
menu_name: Name of the menu to popup.
|
|
625
|
+
"""
|
|
626
|
+
menu.popup(win.mapToGlobal(QC.QPoint(50, 50)))
|
|
627
|
+
|
|
628
|
+
def cleanup_tour(self, win: DLMainWindow) -> None:
|
|
629
|
+
"""
|
|
630
|
+
Cleanup the tour.
|
|
631
|
+
|
|
632
|
+
Args:
|
|
633
|
+
win: DataLab main window.
|
|
634
|
+
"""
|
|
635
|
+
if len(win.signalpanel.objmodel) == 1:
|
|
636
|
+
win.signalpanel.remove_all_objects()
|
|
637
|
+
else:
|
|
638
|
+
win.signalpanel.remove_object()
|
|
639
|
+
if len(win.imagepanel.objmodel) == 1:
|
|
640
|
+
win.imagepanel.remove_all_objects()
|
|
641
|
+
else:
|
|
642
|
+
win.imagepanel.remove_object()
|
|
643
|
+
|
|
644
|
+
def setup_tour(self, win: DLMainWindow) -> None:
|
|
645
|
+
"""
|
|
646
|
+
Setup the tour: add steps to the tour.
|
|
647
|
+
"""
|
|
648
|
+
self.add_step(
|
|
649
|
+
_("Welcome to DataLab!"),
|
|
650
|
+
_("This tour will guide you through the main features of DataLab."),
|
|
651
|
+
)
|
|
652
|
+
self.add_step(
|
|
653
|
+
_("DataLab main window"),
|
|
654
|
+
_(
|
|
655
|
+
"This is the main window of DataLab. It is composed of several parts "
|
|
656
|
+
"that we will describe in the following steps."
|
|
657
|
+
),
|
|
658
|
+
)
|
|
659
|
+
self.add_step(
|
|
660
|
+
_("DataLab main window"),
|
|
661
|
+
_(
|
|
662
|
+
"Menus and toolbars regroup the main actions that can be performed "
|
|
663
|
+
"in DataLab. Their content is adapted to the current panel, as we "
|
|
664
|
+
"will see in the following steps."
|
|
665
|
+
),
|
|
666
|
+
[
|
|
667
|
+
win.menuBar(),
|
|
668
|
+
win.main_toolbar,
|
|
669
|
+
win.signalpanel_toolbar,
|
|
670
|
+
win.imagepanel_toolbar,
|
|
671
|
+
win.signalpanel.acthandler.view_toolbar,
|
|
672
|
+
win.imagepanel.acthandler.view_toolbar,
|
|
673
|
+
],
|
|
674
|
+
)
|
|
675
|
+
self.add_step(
|
|
676
|
+
_("DataLab main window"),
|
|
677
|
+
_(
|
|
678
|
+
"The main window is composed of two main panels: the Signal Panel, "
|
|
679
|
+
"and the Image Panel.<br>"
|
|
680
|
+
"Switching between panels is done using the highlighted tabs."
|
|
681
|
+
),
|
|
682
|
+
[win.tabwidget.tabBar()],
|
|
683
|
+
)
|
|
684
|
+
self.add_step(
|
|
685
|
+
_("Signal Panel"),
|
|
686
|
+
_(
|
|
687
|
+
"The <b>Signal Panel</b> is used to manage 1D signals."
|
|
688
|
+
"It is composed of the elements shown in the following steps."
|
|
689
|
+
),
|
|
690
|
+
)
|
|
691
|
+
self.add_step(
|
|
692
|
+
_("Signal Panel") + " – " + _("List and properties"),
|
|
693
|
+
_(
|
|
694
|
+
"In the highlighted area, signals are listed at the top, and their "
|
|
695
|
+
"properties may be displayed and edited at the bottom.<br><br>"
|
|
696
|
+
"Signals are numbered (but may be reorganized) and put together in "
|
|
697
|
+
"numbered groups."
|
|
698
|
+
),
|
|
699
|
+
[win.tabwidget.tabBar(), win.signalpanel],
|
|
700
|
+
self.prepare_signalpanel,
|
|
701
|
+
)
|
|
702
|
+
self.add_step(
|
|
703
|
+
_("Signal Panel") + " – " + _("View"),
|
|
704
|
+
_(
|
|
705
|
+
"Signals are plotted in the <b>Signal View</b>.<br><br>"
|
|
706
|
+
"Curves may be customized using context menus or the vertical "
|
|
707
|
+
"toolbar on the left (appearance settings are saved in the "
|
|
708
|
+
"signal metadata)."
|
|
709
|
+
),
|
|
710
|
+
[win.docks[win.signalpanel]],
|
|
711
|
+
)
|
|
712
|
+
self.add_step(
|
|
713
|
+
_("Signal Panel") + " – " + _("File menu"),
|
|
714
|
+
_(
|
|
715
|
+
"The <b>File</b> menu contains actions to "
|
|
716
|
+
"import and export signals individually (various formats) or "
|
|
717
|
+
"to save or restore the whole workspace (HDF5 files)."
|
|
718
|
+
),
|
|
719
|
+
[win.menuBar()],
|
|
720
|
+
lambda win: self.popup_menu(win, win.file_menu),
|
|
721
|
+
lambda win: win.file_menu.hide(),
|
|
722
|
+
)
|
|
723
|
+
self.add_step(
|
|
724
|
+
_("Signal Panel") + " – " + _("Create menu"),
|
|
725
|
+
_(
|
|
726
|
+
"The <b>Create</b> menu contains actions to create new signals "
|
|
727
|
+
"from various models (Gaussian, sine, etc.)."
|
|
728
|
+
),
|
|
729
|
+
[win.menuBar()],
|
|
730
|
+
lambda win: self.popup_menu(win, win.create_menu),
|
|
731
|
+
lambda win: win.create_menu.hide(),
|
|
732
|
+
)
|
|
733
|
+
self.add_step(
|
|
734
|
+
_("Signal Panel") + " – " + _("Edit menu"),
|
|
735
|
+
_(
|
|
736
|
+
"The <b>Edit</b> menu contains actions to edit signals individually "
|
|
737
|
+
"or in groups."
|
|
738
|
+
),
|
|
739
|
+
[win.menuBar()],
|
|
740
|
+
lambda win: self.popup_menu(win, win.edit_menu),
|
|
741
|
+
lambda win: win.edit_menu.hide(),
|
|
742
|
+
)
|
|
743
|
+
self.add_step(
|
|
744
|
+
_("Signal Panel") + " – " + _("Operations menu"),
|
|
745
|
+
_(
|
|
746
|
+
"The <b>Operations</b> menu is focused on arithmetic operations, "
|
|
747
|
+
"basic mathematical functions or data type conversions."
|
|
748
|
+
),
|
|
749
|
+
[win.menuBar()],
|
|
750
|
+
lambda win: self.popup_menu(win, win.operation_menu),
|
|
751
|
+
lambda win: win.operation_menu.hide(),
|
|
752
|
+
)
|
|
753
|
+
self.add_step(
|
|
754
|
+
_("Signal Panel") + " – " + _("Processing menu"),
|
|
755
|
+
_("The <b>Processing</b> menu regroups 1->1 signal processing actions."),
|
|
756
|
+
[win.menuBar()],
|
|
757
|
+
lambda win: self.popup_menu(win, win.processing_menu),
|
|
758
|
+
lambda win: win.processing_menu.hide(),
|
|
759
|
+
)
|
|
760
|
+
self.add_step(
|
|
761
|
+
_("Signal Panel") + " – " + _("Analysis menu"),
|
|
762
|
+
_(
|
|
763
|
+
"The <b>Analysis</b> menu regroups 1->0 signal computing actions "
|
|
764
|
+
"(that is, actions that do not modify the signals, but compute "
|
|
765
|
+
"a result, e.g. scalar values), with optional ROI selection."
|
|
766
|
+
),
|
|
767
|
+
[win.menuBar()],
|
|
768
|
+
lambda win: self.popup_menu(win, win.analysis_menu),
|
|
769
|
+
lambda win: win.analysis_menu.hide(),
|
|
770
|
+
)
|
|
771
|
+
self.add_step(
|
|
772
|
+
_("Image Panel"),
|
|
773
|
+
_(
|
|
774
|
+
"The <b>Image Panel</b> is used to manage 2D images. It is composed "
|
|
775
|
+
"of the elements shown in the following steps."
|
|
776
|
+
),
|
|
777
|
+
[],
|
|
778
|
+
lambda win: win.set_current_panel("image"),
|
|
779
|
+
)
|
|
780
|
+
self.add_step(
|
|
781
|
+
_("Image Panel") + " – " + _("List and properties"),
|
|
782
|
+
_(
|
|
783
|
+
"In the highlighted area, images are listed at the top, and their "
|
|
784
|
+
"properties may be displayed and edited at the bottom.<br><br>"
|
|
785
|
+
"Images are numbered (but may be reorganized) and put together in "
|
|
786
|
+
"numbered groups."
|
|
787
|
+
),
|
|
788
|
+
[win.tabwidget.tabBar(), win.imagepanel],
|
|
789
|
+
self.prepare_imagepanel,
|
|
790
|
+
)
|
|
791
|
+
self.add_step(
|
|
792
|
+
_("Image Panel") + " – " + _("View"),
|
|
793
|
+
_(
|
|
794
|
+
"Images are shown in the <b>Image View</b>.<br><br>"
|
|
795
|
+
"The displayed images may be customized using context menus "
|
|
796
|
+
"or the vertical toolbar on the left (appearance settings "
|
|
797
|
+
"are saved in the image metadata)."
|
|
798
|
+
),
|
|
799
|
+
[win.docks[win.imagepanel]],
|
|
800
|
+
)
|
|
801
|
+
self.add_step(
|
|
802
|
+
_("Image Panel") + " – " + _("File menu"),
|
|
803
|
+
_(
|
|
804
|
+
"The <b>File</b> menu contains actions to "
|
|
805
|
+
"import and export images individually (various formats) or "
|
|
806
|
+
"to save or restore the whole workspace (HDF5 files)."
|
|
807
|
+
),
|
|
808
|
+
[win.menuBar()],
|
|
809
|
+
lambda win: self.popup_menu(win, win.file_menu),
|
|
810
|
+
lambda win: win.file_menu.hide(),
|
|
811
|
+
)
|
|
812
|
+
self.add_step(
|
|
813
|
+
_("Image Panel") + " – " + _("Create menu"),
|
|
814
|
+
_(
|
|
815
|
+
"The <b>Create</b> menu contains actions to create new images "
|
|
816
|
+
"from various models (Gaussian, checkerboard, etc.)."
|
|
817
|
+
),
|
|
818
|
+
[win.menuBar()],
|
|
819
|
+
lambda win: self.popup_menu(win, win.create_menu),
|
|
820
|
+
lambda win: win.create_menu.hide(),
|
|
821
|
+
)
|
|
822
|
+
self.add_step(
|
|
823
|
+
_("Image Panel") + " – " + _("Edit menu"),
|
|
824
|
+
_(
|
|
825
|
+
"The <b>Edit</b> menu contains actions to edit images individually "
|
|
826
|
+
"or in groups."
|
|
827
|
+
),
|
|
828
|
+
[win.menuBar()],
|
|
829
|
+
lambda win: self.popup_menu(win, win.edit_menu),
|
|
830
|
+
lambda win: win.edit_menu.hide(),
|
|
831
|
+
)
|
|
832
|
+
self.add_step(
|
|
833
|
+
_("Image Panel") + " – " + _("Operations menu"),
|
|
834
|
+
_(
|
|
835
|
+
"The <b>Operations</b> menu is focused on arithmetic operations, "
|
|
836
|
+
"data type conversions, pixel binning resize, intensity profiles..."
|
|
837
|
+
),
|
|
838
|
+
[win.menuBar()],
|
|
839
|
+
lambda win: self.popup_menu(win, win.operation_menu),
|
|
840
|
+
lambda win: win.operation_menu.hide(),
|
|
841
|
+
)
|
|
842
|
+
self.add_step(
|
|
843
|
+
_("Image Panel") + " – " + _("Processing menu"),
|
|
844
|
+
_(
|
|
845
|
+
"The <b>Processing</b> menu regroups 1->1 image processing actions "
|
|
846
|
+
"(that is, actions that modify the images)."
|
|
847
|
+
),
|
|
848
|
+
[win.menuBar()],
|
|
849
|
+
lambda win: self.popup_menu(win, win.processing_menu),
|
|
850
|
+
lambda win: win.processing_menu.hide(),
|
|
851
|
+
)
|
|
852
|
+
self.add_step(
|
|
853
|
+
_("Image Panel") + " – " + _("Analysis menu"),
|
|
854
|
+
_(
|
|
855
|
+
"The <b>Analysis</b> menu regroups 1->0 image computing actions "
|
|
856
|
+
"(that is, actions that do not modify the images, but compute "
|
|
857
|
+
"a result, e.g. circle coordinates), with optional ROI selection."
|
|
858
|
+
),
|
|
859
|
+
[win.menuBar()],
|
|
860
|
+
lambda win: self.popup_menu(win, win.analysis_menu),
|
|
861
|
+
lambda win: win.analysis_menu.hide(),
|
|
862
|
+
)
|
|
863
|
+
self.add_step(
|
|
864
|
+
_("Extensions"),
|
|
865
|
+
_(
|
|
866
|
+
"DataLab is designed to be easily extended with new features, "
|
|
867
|
+
"by using <b>Macros</b>, <b>Plugins</b> or <b>Remote Control</b>."
|
|
868
|
+
"<br><br>The common point between these mechanisms is that "
|
|
869
|
+
"they are all relying on Python scripts and the <i>DataLab API</i>."
|
|
870
|
+
),
|
|
871
|
+
)
|
|
872
|
+
self.add_step(
|
|
873
|
+
_("Extensions") + " – " + _("Macros"),
|
|
874
|
+
_(
|
|
875
|
+
"The <b>Macro Panel</b> allows to create, edit and run macros.<br>"
|
|
876
|
+
"Macros are saved together with the DataLab workspace (HDF5 file)."
|
|
877
|
+
),
|
|
878
|
+
[win.docks[win.macropanel]],
|
|
879
|
+
lambda win: win.set_current_panel("macro"),
|
|
880
|
+
lambda win: win.set_current_panel("signal"),
|
|
881
|
+
)
|
|
882
|
+
self.add_step(
|
|
883
|
+
_("Extensions") + " – " + _("Plugins"),
|
|
884
|
+
_(
|
|
885
|
+
"The <b>Plugins</b> menu regroups features that are not part of "
|
|
886
|
+
"the core of DataLab, but that are provided as plugins.<br>"
|
|
887
|
+
"(See the documentation for more information about plugins.)"
|
|
888
|
+
),
|
|
889
|
+
[win.menuBar()],
|
|
890
|
+
lambda win: self.popup_menu(win, win.plugins_menu),
|
|
891
|
+
lambda win: win.plugins_menu.hide(),
|
|
892
|
+
)
|
|
893
|
+
self.add_step(
|
|
894
|
+
_("This is the end of the tour!"),
|
|
895
|
+
_("You can show the tour again, or close this dialog box."),
|
|
896
|
+
step_type="conclusion",
|
|
897
|
+
)
|
|
898
|
+
|
|
899
|
+
|
|
900
|
+
def start(win: DLMainWindow) -> None:
|
|
901
|
+
"""
|
|
902
|
+
Start the tour of DataLab features.
|
|
903
|
+
|
|
904
|
+
Args:
|
|
905
|
+
win: DataLab main window.
|
|
906
|
+
"""
|
|
907
|
+
tour = Tour(win)
|
|
908
|
+
tour.start()
|