ngio 0.4.0b1__tar.gz → 0.4.2__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.
Files changed (258) hide show
  1. {ngio-0.4.0b1 → ngio-0.4.2}/.github/workflows/build_docs.yml +1 -1
  2. {ngio-0.4.0b1 → ngio-0.4.2}/.github/workflows/ci.yml +2 -2
  3. {ngio-0.4.0b1 → ngio-0.4.2}/CHANGELOG.md +27 -10
  4. {ngio-0.4.0b1 → ngio-0.4.2}/PKG-INFO +14 -14
  5. {ngio-0.4.0b1 → ngio-0.4.2}/README.md +13 -12
  6. {ngio-0.4.0b1 → ngio-0.4.2}/docs/index.md +4 -3
  7. {ngio-0.4.0b1 → ngio-0.4.2}/pyproject.toml +1 -1
  8. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/common/_roi.py +51 -18
  9. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/io_pipes/_io_pipes_roi.py +4 -10
  10. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/io_pipes/_ops_slices.py +23 -58
  11. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/io_pipes/_ops_slices_utils.py +4 -4
  12. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/io_pipes/_zoom_transform.py +6 -1
  13. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/ome_zarr_meta/ngio_specs/_pixel_size.py +12 -39
  14. {ngio-0.4.0b1 → ngio-0.4.2}/tests/unit/common/test_roi.py +2 -2
  15. {ngio-0.4.0b1 → ngio-0.4.2}/tests/unit/images/test_images.py +33 -0
  16. {ngio-0.4.0b1 → ngio-0.4.2}/.copier-answers.yml +0 -0
  17. {ngio-0.4.0b1 → ngio-0.4.2}/.gitattributes +0 -0
  18. {ngio-0.4.0b1 → ngio-0.4.2}/.github/ISSUE_TEMPLATE.md +0 -0
  19. {ngio-0.4.0b1 → ngio-0.4.2}/.github/TEST_FAIL_TEMPLATE.md +0 -0
  20. {ngio-0.4.0b1 → ngio-0.4.2}/.github/dependabot.yml +0 -0
  21. {ngio-0.4.0b1 → ngio-0.4.2}/.github/pull_request_template.md +0 -0
  22. {ngio-0.4.0b1 → ngio-0.4.2}/.gitignore +0 -0
  23. {ngio-0.4.0b1 → ngio-0.4.2}/.pre-commit-config.yaml +0 -0
  24. {ngio-0.4.0b1 → ngio-0.4.2}/LICENSE +0 -0
  25. {ngio-0.4.0b1 → ngio-0.4.2}/_typos.toml +0 -0
  26. {ngio-0.4.0b1 → ngio-0.4.2}/docs/api/hcs.md +0 -0
  27. {ngio-0.4.0b1 → ngio-0.4.2}/docs/api/images.md +0 -0
  28. {ngio-0.4.0b1 → ngio-0.4.2}/docs/api/iterators.md +0 -0
  29. {ngio-0.4.0b1 → ngio-0.4.2}/docs/api/ngio/common.md +0 -0
  30. {ngio-0.4.0b1 → ngio-0.4.2}/docs/api/ngio/hcs.md +0 -0
  31. {ngio-0.4.0b1 → ngio-0.4.2}/docs/api/ngio/images.md +0 -0
  32. {ngio-0.4.0b1 → ngio-0.4.2}/docs/api/ngio/io_pipes.md +0 -0
  33. {ngio-0.4.0b1 → ngio-0.4.2}/docs/api/ngio/iterators.md +0 -0
  34. {ngio-0.4.0b1 → ngio-0.4.2}/docs/api/ngio/ngio.md +0 -0
  35. {ngio-0.4.0b1 → ngio-0.4.2}/docs/api/ngio/tables.md +0 -0
  36. {ngio-0.4.0b1 → ngio-0.4.2}/docs/api/ngio/transforms.md +0 -0
  37. {ngio-0.4.0b1 → ngio-0.4.2}/docs/api/ngio/utils.md +0 -0
  38. {ngio-0.4.0b1 → ngio-0.4.2}/docs/api/ome_zarr_container.md +0 -0
  39. {ngio-0.4.0b1 → ngio-0.4.2}/docs/api/tables.md +0 -0
  40. {ngio-0.4.0b1 → ngio-0.4.2}/docs/changelog.md +0 -0
  41. {ngio-0.4.0b1 → ngio-0.4.2}/docs/code_of_conduct.md +0 -0
  42. {ngio-0.4.0b1 → ngio-0.4.2}/docs/contributing.md +0 -0
  43. {ngio-0.4.0b1 → ngio-0.4.2}/docs/getting_started/0_quickstart.md +0 -0
  44. {ngio-0.4.0b1 → ngio-0.4.2}/docs/getting_started/1_ome_zarr_containers.md +0 -0
  45. {ngio-0.4.0b1 → ngio-0.4.2}/docs/getting_started/2_images.md +0 -0
  46. {ngio-0.4.0b1 → ngio-0.4.2}/docs/getting_started/3_tables.md +0 -0
  47. {ngio-0.4.0b1 → ngio-0.4.2}/docs/getting_started/4_masked_images.md +0 -0
  48. {ngio-0.4.0b1 → ngio-0.4.2}/docs/getting_started/5_hcs.md +0 -0
  49. {ngio-0.4.0b1 → ngio-0.4.2}/docs/getting_started/6_iterators.md +0 -0
  50. {ngio-0.4.0b1 → ngio-0.4.2}/docs/table_specs/backend.md +0 -0
  51. {ngio-0.4.0b1 → ngio-0.4.2}/docs/table_specs/overview.md +0 -0
  52. {ngio-0.4.0b1 → ngio-0.4.2}/docs/table_specs/table_types/condition_table.md +0 -0
  53. {ngio-0.4.0b1 → ngio-0.4.2}/docs/table_specs/table_types/custom_table.md +0 -0
  54. {ngio-0.4.0b1 → ngio-0.4.2}/docs/table_specs/table_types/feature_table.md +0 -0
  55. {ngio-0.4.0b1 → ngio-0.4.2}/docs/table_specs/table_types/generic_table.md +0 -0
  56. {ngio-0.4.0b1 → ngio-0.4.2}/docs/table_specs/table_types/masking_roi_table.md +0 -0
  57. {ngio-0.4.0b1 → ngio-0.4.2}/docs/table_specs/table_types/roi_table.md +0 -0
  58. {ngio-0.4.0b1 → ngio-0.4.2}/docs/tutorials/create_ome_zarr.ipynb +0 -0
  59. {ngio-0.4.0b1 → ngio-0.4.2}/docs/tutorials/feature_extraction.ipynb +0 -0
  60. {ngio-0.4.0b1 → ngio-0.4.2}/docs/tutorials/hcs_exploration.ipynb +0 -0
  61. {ngio-0.4.0b1 → ngio-0.4.2}/docs/tutorials/image_processing.ipynb +0 -0
  62. {ngio-0.4.0b1 → ngio-0.4.2}/docs/tutorials/image_segmentation.ipynb +0 -0
  63. {ngio-0.4.0b1 → ngio-0.4.2}/mkdocs.yml +0 -0
  64. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/__init__.py +0 -0
  65. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/common/__init__.py +0 -0
  66. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/common/_dimensions.py +0 -0
  67. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/common/_masking_roi.py +0 -0
  68. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/common/_pyramid.py +0 -0
  69. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/common/_synt_images_utils.py +0 -0
  70. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/common/_zoom.py +0 -0
  71. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/experimental/__init__.py +0 -0
  72. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/experimental/iterators/__init__.py +0 -0
  73. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/experimental/iterators/_abstract_iterator.py +0 -0
  74. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/experimental/iterators/_feature.py +0 -0
  75. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/experimental/iterators/_image_processing.py +0 -0
  76. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/experimental/iterators/_mappers.py +0 -0
  77. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/experimental/iterators/_rois_utils.py +0 -0
  78. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/experimental/iterators/_segmentation.py +0 -0
  79. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/hcs/__init__.py +0 -0
  80. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/hcs/_plate.py +0 -0
  81. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/images/__init__.py +0 -0
  82. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/images/_abstract_image.py +0 -0
  83. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/images/_create.py +0 -0
  84. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/images/_create_synt_container.py +0 -0
  85. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/images/_image.py +0 -0
  86. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/images/_label.py +0 -0
  87. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/images/_masked_image.py +0 -0
  88. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/images/_ome_zarr_container.py +0 -0
  89. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/images/_table_ops.py +0 -0
  90. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/io_pipes/__init__.py +0 -0
  91. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/io_pipes/_io_pipes.py +0 -0
  92. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/io_pipes/_io_pipes_masked.py +0 -0
  93. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/io_pipes/_io_pipes_types.py +0 -0
  94. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/io_pipes/_match_shape.py +0 -0
  95. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/io_pipes/_ops_axes.py +0 -0
  96. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/io_pipes/_ops_transforms.py +0 -0
  97. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/ome_zarr_meta/__init__.py +0 -0
  98. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/ome_zarr_meta/_meta_handlers.py +0 -0
  99. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/ome_zarr_meta/ngio_specs/__init__.py +0 -0
  100. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/ome_zarr_meta/ngio_specs/_axes.py +0 -0
  101. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/ome_zarr_meta/ngio_specs/_channels.py +0 -0
  102. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/ome_zarr_meta/ngio_specs/_dataset.py +0 -0
  103. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/ome_zarr_meta/ngio_specs/_ngio_hcs.py +0 -0
  104. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/ome_zarr_meta/ngio_specs/_ngio_image.py +0 -0
  105. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/ome_zarr_meta/v04/__init__.py +0 -0
  106. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/ome_zarr_meta/v04/_custom_models.py +0 -0
  107. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/ome_zarr_meta/v04/_v04_spec_utils.py +0 -0
  108. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/resources/20200812-CardiomyocyteDifferentiation14-Cycle1_B03/mask.png +0 -0
  109. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/resources/20200812-CardiomyocyteDifferentiation14-Cycle1_B03/nuclei.png +0 -0
  110. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/resources/20200812-CardiomyocyteDifferentiation14-Cycle1_B03/raw.jpg +0 -0
  111. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/resources/__init__.py +0 -0
  112. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/resources/resource_model.py +0 -0
  113. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/tables/__init__.py +0 -0
  114. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/tables/_abstract_table.py +0 -0
  115. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/tables/_tables_container.py +0 -0
  116. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/tables/backends/__init__.py +0 -0
  117. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/tables/backends/_abstract_backend.py +0 -0
  118. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/tables/backends/_anndata.py +0 -0
  119. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/tables/backends/_anndata_utils.py +0 -0
  120. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/tables/backends/_csv.py +0 -0
  121. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/tables/backends/_json.py +0 -0
  122. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/tables/backends/_non_zarr_backends.py +0 -0
  123. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/tables/backends/_parquet.py +0 -0
  124. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/tables/backends/_table_backends.py +0 -0
  125. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/tables/backends/_utils.py +0 -0
  126. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/tables/v1/__init__.py +0 -0
  127. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/tables/v1/_condition_table.py +0 -0
  128. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/tables/v1/_feature_table.py +0 -0
  129. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/tables/v1/_generic_table.py +0 -0
  130. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/tables/v1/_roi_table.py +0 -0
  131. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/transforms/__init__.py +0 -0
  132. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/transforms/_zoom.py +0 -0
  133. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/utils/__init__.py +0 -0
  134. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/utils/_datasets.py +0 -0
  135. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/utils/_errors.py +0 -0
  136. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/utils/_fractal_fsspec_store.py +0 -0
  137. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/utils/_logger.py +0 -0
  138. {ngio-0.4.0b1 → ngio-0.4.2}/src/ngio/utils/_zarr_utils.py +0 -0
  139. {ngio-0.4.0b1 → ngio-0.4.2}/tests/conftest.py +0 -0
  140. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_c1yx.zarr/.zattrs +0 -0
  141. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_c1yx.zarr/.zgroup +0 -0
  142. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_c1yx.zarr/0/.zarray +0 -0
  143. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_c1yx.zarr/1/.zarray +0 -0
  144. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_c1yx.zarr/labels/.zattrs +0 -0
  145. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_c1yx.zarr/labels/.zgroup +0 -0
  146. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_c1yx.zarr/labels/label/.zattrs +0 -0
  147. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_c1yx.zarr/labels/label/.zgroup +0 -0
  148. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_c1yx.zarr/labels/label/0/.zarray +0 -0
  149. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_c1yx.zarr/labels/label/1/.zarray +0 -0
  150. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_cyx.zarr/.zattrs +0 -0
  151. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_cyx.zarr/.zgroup +0 -0
  152. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_cyx.zarr/0/.zarray +0 -0
  153. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_cyx.zarr/1/.zarray +0 -0
  154. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_cyx.zarr/labels/.zattrs +0 -0
  155. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_cyx.zarr/labels/.zgroup +0 -0
  156. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_cyx.zarr/labels/label/.zattrs +0 -0
  157. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_cyx.zarr/labels/label/.zgroup +0 -0
  158. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_cyx.zarr/labels/label/0/.zarray +0 -0
  159. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_cyx.zarr/labels/label/1/.zarray +0 -0
  160. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_czyx.zarr/.zattrs +0 -0
  161. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_czyx.zarr/.zgroup +0 -0
  162. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_czyx.zarr/0/.zarray +0 -0
  163. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_czyx.zarr/1/.zarray +0 -0
  164. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_czyx.zarr/labels/.zattrs +0 -0
  165. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_czyx.zarr/labels/.zgroup +0 -0
  166. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_czyx.zarr/labels/label/.zattrs +0 -0
  167. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_czyx.zarr/labels/label/.zgroup +0 -0
  168. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_czyx.zarr/labels/label/0/.zarray +0 -0
  169. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_czyx.zarr/labels/label/1/.zarray +0 -0
  170. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tcyx.zarr/.zattrs +0 -0
  171. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tcyx.zarr/.zgroup +0 -0
  172. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tcyx.zarr/0/.zarray +0 -0
  173. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tcyx.zarr/1/.zarray +0 -0
  174. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tcyx.zarr/labels/.zattrs +0 -0
  175. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tcyx.zarr/labels/.zgroup +0 -0
  176. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tcyx.zarr/labels/label/.zattrs +0 -0
  177. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tcyx.zarr/labels/label/.zgroup +0 -0
  178. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tcyx.zarr/labels/label/0/.zarray +0 -0
  179. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tcyx.zarr/labels/label/1/.zarray +0 -0
  180. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tczyx.zarr/.zattrs +0 -0
  181. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tczyx.zarr/.zgroup +0 -0
  182. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tczyx.zarr/0/.zarray +0 -0
  183. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tczyx.zarr/1/.zarray +0 -0
  184. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tczyx.zarr/labels/.zattrs +0 -0
  185. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tczyx.zarr/labels/.zgroup +0 -0
  186. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tczyx.zarr/labels/label/.zattrs +0 -0
  187. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tczyx.zarr/labels/label/.zgroup +0 -0
  188. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tczyx.zarr/labels/label/0/.zarray +0 -0
  189. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tczyx.zarr/labels/label/1/.zarray +0 -0
  190. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tyx.zarr/.zattrs +0 -0
  191. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tyx.zarr/.zgroup +0 -0
  192. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tyx.zarr/0/.zarray +0 -0
  193. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tyx.zarr/1/.zarray +0 -0
  194. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tyx.zarr/labels/.zattrs +0 -0
  195. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tyx.zarr/labels/.zgroup +0 -0
  196. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tyx.zarr/labels/label/.zattrs +0 -0
  197. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tyx.zarr/labels/label/.zgroup +0 -0
  198. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tyx.zarr/labels/label/0/.zarray +0 -0
  199. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tyx.zarr/labels/label/1/.zarray +0 -0
  200. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tzyx.zarr/.zattrs +0 -0
  201. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tzyx.zarr/.zgroup +0 -0
  202. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tzyx.zarr/0/.zarray +0 -0
  203. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tzyx.zarr/1/.zarray +0 -0
  204. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tzyx.zarr/labels/.zattrs +0 -0
  205. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tzyx.zarr/labels/.zgroup +0 -0
  206. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tzyx.zarr/labels/label/.zattrs +0 -0
  207. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tzyx.zarr/labels/label/.zgroup +0 -0
  208. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tzyx.zarr/labels/label/0/.zarray +0 -0
  209. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_tzyx.zarr/labels/label/1/.zarray +0 -0
  210. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_yx.zarr/.zattrs +0 -0
  211. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_yx.zarr/.zgroup +0 -0
  212. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_yx.zarr/0/.zarray +0 -0
  213. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_yx.zarr/1/.zarray +0 -0
  214. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_yx.zarr/labels/.zattrs +0 -0
  215. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_yx.zarr/labels/.zgroup +0 -0
  216. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_yx.zarr/labels/label/.zattrs +0 -0
  217. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_yx.zarr/labels/label/.zgroup +0 -0
  218. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_yx.zarr/labels/label/0/.zarray +0 -0
  219. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_yx.zarr/labels/label/1/.zarray +0 -0
  220. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_zyx.zarr/.zattrs +0 -0
  221. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_zyx.zarr/.zgroup +0 -0
  222. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_zyx.zarr/0/.zarray +0 -0
  223. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_zyx.zarr/1/.zarray +0 -0
  224. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_zyx.zarr/labels/.zattrs +0 -0
  225. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_zyx.zarr/labels/.zgroup +0 -0
  226. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_zyx.zarr/labels/label/.zattrs +0 -0
  227. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_zyx.zarr/labels/label/.zgroup +0 -0
  228. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_zyx.zarr/labels/label/0/.zarray +0 -0
  229. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/images/test_image_zyx.zarr/labels/label/1/.zarray +0 -0
  230. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/meta/base_ome_zarr_image_meta.json +0 -0
  231. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/meta/base_ome_zarr_image_meta_wrong_axis_order.json +0 -0
  232. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/meta/base_ome_zarr_label_meta.json +0 -0
  233. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/meta/base_ome_zarr_well_meta.json +0 -0
  234. {ngio-0.4.0b1 → ngio-0.4.2}/tests/data/v04/meta/ome_zarr_well_path_normalization_meta.json +0 -0
  235. {ngio-0.4.0b1 → ngio-0.4.2}/tests/unit/common/test_dimensions.py +0 -0
  236. {ngio-0.4.0b1 → ngio-0.4.2}/tests/unit/common/test_pyramid.py +0 -0
  237. {ngio-0.4.0b1 → ngio-0.4.2}/tests/unit/common/test_transforms.py +0 -0
  238. {ngio-0.4.0b1 → ngio-0.4.2}/tests/unit/hcs/test_plate.py +0 -0
  239. {ngio-0.4.0b1 → ngio-0.4.2}/tests/unit/hcs/test_well.py +0 -0
  240. {ngio-0.4.0b1 → ngio-0.4.2}/tests/unit/images/test_create.py +0 -0
  241. {ngio-0.4.0b1 → ngio-0.4.2}/tests/unit/images/test_masked_images.py +0 -0
  242. {ngio-0.4.0b1 → ngio-0.4.2}/tests/unit/images/test_omezarr_container.py +0 -0
  243. {ngio-0.4.0b1 → ngio-0.4.2}/tests/unit/images/test_table_ops.py +0 -0
  244. {ngio-0.4.0b1 → ngio-0.4.2}/tests/unit/io_pipes/test_axes_ops.py +0 -0
  245. {ngio-0.4.0b1 → ngio-0.4.2}/tests/unit/io_pipes/test_slicing_ops.py +0 -0
  246. {ngio-0.4.0b1 → ngio-0.4.2}/tests/unit/iterators/test_iterators.py +0 -0
  247. {ngio-0.4.0b1 → ngio-0.4.2}/tests/unit/ome_zarr_meta/test_image_handler.py +0 -0
  248. {ngio-0.4.0b1 → ngio-0.4.2}/tests/unit/ome_zarr_meta/test_unit_ngio_specs.py +0 -0
  249. {ngio-0.4.0b1 → ngio-0.4.2}/tests/unit/ome_zarr_meta/test_unit_v04_utils.py +0 -0
  250. {ngio-0.4.0b1 → ngio-0.4.2}/tests/unit/tables/test_backends.py +0 -0
  251. {ngio-0.4.0b1 → ngio-0.4.2}/tests/unit/tables/test_backends_utils.py +0 -0
  252. {ngio-0.4.0b1 → ngio-0.4.2}/tests/unit/tables/test_feature_table.py +0 -0
  253. {ngio-0.4.0b1 → ngio-0.4.2}/tests/unit/tables/test_generic_table.py +0 -0
  254. {ngio-0.4.0b1 → ngio-0.4.2}/tests/unit/tables/test_masking_roi_table_v1.py +0 -0
  255. {ngio-0.4.0b1 → ngio-0.4.2}/tests/unit/tables/test_roi_table_v1.py +0 -0
  256. {ngio-0.4.0b1 → ngio-0.4.2}/tests/unit/tables/test_table_group.py +0 -0
  257. {ngio-0.4.0b1 → ngio-0.4.2}/tests/unit/utils/test_download_datasets.py +0 -0
  258. {ngio-0.4.0b1 → ngio-0.4.2}/tests/unit/utils/test_zarr_utils.py +0 -0
@@ -22,7 +22,7 @@ jobs:
22
22
  with:
23
23
  fetch-depth: 0
24
24
  - name: 🐍 Set up Python
25
- uses: actions/setup-python@v5
25
+ uses: actions/setup-python@v6
26
26
  with:
27
27
  python-version: "3.13"
28
28
  cache-dependency-path: "pyproject.toml"
@@ -40,7 +40,7 @@ jobs:
40
40
  - uses: actions/checkout@v5
41
41
 
42
42
  - name: 🐍 Set up Python ${{ matrix.python-version }}
43
- uses: actions/setup-python@v5
43
+ uses: actions/setup-python@v6
44
44
  with:
45
45
  python-version: ${{ matrix.python-version }}
46
46
  cache-dependency-path: "pyproject.toml"
@@ -103,7 +103,7 @@ jobs:
103
103
  fetch-depth: 0
104
104
 
105
105
  - name: 🐍 Set up Python
106
- uses: actions/setup-python@v5
106
+ uses: actions/setup-python@v6
107
107
  with:
108
108
  python-version: "3.x"
109
109
 
@@ -1,13 +1,33 @@
1
1
  # Changelog
2
2
 
3
- ## [v0.4.0a1]
3
+ ## [v0.4.2]
4
+
5
+ ### API Changes
6
+
7
+ - Make roi.to_slicing_dict(pixel_size) always require pixel_size argument for consistency with other roi methods.
8
+ - Make PixelSize object a Pydantic model to allow for serialization.
9
+
10
+ ### Bug Fixes
11
+
12
+ - Improve robustness when rounding Rois to pixel coordinates.
13
+
14
+ ## [v0.4.1]
15
+
16
+ ### Bug Fixes
17
+ - Fix bug in zoom transform when input axes contain unknown axes (e.g. virtual axes). Now unknown axes are treated as virtual axes and set to 1 in the target shape.
18
+
19
+ ## [v0.4.0]
4
20
 
5
21
  ### Features
6
22
 
7
- - add support for time in rois and roi-tables
23
+ - Add Iterators for image processing pipelines
24
+ - Add support for time in rois and roi-tables
8
25
  - Building masking roi tables expanded to time series data
9
- - add experimental support for Iterators
10
- - add support for rescaling on-the-fly masks for masked images
26
+ - Add zoom transformation
27
+ - Add support for rescaling on-the-fly masks for masked images
28
+ - Big refactor of the io pipeline to support iterators and lazy loading
29
+ - Add support for customize dimension separators and compression codecs
30
+ - Simplify AxesHandler and Dataset Classes
11
31
 
12
32
  ### API Changes
13
33
 
@@ -19,15 +39,12 @@
19
39
  - Image like objects now have a more clean API to load data. Instead of `get_array` and `set_array`, they now use `get_as_numpy`, and `get_as_dask` for delayed arrays.
20
40
  - Also for `get_roi` now specific methods are available. For ROI objects, the `get_roi_as_numpy`, and `get_roi_as_dask` methods.
21
41
  - Table ops moved to `ngio.images`
22
- - Make `label` an explicit attribute in `Roi` objects.
42
+ - int `label` as an explicit attribute in `Roi` objects (previously only in stored in name and relying on convention)
43
+ - Slight changes to `Image` and `Label` objects. Some minor attributes have been renamed for consistency.
23
44
 
24
45
  ### Table specs
25
46
 
26
- - add `t_second` and `len_t_second` to ROI tables and masking ROI tables
27
-
28
- ### Bug Fixes
29
-
30
- - improve type consistency and remove non-necessary "type: ignore"
47
+ - Add `t_second` and `len_t_second` to ROI tables and masking ROI tables
31
48
 
32
49
  ## [v0.3.5]
33
50
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ngio
3
- Version: 0.4.0b1
3
+ Version: 0.4.2
4
4
  Summary: Next Generation file format IO
5
5
  Project-URL: homepage, https://github.com/BioVisionCenter/ngio
6
6
  Project-URL: repository, https://github.com/BioVisionCenter/ngio
@@ -28,7 +28,6 @@ Requires-Dist: pooch
28
28
  Requires-Dist: pyarrow
29
29
  Requires-Dist: pydantic
30
30
  Requires-Dist: requests
31
- Requires-Dist: xarray
32
31
  Requires-Dist: zarr<3
33
32
  Provides-Extra: dev
34
33
  Requires-Dist: devtools; extra == 'dev'
@@ -83,20 +82,22 @@ Ngio's mission is to streamline working with OME-Zarr files by providing a simpl
83
82
 
84
83
  ## Key Features
85
84
 
86
- ### 📊 Simple Object-Based API
85
+ ### 🔍 Simple Object-Based API
87
86
 
88
87
  - Easily open, explore, and manipulate OME-Zarr images and HCS plates
89
88
  - Create and derive new images and labels with minimal boilerplate code
90
89
 
91
- ### 🔍 Rich Tables and Regions of Interest (ROI) Support
90
+ ### 📊 Rich Tables and Regions of Interest (ROI) Support
92
91
 
92
+ - Tight integration with [tabular data](https://biovisioncenter.github.io/ngio/stable/table_specs/overview/)
93
93
  - Extract and analyze specific regions of interest
94
- - Tight integration with [Tabular Data](https://BioVisionCenter.github.io/ngio/stable/table_specs/overview/)
94
+ - Store measurements and other metadata in the OME-Zarr container
95
+ - Extensible & modular allowing users to define custom table schemas and on disk serialization
95
96
 
96
- ### 🔄 Scalable Data Processing (Coming Soon)
97
+ ### 🔄 Scalable Data Processing
97
98
 
98
- - Powerful iterators for processing data at scale
99
- - Efficient memory management for large datasets
99
+ - Powerful iterators for building scalable and generalizable image processing pipelines
100
+ - Extensible mapping mechanism for custom parallelization strategies
100
101
 
101
102
  ## Installation
102
103
 
@@ -114,23 +115,22 @@ Currently, ngio only supports OME-Zarr v0.4. Support for version 0.5 and higher
114
115
 
115
116
  ## Development Status
116
117
 
117
- !!! warning
118
- Ngio is under active development and is not yet stable. The API is subject to change, and bugs and breaking changes are expected.
119
- We follow [Semantic Versioning](https://semver.org/). Which means for 0.x releases potentially breaking changes can be introduced in minor releases.
118
+ Ngio is under active development and is not yet stable. The API is subject to change, and bugs and breaking changes are expected.
119
+ We follow [Semantic Versioning](https://semver.org/). Which means for 0.x releases potentially breaking changes can be introduced in minor releases.
120
120
 
121
121
  ### Available Features
122
122
 
123
123
  - ✅ OME-Zarr metadata handling and validation
124
124
  - ✅ Image and label access across pyramid levels
125
125
  - ✅ ROI and table support
126
+ - ✅ Image processing iterators
126
127
  - ✅ Streaming from remote sources
127
128
  - ✅ Documentation and examples
128
129
 
129
130
  ### Upcoming Features
130
131
 
131
- - Advanced image processing iterators
132
- - Parallel processing capabilities
133
- - Support for OME-Zarr v0.5 and Zarr v3
132
+ - Support for OME-Zarr v0.5 and Zarr v3 (via `zarr-python` v3)
133
+ - Enhanced performance optimizations (parallel iterators, optimized io strategies)
134
134
 
135
135
  ## Contributors
136
136
 
@@ -16,20 +16,22 @@ Ngio's mission is to streamline working with OME-Zarr files by providing a simpl
16
16
 
17
17
  ## Key Features
18
18
 
19
- ### 📊 Simple Object-Based API
19
+ ### 🔍 Simple Object-Based API
20
20
 
21
21
  - Easily open, explore, and manipulate OME-Zarr images and HCS plates
22
22
  - Create and derive new images and labels with minimal boilerplate code
23
23
 
24
- ### 🔍 Rich Tables and Regions of Interest (ROI) Support
24
+ ### 📊 Rich Tables and Regions of Interest (ROI) Support
25
25
 
26
+ - Tight integration with [tabular data](https://biovisioncenter.github.io/ngio/stable/table_specs/overview/)
26
27
  - Extract and analyze specific regions of interest
27
- - Tight integration with [Tabular Data](https://BioVisionCenter.github.io/ngio/stable/table_specs/overview/)
28
+ - Store measurements and other metadata in the OME-Zarr container
29
+ - Extensible & modular allowing users to define custom table schemas and on disk serialization
28
30
 
29
- ### 🔄 Scalable Data Processing (Coming Soon)
31
+ ### 🔄 Scalable Data Processing
30
32
 
31
- - Powerful iterators for processing data at scale
32
- - Efficient memory management for large datasets
33
+ - Powerful iterators for building scalable and generalizable image processing pipelines
34
+ - Extensible mapping mechanism for custom parallelization strategies
33
35
 
34
36
  ## Installation
35
37
 
@@ -47,23 +49,22 @@ Currently, ngio only supports OME-Zarr v0.4. Support for version 0.5 and higher
47
49
 
48
50
  ## Development Status
49
51
 
50
- !!! warning
51
- Ngio is under active development and is not yet stable. The API is subject to change, and bugs and breaking changes are expected.
52
- We follow [Semantic Versioning](https://semver.org/). Which means for 0.x releases potentially breaking changes can be introduced in minor releases.
52
+ Ngio is under active development and is not yet stable. The API is subject to change, and bugs and breaking changes are expected.
53
+ We follow [Semantic Versioning](https://semver.org/). Which means for 0.x releases potentially breaking changes can be introduced in minor releases.
53
54
 
54
55
  ### Available Features
55
56
 
56
57
  - ✅ OME-Zarr metadata handling and validation
57
58
  - ✅ Image and label access across pyramid levels
58
59
  - ✅ ROI and table support
60
+ - ✅ Image processing iterators
59
61
  - ✅ Streaming from remote sources
60
62
  - ✅ Documentation and examples
61
63
 
62
64
  ### Upcoming Features
63
65
 
64
- - Advanced image processing iterators
65
- - Parallel processing capabilities
66
- - Support for OME-Zarr v0.5 and Zarr v3
66
+ - Support for OME-Zarr v0.5 and Zarr v3 (via `zarr-python` v3)
67
+ - Enhanced performance optimizations (parallel iterators, optimized io strategies)
67
68
 
68
69
  ## Contributors
69
70
 
@@ -8,15 +8,16 @@ Ngio's mission is to streamline working with OME-Zarr files by providing a simpl
8
8
 
9
9
  ## Key Features
10
10
 
11
- ### 📊 Simple Object-Based API
11
+ ### 🔍 Simple Object-Based API
12
12
 
13
13
  - Easily open, explore, and manipulate OME-Zarr images and HCS plates
14
14
  - Create and derive new images and labels with minimal boilerplate code
15
15
 
16
- ### 🔍 Rich Tables and Regions of Interest (ROI) Support
16
+ ### 📊 Rich Tables and Regions of Interest (ROI) Support
17
17
 
18
+ - Tight integration with [tabular data](https://biovisioncenter.github.io/ngio/stable/table_specs/overview/)
18
19
  - Extract and analyze specific regions of interest
19
- - Tight integration with [Fractal's table framework](https://BioVisionCenter.github.io/fractal-tasks-core/tables/)
20
+ - Store measurements and other metadata in the OME-Zarr container
20
21
  - Extensible & modular allowing users to define custom table schemas and on disk serialization
21
22
 
22
23
  ### 🔄 Scalable Data Processing
@@ -43,7 +43,7 @@ dependencies = [
43
43
  "aiohttp",
44
44
  "dask[array]",
45
45
  "dask[distributed]",
46
- "xarray",
46
+ # "xarray", still not used
47
47
  "ome-zarr-models",
48
48
  "pooch",
49
49
  "polars",
@@ -14,9 +14,22 @@ from ngio.ome_zarr_meta.ngio_specs import DefaultSpaceUnit, PixelSize, SpaceUnit
14
14
  from ngio.utils import NgioValueError
15
15
 
16
16
 
17
- def _to_raster(value: float, length: float, pixel_size: float) -> tuple[float, float]:
17
+ def _world_to_raster(value: float, pixel_size: float, eps: float = 1e-6) -> float:
18
18
  raster_value = value / pixel_size
19
- raster_length = length / pixel_size
19
+
20
+ # If the value is very close to an integer, round it
21
+ # This ensures that we don't have floating point precision issues
22
+ # When loading ROIs that were originally defined in pixel coordinates
23
+ _rounded = round(raster_value)
24
+ if abs(_rounded - raster_value) < eps:
25
+ return _rounded
26
+ return raster_value
27
+
28
+
29
+ def _to_raster(value: float, length: float, pixel_size: float) -> tuple[float, float]:
30
+ """Convert to raster coordinates."""
31
+ raster_value = _world_to_raster(value, pixel_size)
32
+ raster_length = _world_to_raster(length, pixel_size)
20
33
  return raster_value, raster_length
21
34
 
22
35
 
@@ -29,7 +42,7 @@ def _to_slice(start: float | None, length: float | None) -> slice:
29
42
  return slice(start, end)
30
43
 
31
44
 
32
- def _to_world(value: int | float, pixel_size: float) -> float:
45
+ def _raster_to_world(value: int | float, pixel_size: float) -> float:
33
46
  """Convert to world coordinates."""
34
47
  return value * pixel_size
35
48
 
@@ -60,16 +73,28 @@ class GenericRoi(BaseModel):
60
73
 
61
74
  def _nice_str(self) -> str:
62
75
  if self.t is not None:
63
- t_str = f"t={self.t}->{self.t_length}"
76
+ t_start = self.t
77
+ else:
78
+ t_start = None
79
+ if self.t_length is not None and t_start is not None:
80
+ t_end = t_start + self.t_length
64
81
  else:
65
- t_str = "t=None"
82
+ t_end = None
83
+
84
+ t_str = f"t={t_start}->{t_end}"
85
+
66
86
  if self.z is not None:
67
- z_str = f"z={self.z}->{self.z_length}"
87
+ z_start = self.z
88
+ else:
89
+ z_start = None
90
+ if self.z_length is not None and z_start is not None:
91
+ z_end = z_start + self.z_length
68
92
  else:
69
- z_str = "z=None"
93
+ z_end = None
94
+ z_str = f"z={z_start}->{z_end}"
70
95
 
71
- y_str = f"y={self.y}->{self.y_length}"
72
- x_str = f"x={self.x}->{self.x_length}"
96
+ y_str = f"y={self.y}->{self.y + self.y_length}"
97
+ x_str = f"x={self.x}->{self.x + self.x_length}"
73
98
 
74
99
  if self.label is not None:
75
100
  label_str = f", label={self.label}"
@@ -90,6 +115,9 @@ class GenericRoi(BaseModel):
90
115
  def __str__(self) -> str:
91
116
  return self._nice_str()
92
117
 
118
+ def to_slicing_dict(self, pixel_size: PixelSize) -> dict[str, slice]:
119
+ raise NotImplementedError
120
+
93
121
 
94
122
  def _1d_intersection(
95
123
  a: T | None, a_length: T | None, b: T | None, b_length: T | None
@@ -251,6 +279,11 @@ class Roi(GenericRoi):
251
279
  """
252
280
  return zoom_roi(self, zoom_factor)
253
281
 
282
+ def to_slicing_dict(self, pixel_size: PixelSize) -> dict[str, slice]:
283
+ """Convert to a slicing dictionary."""
284
+ roi_pixels = self.to_roi_pixels(pixel_size)
285
+ return roi_pixels.to_slicing_dict(pixel_size)
286
+
254
287
 
255
288
  class RoiPixels(GenericRoi):
256
289
  """Region of interest (ROI) in pixel coordinates."""
@@ -261,30 +294,30 @@ class RoiPixels(GenericRoi):
261
294
 
262
295
  def to_roi(self, pixel_size: PixelSize) -> "Roi":
263
296
  """Convert to raster coordinates."""
264
- x = _to_world(self.x, pixel_size.x)
265
- x_length = _to_world(self.x_length, pixel_size.x)
266
- y = _to_world(self.y, pixel_size.y)
267
- y_length = _to_world(self.y_length, pixel_size.y)
297
+ x = _raster_to_world(self.x, pixel_size.x)
298
+ x_length = _raster_to_world(self.x_length, pixel_size.x)
299
+ y = _raster_to_world(self.y, pixel_size.y)
300
+ y_length = _raster_to_world(self.y_length, pixel_size.y)
268
301
 
269
302
  if self.z is None:
270
303
  z = None
271
304
  else:
272
- z = _to_world(self.z, pixel_size.z)
305
+ z = _raster_to_world(self.z, pixel_size.z)
273
306
 
274
307
  if self.z_length is None:
275
308
  z_length = None
276
309
  else:
277
- z_length = _to_world(self.z_length, pixel_size.z)
310
+ z_length = _raster_to_world(self.z_length, pixel_size.z)
278
311
 
279
312
  if self.t is None:
280
313
  t = None
281
314
  else:
282
- t = _to_world(self.t, pixel_size.t)
315
+ t = _raster_to_world(self.t, pixel_size.t)
283
316
 
284
317
  if self.t_length is None:
285
318
  t_length = None
286
319
  else:
287
- t_length = _to_world(self.t_length, pixel_size.t)
320
+ t_length = _raster_to_world(self.t_length, pixel_size.t)
288
321
 
289
322
  extra_dict = self.model_extra if self.model_extra else {}
290
323
  return Roi(
@@ -302,7 +335,7 @@ class RoiPixels(GenericRoi):
302
335
  **extra_dict,
303
336
  )
304
337
 
305
- def to_slicing_dict(self) -> dict[str, slice]:
338
+ def to_slicing_dict(self, pixel_size: PixelSize) -> dict[str, slice]:
306
339
  """Convert to a slicing dictionary."""
307
340
  x_slice = _to_slice(self.x, self.x_length)
308
341
  y_slice = _to_slice(self.y, self.y_length)
@@ -13,24 +13,18 @@ from ngio.io_pipes._io_pipes import (
13
13
  from ngio.io_pipes._ops_slices import SlicingInputType
14
14
  from ngio.io_pipes._ops_transforms import TransformProtocol
15
15
  from ngio.ome_zarr_meta.ngio_specs._pixel_size import PixelSize
16
- from ngio.utils import NgioValueError
17
16
 
18
17
 
19
18
  def roi_to_slicing_dict(
20
19
  *,
21
20
  roi: Roi | RoiPixels,
22
- pixel_size: PixelSize | None = None,
21
+ pixel_size: PixelSize,
23
22
  slicing_dict: dict[str, SlicingInputType] | None = None,
24
23
  ) -> dict[str, SlicingInputType]:
25
24
  """Convert a ROI to a slicing dictionary."""
26
- if isinstance(roi, Roi):
27
- if pixel_size is None:
28
- raise NgioValueError(
29
- "pixel_size must be provided when converting a Roi to slice_kwargs."
30
- )
31
- roi = roi.to_roi_pixels(pixel_size=pixel_size)
32
-
33
- roi_slicing_dict: dict[str, SlicingInputType] = roi.to_slicing_dict() # type: ignore
25
+ roi_slicing_dict: dict[str, SlicingInputType] = roi.to_slicing_dict(
26
+ pixel_size=pixel_size
27
+ ) # type: ignore
34
28
  if slicing_dict is None:
35
29
  return roi_slicing_dict
36
30
 
@@ -14,7 +14,7 @@ from ngio.ome_zarr_meta.ngio_specs import Axis
14
14
  from ngio.utils import NgioValueError
15
15
 
16
16
  SlicingInputType: TypeAlias = slice | Sequence[int] | int | None
17
- SlicingType: TypeAlias = slice | tuple[int, ...] | int
17
+ SlicingType: TypeAlias = slice | list[int] | int
18
18
 
19
19
  ##############################################################
20
20
  #
@@ -60,7 +60,7 @@ def _slicing_tuple_boundary_check(
60
60
  elif isinstance(sl, int):
61
61
  _int_boundary_check(sl, shape=sh)
62
62
  out_slicing_tuple.append(sl)
63
- elif isinstance(sl, tuple):
63
+ elif isinstance(sl, list):
64
64
  [_int_boundary_check(i, shape=sh) for i in sl]
65
65
  out_slicing_tuple.append(sl)
66
66
  else:
@@ -115,32 +115,31 @@ class SlicingOps(BaseModel):
115
115
  return slicing_tuple[ax_index]
116
116
 
117
117
 
118
- def _check_tuple_in_slicing_tuple(
118
+ def _check_list_in_slicing_tuple(
119
119
  slicing_tuple: tuple[SlicingType, ...],
120
- ) -> tuple[None, None] | tuple[int, tuple[int, ...]]:
121
- """Check if there are any tuple in the slicing tuple.
120
+ ) -> tuple[None, None] | tuple[int, list[int]]:
121
+ """Check if there are any lists in the slicing tuple.
122
122
 
123
- The zarr python api only supports int or slices, not tuples.
124
- Ngio support a single tuple in the slicing tuple to allow non-contiguous
123
+ Dask regions when setting data do not support non-contiguous
124
+ selections natively.
125
+ Ngio support a single list in the slicing tuple to allow non-contiguous
125
126
  selection (main use case: selecting multiple channels).
126
127
  """
127
- # Find if the is any tuple in the slicing tuple
128
+ # Find if the is any list in the slicing tuple
128
129
  # If there is one we need to handle it differently
129
- tuple_in_slice = [
130
- (i, s) for i, s in enumerate(slicing_tuple) if isinstance(s, tuple)
131
- ]
132
- if not tuple_in_slice:
133
- # No tuple in the slicing tuple
130
+ list_in_slice = [(i, s) for i, s in enumerate(slicing_tuple) if isinstance(s, list)]
131
+ if not list_in_slice:
132
+ # No list in the slicing tuple
134
133
  return None, None
135
134
 
136
- if len(tuple_in_slice) > 1:
135
+ if len(list_in_slice) > 1:
137
136
  raise NotImplementedError(
138
137
  "Slicing with multiple non-contiguous tuples/lists "
139
138
  "is not supported yet in Ngio. Use directly the "
140
139
  "zarr.Array api to get the correct array slice."
141
140
  )
142
141
  # Complex case, we have exactly one tuple in the slicing tuple
143
- ax, first_tuple = tuple_in_slice[0]
142
+ ax, first_tuple = list_in_slice[0]
144
143
  if len(first_tuple) > 100:
145
144
  warn(
146
145
  "Performance warning: "
@@ -164,38 +163,14 @@ def get_slice_as_numpy(zarr_array: zarr.Array, slicing_ops: SlicingOps) -> np.nd
164
163
  slicing_tuple = slicing_ops.normalized_slicing_tuple
165
164
  # Find if the is any tuple in the slicing tuple
166
165
  # If there is one we need to handle it differently
167
- ax, first_tuple = _check_tuple_in_slicing_tuple(slicing_tuple)
168
- if ax is None:
169
- # Simple case, no tuple in the slicing tuple
170
- return zarr_array[slicing_tuple]
171
-
172
- assert first_tuple is not None
173
- slices = [
174
- zarr_array[(*slicing_tuple[:ax], idx, *slicing_tuple[ax + 1 :])]
175
- for idx in first_tuple
176
- ]
177
- out_array = np.stack(slices, axis=ax)
178
- return out_array
166
+ return zarr_array[slicing_tuple]
179
167
 
180
168
 
181
169
  def get_slice_as_dask(zarr_array: zarr.Array, slicing_ops: SlicingOps) -> da.Array:
182
170
  """Get a slice of a zarr array as a dask array."""
183
171
  da_array = da.from_zarr(zarr_array)
184
172
  slicing_tuple = slicing_ops.normalized_slicing_tuple
185
- # Find if the is any tuple in the slicing tuple
186
- # If there is one we need to handle it differently
187
- ax, first_tuple = _check_tuple_in_slicing_tuple(slicing_tuple)
188
- if ax is None:
189
- # Base case, no tuple in the slicing tuple
190
- return da_array[slicing_tuple]
191
-
192
- assert first_tuple is not None
193
- slices = [
194
- da_array[(*slicing_tuple[:ax], idx, *slicing_tuple[ax + 1 :])]
195
- for idx in first_tuple
196
- ]
197
- out_array = da.stack(slices, axis=ax)
198
- return out_array
173
+ return da_array[slicing_tuple]
199
174
 
200
175
 
201
176
  def set_slice_as_numpy(
@@ -204,17 +179,7 @@ def set_slice_as_numpy(
204
179
  slicing_ops: SlicingOps,
205
180
  ) -> None:
206
181
  slice_tuple = slicing_ops.normalized_slicing_tuple
207
- ax, first_tuple = _check_tuple_in_slicing_tuple(slice_tuple)
208
- if ax is None:
209
- # Base case, no tuple in the slicing tuple
210
- zarr_array[slice_tuple] = patch
211
- return
212
-
213
- # Complex case, we have exactly one tuple in the slicing tuple
214
- assert first_tuple is not None
215
- for i, idx in enumerate(first_tuple):
216
- _sub_slice = (*slice_tuple[:ax], idx, *slice_tuple[ax + 1 :])
217
- zarr_array[_sub_slice] = np.take(patch, indices=i, axis=ax)
182
+ zarr_array[slice_tuple] = patch
218
183
 
219
184
 
220
185
  def handle_int_set_as_dask(
@@ -237,7 +202,7 @@ def set_slice_as_dask(
237
202
  zarr_array: zarr.Array, patch: da.Array, slicing_ops: SlicingOps
238
203
  ) -> None:
239
204
  slice_tuple = slicing_ops.normalized_slicing_tuple
240
- ax, first_tuple = _check_tuple_in_slicing_tuple(slice_tuple)
205
+ ax, first_tuple = _check_list_in_slicing_tuple(slice_tuple)
241
206
  patch, slice_tuple = handle_int_set_as_dask(patch, slice_tuple)
242
207
  if ax is None:
243
208
  # Base case, no tuple in the slicing tuple
@@ -261,13 +226,13 @@ def set_slice_as_dask(
261
226
  ##############################################################
262
227
 
263
228
 
264
- def _try_to_slice(value: Sequence[int]) -> slice | tuple[int, ...]:
229
+ def _try_to_slice(value: Sequence[int]) -> slice | list[int]:
265
230
  """Try to convert a list of integers into a slice if they are contiguous.
266
231
 
267
232
  - If the input is empty, return an empty tuple.
268
233
  - If the input is sorted, and contains contiguous integers,
269
234
  return a slice from the minimum to the maximum integer.
270
- - Otherwise, return the input as a tuple.
235
+ - Otherwise, return the input as a list of integers.
271
236
 
272
237
  This is useful for optimizing array slicing operations
273
238
  by allowing the use of slices when possible, which can be more efficient.
@@ -293,7 +258,7 @@ def _try_to_slice(value: Sequence[int]) -> slice | tuple[int, ...]:
293
258
  if sorted(value) == list(range(min_input, max_input + 1)):
294
259
  return slice(min_input, max_input + 1)
295
260
 
296
- return tuple(value)
261
+ return list(value)
297
262
 
298
263
 
299
264
  def _remove_channel_slicing(
@@ -393,7 +358,7 @@ def _normalize_slicing_tuple(
393
358
  The output types are:
394
359
  - slice
395
360
  - int
396
- - tuple of int (for non-contiguous selection)
361
+ - list of int (for non-contiguous selection)
397
362
  """
398
363
  axis_name = axis.name
399
364
  if axis_name not in slicing_dict:
@@ -408,7 +373,7 @@ def _normalize_slicing_tuple(
408
373
  elif isinstance(value, Sequence):
409
374
  # If a contiguous sequence of integers is provided,
410
375
  # convert it to a slice for simplicity.
411
- # Alternatively, it will be converted to a tuple of ints
376
+ # Alternatively, it will be converted to a list of ints
412
377
  return _try_to_slice(value)
413
378
 
414
379
  raise NgioValueError(
@@ -22,7 +22,7 @@ def _pairs_stream(iterable: Iterable[T]) -> Iterator[tuple[T, T]]:
22
22
  seen.append(a)
23
23
 
24
24
 
25
- SlicingType: TypeAlias = slice | tuple[int, ...] | int
25
+ SlicingType: TypeAlias = slice | list[int] | int
26
26
 
27
27
 
28
28
  def check_elem_intersection(s1: SlicingType, s2: SlicingType) -> bool:
@@ -30,7 +30,7 @@ def check_elem_intersection(s1: SlicingType, s2: SlicingType) -> bool:
30
30
 
31
31
  If they are a slice, check if they overlap.
32
32
  If they are integers, check if they are equal.
33
- If they are tuples, check if they have any common elements.
33
+ If they are lists, check if they have any common elements.
34
34
  """
35
35
  if not isinstance(s1, type(s2)):
36
36
  raise NgioValueError(
@@ -56,7 +56,7 @@ def check_elem_intersection(s1: SlicingType, s2: SlicingType) -> bool:
56
56
  elif isinstance(s1, int) and isinstance(s2, int):
57
57
  # Handle integer indices
58
58
  return s1 == s2
59
- elif isinstance(s1, tuple) and isinstance(s2, tuple):
59
+ elif isinstance(s1, list) and isinstance(s2, list):
60
60
  if set(s1) & set(s2):
61
61
  return True
62
62
  return False
@@ -130,7 +130,7 @@ def _chunk_indices_for_axis(sel: SlicingType, size: int, csize: int) -> list[int
130
130
  raise IndexError(f"index {sel} out of bounds for axis of size {size}")
131
131
  return [sel // csize]
132
132
 
133
- if isinstance(sel, tuple):
133
+ if isinstance(sel, list):
134
134
  if not sel:
135
135
  return []
136
136
  chunks_hit = {}
@@ -60,7 +60,12 @@ class BaseZoomTransform:
60
60
  target_shape = []
61
61
  for shape, ax_name in zip(array_shape, axes_ops.output_axes, strict=True):
62
62
  ax_type = self._input_dimensions.axes_handler.get_axis(ax_name)
63
- if ax_type is not None and ax_type.axis_type == "channel":
63
+ if ax_type is None:
64
+ # Unknown axis can only be a virtual axis
65
+ # So we set it to 1
66
+ target_shape.append(1)
67
+ continue
68
+ elif ax_type.axis_type == "channel":
64
69
  # Do not scale channel axis
65
70
  target_shape.append(shape)
66
71
  continue