ngio 0.1.6__py3-none-any.whl → 0.2.0a1__py3-none-any.whl

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 (84) hide show
  1. ngio/__init__.py +31 -5
  2. ngio/common/__init__.py +44 -0
  3. ngio/common/_array_pipe.py +160 -0
  4. ngio/common/_axes_transforms.py +63 -0
  5. ngio/common/_common_types.py +5 -0
  6. ngio/common/_dimensions.py +113 -0
  7. ngio/common/_pyramid.py +222 -0
  8. ngio/{core/roi.py → common/_roi.py} +22 -23
  9. ngio/common/_slicer.py +97 -0
  10. ngio/{pipes/_zoom_utils.py → common/_zoom.py} +2 -78
  11. ngio/hcs/__init__.py +60 -0
  12. ngio/images/__init__.py +23 -0
  13. ngio/images/abstract_image.py +240 -0
  14. ngio/images/create.py +251 -0
  15. ngio/images/image.py +383 -0
  16. ngio/images/label.py +96 -0
  17. ngio/images/omezarr_container.py +512 -0
  18. ngio/ome_zarr_meta/__init__.py +35 -0
  19. ngio/ome_zarr_meta/_generic_handlers.py +320 -0
  20. ngio/ome_zarr_meta/_meta_handlers.py +142 -0
  21. ngio/ome_zarr_meta/ngio_specs/__init__.py +63 -0
  22. ngio/ome_zarr_meta/ngio_specs/_axes.py +481 -0
  23. ngio/ome_zarr_meta/ngio_specs/_channels.py +378 -0
  24. ngio/ome_zarr_meta/ngio_specs/_dataset.py +134 -0
  25. ngio/ome_zarr_meta/ngio_specs/_ngio_hcs.py +5 -0
  26. ngio/ome_zarr_meta/ngio_specs/_ngio_image.py +434 -0
  27. ngio/ome_zarr_meta/ngio_specs/_pixel_size.py +84 -0
  28. ngio/ome_zarr_meta/v04/__init__.py +11 -0
  29. ngio/ome_zarr_meta/v04/_meta_handlers.py +54 -0
  30. ngio/ome_zarr_meta/v04/_v04_spec_utils.py +412 -0
  31. ngio/tables/__init__.py +21 -5
  32. ngio/tables/_validators.py +192 -0
  33. ngio/tables/backends/__init__.py +8 -0
  34. ngio/tables/backends/_abstract_backend.py +71 -0
  35. ngio/tables/backends/_anndata_utils.py +194 -0
  36. ngio/tables/backends/_anndata_v1.py +75 -0
  37. ngio/tables/backends/_json_v1.py +56 -0
  38. ngio/tables/backends/_table_backends.py +102 -0
  39. ngio/tables/tables_container.py +300 -0
  40. ngio/tables/v1/__init__.py +6 -5
  41. ngio/tables/v1/_feature_table.py +161 -0
  42. ngio/tables/v1/_generic_table.py +99 -182
  43. ngio/tables/v1/_masking_roi_table.py +175 -0
  44. ngio/tables/v1/_roi_table.py +226 -0
  45. ngio/utils/__init__.py +23 -10
  46. ngio/utils/_datasets.py +51 -0
  47. ngio/utils/_errors.py +10 -4
  48. ngio/utils/_zarr_utils.py +378 -0
  49. {ngio-0.1.6.dist-info → ngio-0.2.0a1.dist-info}/METADATA +18 -39
  50. ngio-0.2.0a1.dist-info/RECORD +53 -0
  51. ngio/core/__init__.py +0 -7
  52. ngio/core/dimensions.py +0 -122
  53. ngio/core/image_handler.py +0 -228
  54. ngio/core/image_like_handler.py +0 -549
  55. ngio/core/label_handler.py +0 -410
  56. ngio/core/ngff_image.py +0 -387
  57. ngio/core/utils.py +0 -287
  58. ngio/io/__init__.py +0 -19
  59. ngio/io/_zarr.py +0 -88
  60. ngio/io/_zarr_array_utils.py +0 -0
  61. ngio/io/_zarr_group_utils.py +0 -60
  62. ngio/iterators/__init__.py +0 -1
  63. ngio/ngff_meta/__init__.py +0 -27
  64. ngio/ngff_meta/fractal_image_meta.py +0 -1267
  65. ngio/ngff_meta/meta_handler.py +0 -92
  66. ngio/ngff_meta/utils.py +0 -235
  67. ngio/ngff_meta/v04/__init__.py +0 -6
  68. ngio/ngff_meta/v04/specs.py +0 -158
  69. ngio/ngff_meta/v04/zarr_utils.py +0 -376
  70. ngio/pipes/__init__.py +0 -7
  71. ngio/pipes/_slicer_transforms.py +0 -176
  72. ngio/pipes/_transforms.py +0 -33
  73. ngio/pipes/data_pipe.py +0 -52
  74. ngio/tables/_ad_reader.py +0 -80
  75. ngio/tables/_utils.py +0 -301
  76. ngio/tables/tables_group.py +0 -252
  77. ngio/tables/v1/feature_tables.py +0 -182
  78. ngio/tables/v1/masking_roi_tables.py +0 -243
  79. ngio/tables/v1/roi_tables.py +0 -285
  80. ngio/utils/_common_types.py +0 -5
  81. ngio/utils/_pydantic_utils.py +0 -52
  82. ngio-0.1.6.dist-info/RECORD +0 -44
  83. {ngio-0.1.6.dist-info → ngio-0.2.0a1.dist-info}/WHEEL +0 -0
  84. {ngio-0.1.6.dist-info → ngio-0.2.0a1.dist-info}/licenses/LICENSE +0 -0
@@ -1,92 +0,0 @@
1
- """Handler for reading and writing NGFF image metadata."""
2
-
3
- from typing import Literal, Protocol
4
-
5
- from ngio.io import AccessModeLiteral, Group, StoreOrGroup
6
- from ngio.ngff_meta.fractal_image_meta import ImageLabelMeta
7
- from ngio.ngff_meta.v04.zarr_utils import (
8
- NgffImageMetaZarrHandlerV04,
9
- )
10
-
11
-
12
- class NgffImageMetaHandler(Protocol):
13
- """Handler for NGFF image metadata."""
14
-
15
- def __init__(
16
- self,
17
- store: StoreOrGroup,
18
- meta_mode: Literal["image", "label"],
19
- cache: bool = False,
20
- mode: AccessModeLiteral = "a",
21
- ):
22
- """Initialize the handler."""
23
- ...
24
-
25
- @property
26
- def group(self) -> Group:
27
- """Return the Zarr group."""
28
- ...
29
-
30
- @property
31
- def store(self) -> StoreOrGroup:
32
- """Return the Zarr store."""
33
- ...
34
-
35
- @property
36
- def zarr_version(self) -> int:
37
- """Return the Zarr version."""
38
- ...
39
-
40
- @staticmethod
41
- def check_version(store: StoreOrGroup) -> bool:
42
- """Check if the version of the metadata is supported."""
43
- ...
44
-
45
- def load_meta(self) -> ImageLabelMeta:
46
- """Load the OME-NGFF 0.4 metadata."""
47
- ...
48
-
49
- def write_meta(self, meta: ImageLabelMeta) -> None:
50
- """Write the OME-NGFF 0.4 metadata."""
51
- ...
52
-
53
- def update_cache(self, meta: ImageLabelMeta) -> None:
54
- """Update the cached metadata."""
55
- ...
56
-
57
- def clear_cache(self) -> None:
58
- """Clear the cached metadata."""
59
- ...
60
-
61
-
62
- _available_load_ngff_image_meta_handlers = {
63
- "0.4": NgffImageMetaZarrHandlerV04,
64
- }
65
-
66
-
67
- def find_ngff_image_meta_handler_version(store: StoreOrGroup) -> str:
68
- """Find the version of the NGFF image metadata."""
69
- for version, handler in _available_load_ngff_image_meta_handlers.items():
70
- if handler.check_version(store=store):
71
- return version
72
-
73
- supported_versions = ", ".join(_available_load_ngff_image_meta_handlers.keys())
74
- raise ValueError(
75
- f"The Zarr store does not contain a supported version. \
76
- Supported OME-Ngff versions are: {supported_versions}."
77
- )
78
-
79
-
80
- def get_ngff_image_meta_handler(
81
- store: StoreOrGroup,
82
- meta_mode: Literal["image", "label"],
83
- version: str | None = None,
84
- cache: bool = False,
85
- mode: AccessModeLiteral = "a",
86
- ) -> NgffImageMetaHandler:
87
- """Load the NGFF image metadata handler."""
88
- if version is None:
89
- version = find_ngff_image_meta_handler_version(store)
90
-
91
- handler = _available_load_ngff_image_meta_handlers[version]
92
- return handler(store=store, meta_mode=meta_mode, cache=cache, mode=mode)
ngio/ngff_meta/utils.py DELETED
@@ -1,235 +0,0 @@
1
- """Utility functions for creating and modifying metadata."""
2
-
3
- from collections.abc import Collection
4
- from typing import Any
5
-
6
- from ngio.ngff_meta.fractal_image_meta import (
7
- Axis,
8
- Channel,
9
- ChannelNames,
10
- ChannelVisualisation,
11
- Dataset,
12
- ImageMeta,
13
- LabelMeta,
14
- Omero,
15
- PixelSize,
16
- SpaceNames,
17
- SpaceUnits,
18
- TimeNames,
19
- TimeUnits,
20
- )
21
-
22
-
23
- def _create_multiscale_meta(
24
- on_disk_axis: Collection[str] = ("t", "c", "z", "y", "x"),
25
- pixel_sizes: PixelSize | None = None,
26
- xy_scaling_factor: float = 2.0,
27
- z_scaling_factor: float = 1.0,
28
- pixel_units: SpaceUnits | str = SpaceUnits.micrometer,
29
- time_spacing: float = 1.0,
30
- time_units: TimeUnits | str | None = None,
31
- levels: int | list[str] = 5,
32
- ) -> list[Dataset]:
33
- """Create a image metadata object from scratch."""
34
- allowed_axes_names = (
35
- SpaceNames.allowed_names()
36
- + TimeNames.allowed_names()
37
- + ChannelNames.allowed_names()
38
- )
39
- for ax in on_disk_axis:
40
- if ax not in allowed_axes_names:
41
- raise ValueError(
42
- f"Invalid axis name: {ax}, allowed names: {allowed_axes_names}"
43
- )
44
-
45
- if isinstance(pixel_units, str):
46
- pixel_units = SpaceUnits(pixel_units)
47
-
48
- if pixel_sizes is None:
49
- pixel_sizes = PixelSize(z=1.0, y=1.0, x=1.0, unit=pixel_units)
50
-
51
- pixel_sizes_dict = pixel_sizes.as_dict()
52
- pixel_sizes_dict["t"] = time_spacing
53
-
54
- scaling_factor_dict = {
55
- "z": z_scaling_factor,
56
- "y": xy_scaling_factor,
57
- "x": xy_scaling_factor,
58
- }
59
-
60
- if time_units is None:
61
- time_units = TimeUnits.s
62
-
63
- if isinstance(time_units, str):
64
- time_units = TimeUnits(time_units)
65
-
66
- axes = Axis.batch_create(on_disk_axis, time_unit=time_units, space_unit=pixel_units)
67
- datasets = []
68
-
69
- if isinstance(levels, int):
70
- paths = [str(i) for i in range(levels)]
71
- elif isinstance(levels, list):
72
- if not all(isinstance(level, str) for level in levels):
73
- raise ValueError(f"All levels must be strings. Got: {levels}")
74
- paths = levels
75
-
76
- for level, path in enumerate(paths):
77
- scale = [
78
- pixel_sizes_dict.get(ax, 1.0) * scaling_factor_dict.get(ax, 1.0) ** level
79
- for ax in on_disk_axis
80
- ]
81
-
82
- datasets.append(
83
- Dataset(
84
- path=path,
85
- on_disk_axes=axes,
86
- on_disk_scale=scale,
87
- on_disk_translation=None,
88
- )
89
- )
90
- return datasets
91
-
92
-
93
- def create_image_metadata(
94
- on_disk_axis: Collection[str] = ("t", "c", "z", "y", "x"),
95
- pixel_sizes: PixelSize | None = None,
96
- xy_scaling_factor: float = 2.0,
97
- z_scaling_factor: float = 1.0,
98
- time_spacing: float = 1.0,
99
- time_units: TimeUnits | str = TimeUnits.s,
100
- levels: int | list[str] = 5,
101
- name: str | None = None,
102
- channel_labels: list[str] | None = None,
103
- channel_wavelengths: list[str] | None = None,
104
- channel_visualization: list[ChannelVisualisation] | None = None,
105
- omero_kwargs: dict[str, Any] | None = None,
106
- version: str = "0.4",
107
- ) -> ImageMeta:
108
- """Create a image metadata object from scratch.
109
-
110
- Args:
111
- on_disk_axis: The names of the axes. The order will correspond to the
112
- on-disk order. Axes order should follow the canonical order
113
- (t, c, z, y, x). Note that a different order can still be used
114
- to store the data on disk if NGFF version used is supports it.
115
- pixel_sizes: The pixel sizes for the z, y, x axes.
116
- xy_scaling_factor: The scaling factor for the y and x axes, to be used
117
- for the pyramid building.
118
- z_scaling_factor: The scaling factor for the z axis, to be used for the
119
- pyramid building. Note that several tools may not support scaling
120
- different than 1.0 for the z axis.
121
- time_spacing: The time spacing (If the time axis is present).
122
- time_units: The units of the time spacing (If the time axis is present).
123
- levels: The number of levels in the pyramid or the list of paths.
124
- name: The name of the metadata.
125
- channel_labels: The names of the channels.
126
- channel_wavelengths: The wavelengths of the channels.
127
- channel_visualization: The visualization of the channels.
128
- omero_kwargs: The additional omero kwargs.
129
- version: The version of NGFF metadata.
130
-
131
- """
132
- datasets = _create_multiscale_meta(
133
- on_disk_axis=on_disk_axis,
134
- pixel_sizes=pixel_sizes,
135
- xy_scaling_factor=xy_scaling_factor,
136
- z_scaling_factor=z_scaling_factor,
137
- time_spacing=time_spacing,
138
- time_units=time_units,
139
- levels=levels,
140
- )
141
-
142
- if channel_labels is None:
143
- return ImageMeta(
144
- version=version,
145
- name=name,
146
- datasets=datasets,
147
- omero=None,
148
- )
149
-
150
- if channel_wavelengths is None:
151
- channel_wavelengths = channel_labels
152
- else:
153
- if len(channel_wavelengths) != len(channel_labels):
154
- raise ValueError(
155
- "The number of channel wavelengths must match the number of "
156
- "channel labels."
157
- )
158
-
159
- if channel_visualization is None:
160
- channel_visualization = [
161
- ChannelVisualisation(color=label) for label in channel_labels
162
- ]
163
- else:
164
- if len(channel_visualization) != len(channel_labels):
165
- raise ValueError(
166
- "The number of channel kwargs must match the number of channel labels."
167
- )
168
-
169
- channels = []
170
- for label, wavelengths, ch_visualization in zip(
171
- channel_labels, channel_wavelengths, channel_visualization, strict=True
172
- ):
173
- channels.append(
174
- Channel(
175
- label=label,
176
- wavelength_id=wavelengths,
177
- channel_visualisation=ch_visualization,
178
- )
179
- )
180
-
181
- omero_kwargs = {} if omero_kwargs is None else omero_kwargs
182
- omero = Omero(channels=channels, **omero_kwargs)
183
-
184
- return ImageMeta(
185
- version=version,
186
- name=name,
187
- datasets=datasets,
188
- omero=omero,
189
- )
190
-
191
-
192
- def create_label_metadata(
193
- on_disk_axis: Collection[str] = ("t", "c", "z", "y", "x"),
194
- pixel_sizes: PixelSize | None = None,
195
- xy_scaling_factor: float = 2.0,
196
- z_scaling_factor: float = 1.0,
197
- time_spacing: float = 1.0,
198
- time_units: TimeUnits | str | None = None,
199
- levels: int | list[str] = 5,
200
- name: str | None = None,
201
- version: str = "0.4",
202
- ) -> LabelMeta:
203
- """Create a label metadata object from scratch.
204
-
205
- Args:
206
- on_disk_axis: The names of the axes. The order will correspond to the
207
- on-disk order. Axes order should follow the canonical order
208
- (t, c, z, y, x). Note that a different order can still be used
209
- to store the data on disk if NGFF version used is supports it.
210
- pixel_sizes: The pixel sizes for the z, y, x axes.
211
- xy_scaling_factor: The scaling factor for the y and x axes, to be used
212
- for the pyramid building.
213
- z_scaling_factor: The scaling factor for the z axis, to be used for the
214
- pyramid building. Note that several tools may not support scaling
215
- different than 1.0 for the z axis.
216
- time_spacing: The time spacing (If the time axis is present).
217
- time_units: The units of the time spacing (If the time axis is present).
218
- levels: The number of levels in the pyramid or the list of paths.
219
- name: The name of the metadata.
220
- version: The version of NGFF metadata.
221
- """
222
- datasets = _create_multiscale_meta(
223
- on_disk_axis=on_disk_axis,
224
- pixel_sizes=pixel_sizes,
225
- xy_scaling_factor=xy_scaling_factor,
226
- z_scaling_factor=z_scaling_factor,
227
- time_spacing=time_spacing,
228
- time_units=time_units,
229
- levels=levels,
230
- )
231
- return LabelMeta(
232
- version=version,
233
- name=name,
234
- datasets=datasets,
235
- )
@@ -1,6 +0,0 @@
1
- """Pydantic Models related to OME-NGFF 0.4 specs."""
2
-
3
- from ngio.ngff_meta.v04.specs import NgffImageMeta04
4
- from ngio.ngff_meta.v04.zarr_utils import NgffImageMetaZarrHandlerV04
5
-
6
- __all__ = ["NgffImageMetaZarrHandlerV04", "NgffImageMeta04"]
@@ -1,158 +0,0 @@
1
- """Implementations of the OME-NGFF 0.4 specs using Pydantic models.
2
-
3
- See https://ngff.openmicroscopy.org/0.4/ for detailed specs.
4
- """
5
-
6
- from typing import Literal
7
-
8
- from pydantic import BaseModel, Field, field_validator
9
-
10
- from ngio.utils._pydantic_utils import (
11
- SKIP_NGFF_VALIDATION,
12
- BaseWithExtraFields,
13
- unique_items_validator,
14
- )
15
-
16
-
17
- class Window04(BaseModel):
18
- """Model for `Channels.Window`."""
19
-
20
- max: int | float
21
- min: int | float
22
- start: int | float
23
- end: int | float
24
-
25
-
26
- class Channel04(BaseWithExtraFields):
27
- """Model for `Omero.channels`."""
28
-
29
- label: str
30
- color: str
31
- active: bool = True
32
- window: Window04 | None = None
33
-
34
-
35
- class Omero04(BaseWithExtraFields):
36
- """Model for `NgffImageMeta.Omero`."""
37
-
38
- channels: list[Channel04]
39
- version: Literal["0.4"] = "0.4"
40
-
41
-
42
- class Axis04(BaseModel):
43
- """Model for `Multiscale.axes` elements."""
44
-
45
- name: str
46
- type: str
47
- unit: str | None = None
48
-
49
-
50
- class ScaleCoordinateTransformation04(BaseModel):
51
- """Model for a scale transformation.
52
-
53
- This corresponds to scale-type elements of
54
- `Dataset.coordinateTransformations` or
55
- `Multiscale.coordinateTransformations`.
56
- """
57
-
58
- type: Literal["scale"]
59
- scale: list[float] = Field(..., min_length=2)
60
-
61
-
62
- class TranslationCoordinateTransformation04(BaseModel):
63
- """Model for a translation transformation.
64
-
65
- This corresponds to translation-type elements of
66
- `Dataset.coordinateTransformations` or
67
- `Multiscale.coordinateTransformations`.
68
- """
69
-
70
- type: Literal["translation"]
71
- translation: list[float] = Field(..., min_length=2)
72
-
73
-
74
- Transformation04 = (
75
- ScaleCoordinateTransformation04 | TranslationCoordinateTransformation04
76
- )
77
-
78
-
79
- class Dataset04(BaseModel):
80
- """Model for `Multiscale.datasets` elements."""
81
-
82
- path: str
83
- coordinateTransformations: list[Transformation04] = Field(
84
- ..., min_length=1, max_length=2
85
- )
86
-
87
- @field_validator("coordinateTransformations")
88
- @classmethod
89
- def _check_scale_exists(cls, v):
90
- # check if at least one scale transformation exists
91
- if SKIP_NGFF_VALIDATION:
92
- return v
93
-
94
- num_scale = sum(
95
- 1 for item in v if isinstance(item, ScaleCoordinateTransformation04)
96
- )
97
- if num_scale != 1:
98
- raise ValueError("Exactly one scale transformation is required.")
99
-
100
- num_translation = sum(
101
- 1 for item in v if isinstance(item, TranslationCoordinateTransformation04)
102
- )
103
- if num_translation > 1:
104
- raise ValueError("At most one translation transformation is allowed.")
105
-
106
- return v
107
-
108
-
109
- class Multiscale04(BaseModel):
110
- """Model for `NgffImageMeta.multiscales` elements."""
111
-
112
- name: str | None = None
113
- datasets: list[Dataset04] = Field(..., min_length=1)
114
- version: Literal["0.4"] | None = "0.4"
115
- axes: list[Axis04] = Field(..., max_length=5, min_length=2)
116
- coordinateTransformations: list[Transformation04] | None = None
117
- _check_unique = field_validator("axes")(unique_items_validator)
118
-
119
- @field_validator("axes")
120
- @classmethod
121
- def _check_axes_order(cls, v):
122
- # check if the order of axes is correct
123
- if SKIP_NGFF_VALIDATION:
124
- return v
125
-
126
- axes_types = [axis.type for axis in v]
127
-
128
- if "time" in axes_types:
129
- time_position = axes_types.index("time")
130
- if time_position != 0:
131
- raise ValueError("Time axis should be the first axis.")
132
-
133
- axes_types = axes_types.pop(0)
134
-
135
- if len(axes_types) < 2:
136
- raise ValueError("At least two spatial axes are required.")
137
-
138
- reversed_axes_types = axes_types[::-1]
139
-
140
- channel_type_flag = False
141
- for ax_type in reversed_axes_types:
142
- if ax_type == "space":
143
- if channel_type_flag:
144
- raise ValueError("Channel axis should precede spatial axes.")
145
- else:
146
- channel_type_flag = True
147
- return v
148
-
149
-
150
- class NgffImageMeta04(BaseWithExtraFields):
151
- """Model for the metadata of a NGFF image."""
152
-
153
- multiscales: list[Multiscale04] = Field(
154
- ...,
155
- min_length=1,
156
- )
157
- omero: Omero04 | None = None
158
- _check_unique = field_validator("multiscales")(unique_items_validator)