ngio 0.4.1__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.1 → ngio-0.4.2}/CHANGELOG.md +11 -0
  2. {ngio-0.4.1 → ngio-0.4.2}/PKG-INFO +1 -1
  3. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/common/_roi.py +51 -18
  4. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/io_pipes/_io_pipes_roi.py +4 -10
  5. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/io_pipes/_ops_slices.py +23 -58
  6. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/io_pipes/_ops_slices_utils.py +4 -4
  7. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/ome_zarr_meta/ngio_specs/_pixel_size.py +12 -39
  8. {ngio-0.4.1 → ngio-0.4.2}/tests/unit/common/test_roi.py +2 -2
  9. {ngio-0.4.1 → ngio-0.4.2}/.copier-answers.yml +0 -0
  10. {ngio-0.4.1 → ngio-0.4.2}/.gitattributes +0 -0
  11. {ngio-0.4.1 → ngio-0.4.2}/.github/ISSUE_TEMPLATE.md +0 -0
  12. {ngio-0.4.1 → ngio-0.4.2}/.github/TEST_FAIL_TEMPLATE.md +0 -0
  13. {ngio-0.4.1 → ngio-0.4.2}/.github/dependabot.yml +0 -0
  14. {ngio-0.4.1 → ngio-0.4.2}/.github/pull_request_template.md +0 -0
  15. {ngio-0.4.1 → ngio-0.4.2}/.github/workflows/build_docs.yml +0 -0
  16. {ngio-0.4.1 → ngio-0.4.2}/.github/workflows/ci.yml +0 -0
  17. {ngio-0.4.1 → ngio-0.4.2}/.gitignore +0 -0
  18. {ngio-0.4.1 → ngio-0.4.2}/.pre-commit-config.yaml +0 -0
  19. {ngio-0.4.1 → ngio-0.4.2}/LICENSE +0 -0
  20. {ngio-0.4.1 → ngio-0.4.2}/README.md +0 -0
  21. {ngio-0.4.1 → ngio-0.4.2}/_typos.toml +0 -0
  22. {ngio-0.4.1 → ngio-0.4.2}/docs/api/hcs.md +0 -0
  23. {ngio-0.4.1 → ngio-0.4.2}/docs/api/images.md +0 -0
  24. {ngio-0.4.1 → ngio-0.4.2}/docs/api/iterators.md +0 -0
  25. {ngio-0.4.1 → ngio-0.4.2}/docs/api/ngio/common.md +0 -0
  26. {ngio-0.4.1 → ngio-0.4.2}/docs/api/ngio/hcs.md +0 -0
  27. {ngio-0.4.1 → ngio-0.4.2}/docs/api/ngio/images.md +0 -0
  28. {ngio-0.4.1 → ngio-0.4.2}/docs/api/ngio/io_pipes.md +0 -0
  29. {ngio-0.4.1 → ngio-0.4.2}/docs/api/ngio/iterators.md +0 -0
  30. {ngio-0.4.1 → ngio-0.4.2}/docs/api/ngio/ngio.md +0 -0
  31. {ngio-0.4.1 → ngio-0.4.2}/docs/api/ngio/tables.md +0 -0
  32. {ngio-0.4.1 → ngio-0.4.2}/docs/api/ngio/transforms.md +0 -0
  33. {ngio-0.4.1 → ngio-0.4.2}/docs/api/ngio/utils.md +0 -0
  34. {ngio-0.4.1 → ngio-0.4.2}/docs/api/ome_zarr_container.md +0 -0
  35. {ngio-0.4.1 → ngio-0.4.2}/docs/api/tables.md +0 -0
  36. {ngio-0.4.1 → ngio-0.4.2}/docs/changelog.md +0 -0
  37. {ngio-0.4.1 → ngio-0.4.2}/docs/code_of_conduct.md +0 -0
  38. {ngio-0.4.1 → ngio-0.4.2}/docs/contributing.md +0 -0
  39. {ngio-0.4.1 → ngio-0.4.2}/docs/getting_started/0_quickstart.md +0 -0
  40. {ngio-0.4.1 → ngio-0.4.2}/docs/getting_started/1_ome_zarr_containers.md +0 -0
  41. {ngio-0.4.1 → ngio-0.4.2}/docs/getting_started/2_images.md +0 -0
  42. {ngio-0.4.1 → ngio-0.4.2}/docs/getting_started/3_tables.md +0 -0
  43. {ngio-0.4.1 → ngio-0.4.2}/docs/getting_started/4_masked_images.md +0 -0
  44. {ngio-0.4.1 → ngio-0.4.2}/docs/getting_started/5_hcs.md +0 -0
  45. {ngio-0.4.1 → ngio-0.4.2}/docs/getting_started/6_iterators.md +0 -0
  46. {ngio-0.4.1 → ngio-0.4.2}/docs/index.md +0 -0
  47. {ngio-0.4.1 → ngio-0.4.2}/docs/table_specs/backend.md +0 -0
  48. {ngio-0.4.1 → ngio-0.4.2}/docs/table_specs/overview.md +0 -0
  49. {ngio-0.4.1 → ngio-0.4.2}/docs/table_specs/table_types/condition_table.md +0 -0
  50. {ngio-0.4.1 → ngio-0.4.2}/docs/table_specs/table_types/custom_table.md +0 -0
  51. {ngio-0.4.1 → ngio-0.4.2}/docs/table_specs/table_types/feature_table.md +0 -0
  52. {ngio-0.4.1 → ngio-0.4.2}/docs/table_specs/table_types/generic_table.md +0 -0
  53. {ngio-0.4.1 → ngio-0.4.2}/docs/table_specs/table_types/masking_roi_table.md +0 -0
  54. {ngio-0.4.1 → ngio-0.4.2}/docs/table_specs/table_types/roi_table.md +0 -0
  55. {ngio-0.4.1 → ngio-0.4.2}/docs/tutorials/create_ome_zarr.ipynb +0 -0
  56. {ngio-0.4.1 → ngio-0.4.2}/docs/tutorials/feature_extraction.ipynb +0 -0
  57. {ngio-0.4.1 → ngio-0.4.2}/docs/tutorials/hcs_exploration.ipynb +0 -0
  58. {ngio-0.4.1 → ngio-0.4.2}/docs/tutorials/image_processing.ipynb +0 -0
  59. {ngio-0.4.1 → ngio-0.4.2}/docs/tutorials/image_segmentation.ipynb +0 -0
  60. {ngio-0.4.1 → ngio-0.4.2}/mkdocs.yml +0 -0
  61. {ngio-0.4.1 → ngio-0.4.2}/pyproject.toml +0 -0
  62. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/__init__.py +0 -0
  63. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/common/__init__.py +0 -0
  64. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/common/_dimensions.py +0 -0
  65. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/common/_masking_roi.py +0 -0
  66. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/common/_pyramid.py +0 -0
  67. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/common/_synt_images_utils.py +0 -0
  68. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/common/_zoom.py +0 -0
  69. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/experimental/__init__.py +0 -0
  70. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/experimental/iterators/__init__.py +0 -0
  71. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/experimental/iterators/_abstract_iterator.py +0 -0
  72. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/experimental/iterators/_feature.py +0 -0
  73. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/experimental/iterators/_image_processing.py +0 -0
  74. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/experimental/iterators/_mappers.py +0 -0
  75. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/experimental/iterators/_rois_utils.py +0 -0
  76. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/experimental/iterators/_segmentation.py +0 -0
  77. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/hcs/__init__.py +0 -0
  78. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/hcs/_plate.py +0 -0
  79. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/images/__init__.py +0 -0
  80. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/images/_abstract_image.py +0 -0
  81. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/images/_create.py +0 -0
  82. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/images/_create_synt_container.py +0 -0
  83. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/images/_image.py +0 -0
  84. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/images/_label.py +0 -0
  85. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/images/_masked_image.py +0 -0
  86. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/images/_ome_zarr_container.py +0 -0
  87. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/images/_table_ops.py +0 -0
  88. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/io_pipes/__init__.py +0 -0
  89. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/io_pipes/_io_pipes.py +0 -0
  90. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/io_pipes/_io_pipes_masked.py +0 -0
  91. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/io_pipes/_io_pipes_types.py +0 -0
  92. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/io_pipes/_match_shape.py +0 -0
  93. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/io_pipes/_ops_axes.py +0 -0
  94. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/io_pipes/_ops_transforms.py +0 -0
  95. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/io_pipes/_zoom_transform.py +0 -0
  96. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/ome_zarr_meta/__init__.py +0 -0
  97. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/ome_zarr_meta/_meta_handlers.py +0 -0
  98. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/ome_zarr_meta/ngio_specs/__init__.py +0 -0
  99. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/ome_zarr_meta/ngio_specs/_axes.py +0 -0
  100. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/ome_zarr_meta/ngio_specs/_channels.py +0 -0
  101. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/ome_zarr_meta/ngio_specs/_dataset.py +0 -0
  102. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/ome_zarr_meta/ngio_specs/_ngio_hcs.py +0 -0
  103. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/ome_zarr_meta/ngio_specs/_ngio_image.py +0 -0
  104. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/ome_zarr_meta/v04/__init__.py +0 -0
  105. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/ome_zarr_meta/v04/_custom_models.py +0 -0
  106. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/ome_zarr_meta/v04/_v04_spec_utils.py +0 -0
  107. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/resources/20200812-CardiomyocyteDifferentiation14-Cycle1_B03/mask.png +0 -0
  108. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/resources/20200812-CardiomyocyteDifferentiation14-Cycle1_B03/nuclei.png +0 -0
  109. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/resources/20200812-CardiomyocyteDifferentiation14-Cycle1_B03/raw.jpg +0 -0
  110. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/resources/__init__.py +0 -0
  111. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/resources/resource_model.py +0 -0
  112. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/tables/__init__.py +0 -0
  113. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/tables/_abstract_table.py +0 -0
  114. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/tables/_tables_container.py +0 -0
  115. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/tables/backends/__init__.py +0 -0
  116. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/tables/backends/_abstract_backend.py +0 -0
  117. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/tables/backends/_anndata.py +0 -0
  118. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/tables/backends/_anndata_utils.py +0 -0
  119. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/tables/backends/_csv.py +0 -0
  120. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/tables/backends/_json.py +0 -0
  121. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/tables/backends/_non_zarr_backends.py +0 -0
  122. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/tables/backends/_parquet.py +0 -0
  123. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/tables/backends/_table_backends.py +0 -0
  124. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/tables/backends/_utils.py +0 -0
  125. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/tables/v1/__init__.py +0 -0
  126. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/tables/v1/_condition_table.py +0 -0
  127. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/tables/v1/_feature_table.py +0 -0
  128. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/tables/v1/_generic_table.py +0 -0
  129. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/tables/v1/_roi_table.py +0 -0
  130. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/transforms/__init__.py +0 -0
  131. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/transforms/_zoom.py +0 -0
  132. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/utils/__init__.py +0 -0
  133. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/utils/_datasets.py +0 -0
  134. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/utils/_errors.py +0 -0
  135. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/utils/_fractal_fsspec_store.py +0 -0
  136. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/utils/_logger.py +0 -0
  137. {ngio-0.4.1 → ngio-0.4.2}/src/ngio/utils/_zarr_utils.py +0 -0
  138. {ngio-0.4.1 → ngio-0.4.2}/tests/conftest.py +0 -0
  139. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_c1yx.zarr/.zattrs +0 -0
  140. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_c1yx.zarr/.zgroup +0 -0
  141. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_c1yx.zarr/0/.zarray +0 -0
  142. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_c1yx.zarr/1/.zarray +0 -0
  143. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_c1yx.zarr/labels/.zattrs +0 -0
  144. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_c1yx.zarr/labels/.zgroup +0 -0
  145. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_c1yx.zarr/labels/label/.zattrs +0 -0
  146. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_c1yx.zarr/labels/label/.zgroup +0 -0
  147. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_c1yx.zarr/labels/label/0/.zarray +0 -0
  148. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_c1yx.zarr/labels/label/1/.zarray +0 -0
  149. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_cyx.zarr/.zattrs +0 -0
  150. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_cyx.zarr/.zgroup +0 -0
  151. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_cyx.zarr/0/.zarray +0 -0
  152. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_cyx.zarr/1/.zarray +0 -0
  153. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_cyx.zarr/labels/.zattrs +0 -0
  154. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_cyx.zarr/labels/.zgroup +0 -0
  155. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_cyx.zarr/labels/label/.zattrs +0 -0
  156. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_cyx.zarr/labels/label/.zgroup +0 -0
  157. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_cyx.zarr/labels/label/0/.zarray +0 -0
  158. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_cyx.zarr/labels/label/1/.zarray +0 -0
  159. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_czyx.zarr/.zattrs +0 -0
  160. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_czyx.zarr/.zgroup +0 -0
  161. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_czyx.zarr/0/.zarray +0 -0
  162. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_czyx.zarr/1/.zarray +0 -0
  163. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_czyx.zarr/labels/.zattrs +0 -0
  164. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_czyx.zarr/labels/.zgroup +0 -0
  165. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_czyx.zarr/labels/label/.zattrs +0 -0
  166. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_czyx.zarr/labels/label/.zgroup +0 -0
  167. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_czyx.zarr/labels/label/0/.zarray +0 -0
  168. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_czyx.zarr/labels/label/1/.zarray +0 -0
  169. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tcyx.zarr/.zattrs +0 -0
  170. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tcyx.zarr/.zgroup +0 -0
  171. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tcyx.zarr/0/.zarray +0 -0
  172. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tcyx.zarr/1/.zarray +0 -0
  173. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tcyx.zarr/labels/.zattrs +0 -0
  174. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tcyx.zarr/labels/.zgroup +0 -0
  175. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tcyx.zarr/labels/label/.zattrs +0 -0
  176. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tcyx.zarr/labels/label/.zgroup +0 -0
  177. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tcyx.zarr/labels/label/0/.zarray +0 -0
  178. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tcyx.zarr/labels/label/1/.zarray +0 -0
  179. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tczyx.zarr/.zattrs +0 -0
  180. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tczyx.zarr/.zgroup +0 -0
  181. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tczyx.zarr/0/.zarray +0 -0
  182. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tczyx.zarr/1/.zarray +0 -0
  183. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tczyx.zarr/labels/.zattrs +0 -0
  184. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tczyx.zarr/labels/.zgroup +0 -0
  185. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tczyx.zarr/labels/label/.zattrs +0 -0
  186. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tczyx.zarr/labels/label/.zgroup +0 -0
  187. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tczyx.zarr/labels/label/0/.zarray +0 -0
  188. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tczyx.zarr/labels/label/1/.zarray +0 -0
  189. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tyx.zarr/.zattrs +0 -0
  190. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tyx.zarr/.zgroup +0 -0
  191. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tyx.zarr/0/.zarray +0 -0
  192. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tyx.zarr/1/.zarray +0 -0
  193. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tyx.zarr/labels/.zattrs +0 -0
  194. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tyx.zarr/labels/.zgroup +0 -0
  195. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tyx.zarr/labels/label/.zattrs +0 -0
  196. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tyx.zarr/labels/label/.zgroup +0 -0
  197. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tyx.zarr/labels/label/0/.zarray +0 -0
  198. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tyx.zarr/labels/label/1/.zarray +0 -0
  199. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tzyx.zarr/.zattrs +0 -0
  200. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tzyx.zarr/.zgroup +0 -0
  201. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tzyx.zarr/0/.zarray +0 -0
  202. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tzyx.zarr/1/.zarray +0 -0
  203. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tzyx.zarr/labels/.zattrs +0 -0
  204. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tzyx.zarr/labels/.zgroup +0 -0
  205. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tzyx.zarr/labels/label/.zattrs +0 -0
  206. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tzyx.zarr/labels/label/.zgroup +0 -0
  207. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tzyx.zarr/labels/label/0/.zarray +0 -0
  208. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_tzyx.zarr/labels/label/1/.zarray +0 -0
  209. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_yx.zarr/.zattrs +0 -0
  210. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_yx.zarr/.zgroup +0 -0
  211. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_yx.zarr/0/.zarray +0 -0
  212. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_yx.zarr/1/.zarray +0 -0
  213. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_yx.zarr/labels/.zattrs +0 -0
  214. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_yx.zarr/labels/.zgroup +0 -0
  215. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_yx.zarr/labels/label/.zattrs +0 -0
  216. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_yx.zarr/labels/label/.zgroup +0 -0
  217. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_yx.zarr/labels/label/0/.zarray +0 -0
  218. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_yx.zarr/labels/label/1/.zarray +0 -0
  219. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_zyx.zarr/.zattrs +0 -0
  220. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_zyx.zarr/.zgroup +0 -0
  221. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_zyx.zarr/0/.zarray +0 -0
  222. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_zyx.zarr/1/.zarray +0 -0
  223. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_zyx.zarr/labels/.zattrs +0 -0
  224. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_zyx.zarr/labels/.zgroup +0 -0
  225. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_zyx.zarr/labels/label/.zattrs +0 -0
  226. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_zyx.zarr/labels/label/.zgroup +0 -0
  227. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_zyx.zarr/labels/label/0/.zarray +0 -0
  228. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/images/test_image_zyx.zarr/labels/label/1/.zarray +0 -0
  229. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/meta/base_ome_zarr_image_meta.json +0 -0
  230. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/meta/base_ome_zarr_image_meta_wrong_axis_order.json +0 -0
  231. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/meta/base_ome_zarr_label_meta.json +0 -0
  232. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/meta/base_ome_zarr_well_meta.json +0 -0
  233. {ngio-0.4.1 → ngio-0.4.2}/tests/data/v04/meta/ome_zarr_well_path_normalization_meta.json +0 -0
  234. {ngio-0.4.1 → ngio-0.4.2}/tests/unit/common/test_dimensions.py +0 -0
  235. {ngio-0.4.1 → ngio-0.4.2}/tests/unit/common/test_pyramid.py +0 -0
  236. {ngio-0.4.1 → ngio-0.4.2}/tests/unit/common/test_transforms.py +0 -0
  237. {ngio-0.4.1 → ngio-0.4.2}/tests/unit/hcs/test_plate.py +0 -0
  238. {ngio-0.4.1 → ngio-0.4.2}/tests/unit/hcs/test_well.py +0 -0
  239. {ngio-0.4.1 → ngio-0.4.2}/tests/unit/images/test_create.py +0 -0
  240. {ngio-0.4.1 → ngio-0.4.2}/tests/unit/images/test_images.py +0 -0
  241. {ngio-0.4.1 → ngio-0.4.2}/tests/unit/images/test_masked_images.py +0 -0
  242. {ngio-0.4.1 → ngio-0.4.2}/tests/unit/images/test_omezarr_container.py +0 -0
  243. {ngio-0.4.1 → ngio-0.4.2}/tests/unit/images/test_table_ops.py +0 -0
  244. {ngio-0.4.1 → ngio-0.4.2}/tests/unit/io_pipes/test_axes_ops.py +0 -0
  245. {ngio-0.4.1 → ngio-0.4.2}/tests/unit/io_pipes/test_slicing_ops.py +0 -0
  246. {ngio-0.4.1 → ngio-0.4.2}/tests/unit/iterators/test_iterators.py +0 -0
  247. {ngio-0.4.1 → ngio-0.4.2}/tests/unit/ome_zarr_meta/test_image_handler.py +0 -0
  248. {ngio-0.4.1 → ngio-0.4.2}/tests/unit/ome_zarr_meta/test_unit_ngio_specs.py +0 -0
  249. {ngio-0.4.1 → ngio-0.4.2}/tests/unit/ome_zarr_meta/test_unit_v04_utils.py +0 -0
  250. {ngio-0.4.1 → ngio-0.4.2}/tests/unit/tables/test_backends.py +0 -0
  251. {ngio-0.4.1 → ngio-0.4.2}/tests/unit/tables/test_backends_utils.py +0 -0
  252. {ngio-0.4.1 → ngio-0.4.2}/tests/unit/tables/test_feature_table.py +0 -0
  253. {ngio-0.4.1 → ngio-0.4.2}/tests/unit/tables/test_generic_table.py +0 -0
  254. {ngio-0.4.1 → ngio-0.4.2}/tests/unit/tables/test_masking_roi_table_v1.py +0 -0
  255. {ngio-0.4.1 → ngio-0.4.2}/tests/unit/tables/test_roi_table_v1.py +0 -0
  256. {ngio-0.4.1 → ngio-0.4.2}/tests/unit/tables/test_table_group.py +0 -0
  257. {ngio-0.4.1 → ngio-0.4.2}/tests/unit/utils/test_download_datasets.py +0 -0
  258. {ngio-0.4.1 → ngio-0.4.2}/tests/unit/utils/test_zarr_utils.py +0 -0
@@ -1,5 +1,16 @@
1
1
  # Changelog
2
2
 
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
+
3
14
  ## [v0.4.1]
4
15
 
5
16
  ### Bug Fixes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ngio
3
- Version: 0.4.1
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
@@ -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 = {}
@@ -5,6 +5,7 @@ from functools import total_ordering
5
5
  from typing import overload
6
6
 
7
7
  import numpy as np
8
+ from pydantic import BaseModel
8
9
 
9
10
  from ngio.ome_zarr_meta.ngio_specs import (
10
11
  DefaultSpaceUnit,
@@ -22,34 +23,16 @@ from ngio.ome_zarr_meta.ngio_specs import (
22
23
  #################################################################################################
23
24
 
24
25
 
25
- def _validate_type(value: float, name: str) -> float:
26
- """Check the type of the value."""
27
- if not isinstance(value, int | float):
28
- raise TypeError(f"{name} must be a number.")
29
- return float(value)
30
-
31
-
32
26
  @total_ordering
33
- class PixelSize:
27
+ class PixelSize(BaseModel):
34
28
  """PixelSize class to store the pixel size in 3D space."""
35
29
 
36
- def __init__(
37
- self,
38
- x: float,
39
- y: float,
40
- z: float,
41
- t: float = 1,
42
- space_unit: SpaceUnits | str | None = DefaultSpaceUnit,
43
- time_unit: TimeUnits | str | None = DefaultTimeUnit,
44
- ):
45
- """Initialize the pixel size."""
46
- self.x = _validate_type(x, "x")
47
- self.y = _validate_type(y, "y")
48
- self.z = _validate_type(z, "z")
49
- self.t = _validate_type(t, "t")
50
-
51
- self._space_unit = space_unit
52
- self._time_unit = time_unit
30
+ x: float
31
+ y: float
32
+ z: float
33
+ t: float = 1
34
+ space_unit: SpaceUnits | str | None = DefaultSpaceUnit
35
+ time_unit: TimeUnits | str | None = DefaultTimeUnit
53
36
 
54
37
  def __repr__(self) -> str:
55
38
  """Return a string representation of the pixel size."""
@@ -76,10 +59,10 @@ class PixelSize:
76
59
  if not isinstance(other, PixelSize):
77
60
  raise TypeError("Can only compare PixelSize with PixelSize.")
78
61
  ref = PixelSize(
79
- 0,
80
- 0,
81
- 0,
82
- 0,
62
+ x=0,
63
+ y=0,
64
+ z=0,
65
+ t=0,
83
66
  space_unit=self.space_unit,
84
67
  time_unit=self.time_unit, # type: ignore
85
68
  )
@@ -104,16 +87,6 @@ class PixelSize:
104
87
  )
105
88
  return px_size
106
89
 
107
- @property
108
- def space_unit(self) -> SpaceUnits | str | None:
109
- """Return the space unit."""
110
- return self._space_unit
111
-
112
- @property
113
- def time_unit(self) -> TimeUnits | str | None:
114
- """Return the time unit."""
115
- return self._time_unit
116
-
117
90
  @property
118
91
  def tzyx(self) -> tuple[float, float, float, float]:
119
92
  """Return the voxel size in t, z, y, x order."""
@@ -26,7 +26,7 @@ def test_basic_rois_ops():
26
26
  assert roi.__str__()
27
27
  assert roi.__repr__()
28
28
 
29
- assert raster_roi.to_slicing_dict() == {
29
+ assert raster_roi.to_slicing_dict(pixel_size=pixel_size) == {
30
30
  "x": slice(0, 1),
31
31
  "y": slice(0, 1),
32
32
  "z": slice(0, 1),
@@ -49,7 +49,7 @@ def test_basic_rois_ops():
49
49
  with pytest.raises(ValueError):
50
50
  roi.zoom(-1.0)
51
51
 
52
- assert roi_zoomed.to_roi_pixels(pixel_size).to_slicing_dict() == {
52
+ assert roi_zoomed.to_slicing_dict(pixel_size) == {
53
53
  "x": slice(0, 2),
54
54
  "y": slice(0, 2),
55
55
  "z": slice(0, 1),
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes