dclab 0.64.3__tar.gz → 0.66.0__tar.gz
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.
Potentially problematic release.
This version of dclab might be problematic. Click here for more details.
- {dclab-0.64.3 → dclab-0.66.0}/CHANGELOG +7 -0
- {dclab-0.64.3 → dclab-0.66.0}/PKG-INFO +1 -1
- {dclab-0.64.3 → dclab-0.66.0}/dclab/_version.py +2 -2
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/core.py +3 -1
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/export.py +6 -3
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/feat_basin.py +36 -16
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/writer.py +26 -7
- {dclab-0.64.3 → dclab-0.66.0}/dclab.egg-info/PKG-INFO +1 -1
- {dclab-0.64.3 → dclab-0.66.0}/dclab.egg-info/SOURCES.txt +1 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/sec_av_basins/index.rst +6 -0
- {dclab-0.64.3 → dclab-0.66.0}/scripts/requirements.txt +3 -1
- dclab-0.66.0/scripts/vid2dc.py +240 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_rtdc_feat_basin.py +28 -4
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_rtdc_writer.py +53 -0
- {dclab-0.64.3 → dclab-0.66.0}/.gitignore +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/.readthedocs.yml +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/LICENSE +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/MANIFEST.in +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/README.rst +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/__init__.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/cached.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/cli/__init__.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/cli/common.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/cli/task_compress.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/cli/task_condense.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/cli/task_join.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/cli/task_repack.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/cli/task_split.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/cli/task_tdms2rtdc.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/cli/task_verify_dataset.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/definitions/__init__.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/definitions/feat_const.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/definitions/feat_logic.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/definitions/meta_const.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/definitions/meta_logic.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/definitions/meta_parse.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/downsampling.pyx +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/external/__init__.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/external/packaging/LICENSE +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/external/packaging/LICENSE.APACHE +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/external/packaging/LICENSE.BSD +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/external/packaging/__init__.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/external/packaging/_structures.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/external/packaging/version.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/external/skimage/LICENSE +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/external/skimage/__init__.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/external/skimage/_find_contours.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/external/skimage/_find_contours_cy.pyx +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/external/skimage/_pnpoly.pyx +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/external/skimage/_shared/__init__.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/external/skimage/_shared/geometry.pxd +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/external/skimage/_shared/geometry.pyx +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/external/skimage/measure.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/external/skimage/pnpoly.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/external/statsmodels/LICENSE +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/external/statsmodels/__init__.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/external/statsmodels/nonparametric/__init__.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/external/statsmodels/nonparametric/_kernel_base.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/external/statsmodels/nonparametric/kernel_density.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/external/statsmodels/nonparametric/kernels.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/features/__init__.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/features/bright.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/features/bright_bc.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/features/bright_perc.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/features/contour.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/features/emodulus/__init__.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/features/emodulus/load.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/features/emodulus/lut_HE-2D-FEM-22.txt +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/features/emodulus/lut_HE-3D-FEM-22.txt +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/features/emodulus/lut_LE-2D-FEM-19.txt +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/features/emodulus/pxcorr.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/features/emodulus/scale_linear.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/features/emodulus/viscosity.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/features/fl_crosstalk.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/features/inert_ratio.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/features/volume.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/http_utils.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/isoelastics/__init__.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/isoelastics/iso_HE-2D-FEM-22-area_um-deform.txt +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/isoelastics/iso_HE-2D-FEM-22-volume-deform.txt +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/isoelastics/iso_HE-3D-FEM-22-area_um-deform.txt +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/isoelastics/iso_HE-3D-FEM-22-volume-deform.txt +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/isoelastics/iso_LE-2D-FEM-19-area_um-deform.txt +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/isoelastics/iso_LE-2D-FEM-19-volume-deform.txt +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/isoelastics/iso_LE-2D-ana-18-area_um-deform.txt +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/kde/__init__.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/kde/base.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/kde/contours.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/kde/methods.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/kde_contours.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/kde_methods.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/lme4/__init__.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/lme4/lme4_template.R +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/lme4/rsetup.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/lme4/wrapr.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/polygon_filter.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/__init__.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/check.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/config.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/copier.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/feat_anc_core/__init__.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/feat_anc_core/af_basic.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/feat_anc_core/af_emodulus.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/feat_anc_core/af_fl_max_ctc.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/feat_anc_core/af_image_contour.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/feat_anc_core/af_ml_class.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/feat_anc_core/ancillary_feature.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/feat_anc_ml/__init__.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/feat_anc_plugin/__init__.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/feat_anc_plugin/plugin_feature.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/feat_temp.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/filter.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/fmt_dcor/__init__.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/fmt_dcor/access_token.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/fmt_dcor/api.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/fmt_dcor/base.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/fmt_dcor/basin.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/fmt_dcor/logs.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/fmt_dcor/tables.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/fmt_dict.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/fmt_hdf5/__init__.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/fmt_hdf5/base.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/fmt_hdf5/basin.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/fmt_hdf5/events.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/fmt_hdf5/feat_defect.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/fmt_hdf5/logs.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/fmt_hdf5/tables.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/fmt_hierarchy/__init__.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/fmt_hierarchy/base.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/fmt_hierarchy/events.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/fmt_hierarchy/hfilter.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/fmt_hierarchy/mapper.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/fmt_http.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/fmt_s3.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/fmt_tdms/__init__.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/fmt_tdms/event_contour.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/fmt_tdms/event_image.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/fmt_tdms/event_mask.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/fmt_tdms/event_trace.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/fmt_tdms/exc.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/fmt_tdms/naming.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/load.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/rtdc_dataset/meta_table.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/statistics.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/util.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab/warn.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab.egg-info/dependency_links.txt +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab.egg-info/entry_points.txt +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab.egg-info/requires.txt +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/dclab.egg-info/top_level.txt +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/.gitignore +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/README.md +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/conf.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/data/example.poly +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/data/example.rtdc +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/data/example_plugin.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/data/example_plugin_metadata.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/data/example_traces.rtdc +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/data/example_video.rtdc +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/dclab.bib +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/extensions/dclab_defs.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/extensions/fancy_include.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/extensions/github_changelog.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/extensions/simple_argparse.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/figures/DCOR_API_Token_website.png +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/index.rst +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/logo/dc_logo.png +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/logo/dc_logo.svg +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/logo/dclab.png +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/logo/dclab.svg +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/logo/dclab_large_white.png +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/logo/dclab_large_white.svg +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/logo/favicon.ico +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/logo/favicon.svg +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/requirements.txt +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/sec_advanced_usage.rst +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/sec_av_basins/basin_example_workflows.svg +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/sec_av_dc_io.rst +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/sec_av_dc_usage.rst +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/sec_av_dcor.rst +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/sec_av_emodulus/figures_emodulus/.gitignore +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/sec_av_emodulus/figures_emodulus/emodulus_20um_HE-2D-FEM-22.png +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/sec_av_emodulus/figures_emodulus/emodulus_20um_HE-3D-FEM-22.png +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/sec_av_emodulus/figures_emodulus/emodulus_20um_LE-2D-FEM-19.png +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/sec_av_emodulus/figures_emodulus/plot_emodulus_lut.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/sec_av_emodulus/figures_emodulus/requirements.txt +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/sec_av_emodulus/figures_viscosity/LICENSE +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/sec_av_emodulus/figures_viscosity/buyukurganci_22_fig3a.jpg +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/sec_av_emodulus/figures_viscosity/buyukurganci_22_fig3a.pdf +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/sec_av_emodulus/index.rst +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/sec_av_feat_plugin.rst +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/sec_av_feat_temp.rst +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/sec_av_fluorescence.rst +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/sec_av_lme4.rst +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/sec_av_notation.rst +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/sec_av_s3.rst +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/sec_av_scatter.rst +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/sec_changelog.rst +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/sec_cli.rst +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/sec_code_reference.rst +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/sec_examples.rst +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/sec_getting_started.rst +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/docs/sec_z_bib.rst +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/examples/emodulus_dcor.jpg +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/examples/emodulus_dcor.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/examples/generate_example_images.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/examples/isoelastics.jpg +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/examples/isoelastics.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/examples/isoelastics_custom.jpg +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/examples/isoelastics_custom.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/examples/lme4_glmer_diff.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/examples/lme4_lmer.jpg +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/examples/lme4_lmer.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/examples/overview_plot.jpg +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/examples/overview_plot.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/examples/plugin_example.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/examples/plugin_usage.jpg +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/examples/plugin_usage.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/examples/viscosity_models.jpg +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/examples/viscosity_models.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/pyproject.toml +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/scripts/.gitignore +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/scripts/README.md +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/scripts/fem2iso_volume.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/scripts/fem2lutiso_std.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/scripts/fem2rtdc.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/scripts/lut_recipes/__init__.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/scripts/lut_recipes/hooks/LUT_analytical_linear-elastic_2Daxis.txt +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/scripts/lut_recipes/hooks/README.md +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/scripts/lut_recipes/hooks/__init__.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/scripts/lut_recipes/hooks/common.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/scripts/lut_recipes/hooks/he_2d_fem_22.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/scripts/lut_recipes/hooks/he_3d_fem_22.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/scripts/lut_recipes/hooks/le_2d_fem_19.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/scripts/lut_recipes/lut_processor.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/scripts/pixelation_correction.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/scripts/pixelation_correction_2020.png +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/scripts/pixelation_correction_2022.png +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/setup.cfg +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/setup.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/README.md +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/conftest.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/data/README.md +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/data/example_access_token.dcor-access +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/data/example_isoelastics.txt +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/data/feat_anc_plugin_creative.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/data/fmt-hdf5_fl-no-contour_2019.zip +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/data/fmt-hdf5_fl_2017.zip +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/data/fmt-hdf5_fl_2018.zip +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/data/fmt-hdf5_fl_wide-channel_2023.zip +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/data/fmt-hdf5_image-bg_2020.zip +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/data/fmt-hdf5_image-mask-blood_2021.zip +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/data/fmt-hdf5_mask-contour_2018.zip +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/data/fmt-hdf5_polygon_gate_2021.zip +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/data/fmt-hdf5_raw-cytoshot-exported.zip +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/data/fmt-hdf5_segfault-compound_2023.zip +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/data/fmt-hdf5_wide-channel_2023.zip +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/data/fmt-tdms_2fl-no-image_2017.zip +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/data/fmt-tdms_fl-image-bright_2017.zip +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/data/fmt-tdms_fl-image-large-fov_2017.zip +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/data/fmt-tdms_fl-image_2016.zip +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/data/fmt-tdms_fl_2015.zip +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/data/fmt-tdms_minimal_2016.zip +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/data/fmt-tdms_shapein-2.0.1-no-image_2017.zip +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/helper_methods.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/requirements.txt +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_cache.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_cli.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_cli_argparse.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_cli_compress.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_cli_condense.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_cli_join.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_cli_repack.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_cli_split.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_config_value_mapping.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_dfn_feat.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_dfn_meta.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_downsampling.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_feat_bright.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_feat_bright_bc.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_feat_bright_perc.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_feat_contour.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_feat_emodulus.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_feat_emodulus_viscosity.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_feat_fl_crosstalk.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_feat_inert_ratio.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_feat_volume.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_http_utils.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_isoelastics.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_kde.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_kde_contours.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_kde_deprecations.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_kde_methods.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_lme4.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_lut_he_2d_fem_22.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_lut_he_3d_fem_22.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_polygon_contains.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_polygon_filter.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_rtdc_check_dataset.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_rtdc_config.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_rtdc_copier.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_rtdc_core_feat.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_rtdc_downsampling.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_rtdc_export.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_rtdc_export_avi.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_rtdc_export_fcs.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_rtdc_export_hdf5.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_rtdc_export_tsv.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_rtdc_feat_anc_core.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_rtdc_feat_anc_ml.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_rtdc_feat_anc_plugin.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_rtdc_feat_basin_mapped.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_rtdc_feat_basin_perishable.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_rtdc_feat_temp.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_rtdc_filter.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_rtdc_fmt_dcor.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_rtdc_fmt_dcor_access_token.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_rtdc_fmt_dcor_basin.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_rtdc_fmt_dcor_private.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_rtdc_fmt_dict.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_rtdc_fmt_hdf5.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_rtdc_fmt_hdf5_basins.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_rtdc_fmt_hdf5_basins_internal.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_rtdc_fmt_hierarchy.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_rtdc_fmt_http.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_rtdc_fmt_http_basin.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_rtdc_fmt_s3.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_rtdc_fmt_s3_basin.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_rtdc_fmt_tdms.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_rtdc_hash.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_rtdc_kde.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_rtdc_limit_events.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_statistics.py +0 -0
- {dclab-0.64.3 → dclab-0.66.0}/tests/test_util.py +0 -0
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
0.66.0
|
|
2
|
+
- feat: introduce optional identifiers for basins
|
|
3
|
+
- ref: rename `measurement_identifier` to `referrer_identifier`
|
|
4
|
+
in the `feat_basin` context to clarify which dataset it belongs to
|
|
5
|
+
0.65.0
|
|
6
|
+
- scripts: add `vid2dc.py` for converting videos to raw .rtdc files
|
|
7
|
+
- enh: run identifier splits use "_" upon export and have increased length
|
|
1
8
|
0.64.3
|
|
2
9
|
- ci: use GitHub windows-latest runner for building wheel
|
|
3
10
|
0.64.2
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dclab
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.66.0
|
|
4
4
|
Summary: Library for real-time deformability cytometry (RT-DC)
|
|
5
5
|
Author: Benedikt Hartmann, Eoghan O'Connell, Maik Herbig, Maximilian Schlögel, Nadia Sbaa, Paul Müller, Philipp Rosendahl, Raghava Alajangi
|
|
6
6
|
Maintainer-email: Paul Müller <dev@craban.de>
|
|
@@ -741,7 +741,9 @@ class RTDCBase(abc.ABC):
|
|
|
741
741
|
# need the referring dataset.
|
|
742
742
|
"mapping_referrer": self,
|
|
743
743
|
# Make sure the measurement identifier is checked.
|
|
744
|
-
"
|
|
744
|
+
"referrer_identifier": self.get_measurement_identifier(),
|
|
745
|
+
# Make sure the basin identifier is checked.
|
|
746
|
+
"basin_identifier": bdict.get("identifier"),
|
|
745
747
|
# allow to ignore basins
|
|
746
748
|
"ignored_basins": bd_keys,
|
|
747
749
|
# basin key
|
|
@@ -334,8 +334,8 @@ class Export(object):
|
|
|
334
334
|
# Define a new measurement identifier, so that we are not running
|
|
335
335
|
# into any problems with basins being defined for filtered data.
|
|
336
336
|
ds_run_id = ds.get_measurement_identifier()
|
|
337
|
-
random_ap = str(uuid.uuid4())[:
|
|
338
|
-
meta["experiment"]["run identifier"] = f"{ds_run_id}
|
|
337
|
+
random_ap = f"dclab-{str(uuid.uuid4())[:7]}"
|
|
338
|
+
meta["experiment"]["run identifier"] = f"{ds_run_id}_{random_ap}"
|
|
339
339
|
|
|
340
340
|
if filtered:
|
|
341
341
|
filter_arr = ds.filter.all
|
|
@@ -438,7 +438,6 @@ class Export(object):
|
|
|
438
438
|
if progress_callback:
|
|
439
439
|
progress_callback(1 - 1 / (len(features) or 1),
|
|
440
440
|
"writing basins")
|
|
441
|
-
|
|
442
441
|
# We have to store basins. There are three options:
|
|
443
442
|
# - filtering disabled: just copy basins
|
|
444
443
|
# - filtering enabled
|
|
@@ -450,6 +449,8 @@ class Export(object):
|
|
|
450
449
|
basin_list = [bn.as_dict() for bn in ds.basins]
|
|
451
450
|
# In addition to the upstream basins, also store a reference
|
|
452
451
|
# to the original file from which the export was done.
|
|
452
|
+
# Get the identifier of the current dataset for the new basins.
|
|
453
|
+
basin_id = ds.get_measurement_identifier()
|
|
453
454
|
if ds.format in get_basin_classes():
|
|
454
455
|
# The dataset has a format that matches a basin format
|
|
455
456
|
# directly.
|
|
@@ -464,6 +465,7 @@ class Export(object):
|
|
|
464
465
|
"basin_format": ds.format,
|
|
465
466
|
"basin_locs": basin_locs,
|
|
466
467
|
"basin_descr": f"Exported with dclab {version}",
|
|
468
|
+
"basin_id": basin_id,
|
|
467
469
|
})
|
|
468
470
|
elif (ds.format == "hierarchy"
|
|
469
471
|
and ds.get_root_parent().format in get_basin_classes()):
|
|
@@ -497,6 +499,7 @@ class Export(object):
|
|
|
497
499
|
child=ds,
|
|
498
500
|
child_indices=np.arange(len(ds))
|
|
499
501
|
),
|
|
502
|
+
"basin_id": basin_id,
|
|
500
503
|
})
|
|
501
504
|
|
|
502
505
|
for bn_dict in basin_list:
|
|
@@ -176,7 +176,8 @@ class Basin(abc.ABC):
|
|
|
176
176
|
name: str = None,
|
|
177
177
|
description: str = None,
|
|
178
178
|
features: List[str] = None,
|
|
179
|
-
|
|
179
|
+
referrer_identifier: str = None,
|
|
180
|
+
basin_identifier: str = None,
|
|
180
181
|
mapping: Literal["same",
|
|
181
182
|
"basinmap0",
|
|
182
183
|
"basinmap1",
|
|
@@ -208,10 +209,18 @@ class Basin(abc.ABC):
|
|
|
208
209
|
features: list of str
|
|
209
210
|
List of features this basin provides; This list is enforced,
|
|
210
211
|
even if the basin actually contains more features.
|
|
211
|
-
|
|
212
|
+
referrer_identifier: str
|
|
212
213
|
A measurement identifier against which to check the basin.
|
|
214
|
+
If the basin mapping is "same", then this must match the
|
|
215
|
+
identifier of the basin exactly, otherwise it must start
|
|
216
|
+
with the basin identifier (e.g. "basin-id_referrer-sub-id").
|
|
213
217
|
If this is set to None (default), there is no certainty
|
|
214
218
|
that the downstream dataset is from the same measurement.
|
|
219
|
+
basin_identifier: str
|
|
220
|
+
A measurement identifier that must match the basin exactly.
|
|
221
|
+
In contrast to `referrer_identifier`, the basin identifier is
|
|
222
|
+
the identifier of the basin file. If `basin_identifier` is
|
|
223
|
+
specified, the identifier of the basin must be identical to it.
|
|
215
224
|
mapping: str
|
|
216
225
|
Which type of mapping to use. This can be either "same"
|
|
217
226
|
when the event list of the basin is identical to that
|
|
@@ -261,8 +270,9 @@ class Basin(abc.ABC):
|
|
|
261
270
|
# features this basin provides
|
|
262
271
|
self._features = features
|
|
263
272
|
#: measurement identifier of the referencing dataset
|
|
264
|
-
self.
|
|
265
|
-
self.
|
|
273
|
+
self.referrer_identifier = referrer_identifier
|
|
274
|
+
self.basin_identifier = basin_identifier or None
|
|
275
|
+
self._identifiers_verification = None
|
|
266
276
|
#: ignored basins
|
|
267
277
|
self.ignored_basins = ignored_basins or []
|
|
268
278
|
#: additional keyword arguments passed to the basin
|
|
@@ -304,13 +314,13 @@ class Basin(abc.ABC):
|
|
|
304
314
|
|
|
305
315
|
return f"<{self.__class__.__name__} ({opt_str}) at {hex(id(self))}>"
|
|
306
316
|
|
|
307
|
-
def
|
|
317
|
+
def _assert_referrer_identifier(self):
|
|
308
318
|
"""Make sure the basin matches the measurement identifier
|
|
309
319
|
"""
|
|
310
320
|
if not self.verify_basin(run_identifier=True):
|
|
311
321
|
raise KeyError(f"Measurement identifier of basin {self.ds} "
|
|
312
322
|
f"({self.get_measurement_identifier()}) does "
|
|
313
|
-
f"not match {self.
|
|
323
|
+
f"not match {self.referrer_identifier}!")
|
|
314
324
|
|
|
315
325
|
@property
|
|
316
326
|
def basinmap(self):
|
|
@@ -410,7 +420,7 @@ class Basin(abc.ABC):
|
|
|
410
420
|
|
|
411
421
|
def get_feature_data(self, feat):
|
|
412
422
|
"""Return an object representing feature data of the basin"""
|
|
413
|
-
self.
|
|
423
|
+
self._assert_referrer_identifier()
|
|
414
424
|
return self.ds[feat]
|
|
415
425
|
|
|
416
426
|
def get_measurement_identifier(self):
|
|
@@ -455,20 +465,30 @@ class Basin(abc.ABC):
|
|
|
455
465
|
# Only check for run identifier if requested and if the availability
|
|
456
466
|
# check did not fail.
|
|
457
467
|
if run_identifier and check_avail:
|
|
458
|
-
if
|
|
459
|
-
|
|
468
|
+
if self._identifiers_verification is None:
|
|
469
|
+
# This is the measurement identifier of the basin.
|
|
470
|
+
basin_identifier = self.get_measurement_identifier()
|
|
471
|
+
|
|
472
|
+
# Perform a sanity check for the basin identifier.
|
|
473
|
+
if (self.basin_identifier
|
|
474
|
+
and self.basin_identifier != basin_identifier):
|
|
475
|
+
# We should not proceed any further with this basin.
|
|
476
|
+
self._identifiers_verification = False
|
|
477
|
+
warnings.warn(
|
|
478
|
+
f"Basin identifier mismatch for {self}. Expected "
|
|
479
|
+
f"'{self.basin_identifier}', got '{basin_identifier}'")
|
|
480
|
+
|
|
481
|
+
if self.referrer_identifier is None:
|
|
460
482
|
# No measurement identifier was presented by the
|
|
461
483
|
# referencing dataset. We are in the dark.
|
|
462
484
|
# Don't perform any checks.
|
|
463
|
-
self.
|
|
485
|
+
self._identifiers_verification = True
|
|
464
486
|
else:
|
|
465
|
-
# This is the measurement identifier of the basin.
|
|
466
|
-
basin_identifier = self.get_measurement_identifier()
|
|
467
487
|
if basin_identifier is None:
|
|
468
488
|
# Again, we are in the dark, because the basin dataset
|
|
469
489
|
# does not have an identifier. This is an undesirable
|
|
470
490
|
# situation, but there is nothing we can do about it.
|
|
471
|
-
self.
|
|
491
|
+
self._identifiers_verification = True
|
|
472
492
|
else:
|
|
473
493
|
if self.mapping == "same":
|
|
474
494
|
# When we have identical mapping, then the
|
|
@@ -479,10 +499,10 @@ class Basin(abc.ABC):
|
|
|
479
499
|
# data), then the measurement identifier has to
|
|
480
500
|
# partially match.
|
|
481
501
|
verifier = str.startswith
|
|
482
|
-
self.
|
|
483
|
-
self.
|
|
502
|
+
self._identifiers_verification = verifier(
|
|
503
|
+
self.referrer_identifier, basin_identifier)
|
|
484
504
|
|
|
485
|
-
check_rid = self.
|
|
505
|
+
check_rid = self._identifiers_verification
|
|
486
506
|
else:
|
|
487
507
|
check_rid = True
|
|
488
508
|
|
|
@@ -207,6 +207,7 @@ class RTDCWriter:
|
|
|
207
207
|
basin_descr: str | None = None,
|
|
208
208
|
basin_feats: List[str] = None,
|
|
209
209
|
basin_map: np.ndarray | Tuple[str, np.ndarray] = None,
|
|
210
|
+
basin_id: str = None,
|
|
210
211
|
internal_data: Dict | h5py.Group = None,
|
|
211
212
|
verify: bool = True,
|
|
212
213
|
perishable: bool = False,
|
|
@@ -243,6 +244,12 @@ class RTDCWriter:
|
|
|
243
244
|
a case, you may specify a tuple `(feature_name, mapping_array)`
|
|
244
245
|
where `feature_name` is the explicit mapping name, e.g.
|
|
245
246
|
`"basinmap3"`.
|
|
247
|
+
basin_id: str
|
|
248
|
+
Identifier of the basin. This is the string returned by
|
|
249
|
+
:meth:`.RTDCBase.get_measurement_identifier`. This is
|
|
250
|
+
a unique string that identifies the data within a basin.
|
|
251
|
+
If not specified and `verify=True`, this value is automatically
|
|
252
|
+
taken from the basin file.
|
|
246
253
|
internal_data: dict or instance of h5py.Group
|
|
247
254
|
A dictionary or an `h5py.Group` containing the basin data.
|
|
248
255
|
The data are copied to the "basin_events" group, if
|
|
@@ -310,19 +317,30 @@ class RTDCWriter:
|
|
|
310
317
|
# We have to import this here to avoid circular imports
|
|
311
318
|
from .load import new_dataset
|
|
312
319
|
# Make sure the basin can be opened by dclab, verify its ID
|
|
313
|
-
|
|
320
|
+
ref_id = self.h5file.attrs.get("experiment:run identifier")
|
|
314
321
|
for loc in basin_locs:
|
|
315
322
|
with new_dataset(loc) as ds:
|
|
316
323
|
# We can open the file, which is great.
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
324
|
+
# Compare the IDs.
|
|
325
|
+
bn_id = ds.get_measurement_identifier()
|
|
326
|
+
# Check whether `basin_id` matches the actual basin
|
|
327
|
+
if basin_id:
|
|
328
|
+
if basin_id != bn_id:
|
|
329
|
+
raise ValueError(
|
|
330
|
+
f"Measurement identifier mismatch for "
|
|
331
|
+
f"{loc}: got {bn_id}, expected {basin_id=})!")
|
|
332
|
+
else:
|
|
333
|
+
# If `basin_id` was not specified, set it here for
|
|
334
|
+
# user convenience.
|
|
335
|
+
basin_id = bn_id or None
|
|
336
|
+
# Check whether the referrer ID matches the basin ID.
|
|
337
|
+
if ref_id:
|
|
338
|
+
if not (bn_id == ref_id
|
|
321
339
|
or (basin_map is not None
|
|
322
|
-
and
|
|
340
|
+
and ref_id.startswith(bn_id))):
|
|
323
341
|
raise ValueError(
|
|
324
342
|
f"Measurement identifier mismatch between "
|
|
325
|
-
f"{self.path} ({
|
|
343
|
+
f"{self.path} ({ref_id}) and {loc} ({bn_id})!")
|
|
326
344
|
if basin_feats:
|
|
327
345
|
for feat in basin_feats:
|
|
328
346
|
if not dfn.feature_exists(feat):
|
|
@@ -389,6 +407,7 @@ class RTDCWriter:
|
|
|
389
407
|
"features": None if basin_feats is None else sorted(basin_feats),
|
|
390
408
|
"mapping": basin_map_name,
|
|
391
409
|
"perishable": perishable,
|
|
410
|
+
"identifier": basin_id,
|
|
392
411
|
}
|
|
393
412
|
if basin_type == "file":
|
|
394
413
|
flocs = []
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dclab
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.66.0
|
|
4
4
|
Summary: Library for real-time deformability cytometry (RT-DC)
|
|
5
5
|
Author: Benedikt Hartmann, Eoghan O'Connell, Maik Herbig, Maximilian Schlögel, Nadia Sbaa, Paul Müller, Philipp Rosendahl, Raghava Alajangi
|
|
6
6
|
Maintainer-email: Paul Müller <dev@craban.de>
|
|
@@ -224,6 +224,7 @@ scripts/pixelation_correction.py
|
|
|
224
224
|
scripts/pixelation_correction_2020.png
|
|
225
225
|
scripts/pixelation_correction_2022.png
|
|
226
226
|
scripts/requirements.txt
|
|
227
|
+
scripts/vid2dc.py
|
|
227
228
|
scripts/lut_recipes/__init__.py
|
|
228
229
|
scripts/lut_recipes/lut_processor.py
|
|
229
230
|
scripts/lut_recipes/hooks/LUT_analytical_linear-elastic_2Daxis.txt
|
|
@@ -409,6 +409,7 @@ the json data looks like this:
|
|
|
409
409
|
"type": "file",
|
|
410
410
|
"features": null,
|
|
411
411
|
"mapping": "basinmap0",
|
|
412
|
+
"identifier": "1231ae-31f23-342-232-42b1c",
|
|
412
413
|
"paths": [
|
|
413
414
|
"/absolute/path/to/input.rtdc",
|
|
414
415
|
"input.rtdc"
|
|
@@ -427,6 +428,11 @@ are a few things to notice:
|
|
|
427
428
|
``/events/basinmap0`` in the output file. Note that the fact that this mapping
|
|
428
429
|
information is stored *as a feature* means that it is also properly
|
|
429
430
|
gated when you define basins iteratively.
|
|
431
|
+
- The *identifier* is a string that matches the identifier of the dataset.
|
|
432
|
+
When creating basins without a "same" mapping (as in this case), then the
|
|
433
|
+
referrer will obtain an identifier that starts with this identifier, but
|
|
434
|
+
contains additional text. This means identifiers are effectively cryptic
|
|
435
|
+
data analysis trackers.
|
|
430
436
|
- There are two *paths* defined, an absolute path (from the root of the file
|
|
431
437
|
system) and a relative path (relative to the directory of the output file).
|
|
432
438
|
This relative path makes it possible to copy-paste these two files *together* to
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
"""vid2dc
|
|
2
|
+
|
|
3
|
+
Convert video files to .rtdc files. This script generates a valid .rtdc
|
|
4
|
+
file from a video file (e.g. an .avi file). This script does not perform
|
|
5
|
+
segmentation and feature extraction, a feature that is available via the
|
|
6
|
+
ChipStream package (https://github.com/DC-analysis/ChipStream).
|
|
7
|
+
|
|
8
|
+
Prerequisites:
|
|
9
|
+
|
|
10
|
+
pip install dclab[tdms] imageio[pyav] click
|
|
11
|
+
|
|
12
|
+
Author: Paul Müller
|
|
13
|
+
License: GPLv3+
|
|
14
|
+
"""
|
|
15
|
+
import configparser
|
|
16
|
+
import logging
|
|
17
|
+
import pathlib
|
|
18
|
+
import time
|
|
19
|
+
import traceback
|
|
20
|
+
|
|
21
|
+
import click
|
|
22
|
+
from dclab.rtdc_dataset import fmt_tdms
|
|
23
|
+
from dclab.util import hashfile, hashobj
|
|
24
|
+
from dclab import RTDCWriter
|
|
25
|
+
import h5py
|
|
26
|
+
import imageio.v3 as iio
|
|
27
|
+
import numpy as np
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
logger = logging.getLogger("vid2dc")
|
|
31
|
+
logging.basicConfig(level=logging.INFO)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
__version__ = "2025.07.07"
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@click.command()
|
|
38
|
+
@click.argument("path_in",
|
|
39
|
+
type=click.Path(exists=True,
|
|
40
|
+
dir_okay=True,
|
|
41
|
+
resolve_path=True,
|
|
42
|
+
path_type=pathlib.Path))
|
|
43
|
+
@click.argument("path-out",
|
|
44
|
+
required=False,
|
|
45
|
+
type=click.Path(dir_okay=False,
|
|
46
|
+
writable=True,
|
|
47
|
+
resolve_path=True,
|
|
48
|
+
path_type=pathlib.Path),
|
|
49
|
+
)
|
|
50
|
+
def vid2dc(path_in: pathlib.Path,
|
|
51
|
+
path_out: pathlib.Path | None = None):
|
|
52
|
+
"""Convert raw video data to raw .rtdc data
|
|
53
|
+
|
|
54
|
+
Use this command to convert a video file (e.g. from a legacy
|
|
55
|
+
.tdms measurement or from a custom setup) to a raw .rtdc file.
|
|
56
|
+
No segmentation or feature extraction will take place.
|
|
57
|
+
|
|
58
|
+
You may also specify an input directory instead of a single file
|
|
59
|
+
for batch conversion.
|
|
60
|
+
"""
|
|
61
|
+
if path_in.is_dir():
|
|
62
|
+
if path_out is not None:
|
|
63
|
+
raise NotImplementedError("If you pass an input directory, you "
|
|
64
|
+
"must omit the output directory.")
|
|
65
|
+
for ext in [".avi", ".mp4", ".mpg", ".wmv", ".mkv"]:
|
|
66
|
+
for pp in path_in.rglob(f"*{ext}"):
|
|
67
|
+
try:
|
|
68
|
+
convert_video_to_dc(video_path=pp)
|
|
69
|
+
except BaseException:
|
|
70
|
+
elog = pp.with_name(pp.stem + "_vid2dc_error.log")
|
|
71
|
+
elog.write_text(traceback.format_exc())
|
|
72
|
+
click.secho(f"Could not process {pp}, wrote error log "
|
|
73
|
+
f"to {elog}.",
|
|
74
|
+
bold=True, fg="red")
|
|
75
|
+
else:
|
|
76
|
+
convert_video_to_dc(video_path=path_in, dc_path=path_out)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def convert_video_to_dc(video_path: str | pathlib.Path,
|
|
80
|
+
dc_path: str | pathlib.Path = None,
|
|
81
|
+
):
|
|
82
|
+
"""Convert an .avi file to an .rtdc file
|
|
83
|
+
|
|
84
|
+
A valid .rtdc file is produced. Metadata are guessed, but you
|
|
85
|
+
can put metadata in camera.ini files. This is not fully supported yet.
|
|
86
|
+
Please check the metadata of the output .rtdc file.
|
|
87
|
+
|
|
88
|
+
Parameters
|
|
89
|
+
----------
|
|
90
|
+
video_path:
|
|
91
|
+
Path to a video file (e.g. an .avi file) to convert to .rtdc.
|
|
92
|
+
dc_path:
|
|
93
|
+
Path to an .rtdc file that is created from the video file.
|
|
94
|
+
If the .rtdc file already exists, it will only be overridden
|
|
95
|
+
if the input file or metadata changed.
|
|
96
|
+
"""
|
|
97
|
+
video_path = pathlib.Path(video_path)
|
|
98
|
+
if dc_path is None:
|
|
99
|
+
dc_path = video_path.with_name(video_path.stem + "_raw.rtdc")
|
|
100
|
+
dc_path = pathlib.Path(dc_path)
|
|
101
|
+
|
|
102
|
+
# get the dataset configuration
|
|
103
|
+
config, log_paths = fmt_tdms.RTDC_TDMS.extract_tdms_config(
|
|
104
|
+
video_path, ret_source_files=True, ignore_missing=True)
|
|
105
|
+
|
|
106
|
+
# RecoTeem stores an ini file next to the measurement
|
|
107
|
+
prt = video_path.with_suffix(".ini")
|
|
108
|
+
if prt.exists():
|
|
109
|
+
log_paths.append(prt)
|
|
110
|
+
|
|
111
|
+
# read logs
|
|
112
|
+
logs = {}
|
|
113
|
+
for ppl in log_paths:
|
|
114
|
+
logs[ppl.name] = ppl.read_text().split("\n")
|
|
115
|
+
|
|
116
|
+
vmeta = iio.improps(video_path)
|
|
117
|
+
width = vmeta.shape[2]
|
|
118
|
+
height = vmeta.shape[1]
|
|
119
|
+
|
|
120
|
+
config["imaging"].setdefault("frame rate", 2000)
|
|
121
|
+
config["imaging"].setdefault("pixel size", 0.34)
|
|
122
|
+
config["imaging"]["roi size x"] = width
|
|
123
|
+
config["imaging"]["roi size y"] = height
|
|
124
|
+
|
|
125
|
+
# extract additional information from an optional ini file (RecoTeem)
|
|
126
|
+
if prt.exists():
|
|
127
|
+
# measurement index
|
|
128
|
+
if prt.name.startswith("M") and prt.name.count("_"):
|
|
129
|
+
mid = video_path.name.split("_")[0]
|
|
130
|
+
config["experiment"]["run index"] = int(mid[1:])
|
|
131
|
+
cp = configparser.RawConfigParser(allow_no_value=True)
|
|
132
|
+
# Allow upper-case keys (comment for sample name)
|
|
133
|
+
cp.optionxform = lambda x: x
|
|
134
|
+
cp.read(prt)
|
|
135
|
+
rt_fr = cp.getint("set parameter", "frame rate [fps]", fallback=None)
|
|
136
|
+
# frame rate
|
|
137
|
+
if rt_fr is not None:
|
|
138
|
+
config["imaging"]["frame rate"] = rt_fr
|
|
139
|
+
rt_dur = cp.getfloat("set parameter", "set record time [s]",
|
|
140
|
+
fallback=None)
|
|
141
|
+
# duration
|
|
142
|
+
if rt_dur is not None:
|
|
143
|
+
config["online_filter"]["target duration"] = rt_dur / 60
|
|
144
|
+
# sample name
|
|
145
|
+
if cp.has_section("Optional Text"):
|
|
146
|
+
descr = list(cp["Optional Text"].keys())[0]
|
|
147
|
+
config["experiment"]["sample"] = descr
|
|
148
|
+
|
|
149
|
+
# Set the time of the input file
|
|
150
|
+
tse = video_path.stat().st_mtime
|
|
151
|
+
loct = time.localtime(tse)
|
|
152
|
+
# Start time of measurement ('HH:MM:SS')
|
|
153
|
+
timestr = time.strftime("%H:%M:%S", loct)
|
|
154
|
+
config["experiment"].setdefault("time", timestr)
|
|
155
|
+
# Date of measurement ('YYYY-MM-DD')
|
|
156
|
+
datestr = time.strftime("%Y-%m-%d", loct)
|
|
157
|
+
config["experiment"].setdefault("date", datestr)
|
|
158
|
+
config["experiment"].setdefault("sample", video_path.name)
|
|
159
|
+
|
|
160
|
+
config["setup"].setdefault("chip region", "channel")
|
|
161
|
+
config["setup"].setdefault("flow rate", 0)
|
|
162
|
+
config["setup"].setdefault("software version", f"vid2dc {__version__}")
|
|
163
|
+
|
|
164
|
+
config = dict(config)
|
|
165
|
+
if "filtering" in config:
|
|
166
|
+
config.pop("filtering")
|
|
167
|
+
|
|
168
|
+
# Compute a unique hash of the input files
|
|
169
|
+
video_hash = hashobj([hashobj(config),
|
|
170
|
+
hashfile(video_path),
|
|
171
|
+
video_path.stat().st_size,
|
|
172
|
+
])
|
|
173
|
+
|
|
174
|
+
# If the output file already exists, check whether the hashes match.
|
|
175
|
+
log_name = "vid2dc"
|
|
176
|
+
if dc_path.exists():
|
|
177
|
+
with h5py.File(dc_path) as h5:
|
|
178
|
+
if (log_name in h5.get("logs", [])
|
|
179
|
+
and h5["logs"][log_name].attrs.get("hash") == video_hash):
|
|
180
|
+
# We can reuse this file
|
|
181
|
+
logger.info(f"Reusing existing file {dc_path}")
|
|
182
|
+
return
|
|
183
|
+
else:
|
|
184
|
+
logger.info(f"Rewriting existing {dc_path} (hash mismatch)")
|
|
185
|
+
dc_path.unlink()
|
|
186
|
+
|
|
187
|
+
vid = iio.imiter(video_path)
|
|
188
|
+
|
|
189
|
+
# This is the actual workload of this function. Populate the .rtdc
|
|
190
|
+
# file with the image data.
|
|
191
|
+
logger.info(f"Writing .rtdc file {dc_path}")
|
|
192
|
+
with RTDCWriter(dc_path, mode="reset") as hw:
|
|
193
|
+
# store the image data to the output file in chunks
|
|
194
|
+
chunk_size = hw.get_best_nd_chunks(item_shape=(height, width),
|
|
195
|
+
item_dtype=np.uint8)[0]
|
|
196
|
+
image_chunk = np.zeros((chunk_size, height, width), dtype=np.uint8)
|
|
197
|
+
ii = 0
|
|
198
|
+
for image in vid:
|
|
199
|
+
if len(image.shape) == 3:
|
|
200
|
+
image = image[:, :, 0]
|
|
201
|
+
image_chunk[ii] = image
|
|
202
|
+
ii += 1
|
|
203
|
+
if ii == chunk_size:
|
|
204
|
+
ii = 0
|
|
205
|
+
hw.store_feature("image", image_chunk)
|
|
206
|
+
# store the rest
|
|
207
|
+
if ii:
|
|
208
|
+
hw.store_feature("image", image_chunk[:ii])
|
|
209
|
+
|
|
210
|
+
event_count = hw.h5file["events/image"].shape[0]
|
|
211
|
+
config["experiment"]["event count"] = event_count
|
|
212
|
+
hw.store_metadata(config)
|
|
213
|
+
|
|
214
|
+
# store the input file information as a log
|
|
215
|
+
hw.store_log(
|
|
216
|
+
name=log_name,
|
|
217
|
+
lines=[
|
|
218
|
+
f"Input filename: {video_path.name}",
|
|
219
|
+
f"Output filename: {dc_path.name}",
|
|
220
|
+
f"Input file size: {video_path.stat().st_size}",
|
|
221
|
+
f"Input last edited: {video_path.stat().st_mtime}",
|
|
222
|
+
f"Unique conversion hash: {video_hash}",
|
|
223
|
+
]
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
# store time
|
|
227
|
+
hw.store_feature(
|
|
228
|
+
"time",
|
|
229
|
+
np.arange(event_count) / config["imaging"]["frame rate"])
|
|
230
|
+
# index starts at 1
|
|
231
|
+
hw.store_feature("index", np.arange(1, event_count + 1))
|
|
232
|
+
# frame is an ascending number, just start with 1
|
|
233
|
+
hw.store_feature("frame", np.arange(1, event_count + 1))
|
|
234
|
+
|
|
235
|
+
# only store hash attribute when successful
|
|
236
|
+
hw.h5file["logs"][log_name].attrs["hash"] = video_hash
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
if __name__ == "__main__":
|
|
240
|
+
vid2dc()
|
|
@@ -358,7 +358,10 @@ def test_basin_relative_paths(path_sep):
|
|
|
358
358
|
@pytest.mark.filterwarnings(
|
|
359
359
|
"ignore::dclab.rtdc_dataset.config.WrongConfigurationTypeWarning")
|
|
360
360
|
def test_basin_key_reproducible():
|
|
361
|
-
"""
|
|
361
|
+
"""
|
|
362
|
+
Since 0.62.9 we sort basin keys
|
|
363
|
+
Since 0.66.0 we have identifiers in the basins
|
|
364
|
+
"""
|
|
362
365
|
h5path = retrieve_data("fmt-hdf5_fl_wide-channel_2023.zip")
|
|
363
366
|
h5path_small = h5path.parent / "subdirectory" / "relative.rtdc"
|
|
364
367
|
h5path_small.parent.mkdir()
|
|
@@ -409,12 +412,11 @@ def test_basin_key_reproducible():
|
|
|
409
412
|
# from the input file.
|
|
410
413
|
with dclab.new_dataset(h5path_small_2) as ds:
|
|
411
414
|
assert len(ds.basins) == 1
|
|
412
|
-
# dclab 0.62.9
|
|
413
415
|
assert ds.basins[0].key in [
|
|
414
416
|
# posix linesep
|
|
415
|
-
"
|
|
417
|
+
"b125c0e7d4ab1aff1030f40b87d670c3",
|
|
416
418
|
# win linesep
|
|
417
|
-
"
|
|
419
|
+
"93bc9ab45b50c094c1b585cc8702ca92",
|
|
418
420
|
]
|
|
419
421
|
|
|
420
422
|
|
|
@@ -460,6 +462,28 @@ def test_basin_run_identifier_unknown():
|
|
|
460
462
|
assert ds["image"][0][0, 0] == 126
|
|
461
463
|
|
|
462
464
|
|
|
465
|
+
def test_basin_run_identifier_verify():
|
|
466
|
+
h5path = retrieve_data("fmt-hdf5_fl_wide-channel_2023.zip")
|
|
467
|
+
export_same = h5path.with_name("same.rtdc")
|
|
468
|
+
|
|
469
|
+
# export a subset with basins.
|
|
470
|
+
with dclab.new_dataset(h5path) as ds:
|
|
471
|
+
# export without filters
|
|
472
|
+
ds.export.hdf5(export_same, features=["deform"], basins=True)
|
|
473
|
+
|
|
474
|
+
# change the run identifier of the original file
|
|
475
|
+
with h5py.File(h5path, "a") as h5:
|
|
476
|
+
h5.attrs["experiment:run identifier"] = "Uiiiid!"
|
|
477
|
+
|
|
478
|
+
with dclab.new_dataset(h5path) as ds:
|
|
479
|
+
assert ds.get_measurement_identifier() == "Uiiiid!"
|
|
480
|
+
|
|
481
|
+
with dclab.new_dataset(export_same) as ds2:
|
|
482
|
+
with pytest.warns(UserWarning, match="identifier mismatch"):
|
|
483
|
+
with pytest.raises(KeyError, match="does not exist"):
|
|
484
|
+
ds2["area_um"][0]
|
|
485
|
+
|
|
486
|
+
|
|
463
487
|
def test_basin_sorting_basic():
|
|
464
488
|
bnlist = [
|
|
465
489
|
{"type": "remote", "format": "dcor", "ident": 0},
|