datalab-platform 0.0.1.dev0__py3-none-any.whl → 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- datalab/__init__.py +35 -2
- datalab/adapters_metadata/__init__.py +31 -0
- datalab/adapters_metadata/base_adapter.py +316 -0
- datalab/adapters_metadata/common.py +422 -0
- datalab/adapters_metadata/geometry_adapter.py +98 -0
- datalab/adapters_metadata/table_adapter.py +84 -0
- datalab/adapters_plotpy/__init__.py +54 -0
- datalab/adapters_plotpy/annotations.py +124 -0
- datalab/adapters_plotpy/base.py +110 -0
- datalab/adapters_plotpy/converters.py +86 -0
- datalab/adapters_plotpy/factories.py +80 -0
- datalab/adapters_plotpy/objects/__init__.py +0 -0
- datalab/adapters_plotpy/objects/base.py +197 -0
- datalab/adapters_plotpy/objects/image.py +157 -0
- datalab/adapters_plotpy/objects/scalar.py +565 -0
- datalab/adapters_plotpy/objects/signal.py +264 -0
- datalab/adapters_plotpy/roi/__init__.py +0 -0
- datalab/adapters_plotpy/roi/base.py +146 -0
- datalab/adapters_plotpy/roi/factory.py +93 -0
- datalab/adapters_plotpy/roi/image.py +207 -0
- datalab/adapters_plotpy/roi/signal.py +72 -0
- datalab/app.py +98 -0
- datalab/config.py +817 -0
- datalab/control/__init__.py +0 -0
- datalab/control/baseproxy.py +776 -0
- datalab/control/proxy.py +343 -0
- datalab/control/remote.py +1005 -0
- datalab/data/doc/DataLab_en.pdf +0 -0
- datalab/data/doc/DataLab_fr.pdf +0 -0
- datalab/data/icons/analysis/delete_results.svg +109 -0
- datalab/data/icons/analysis/fw1e2.svg +156 -0
- datalab/data/icons/analysis/fwhm.svg +156 -0
- datalab/data/icons/analysis/histogram.svg +49 -0
- datalab/data/icons/analysis/peak_detect.svg +160 -0
- datalab/data/icons/analysis/plot_results.svg +151 -0
- datalab/data/icons/analysis/show_results.svg +83 -0
- datalab/data/icons/analysis/stats.svg +49 -0
- datalab/data/icons/analysis.svg +120 -0
- datalab/data/icons/apply.svg +3 -0
- datalab/data/icons/check_all.svg +15 -0
- datalab/data/icons/collapse.svg +44 -0
- datalab/data/icons/collapse_selection.svg +63 -0
- datalab/data/icons/console.svg +101 -0
- datalab/data/icons/create/1d-normal.svg +8 -0
- datalab/data/icons/create/1d-poisson.svg +9 -0
- datalab/data/icons/create/1d-uniform.svg +8 -0
- datalab/data/icons/create/1d-zero.svg +57 -0
- datalab/data/icons/create/2d-gaussian.svg +56 -0
- datalab/data/icons/create/2d-normal.svg +38 -0
- datalab/data/icons/create/2d-poisson.svg +38 -0
- datalab/data/icons/create/2d-ramp.svg +90 -0
- datalab/data/icons/create/2d-sinc.svg +62 -0
- datalab/data/icons/create/2d-uniform.svg +38 -0
- datalab/data/icons/create/2d-zero.svg +13 -0
- datalab/data/icons/create/checkerboard.svg +39 -0
- datalab/data/icons/create/cosine.svg +12 -0
- datalab/data/icons/create/exponential.svg +55 -0
- datalab/data/icons/create/gaussian.svg +12 -0
- datalab/data/icons/create/grating.svg +29 -0
- datalab/data/icons/create/linear_chirp.svg +7 -0
- datalab/data/icons/create/logistic.svg +7 -0
- datalab/data/icons/create/lorentzian.svg +12 -0
- datalab/data/icons/create/planck.svg +12 -0
- datalab/data/icons/create/polynomial.svg +7 -0
- datalab/data/icons/create/pulse.svg +12 -0
- datalab/data/icons/create/ring.svg +18 -0
- datalab/data/icons/create/sawtooth.svg +7 -0
- datalab/data/icons/create/siemens.svg +35 -0
- datalab/data/icons/create/sinc.svg +12 -0
- datalab/data/icons/create/sine.svg +7 -0
- datalab/data/icons/create/square.svg +7 -0
- datalab/data/icons/create/square_pulse.svg +7 -0
- datalab/data/icons/create/step.svg +7 -0
- datalab/data/icons/create/step_pulse.svg +12 -0
- datalab/data/icons/create/triangle.svg +7 -0
- datalab/data/icons/create/voigt.svg +12 -0
- datalab/data/icons/edit/annotations.svg +72 -0
- datalab/data/icons/edit/annotations_copy.svg +114 -0
- datalab/data/icons/edit/annotations_delete.svg +83 -0
- datalab/data/icons/edit/annotations_edit.svg +98 -0
- datalab/data/icons/edit/annotations_export.svg +85 -0
- datalab/data/icons/edit/annotations_import.svg +85 -0
- datalab/data/icons/edit/annotations_paste.svg +100 -0
- datalab/data/icons/edit/copy_titles.svg +109 -0
- datalab/data/icons/edit/delete.svg +84 -0
- datalab/data/icons/edit/delete_all.svg +214 -0
- datalab/data/icons/edit/duplicate.svg +64 -0
- datalab/data/icons/edit/goto_source.svg +60 -0
- datalab/data/icons/edit/metadata.svg +60 -0
- datalab/data/icons/edit/metadata_add.svg +80 -0
- datalab/data/icons/edit/metadata_copy.svg +96 -0
- datalab/data/icons/edit/metadata_delete.svg +62 -0
- datalab/data/icons/edit/metadata_export.svg +68 -0
- datalab/data/icons/edit/metadata_import.svg +68 -0
- datalab/data/icons/edit/metadata_paste.svg +79 -0
- datalab/data/icons/edit/move_down.svg +55 -0
- datalab/data/icons/edit/move_up.svg +54 -0
- datalab/data/icons/edit/new_group.svg +76 -0
- datalab/data/icons/edit/recompute.svg +60 -0
- datalab/data/icons/edit/rename.svg +49 -0
- datalab/data/icons/edit.svg +16 -0
- datalab/data/icons/expand.svg +44 -0
- datalab/data/icons/expand_selection.svg +63 -0
- datalab/data/icons/fit/cdf_fit.svg +56 -0
- datalab/data/icons/fit/exponential_fit.svg +55 -0
- datalab/data/icons/fit/gaussian_fit.svg +62 -0
- datalab/data/icons/fit/interactive_fit.svg +101 -0
- datalab/data/icons/fit/linear_fit.svg +57 -0
- datalab/data/icons/fit/lorentzian_fit.svg +209 -0
- datalab/data/icons/fit/multigaussian_fit.svg +85 -0
- datalab/data/icons/fit/multilorentzian_fit.svg +85 -0
- datalab/data/icons/fit/piecewiseexponential_fit.svg +209 -0
- datalab/data/icons/fit/planckian_fit.svg +62 -0
- datalab/data/icons/fit/polynomial_fit.svg +59 -0
- datalab/data/icons/fit/sigmoid_fit.svg +56 -0
- datalab/data/icons/fit/sinusoidal_fit.svg +72 -0
- datalab/data/icons/fit/twohalfgaussian_fit.svg +63 -0
- datalab/data/icons/fit/voigt_fit.svg +57 -0
- datalab/data/icons/group.svg +56 -0
- datalab/data/icons/h5/h5array.svg +59 -0
- datalab/data/icons/h5/h5attrs.svg +75 -0
- datalab/data/icons/h5/h5browser.svg +133 -0
- datalab/data/icons/h5/h5file.svg +69 -0
- datalab/data/icons/h5/h5group.svg +49 -0
- datalab/data/icons/h5/h5scalar.svg +1 -0
- datalab/data/icons/help_pdf.svg +46 -0
- datalab/data/icons/history.svg +7 -0
- datalab/data/icons/image.svg +135 -0
- datalab/data/icons/io/fileopen_directory.svg +60 -0
- datalab/data/icons/io/fileopen_h5.svg +84 -0
- datalab/data/icons/io/fileopen_ima.svg +187 -0
- datalab/data/icons/io/fileopen_py.svg +123 -0
- datalab/data/icons/io/fileopen_sig.svg +138 -0
- datalab/data/icons/io/filesave_h5.svg +97 -0
- datalab/data/icons/io/filesave_ima.svg +200 -0
- datalab/data/icons/io/filesave_py.svg +136 -0
- datalab/data/icons/io/filesave_sig.svg +151 -0
- datalab/data/icons/io/import_text.svg +144 -0
- datalab/data/icons/io/save_to_directory.svg +134 -0
- datalab/data/icons/io.svg +84 -0
- datalab/data/icons/libre-camera-flash-off.svg +1 -0
- datalab/data/icons/libre-camera-flash-on.svg +1 -0
- datalab/data/icons/libre-gui-about.svg +1 -0
- datalab/data/icons/libre-gui-action-delete.svg +1 -0
- datalab/data/icons/libre-gui-add.svg +1 -0
- datalab/data/icons/libre-gui-arrow-down.svg +1 -0
- datalab/data/icons/libre-gui-arrow-left.svg +1 -0
- datalab/data/icons/libre-gui-arrow-right.svg +1 -0
- datalab/data/icons/libre-gui-arrow-up.svg +1 -0
- datalab/data/icons/libre-gui-close.svg +40 -0
- datalab/data/icons/libre-gui-cogs.svg +1 -0
- datalab/data/icons/libre-gui-globe.svg +1 -0
- datalab/data/icons/libre-gui-help.svg +1 -0
- datalab/data/icons/libre-gui-link.svg +1 -0
- datalab/data/icons/libre-gui-menu.svg +1 -0
- datalab/data/icons/libre-gui-pencil.svg +1 -0
- datalab/data/icons/libre-gui-plugin.svg +1 -0
- datalab/data/icons/libre-gui-questions.svg +1 -0
- datalab/data/icons/libre-gui-settings.svg +1 -0
- datalab/data/icons/libre-gui-unlink.svg +1 -0
- datalab/data/icons/libre-tech-ram.svg +1 -0
- datalab/data/icons/libre-toolbox.svg +1 -0
- datalab/data/icons/logs.svg +1 -0
- datalab/data/icons/markers.svg +74 -0
- datalab/data/icons/menu.svg +13 -0
- datalab/data/icons/new_ima.svg +148 -0
- datalab/data/icons/new_sig.svg +123 -0
- datalab/data/icons/operations/abs.svg +116 -0
- datalab/data/icons/operations/arithmetic.svg +123 -0
- datalab/data/icons/operations/average.svg +124 -0
- datalab/data/icons/operations/complex_from_magnitude_phase.svg +116 -0
- datalab/data/icons/operations/complex_from_real_imag.svg +124 -0
- datalab/data/icons/operations/constant.svg +116 -0
- datalab/data/icons/operations/constant_add.svg +109 -0
- datalab/data/icons/operations/constant_divide.svg +109 -0
- datalab/data/icons/operations/constant_multiply.svg +109 -0
- datalab/data/icons/operations/constant_subtract.svg +109 -0
- datalab/data/icons/operations/convert_dtype.svg +117 -0
- datalab/data/icons/operations/convolution.svg +46 -0
- datalab/data/icons/operations/deconvolution.svg +57 -0
- datalab/data/icons/operations/derivative.svg +127 -0
- datalab/data/icons/operations/difference.svg +52 -0
- datalab/data/icons/operations/division.svg +139 -0
- datalab/data/icons/operations/exp.svg +116 -0
- datalab/data/icons/operations/flip_horizontally.svg +69 -0
- datalab/data/icons/operations/flip_vertically.svg +74 -0
- datalab/data/icons/operations/im.svg +124 -0
- datalab/data/icons/operations/integral.svg +50 -0
- datalab/data/icons/operations/inverse.svg +143 -0
- datalab/data/icons/operations/log10.svg +109 -0
- datalab/data/icons/operations/phase.svg +116 -0
- datalab/data/icons/operations/power.svg +118 -0
- datalab/data/icons/operations/product.svg +124 -0
- datalab/data/icons/operations/profile.svg +379 -0
- datalab/data/icons/operations/profile_average.svg +399 -0
- datalab/data/icons/operations/profile_radial.svg +261 -0
- datalab/data/icons/operations/profile_segment.svg +262 -0
- datalab/data/icons/operations/quadratic_difference.svg +84 -0
- datalab/data/icons/operations/re.svg +124 -0
- datalab/data/icons/operations/rotate_left.svg +72 -0
- datalab/data/icons/operations/rotate_right.svg +72 -0
- datalab/data/icons/operations/signals_to_image.svg +314 -0
- datalab/data/icons/operations/sqrt.svg +110 -0
- datalab/data/icons/operations/std.svg +124 -0
- datalab/data/icons/operations/sum.svg +102 -0
- datalab/data/icons/play_demo.svg +9 -0
- datalab/data/icons/processing/axis_transform.svg +62 -0
- datalab/data/icons/processing/bandpass.svg +79 -0
- datalab/data/icons/processing/bandstop.svg +71 -0
- datalab/data/icons/processing/binning.svg +126 -0
- datalab/data/icons/processing/clip.svg +119 -0
- datalab/data/icons/processing/detrending.svg +173 -0
- datalab/data/icons/processing/distribute_on_grid.svg +769 -0
- datalab/data/icons/processing/edge_detection.svg +46 -0
- datalab/data/icons/processing/erase.svg +1 -0
- datalab/data/icons/processing/exposure.svg +143 -0
- datalab/data/icons/processing/fourier.svg +104 -0
- datalab/data/icons/processing/highpass.svg +59 -0
- datalab/data/icons/processing/interpolation.svg +71 -0
- datalab/data/icons/processing/level_adjustment.svg +70 -0
- datalab/data/icons/processing/lowpass.svg +60 -0
- datalab/data/icons/processing/morphology.svg +49 -0
- datalab/data/icons/processing/noise_addition.svg +114 -0
- datalab/data/icons/processing/noise_reduction.svg +38 -0
- datalab/data/icons/processing/normalize.svg +84 -0
- datalab/data/icons/processing/offset_correction.svg +131 -0
- datalab/data/icons/processing/resampling1d.svg +101 -0
- datalab/data/icons/processing/resampling2d.svg +240 -0
- datalab/data/icons/processing/reset_positions.svg +185 -0
- datalab/data/icons/processing/resize.svg +9 -0
- datalab/data/icons/processing/reverse_signal_x.svg +171 -0
- datalab/data/icons/processing/stability.svg +11 -0
- datalab/data/icons/processing/swap_x_y.svg +65 -0
- datalab/data/icons/processing/thresholding.svg +63 -0
- datalab/data/icons/processing/windowing.svg +45 -0
- datalab/data/icons/properties.svg +26 -0
- datalab/data/icons/reset.svg +9 -0
- datalab/data/icons/restore.svg +40 -0
- datalab/data/icons/roi/roi.svg +76 -0
- datalab/data/icons/roi/roi_coordinate.svg +78 -0
- datalab/data/icons/roi/roi_copy.svg +112 -0
- datalab/data/icons/roi/roi_delete.svg +81 -0
- datalab/data/icons/roi/roi_export.svg +87 -0
- datalab/data/icons/roi/roi_graphical.svg +78 -0
- datalab/data/icons/roi/roi_grid.svg +67 -0
- datalab/data/icons/roi/roi_ima.svg +188 -0
- datalab/data/icons/roi/roi_import.svg +87 -0
- datalab/data/icons/roi/roi_new.svg +81 -0
- datalab/data/icons/roi/roi_new_circle.svg +95 -0
- datalab/data/icons/roi/roi_new_polygon.svg +110 -0
- datalab/data/icons/roi/roi_new_rectangle.svg +70 -0
- datalab/data/icons/roi/roi_paste.svg +98 -0
- datalab/data/icons/roi/roi_sig.svg +124 -0
- datalab/data/icons/shapes.svg +134 -0
- datalab/data/icons/signal.svg +103 -0
- datalab/data/icons/table.svg +85 -0
- datalab/data/icons/table_unavailable.svg +102 -0
- datalab/data/icons/to_signal.svg +124 -0
- datalab/data/icons/tour/next.svg +44 -0
- datalab/data/icons/tour/previous.svg +44 -0
- datalab/data/icons/tour/rewind.svg +51 -0
- datalab/data/icons/tour/stop.svg +47 -0
- datalab/data/icons/tour/tour.svg +16 -0
- datalab/data/icons/uncheck_all.svg +78 -0
- datalab/data/icons/view/curve_antialiasing.svg +50 -0
- datalab/data/icons/view/new_window.svg +98 -0
- datalab/data/icons/view/refresh-auto.svg +57 -0
- datalab/data/icons/view/refresh-manual.svg +51 -0
- datalab/data/icons/view/reset_curve_styles.svg +96 -0
- datalab/data/icons/view/show_first.svg +55 -0
- datalab/data/icons/view/show_titles.svg +46 -0
- datalab/data/icons/visualization.svg +51 -0
- datalab/data/logo/DataLab-Banner-150.png +0 -0
- datalab/data/logo/DataLab-Banner-200.png +0 -0
- datalab/data/logo/DataLab-Banner2-100.png +0 -0
- datalab/data/logo/DataLab-Splash.png +0 -0
- datalab/data/logo/DataLab-watermark.png +0 -0
- datalab/data/logo/DataLab.svg +83 -0
- datalab/data/tests/reordering_test.h5 +0 -0
- datalab/data/tutorials/fabry_perot/fabry-perot1.jpg +0 -0
- datalab/data/tutorials/fabry_perot/fabry-perot2.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_13.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_18.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_23.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_30.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_35.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_40.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_45.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_50.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_55.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_60.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_65.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_70.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_75.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_80.jpg +0 -0
- datalab/env.py +542 -0
- datalab/gui/__init__.py +89 -0
- datalab/gui/actionhandler.py +1701 -0
- datalab/gui/docks.py +473 -0
- datalab/gui/h5io.py +150 -0
- datalab/gui/macroeditor.py +310 -0
- datalab/gui/main.py +2081 -0
- datalab/gui/newobject.py +217 -0
- datalab/gui/objectview.py +766 -0
- datalab/gui/panel/__init__.py +48 -0
- datalab/gui/panel/base.py +3254 -0
- datalab/gui/panel/image.py +157 -0
- datalab/gui/panel/macro.py +607 -0
- datalab/gui/panel/signal.py +164 -0
- datalab/gui/plothandler.py +800 -0
- datalab/gui/processor/__init__.py +84 -0
- datalab/gui/processor/base.py +2456 -0
- datalab/gui/processor/catcher.py +75 -0
- datalab/gui/processor/image.py +1214 -0
- datalab/gui/processor/signal.py +755 -0
- datalab/gui/profiledialog.py +333 -0
- datalab/gui/roieditor.py +633 -0
- datalab/gui/roigrideditor.py +208 -0
- datalab/gui/settings.py +612 -0
- datalab/gui/tour.py +908 -0
- datalab/h5/__init__.py +12 -0
- datalab/h5/common.py +314 -0
- datalab/h5/generic.py +580 -0
- datalab/h5/native.py +39 -0
- datalab/h5/utils.py +95 -0
- datalab/objectmodel.py +640 -0
- datalab/plugins/_readme_.txt +9 -0
- datalab/plugins/datalab_imageformats.py +175 -0
- datalab/plugins/datalab_testdata.py +190 -0
- datalab/plugins.py +355 -0
- datalab/tests/__init__.py +199 -0
- datalab/tests/backbone/__init__.py +1 -0
- datalab/tests/backbone/config_unit_test.py +170 -0
- datalab/tests/backbone/config_versioning_unit_test.py +34 -0
- datalab/tests/backbone/dictlistserial_app_test.py +38 -0
- datalab/tests/backbone/errorcatcher_unit_test.py +69 -0
- datalab/tests/backbone/errormsgbox_unit_test.py +50 -0
- datalab/tests/backbone/execenv_unit.py +262 -0
- datalab/tests/backbone/loadtest_gdi.py +147 -0
- datalab/tests/backbone/long_callback.py +96 -0
- datalab/tests/backbone/main_app_test.py +137 -0
- datalab/tests/backbone/memory_leak.py +43 -0
- datalab/tests/backbone/procisolation1_unit.py +128 -0
- datalab/tests/backbone/procisolation2_unit.py +171 -0
- datalab/tests/backbone/procisolation_unit_test.py +22 -0
- datalab/tests/backbone/profiling_app.py +27 -0
- datalab/tests/backbone/strings_unit_test.py +65 -0
- datalab/tests/backbone/title_formatting_unit_test.py +82 -0
- datalab/tests/conftest.py +131 -0
- datalab/tests/features/__init__.py +1 -0
- datalab/tests/features/applauncher/__init__.py +1 -0
- datalab/tests/features/applauncher/launcher1_app_test.py +28 -0
- datalab/tests/features/applauncher/launcher2_app_test.py +30 -0
- datalab/tests/features/common/__init__.py +1 -0
- datalab/tests/features/common/add_metadata_app_test.py +134 -0
- datalab/tests/features/common/add_metadata_unit_test.py +267 -0
- datalab/tests/features/common/annotations_management_unit_test.py +152 -0
- datalab/tests/features/common/auto_analysis_recompute_unit_test.py +240 -0
- datalab/tests/features/common/createobject_unit_test.py +50 -0
- datalab/tests/features/common/geometry_results_app_test.py +135 -0
- datalab/tests/features/common/interactive_processing_test.py +1109 -0
- datalab/tests/features/common/io_app_test.py +75 -0
- datalab/tests/features/common/large_results_app_test.py +187 -0
- datalab/tests/features/common/metadata_all_patterns_test.py +103 -0
- datalab/tests/features/common/metadata_app_test.py +139 -0
- datalab/tests/features/common/metadata_io_unit_test.py +60 -0
- datalab/tests/features/common/misc_app_test.py +236 -0
- datalab/tests/features/common/multiple_geometry_results_unit_test.py +122 -0
- datalab/tests/features/common/multiple_table_results_unit_test.py +64 -0
- datalab/tests/features/common/operation_modes_app_test.py +392 -0
- datalab/tests/features/common/plot_results_app_test.py +278 -0
- datalab/tests/features/common/reorder_app_test.py +75 -0
- datalab/tests/features/common/result_deletion_unit_test.py +96 -0
- datalab/tests/features/common/result_merged_label_unit_test.py +154 -0
- datalab/tests/features/common/result_shape_settings_unit_test.py +223 -0
- datalab/tests/features/common/roi_plotitem_unit_test.py +64 -0
- datalab/tests/features/common/roieditor_unit_test.py +102 -0
- datalab/tests/features/common/save_to_dir_app_test.py +163 -0
- datalab/tests/features/common/save_to_dir_unit_test.py +474 -0
- datalab/tests/features/common/stat_app_test.py +40 -0
- datalab/tests/features/common/stats_tools_unit_test.py +77 -0
- datalab/tests/features/common/table_results_app_test.py +52 -0
- datalab/tests/features/common/textimport_unit_test.py +131 -0
- datalab/tests/features/common/uuid_preservation_test.py +281 -0
- datalab/tests/features/common/worker_unit_test.py +402 -0
- datalab/tests/features/control/__init__.py +1 -0
- datalab/tests/features/control/connect_dialog.py +28 -0
- datalab/tests/features/control/embedded1_unit_test.py +304 -0
- datalab/tests/features/control/embedded2_unit_test.py +52 -0
- datalab/tests/features/control/remoteclient_app_test.py +219 -0
- datalab/tests/features/control/remoteclient_unit.py +75 -0
- datalab/tests/features/control/simpleclient_unit_test.py +321 -0
- datalab/tests/features/hdf5/__init__.py +1 -0
- datalab/tests/features/hdf5/h5browser1_unit_test.py +31 -0
- datalab/tests/features/hdf5/h5browser2_unit.py +55 -0
- datalab/tests/features/hdf5/h5browser_app_test.py +77 -0
- datalab/tests/features/hdf5/h5import_app_test.py +25 -0
- datalab/tests/features/hdf5/h5importer_app_test.py +34 -0
- datalab/tests/features/image/__init__.py +1 -0
- datalab/tests/features/image/annotations_app_test.py +28 -0
- datalab/tests/features/image/annotations_unit_test.py +80 -0
- datalab/tests/features/image/average_app_test.py +46 -0
- datalab/tests/features/image/background_dialog_test.py +70 -0
- datalab/tests/features/image/blobs_app_test.py +50 -0
- datalab/tests/features/image/contour_app_test.py +42 -0
- datalab/tests/features/image/contour_fabryperot_app_test.py +51 -0
- datalab/tests/features/image/denoise_app_test.py +31 -0
- datalab/tests/features/image/distribute_on_grid_app_test.py +95 -0
- datalab/tests/features/image/edges_app_test.py +31 -0
- datalab/tests/features/image/erase_app_test.py +21 -0
- datalab/tests/features/image/fft2d_app_test.py +27 -0
- datalab/tests/features/image/flatfield_app_test.py +40 -0
- datalab/tests/features/image/geometry_transform_unit_test.py +396 -0
- datalab/tests/features/image/imagetools_app_test.py +51 -0
- datalab/tests/features/image/imagetools_unit_test.py +27 -0
- datalab/tests/features/image/load_app_test.py +73 -0
- datalab/tests/features/image/morph_app_test.py +32 -0
- datalab/tests/features/image/offsetcorrection_app_test.py +30 -0
- datalab/tests/features/image/peak2d_app_test.py +53 -0
- datalab/tests/features/image/profile_app_test.py +73 -0
- datalab/tests/features/image/profile_dialog_test.py +56 -0
- datalab/tests/features/image/roi_app_test.py +98 -0
- datalab/tests/features/image/roi_circ_app_test.py +62 -0
- datalab/tests/features/image/roi_manipulation_app_test.py +268 -0
- datalab/tests/features/image/roigrid_unit_test.py +60 -0
- datalab/tests/features/image/side_by_side_app_test.py +52 -0
- datalab/tests/features/macro/__init__.py +1 -0
- datalab/tests/features/macro/macro_app_test.py +28 -0
- datalab/tests/features/macro/macroeditor_unit_test.py +102 -0
- datalab/tests/features/signal/__init__.py +1 -0
- datalab/tests/features/signal/baseline_dialog_test.py +53 -0
- datalab/tests/features/signal/deltax_dialog_unit_test.py +34 -0
- datalab/tests/features/signal/fft1d_app_test.py +26 -0
- datalab/tests/features/signal/filter_app_test.py +44 -0
- datalab/tests/features/signal/fitdialog_unit_test.py +50 -0
- datalab/tests/features/signal/interpolation_app_test.py +110 -0
- datalab/tests/features/signal/loadbigsignal_app_test.py +80 -0
- datalab/tests/features/signal/multiple_rois_unit_test.py +132 -0
- datalab/tests/features/signal/pulse_features_app_test.py +118 -0
- datalab/tests/features/signal/pulse_features_roi_app_test.py +55 -0
- datalab/tests/features/signal/roi_app_test.py +78 -0
- datalab/tests/features/signal/roi_manipulation_app_test.py +261 -0
- datalab/tests/features/signal/select_xy_cursor_unit_test.py +46 -0
- datalab/tests/features/signal/signalpeakdetection_dialog_test.py +33 -0
- datalab/tests/features/signal/signals_to_image_app_test.py +98 -0
- datalab/tests/features/signal/xarray_compat_app_test.py +128 -0
- datalab/tests/features/tour_unit_test.py +22 -0
- datalab/tests/features/utilities/__init__.py +1 -0
- datalab/tests/features/utilities/installconf_unit_test.py +21 -0
- datalab/tests/features/utilities/logview_app_test.py +21 -0
- datalab/tests/features/utilities/logview_error.py +24 -0
- datalab/tests/features/utilities/logview_unit_test.py +21 -0
- datalab/tests/features/utilities/memstatus_app_test.py +42 -0
- datalab/tests/features/utilities/settings_unit_test.py +88 -0
- datalab/tests/scenarios/__init__.py +1 -0
- datalab/tests/scenarios/beautiful_app.py +121 -0
- datalab/tests/scenarios/common.py +463 -0
- datalab/tests/scenarios/demo.py +212 -0
- datalab/tests/scenarios/example_app_test.py +47 -0
- datalab/tests/scenarios/scenario_h5_app_test.py +75 -0
- datalab/tests/scenarios/scenario_ima1_app_test.py +34 -0
- datalab/tests/scenarios/scenario_ima2_app_test.py +34 -0
- datalab/tests/scenarios/scenario_mac_app_test.py +58 -0
- datalab/tests/scenarios/scenario_sig1_app_test.py +36 -0
- datalab/tests/scenarios/scenario_sig2_app_test.py +35 -0
- datalab/utils/__init__.py +1 -0
- datalab/utils/conf.py +304 -0
- datalab/utils/dephash.py +105 -0
- datalab/utils/qthelpers.py +633 -0
- datalab/utils/strings.py +34 -0
- datalab/utils/tests.py +0 -0
- datalab/widgets/__init__.py +1 -0
- datalab/widgets/connection.py +138 -0
- datalab/widgets/filedialog.py +91 -0
- datalab/widgets/fileviewer.py +84 -0
- datalab/widgets/fitdialog.py +788 -0
- datalab/widgets/h5browser.py +1048 -0
- datalab/widgets/imagebackground.py +111 -0
- datalab/widgets/instconfviewer.py +175 -0
- datalab/widgets/logviewer.py +80 -0
- datalab/widgets/signalbaseline.py +90 -0
- datalab/widgets/signalcursor.py +208 -0
- datalab/widgets/signaldeltax.py +151 -0
- datalab/widgets/signalpeak.py +199 -0
- datalab/widgets/status.py +249 -0
- datalab/widgets/textimport.py +786 -0
- datalab/widgets/warningerror.py +223 -0
- datalab/widgets/wizard.py +286 -0
- datalab_platform-1.0.0.dist-info/METADATA +121 -0
- datalab_platform-1.0.0.dist-info/RECORD +494 -0
- datalab_platform-0.0.1.dev0.dist-info/METADATA +0 -67
- datalab_platform-0.0.1.dev0.dist-info/RECORD +0 -7
- {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.0.dist-info}/WHEEL +0 -0
- {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.0.dist-info}/entry_points.txt +0 -0
- {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.0.dist-info}/licenses/LICENSE +0 -0
- {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Common functions for metadata adapters.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import dataclasses
|
|
10
|
+
import warnings
|
|
11
|
+
from typing import TYPE_CHECKING
|
|
12
|
+
|
|
13
|
+
import numpy as np
|
|
14
|
+
import pandas as pd
|
|
15
|
+
from guidata.qthelpers import exec_dialog
|
|
16
|
+
from guidata.widgets.dataframeeditor import DataFrameEditor
|
|
17
|
+
from sigima.objects import ImageObj, SignalObj
|
|
18
|
+
|
|
19
|
+
from datalab.adapters_metadata.base_adapter import BaseResultAdapter
|
|
20
|
+
from datalab.adapters_metadata.geometry_adapter import GeometryAdapter
|
|
21
|
+
from datalab.adapters_metadata.table_adapter import TableAdapter
|
|
22
|
+
from datalab.config import Conf, _
|
|
23
|
+
from datalab.objectmodel import get_short_id
|
|
24
|
+
|
|
25
|
+
if TYPE_CHECKING:
|
|
26
|
+
from qtpy.QtWidgets import QWidget
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@dataclasses.dataclass
|
|
30
|
+
class ResultData:
|
|
31
|
+
"""Result data associated to a shapetype"""
|
|
32
|
+
|
|
33
|
+
# We now store adapted objects from the new architecture
|
|
34
|
+
results: list[BaseResultAdapter] | None = None
|
|
35
|
+
ylabels: list[str] | None = None
|
|
36
|
+
short_ids: list[str] | None = None
|
|
37
|
+
|
|
38
|
+
def __bool__(self) -> bool:
|
|
39
|
+
"""Return True if there are results stored"""
|
|
40
|
+
return bool(self.results)
|
|
41
|
+
|
|
42
|
+
@property
|
|
43
|
+
def category(self) -> str:
|
|
44
|
+
"""Return category of results"""
|
|
45
|
+
if not self.results:
|
|
46
|
+
raise ValueError("No result available")
|
|
47
|
+
return self.results[0].category
|
|
48
|
+
|
|
49
|
+
@property
|
|
50
|
+
def headers(self) -> list[str]:
|
|
51
|
+
"""Return headers of results"""
|
|
52
|
+
if not self.results:
|
|
53
|
+
raise ValueError("No result available")
|
|
54
|
+
# Return the intersection of all headers
|
|
55
|
+
headers = set(self.results[0].headers)
|
|
56
|
+
if len(self.results) > 1:
|
|
57
|
+
for adapter in self.results[1:]:
|
|
58
|
+
headers.intersection_update(adapter.headers)
|
|
59
|
+
return list(headers)
|
|
60
|
+
|
|
61
|
+
def __post_init__(self):
|
|
62
|
+
"""Check and initialize fields"""
|
|
63
|
+
if self.results is None:
|
|
64
|
+
self.results = []
|
|
65
|
+
if self.ylabels is None:
|
|
66
|
+
self.ylabels = []
|
|
67
|
+
if self.short_ids is None:
|
|
68
|
+
self.short_ids = []
|
|
69
|
+
|
|
70
|
+
def append(self, adapter: BaseResultAdapter, obj: SignalObj | ImageObj) -> None:
|
|
71
|
+
"""Append a result adapter
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
adapter: Adapter to append
|
|
75
|
+
obj: Object associated to the adapter
|
|
76
|
+
"""
|
|
77
|
+
# Check that the adapter is compatible with existing ones
|
|
78
|
+
if self.results:
|
|
79
|
+
if adapter.category != self.results[0].category:
|
|
80
|
+
raise ValueError("Incompatible adapter category")
|
|
81
|
+
if len(set(self.headers).intersection(set(adapter.headers))) == 0:
|
|
82
|
+
raise ValueError("Incompatible adapter headers")
|
|
83
|
+
self.results.append(adapter)
|
|
84
|
+
df = adapter.to_dataframe()
|
|
85
|
+
for i_row_res in range(len(df)):
|
|
86
|
+
sid = get_short_id(obj)
|
|
87
|
+
ylabel = f"{adapter.func_name}({sid})"
|
|
88
|
+
if "roi_index" in df.columns:
|
|
89
|
+
i_roi = int(df.iloc[i_row_res]["roi_index"])
|
|
90
|
+
roititle = ""
|
|
91
|
+
if i_roi >= 0:
|
|
92
|
+
roititle = obj.roi.get_single_roi_title(i_roi)
|
|
93
|
+
ylabel += f"|{roititle}"
|
|
94
|
+
self.ylabels.append(ylabel)
|
|
95
|
+
self.short_ids.append(sid)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def have_results(objs: list[SignalObj | ImageObj]) -> bool:
|
|
99
|
+
"""Return True if any object has results
|
|
100
|
+
|
|
101
|
+
Args:
|
|
102
|
+
objs: List of objects
|
|
103
|
+
|
|
104
|
+
Returns:
|
|
105
|
+
True if any object has results, False otherwise
|
|
106
|
+
"""
|
|
107
|
+
return any(
|
|
108
|
+
item for obj in objs for item in GeometryAdapter.iterate_from_obj(obj)
|
|
109
|
+
) or any(item for obj in objs for item in TableAdapter.iterate_from_obj(obj))
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def have_geometry_results(objs: list[SignalObj | ImageObj]) -> bool:
|
|
113
|
+
"""Return True if any object has geometry results
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
objs: List of objects
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
True if any object has geometry results, False otherwise
|
|
120
|
+
"""
|
|
121
|
+
return any(item for obj in objs for item in GeometryAdapter.iterate_from_obj(obj))
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def create_resultdata_dict(
|
|
125
|
+
objs: list[SignalObj | ImageObj],
|
|
126
|
+
) -> dict[str, ResultData]:
|
|
127
|
+
"""Return result data dictionary
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
objs: List of objects
|
|
131
|
+
|
|
132
|
+
Returns:
|
|
133
|
+
Result data dictionary: keys are result categories, values are ResultData
|
|
134
|
+
"""
|
|
135
|
+
rdatadict: dict[str, ResultData] = {}
|
|
136
|
+
for obj in objs:
|
|
137
|
+
for adapter in list(GeometryAdapter.iterate_from_obj(obj)) + list(
|
|
138
|
+
TableAdapter.iterate_from_obj(obj)
|
|
139
|
+
):
|
|
140
|
+
rdata = rdatadict.setdefault(adapter.category, ResultData())
|
|
141
|
+
rdata.append(adapter, obj)
|
|
142
|
+
return rdatadict
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def show_resultdata(parent: QWidget, rdata: ResultData, object_name: str = "") -> None:
|
|
146
|
+
"""Show result data in a DataFrame editor window
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
parent: Parent widget
|
|
150
|
+
rdata: Result data to show
|
|
151
|
+
object_name: Optional object name for the dialog
|
|
152
|
+
"""
|
|
153
|
+
with warnings.catch_warnings():
|
|
154
|
+
warnings.simplefilter("ignore", RuntimeWarning)
|
|
155
|
+
|
|
156
|
+
# Generate dataframes with visible columns only
|
|
157
|
+
# Use the object-level visible_only parameter for cleaner implementation
|
|
158
|
+
dfs = [result.to_dataframe(visible_only=True) for result in rdata.results]
|
|
159
|
+
|
|
160
|
+
# Combine all dataframes
|
|
161
|
+
df = pd.concat(dfs, ignore_index=True)
|
|
162
|
+
|
|
163
|
+
# Add comparison columns if we have multiple results of the same kind
|
|
164
|
+
if len(dfs) > 1:
|
|
165
|
+
df = _add_comparison_columns_to_dataframe(df, rdata)
|
|
166
|
+
|
|
167
|
+
# Remove roi_index column for display (not needed in the GUI)
|
|
168
|
+
if "roi_index" in df.columns:
|
|
169
|
+
df = df.drop(columns=["roi_index"])
|
|
170
|
+
|
|
171
|
+
df.set_index(pd.Index(rdata.ylabels), inplace=True)
|
|
172
|
+
dlg = DataFrameEditor(parent)
|
|
173
|
+
dlg.setup_and_check(
|
|
174
|
+
df,
|
|
175
|
+
_("Results") + f" ({rdata.category})",
|
|
176
|
+
readonly=True,
|
|
177
|
+
add_title_suffix=False,
|
|
178
|
+
)
|
|
179
|
+
if object_name:
|
|
180
|
+
dlg.setObjectName(object_name)
|
|
181
|
+
dlg.resize(750, 300)
|
|
182
|
+
exec_dialog(dlg)
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def _add_comparison_columns_to_dataframe(
|
|
186
|
+
df: pd.DataFrame, rdata: ResultData
|
|
187
|
+
) -> pd.DataFrame:
|
|
188
|
+
"""Add comparison columns to dataframe with ROI-aware grouping.
|
|
189
|
+
|
|
190
|
+
For each original column, adds one comparison column showing the difference
|
|
191
|
+
between the current row and the corresponding reference row.
|
|
192
|
+
|
|
193
|
+
Args:
|
|
194
|
+
df: Combined DataFrame with all results
|
|
195
|
+
rdata: ResultData containing ylabels and short_ids
|
|
196
|
+
|
|
197
|
+
Returns:
|
|
198
|
+
DataFrame with comparison columns added (one Δ column per original column)
|
|
199
|
+
"""
|
|
200
|
+
# Build signal/image groups:
|
|
201
|
+
# list of (object_id, start_row, end_row) for each signal/image
|
|
202
|
+
obj_groups = []
|
|
203
|
+
current_obj_id = None
|
|
204
|
+
group_start = 0
|
|
205
|
+
|
|
206
|
+
for i, obj_id in enumerate(rdata.short_ids):
|
|
207
|
+
if obj_id != current_obj_id:
|
|
208
|
+
# New signal group
|
|
209
|
+
if current_obj_id is not None:
|
|
210
|
+
# Close previous group
|
|
211
|
+
obj_groups.append((current_obj_id, group_start, i - 1))
|
|
212
|
+
current_obj_id = obj_id
|
|
213
|
+
group_start = i
|
|
214
|
+
|
|
215
|
+
# Close the last group
|
|
216
|
+
if current_obj_id is not None:
|
|
217
|
+
obj_groups.append((current_obj_id, group_start, len(rdata.ylabels) - 1))
|
|
218
|
+
|
|
219
|
+
# If we only have one signal group, no need for comparisons
|
|
220
|
+
if len(obj_groups) <= 1:
|
|
221
|
+
return df
|
|
222
|
+
|
|
223
|
+
# Use the first signal group as reference
|
|
224
|
+
reference_group = obj_groups[0]
|
|
225
|
+
_ref_obj_id, reference_start, reference_end = reference_group
|
|
226
|
+
|
|
227
|
+
# Get columns to compare (exclude roi_index)
|
|
228
|
+
cols_to_compare = [col for col in df.columns if col != "roi_index"]
|
|
229
|
+
|
|
230
|
+
# Create new dataframe with original columns plus one comparison column per
|
|
231
|
+
# original column
|
|
232
|
+
result_df = df.copy()
|
|
233
|
+
|
|
234
|
+
# Add comparison columns - one per original column
|
|
235
|
+
for col in cols_to_compare:
|
|
236
|
+
comparison_col_name = f"Δ({col})"
|
|
237
|
+
comparison_values = []
|
|
238
|
+
|
|
239
|
+
# For each row in the entire dataframe
|
|
240
|
+
for row_idx in range(len(df)):
|
|
241
|
+
# Find which group this row belongs to
|
|
242
|
+
row_group_idx = None
|
|
243
|
+
for group_idx, (obj_id, start, end) in enumerate(obj_groups):
|
|
244
|
+
if start <= row_idx <= end:
|
|
245
|
+
row_group_idx = group_idx
|
|
246
|
+
break
|
|
247
|
+
|
|
248
|
+
if row_group_idx == 0:
|
|
249
|
+
# Reference group - no comparison needed
|
|
250
|
+
comparison_values.append("")
|
|
251
|
+
elif row_group_idx is not None:
|
|
252
|
+
# Non-reference group - calculate comparison with corresponding
|
|
253
|
+
# reference row
|
|
254
|
+
group_start = obj_groups[row_group_idx][1]
|
|
255
|
+
ref_row_idx = reference_start + (row_idx - group_start)
|
|
256
|
+
if ref_row_idx <= reference_end:
|
|
257
|
+
ref_val = df.iloc[ref_row_idx][col]
|
|
258
|
+
curr_val = df.iloc[row_idx][col]
|
|
259
|
+
comparison_values.append(
|
|
260
|
+
_compute_comparison_value(ref_val, curr_val)
|
|
261
|
+
)
|
|
262
|
+
else:
|
|
263
|
+
comparison_values.append("")
|
|
264
|
+
else:
|
|
265
|
+
# Should not happen, but handle gracefully
|
|
266
|
+
comparison_values.append("")
|
|
267
|
+
|
|
268
|
+
# Insert comparison column right after the original column
|
|
269
|
+
col_idx = result_df.columns.get_loc(col)
|
|
270
|
+
result_df.insert(col_idx + 1, comparison_col_name, comparison_values)
|
|
271
|
+
|
|
272
|
+
return result_df
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
def _compute_comparison_value(ref_val, curr_val) -> str:
|
|
276
|
+
"""Compute a comparison value between reference and current values.
|
|
277
|
+
|
|
278
|
+
Args:
|
|
279
|
+
ref_val: Reference value
|
|
280
|
+
curr_val: Current value to compare
|
|
281
|
+
|
|
282
|
+
Returns:
|
|
283
|
+
String representation of the comparison
|
|
284
|
+
"""
|
|
285
|
+
# Handle different data types
|
|
286
|
+
if pd.isna(ref_val) or pd.isna(curr_val):
|
|
287
|
+
return "N/A"
|
|
288
|
+
if isinstance(ref_val, str) or isinstance(curr_val, str):
|
|
289
|
+
# String comparison
|
|
290
|
+
return "=" if str(ref_val) == str(curr_val) else "≠"
|
|
291
|
+
if isinstance(ref_val, (int, float, np.integer, np.floating)) and isinstance(
|
|
292
|
+
curr_val, (int, float, np.integer, np.floating)
|
|
293
|
+
):
|
|
294
|
+
# Numeric comparison - show difference
|
|
295
|
+
diff = curr_val - ref_val
|
|
296
|
+
# For integers, check exact equality; for floats, use small tolerance
|
|
297
|
+
if isinstance(ref_val, (int, np.integer)) and isinstance(
|
|
298
|
+
curr_val, (int, np.integer)
|
|
299
|
+
):
|
|
300
|
+
tolerance = 0
|
|
301
|
+
else:
|
|
302
|
+
tolerance = 1e-10
|
|
303
|
+
|
|
304
|
+
if abs(diff) <= tolerance:
|
|
305
|
+
return "="
|
|
306
|
+
|
|
307
|
+
# Format the difference with appropriate sign
|
|
308
|
+
sign = "+" if diff > 0 else ""
|
|
309
|
+
return f"{sign}{diff:.4g}"
|
|
310
|
+
|
|
311
|
+
# Default comparison
|
|
312
|
+
return "=" if ref_val == curr_val else "≠"
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
def resultadapter_to_html(
|
|
316
|
+
adapter: BaseResultAdapter | list[BaseResultAdapter],
|
|
317
|
+
obj: SignalObj | ImageObj,
|
|
318
|
+
visible_only: bool = True,
|
|
319
|
+
transpose_single_row: bool = True,
|
|
320
|
+
max_cells: int | None = None,
|
|
321
|
+
**kwargs,
|
|
322
|
+
) -> str:
|
|
323
|
+
"""Convert a result adapter to HTML format
|
|
324
|
+
|
|
325
|
+
Args:
|
|
326
|
+
adapter: Adapter to convert, or list of adapters to concatenate
|
|
327
|
+
obj: Object associated to the adapter
|
|
328
|
+
visible_only: If True, include only visible headers based on display
|
|
329
|
+
preferences. Default is False.
|
|
330
|
+
transpose_single_row: If True, transpose the table when there's only one row
|
|
331
|
+
max_cells: Maximum number of table cells (rows × columns) to display per
|
|
332
|
+
result. If None, use the configuration value. If a result has more cells,
|
|
333
|
+
it will be truncated with a notice.
|
|
334
|
+
**kwargs: Additional arguments passed to DataFrame.to_html()
|
|
335
|
+
|
|
336
|
+
Returns:
|
|
337
|
+
HTML representation of the adapter
|
|
338
|
+
"""
|
|
339
|
+
if not isinstance(adapter, BaseResultAdapter) and not all(
|
|
340
|
+
isinstance(adp, BaseResultAdapter) for adp in adapter
|
|
341
|
+
):
|
|
342
|
+
raise ValueError(
|
|
343
|
+
"Adapter must be a BaseResultAdapter "
|
|
344
|
+
"or a list of BaseResultAdapter instances"
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
# Get max_cells from config if not provided
|
|
348
|
+
if max_cells is None:
|
|
349
|
+
max_cells = Conf.view.max_cells_in_label.get(100)
|
|
350
|
+
|
|
351
|
+
if isinstance(adapter, BaseResultAdapter):
|
|
352
|
+
# Get the dataframe FIRST to check truncation needs
|
|
353
|
+
df = adapter.to_dataframe(visible_only=visible_only)
|
|
354
|
+
|
|
355
|
+
# Remove roi_index column for display calculations
|
|
356
|
+
display_df = df.drop(columns=["roi_index"]) if "roi_index" in df.columns else df
|
|
357
|
+
|
|
358
|
+
# For merged labels, limit display columns for readability
|
|
359
|
+
max_display_cols = Conf.view.max_cols_in_label.get(20)
|
|
360
|
+
num_cols = len(display_df.columns)
|
|
361
|
+
cols_truncated = num_cols > max_display_cols
|
|
362
|
+
|
|
363
|
+
if cols_truncated:
|
|
364
|
+
display_df = display_df.iloc[:, :max_display_cols]
|
|
365
|
+
num_cols = max_display_cols
|
|
366
|
+
|
|
367
|
+
# Calculate number of cells (rows × columns)
|
|
368
|
+
num_rows = len(adapter.result)
|
|
369
|
+
num_cells = num_rows * num_cols
|
|
370
|
+
|
|
371
|
+
# Check if truncation is needed BEFORE calling to_html()
|
|
372
|
+
if num_cells > max_cells or cols_truncated:
|
|
373
|
+
# Calculate how many rows we can display given max_cells
|
|
374
|
+
max_rows = max(1, max_cells // num_cols) if num_cols > 0 else num_rows
|
|
375
|
+
|
|
376
|
+
# Truncate to max_rows and make a copy to avoid SettingWithCopyWarning
|
|
377
|
+
df_truncated = display_df.head(max_rows).copy()
|
|
378
|
+
|
|
379
|
+
# Generate HTML directly from truncated DataFrame for performance
|
|
380
|
+
# This is MUCH faster than calling adapter.to_html() on full data
|
|
381
|
+
html_kwargs = {"border": 0}
|
|
382
|
+
html_kwargs.update(kwargs)
|
|
383
|
+
|
|
384
|
+
# Format numeric columns efficiently
|
|
385
|
+
for col in df_truncated.select_dtypes(include=["number"]).columns:
|
|
386
|
+
df_truncated[col] = df_truncated[col].map(
|
|
387
|
+
lambda x: f"{x:.3g}" if pd.notna(x) else x
|
|
388
|
+
)
|
|
389
|
+
|
|
390
|
+
text = f'<u><b style="color: #5294e2">{adapter.result.title}</b></u>:'
|
|
391
|
+
text += df_truncated.to_html(**html_kwargs)
|
|
392
|
+
|
|
393
|
+
# Add truncation notice
|
|
394
|
+
omitted_parts = []
|
|
395
|
+
if num_rows > max_rows:
|
|
396
|
+
omitted_parts.append(_("%d more rows") % (num_rows - max_rows))
|
|
397
|
+
if cols_truncated:
|
|
398
|
+
num_omitted_cols = len(df.columns) - max_display_cols
|
|
399
|
+
omitted_parts.append(_("%d more columns") % num_omitted_cols)
|
|
400
|
+
if omitted_parts:
|
|
401
|
+
omitted_str = _("%s omitted") % ", ".join(omitted_parts)
|
|
402
|
+
text += f"<p><i>... ({omitted_str})</i></p>"
|
|
403
|
+
|
|
404
|
+
return text
|
|
405
|
+
|
|
406
|
+
# No truncation needed, use the standard adapter.to_html() method
|
|
407
|
+
return adapter.to_html(
|
|
408
|
+
obj=obj,
|
|
409
|
+
visible_only=visible_only,
|
|
410
|
+
transpose_single_row=transpose_single_row,
|
|
411
|
+
**kwargs,
|
|
412
|
+
)
|
|
413
|
+
|
|
414
|
+
# For lists of adapters, recursively process each one
|
|
415
|
+
return "<hr>".join(
|
|
416
|
+
[
|
|
417
|
+
resultadapter_to_html(
|
|
418
|
+
res, obj, visible_only, transpose_single_row, max_cells
|
|
419
|
+
)
|
|
420
|
+
for res in adapter
|
|
421
|
+
]
|
|
422
|
+
)
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Adapter for Sigima's GeometryResult, providing features
|
|
5
|
+
for storing and retrieving those objects as metadata for DataLab's signal
|
|
6
|
+
and image objects.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from typing import ClassVar
|
|
12
|
+
|
|
13
|
+
from sigima.objects import GeometryResult, ImageObj, SignalObj
|
|
14
|
+
|
|
15
|
+
from datalab.adapters_metadata.base_adapter import BaseResultAdapter
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class GeometryAdapter(BaseResultAdapter):
|
|
19
|
+
"""Adapter for GeometryResult objects.
|
|
20
|
+
|
|
21
|
+
This adapter provides a unified interface for working with GeometryResult objects,
|
|
22
|
+
including metadata storage/retrieval and various data representations.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
geometry: GeometryResult object to adapt
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
# Class constants for metadata storage
|
|
29
|
+
META_PREFIX: ClassVar[str] = "Geometry_"
|
|
30
|
+
|
|
31
|
+
def __init__(self, geometry: GeometryResult) -> None:
|
|
32
|
+
super().__init__(geometry)
|
|
33
|
+
|
|
34
|
+
@classmethod
|
|
35
|
+
def from_geometry_result(cls, geometry: GeometryResult) -> GeometryAdapter:
|
|
36
|
+
"""Create GeometryAdapter from GeometryResult.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
geometry: GeometryResult object
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
GeometryAdapter instance
|
|
43
|
+
"""
|
|
44
|
+
return cls(geometry)
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
def headers(self) -> list[str]:
|
|
48
|
+
"""Get column headers for the coordinates.
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
List of column headers
|
|
52
|
+
"""
|
|
53
|
+
# Get headers directly from the DataFrame
|
|
54
|
+
df = self.result.to_dataframe()
|
|
55
|
+
# Return coordinate columns (exclude 'roi_index' if present)
|
|
56
|
+
return [col for col in df.columns if col != "roi_index"]
|
|
57
|
+
|
|
58
|
+
@property
|
|
59
|
+
def category(self) -> str:
|
|
60
|
+
"""Get the category.
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
Category
|
|
64
|
+
"""
|
|
65
|
+
return f"shape_{self.result.kind.value}"
|
|
66
|
+
|
|
67
|
+
@staticmethod
|
|
68
|
+
def add_geometry_result_to_obj(
|
|
69
|
+
geometry: GeometryResult, obj: SignalObj | ImageObj
|
|
70
|
+
) -> None:
|
|
71
|
+
"""Static method to add GeometryResult to object.
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
geometry: GeometryResult object
|
|
75
|
+
obj: Signal or image object
|
|
76
|
+
"""
|
|
77
|
+
# Create adapter and add to object
|
|
78
|
+
adapter = GeometryAdapter.from_geometry_result(geometry)
|
|
79
|
+
adapter.add_to(obj)
|
|
80
|
+
|
|
81
|
+
@classmethod
|
|
82
|
+
def from_metadata_entry(cls, obj: SignalObj | ImageObj, key: str):
|
|
83
|
+
"""Create a geometry result adapter from a metadata entry.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
obj: Object containing the metadata
|
|
87
|
+
key: Metadata key for the array data
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
GeometryAdapter object
|
|
91
|
+
|
|
92
|
+
Raises:
|
|
93
|
+
ValueError: Invalid metadata entry
|
|
94
|
+
"""
|
|
95
|
+
# Load the geometry data from the dictionary
|
|
96
|
+
geometry_dict = obj.metadata[key]
|
|
97
|
+
geometry = GeometryResult.from_dict(geometry_dict)
|
|
98
|
+
return cls(geometry)
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Adapter for Sigima's TableResult, providing features
|
|
5
|
+
for storing and retrieving those objects as metadata for DataLab's signal
|
|
6
|
+
and image objects.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from typing import ClassVar, Union
|
|
12
|
+
|
|
13
|
+
from sigima.objects import ImageObj, SignalObj
|
|
14
|
+
from sigima.objects.scalar import NO_ROI, TableResult
|
|
15
|
+
|
|
16
|
+
from datalab.adapters_metadata.base_adapter import BaseResultAdapter
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class TableAdapter(BaseResultAdapter):
|
|
20
|
+
"""Adapter for TableResult objects.
|
|
21
|
+
|
|
22
|
+
This adapter provides a unified interface for working with TableResult objects,
|
|
23
|
+
including metadata storage/retrieval and various data representations.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
table: TableResult object to adapt
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
# Class constants for metadata storage
|
|
30
|
+
META_PREFIX: ClassVar[str] = "Table_"
|
|
31
|
+
|
|
32
|
+
def __init__(self, table: TableResult) -> None:
|
|
33
|
+
super().__init__(table)
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
def headers(self) -> list[str]:
|
|
37
|
+
"""Get the column headers.
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
Column headers
|
|
41
|
+
"""
|
|
42
|
+
return list(self.result.headers)
|
|
43
|
+
|
|
44
|
+
@property
|
|
45
|
+
def category(self) -> str:
|
|
46
|
+
"""Get the category.
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
Category (uses the title for backward compatibility)
|
|
50
|
+
"""
|
|
51
|
+
return self.result.title
|
|
52
|
+
|
|
53
|
+
def get_unique_roi_indices(self) -> list[int]:
|
|
54
|
+
"""Get unique ROI indices present in the data.
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
List of unique ROI indices
|
|
58
|
+
"""
|
|
59
|
+
df = self.to_dataframe()
|
|
60
|
+
if "roi_index" in df.columns:
|
|
61
|
+
return sorted(df["roi_index"].unique().tolist())
|
|
62
|
+
return [NO_ROI] if len(df) > 0 else []
|
|
63
|
+
|
|
64
|
+
@classmethod
|
|
65
|
+
def from_metadata_entry(cls, obj: Union[SignalObj, ImageObj], key: str):
|
|
66
|
+
"""Create a table result adapter from a metadata entry.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
obj: Object containing the metadata
|
|
70
|
+
key: Metadata key for the table data
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
TableAdapter object
|
|
74
|
+
|
|
75
|
+
Raises:
|
|
76
|
+
ValueError: Invalid metadata entry
|
|
77
|
+
"""
|
|
78
|
+
if not cls.match(key, obj.metadata[key]):
|
|
79
|
+
raise ValueError(f"Invalid metadata key for table result: {key}")
|
|
80
|
+
|
|
81
|
+
# Parse the metadata entry as a TableResult dictionary
|
|
82
|
+
table_dict = obj.metadata[key]
|
|
83
|
+
table = TableResult.from_dict(table_dict)
|
|
84
|
+
return cls(table)
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Adapters for PlotPy
|
|
5
|
+
===================
|
|
6
|
+
|
|
7
|
+
The :mod:`datalab.adapters_plotpy` package provides adapters for
|
|
8
|
+
PlotPy to integrate with DataLab's data model and GUI.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"CURVESTYLES",
|
|
13
|
+
"CircularROIPlotPyAdapter",
|
|
14
|
+
"GeometryPlotPyAdapter",
|
|
15
|
+
"ImageObjPlotPyAdapter",
|
|
16
|
+
"PolygonalROIPlotPyAdapter",
|
|
17
|
+
"RectangularROIPlotPyAdapter",
|
|
18
|
+
"SegmentROIPlotPyAdapter",
|
|
19
|
+
"SignalObjPlotPyAdapter",
|
|
20
|
+
"SignalROIPlotPyAdapter",
|
|
21
|
+
"TablePlotPyAdapter",
|
|
22
|
+
"TypePlotItem",
|
|
23
|
+
"TypeROIItem",
|
|
24
|
+
"configure_roi_item",
|
|
25
|
+
"create_adapter_from_object",
|
|
26
|
+
"items_to_json",
|
|
27
|
+
"json_to_items",
|
|
28
|
+
"plotitem_to_singleroi",
|
|
29
|
+
"singleroi_to_plotitem",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
from .base import items_to_json, json_to_items
|
|
34
|
+
from .converters import (
|
|
35
|
+
create_adapter_from_object,
|
|
36
|
+
plotitem_to_singleroi,
|
|
37
|
+
singleroi_to_plotitem,
|
|
38
|
+
)
|
|
39
|
+
from .objects.base import TypePlotItem
|
|
40
|
+
from .objects.image import (
|
|
41
|
+
ImageObjPlotPyAdapter,
|
|
42
|
+
)
|
|
43
|
+
from .objects.scalar import (
|
|
44
|
+
GeometryPlotPyAdapter,
|
|
45
|
+
TablePlotPyAdapter,
|
|
46
|
+
)
|
|
47
|
+
from .objects.signal import CURVESTYLES, SignalObjPlotPyAdapter
|
|
48
|
+
from .roi.base import TypeROIItem, configure_roi_item
|
|
49
|
+
from .roi.image import (
|
|
50
|
+
CircularROIPlotPyAdapter,
|
|
51
|
+
PolygonalROIPlotPyAdapter,
|
|
52
|
+
RectangularROIPlotPyAdapter,
|
|
53
|
+
)
|
|
54
|
+
from .roi.signal import SegmentROIPlotPyAdapter, SignalROIPlotPyAdapter
|