datalab-platform 0.0.1.dev0__py3-none-any.whl → 1.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- datalab/__init__.py +35 -2
- datalab/adapters_metadata/__init__.py +31 -0
- datalab/adapters_metadata/base_adapter.py +316 -0
- datalab/adapters_metadata/common.py +422 -0
- datalab/adapters_metadata/geometry_adapter.py +98 -0
- datalab/adapters_metadata/table_adapter.py +84 -0
- datalab/adapters_plotpy/__init__.py +54 -0
- datalab/adapters_plotpy/annotations.py +124 -0
- datalab/adapters_plotpy/base.py +110 -0
- datalab/adapters_plotpy/converters.py +86 -0
- datalab/adapters_plotpy/factories.py +80 -0
- datalab/adapters_plotpy/objects/__init__.py +0 -0
- datalab/adapters_plotpy/objects/base.py +197 -0
- datalab/adapters_plotpy/objects/image.py +157 -0
- datalab/adapters_plotpy/objects/scalar.py +565 -0
- datalab/adapters_plotpy/objects/signal.py +264 -0
- datalab/adapters_plotpy/roi/__init__.py +0 -0
- datalab/adapters_plotpy/roi/base.py +146 -0
- datalab/adapters_plotpy/roi/factory.py +93 -0
- datalab/adapters_plotpy/roi/image.py +207 -0
- datalab/adapters_plotpy/roi/signal.py +72 -0
- datalab/app.py +98 -0
- datalab/config.py +817 -0
- datalab/control/__init__.py +0 -0
- datalab/control/baseproxy.py +776 -0
- datalab/control/proxy.py +343 -0
- datalab/control/remote.py +1005 -0
- datalab/data/doc/DataLab_en.pdf +0 -0
- datalab/data/doc/DataLab_fr.pdf +0 -0
- datalab/data/icons/analysis/delete_results.svg +109 -0
- datalab/data/icons/analysis/fw1e2.svg +156 -0
- datalab/data/icons/analysis/fwhm.svg +156 -0
- datalab/data/icons/analysis/histogram.svg +49 -0
- datalab/data/icons/analysis/peak_detect.svg +160 -0
- datalab/data/icons/analysis/plot_results.svg +151 -0
- datalab/data/icons/analysis/show_results.svg +83 -0
- datalab/data/icons/analysis/stats.svg +49 -0
- datalab/data/icons/analysis.svg +120 -0
- datalab/data/icons/apply.svg +3 -0
- datalab/data/icons/check_all.svg +15 -0
- datalab/data/icons/collapse.svg +44 -0
- datalab/data/icons/collapse_selection.svg +63 -0
- datalab/data/icons/console.svg +101 -0
- datalab/data/icons/create/1d-normal.svg +8 -0
- datalab/data/icons/create/1d-poisson.svg +9 -0
- datalab/data/icons/create/1d-uniform.svg +8 -0
- datalab/data/icons/create/1d-zero.svg +57 -0
- datalab/data/icons/create/2d-gaussian.svg +56 -0
- datalab/data/icons/create/2d-normal.svg +38 -0
- datalab/data/icons/create/2d-poisson.svg +38 -0
- datalab/data/icons/create/2d-ramp.svg +90 -0
- datalab/data/icons/create/2d-sinc.svg +62 -0
- datalab/data/icons/create/2d-uniform.svg +38 -0
- datalab/data/icons/create/2d-zero.svg +13 -0
- datalab/data/icons/create/checkerboard.svg +39 -0
- datalab/data/icons/create/cosine.svg +12 -0
- datalab/data/icons/create/exponential.svg +55 -0
- datalab/data/icons/create/gaussian.svg +12 -0
- datalab/data/icons/create/grating.svg +29 -0
- datalab/data/icons/create/linear_chirp.svg +7 -0
- datalab/data/icons/create/logistic.svg +7 -0
- datalab/data/icons/create/lorentzian.svg +12 -0
- datalab/data/icons/create/planck.svg +12 -0
- datalab/data/icons/create/polynomial.svg +7 -0
- datalab/data/icons/create/pulse.svg +12 -0
- datalab/data/icons/create/ring.svg +18 -0
- datalab/data/icons/create/sawtooth.svg +7 -0
- datalab/data/icons/create/siemens.svg +35 -0
- datalab/data/icons/create/sinc.svg +12 -0
- datalab/data/icons/create/sine.svg +7 -0
- datalab/data/icons/create/square.svg +7 -0
- datalab/data/icons/create/square_pulse.svg +7 -0
- datalab/data/icons/create/step.svg +7 -0
- datalab/data/icons/create/step_pulse.svg +12 -0
- datalab/data/icons/create/triangle.svg +7 -0
- datalab/data/icons/create/voigt.svg +12 -0
- datalab/data/icons/edit/annotations.svg +72 -0
- datalab/data/icons/edit/annotations_copy.svg +114 -0
- datalab/data/icons/edit/annotations_delete.svg +83 -0
- datalab/data/icons/edit/annotations_edit.svg +98 -0
- datalab/data/icons/edit/annotations_export.svg +85 -0
- datalab/data/icons/edit/annotations_import.svg +85 -0
- datalab/data/icons/edit/annotations_paste.svg +100 -0
- datalab/data/icons/edit/copy_titles.svg +109 -0
- datalab/data/icons/edit/delete.svg +84 -0
- datalab/data/icons/edit/delete_all.svg +214 -0
- datalab/data/icons/edit/duplicate.svg +64 -0
- datalab/data/icons/edit/goto_source.svg +60 -0
- datalab/data/icons/edit/metadata.svg +60 -0
- datalab/data/icons/edit/metadata_add.svg +80 -0
- datalab/data/icons/edit/metadata_copy.svg +96 -0
- datalab/data/icons/edit/metadata_delete.svg +62 -0
- datalab/data/icons/edit/metadata_export.svg +68 -0
- datalab/data/icons/edit/metadata_import.svg +68 -0
- datalab/data/icons/edit/metadata_paste.svg +79 -0
- datalab/data/icons/edit/move_down.svg +55 -0
- datalab/data/icons/edit/move_up.svg +54 -0
- datalab/data/icons/edit/new_group.svg +76 -0
- datalab/data/icons/edit/recompute.svg +60 -0
- datalab/data/icons/edit/rename.svg +49 -0
- datalab/data/icons/edit.svg +16 -0
- datalab/data/icons/expand.svg +44 -0
- datalab/data/icons/expand_selection.svg +63 -0
- datalab/data/icons/fit/cdf_fit.svg +56 -0
- datalab/data/icons/fit/exponential_fit.svg +55 -0
- datalab/data/icons/fit/gaussian_fit.svg +62 -0
- datalab/data/icons/fit/interactive_fit.svg +101 -0
- datalab/data/icons/fit/linear_fit.svg +57 -0
- datalab/data/icons/fit/lorentzian_fit.svg +209 -0
- datalab/data/icons/fit/multigaussian_fit.svg +85 -0
- datalab/data/icons/fit/multilorentzian_fit.svg +85 -0
- datalab/data/icons/fit/piecewiseexponential_fit.svg +209 -0
- datalab/data/icons/fit/planckian_fit.svg +62 -0
- datalab/data/icons/fit/polynomial_fit.svg +59 -0
- datalab/data/icons/fit/sigmoid_fit.svg +56 -0
- datalab/data/icons/fit/sinusoidal_fit.svg +72 -0
- datalab/data/icons/fit/twohalfgaussian_fit.svg +63 -0
- datalab/data/icons/fit/voigt_fit.svg +57 -0
- datalab/data/icons/group.svg +56 -0
- datalab/data/icons/h5/h5array.svg +59 -0
- datalab/data/icons/h5/h5attrs.svg +75 -0
- datalab/data/icons/h5/h5browser.svg +133 -0
- datalab/data/icons/h5/h5file.svg +69 -0
- datalab/data/icons/h5/h5group.svg +49 -0
- datalab/data/icons/h5/h5scalar.svg +1 -0
- datalab/data/icons/help_pdf.svg +46 -0
- datalab/data/icons/history.svg +7 -0
- datalab/data/icons/image.svg +135 -0
- datalab/data/icons/io/fileopen_directory.svg +60 -0
- datalab/data/icons/io/fileopen_h5.svg +84 -0
- datalab/data/icons/io/fileopen_ima.svg +187 -0
- datalab/data/icons/io/fileopen_py.svg +123 -0
- datalab/data/icons/io/fileopen_sig.svg +138 -0
- datalab/data/icons/io/filesave_h5.svg +97 -0
- datalab/data/icons/io/filesave_ima.svg +200 -0
- datalab/data/icons/io/filesave_py.svg +136 -0
- datalab/data/icons/io/filesave_sig.svg +151 -0
- datalab/data/icons/io/import_text.svg +144 -0
- datalab/data/icons/io/save_to_directory.svg +134 -0
- datalab/data/icons/io.svg +84 -0
- datalab/data/icons/libre-camera-flash-off.svg +1 -0
- datalab/data/icons/libre-camera-flash-on.svg +1 -0
- datalab/data/icons/libre-gui-about.svg +1 -0
- datalab/data/icons/libre-gui-action-delete.svg +1 -0
- datalab/data/icons/libre-gui-add.svg +1 -0
- datalab/data/icons/libre-gui-arrow-down.svg +1 -0
- datalab/data/icons/libre-gui-arrow-left.svg +1 -0
- datalab/data/icons/libre-gui-arrow-right.svg +1 -0
- datalab/data/icons/libre-gui-arrow-up.svg +1 -0
- datalab/data/icons/libre-gui-close.svg +40 -0
- datalab/data/icons/libre-gui-cogs.svg +1 -0
- datalab/data/icons/libre-gui-globe.svg +1 -0
- datalab/data/icons/libre-gui-help.svg +1 -0
- datalab/data/icons/libre-gui-link.svg +1 -0
- datalab/data/icons/libre-gui-menu.svg +1 -0
- datalab/data/icons/libre-gui-pencil.svg +1 -0
- datalab/data/icons/libre-gui-plugin.svg +1 -0
- datalab/data/icons/libre-gui-questions.svg +1 -0
- datalab/data/icons/libre-gui-settings.svg +1 -0
- datalab/data/icons/libre-gui-unlink.svg +1 -0
- datalab/data/icons/libre-tech-ram.svg +1 -0
- datalab/data/icons/libre-toolbox.svg +1 -0
- datalab/data/icons/logs.svg +1 -0
- datalab/data/icons/markers.svg +74 -0
- datalab/data/icons/menu.svg +13 -0
- datalab/data/icons/new_ima.svg +148 -0
- datalab/data/icons/new_sig.svg +123 -0
- datalab/data/icons/operations/abs.svg +116 -0
- datalab/data/icons/operations/arithmetic.svg +123 -0
- datalab/data/icons/operations/average.svg +124 -0
- datalab/data/icons/operations/complex_from_magnitude_phase.svg +116 -0
- datalab/data/icons/operations/complex_from_real_imag.svg +124 -0
- datalab/data/icons/operations/constant.svg +116 -0
- datalab/data/icons/operations/constant_add.svg +109 -0
- datalab/data/icons/operations/constant_divide.svg +109 -0
- datalab/data/icons/operations/constant_multiply.svg +109 -0
- datalab/data/icons/operations/constant_subtract.svg +109 -0
- datalab/data/icons/operations/convert_dtype.svg +117 -0
- datalab/data/icons/operations/convolution.svg +46 -0
- datalab/data/icons/operations/deconvolution.svg +57 -0
- datalab/data/icons/operations/derivative.svg +127 -0
- datalab/data/icons/operations/difference.svg +52 -0
- datalab/data/icons/operations/division.svg +139 -0
- datalab/data/icons/operations/exp.svg +116 -0
- datalab/data/icons/operations/flip_horizontally.svg +69 -0
- datalab/data/icons/operations/flip_vertically.svg +74 -0
- datalab/data/icons/operations/im.svg +124 -0
- datalab/data/icons/operations/integral.svg +50 -0
- datalab/data/icons/operations/inverse.svg +143 -0
- datalab/data/icons/operations/log10.svg +109 -0
- datalab/data/icons/operations/phase.svg +116 -0
- datalab/data/icons/operations/power.svg +118 -0
- datalab/data/icons/operations/product.svg +124 -0
- datalab/data/icons/operations/profile.svg +379 -0
- datalab/data/icons/operations/profile_average.svg +399 -0
- datalab/data/icons/operations/profile_radial.svg +261 -0
- datalab/data/icons/operations/profile_segment.svg +262 -0
- datalab/data/icons/operations/quadratic_difference.svg +84 -0
- datalab/data/icons/operations/re.svg +124 -0
- datalab/data/icons/operations/rotate_left.svg +72 -0
- datalab/data/icons/operations/rotate_right.svg +72 -0
- datalab/data/icons/operations/signals_to_image.svg +314 -0
- datalab/data/icons/operations/sqrt.svg +110 -0
- datalab/data/icons/operations/std.svg +124 -0
- datalab/data/icons/operations/sum.svg +102 -0
- datalab/data/icons/play_demo.svg +9 -0
- datalab/data/icons/processing/axis_transform.svg +62 -0
- datalab/data/icons/processing/bandpass.svg +79 -0
- datalab/data/icons/processing/bandstop.svg +71 -0
- datalab/data/icons/processing/binning.svg +126 -0
- datalab/data/icons/processing/clip.svg +119 -0
- datalab/data/icons/processing/detrending.svg +173 -0
- datalab/data/icons/processing/distribute_on_grid.svg +769 -0
- datalab/data/icons/processing/edge_detection.svg +46 -0
- datalab/data/icons/processing/erase.svg +1 -0
- datalab/data/icons/processing/exposure.svg +143 -0
- datalab/data/icons/processing/fourier.svg +104 -0
- datalab/data/icons/processing/highpass.svg +59 -0
- datalab/data/icons/processing/interpolation.svg +71 -0
- datalab/data/icons/processing/level_adjustment.svg +70 -0
- datalab/data/icons/processing/lowpass.svg +60 -0
- datalab/data/icons/processing/morphology.svg +49 -0
- datalab/data/icons/processing/noise_addition.svg +114 -0
- datalab/data/icons/processing/noise_reduction.svg +38 -0
- datalab/data/icons/processing/normalize.svg +84 -0
- datalab/data/icons/processing/offset_correction.svg +131 -0
- datalab/data/icons/processing/resampling1d.svg +101 -0
- datalab/data/icons/processing/resampling2d.svg +240 -0
- datalab/data/icons/processing/reset_positions.svg +185 -0
- datalab/data/icons/processing/resize.svg +9 -0
- datalab/data/icons/processing/reverse_signal_x.svg +171 -0
- datalab/data/icons/processing/stability.svg +11 -0
- datalab/data/icons/processing/swap_x_y.svg +65 -0
- datalab/data/icons/processing/thresholding.svg +63 -0
- datalab/data/icons/processing/windowing.svg +45 -0
- datalab/data/icons/properties.svg +26 -0
- datalab/data/icons/reset.svg +9 -0
- datalab/data/icons/restore.svg +40 -0
- datalab/data/icons/roi/roi.svg +76 -0
- datalab/data/icons/roi/roi_coordinate.svg +78 -0
- datalab/data/icons/roi/roi_copy.svg +112 -0
- datalab/data/icons/roi/roi_delete.svg +81 -0
- datalab/data/icons/roi/roi_export.svg +87 -0
- datalab/data/icons/roi/roi_graphical.svg +78 -0
- datalab/data/icons/roi/roi_grid.svg +67 -0
- datalab/data/icons/roi/roi_ima.svg +188 -0
- datalab/data/icons/roi/roi_import.svg +87 -0
- datalab/data/icons/roi/roi_new.svg +81 -0
- datalab/data/icons/roi/roi_new_circle.svg +95 -0
- datalab/data/icons/roi/roi_new_polygon.svg +110 -0
- datalab/data/icons/roi/roi_new_rectangle.svg +70 -0
- datalab/data/icons/roi/roi_paste.svg +98 -0
- datalab/data/icons/roi/roi_sig.svg +124 -0
- datalab/data/icons/shapes.svg +134 -0
- datalab/data/icons/signal.svg +103 -0
- datalab/data/icons/table.svg +85 -0
- datalab/data/icons/table_unavailable.svg +102 -0
- datalab/data/icons/to_signal.svg +124 -0
- datalab/data/icons/tour/next.svg +44 -0
- datalab/data/icons/tour/previous.svg +44 -0
- datalab/data/icons/tour/rewind.svg +51 -0
- datalab/data/icons/tour/stop.svg +47 -0
- datalab/data/icons/tour/tour.svg +16 -0
- datalab/data/icons/uncheck_all.svg +78 -0
- datalab/data/icons/view/curve_antialiasing.svg +50 -0
- datalab/data/icons/view/new_window.svg +98 -0
- datalab/data/icons/view/refresh-auto.svg +57 -0
- datalab/data/icons/view/refresh-manual.svg +51 -0
- datalab/data/icons/view/reset_curve_styles.svg +96 -0
- datalab/data/icons/view/show_first.svg +55 -0
- datalab/data/icons/view/show_titles.svg +46 -0
- datalab/data/icons/visualization.svg +51 -0
- datalab/data/logo/DataLab-Banner-150.png +0 -0
- datalab/data/logo/DataLab-Banner-200.png +0 -0
- datalab/data/logo/DataLab-Banner2-100.png +0 -0
- datalab/data/logo/DataLab-Splash.png +0 -0
- datalab/data/logo/DataLab-watermark.png +0 -0
- datalab/data/logo/DataLab.svg +83 -0
- datalab/data/tests/reordering_test.h5 +0 -0
- datalab/data/tutorials/fabry_perot/fabry-perot1.jpg +0 -0
- datalab/data/tutorials/fabry_perot/fabry-perot2.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_13.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_18.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_23.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_30.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_35.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_40.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_45.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_50.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_55.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_60.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_65.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_70.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_75.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_80.jpg +0 -0
- datalab/env.py +542 -0
- datalab/gui/__init__.py +89 -0
- datalab/gui/actionhandler.py +1701 -0
- datalab/gui/docks.py +473 -0
- datalab/gui/h5io.py +150 -0
- datalab/gui/macroeditor.py +310 -0
- datalab/gui/main.py +2081 -0
- datalab/gui/newobject.py +217 -0
- datalab/gui/objectview.py +766 -0
- datalab/gui/panel/__init__.py +48 -0
- datalab/gui/panel/base.py +3254 -0
- datalab/gui/panel/image.py +157 -0
- datalab/gui/panel/macro.py +607 -0
- datalab/gui/panel/signal.py +164 -0
- datalab/gui/plothandler.py +800 -0
- datalab/gui/processor/__init__.py +84 -0
- datalab/gui/processor/base.py +2456 -0
- datalab/gui/processor/catcher.py +75 -0
- datalab/gui/processor/image.py +1214 -0
- datalab/gui/processor/signal.py +755 -0
- datalab/gui/profiledialog.py +333 -0
- datalab/gui/roieditor.py +633 -0
- datalab/gui/roigrideditor.py +208 -0
- datalab/gui/settings.py +612 -0
- datalab/gui/tour.py +908 -0
- datalab/h5/__init__.py +12 -0
- datalab/h5/common.py +314 -0
- datalab/h5/generic.py +580 -0
- datalab/h5/native.py +39 -0
- datalab/h5/utils.py +95 -0
- datalab/objectmodel.py +640 -0
- datalab/plugins/_readme_.txt +9 -0
- datalab/plugins/datalab_imageformats.py +175 -0
- datalab/plugins/datalab_testdata.py +190 -0
- datalab/plugins.py +355 -0
- datalab/tests/__init__.py +199 -0
- datalab/tests/backbone/__init__.py +1 -0
- datalab/tests/backbone/config_unit_test.py +170 -0
- datalab/tests/backbone/config_versioning_unit_test.py +34 -0
- datalab/tests/backbone/dictlistserial_app_test.py +38 -0
- datalab/tests/backbone/errorcatcher_unit_test.py +69 -0
- datalab/tests/backbone/errormsgbox_unit_test.py +50 -0
- datalab/tests/backbone/execenv_unit.py +262 -0
- datalab/tests/backbone/loadtest_gdi.py +147 -0
- datalab/tests/backbone/long_callback.py +96 -0
- datalab/tests/backbone/main_app_test.py +137 -0
- datalab/tests/backbone/memory_leak.py +43 -0
- datalab/tests/backbone/procisolation1_unit.py +128 -0
- datalab/tests/backbone/procisolation2_unit.py +171 -0
- datalab/tests/backbone/procisolation_unit_test.py +22 -0
- datalab/tests/backbone/profiling_app.py +27 -0
- datalab/tests/backbone/strings_unit_test.py +65 -0
- datalab/tests/backbone/title_formatting_unit_test.py +82 -0
- datalab/tests/conftest.py +131 -0
- datalab/tests/features/__init__.py +1 -0
- datalab/tests/features/applauncher/__init__.py +1 -0
- datalab/tests/features/applauncher/launcher1_app_test.py +28 -0
- datalab/tests/features/applauncher/launcher2_app_test.py +30 -0
- datalab/tests/features/common/__init__.py +1 -0
- datalab/tests/features/common/add_metadata_app_test.py +134 -0
- datalab/tests/features/common/add_metadata_unit_test.py +267 -0
- datalab/tests/features/common/annotations_management_unit_test.py +152 -0
- datalab/tests/features/common/auto_analysis_recompute_unit_test.py +240 -0
- datalab/tests/features/common/createobject_unit_test.py +50 -0
- datalab/tests/features/common/geometry_results_app_test.py +135 -0
- datalab/tests/features/common/interactive_processing_test.py +1109 -0
- datalab/tests/features/common/io_app_test.py +75 -0
- datalab/tests/features/common/large_results_app_test.py +187 -0
- datalab/tests/features/common/metadata_all_patterns_test.py +103 -0
- datalab/tests/features/common/metadata_app_test.py +139 -0
- datalab/tests/features/common/metadata_io_unit_test.py +60 -0
- datalab/tests/features/common/misc_app_test.py +236 -0
- datalab/tests/features/common/multiple_geometry_results_unit_test.py +122 -0
- datalab/tests/features/common/multiple_table_results_unit_test.py +64 -0
- datalab/tests/features/common/operation_modes_app_test.py +392 -0
- datalab/tests/features/common/plot_results_app_test.py +278 -0
- datalab/tests/features/common/reorder_app_test.py +75 -0
- datalab/tests/features/common/result_deletion_unit_test.py +96 -0
- datalab/tests/features/common/result_merged_label_unit_test.py +154 -0
- datalab/tests/features/common/result_shape_settings_unit_test.py +223 -0
- datalab/tests/features/common/roi_plotitem_unit_test.py +64 -0
- datalab/tests/features/common/roieditor_unit_test.py +102 -0
- datalab/tests/features/common/save_to_dir_app_test.py +163 -0
- datalab/tests/features/common/save_to_dir_unit_test.py +474 -0
- datalab/tests/features/common/stat_app_test.py +40 -0
- datalab/tests/features/common/stats_tools_unit_test.py +77 -0
- datalab/tests/features/common/table_results_app_test.py +52 -0
- datalab/tests/features/common/textimport_unit_test.py +131 -0
- datalab/tests/features/common/uuid_preservation_test.py +281 -0
- datalab/tests/features/common/worker_unit_test.py +402 -0
- datalab/tests/features/control/__init__.py +1 -0
- datalab/tests/features/control/connect_dialog.py +28 -0
- datalab/tests/features/control/embedded1_unit_test.py +304 -0
- datalab/tests/features/control/embedded2_unit_test.py +52 -0
- datalab/tests/features/control/remoteclient_app_test.py +219 -0
- datalab/tests/features/control/remoteclient_unit.py +75 -0
- datalab/tests/features/control/simpleclient_unit_test.py +321 -0
- datalab/tests/features/hdf5/__init__.py +1 -0
- datalab/tests/features/hdf5/h5browser1_unit_test.py +31 -0
- datalab/tests/features/hdf5/h5browser2_unit.py +55 -0
- datalab/tests/features/hdf5/h5browser_app_test.py +77 -0
- datalab/tests/features/hdf5/h5import_app_test.py +25 -0
- datalab/tests/features/hdf5/h5importer_app_test.py +34 -0
- datalab/tests/features/image/__init__.py +1 -0
- datalab/tests/features/image/annotations_app_test.py +28 -0
- datalab/tests/features/image/annotations_unit_test.py +80 -0
- datalab/tests/features/image/average_app_test.py +46 -0
- datalab/tests/features/image/background_dialog_test.py +70 -0
- datalab/tests/features/image/blobs_app_test.py +50 -0
- datalab/tests/features/image/contour_app_test.py +42 -0
- datalab/tests/features/image/contour_fabryperot_app_test.py +51 -0
- datalab/tests/features/image/denoise_app_test.py +31 -0
- datalab/tests/features/image/distribute_on_grid_app_test.py +95 -0
- datalab/tests/features/image/edges_app_test.py +31 -0
- datalab/tests/features/image/erase_app_test.py +21 -0
- datalab/tests/features/image/fft2d_app_test.py +27 -0
- datalab/tests/features/image/flatfield_app_test.py +40 -0
- datalab/tests/features/image/geometry_transform_unit_test.py +396 -0
- datalab/tests/features/image/imagetools_app_test.py +51 -0
- datalab/tests/features/image/imagetools_unit_test.py +27 -0
- datalab/tests/features/image/load_app_test.py +73 -0
- datalab/tests/features/image/morph_app_test.py +32 -0
- datalab/tests/features/image/offsetcorrection_app_test.py +30 -0
- datalab/tests/features/image/peak2d_app_test.py +53 -0
- datalab/tests/features/image/profile_app_test.py +73 -0
- datalab/tests/features/image/profile_dialog_test.py +56 -0
- datalab/tests/features/image/roi_app_test.py +98 -0
- datalab/tests/features/image/roi_circ_app_test.py +62 -0
- datalab/tests/features/image/roi_manipulation_app_test.py +268 -0
- datalab/tests/features/image/roigrid_unit_test.py +60 -0
- datalab/tests/features/image/side_by_side_app_test.py +52 -0
- datalab/tests/features/macro/__init__.py +1 -0
- datalab/tests/features/macro/macro_app_test.py +28 -0
- datalab/tests/features/macro/macroeditor_unit_test.py +102 -0
- datalab/tests/features/signal/__init__.py +1 -0
- datalab/tests/features/signal/baseline_dialog_test.py +53 -0
- datalab/tests/features/signal/deltax_dialog_unit_test.py +34 -0
- datalab/tests/features/signal/fft1d_app_test.py +26 -0
- datalab/tests/features/signal/filter_app_test.py +44 -0
- datalab/tests/features/signal/fitdialog_unit_test.py +50 -0
- datalab/tests/features/signal/interpolation_app_test.py +110 -0
- datalab/tests/features/signal/loadbigsignal_app_test.py +80 -0
- datalab/tests/features/signal/multiple_rois_unit_test.py +132 -0
- datalab/tests/features/signal/pulse_features_app_test.py +118 -0
- datalab/tests/features/signal/pulse_features_roi_app_test.py +55 -0
- datalab/tests/features/signal/roi_app_test.py +78 -0
- datalab/tests/features/signal/roi_manipulation_app_test.py +261 -0
- datalab/tests/features/signal/select_xy_cursor_unit_test.py +46 -0
- datalab/tests/features/signal/signalpeakdetection_dialog_test.py +33 -0
- datalab/tests/features/signal/signals_to_image_app_test.py +98 -0
- datalab/tests/features/signal/xarray_compat_app_test.py +128 -0
- datalab/tests/features/tour_unit_test.py +22 -0
- datalab/tests/features/utilities/__init__.py +1 -0
- datalab/tests/features/utilities/installconf_unit_test.py +21 -0
- datalab/tests/features/utilities/logview_app_test.py +21 -0
- datalab/tests/features/utilities/logview_error.py +24 -0
- datalab/tests/features/utilities/logview_unit_test.py +21 -0
- datalab/tests/features/utilities/memstatus_app_test.py +42 -0
- datalab/tests/features/utilities/settings_unit_test.py +88 -0
- datalab/tests/scenarios/__init__.py +1 -0
- datalab/tests/scenarios/beautiful_app.py +121 -0
- datalab/tests/scenarios/common.py +463 -0
- datalab/tests/scenarios/demo.py +212 -0
- datalab/tests/scenarios/example_app_test.py +47 -0
- datalab/tests/scenarios/scenario_h5_app_test.py +75 -0
- datalab/tests/scenarios/scenario_ima1_app_test.py +34 -0
- datalab/tests/scenarios/scenario_ima2_app_test.py +34 -0
- datalab/tests/scenarios/scenario_mac_app_test.py +58 -0
- datalab/tests/scenarios/scenario_sig1_app_test.py +36 -0
- datalab/tests/scenarios/scenario_sig2_app_test.py +35 -0
- datalab/utils/__init__.py +1 -0
- datalab/utils/conf.py +304 -0
- datalab/utils/dephash.py +105 -0
- datalab/utils/qthelpers.py +633 -0
- datalab/utils/strings.py +34 -0
- datalab/utils/tests.py +0 -0
- datalab/widgets/__init__.py +1 -0
- datalab/widgets/connection.py +138 -0
- datalab/widgets/filedialog.py +91 -0
- datalab/widgets/fileviewer.py +84 -0
- datalab/widgets/fitdialog.py +788 -0
- datalab/widgets/h5browser.py +1048 -0
- datalab/widgets/imagebackground.py +111 -0
- datalab/widgets/instconfviewer.py +175 -0
- datalab/widgets/logviewer.py +80 -0
- datalab/widgets/signalbaseline.py +90 -0
- datalab/widgets/signalcursor.py +208 -0
- datalab/widgets/signaldeltax.py +151 -0
- datalab/widgets/signalpeak.py +199 -0
- datalab/widgets/status.py +249 -0
- datalab/widgets/textimport.py +786 -0
- datalab/widgets/warningerror.py +223 -0
- datalab/widgets/wizard.py +286 -0
- datalab_platform-1.0.1.dist-info/METADATA +121 -0
- datalab_platform-1.0.1.dist-info/RECORD +494 -0
- datalab_platform-0.0.1.dev0.dist-info/METADATA +0 -67
- datalab_platform-0.0.1.dev0.dist-info/RECORD +0 -7
- {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.1.dist-info}/WHEEL +0 -0
- {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.1.dist-info}/entry_points.txt +0 -0
- {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.1.dist-info}/licenses/LICENSE +0 -0
- {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
|
|
2
|
+
|
|
3
|
+
"""Image background selection dialog."""
|
|
4
|
+
|
|
5
|
+
# pylint: disable=invalid-name # Allows short reference names like x, y, ...
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import TYPE_CHECKING
|
|
10
|
+
|
|
11
|
+
import numpy as np
|
|
12
|
+
from guidata.configtools import get_icon
|
|
13
|
+
from plotpy.builder import make
|
|
14
|
+
from plotpy.plot import PlotDialog
|
|
15
|
+
|
|
16
|
+
from datalab.adapters_plotpy import create_adapter_from_object
|
|
17
|
+
from datalab.config import _
|
|
18
|
+
from datalab.utils.qthelpers import resize_widget_to_parent
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
from plotpy.items import MaskedXYImageItem, RangeComputation2d, RectangleShape
|
|
22
|
+
from qtpy.QtWidgets import QWidget
|
|
23
|
+
from sigima.objects import ImageObj
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class ImageBackgroundDialog(PlotDialog):
|
|
27
|
+
"""Image background selection dialog.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
image: image object
|
|
31
|
+
parent: parent widget. Defaults to None.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
def __init__(self, image: ImageObj, parent: QWidget | None = None) -> None:
|
|
35
|
+
self.__background: float | None = None
|
|
36
|
+
self.__rect_coords: tuple[float, float, float, float] | None = None
|
|
37
|
+
self.imageitem: MaskedXYImageItem | None = None
|
|
38
|
+
self.rectarea: RectangleShape | None = None
|
|
39
|
+
self.comput2d: RangeComputation2d | None = None
|
|
40
|
+
super().__init__(
|
|
41
|
+
title=_("Image background selection"), edit=True, parent=parent
|
|
42
|
+
)
|
|
43
|
+
self.setObjectName("backgroundselection")
|
|
44
|
+
if parent is None:
|
|
45
|
+
self.setWindowIcon(get_icon("DataLab.svg"))
|
|
46
|
+
else:
|
|
47
|
+
resize_widget_to_parent(self, aspect_ratio=1.0)
|
|
48
|
+
self.__image = image.copy()
|
|
49
|
+
self.__setup_dialog()
|
|
50
|
+
|
|
51
|
+
def test_compute_background(self) -> None:
|
|
52
|
+
"""Method to test background computation."""
|
|
53
|
+
# Instead of waiting for Qt events, directly test the computation method
|
|
54
|
+
# by simulating what RangeComputation2d would do
|
|
55
|
+
x0, y0, x1, y1 = self.rectarea.get_rect()
|
|
56
|
+
x, y, z = self.imageitem.get_data(x0, y0, x1, y1)
|
|
57
|
+
self.__compute_background(x, y, z)
|
|
58
|
+
|
|
59
|
+
def __compute_background(
|
|
60
|
+
self,
|
|
61
|
+
x: np.ndarray, # pylint: disable=unused-argument
|
|
62
|
+
y: np.ndarray, # pylint: disable=unused-argument
|
|
63
|
+
z: np.ndarray,
|
|
64
|
+
) -> float:
|
|
65
|
+
"""Compute background value"""
|
|
66
|
+
self.__rect_coords = self.rectarea.get_rect()
|
|
67
|
+
self.__background = z.mean()
|
|
68
|
+
return self.__background
|
|
69
|
+
|
|
70
|
+
def __setup_dialog(self) -> None:
|
|
71
|
+
"""Setup dialog box"""
|
|
72
|
+
obj = self.__image
|
|
73
|
+
self.imageitem = create_adapter_from_object(obj).make_item()
|
|
74
|
+
plot = self.get_plot()
|
|
75
|
+
if obj.is_uniform_coords:
|
|
76
|
+
x0, y0 = obj.x0, obj.y0
|
|
77
|
+
x1, y1 = obj.xc + obj.dx, obj.yc + obj.dy
|
|
78
|
+
else:
|
|
79
|
+
x0, y0 = obj.xcoords[0], obj.ycoords[0]
|
|
80
|
+
xc = (obj.xcoords[0] + obj.xcoords[-1]) / 2
|
|
81
|
+
yc = (obj.ycoords[0] + obj.ycoords[-1]) / 2
|
|
82
|
+
x1, y1 = xc, yc
|
|
83
|
+
self.rectarea = make.rectangle(x0, y0, x1, y1, _("Background area"))
|
|
84
|
+
self.comput2d = make.computation2d(
|
|
85
|
+
self.rectarea,
|
|
86
|
+
"TL",
|
|
87
|
+
_("Background value:") + " %g",
|
|
88
|
+
self.imageitem,
|
|
89
|
+
self.__compute_background,
|
|
90
|
+
)
|
|
91
|
+
for item in (self.imageitem, self.rectarea, self.comput2d):
|
|
92
|
+
plot.add_item(item)
|
|
93
|
+
plot.replot()
|
|
94
|
+
plot.set_active_item(self.rectarea)
|
|
95
|
+
|
|
96
|
+
def get_background(self) -> float:
|
|
97
|
+
"""Get background value"""
|
|
98
|
+
return self.__background
|
|
99
|
+
|
|
100
|
+
def get_rect_coords(self) -> tuple[float, float, float, float]:
|
|
101
|
+
"""Get rectangle coordinates
|
|
102
|
+
|
|
103
|
+
Returns:
|
|
104
|
+
tuple: rectangle coordinates (x0, y0, x1, y1)
|
|
105
|
+
|
|
106
|
+
Raises:
|
|
107
|
+
ValueError: if rectangle coordinates are not set
|
|
108
|
+
"""
|
|
109
|
+
if self.__rect_coords is None:
|
|
110
|
+
raise ValueError("Rectangle coordinates not set")
|
|
111
|
+
return self.__rect_coords
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Module providing DataLab Installation configuration widget
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import json
|
|
10
|
+
import locale
|
|
11
|
+
import os
|
|
12
|
+
import platform
|
|
13
|
+
import sys
|
|
14
|
+
from importlib.metadata import distributions
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
|
|
17
|
+
from guidata.configtools import get_icon
|
|
18
|
+
from guidata.qthelpers import exec_dialog
|
|
19
|
+
from qtpy import QtWidgets as QW
|
|
20
|
+
from sigima.io.image import ImageIORegistry
|
|
21
|
+
from sigima.io.signal import SignalIORegistry
|
|
22
|
+
|
|
23
|
+
import datalab
|
|
24
|
+
from datalab.config import APP_NAME, IS_FROZEN, Conf, _
|
|
25
|
+
from datalab.plugins import PluginRegistry
|
|
26
|
+
from datalab.widgets.fileviewer import FileViewerWidget, get_title_contents
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def decode_fs_string(string: bytes) -> str:
|
|
30
|
+
"""Convert string from file system charset to unicode"""
|
|
31
|
+
charset = sys.getfilesystemencoding()
|
|
32
|
+
if charset is None:
|
|
33
|
+
charset = locale.getpreferredencoding()
|
|
34
|
+
return string.decode(charset)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def get_installed_package_info() -> str:
|
|
38
|
+
"""Get the list of installed packages with their versions"""
|
|
39
|
+
packages = [(dist.metadata["Name"], dist.version) for dist in distributions()]
|
|
40
|
+
|
|
41
|
+
# Sort alphabetically by package name
|
|
42
|
+
packages.sort(key=lambda x: x[0].lower())
|
|
43
|
+
|
|
44
|
+
# Determine column widths
|
|
45
|
+
name_width = max(len(name) for name, _ in packages)
|
|
46
|
+
version_width = max(len(version) for _, version in packages)
|
|
47
|
+
|
|
48
|
+
header = f"{'Package':{name_width}} {'Version':{version_width}}"
|
|
49
|
+
separator = f"{'-' * name_width} {'-' * version_width}"
|
|
50
|
+
result_lines = [header, separator]
|
|
51
|
+
for name, version in packages:
|
|
52
|
+
result_lines.append(f"{name:{name_width}} {version:{version_width}}")
|
|
53
|
+
|
|
54
|
+
return os.linesep.join(result_lines)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def get_manifest_package_info(manifest_path: Path) -> str:
|
|
58
|
+
"""Get the list of packages from the build manifest file
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
manifest_path: Path to the manifest.json file
|
|
62
|
+
|
|
63
|
+
Returns:
|
|
64
|
+
Formatted string with package list and build information
|
|
65
|
+
"""
|
|
66
|
+
try:
|
|
67
|
+
with open(manifest_path, "r", encoding="utf-8") as f:
|
|
68
|
+
manifest = json.load(f)
|
|
69
|
+
|
|
70
|
+
packages = list(manifest["packages"].items())
|
|
71
|
+
packages.sort(key=lambda x: x[0].lower())
|
|
72
|
+
|
|
73
|
+
# Determine column widths
|
|
74
|
+
name_width = max(len(name) for name, _ in packages)
|
|
75
|
+
version_width = max(len(version) for _, version in packages)
|
|
76
|
+
|
|
77
|
+
header = f"{'Package':{name_width}} {'Version':{version_width}}"
|
|
78
|
+
separator = f"{'-' * name_width} {'-' * version_width}"
|
|
79
|
+
result_lines = [
|
|
80
|
+
f"Build time: {manifest['build_time']}",
|
|
81
|
+
f"Python version: {manifest['python_version']}",
|
|
82
|
+
f"Build system: {manifest['system']} {manifest['release']}",
|
|
83
|
+
f"Architecture: {manifest['architecture']}",
|
|
84
|
+
"",
|
|
85
|
+
header,
|
|
86
|
+
separator,
|
|
87
|
+
]
|
|
88
|
+
for name, version in packages:
|
|
89
|
+
result_lines.append(f"{name:{name_width}} {version:{version_width}}")
|
|
90
|
+
|
|
91
|
+
return os.linesep.join(result_lines)
|
|
92
|
+
except Exception as e:
|
|
93
|
+
return f"Error reading manifest file: {e}"
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def get_install_info() -> str:
|
|
97
|
+
"""Get DataLab installation informations
|
|
98
|
+
|
|
99
|
+
Returns:
|
|
100
|
+
str: installation informations
|
|
101
|
+
"""
|
|
102
|
+
if IS_FROZEN:
|
|
103
|
+
# Stand-alone version
|
|
104
|
+
more_info = "This is the Stand-alone version of DataLab."
|
|
105
|
+
more_info += os.linesep * 2
|
|
106
|
+
|
|
107
|
+
# Try to read manifest file from executable root directory
|
|
108
|
+
manifest_path = Path(sys.executable).parent / "manifest.json"
|
|
109
|
+
if manifest_path.exists():
|
|
110
|
+
more_info += get_manifest_package_info(manifest_path)
|
|
111
|
+
else:
|
|
112
|
+
more_info += "Manifest file not found."
|
|
113
|
+
else:
|
|
114
|
+
more_info = get_installed_package_info()
|
|
115
|
+
info = os.linesep.join(
|
|
116
|
+
[
|
|
117
|
+
f"DataLab v{datalab.__version__}",
|
|
118
|
+
"",
|
|
119
|
+
f"Machine type: {platform.machine()}",
|
|
120
|
+
f"Platform: {platform.platform()}",
|
|
121
|
+
f"Python v{sys.version}",
|
|
122
|
+
"",
|
|
123
|
+
more_info,
|
|
124
|
+
]
|
|
125
|
+
)
|
|
126
|
+
return info
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
class InstallConfigViewerWindow(QW.QDialog):
|
|
130
|
+
"""Installation configuration window"""
|
|
131
|
+
|
|
132
|
+
def __init__(self, parent: QW.QWidget | None = None) -> None:
|
|
133
|
+
super().__init__(parent)
|
|
134
|
+
self.setObjectName("instviewer")
|
|
135
|
+
self.setWindowTitle(APP_NAME + " - " + _("Installation and configuration"))
|
|
136
|
+
self.setWindowIcon(get_icon("DataLab.svg"))
|
|
137
|
+
self.tabs = QW.QTabWidget(self)
|
|
138
|
+
uc_title, uc_contents = get_title_contents(Conf.get_filename())
|
|
139
|
+
plugins_io_contents = PluginRegistry.get_plugin_info(html=False)
|
|
140
|
+
for registry in (SignalIORegistry, ImageIORegistry):
|
|
141
|
+
plugins_io_contents += os.linesep + ("_" * 80) + os.linesep * 2
|
|
142
|
+
plugins_io_contents += registry.get_format_info(mode="text")
|
|
143
|
+
for title, contents, tab_icon, tab_title in (
|
|
144
|
+
(
|
|
145
|
+
_("Installation configuration"),
|
|
146
|
+
get_install_info(),
|
|
147
|
+
get_icon("libre-toolbox.svg"),
|
|
148
|
+
_("Installation configuration"),
|
|
149
|
+
),
|
|
150
|
+
(
|
|
151
|
+
uc_title,
|
|
152
|
+
uc_contents,
|
|
153
|
+
get_icon("libre-gui-settings.svg"),
|
|
154
|
+
_("User configuration"),
|
|
155
|
+
),
|
|
156
|
+
(
|
|
157
|
+
_("Plugins and I/O features"),
|
|
158
|
+
plugins_io_contents,
|
|
159
|
+
get_icon("libre-gui-plugin.svg"),
|
|
160
|
+
_("Plugins and I/O features"),
|
|
161
|
+
),
|
|
162
|
+
):
|
|
163
|
+
viewer = FileViewerWidget()
|
|
164
|
+
viewer.set_data(title, contents)
|
|
165
|
+
self.tabs.addTab(viewer, tab_icon, tab_title)
|
|
166
|
+
layout = QW.QVBoxLayout()
|
|
167
|
+
layout.addWidget(self.tabs)
|
|
168
|
+
self.setLayout(layout)
|
|
169
|
+
self.resize(800, 500)
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def exec_datalab_installconfig_dialog(parent: QW.QWidget | None = None) -> None:
|
|
173
|
+
"""View DataLab installation configuration"""
|
|
174
|
+
dlg = InstallConfigViewerWindow(parent=parent)
|
|
175
|
+
exec_dialog(dlg)
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Module providing a log viewer widget, a log viewer window and DataLab's log viewer
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import os.path as osp
|
|
10
|
+
|
|
11
|
+
from guidata.configtools import get_icon
|
|
12
|
+
from guidata.qthelpers import exec_dialog
|
|
13
|
+
from qtpy import QtWidgets as QW
|
|
14
|
+
|
|
15
|
+
from datalab.config import APP_NAME, Conf, _, get_old_log_fname
|
|
16
|
+
from datalab.env import execenv
|
|
17
|
+
from datalab.widgets.fileviewer import FileViewerWidget, get_title_contents
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class LogViewerWindow(QW.QDialog):
|
|
21
|
+
"""Log viewer window"""
|
|
22
|
+
|
|
23
|
+
def __init__(self, fnames: list[str], parent: QW.QWidget | None = None) -> None:
|
|
24
|
+
super().__init__(parent)
|
|
25
|
+
self.setObjectName("logviewer")
|
|
26
|
+
self.setWindowTitle(APP_NAME + " - " + _("Log files"))
|
|
27
|
+
self.setWindowIcon(get_icon("DataLab.svg"))
|
|
28
|
+
self.tabs = QW.QTabWidget(self)
|
|
29
|
+
for fname in fnames:
|
|
30
|
+
if osp.isfile(fname):
|
|
31
|
+
title, contents = get_title_contents(fname)
|
|
32
|
+
if not contents.strip():
|
|
33
|
+
continue
|
|
34
|
+
viewer = FileViewerWidget(language="Python")
|
|
35
|
+
viewer.set_data(title, contents)
|
|
36
|
+
self.tabs.addTab(viewer, get_icon("logs.svg"), osp.basename(fname))
|
|
37
|
+
layout = QW.QVBoxLayout()
|
|
38
|
+
layout.addWidget(self.tabs)
|
|
39
|
+
self.setLayout(layout)
|
|
40
|
+
self.resize(900, 400)
|
|
41
|
+
|
|
42
|
+
@property
|
|
43
|
+
def is_empty(self) -> bool:
|
|
44
|
+
"""Return True if there is no log available"""
|
|
45
|
+
return self.tabs.count() == 0
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def get_log_filenames() -> list[str]:
|
|
49
|
+
"""Return log filenames"""
|
|
50
|
+
return [
|
|
51
|
+
Conf.main.traceback_log_path.get(),
|
|
52
|
+
Conf.main.faulthandler_log_path.get(),
|
|
53
|
+
get_old_log_fname(Conf.main.traceback_log_path.get()),
|
|
54
|
+
get_old_log_fname(Conf.main.faulthandler_log_path.get()),
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def get_log_prompt_message() -> str | None:
|
|
59
|
+
"""Return prompt message for log files, i.e. a message informing the user
|
|
60
|
+
whether log files were generated during last session or current session."""
|
|
61
|
+
avail = [osp.isfile(fname) for fname in get_log_filenames()]
|
|
62
|
+
if avail[0] or avail[1]:
|
|
63
|
+
return _("Log files were generated during current session.")
|
|
64
|
+
if avail[2] or avail[3]:
|
|
65
|
+
return _("Log files were generated during last session.")
|
|
66
|
+
return None
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def exec_datalab_logviewer_dialog(parent: QW.QWidget | None = None) -> None:
|
|
70
|
+
"""View DataLab logs"""
|
|
71
|
+
fnames = [osp.normpath(fname) for fname in get_log_filenames() if osp.isfile(fname)]
|
|
72
|
+
dlg = LogViewerWindow(fnames, parent=parent)
|
|
73
|
+
if dlg.is_empty:
|
|
74
|
+
if not execenv.unattended:
|
|
75
|
+
QW.QMessageBox.information(
|
|
76
|
+
dlg, APP_NAME, _("Log files are currently empty.")
|
|
77
|
+
)
|
|
78
|
+
dlg.close()
|
|
79
|
+
else:
|
|
80
|
+
exec_dialog(dlg)
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
|
|
2
|
+
|
|
3
|
+
"""Signal base line selection dialog."""
|
|
4
|
+
|
|
5
|
+
# pylint: disable=invalid-name # Allows short reference names like x, y, ...
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import TYPE_CHECKING
|
|
10
|
+
|
|
11
|
+
import numpy as np
|
|
12
|
+
from guidata.configtools import get_icon
|
|
13
|
+
from plotpy.builder import make
|
|
14
|
+
from plotpy.plot import PlotDialog
|
|
15
|
+
|
|
16
|
+
from datalab.adapters_plotpy import CURVESTYLES, create_adapter_from_object
|
|
17
|
+
from datalab.config import _
|
|
18
|
+
from datalab.utils.qthelpers import resize_widget_to_parent
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
from plotpy.items import CurveItem, Marker, XRangeSelection
|
|
22
|
+
from qtpy.QtWidgets import QWidget
|
|
23
|
+
from sigima.objects import SignalObj
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class SignalBaselineDialog(PlotDialog):
|
|
27
|
+
"""Signal baseline selection dialog.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
signal: signal object
|
|
31
|
+
parent: parent widget. Defaults to None.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
def __init__(self, signal: SignalObj, parent: QWidget | None = None) -> None:
|
|
35
|
+
self.__curve_styles = CURVESTYLES.style_generator()
|
|
36
|
+
self.__baseline: float | None = None
|
|
37
|
+
self.__x_range: tuple[float, float] = [np.nan, np.nan]
|
|
38
|
+
self.curve: CurveItem | None = None
|
|
39
|
+
self.cursor: Marker | None = None
|
|
40
|
+
self.xrange: XRangeSelection | None = None
|
|
41
|
+
super().__init__(title=_("Signal baseline selection"), edit=True, parent=parent)
|
|
42
|
+
self.setObjectName("baselineselection")
|
|
43
|
+
if parent is None:
|
|
44
|
+
self.setWindowIcon(get_icon("DataLab.svg"))
|
|
45
|
+
legend = make.legend("TR")
|
|
46
|
+
self.get_plot().add_item(legend)
|
|
47
|
+
self.__signal = signal.copy()
|
|
48
|
+
self.__setup_dialog()
|
|
49
|
+
resize_widget_to_parent(self, aspect_ratio=1.0)
|
|
50
|
+
|
|
51
|
+
def __setup_dialog(self) -> None:
|
|
52
|
+
"""Setup dialog box"""
|
|
53
|
+
obj = self.__signal
|
|
54
|
+
with CURVESTYLES.alternative(self.__curve_styles):
|
|
55
|
+
self.curve = create_adapter_from_object(obj).make_item()
|
|
56
|
+
plot = self.get_plot()
|
|
57
|
+
plot.set_antialiasing(True)
|
|
58
|
+
plot.SIG_RANGE_CHANGED.connect(self.xrange_changed)
|
|
59
|
+
plot.SIG_MARKER_CHANGED.connect(self.cursor_changed)
|
|
60
|
+
self.cursor = make.hcursor(0.0, _("Base line") + " = %g")
|
|
61
|
+
self.cursor.set_movable(False)
|
|
62
|
+
self.xrange = make.xrange(obj.x[0], obj.x[int(0.2 * len(obj.x))])
|
|
63
|
+
for item in (self.curve, self.cursor, self.xrange):
|
|
64
|
+
plot.add_item(item)
|
|
65
|
+
plot.replot()
|
|
66
|
+
plot.set_active_item(self.xrange)
|
|
67
|
+
self.xrange_changed(self.xrange, *self.xrange.get_range())
|
|
68
|
+
|
|
69
|
+
# pylint: disable=unused-argument
|
|
70
|
+
def xrange_changed(self, item: XRangeSelection, xmin: float, xmax: float) -> None:
|
|
71
|
+
"""X range changed"""
|
|
72
|
+
self.__x_range = sorted([xmin, xmax])
|
|
73
|
+
imin, imax = np.searchsorted(self.__signal.x, self.__x_range)
|
|
74
|
+
if imin == imax:
|
|
75
|
+
return
|
|
76
|
+
self.cursor.set_pos(0, np.mean(self.__signal.y[imin:imax]))
|
|
77
|
+
plot = self.get_plot()
|
|
78
|
+
plot.replot()
|
|
79
|
+
|
|
80
|
+
def cursor_changed(self, item: Marker) -> None:
|
|
81
|
+
"""Cursor changed"""
|
|
82
|
+
_x, self.__baseline = item.get_pos()
|
|
83
|
+
|
|
84
|
+
def get_baseline(self) -> float:
|
|
85
|
+
"""Get baseline"""
|
|
86
|
+
return self.__baseline
|
|
87
|
+
|
|
88
|
+
def get_x_range(self) -> tuple[float, float]:
|
|
89
|
+
"""Get x range"""
|
|
90
|
+
return self.__x_range
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
|
|
2
|
+
|
|
3
|
+
"""Signal horizontal or vertical cursor selection dialog."""
|
|
4
|
+
|
|
5
|
+
# pylint: disable=invalid-name # Allows short reference names like x, y, ...
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import TYPE_CHECKING, Literal
|
|
10
|
+
|
|
11
|
+
import numpy as np
|
|
12
|
+
from guidata.configtools import get_icon
|
|
13
|
+
from plotpy.builder import make
|
|
14
|
+
from plotpy.plot import PlotDialog
|
|
15
|
+
from qtpy import QtGui as QG
|
|
16
|
+
from qtpy import QtWidgets as QW
|
|
17
|
+
from sigima.tools.signal.features import find_x_values_at_y
|
|
18
|
+
|
|
19
|
+
from datalab.adapters_plotpy import CURVESTYLES, create_adapter_from_object
|
|
20
|
+
from datalab.config import _
|
|
21
|
+
from datalab.utils.qthelpers import block_signals, resize_widget_to_parent
|
|
22
|
+
|
|
23
|
+
if TYPE_CHECKING:
|
|
24
|
+
from plotpy.items import CurveItem, Marker
|
|
25
|
+
from qtpy.QtWidgets import QWidget
|
|
26
|
+
from sigima.objects import SignalObj
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class SignalCursorDialog(PlotDialog):
|
|
30
|
+
"""Signal horizontal or vertical cursor selection dialog.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
signal: signal object
|
|
34
|
+
parent: parent widget. Defaults to None.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
def __init__(
|
|
38
|
+
self,
|
|
39
|
+
signal: SignalObj,
|
|
40
|
+
cursor_orientation: Literal["horizontal", "vertical"],
|
|
41
|
+
parent: QWidget | None = None,
|
|
42
|
+
) -> None:
|
|
43
|
+
assert cursor_orientation in (
|
|
44
|
+
"horizontal",
|
|
45
|
+
"vertical",
|
|
46
|
+
), "cursor_orientation must be 'horizontal' or 'vertical'"
|
|
47
|
+
self.__curve_styles = CURVESTYLES.style_generator()
|
|
48
|
+
self.__cursor_orientation = cursor_orientation
|
|
49
|
+
self.__signal = signal
|
|
50
|
+
self.__x_value: float | None = None
|
|
51
|
+
self.__y_value: float | None = None
|
|
52
|
+
self.curve: CurveItem | None = None
|
|
53
|
+
self.hcursor: Marker | None = None
|
|
54
|
+
self.vcursor: Marker | None = None
|
|
55
|
+
self.xlineedit: QW.QLineEdit | None = None
|
|
56
|
+
self.ylineedit: QW.QLineEdit | None = None
|
|
57
|
+
if cursor_orientation == "horizontal":
|
|
58
|
+
title = _("Select X value with cursor")
|
|
59
|
+
else:
|
|
60
|
+
title = _("Select Y value with cursor")
|
|
61
|
+
super().__init__(title=title, edit=True, parent=parent)
|
|
62
|
+
self.setObjectName("SignalCursorDialog")
|
|
63
|
+
if parent is None:
|
|
64
|
+
self.setWindowIcon(get_icon("DataLab.svg"))
|
|
65
|
+
legend = make.legend("TR")
|
|
66
|
+
self.get_plot().add_item(legend)
|
|
67
|
+
self.__setup_dialog()
|
|
68
|
+
resize_widget_to_parent(self, aspect_ratio=1.0)
|
|
69
|
+
|
|
70
|
+
def __setup_dialog(self) -> None:
|
|
71
|
+
"""Setup dialog box"""
|
|
72
|
+
apply_button = QW.QPushButton(_("Apply"))
|
|
73
|
+
apply_button.setIcon(get_icon("apply.svg"))
|
|
74
|
+
apply_button.setToolTip(_("Apply cursor position"))
|
|
75
|
+
xlabel = QW.QLabel("X=")
|
|
76
|
+
ylabel = QW.QLabel("Y=")
|
|
77
|
+
self.xlineedit = QW.QLineEdit()
|
|
78
|
+
self.xlineedit.editingFinished.connect(self.xlineedit_editing_finished)
|
|
79
|
+
self.xlineedit.setValidator(QG.QDoubleValidator())
|
|
80
|
+
self.ylineedit = QW.QLineEdit()
|
|
81
|
+
self.ylineedit.editingFinished.connect(self.ylineedit_editing_finished)
|
|
82
|
+
self.ylineedit.setValidator(QG.QDoubleValidator())
|
|
83
|
+
self.xlineedit.setReadOnly(self.__cursor_orientation == "horizontal")
|
|
84
|
+
self.xlineedit.setDisabled(self.__cursor_orientation == "horizontal")
|
|
85
|
+
self.ylineedit.setReadOnly(self.__cursor_orientation == "vertical")
|
|
86
|
+
self.ylineedit.setDisabled(self.__cursor_orientation == "vertical")
|
|
87
|
+
xygroup = QW.QGroupBox(_("Cursor position"))
|
|
88
|
+
xylayout = QW.QHBoxLayout()
|
|
89
|
+
xylayout.addWidget(xlabel)
|
|
90
|
+
xylayout.addWidget(self.xlineedit)
|
|
91
|
+
if self.__cursor_orientation == "vertical":
|
|
92
|
+
xylayout.addWidget(apply_button)
|
|
93
|
+
apply_button.clicked.connect(self.xlineedit_editing_finished)
|
|
94
|
+
xylayout.addStretch()
|
|
95
|
+
xylayout.addSpacing(10)
|
|
96
|
+
xylayout.addWidget(ylabel)
|
|
97
|
+
xylayout.addWidget(self.ylineedit)
|
|
98
|
+
if self.__cursor_orientation == "horizontal":
|
|
99
|
+
xylayout.addWidget(apply_button)
|
|
100
|
+
apply_button.clicked.connect(self.ylineedit_editing_finished)
|
|
101
|
+
xygroup.setLayout(xylayout)
|
|
102
|
+
self.button_layout.insertWidget(0, xygroup)
|
|
103
|
+
|
|
104
|
+
obj = self.__signal
|
|
105
|
+
with CURVESTYLES.alternative(self.__curve_styles):
|
|
106
|
+
self.curve = create_adapter_from_object(obj).make_item()
|
|
107
|
+
plot = self.get_plot()
|
|
108
|
+
plot.set_antialiasing(True)
|
|
109
|
+
|
|
110
|
+
xcursor = make.xcursor(np.mean(obj.x), np.mean(obj.y), "X = %g, Y = %g")
|
|
111
|
+
xcursor.set_selectable(False)
|
|
112
|
+
param = xcursor.markerparam
|
|
113
|
+
param.symbol.facecolor = "blue"
|
|
114
|
+
param.symbol.edgecolor = "cyan"
|
|
115
|
+
param.symbol.size = 9
|
|
116
|
+
param.line.style = "DotLine"
|
|
117
|
+
param.line.color = "blue"
|
|
118
|
+
param.line.width = 2.0
|
|
119
|
+
param.update_item(xcursor)
|
|
120
|
+
|
|
121
|
+
plot.SIG_MARKER_CHANGED.connect(self.cursor_changed)
|
|
122
|
+
if self.__cursor_orientation == "horizontal":
|
|
123
|
+
self.hcursor = make.hcursor(np.mean(obj.y), "Y = %g")
|
|
124
|
+
self.vcursor = xcursor
|
|
125
|
+
self.vcursor.setVisible(False)
|
|
126
|
+
else:
|
|
127
|
+
self.vcursor = make.vcursor(np.mean(obj.x), "X = %g")
|
|
128
|
+
self.hcursor = xcursor
|
|
129
|
+
self.hcursor.setVisible(False)
|
|
130
|
+
for item in (self.curve, self.vcursor, self.hcursor):
|
|
131
|
+
plot.add_item(item)
|
|
132
|
+
plot.replot()
|
|
133
|
+
if self.__cursor_orientation == "horizontal":
|
|
134
|
+
plot.set_active_item(self.hcursor)
|
|
135
|
+
self.cursor_changed(self.hcursor)
|
|
136
|
+
else:
|
|
137
|
+
plot.set_active_item(self.vcursor)
|
|
138
|
+
self.cursor_changed(self.vcursor)
|
|
139
|
+
|
|
140
|
+
def cursor_changed(self, item: Marker) -> None:
|
|
141
|
+
"""Cursor changed"""
|
|
142
|
+
sig = self.__signal
|
|
143
|
+
plot = self.get_plot()
|
|
144
|
+
if self.__cursor_orientation == "horizontal" and item is self.hcursor:
|
|
145
|
+
_x, y = item.get_pos()
|
|
146
|
+
x = None
|
|
147
|
+
x_values = find_x_values_at_y(sig.x, sig.y, y)
|
|
148
|
+
if len(x_values) > 0:
|
|
149
|
+
x = x_values[0]
|
|
150
|
+
with block_signals(plot):
|
|
151
|
+
self.vcursor.set_pos(x, y)
|
|
152
|
+
self.vcursor.setVisible(x is not None)
|
|
153
|
+
self.button_box.button(QW.QDialogButtonBox.Ok).setEnabled(x is not None)
|
|
154
|
+
elif self.__cursor_orientation == "vertical" and item is self.vcursor:
|
|
155
|
+
x, _y = item.get_pos()
|
|
156
|
+
y_index = np.searchsorted(self.__signal.x, x)
|
|
157
|
+
if x < self.__signal.x[0] or y_index >= len(self.__signal.y):
|
|
158
|
+
y = None
|
|
159
|
+
else:
|
|
160
|
+
y = self.__signal.y[y_index]
|
|
161
|
+
with block_signals(plot):
|
|
162
|
+
self.hcursor.set_pos(x, y)
|
|
163
|
+
self.hcursor.setVisible(True)
|
|
164
|
+
self.hcursor.setVisible(y is not None)
|
|
165
|
+
self.button_box.button(QW.QDialogButtonBox.Ok).setEnabled(y is not None)
|
|
166
|
+
self.xlineedit.setText(f"{x:g}" if x is not None else "")
|
|
167
|
+
self.ylineedit.setText(f"{y:g}" if y is not None else "")
|
|
168
|
+
self.__x_value, self.__y_value = x, y
|
|
169
|
+
|
|
170
|
+
def xlineedit_editing_finished(self) -> None:
|
|
171
|
+
"""X line edit editing finished"""
|
|
172
|
+
try:
|
|
173
|
+
x = float(self.xlineedit.text())
|
|
174
|
+
_x, y = self.vcursor.get_pos()
|
|
175
|
+
if self.__cursor_orientation == "horizontal":
|
|
176
|
+
self.hcursor.set_pos(x, y)
|
|
177
|
+
else:
|
|
178
|
+
self.vcursor.set_pos(x, y)
|
|
179
|
+
except ValueError:
|
|
180
|
+
pass
|
|
181
|
+
plot = self.get_plot()
|
|
182
|
+
plot.replot()
|
|
183
|
+
|
|
184
|
+
def ylineedit_editing_finished(self) -> None:
|
|
185
|
+
"""Y line edit editing finished"""
|
|
186
|
+
try:
|
|
187
|
+
y = float(self.ylineedit.text())
|
|
188
|
+
x, _y = self.hcursor.get_pos()
|
|
189
|
+
if self.__cursor_orientation == "horizontal":
|
|
190
|
+
self.hcursor.set_pos(x, y)
|
|
191
|
+
else:
|
|
192
|
+
self.vcursor.set_pos(x, y)
|
|
193
|
+
except ValueError:
|
|
194
|
+
pass
|
|
195
|
+
plot = self.get_plot()
|
|
196
|
+
plot.replot()
|
|
197
|
+
|
|
198
|
+
def get_cursor_position(self) -> tuple[float, float]:
|
|
199
|
+
"""Get cursor position"""
|
|
200
|
+
return self.__x_value, self.__y_value
|
|
201
|
+
|
|
202
|
+
def get_x_value(self) -> float:
|
|
203
|
+
"""Get cursor x value"""
|
|
204
|
+
return self.__x_value
|
|
205
|
+
|
|
206
|
+
def get_y_value(self) -> float:
|
|
207
|
+
"""Get cursor y value"""
|
|
208
|
+
return self.__y_value
|