ngio 0.2.1__tar.gz → 0.2.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 (206) hide show
  1. {ngio-0.2.1 → ngio-0.2.2}/PKG-INFO +1 -1
  2. {ngio-0.2.1 → ngio-0.2.2}/docs/getting_started/5_hcs.md +2 -2
  3. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/__init__.py +20 -2
  4. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/common/_roi.py +2 -2
  5. ngio-0.2.2/src/ngio/hcs/__init__.py +19 -0
  6. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/hcs/plate.py +381 -22
  7. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/images/abstract_image.py +10 -0
  8. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/images/create.py +25 -36
  9. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/images/image.py +38 -6
  10. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/images/label.py +23 -2
  11. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/images/ome_zarr_container.py +66 -26
  12. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/ome_zarr_meta/__init__.py +5 -3
  13. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/ome_zarr_meta/ngio_specs/__init__.py +10 -2
  14. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/ome_zarr_meta/ngio_specs/_axes.py +90 -65
  15. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/ome_zarr_meta/ngio_specs/_dataset.py +46 -8
  16. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/ome_zarr_meta/ngio_specs/_ngio_hcs.py +242 -70
  17. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/ome_zarr_meta/ngio_specs/_ngio_image.py +49 -11
  18. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/ome_zarr_meta/ngio_specs/_pixel_size.py +28 -11
  19. ngio-0.2.2/src/ngio/ome_zarr_meta/v04/_custom_models.py +18 -0
  20. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/ome_zarr_meta/v04/_v04_spec_utils.py +2 -2
  21. ngio-0.2.2/tests/data/v04/meta/base_ome_zarr_well_meta.json +10 -0
  22. ngio-0.2.2/tests/data/v04/meta/ome_zarr_well_path_normalization_meta.json +13 -0
  23. ngio-0.2.2/tests/unit/hcs/test_plate.py +146 -0
  24. ngio-0.2.2/tests/unit/hcs/test_well.py +35 -0
  25. {ngio-0.2.1 → ngio-0.2.2}/tests/unit/images/test_omezarr_container.py +9 -3
  26. {ngio-0.2.1/tests/unit/test_ome_zarr_meta → ngio-0.2.2/tests/unit/ome_zarr_meta}/test_unit_ngio_specs.py +15 -16
  27. {ngio-0.2.1/tests/unit/test_ome_zarr_meta → ngio-0.2.2/tests/unit/ome_zarr_meta}/test_unit_v04_utils.py +32 -1
  28. ngio-0.2.1/src/ngio/hcs/__init__.py +0 -5
  29. ngio-0.2.1/tests/unit/hcs/test_plate.py +0 -57
  30. {ngio-0.2.1 → ngio-0.2.2}/.copier-answers.yml +0 -0
  31. {ngio-0.2.1 → ngio-0.2.2}/.gitattributes +0 -0
  32. {ngio-0.2.1 → ngio-0.2.2}/.github/ISSUE_TEMPLATE.md +0 -0
  33. {ngio-0.2.1 → ngio-0.2.2}/.github/TEST_FAIL_TEMPLATE.md +0 -0
  34. {ngio-0.2.1 → ngio-0.2.2}/.github/dependabot.yml +0 -0
  35. {ngio-0.2.1 → ngio-0.2.2}/.github/scripts/download_data.sh +0 -0
  36. {ngio-0.2.1 → ngio-0.2.2}/.github/workflows/build_docs.yml +0 -0
  37. {ngio-0.2.1 → ngio-0.2.2}/.github/workflows/ci.yml +0 -0
  38. {ngio-0.2.1 → ngio-0.2.2}/.gitignore +0 -0
  39. {ngio-0.2.1 → ngio-0.2.2}/.pre-commit-config.yaml +0 -0
  40. {ngio-0.2.1 → ngio-0.2.2}/LICENSE +0 -0
  41. {ngio-0.2.1 → ngio-0.2.2}/README.md +0 -0
  42. {ngio-0.2.1 → ngio-0.2.2}/_typos.toml +0 -0
  43. {ngio-0.2.1 → ngio-0.2.2}/docs/api/common.md +0 -0
  44. {ngio-0.2.1 → ngio-0.2.2}/docs/api/hcs.md +0 -0
  45. {ngio-0.2.1 → ngio-0.2.2}/docs/api/images.md +0 -0
  46. {ngio-0.2.1 → ngio-0.2.2}/docs/api/ngio.md +0 -0
  47. {ngio-0.2.1 → ngio-0.2.2}/docs/api/tables.md +0 -0
  48. {ngio-0.2.1 → ngio-0.2.2}/docs/api/utils.md +0 -0
  49. {ngio-0.2.1 → ngio-0.2.2}/docs/code_of_conduct.md +0 -0
  50. {ngio-0.2.1 → ngio-0.2.2}/docs/contributing.md +0 -0
  51. {ngio-0.2.1 → ngio-0.2.2}/docs/getting_started/0_quickstart.md +0 -0
  52. {ngio-0.2.1 → ngio-0.2.2}/docs/getting_started/1_ome_zarr_containers.md +0 -0
  53. {ngio-0.2.1 → ngio-0.2.2}/docs/getting_started/2_images.md +0 -0
  54. {ngio-0.2.1 → ngio-0.2.2}/docs/getting_started/3_tables.md +0 -0
  55. {ngio-0.2.1 → ngio-0.2.2}/docs/getting_started/4_masked_images.md +0 -0
  56. {ngio-0.2.1 → ngio-0.2.2}/docs/index.md +0 -0
  57. {ngio-0.2.1 → ngio-0.2.2}/docs/tutorials/feature_extraction.ipynb +0 -0
  58. {ngio-0.2.1 → ngio-0.2.2}/docs/tutorials/hcs_processing.ipynb +0 -0
  59. {ngio-0.2.1 → ngio-0.2.2}/docs/tutorials/image_processing.ipynb +0 -0
  60. {ngio-0.2.1 → ngio-0.2.2}/docs/tutorials/image_segmentation.ipynb +0 -0
  61. {ngio-0.2.1 → ngio-0.2.2}/index.md +0 -0
  62. {ngio-0.2.1 → ngio-0.2.2}/mkdocs.yml +0 -0
  63. {ngio-0.2.1 → ngio-0.2.2}/pyproject.toml +0 -0
  64. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/common/__init__.py +0 -0
  65. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/common/_array_pipe.py +0 -0
  66. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/common/_axes_transforms.py +0 -0
  67. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/common/_common_types.py +0 -0
  68. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/common/_dimensions.py +0 -0
  69. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/common/_masking_roi.py +0 -0
  70. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/common/_pyramid.py +0 -0
  71. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/common/_slicer.py +0 -0
  72. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/common/_zoom.py +0 -0
  73. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/images/__init__.py +0 -0
  74. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/images/masked_image.py +0 -0
  75. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/ome_zarr_meta/_meta_handlers.py +0 -0
  76. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/ome_zarr_meta/ngio_specs/_channels.py +0 -0
  77. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/ome_zarr_meta/v04/__init__.py +0 -0
  78. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/tables/__init__.py +0 -0
  79. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/tables/_validators.py +0 -0
  80. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/tables/backends/__init__.py +0 -0
  81. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/tables/backends/_abstract_backend.py +0 -0
  82. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/tables/backends/_anndata_utils.py +0 -0
  83. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/tables/backends/_anndata_v1.py +0 -0
  84. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/tables/backends/_json_v1.py +0 -0
  85. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/tables/backends/_table_backends.py +0 -0
  86. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/tables/tables_container.py +0 -0
  87. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/tables/v1/__init__.py +0 -0
  88. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/tables/v1/_feature_table.py +0 -0
  89. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/tables/v1/_generic_table.py +0 -0
  90. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/tables/v1/_roi_table.py +0 -0
  91. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/utils/__init__.py +0 -0
  92. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/utils/_datasets.py +0 -0
  93. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/utils/_errors.py +0 -0
  94. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/utils/_fractal_fsspec_store.py +0 -0
  95. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/utils/_logger.py +0 -0
  96. {ngio-0.2.1 → ngio-0.2.2}/src/ngio/utils/_zarr_utils.py +0 -0
  97. {ngio-0.2.1 → ngio-0.2.2}/tests/conftest.py +0 -0
  98. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_c1yx.zarr/.zattrs +0 -0
  99. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_c1yx.zarr/.zgroup +0 -0
  100. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_c1yx.zarr/0/.zarray +0 -0
  101. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_c1yx.zarr/1/.zarray +0 -0
  102. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_c1yx.zarr/labels/.zattrs +0 -0
  103. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_c1yx.zarr/labels/.zgroup +0 -0
  104. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_c1yx.zarr/labels/label/.zattrs +0 -0
  105. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_c1yx.zarr/labels/label/.zgroup +0 -0
  106. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_c1yx.zarr/labels/label/0/.zarray +0 -0
  107. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_c1yx.zarr/labels/label/1/.zarray +0 -0
  108. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_cyx.zarr/.zattrs +0 -0
  109. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_cyx.zarr/.zgroup +0 -0
  110. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_cyx.zarr/0/.zarray +0 -0
  111. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_cyx.zarr/1/.zarray +0 -0
  112. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_cyx.zarr/labels/.zattrs +0 -0
  113. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_cyx.zarr/labels/.zgroup +0 -0
  114. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_cyx.zarr/labels/label/.zattrs +0 -0
  115. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_cyx.zarr/labels/label/.zgroup +0 -0
  116. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_cyx.zarr/labels/label/0/.zarray +0 -0
  117. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_cyx.zarr/labels/label/1/.zarray +0 -0
  118. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_czyx.zarr/.zattrs +0 -0
  119. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_czyx.zarr/.zgroup +0 -0
  120. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_czyx.zarr/0/.zarray +0 -0
  121. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_czyx.zarr/1/.zarray +0 -0
  122. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_czyx.zarr/labels/.zattrs +0 -0
  123. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_czyx.zarr/labels/.zgroup +0 -0
  124. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_czyx.zarr/labels/label/.zattrs +0 -0
  125. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_czyx.zarr/labels/label/.zgroup +0 -0
  126. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_czyx.zarr/labels/label/0/.zarray +0 -0
  127. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_czyx.zarr/labels/label/1/.zarray +0 -0
  128. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tcyx.zarr/.zattrs +0 -0
  129. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tcyx.zarr/.zgroup +0 -0
  130. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tcyx.zarr/0/.zarray +0 -0
  131. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tcyx.zarr/1/.zarray +0 -0
  132. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tcyx.zarr/labels/.zattrs +0 -0
  133. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tcyx.zarr/labels/.zgroup +0 -0
  134. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tcyx.zarr/labels/label/.zattrs +0 -0
  135. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tcyx.zarr/labels/label/.zgroup +0 -0
  136. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tcyx.zarr/labels/label/0/.zarray +0 -0
  137. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tcyx.zarr/labels/label/1/.zarray +0 -0
  138. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tczyx.zarr/.zattrs +0 -0
  139. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tczyx.zarr/.zgroup +0 -0
  140. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tczyx.zarr/0/.zarray +0 -0
  141. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tczyx.zarr/1/.zarray +0 -0
  142. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tczyx.zarr/labels/.zattrs +0 -0
  143. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tczyx.zarr/labels/.zgroup +0 -0
  144. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tczyx.zarr/labels/label/.zattrs +0 -0
  145. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tczyx.zarr/labels/label/.zgroup +0 -0
  146. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tczyx.zarr/labels/label/0/.zarray +0 -0
  147. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tczyx.zarr/labels/label/1/.zarray +0 -0
  148. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tyx.zarr/.zattrs +0 -0
  149. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tyx.zarr/.zgroup +0 -0
  150. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tyx.zarr/0/.zarray +0 -0
  151. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tyx.zarr/1/.zarray +0 -0
  152. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tyx.zarr/labels/.zattrs +0 -0
  153. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tyx.zarr/labels/.zgroup +0 -0
  154. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tyx.zarr/labels/label/.zattrs +0 -0
  155. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tyx.zarr/labels/label/.zgroup +0 -0
  156. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tyx.zarr/labels/label/0/.zarray +0 -0
  157. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tyx.zarr/labels/label/1/.zarray +0 -0
  158. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tzyx.zarr/.zattrs +0 -0
  159. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tzyx.zarr/.zgroup +0 -0
  160. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tzyx.zarr/0/.zarray +0 -0
  161. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tzyx.zarr/1/.zarray +0 -0
  162. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tzyx.zarr/labels/.zattrs +0 -0
  163. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tzyx.zarr/labels/.zgroup +0 -0
  164. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tzyx.zarr/labels/label/.zattrs +0 -0
  165. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tzyx.zarr/labels/label/.zgroup +0 -0
  166. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tzyx.zarr/labels/label/0/.zarray +0 -0
  167. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_tzyx.zarr/labels/label/1/.zarray +0 -0
  168. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_yx.zarr/.zattrs +0 -0
  169. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_yx.zarr/.zgroup +0 -0
  170. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_yx.zarr/0/.zarray +0 -0
  171. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_yx.zarr/1/.zarray +0 -0
  172. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_yx.zarr/labels/.zattrs +0 -0
  173. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_yx.zarr/labels/.zgroup +0 -0
  174. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_yx.zarr/labels/label/.zattrs +0 -0
  175. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_yx.zarr/labels/label/.zgroup +0 -0
  176. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_yx.zarr/labels/label/0/.zarray +0 -0
  177. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_yx.zarr/labels/label/1/.zarray +0 -0
  178. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_zyx.zarr/.zattrs +0 -0
  179. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_zyx.zarr/.zgroup +0 -0
  180. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_zyx.zarr/0/.zarray +0 -0
  181. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_zyx.zarr/1/.zarray +0 -0
  182. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_zyx.zarr/labels/.zattrs +0 -0
  183. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_zyx.zarr/labels/.zgroup +0 -0
  184. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_zyx.zarr/labels/label/.zattrs +0 -0
  185. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_zyx.zarr/labels/label/.zgroup +0 -0
  186. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_zyx.zarr/labels/label/0/.zarray +0 -0
  187. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/images/test_image_zyx.zarr/labels/label/1/.zarray +0 -0
  188. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/meta/base_ome_zarr_image_meta.json +0 -0
  189. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/meta/base_ome_zarr_image_meta_wrong_axis_order.json +0 -0
  190. {ngio-0.2.1 → ngio-0.2.2}/tests/data/v04/meta/base_ome_zarr_label_meta.json +0 -0
  191. {ngio-0.2.1 → ngio-0.2.2}/tests/unit/common/test_dimensions.py +0 -0
  192. {ngio-0.2.1 → ngio-0.2.2}/tests/unit/common/test_pyramid.py +0 -0
  193. {ngio-0.2.1 → ngio-0.2.2}/tests/unit/common/test_roi.py +0 -0
  194. {ngio-0.2.1 → ngio-0.2.2}/tests/unit/images/test_create.py +0 -0
  195. {ngio-0.2.1 → ngio-0.2.2}/tests/unit/images/test_images.py +0 -0
  196. {ngio-0.2.1 → ngio-0.2.2}/tests/unit/images/test_masked_images.py +0 -0
  197. {ngio-0.2.1/tests/unit/test_ome_zarr_meta → ngio-0.2.2/tests/unit/ome_zarr_meta}/test_image_handler.py +0 -0
  198. {ngio-0.2.1 → ngio-0.2.2}/tests/unit/tables/test_backends.py +0 -0
  199. {ngio-0.2.1 → ngio-0.2.2}/tests/unit/tables/test_feature_table.py +0 -0
  200. {ngio-0.2.1 → ngio-0.2.2}/tests/unit/tables/test_generic_table.py +0 -0
  201. {ngio-0.2.1 → ngio-0.2.2}/tests/unit/tables/test_masking_roi_table_v1.py +0 -0
  202. {ngio-0.2.1 → ngio-0.2.2}/tests/unit/tables/test_roi_table_v1.py +0 -0
  203. {ngio-0.2.1 → ngio-0.2.2}/tests/unit/tables/test_table_group.py +0 -0
  204. {ngio-0.2.1 → ngio-0.2.2}/tests/unit/tables/test_validators.py +0 -0
  205. {ngio-0.2.1 → ngio-0.2.2}/tests/unit/utils/test_download_datasets.py +0 -0
  206. {ngio-0.2.1 → ngio-0.2.2}/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.1
3
+ Version: 0.2.2
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
@@ -38,8 +38,8 @@ The `OmeZarrPlate` object provides a high-level overview of the plate, including
38
38
  === "Acquisitions"
39
39
  Show the acquisitions ids:
40
40
  ```pycon exec="true" source="console" session="hcs_plate"
41
- >>> ome_zarr_plate.acquisitions_ids
42
- >>> print(ome_zarr_plate.acquisitions_ids) # markdown-exec: hide
41
+ >>> ome_zarr_plate.acquisition_ids
42
+ >>> print(ome_zarr_plate.acquisition_ids) # markdown-exec: hide
43
43
  ```
44
44
 
45
45
  ## Retrieving the path to the images
@@ -10,7 +10,14 @@ __author__ = "Lorenzo Cerrone"
10
10
  __email__ = "lorenzo.cerrone@uzh.ch"
11
11
 
12
12
  from ngio.common import ArrayLike, Dimensions, Roi, RoiPixels
13
- from ngio.hcs import OmeZarrPlate, create_empty_plate, open_ome_zarr_plate
13
+ from ngio.hcs import (
14
+ OmeZarrPlate,
15
+ OmeZarrWell,
16
+ create_empty_plate,
17
+ create_empty_well,
18
+ open_ome_zarr_plate,
19
+ open_ome_zarr_well,
20
+ )
14
21
  from ngio.images import (
15
22
  Image,
16
23
  Label,
@@ -20,24 +27,35 @@ from ngio.images import (
20
27
  open_image,
21
28
  open_ome_zarr_container,
22
29
  )
23
- from ngio.ome_zarr_meta.ngio_specs import AxesSetup, ImageInWellPath, PixelSize
30
+ from ngio.ome_zarr_meta.ngio_specs import (
31
+ AxesSetup,
32
+ DefaultNgffVersion,
33
+ ImageInWellPath,
34
+ NgffVersions,
35
+ PixelSize,
36
+ )
24
37
 
25
38
  __all__ = [
26
39
  "ArrayLike",
27
40
  "AxesSetup",
41
+ "DefaultNgffVersion",
28
42
  "Dimensions",
29
43
  "Image",
30
44
  "ImageInWellPath",
31
45
  "Label",
46
+ "NgffVersions",
32
47
  "OmeZarrContainer",
33
48
  "OmeZarrPlate",
49
+ "OmeZarrWell",
34
50
  "PixelSize",
35
51
  "Roi",
36
52
  "RoiPixels",
37
53
  "create_empty_ome_zarr",
38
54
  "create_empty_plate",
55
+ "create_empty_well",
39
56
  "create_ome_zarr_from_array",
40
57
  "open_image",
41
58
  "open_ome_zarr_container",
42
59
  "open_ome_zarr_plate",
60
+ "open_ome_zarr_well",
43
61
  ]
@@ -10,7 +10,7 @@ import numpy as np
10
10
  from pydantic import BaseModel, ConfigDict, Field
11
11
 
12
12
  from ngio.common._dimensions import Dimensions
13
- from ngio.ome_zarr_meta.ngio_specs import PixelSize, SpaceUnits
13
+ from ngio.ome_zarr_meta.ngio_specs import DefaultSpaceUnit, PixelSize, SpaceUnits
14
14
  from ngio.utils import NgioValueError
15
15
 
16
16
 
@@ -36,7 +36,7 @@ class Roi(BaseModel):
36
36
  x: float = 0.0
37
37
  y: float = 0.0
38
38
  z: float = 0.0
39
- unit: SpaceUnits = Field(SpaceUnits.micrometer, repr=False)
39
+ unit: SpaceUnits | str | None = Field(DefaultSpaceUnit, repr=False)
40
40
 
41
41
  model_config = ConfigDict(extra="allow")
42
42
 
@@ -0,0 +1,19 @@
1
+ """OME-Zarr HCS objects models."""
2
+
3
+ from ngio.hcs.plate import (
4
+ OmeZarrPlate,
5
+ OmeZarrWell,
6
+ create_empty_plate,
7
+ create_empty_well,
8
+ open_ome_zarr_plate,
9
+ open_ome_zarr_well,
10
+ )
11
+
12
+ __all__ = [
13
+ "OmeZarrPlate",
14
+ "OmeZarrWell",
15
+ "create_empty_plate",
16
+ "create_empty_well",
17
+ "open_ome_zarr_plate",
18
+ "open_ome_zarr_well",
19
+ ]
@@ -3,19 +3,16 @@
3
3
  from ngio.images import OmeZarrContainer
4
4
  from ngio.ome_zarr_meta import (
5
5
  ImageInWellPath,
6
- NgffVersion,
6
+ NgffVersions,
7
7
  NgioPlateMeta,
8
8
  NgioWellMeta,
9
9
  find_plate_meta_handler,
10
10
  find_well_meta_handler,
11
11
  get_plate_meta_handler,
12
12
  get_well_meta_handler,
13
+ path_in_well_validation,
13
14
  )
14
- from ngio.utils import (
15
- AccessModeLiteral,
16
- StoreOrGroup,
17
- ZarrGroupHandler,
18
- )
15
+ from ngio.utils import AccessModeLiteral, StoreOrGroup, ZarrGroupHandler
19
16
 
20
17
 
21
18
  # Mock lock class that does nothing
@@ -43,6 +40,10 @@ class OmeZarrWell:
43
40
  self._group_handler = group_handler
44
41
  self._meta_handler = find_well_meta_handler(group_handler)
45
42
 
43
+ def __repr__(self) -> str:
44
+ """Return a string representation of the well."""
45
+ return f"Well(#images: {len(self.paths())})"
46
+
46
47
  @property
47
48
  def meta_handler(self):
48
49
  """Return the metadata handler."""
@@ -53,6 +54,11 @@ class OmeZarrWell:
53
54
  """Return the metadata."""
54
55
  return self._meta_handler.meta
55
56
 
57
+ @property
58
+ def acquisition_ids(self) -> list[int]:
59
+ """Return the acquisitions ids in the well."""
60
+ return self.meta.acquisition_ids
61
+
56
62
  def paths(self, acquisition: int | None = None) -> list[str]:
57
63
  """Return the images paths in the well.
58
64
 
@@ -64,6 +70,97 @@ class OmeZarrWell:
64
70
  """
65
71
  return self.meta.paths(acquisition)
66
72
 
73
+ def get_image_store(self, image_path: str) -> StoreOrGroup:
74
+ """Get the image store from the well.
75
+
76
+ Args:
77
+ image_path (str): The path of the image.
78
+ """
79
+ return self._group_handler.get_group(image_path, create_mode=True)
80
+
81
+ def get_image_acquisition_id(self, image_path: str) -> int | None:
82
+ """Get the acquisition id of an image in the well.
83
+
84
+ Args:
85
+ image_path (str): The path of the image.
86
+
87
+ Returns:
88
+ int | None: The acquisition id of the image.
89
+ """
90
+ return self.meta.get_image_acquisition_id(image_path=image_path)
91
+
92
+ def get_image(self, image_path: str) -> OmeZarrContainer:
93
+ """Get an image from the well.
94
+
95
+ Args:
96
+ image_path (str): The path of the image.
97
+
98
+ Returns:
99
+ OmeZarrContainer: The image.
100
+ """
101
+ handler = self._group_handler.derive_handler(image_path)
102
+ return OmeZarrContainer(handler)
103
+
104
+ def _add_image(
105
+ self,
106
+ image_path: str,
107
+ acquisition_id: int | None = None,
108
+ strict: bool = True,
109
+ atomic: bool = False,
110
+ ) -> StoreOrGroup:
111
+ """Add an image to an ome-zarr well."""
112
+ image_path = path_in_well_validation(path=image_path)
113
+
114
+ if atomic:
115
+ well_lock = self._group_handler.lock
116
+ else:
117
+ well_lock = MockLock()
118
+
119
+ with well_lock:
120
+ meta = self.meta.add_image(
121
+ path=image_path, acquisition=acquisition_id, strict=strict
122
+ )
123
+ self.meta_handler.write_meta(meta)
124
+ self.meta_handler._group_handler.clean_cache()
125
+
126
+ return self._group_handler.get_group(image_path, create_mode=True)
127
+
128
+ def atomic_add_image(
129
+ self,
130
+ image_path: str,
131
+ acquisition_id: int | None = None,
132
+ strict: bool = True,
133
+ ) -> StoreOrGroup:
134
+ """Parallel safe version of add_image."""
135
+ return self._add_image(
136
+ image_path=image_path,
137
+ acquisition_id=acquisition_id,
138
+ atomic=True,
139
+ strict=strict,
140
+ )
141
+
142
+ def add_image(
143
+ self,
144
+ image_path: str,
145
+ acquisition_id: int | None = None,
146
+ strict: bool = True,
147
+ ) -> StoreOrGroup:
148
+ """Add an image to an ome-zarr well.
149
+
150
+ Args:
151
+ image_path (str): The path of the image.
152
+ acquisition_id (int | None): The acquisition id to filter the images.
153
+ strict (bool): Whether to check if the acquisition id is already exists
154
+ in the well. Defaults to True. If False this might lead to
155
+ acquision in a well that does not exist at the plate level.
156
+ """
157
+ return self._add_image(
158
+ image_path=image_path,
159
+ acquisition_id=acquisition_id,
160
+ atomic=False,
161
+ strict=strict,
162
+ )
163
+
67
164
 
68
165
  class OmeZarrPlate:
69
166
  """A class to handle the Plate Collection in an OME-Zarr file."""
@@ -107,9 +204,9 @@ class OmeZarrPlate:
107
204
  return self.meta.acquisitions_names
108
205
 
109
206
  @property
110
- def acquisitions_ids(self) -> list[int]:
207
+ def acquisition_ids(self) -> list[int]:
111
208
  """Return the acquisitions ids in the plate."""
112
- return self.meta.acquisitions_ids
209
+ return self.meta.acquisition_ids
113
210
 
114
211
  def _well_path(self, row: str, column: int | str) -> str:
115
212
  """Return the well path in the plate."""
@@ -160,6 +257,22 @@ class OmeZarrPlate:
160
257
  images.append(self._image_path(row=row, column=column, path=path))
161
258
  return images
162
259
 
260
+ def get_image_acquisition_id(
261
+ self, row: str, column: int | str, image_path: str
262
+ ) -> int | None:
263
+ """Get the acquisition id of an image in a well.
264
+
265
+ Args:
266
+ row (str): The row of the well.
267
+ column (int | str): The column of the well.
268
+ image_path (str): The path of the image.
269
+
270
+ Returns:
271
+ int | None: The acquisition id of the image.
272
+ """
273
+ well = self.get_well(row=row, column=column)
274
+ return well.get_image_acquisition_id(image_path=image_path)
275
+
163
276
  def get_well(self, row: str, column: int | str) -> OmeZarrWell:
164
277
  """Get a well from the plate.
165
278
 
@@ -217,6 +330,19 @@ class OmeZarrPlate:
217
330
  group_handler = self._group_handler.derive_handler(image_path)
218
331
  return OmeZarrContainer(group_handler)
219
332
 
333
+ def get_image_store(
334
+ self, row: str, column: int | str, image_path: str
335
+ ) -> StoreOrGroup:
336
+ """Get the image store from the plate.
337
+
338
+ Args:
339
+ row (str): The row of the well.
340
+ column (int | str): The column of the well.
341
+ image_path (str): The path of the image.
342
+ """
343
+ well = self.get_well(row=row, column=column)
344
+ return well.get_image_store(image_path=image_path)
345
+
220
346
  def get_well_images(
221
347
  self, row: str, column: str | int, acquisition: int | None = None
222
348
  ) -> dict[str, OmeZarrContainer]:
@@ -239,12 +365,15 @@ class OmeZarrPlate:
239
365
  self,
240
366
  row: str,
241
367
  column: int | str,
242
- image_path: str,
368
+ image_path: str | None = None,
243
369
  acquisition_id: int | None = None,
244
370
  acquisition_name: str | None = None,
245
371
  atomic: bool = False,
246
- ) -> StoreOrGroup:
372
+ ) -> StoreOrGroup | None:
247
373
  """Add an image to an ome-zarr plate."""
374
+ if image_path is not None:
375
+ image_path = path_in_well_validation(path=image_path)
376
+
248
377
  if atomic:
249
378
  plate_lock = self._group_handler.lock
250
379
  else:
@@ -252,7 +381,11 @@ class OmeZarrPlate:
252
381
 
253
382
  with plate_lock:
254
383
  meta = self.meta
255
- meta = meta.add_well(row, column, acquisition_id, acquisition_name)
384
+ meta = meta.add_well(row=row, column=column)
385
+ if acquisition_id is not None:
386
+ meta = meta.add_acquisition(
387
+ acquisition_id=acquisition_id, acquisition_name=acquisition_name
388
+ )
256
389
  self.meta_handler.write_meta(meta)
257
390
  self.meta_handler._group_handler.clean_cache()
258
391
 
@@ -279,11 +412,16 @@ class OmeZarrPlate:
279
412
 
280
413
  group_handler = self._group_handler.derive_handler(well_path)
281
414
 
282
- well_meta = well_meta.add_image(path=image_path, acquisition=acquisition_id)
415
+ if image_path is not None:
416
+ well_meta = well_meta.add_image(
417
+ path=image_path, acquisition=acquisition_id, strict=False
418
+ )
283
419
  meta_handler.write_meta(well_meta)
284
420
  meta_handler._group_handler.clean_cache()
285
421
 
286
- return group_handler.get_group(image_path, create_mode=True)
422
+ if image_path is not None:
423
+ return group_handler.get_group(image_path, create_mode=True)
424
+ return None
287
425
 
288
426
  def atomic_add_image(
289
427
  self,
@@ -294,7 +432,12 @@ class OmeZarrPlate:
294
432
  acquisition_name: str | None = None,
295
433
  ) -> StoreOrGroup:
296
434
  """Parallel safe version of add_image."""
297
- return self._add_image(
435
+ if image_path is None:
436
+ raise ValueError(
437
+ "Image path cannot be None for atomic add_image. "
438
+ "If your intent is to add a well, use add_well instead."
439
+ )
440
+ group = self._add_image(
298
441
  row=row,
299
442
  column=column,
300
443
  image_path=image_path,
@@ -302,6 +445,12 @@ class OmeZarrPlate:
302
445
  acquisition_name=acquisition_name,
303
446
  atomic=True,
304
447
  )
448
+ if group is None:
449
+ raise ValueError(
450
+ f"Some error occurred while adding image {image_path} "
451
+ f"to well {row}{column}."
452
+ )
453
+ return group
305
454
 
306
455
  def add_image(
307
456
  self,
@@ -312,7 +461,12 @@ class OmeZarrPlate:
312
461
  acquisition_name: str | None = None,
313
462
  ) -> StoreOrGroup:
314
463
  """Add an image to an ome-zarr plate."""
315
- return self._add_image(
464
+ if image_path is None:
465
+ raise ValueError(
466
+ "Image path cannot be None for atomic add_image. "
467
+ "If your intent is to add a well, use add_well instead."
468
+ )
469
+ group = self._add_image(
316
470
  row=row,
317
471
  column=column,
318
472
  image_path=image_path,
@@ -320,6 +474,68 @@ class OmeZarrPlate:
320
474
  acquisition_name=acquisition_name,
321
475
  atomic=False,
322
476
  )
477
+ if group is None:
478
+ raise ValueError(
479
+ f"Some error occurred while adding image {image_path} "
480
+ f"to well {row}{column}."
481
+ )
482
+ return group
483
+
484
+ def add_well(
485
+ self,
486
+ row: str,
487
+ column: int | str,
488
+ ) -> OmeZarrWell:
489
+ """Add a well to an ome-zarr plate."""
490
+ _ = self._add_image(
491
+ row=row,
492
+ column=column,
493
+ image_path=None,
494
+ acquisition_id=None,
495
+ acquisition_name=None,
496
+ atomic=False,
497
+ )
498
+ return self.get_well(row=row, column=column)
499
+
500
+ def add_column(
501
+ self,
502
+ column: int | str,
503
+ ) -> "OmeZarrPlate":
504
+ """Add a column to an ome-zarr plate."""
505
+ meta, _ = self.meta.add_column(column)
506
+ self.meta_handler.write_meta(meta)
507
+ self.meta_handler._group_handler.clean_cache()
508
+ return self
509
+
510
+ def add_row(
511
+ self,
512
+ row: str,
513
+ ) -> "OmeZarrPlate":
514
+ """Add a row to an ome-zarr plate."""
515
+ meta, _ = self.meta.add_row(row)
516
+ self.meta_handler.write_meta(meta)
517
+ self.meta_handler._group_handler.clean_cache()
518
+ return self
519
+
520
+ def add_acquisition(
521
+ self,
522
+ acquisition_id: int,
523
+ acquisition_name: str,
524
+ ) -> "OmeZarrPlate":
525
+ """Add an acquisition to an ome-zarr plate.
526
+
527
+ Be aware that this is not a parallel safe operation.
528
+
529
+ Args:
530
+ acquisition_id (int): The acquisition id.
531
+ acquisition_name (str): The acquisition name.
532
+ """
533
+ meta = self.meta.add_acquisition(
534
+ acquisition_id=acquisition_id, acquisition_name=acquisition_name
535
+ )
536
+ self.meta_handler.write_meta(meta)
537
+ self.meta_handler._group_handler.clean_cache()
538
+ return self
323
539
 
324
540
  def _remove_well(
325
541
  self,
@@ -390,6 +606,38 @@ class OmeZarrPlate:
390
606
  atomic=False,
391
607
  )
392
608
 
609
+ def derive_plate(
610
+ self,
611
+ store: StoreOrGroup,
612
+ plate_name: str | None = None,
613
+ version: NgffVersions = "0.4",
614
+ keep_acquisitions: bool = False,
615
+ cache: bool = False,
616
+ overwrite: bool = False,
617
+ parallel_safe: bool = True,
618
+ ) -> "OmeZarrPlate":
619
+ """Derive a new OME-Zarr plate from an existing one.
620
+
621
+ Args:
622
+ store (StoreOrGroup): The Zarr store or group that stores the plate.
623
+ plate_name (str | None): The name of the new plate.
624
+ version (NgffVersion): The version of the new plate.
625
+ keep_acquisitions (bool): Whether to keep the acquisitions in the new plate.
626
+ cache (bool): Whether to use a cache for the zarr group metadata.
627
+ overwrite (bool): Whether to overwrite the existing plate.
628
+ parallel_safe (bool): Whether the group handler is parallel safe.
629
+ """
630
+ return derive_ome_zarr_plate(
631
+ ome_zarr_plate=self,
632
+ store=store,
633
+ plate_name=plate_name,
634
+ version=version,
635
+ keep_acquisitions=keep_acquisitions,
636
+ cache=cache,
637
+ overwrite=overwrite,
638
+ parallel_safe=parallel_safe,
639
+ )
640
+
393
641
 
394
642
  def open_ome_zarr_plate(
395
643
  store: StoreOrGroup,
@@ -412,26 +660,42 @@ def open_ome_zarr_plate(
412
660
  return OmeZarrPlate(group_handler)
413
661
 
414
662
 
663
+ def _create_empty_plate_from_meta(
664
+ store: StoreOrGroup,
665
+ meta: NgioPlateMeta,
666
+ version: NgffVersions = "0.4",
667
+ overwrite: bool = False,
668
+ ) -> ZarrGroupHandler:
669
+ """Create an empty OME-Zarr plate from metadata."""
670
+ mode = "w" if overwrite else "w-"
671
+ group_handler = ZarrGroupHandler(
672
+ store=store, cache=True, mode=mode, parallel_safe=False
673
+ )
674
+ meta_handler = get_plate_meta_handler(group_handler, version=version)
675
+ meta_handler.write_meta(meta)
676
+ return group_handler
677
+
678
+
415
679
  def create_empty_plate(
416
680
  store: StoreOrGroup,
417
681
  name: str,
418
682
  images: list[ImageInWellPath] | None = None,
419
- version: NgffVersion = "0.4",
683
+ version: NgffVersions = "0.4",
420
684
  cache: bool = False,
421
685
  overwrite: bool = False,
422
686
  parallel_safe: bool = True,
423
687
  ) -> OmeZarrPlate:
424
688
  """Initialize and create an empty OME-Zarr plate."""
425
- mode = "w" if overwrite else "w-"
426
- group_handler = ZarrGroupHandler(
427
- store=store, cache=True, mode=mode, parallel_safe=False
428
- )
429
- meta_handler = get_plate_meta_handler(group_handler, version=version)
430
689
  plate_meta = NgioPlateMeta.default_init(
431
690
  name=name,
432
691
  version=version,
433
692
  )
434
- meta_handler.write_meta(plate_meta)
693
+ group_handler = _create_empty_plate_from_meta(
694
+ store=store,
695
+ meta=plate_meta,
696
+ version=version,
697
+ overwrite=overwrite,
698
+ )
435
699
 
436
700
  if images is not None:
437
701
  plate = OmeZarrPlate(group_handler)
@@ -449,3 +713,98 @@ def create_empty_plate(
449
713
  mode="r+",
450
714
  parallel_safe=parallel_safe,
451
715
  )
716
+
717
+
718
+ def derive_ome_zarr_plate(
719
+ ome_zarr_plate: OmeZarrPlate,
720
+ store: StoreOrGroup,
721
+ plate_name: str | None = None,
722
+ version: NgffVersions = "0.4",
723
+ keep_acquisitions: bool = False,
724
+ cache: bool = False,
725
+ overwrite: bool = False,
726
+ parallel_safe: bool = True,
727
+ ) -> OmeZarrPlate:
728
+ """Derive a new OME-Zarr plate from an existing one.
729
+
730
+ Args:
731
+ ome_zarr_plate (OmeZarrPlate): The existing OME-Zarr plate.
732
+ store (StoreOrGroup): The Zarr store or group that stores the plate.
733
+ plate_name (str | None): The name of the new plate.
734
+ version (NgffVersion): The version of the new plate.
735
+ keep_acquisitions (bool): Whether to keep the acquisitions in the new plate.
736
+ cache (bool): Whether to use a cache for the zarr group metadata.
737
+ overwrite (bool): Whether to overwrite the existing plate.
738
+ parallel_safe (bool): Whether the group handler is parallel safe.
739
+ """
740
+ if plate_name is None:
741
+ plate_name = ome_zarr_plate.meta.plate.name
742
+
743
+ new_meta = ome_zarr_plate.meta.derive(
744
+ name=plate_name,
745
+ version=version,
746
+ keep_acquisitions=keep_acquisitions,
747
+ )
748
+ _ = _create_empty_plate_from_meta(
749
+ store=store,
750
+ meta=new_meta,
751
+ overwrite=overwrite,
752
+ version=version,
753
+ )
754
+ return open_ome_zarr_plate(
755
+ store=store,
756
+ cache=cache,
757
+ mode="r+",
758
+ parallel_safe=parallel_safe,
759
+ )
760
+
761
+
762
+ def open_ome_zarr_well(
763
+ store: StoreOrGroup,
764
+ cache: bool = False,
765
+ mode: AccessModeLiteral = "r+",
766
+ parallel_safe: bool = True,
767
+ ) -> OmeZarrWell:
768
+ """Open an OME-Zarr well.
769
+
770
+ Args:
771
+ store (StoreOrGroup): The Zarr store or group that stores the plate.
772
+ cache (bool): Whether to use a cache for the zarr group metadata.
773
+ mode (AccessModeLiteral): The access mode for the image. Defaults to "r+".
774
+ parallel_safe (bool): Whether the group handler is parallel safe.
775
+ """
776
+ group_handler = ZarrGroupHandler(
777
+ store=store, cache=cache, mode=mode, parallel_safe=parallel_safe
778
+ )
779
+ return OmeZarrWell(group_handler)
780
+
781
+
782
+ def create_empty_well(
783
+ store: StoreOrGroup,
784
+ version: NgffVersions = "0.4",
785
+ cache: bool = False,
786
+ overwrite: bool = False,
787
+ parallel_safe: bool = True,
788
+ ) -> OmeZarrWell:
789
+ """Create an empty OME-Zarr well.
790
+
791
+ Args:
792
+ store (StoreOrGroup): The Zarr store or group that stores the well.
793
+ version (NgffVersion): The version of the new well.
794
+ cache (bool): Whether to use a cache for the zarr group metadata.
795
+ overwrite (bool): Whether to overwrite the existing well.
796
+ parallel_safe (bool): Whether the group handler is parallel safe.
797
+ """
798
+ group_handler = ZarrGroupHandler(
799
+ store=store, cache=True, mode="w" if overwrite else "w-", parallel_safe=False
800
+ )
801
+ meta_handler = get_well_meta_handler(group_handler, version=version)
802
+ meta = NgioWellMeta.default_init()
803
+ meta_handler.write_meta(meta)
804
+
805
+ return open_ome_zarr_well(
806
+ store=store,
807
+ cache=cache,
808
+ mode="r+",
809
+ parallel_safe=parallel_safe,
810
+ )
@@ -135,6 +135,16 @@ class AbstractImage(Generic[_image_handler]):
135
135
  """Return True if the image is multichannel."""
136
136
  return self.dimensions.is_multi_channels
137
137
 
138
+ @property
139
+ def space_unit(self) -> str | None:
140
+ """Return the space unit of the image."""
141
+ return self.meta_handler.meta.space_unit
142
+
143
+ @property
144
+ def time_unit(self) -> str | None:
145
+ """Return the time unit of the image."""
146
+ return self.meta_handler.meta.time_unit
147
+
138
148
  @property
139
149
  def pixel_size(self) -> PixelSize:
140
150
  """Return the pixel size of the image."""