ngio 0.1.6__py3-none-any.whl → 0.2.0a2__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 +223 -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 +389 -0
  16. ngio/images/label.py +236 -0
  17. ngio/images/omezarr_container.py +535 -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.0a2.dist-info}/METADATA +18 -39
  50. ngio-0.2.0a2.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.0a2.dist-info}/WHEEL +0 -0
  84. {ngio-0.1.6.dist-info → ngio-0.2.0a2.dist-info}/licenses/LICENSE +0 -0
@@ -1,410 +0,0 @@
1
- """A module to handle OME-NGFF images stored in Zarr format."""
2
-
3
- import builtins
4
- from typing import Any, Literal
5
-
6
- import zarr
7
-
8
- from ngio.core.image_handler import Image
9
- from ngio.core.image_like_handler import ImageLike
10
- from ngio.core.roi import WorldCooROI
11
- from ngio.core.utils import create_empty_ome_zarr_label
12
- from ngio.io import AccessModeLiteral, StoreLike, StoreOrGroup
13
- from ngio.ngff_meta.fractal_image_meta import LabelMeta, PixelSize
14
- from ngio.utils._common_types import ArrayLike
15
-
16
-
17
- class Label(ImageLike):
18
- """A class to handle OME-NGFF images stored in Zarr format.
19
-
20
- This class provides methods to load label data and metadata from
21
- an OME-Zarr file.
22
- """
23
-
24
- def __init__(
25
- self,
26
- store: StoreOrGroup,
27
- *,
28
- name: str,
29
- path: str | None = None,
30
- idx: int | None = None,
31
- pixel_size: PixelSize | None = None,
32
- highest_resolution: bool = False,
33
- strict: bool = True,
34
- cache: bool = True,
35
- mode: AccessModeLiteral = "r+",
36
- label_group: Any = None,
37
- ) -> None:
38
- """Initialize the the Label Object.
39
-
40
- Note: Only one of `path`, `idx`, 'pixel_size' or 'highest_resolution'
41
- should be provided.
42
-
43
- Args:
44
- store (StoreOrGroup): The Zarr store or group containing the image data.
45
- name (str): The name of the label.
46
- path (str | None): The path to the level.
47
- idx (int | None): The index of the level.
48
- pixel_size (PixelSize | None): The pixel size of the level.
49
- highest_resolution (bool): Whether to get the highest resolution level.
50
- strict (bool): Whether to raise an error where a pixel size is not found
51
- to match the requested "pixel_size".
52
- cache (bool): Whether to cache the metadata.
53
- mode (AccessModeLiteral): The mode to open the group in.
54
- label_group: The group containing the labels.
55
- """
56
- super().__init__(
57
- store,
58
- path=path,
59
- idx=idx,
60
- pixel_size=pixel_size,
61
- highest_resolution=highest_resolution,
62
- strict=strict,
63
- meta_mode="label",
64
- cache=cache,
65
- mode=mode,
66
- _label_group=label_group,
67
- )
68
-
69
- self._name = name
70
-
71
- def __repr__(self) -> str:
72
- """Return the string representation of the label."""
73
- name = "Label("
74
- len_name = len(name)
75
- return (
76
- f"{name}"
77
- f"group_path={self.group_path}, \n"
78
- f"{' ':>{len_name}}path={self.path},\n"
79
- f"{' ':>{len_name}}name={self.name},\n"
80
- f"{' ':>{len_name}}{self.pixel_size},\n"
81
- f"{' ':>{len_name}}{self.dimensions},\n"
82
- ")"
83
- )
84
-
85
- @property
86
- def name(self) -> str:
87
- """Return the name of the label."""
88
- return self._name
89
-
90
- @property
91
- def metadata(self) -> LabelMeta:
92
- """Return the metadata of the image."""
93
- meta = super().metadata
94
- assert isinstance(meta, LabelMeta)
95
- return meta
96
-
97
- def get_array_from_roi(
98
- self,
99
- roi: WorldCooROI,
100
- t: int | slice | None = None,
101
- mode: Literal["numpy"] | Literal["dask"] = "numpy",
102
- preserve_dimensions: bool = False,
103
- ) -> ArrayLike:
104
- """Return the label data from a region of interest (ROI).
105
-
106
- Args:
107
- roi (WorldCooROI): The region of interest.
108
- t (int | slice | None): The time index or slice.
109
- mode (str): The mode to return the data.
110
- preserve_dimensions (bool): Whether to preserve the dimensions of the data.
111
- """
112
- return self._get_array_from_roi(
113
- roi=roi, t=t, c=None, mode=mode, preserve_dimensions=preserve_dimensions
114
- )
115
-
116
- def set_array_from_roi(
117
- self,
118
- patch: ArrayLike,
119
- roi: WorldCooROI,
120
- t: int | slice | None = None,
121
- preserve_dimensions: bool = False,
122
- ) -> None:
123
- """Set the label data from a region of interest (ROI).
124
-
125
- Args:
126
- roi (WorldCooROI): The region of interest.
127
- patch (ArrayLike): The patch to set.
128
- t (int | slice | None): The time index or slice.
129
- preserve_dimensions (bool): Whether to preserve the dimensions of the data.
130
- """
131
- return self._set_array_from_roi(
132
- patch=patch, roi=roi, t=t, c=None, preserve_dimensions=preserve_dimensions
133
- )
134
-
135
- def get_array(
136
- self,
137
- x: int | slice | None = None,
138
- y: int | slice | None = None,
139
- z: int | slice | None = None,
140
- t: int | slice | None = None,
141
- mode: Literal["numpy"] | Literal["dask"] = "numpy",
142
- preserve_dimensions: bool = False,
143
- ) -> ArrayLike:
144
- """Return the label data.
145
-
146
- Args:
147
- x (int | slice | None): The x index or slice.
148
- y (int | slice | None): The y index or slice.
149
- z (int | slice | None): The z index or slice.
150
- t (int | slice | None): The time index or slice.
151
- mode (str): The mode to return the data.
152
- preserve_dimensions (bool): Whether to preserve the dimensions of the data.
153
- """
154
- return self._get_array(
155
- x=x,
156
- y=y,
157
- z=z,
158
- t=t,
159
- c=None,
160
- mode=mode,
161
- preserve_dimensions=preserve_dimensions,
162
- )
163
-
164
- def set_array(
165
- self,
166
- patch: ArrayLike,
167
- x: int | slice | None = None,
168
- y: int | slice | None = None,
169
- z: int | slice | None = None,
170
- t: int | slice | None = None,
171
- preserve_dimensions: bool = False,
172
- ) -> None:
173
- """Set the label data in the zarr array.
174
-
175
- Args:
176
- patch (ArrayLike): The patch to set.
177
- x (int | slice | None): The x index or slice.
178
- y (int | slice | None): The y index or slice.
179
- z (int | slice | None): The z index or slice.
180
- t (int | slice | None): The time index or slice.
181
- preserve_dimensions (bool): Whether to preserve the dimensions of the data.
182
- """
183
- return self._set_array(
184
- patch=patch,
185
- x=x,
186
- y=y,
187
- z=z,
188
- t=t,
189
- c=None,
190
- preserve_dimensions=preserve_dimensions,
191
- )
192
-
193
- def mask(
194
- self,
195
- roi: WorldCooROI,
196
- t: int | slice | None = None,
197
- mode: Literal["numpy"] = "numpy",
198
- preserve_dimensions: bool = False,
199
- ) -> ArrayLike:
200
- """Return the image data from a region of interest (ROI).
201
-
202
- Args:
203
- roi (WorldCooROI): The region of interest.
204
- t (int | slice | None): The time index or slice.
205
- c (int | slice | None): The channel index or slice.
206
- mask_mode (str): Masking mode
207
- mode (str): The mode to return the data.
208
- preserve_dimensions (bool): Whether to preserve the dimensions of the data.
209
- """
210
- mask = self._get_array_from_roi(
211
- roi=roi, t=t, mode=mode, preserve_dimensions=preserve_dimensions
212
- )
213
-
214
- label = roi.infos.get("label", None)
215
- if label is None:
216
- raise ValueError(
217
- "Label not found in the ROI. Please provide a valid ROI Object."
218
- )
219
- mask = mask == label
220
- return mask
221
-
222
- def consolidate(self) -> None:
223
- """Consolidate the label group.
224
-
225
- This method consolidates the label group by
226
- filling all other pyramid levels with the data
227
- """
228
- return self._consolidate(order=0)
229
-
230
-
231
- class LabelGroup:
232
- """A class to handle the /labels group in an OME-NGFF file."""
233
-
234
- def __init__(
235
- self,
236
- group: StoreLike | zarr.Group,
237
- image_ref: Image | None = None,
238
- cache: bool = True,
239
- mode: AccessModeLiteral = "r+",
240
- ) -> None:
241
- """Initialize the LabelGroupHandler."""
242
- self._mode = mode
243
- if not isinstance(group, zarr.Group):
244
- group = zarr.open_group(group, mode=self._mode)
245
-
246
- label_group = group.get("labels", None)
247
- if label_group is None and not group.read_only:
248
- label_group = group.create_group("labels")
249
- label_group.attrs["labels"] = [] # initialize the labels attribute
250
-
251
- assert isinstance(label_group, zarr.Group) or label_group is None
252
- self._label_group = label_group
253
-
254
- self._image_ref = image_ref
255
- self._metadata_cache = cache
256
-
257
- def list(self) -> list[str]:
258
- """List all labels in the group."""
259
- if self._label_group is None:
260
- return []
261
- _labels = self._label_group.attrs.get("labels", [])
262
- assert isinstance(_labels, list)
263
- return _labels
264
-
265
- def num_levels(self, name: str) -> int:
266
- """Get the number of levels in the labels."""
267
- label = self.get_label(name)
268
- return label.metadata.num_levels
269
-
270
- def levels_paths(self, name: str) -> list:
271
- """Get the paths of the levels in the labels."""
272
- label = self.get_label(name)
273
- return label.metadata.levels_paths
274
-
275
- def get_label(
276
- self,
277
- name: str,
278
- path: str | None = None,
279
- pixel_size: PixelSize | None = None,
280
- highest_resolution: bool = True,
281
- ) -> Label:
282
- """Geta a Label from the group.
283
-
284
- Args:
285
- name (str): The name of the label.
286
- path (str | None, optional): The path to the level.
287
- pixel_size (tuple[float, ...] | list[float] | None, optional): The pixel
288
- size of the level.
289
- highest_resolution (bool, optional): Whether to get the highest
290
- resolution level
291
- """
292
- if self._label_group is None:
293
- raise ValueError("No labels found in the group.")
294
-
295
- if name not in self.list():
296
- raise ValueError(f"Label {name} not found in the group.")
297
-
298
- if path is not None or pixel_size is not None:
299
- highest_resolution = False
300
-
301
- return Label(
302
- store=self._label_group[name],
303
- name=name,
304
- path=path,
305
- pixel_size=pixel_size,
306
- highest_resolution=highest_resolution,
307
- cache=self._metadata_cache,
308
- )
309
-
310
- def derive(
311
- self,
312
- name: str,
313
- reference: ImageLike | None = None,
314
- levels: int | builtins.list[str] = 5,
315
- overwrite: bool = False,
316
- **kwargs: dict,
317
- ) -> Label:
318
- """Derive a new label from an existing label.
319
-
320
- Args:
321
- name (str): The name of the new label.
322
- reference (ImageLike | None): The reference image to use for the new label.
323
- levels (int | list[str]): The number of levels to create or
324
- a list of paths names.
325
- overwrite (bool): If True, the label will be overwritten if it exists.
326
- Default is False.
327
- **kwargs: Additional keyword arguments to pass to the new label.
328
- """
329
- if self._label_group is None:
330
- raise ValueError("Cannot derive a new label. Group is empty or read-only.")
331
-
332
- list_of_labels = self.list()
333
-
334
- if overwrite and name in list_of_labels:
335
- self._label_group.attrs["label"] = [
336
- label for label in list_of_labels if label != name
337
- ]
338
- elif not overwrite and name in list_of_labels:
339
- raise ValueError(f"Label {name} already exists in the group.")
340
-
341
- # create the new label
342
- new_label_group = self._label_group.create_group(name, overwrite=overwrite)
343
-
344
- ref_0 = self._image_ref if reference is None else reference
345
- assert isinstance(ref_0, ImageLike)
346
-
347
- if isinstance(levels, int):
348
- paths = [str(i) for i in range(levels)]
349
- elif isinstance(levels, list):
350
- if not all(isinstance(level, str) for level in levels):
351
- raise ValueError(f"All levels must be strings. Got: {levels}")
352
- paths = levels
353
-
354
- on_disk_ch_index = ref_0.find_axis("c")
355
- metadata = ref_0.metadata
356
-
357
- if on_disk_ch_index is None:
358
- on_disk_shape = ref_0.on_disk_shape
359
- chunks = ref_0.on_disk_array.chunks
360
- else:
361
- metadata = metadata.remove_axis("c")
362
- on_disk_shape = (
363
- ref_0.on_disk_shape[:on_disk_ch_index]
364
- + ref_0.on_disk_shape[on_disk_ch_index + 1 :]
365
- )
366
- chunks = (
367
- ref_0.on_disk_array.chunks[:on_disk_ch_index]
368
- + ref_0.on_disk_array.chunks[on_disk_ch_index + 1 :]
369
- )
370
- dataset = metadata.get_dataset(path=paths[0])
371
-
372
- default_kwargs = {
373
- "store": new_label_group,
374
- "shape": on_disk_shape,
375
- "chunks": chunks,
376
- "dtype": ref_0.on_disk_array.dtype,
377
- "on_disk_axis": dataset.on_disk_axes_names,
378
- "pixel_sizes": dataset.pixel_size,
379
- "xy_scaling_factor": metadata.xy_scaling_factor,
380
- "z_scaling_factor": metadata.z_scaling_factor,
381
- "time_spacing": dataset.time_spacing,
382
- "time_units": dataset.time_axis_unit,
383
- "levels": paths,
384
- "name": name,
385
- "overwrite": overwrite,
386
- "version": metadata.version,
387
- }
388
-
389
- default_kwargs.update(kwargs)
390
-
391
- create_empty_ome_zarr_label(
392
- store=new_label_group,
393
- on_disk_shape=on_disk_shape,
394
- chunks=chunks,
395
- dtype=ref_0.on_disk_array.dtype,
396
- on_disk_axis=dataset.on_disk_axes_names,
397
- pixel_sizes=dataset.pixel_size,
398
- xy_scaling_factor=metadata.xy_scaling_factor,
399
- z_scaling_factor=metadata.z_scaling_factor,
400
- time_spacing=dataset.time_spacing,
401
- time_units=dataset.time_axis_unit,
402
- levels=paths,
403
- name=name,
404
- overwrite=overwrite,
405
- version=metadata.version,
406
- )
407
-
408
- if name not in self.list():
409
- self._label_group.attrs["labels"] = [*list_of_labels, name]
410
- return self.get_label(name)