ngio 0.2.0a2__tar.gz → 0.2.0b1__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.
- {ngio-0.2.0a2 → ngio-0.2.0b1}/.gitignore +3 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/PKG-INFO +4 -1
- ngio-0.2.0b1/docs/api/core.md +3 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/docs/notebooks/basic_usage.ipynb +45 -16
- {ngio-0.2.0a2 → ngio-0.2.0b1}/docs/notebooks/image.ipynb +2 -9
- {ngio-0.2.0a2 → ngio-0.2.0b1}/pyproject.toml +10 -23
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/__init__.py +4 -4
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/common/__init__.py +12 -2
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/common/_array_pipe.py +106 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/common/_axes_transforms.py +3 -2
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/common/_dimensions.py +7 -0
- ngio-0.2.0b1/src/ngio/common/_masking_roi.py +158 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/common/_pyramid.py +16 -11
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/common/_roi.py +74 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/common/_slicer.py +1 -2
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/common/_zoom.py +5 -3
- ngio-0.2.0b1/src/ngio/hcs/__init__.py +5 -0
- ngio-0.2.0b1/src/ngio/hcs/plate.py +399 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/images/abstract_image.py +97 -28
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/images/create.py +48 -29
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/images/image.py +121 -57
- ngio-0.2.0b1/src/ngio/images/label.py +281 -0
- ngio-0.2.0b1/src/ngio/images/masked_image.py +259 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/images/omezarr_container.py +250 -77
- ngio-0.2.0b1/src/ngio/ome_zarr_meta/__init__.py +47 -0
- ngio-0.2.0b1/src/ngio/ome_zarr_meta/_meta_handlers.py +791 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/ome_zarr_meta/ngio_specs/__init__.py +8 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/ome_zarr_meta/ngio_specs/_channels.py +11 -0
- ngio-0.2.0b1/src/ngio/ome_zarr_meta/ngio_specs/_ngio_hcs.py +377 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/ome_zarr_meta/ngio_specs/_ngio_image.py +174 -113
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/ome_zarr_meta/ngio_specs/_pixel_size.py +35 -3
- ngio-0.2.0b1/src/ngio/ome_zarr_meta/v04/__init__.py +23 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/ome_zarr_meta/v04/_v04_spec_utils.py +85 -12
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/tables/__init__.py +2 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/tables/_validators.py +2 -4
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/tables/backends/_anndata_utils.py +2 -1
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/tables/backends/_anndata_v1.py +2 -1
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/tables/backends/_json_v1.py +1 -1
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/tables/tables_container.py +12 -2
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/tables/v1/__init__.py +1 -2
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/tables/v1/_feature_table.py +7 -5
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/tables/v1/_generic_table.py +65 -11
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/tables/v1/_roi_table.py +145 -27
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/utils/__init__.py +3 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/utils/_datasets.py +4 -2
- ngio-0.2.0b1/src/ngio/utils/_fractal_fsspec_store.py +13 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/utils/_logger.py +3 -1
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/utils/_zarr_utils.py +25 -2
- ngio-0.2.0b1/tests/conftest.py +40 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_c1yx.zarr/.zattrs +86 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_c1yx.zarr/.zgroup +3 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_c1yx.zarr/0/.zarray +27 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_c1yx.zarr/1/.zarray +27 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_c1yx.zarr/labels/.zattrs +5 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_c1yx.zarr/labels/.zgroup +3 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_c1yx.zarr/labels/label/.zattrs +59 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_c1yx.zarr/labels/label/.zgroup +3 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_c1yx.zarr/labels/label/0/.zarray +25 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_c1yx.zarr/labels/label/1/.zarray +25 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_cyx.zarr/.zattrs +79 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_cyx.zarr/.zgroup +3 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_cyx.zarr/0/.zarray +25 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_cyx.zarr/1/.zarray +25 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_cyx.zarr/labels/.zattrs +5 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_cyx.zarr/labels/.zgroup +3 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_cyx.zarr/labels/label/.zattrs +52 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_cyx.zarr/labels/label/.zgroup +3 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_cyx.zarr/labels/label/0/.zarray +23 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_cyx.zarr/labels/label/1/.zarray +23 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_czyx.zarr/.zattrs +86 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_czyx.zarr/.zgroup +3 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_czyx.zarr/0/.zarray +27 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_czyx.zarr/1/.zarray +27 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_czyx.zarr/labels/.zattrs +5 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_czyx.zarr/labels/.zgroup +3 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_czyx.zarr/labels/label/.zattrs +59 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_czyx.zarr/labels/label/.zgroup +3 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_czyx.zarr/labels/label/0/.zarray +25 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_czyx.zarr/labels/label/1/.zarray +25 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tcyx.zarr/.zattrs +86 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tcyx.zarr/.zgroup +3 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tcyx.zarr/0/.zarray +27 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tcyx.zarr/1/.zarray +27 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tcyx.zarr/labels/.zattrs +5 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tcyx.zarr/labels/.zgroup +3 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tcyx.zarr/labels/label/.zattrs +59 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tcyx.zarr/labels/label/.zgroup +3 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tcyx.zarr/labels/label/0/.zarray +25 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tcyx.zarr/labels/label/1/.zarray +25 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tczyx.zarr/.zattrs +93 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tczyx.zarr/.zgroup +3 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tczyx.zarr/0/.zarray +29 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tczyx.zarr/1/.zarray +29 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tczyx.zarr/labels/.zattrs +5 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tczyx.zarr/labels/.zgroup +3 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tczyx.zarr/labels/label/.zattrs +66 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tczyx.zarr/labels/label/.zgroup +3 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tczyx.zarr/labels/label/0/.zarray +27 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tczyx.zarr/labels/label/1/.zarray +27 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tyx.zarr/.zattrs +68 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tyx.zarr/.zgroup +3 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tyx.zarr/0/.zarray +25 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tyx.zarr/1/.zarray +25 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tyx.zarr/labels/.zattrs +5 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tyx.zarr/labels/.zgroup +3 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tyx.zarr/labels/label/.zattrs +59 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tyx.zarr/labels/label/.zgroup +3 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tyx.zarr/labels/label/0/.zarray +25 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tyx.zarr/labels/label/1/.zarray +25 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tzyx.zarr/.zattrs +75 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tzyx.zarr/.zgroup +3 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tzyx.zarr/0/.zarray +27 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tzyx.zarr/1/.zarray +27 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tzyx.zarr/labels/.zattrs +5 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tzyx.zarr/labels/.zgroup +3 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tzyx.zarr/labels/label/.zattrs +66 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tzyx.zarr/labels/label/.zgroup +3 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tzyx.zarr/labels/label/0/.zarray +27 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_tzyx.zarr/labels/label/1/.zarray +27 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_yx.zarr/.zattrs +61 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_yx.zarr/.zgroup +3 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_yx.zarr/0/.zarray +23 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_yx.zarr/1/.zarray +23 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_yx.zarr/labels/.zattrs +5 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_yx.zarr/labels/.zgroup +3 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_yx.zarr/labels/label/.zattrs +52 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_yx.zarr/labels/label/.zgroup +3 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_yx.zarr/labels/label/0/.zarray +23 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_yx.zarr/labels/label/1/.zarray +23 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_zyx.zarr/.zattrs +68 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_zyx.zarr/.zgroup +3 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_zyx.zarr/0/.zarray +25 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_zyx.zarr/1/.zarray +25 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_zyx.zarr/labels/.zattrs +5 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_zyx.zarr/labels/.zgroup +3 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_zyx.zarr/labels/label/.zattrs +59 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_zyx.zarr/labels/label/.zgroup +3 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_zyx.zarr/labels/label/0/.zarray +25 -0
- ngio-0.2.0b1/tests/data/v04/images/test_image_zyx.zarr/labels/label/1/.zarray +25 -0
- ngio-0.2.0b1/tests/unit/hcs/test_plate.py +57 -0
- ngio-0.2.0b1/tests/unit/images/test_create.py +128 -0
- ngio-0.2.0b1/tests/unit/images/test_images.py +25 -0
- ngio-0.2.0b1/tests/unit/images/test_masked_images.py +73 -0
- ngio-0.2.0b1/tests/unit/images/test_omezarr_container.py +155 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/tests/unit/tables/test_backends.py +7 -5
- {ngio-0.2.0a2 → ngio-0.2.0b1}/tests/unit/tables/test_feature_table.py +1 -1
- ngio-0.2.0b1/tests/unit/tables/test_generic_table.py +56 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/tests/unit/tables/test_masking_roi_table_v1.py +1 -1
- ngio-0.2.0b1/tests/unit/tables/test_table_group.py +34 -0
- ngio-0.2.0b1/tests/unit/test_ome_zarr_meta/test_image_handler.py +15 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/tests/unit/test_ome_zarr_meta/test_unit_ngio_specs.py +14 -6
- {ngio-0.2.0a2 → ngio-0.2.0b1}/tests/unit/test_ome_zarr_meta/test_unit_v04_utils.py +2 -2
- ngio-0.2.0a2/docs/api/core.md +0 -8
- ngio-0.2.0a2/src/ngio/hcs/__init__.py +0 -60
- ngio-0.2.0a2/src/ngio/images/label.py +0 -236
- ngio-0.2.0a2/src/ngio/ome_zarr_meta/__init__.py +0 -35
- ngio-0.2.0a2/src/ngio/ome_zarr_meta/_generic_handlers.py +0 -320
- ngio-0.2.0a2/src/ngio/ome_zarr_meta/_meta_handlers.py +0 -142
- ngio-0.2.0a2/src/ngio/ome_zarr_meta/ngio_specs/_ngio_hcs.py +0 -5
- ngio-0.2.0a2/src/ngio/ome_zarr_meta/v04/__init__.py +0 -11
- ngio-0.2.0a2/src/ngio/ome_zarr_meta/v04/_meta_handlers.py +0 -54
- ngio-0.2.0a2/src/ngio/tables/v1/_masking_roi_table.py +0 -175
- ngio-0.2.0a2/tests/conftest.py +0 -11
- ngio-0.2.0a2/tests/unit/images/test_omezarr_container.py +0 -95
- ngio-0.2.0a2/tests/unit/tables/test_generic_table.py +0 -24
- ngio-0.2.0a2/tests/unit/tables/test_table_group.py +0 -9
- ngio-0.2.0a2/tests/unit/test_ome_zarr_meta/test_image_handler.py +0 -13
- {ngio-0.2.0a2 → ngio-0.2.0b1}/.copier-answers.yml +0 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/.gitattributes +0 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/.github/ISSUE_TEMPLATE.md +0 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/.github/TEST_FAIL_TEMPLATE.md +0 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/.github/dependabot.yml +0 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/.github/workflows/build_docs.yml +0 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/.github/workflows/ci.yml +0 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/.pre-commit-config.yaml +0 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/LICENSE +0 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/README.md +0 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/_typos.toml +0 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/docs/getting-started.md +0 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/docs/index.md +0 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/docs/notebooks/processing.ipynb +0 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/mkdocs.yml +0 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/common/_common_types.py +0 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/images/__init__.py +0 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/ome_zarr_meta/ngio_specs/_axes.py +0 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/ome_zarr_meta/ngio_specs/_dataset.py +0 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/tables/backends/__init__.py +0 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/tables/backends/_abstract_backend.py +0 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/tables/backends/_table_backends.py +0 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/src/ngio/utils/_errors.py +0 -0
- {ngio-0.2.0a2/tests/data/meta_v04 → ngio-0.2.0b1/tests/data/v04/meta}/base_ome_zarr_image_meta.json +0 -0
- {ngio-0.2.0a2/tests/data/meta_v04 → ngio-0.2.0b1/tests/data/v04/meta}/base_ome_zarr_image_meta_wrong_axis_order.json +0 -0
- {ngio-0.2.0a2/tests/data/meta_v04 → ngio-0.2.0b1/tests/data/v04/meta}/base_ome_zarr_label_meta.json +0 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/tests/unit/common/test_dimensions.py +0 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/tests/unit/common/test_pyramid.py +0 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/tests/unit/common/test_roi.py +0 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/tests/unit/tables/test_roi_table_v1.py +0 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/tests/unit/tables/test_validators.py +0 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/tests/unit/utils/test_download_datasets.py +0 -0
- {ngio-0.2.0a2 → ngio-0.2.0b1}/tests/unit/utils/test_zarr_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ngio
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.0b1
|
|
4
4
|
Summary: Next Generation file format IO
|
|
5
5
|
Project-URL: homepage, https://github.com/lorenzocerrone/ngio
|
|
6
6
|
Project-URL: repository, https://github.com/lorenzocerrone/ngio
|
|
@@ -29,6 +29,7 @@ Requires-Dist: requests
|
|
|
29
29
|
Requires-Dist: xarray
|
|
30
30
|
Requires-Dist: zarr<3
|
|
31
31
|
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: devtools; extra == 'dev'
|
|
32
33
|
Requires-Dist: matplotlib; extra == 'dev'
|
|
33
34
|
Requires-Dist: mypy; extra == 'dev'
|
|
34
35
|
Requires-Dist: napari; extra == 'dev'
|
|
@@ -38,6 +39,7 @@ Requires-Dist: pre-commit; extra == 'dev'
|
|
|
38
39
|
Requires-Dist: pyqt5; extra == 'dev'
|
|
39
40
|
Requires-Dist: rich; extra == 'dev'
|
|
40
41
|
Requires-Dist: ruff; extra == 'dev'
|
|
42
|
+
Requires-Dist: scikit-image; extra == 'dev'
|
|
41
43
|
Provides-Extra: docs
|
|
42
44
|
Requires-Dist: mkdocs; extra == 'docs'
|
|
43
45
|
Requires-Dist: mkdocs-autorefs; extra == 'docs'
|
|
@@ -50,6 +52,7 @@ Requires-Dist: scikit-image; extra == 'docs'
|
|
|
50
52
|
Provides-Extra: test
|
|
51
53
|
Requires-Dist: pytest; extra == 'test'
|
|
52
54
|
Requires-Dist: pytest-cov; extra == 'test'
|
|
55
|
+
Requires-Dist: scikit-image; extra == 'test'
|
|
53
56
|
Description-Content-Type: text/markdown
|
|
54
57
|
|
|
55
58
|
# NGIO - Next Generation file format IO
|
|
@@ -10,15 +10,6 @@
|
|
|
10
10
|
"\n",
|
|
11
11
|
"For this example we will use a small example image that can be downloaded from the following link: [example ome-zarr](https://zenodo.org/records/13305156)\n",
|
|
12
12
|
"\n",
|
|
13
|
-
"## Setup\n",
|
|
14
|
-
"\n",
|
|
15
|
-
"You can download the example image (on Linux and Mac os) by running the following command:\n",
|
|
16
|
-
"\n",
|
|
17
|
-
"```bash\n",
|
|
18
|
-
"bash setup_data.sh\n",
|
|
19
|
-
"```\n",
|
|
20
|
-
"from the root of the repository.\n",
|
|
21
|
-
"\n",
|
|
22
13
|
"## OmeZarr Container\n",
|
|
23
14
|
"\n",
|
|
24
15
|
"The `OmeZarr Container` provides a high-level interface to read, write and manipulate NGFF images.\n",
|
|
@@ -95,8 +86,10 @@
|
|
|
95
86
|
"print(image)\n",
|
|
96
87
|
"\n",
|
|
97
88
|
"# 3. Get image from a specific pixel size using the pixel_size keyword\n",
|
|
98
|
-
"image = omezarr_container.get_image(
|
|
99
|
-
"
|
|
89
|
+
"# image = omezarr_container.get_image(\n",
|
|
90
|
+
"# pixel_size=PixelSize(x=0.65, y=0.65, z=1), strict=True\n",
|
|
91
|
+
"# )\n",
|
|
92
|
+
"print(image.pixel_size == PixelSize(x=0.325, y=0.325, z=1))"
|
|
100
93
|
]
|
|
101
94
|
},
|
|
102
95
|
{
|
|
@@ -253,6 +246,32 @@
|
|
|
253
246
|
"print(new_omezarr_image)"
|
|
254
247
|
]
|
|
255
248
|
},
|
|
249
|
+
{
|
|
250
|
+
"cell_type": "markdown",
|
|
251
|
+
"metadata": {},
|
|
252
|
+
"source": [
|
|
253
|
+
"# Create an OmeZarr From a Numpy Array\n"
|
|
254
|
+
]
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
"cell_type": "code",
|
|
258
|
+
"execution_count": null,
|
|
259
|
+
"metadata": {},
|
|
260
|
+
"outputs": [],
|
|
261
|
+
"source": [
|
|
262
|
+
"import numpy as np\n",
|
|
263
|
+
"\n",
|
|
264
|
+
"from ngio import create_omezarr_from_array\n",
|
|
265
|
+
"\n",
|
|
266
|
+
"x = np.random.randint(0, 255, (16, 128, 128), dtype=np.uint8)\n",
|
|
267
|
+
"\n",
|
|
268
|
+
"new_omezarr_image = create_omezarr_from_array(\n",
|
|
269
|
+
" store=\"random_ome.zarr\", array=x, xy_pixelsize=0.65, z_spacing=1.0\n",
|
|
270
|
+
")\n",
|
|
271
|
+
"print(new_omezarr_image)\n",
|
|
272
|
+
"print(new_omezarr_image.get_image())"
|
|
273
|
+
]
|
|
274
|
+
},
|
|
256
275
|
{
|
|
257
276
|
"cell_type": "markdown",
|
|
258
277
|
"metadata": {},
|
|
@@ -268,6 +287,7 @@
|
|
|
268
287
|
"metadata": {},
|
|
269
288
|
"outputs": [],
|
|
270
289
|
"source": [
|
|
290
|
+
"import fsspec\n",
|
|
271
291
|
"import fsspec.implementations.http\n",
|
|
272
292
|
"\n",
|
|
273
293
|
"url = (\n",
|
|
@@ -279,17 +299,26 @@
|
|
|
279
299
|
"\n",
|
|
280
300
|
"fs = fsspec.implementations.http.HTTPFileSystem(client_kwargs={})\n",
|
|
281
301
|
"store = fs.get_mapper(url)\n",
|
|
282
|
-
"\n",
|
|
283
302
|
"omezarr = open_omezarr_container(store)\n",
|
|
284
303
|
"omezarr"
|
|
285
304
|
]
|
|
286
305
|
},
|
|
287
306
|
{
|
|
288
|
-
"cell_type": "
|
|
289
|
-
"execution_count": null,
|
|
307
|
+
"cell_type": "markdown",
|
|
290
308
|
"metadata": {},
|
|
291
|
-
"
|
|
292
|
-
|
|
309
|
+
"source": [
|
|
310
|
+
"# Streaming an OmeZarr from a Fractal Server\n",
|
|
311
|
+
"\n",
|
|
312
|
+
"Example:\n",
|
|
313
|
+
"\n",
|
|
314
|
+
"```python\n",
|
|
315
|
+
"from ngio.utils import fractal_fsspec_store\n",
|
|
316
|
+
"\n",
|
|
317
|
+
"store = fractal_fsspec_store(url=\"https://fracral_url...\", fractal_token=\"**your_secret_token**\")\n",
|
|
318
|
+
"omezarr = open_omezarr_container(store)\n",
|
|
319
|
+
"omezarr\n",
|
|
320
|
+
"```"
|
|
321
|
+
]
|
|
293
322
|
}
|
|
294
323
|
],
|
|
295
324
|
"metadata": {
|
|
@@ -216,7 +216,7 @@
|
|
|
216
216
|
"outputs": [],
|
|
217
217
|
"source": [
|
|
218
218
|
"# Create a a new label object and set it to a simple segmentation\n",
|
|
219
|
-
"new_label = omezarr.derive_label(\"
|
|
219
|
+
"new_label = omezarr.derive_label(\"new_label\", overwrite=True)\n",
|
|
220
220
|
"\n",
|
|
221
221
|
"simple_segmentation = image.get_array(c=0) > 100\n",
|
|
222
222
|
"simple_segmentation = simple_segmentation[0]\n",
|
|
@@ -225,7 +225,7 @@
|
|
|
225
225
|
"# make a subplot with two image show side by side\n",
|
|
226
226
|
"fig, axs = plt.subplots(1, 2, figsize=(10, 5))\n",
|
|
227
227
|
"axs[0].imshow(image.get_array()[0, 0], cmap=\"gray\")\n",
|
|
228
|
-
"axs[1].imshow(new_label.get_array()[0]
|
|
228
|
+
"axs[1].imshow(new_label.get_array()[0])\n",
|
|
229
229
|
"for ax in axs:\n",
|
|
230
230
|
" ax.axis(\"off\")\n",
|
|
231
231
|
"plt.tight_layout()\n",
|
|
@@ -327,13 +327,6 @@
|
|
|
327
327
|
"feat_table = omezarr.get_table(\"new_feature_table\")\n",
|
|
328
328
|
"feat_table.dataframe"
|
|
329
329
|
]
|
|
330
|
-
},
|
|
331
|
-
{
|
|
332
|
-
"cell_type": "code",
|
|
333
|
-
"execution_count": null,
|
|
334
|
-
"metadata": {},
|
|
335
|
-
"outputs": [],
|
|
336
|
-
"source": []
|
|
337
330
|
}
|
|
338
331
|
],
|
|
339
332
|
"metadata": {
|
|
@@ -51,18 +51,20 @@ dependencies = [
|
|
|
51
51
|
# https://peps.python.org/pep-0621/#dependencies-optional-dependencies
|
|
52
52
|
# "extras" (e.g. for `pip install .[test]`)
|
|
53
53
|
[project.optional-dependencies]
|
|
54
|
-
test = ["pytest", "pytest-cov"]
|
|
54
|
+
test = ["pytest", "pytest-cov", "scikit-image"]
|
|
55
55
|
|
|
56
56
|
dev = [
|
|
57
57
|
"napari",
|
|
58
58
|
"pyqt5",
|
|
59
59
|
"matplotlib",
|
|
60
|
+
"devtools",
|
|
60
61
|
"notebook",
|
|
61
62
|
"mypy",
|
|
62
|
-
"pdbpp",
|
|
63
|
+
"pdbpp", # https://github.com/pdbpp/pdbpp
|
|
63
64
|
"pre-commit",
|
|
64
|
-
"rich",
|
|
65
|
+
"rich", # https://github.com/Textualize/rich
|
|
65
66
|
"ruff",
|
|
67
|
+
"scikit-image",
|
|
66
68
|
] # add anything else you like to have in your dev environment here
|
|
67
69
|
|
|
68
70
|
docs = [
|
|
@@ -212,18 +214,12 @@ test13 = { features = ["py13", "test"], solve-group = "py13" }
|
|
|
212
214
|
# dev env
|
|
213
215
|
dev = { features = ["dev", "test"], solve-group = "py11" }
|
|
214
216
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
217
|
+
[tool.pixi.tasks]
|
|
218
|
+
serve_docs = "mkdocs serve"
|
|
219
|
+
run_tests = "pytest"
|
|
220
|
+
clean_nb_data = "rm -rf ./docs/notebooks/**/*.zarr"
|
|
218
221
|
test_nb = { cmd = "jupyter-execute ./docs/notebooks/*.ipynb" }
|
|
219
|
-
|
|
220
|
-
[tool.pixi.feature.py12.tasks]
|
|
221
|
-
pytest_test12 = "pytest"
|
|
222
|
-
|
|
223
|
-
[tool.pixi.feature.py13.tasks]
|
|
224
|
-
pytest_test13 = "pytest"
|
|
225
|
-
|
|
226
|
-
[tool.pixi.feature.task-feat.tasks]
|
|
222
|
+
test = { depends-on = ["run_tests", "clean_nb_data", "test_nb"] }
|
|
227
223
|
pre_commit_install = "pre-commit install"
|
|
228
224
|
|
|
229
225
|
ruff-fix-imports = "ruff check --select I --fix"
|
|
@@ -233,12 +229,3 @@ pre-commit = { cmd = "pre-commit run --all-files", depends-on = [
|
|
|
233
229
|
"pre_commit_install",
|
|
234
230
|
"ruff-format",
|
|
235
231
|
] }
|
|
236
|
-
|
|
237
|
-
[tool.pixi.tasks]
|
|
238
|
-
serve_docs = "mkdocs serve"
|
|
239
|
-
test = { depends-on = [
|
|
240
|
-
"pytest_test11",
|
|
241
|
-
"pytest_test12",
|
|
242
|
-
"pytest_test13",
|
|
243
|
-
"test_nb",
|
|
244
|
-
] }
|
|
@@ -10,7 +10,7 @@ __author__ = "Lorenzo Cerrone"
|
|
|
10
10
|
__email__ = "lorenzo.cerrone@uzh.ch"
|
|
11
11
|
|
|
12
12
|
from ngio.common import ArrayLike, Dimensions
|
|
13
|
-
from ngio.hcs import OmeZarrPlate,
|
|
13
|
+
from ngio.hcs import OmeZarrPlate, create_empty_plate, open_omezarr_plate
|
|
14
14
|
from ngio.images import (
|
|
15
15
|
Image,
|
|
16
16
|
Label,
|
|
@@ -20,22 +20,22 @@ from ngio.images import (
|
|
|
20
20
|
open_image,
|
|
21
21
|
open_omezarr_container,
|
|
22
22
|
)
|
|
23
|
-
from ngio.ome_zarr_meta.ngio_specs import AxesSetup, PixelSize
|
|
23
|
+
from ngio.ome_zarr_meta.ngio_specs import AxesSetup, ImageInWellPath, PixelSize
|
|
24
24
|
|
|
25
25
|
__all__ = [
|
|
26
26
|
"ArrayLike",
|
|
27
27
|
"AxesSetup",
|
|
28
28
|
"Dimensions",
|
|
29
29
|
"Image",
|
|
30
|
+
"ImageInWellPath",
|
|
30
31
|
"Label",
|
|
31
32
|
"OmeZarrContainer",
|
|
32
33
|
"OmeZarrPlate",
|
|
33
|
-
"OmeZarrWell",
|
|
34
34
|
"PixelSize",
|
|
35
35
|
"create_empty_omezarr",
|
|
36
|
+
"create_empty_plate",
|
|
36
37
|
"create_omezarr_from_array",
|
|
37
38
|
"open_image",
|
|
38
39
|
"open_omezarr_container",
|
|
39
40
|
"open_omezarr_plate",
|
|
40
|
-
"open_omezarr_well",
|
|
41
41
|
]
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
"""Common classes and functions that are used across the package."""
|
|
2
2
|
|
|
3
|
-
from ngio.common._array_pipe import
|
|
3
|
+
from ngio.common._array_pipe import (
|
|
4
|
+
get_masked_pipe,
|
|
5
|
+
get_pipe,
|
|
6
|
+
set_masked_pipe,
|
|
7
|
+
set_pipe,
|
|
8
|
+
)
|
|
4
9
|
from ngio.common._axes_transforms import (
|
|
5
10
|
transform_dask_array,
|
|
6
11
|
transform_list,
|
|
@@ -8,8 +13,9 @@ from ngio.common._axes_transforms import (
|
|
|
8
13
|
)
|
|
9
14
|
from ngio.common._common_types import ArrayLike
|
|
10
15
|
from ngio.common._dimensions import Dimensions
|
|
16
|
+
from ngio.common._masking_roi import compute_masking_roi
|
|
11
17
|
from ngio.common._pyramid import consolidate_pyramid, init_empty_pyramid, on_disk_zoom
|
|
12
|
-
from ngio.common._roi import RasterCooROI, WorldCooROI
|
|
18
|
+
from ngio.common._roi import RasterCooROI, WorldCooROI, roi_to_slice_kwargs
|
|
13
19
|
from ngio.common._slicer import (
|
|
14
20
|
SliceTransform,
|
|
15
21
|
compute_and_slices,
|
|
@@ -27,16 +33,20 @@ __all__ = [
|
|
|
27
33
|
"SliceTransform",
|
|
28
34
|
"WorldCooROI",
|
|
29
35
|
"compute_and_slices",
|
|
36
|
+
"compute_masking_roi",
|
|
30
37
|
"consolidate_pyramid",
|
|
31
38
|
"dask_get_slice",
|
|
32
39
|
"dask_set_slice",
|
|
33
40
|
"dask_zoom",
|
|
41
|
+
"get_masked_pipe",
|
|
34
42
|
"get_pipe",
|
|
35
43
|
"init_empty_pyramid",
|
|
36
44
|
"numpy_get_slice",
|
|
37
45
|
"numpy_set_slice",
|
|
38
46
|
"numpy_zoom",
|
|
39
47
|
"on_disk_zoom",
|
|
48
|
+
"roi_to_slice_kwargs",
|
|
49
|
+
"set_masked_pipe",
|
|
40
50
|
"set_pipe",
|
|
41
51
|
"transform_dask_array",
|
|
42
52
|
"transform_list",
|
|
@@ -158,3 +158,109 @@ def set_pipe(
|
|
|
158
158
|
)
|
|
159
159
|
else:
|
|
160
160
|
raise NgioValueError("Unknown patch type, expected numpy, dask or delayed.")
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def _mask_pipe_common(
|
|
164
|
+
array: zarr.Array,
|
|
165
|
+
label_array: zarr.Array,
|
|
166
|
+
label: int,
|
|
167
|
+
*,
|
|
168
|
+
dimensions_array: Dimensions,
|
|
169
|
+
dimensions_label: Dimensions,
|
|
170
|
+
axes_order: Collection[str] | None = None,
|
|
171
|
+
mode: Literal["numpy", "dask", "delayed"] = "numpy",
|
|
172
|
+
**slice_kwargs: slice | int | Iterable[int],
|
|
173
|
+
):
|
|
174
|
+
array_patch = get_pipe(
|
|
175
|
+
array,
|
|
176
|
+
dimensions=dimensions_array,
|
|
177
|
+
axes_order=axes_order,
|
|
178
|
+
mode=mode,
|
|
179
|
+
**slice_kwargs,
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
if "c" in slice_kwargs.keys():
|
|
183
|
+
# This makes the strong assumption that the
|
|
184
|
+
# user is passing the channel axis as "c"
|
|
185
|
+
# This will fail if the channel axis is queried
|
|
186
|
+
# with a different on-disk name
|
|
187
|
+
slice_kwargs.pop("c")
|
|
188
|
+
|
|
189
|
+
label_patch = get_pipe(
|
|
190
|
+
label_array,
|
|
191
|
+
dimensions=dimensions_label,
|
|
192
|
+
axes_order=axes_order,
|
|
193
|
+
mode=mode,
|
|
194
|
+
**slice_kwargs,
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
if isinstance(array_patch, np.ndarray):
|
|
198
|
+
label_patch = np.broadcast_to(label_patch, array_patch.shape)
|
|
199
|
+
elif isinstance(array_patch, dask.array.Array):
|
|
200
|
+
label_patch = dask.array.broadcast_to(label_patch, array_patch.shape)
|
|
201
|
+
else:
|
|
202
|
+
raise NgioValueError(f"Mode {mode} not yet supported for masked array.")
|
|
203
|
+
|
|
204
|
+
mask = label_patch == label
|
|
205
|
+
return array_patch, mask
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def get_masked_pipe(
|
|
209
|
+
array: zarr.Array,
|
|
210
|
+
label_array: zarr.Array,
|
|
211
|
+
label: int,
|
|
212
|
+
*,
|
|
213
|
+
dimensions_array: Dimensions,
|
|
214
|
+
dimensions_label: Dimensions,
|
|
215
|
+
axes_order: Collection[str] | None = None,
|
|
216
|
+
mode: Literal["numpy", "dask", "delayed"] = "numpy",
|
|
217
|
+
**slice_kwargs: slice | int | Iterable[int],
|
|
218
|
+
):
|
|
219
|
+
array_patch, mask = _mask_pipe_common(
|
|
220
|
+
array=array,
|
|
221
|
+
label_array=label_array,
|
|
222
|
+
label=label,
|
|
223
|
+
dimensions_array=dimensions_array,
|
|
224
|
+
dimensions_label=dimensions_label,
|
|
225
|
+
axes_order=axes_order,
|
|
226
|
+
mode=mode,
|
|
227
|
+
**slice_kwargs,
|
|
228
|
+
)
|
|
229
|
+
array_patch[~mask] = 0
|
|
230
|
+
return array_patch
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def set_masked_pipe(
|
|
234
|
+
array: zarr.Array,
|
|
235
|
+
label_array: zarr.Array,
|
|
236
|
+
label: int,
|
|
237
|
+
patch: ArrayLike,
|
|
238
|
+
*,
|
|
239
|
+
dimensions_array: Dimensions,
|
|
240
|
+
dimensions_label: Dimensions,
|
|
241
|
+
axes_order: Collection[str] | None = None,
|
|
242
|
+
**slice_kwargs: slice | int | Iterable[int],
|
|
243
|
+
):
|
|
244
|
+
if isinstance(patch, dask.array.Array):
|
|
245
|
+
mode = "dask"
|
|
246
|
+
elif isinstance(patch, np.ndarray):
|
|
247
|
+
mode = "numpy"
|
|
248
|
+
else:
|
|
249
|
+
raise NgioValueError(
|
|
250
|
+
"Mode not yet supported for masked array. Expected a numpy or dask array."
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
array_patch, mask = _mask_pipe_common(
|
|
254
|
+
array=array,
|
|
255
|
+
label_array=label_array,
|
|
256
|
+
label=label,
|
|
257
|
+
dimensions_array=dimensions_array,
|
|
258
|
+
dimensions_label=dimensions_label,
|
|
259
|
+
axes_order=axes_order,
|
|
260
|
+
mode=mode,
|
|
261
|
+
**slice_kwargs,
|
|
262
|
+
)
|
|
263
|
+
patch = np.where(mask, patch, array_patch)
|
|
264
|
+
set_pipe(
|
|
265
|
+
array, patch, dimensions=dimensions_array, axes_order=axes_order, **slice_kwargs
|
|
266
|
+
)
|
|
@@ -9,6 +9,7 @@ from ngio.ome_zarr_meta.ngio_specs._axes import (
|
|
|
9
9
|
AxesTransformation,
|
|
10
10
|
AxesTranspose,
|
|
11
11
|
)
|
|
12
|
+
from ngio.utils import NgioValueError
|
|
12
13
|
|
|
13
14
|
T = TypeVar("T")
|
|
14
15
|
|
|
@@ -44,7 +45,7 @@ def transform_numpy_array(
|
|
|
44
45
|
elif isinstance(operation, AxesSqueeze):
|
|
45
46
|
array = np.squeeze(array, axis=operation.axes)
|
|
46
47
|
else:
|
|
47
|
-
raise
|
|
48
|
+
raise NgioValueError(f"Unknown operation {operation}")
|
|
48
49
|
return array
|
|
49
50
|
|
|
50
51
|
|
|
@@ -59,5 +60,5 @@ def transform_dask_array(
|
|
|
59
60
|
elif isinstance(operation, AxesSqueeze):
|
|
60
61
|
array = da.squeeze(array, axis=operation.axes)
|
|
61
62
|
else:
|
|
62
|
-
raise
|
|
63
|
+
raise NgioValueError(f"Unknown operation {operation}")
|
|
63
64
|
return array
|
|
@@ -57,6 +57,13 @@ class Dimensions:
|
|
|
57
57
|
return 1
|
|
58
58
|
return self._shape[index]
|
|
59
59
|
|
|
60
|
+
def has_axis(self, axis_name: str) -> bool:
|
|
61
|
+
"""Return whether the axis exists."""
|
|
62
|
+
index = self._axes_mapper.get_axis(axis_name)
|
|
63
|
+
if index is None:
|
|
64
|
+
return False
|
|
65
|
+
return True
|
|
66
|
+
|
|
60
67
|
def get_shape(self, axes_order: Collection[str]) -> tuple[int, ...]:
|
|
61
68
|
"""Return the shape in the given axes order."""
|
|
62
69
|
transforms = self._axes_mapper.to_order(axes_order)
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"""Utilities to build masking regions of interest (ROIs)."""
|
|
2
|
+
|
|
3
|
+
import itertools
|
|
4
|
+
|
|
5
|
+
import dask
|
|
6
|
+
import dask.array as da
|
|
7
|
+
import dask.delayed
|
|
8
|
+
import numpy as np
|
|
9
|
+
import scipy.ndimage as ndi
|
|
10
|
+
|
|
11
|
+
from ngio.common._roi import RasterCooROI, WorldCooROI
|
|
12
|
+
from ngio.ome_zarr_meta import PixelSize
|
|
13
|
+
from ngio.utils import NgioValueError
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _compute_offsets(chunks):
|
|
17
|
+
"""Given a chunks tuple, compute cumulative offsets for each axis.
|
|
18
|
+
|
|
19
|
+
Returns a list where each element is a list of offsets for that dimension.
|
|
20
|
+
"""
|
|
21
|
+
offsets = []
|
|
22
|
+
for dim_chunks in chunks:
|
|
23
|
+
dim_offsets = [0]
|
|
24
|
+
for size in dim_chunks:
|
|
25
|
+
dim_offsets.append(dim_offsets[-1] + size)
|
|
26
|
+
offsets.append(dim_offsets)
|
|
27
|
+
return offsets
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _adjust_slices(slices, offset):
|
|
31
|
+
"""Adjust slices to global coordinates using the provided offset."""
|
|
32
|
+
adjusted_slices = {}
|
|
33
|
+
for label, s in slices.items():
|
|
34
|
+
adjusted = tuple(
|
|
35
|
+
slice(s_dim.start + off, s_dim.stop + off)
|
|
36
|
+
for s_dim, off in zip(s, offset, strict=True)
|
|
37
|
+
)
|
|
38
|
+
adjusted_slices[label] = adjusted
|
|
39
|
+
return adjusted_slices
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@dask.delayed
|
|
43
|
+
def _process_chunk(chunk, offset):
|
|
44
|
+
"""Process a single chunk.
|
|
45
|
+
|
|
46
|
+
run ndi.find_objects and adjust the slices
|
|
47
|
+
to global coordinates using the provided offset.
|
|
48
|
+
"""
|
|
49
|
+
local_slices = compute_slices(chunk)
|
|
50
|
+
local_slices = _adjust_slices(local_slices, offset)
|
|
51
|
+
return local_slices
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _merge_slices(
|
|
55
|
+
slice1: tuple[slice, ...], slice2: tuple[slice, ...]
|
|
56
|
+
) -> tuple[slice, ...]:
|
|
57
|
+
"""Merge two slices."""
|
|
58
|
+
merged = []
|
|
59
|
+
for s1, s2 in zip(slice1, slice2, strict=True):
|
|
60
|
+
start = min(s1.start, s2.start)
|
|
61
|
+
stop = max(s1.stop, s2.stop)
|
|
62
|
+
merged.append(slice(start, stop))
|
|
63
|
+
return tuple(merged)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@dask.delayed
|
|
67
|
+
def _collect_slices(
|
|
68
|
+
local_slices: list[dict[int, tuple[slice, ...]]],
|
|
69
|
+
) -> dict[int, tuple[slice]]:
|
|
70
|
+
"""Collect the slices from the delayed results."""
|
|
71
|
+
global_slices = {}
|
|
72
|
+
for result in local_slices:
|
|
73
|
+
for label, s in result.items():
|
|
74
|
+
if label in global_slices:
|
|
75
|
+
global_slices[label] = _merge_slices(global_slices[label], s)
|
|
76
|
+
else:
|
|
77
|
+
global_slices[label] = s
|
|
78
|
+
return global_slices
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def compute_slices(segmentation: np.ndarray) -> dict[int, tuple[slice, ...]]:
|
|
82
|
+
"""Compute slices for each label in a segmentation.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
segmentation (ndarray): The segmentation array.
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
dict[int, tuple[slice]]: A dictionary with the label as key
|
|
89
|
+
and the slice as value.
|
|
90
|
+
"""
|
|
91
|
+
slices = ndi.find_objects(segmentation)
|
|
92
|
+
slices_dict = {}
|
|
93
|
+
for label, s in enumerate(slices, start=1):
|
|
94
|
+
if s is None:
|
|
95
|
+
continue
|
|
96
|
+
else:
|
|
97
|
+
slices_dict[label] = s
|
|
98
|
+
return slices_dict
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def lazy_compute_slices(segmentation: da.Array) -> dict[int, tuple[slice, ...]]:
|
|
102
|
+
"""Compute slices for each label in a segmentation."""
|
|
103
|
+
global_offsets = _compute_offsets(segmentation.chunks)
|
|
104
|
+
delayed_chunks = segmentation.to_delayed()
|
|
105
|
+
|
|
106
|
+
grid_shape = tuple(len(c) for c in segmentation.chunks)
|
|
107
|
+
|
|
108
|
+
grid_indices = list(itertools.product(*[range(n) for n in grid_shape]))
|
|
109
|
+
delayed_results = []
|
|
110
|
+
for idx, chunk in zip(grid_indices, np.ravel(delayed_chunks), strict=True):
|
|
111
|
+
offset = tuple(global_offsets[dim][idx[dim]] for dim in range(len(idx)))
|
|
112
|
+
delayed_result = _process_chunk(chunk, offset)
|
|
113
|
+
delayed_results.append(delayed_result)
|
|
114
|
+
|
|
115
|
+
return _collect_slices(delayed_results).compute()
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def compute_masking_roi(
|
|
119
|
+
segmentation: np.ndarray | da.Array, pixel_size: PixelSize
|
|
120
|
+
) -> list[WorldCooROI]:
|
|
121
|
+
"""Compute a ROIs for each label in a segmentation.
|
|
122
|
+
|
|
123
|
+
This function expects a 2D or 3D segmentation array.
|
|
124
|
+
And this function expects the axes order to be 'zyx' or 'yx'.
|
|
125
|
+
Other axes orders are not supported.
|
|
126
|
+
|
|
127
|
+
"""
|
|
128
|
+
if segmentation.ndim not in [2, 3]:
|
|
129
|
+
raise NgioValueError("Only 2D and 3D segmentations are supported.")
|
|
130
|
+
|
|
131
|
+
if isinstance(segmentation, da.Array):
|
|
132
|
+
slices = lazy_compute_slices(segmentation)
|
|
133
|
+
else:
|
|
134
|
+
slices = compute_slices(segmentation)
|
|
135
|
+
|
|
136
|
+
rois = []
|
|
137
|
+
for label, slice_ in slices.items():
|
|
138
|
+
if len(slice_) == 2:
|
|
139
|
+
min_z, min_y, min_x = 0, slice_[0].start, slice_[1].start
|
|
140
|
+
max_z, max_y, max_x = 1, slice_[0].stop, slice_[1].stop
|
|
141
|
+
elif len(slice_) == 3:
|
|
142
|
+
min_z, min_y, min_x = slice_[0].start, slice_[1].start, slice_[2].start
|
|
143
|
+
max_z, max_y, max_x = slice_[0].stop, slice_[1].stop, slice_[2].stop
|
|
144
|
+
else:
|
|
145
|
+
raise ValueError("Invalid slice length.")
|
|
146
|
+
roi = RasterCooROI(
|
|
147
|
+
name=str(label),
|
|
148
|
+
x_length=max_x - min_x,
|
|
149
|
+
y_length=max_y - min_y,
|
|
150
|
+
z_length=max_z - min_z,
|
|
151
|
+
x=min_x,
|
|
152
|
+
y=min_y,
|
|
153
|
+
z=min_z,
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
roi = roi.to_world_coo_roi(pixel_size)
|
|
157
|
+
rois.append(roi)
|
|
158
|
+
return rois
|