ngio 0.4.0a3__py3-none-any.whl → 0.4.0a4__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.
- ngio/__init__.py +1 -2
- ngio/common/__init__.py +2 -51
- ngio/common/_dimensions.py +223 -64
- ngio/common/_pyramid.py +42 -23
- ngio/common/_roi.py +47 -411
- ngio/common/_zoom.py +32 -7
- ngio/experimental/iterators/_abstract_iterator.py +2 -2
- ngio/experimental/iterators/_feature.py +9 -14
- ngio/experimental/iterators/_image_processing.py +17 -27
- ngio/experimental/iterators/_rois_utils.py +4 -4
- ngio/experimental/iterators/_segmentation.py +37 -53
- ngio/images/_abstract_image.py +135 -93
- ngio/images/_create.py +16 -0
- ngio/images/_create_synt_container.py +10 -0
- ngio/images/_image.py +33 -9
- ngio/images/_label.py +24 -3
- ngio/images/_masked_image.py +60 -81
- ngio/images/_ome_zarr_container.py +33 -0
- ngio/io_pipes/__init__.py +49 -0
- ngio/io_pipes/_io_pipes.py +286 -0
- ngio/io_pipes/_io_pipes_masked.py +481 -0
- ngio/io_pipes/_io_pipes_roi.py +143 -0
- ngio/io_pipes/_io_pipes_utils.py +299 -0
- ngio/io_pipes/_match_shape.py +376 -0
- ngio/io_pipes/_ops_axes.py +146 -0
- ngio/io_pipes/_ops_slices.py +218 -0
- ngio/io_pipes/_ops_transforms.py +104 -0
- ngio/io_pipes/_zoom_transform.py +175 -0
- ngio/ome_zarr_meta/__init__.py +6 -2
- ngio/ome_zarr_meta/ngio_specs/__init__.py +6 -4
- ngio/ome_zarr_meta/ngio_specs/_axes.py +182 -70
- ngio/ome_zarr_meta/ngio_specs/_dataset.py +47 -121
- ngio/ome_zarr_meta/ngio_specs/_ngio_image.py +30 -22
- ngio/ome_zarr_meta/ngio_specs/_pixel_size.py +17 -1
- ngio/ome_zarr_meta/v04/_v04_spec_utils.py +33 -30
- ngio/resources/20200812-CardiomyocyteDifferentiation14-Cycle1_B03/nuclei.png +0 -0
- ngio/resources/__init__.py +1 -0
- ngio/resources/resource_model.py +1 -0
- ngio/{common/transforms → transforms}/__init__.py +1 -1
- ngio/transforms/_zoom.py +19 -0
- ngio/utils/_zarr_utils.py +5 -1
- {ngio-0.4.0a3.dist-info → ngio-0.4.0a4.dist-info}/METADATA +1 -1
- ngio-0.4.0a4.dist-info/RECORD +83 -0
- ngio/common/_array_io_pipes.py +0 -554
- ngio/common/_array_io_utils.py +0 -508
- ngio/common/transforms/_label.py +0 -12
- ngio/common/transforms/_zoom.py +0 -109
- ngio-0.4.0a3.dist-info/RECORD +0 -76
- {ngio-0.4.0a3.dist-info → ngio-0.4.0a4.dist-info}/WHEEL +0 -0
- {ngio-0.4.0a3.dist-info → ngio-0.4.0a4.dist-info}/licenses/LICENSE +0 -0
ngio/images/_abstract_image.py
CHANGED
|
@@ -8,24 +8,26 @@ import numpy as np
|
|
|
8
8
|
import zarr
|
|
9
9
|
|
|
10
10
|
from ngio.common import (
|
|
11
|
-
ArrayLike,
|
|
12
11
|
Dimensions,
|
|
12
|
+
InterpolationOrder,
|
|
13
13
|
Roi,
|
|
14
14
|
RoiPixels,
|
|
15
|
+
consolidate_pyramid,
|
|
16
|
+
)
|
|
17
|
+
from ngio.io_pipes import (
|
|
18
|
+
DaskGetter,
|
|
19
|
+
DaskRoiGetter,
|
|
20
|
+
DaskRoiSetter,
|
|
21
|
+
DaskSetter,
|
|
22
|
+
NumpyGetter,
|
|
23
|
+
NumpyRoiGetter,
|
|
24
|
+
NumpyRoiSetter,
|
|
25
|
+
NumpySetter,
|
|
15
26
|
SlicingInputType,
|
|
16
27
|
TransformProtocol,
|
|
17
|
-
build_dask_getter,
|
|
18
|
-
build_dask_setter,
|
|
19
|
-
build_numpy_getter,
|
|
20
|
-
build_numpy_setter,
|
|
21
|
-
build_roi_dask_getter,
|
|
22
|
-
build_roi_dask_setter,
|
|
23
|
-
build_roi_numpy_getter,
|
|
24
|
-
build_roi_numpy_setter,
|
|
25
|
-
consolidate_pyramid,
|
|
26
28
|
)
|
|
27
29
|
from ngio.ome_zarr_meta import (
|
|
28
|
-
|
|
30
|
+
AxesHandler,
|
|
29
31
|
Dataset,
|
|
30
32
|
ImageMetaHandler,
|
|
31
33
|
LabelMetaHandler,
|
|
@@ -61,29 +63,50 @@ class AbstractImage(Generic[_image_handler]):
|
|
|
61
63
|
self._group_handler = group_handler
|
|
62
64
|
self._meta_handler = meta_handler
|
|
63
65
|
|
|
64
|
-
self._dataset = self._meta_handler.meta.get_dataset(path=path)
|
|
65
|
-
self._pixel_size = self._dataset.pixel_size
|
|
66
|
-
|
|
67
66
|
try:
|
|
68
|
-
self._zarr_array = self._group_handler.get_array(self.
|
|
67
|
+
self._zarr_array = self._group_handler.get_array(self._path)
|
|
69
68
|
except NgioFileExistsError as e:
|
|
70
69
|
raise NgioFileExistsError(f"Could not find the dataset at {path}.") from e
|
|
71
70
|
|
|
72
|
-
self._dimensions = Dimensions(
|
|
73
|
-
shape=self._zarr_array.shape, axes_mapper=self._dataset.axes_mapper
|
|
74
|
-
)
|
|
75
|
-
|
|
76
|
-
self._axes_mapper = self._dataset.axes_mapper
|
|
77
|
-
|
|
78
71
|
def __repr__(self) -> str:
|
|
79
72
|
"""Return a string representation of the image."""
|
|
80
73
|
return f"Image(path={self.path}, {self.dimensions})"
|
|
81
74
|
|
|
75
|
+
@property
|
|
76
|
+
def path(self) -> str:
|
|
77
|
+
"""Return the path of the image."""
|
|
78
|
+
return self._path
|
|
79
|
+
|
|
82
80
|
@property
|
|
83
81
|
def meta_handler(self) -> _image_handler:
|
|
84
82
|
"""Return the metadata."""
|
|
85
83
|
return self._meta_handler
|
|
86
84
|
|
|
85
|
+
@property
|
|
86
|
+
def dataset(self) -> Dataset:
|
|
87
|
+
"""Return the dataset of the image."""
|
|
88
|
+
return self.meta_handler.meta.get_dataset(path=self.path)
|
|
89
|
+
|
|
90
|
+
@property
|
|
91
|
+
def dimensions(self) -> Dimensions:
|
|
92
|
+
"""Return the dimensions of the image."""
|
|
93
|
+
return Dimensions(shape=self.zarr_array.shape, dataset=self.dataset)
|
|
94
|
+
|
|
95
|
+
@property
|
|
96
|
+
def pixel_size(self) -> PixelSize:
|
|
97
|
+
"""Return the pixel size of the image."""
|
|
98
|
+
return self.dataset.pixel_size
|
|
99
|
+
|
|
100
|
+
@property
|
|
101
|
+
def axes_handler(self) -> AxesHandler:
|
|
102
|
+
"""Return the axes handler of the image."""
|
|
103
|
+
return self.dataset.axes_handler
|
|
104
|
+
|
|
105
|
+
@property
|
|
106
|
+
def axes(self) -> tuple[str, ...]:
|
|
107
|
+
"""Return the axes of the image."""
|
|
108
|
+
return self.dimensions.axes
|
|
109
|
+
|
|
87
110
|
@property
|
|
88
111
|
def zarr_array(self) -> zarr.Array:
|
|
89
112
|
"""Return the Zarr array."""
|
|
@@ -104,16 +127,6 @@ class AbstractImage(Generic[_image_handler]):
|
|
|
104
127
|
"""Return the chunks of the image."""
|
|
105
128
|
return self.zarr_array.chunks
|
|
106
129
|
|
|
107
|
-
@property
|
|
108
|
-
def dimensions(self) -> Dimensions:
|
|
109
|
-
"""Return the dimensions of the image."""
|
|
110
|
-
return self._dimensions
|
|
111
|
-
|
|
112
|
-
@property
|
|
113
|
-
def axes_mapper(self) -> AxesMapper:
|
|
114
|
-
"""Return the axes mapper of the image."""
|
|
115
|
-
return self._axes_mapper
|
|
116
|
-
|
|
117
130
|
@property
|
|
118
131
|
def is_3d(self) -> bool:
|
|
119
132
|
"""Return True if the image is 3D."""
|
|
@@ -147,31 +160,15 @@ class AbstractImage(Generic[_image_handler]):
|
|
|
147
160
|
@property
|
|
148
161
|
def space_unit(self) -> str | None:
|
|
149
162
|
"""Return the space unit of the image."""
|
|
150
|
-
return self.
|
|
163
|
+
return self.axes_handler.space_unit
|
|
151
164
|
|
|
152
165
|
@property
|
|
153
166
|
def time_unit(self) -> str | None:
|
|
154
167
|
"""Return the time unit of the image."""
|
|
155
|
-
return self.
|
|
156
|
-
|
|
157
|
-
@property
|
|
158
|
-
def pixel_size(self) -> PixelSize:
|
|
159
|
-
"""Return the pixel size of the image."""
|
|
160
|
-
return self._pixel_size
|
|
161
|
-
|
|
162
|
-
@property
|
|
163
|
-
def dataset(self) -> Dataset:
|
|
164
|
-
"""Return the dataset of the image."""
|
|
165
|
-
return self._dataset
|
|
166
|
-
|
|
167
|
-
@property
|
|
168
|
-
def path(self) -> str:
|
|
169
|
-
"""Return the path of the image."""
|
|
170
|
-
return self._dataset.path
|
|
168
|
+
return self.axes_handler.time_unit
|
|
171
169
|
|
|
172
170
|
def has_axis(self, axis: str) -> bool:
|
|
173
171
|
"""Return True if the image has the given axis."""
|
|
174
|
-
self.axes_mapper.get_index("x")
|
|
175
172
|
return self.dimensions.has_axis(axis)
|
|
176
173
|
|
|
177
174
|
def _get_as_numpy(
|
|
@@ -190,7 +187,7 @@ class AbstractImage(Generic[_image_handler]):
|
|
|
190
187
|
Returns:
|
|
191
188
|
The array of the region of interest.
|
|
192
189
|
"""
|
|
193
|
-
numpy_getter =
|
|
190
|
+
numpy_getter = NumpyGetter(
|
|
194
191
|
zarr_array=self.zarr_array,
|
|
195
192
|
dimensions=self.dimensions,
|
|
196
193
|
axes_order=axes_order,
|
|
@@ -217,11 +214,10 @@ class AbstractImage(Generic[_image_handler]):
|
|
|
217
214
|
Returns:
|
|
218
215
|
The array of the region of interest.
|
|
219
216
|
"""
|
|
220
|
-
numpy_roi_getter =
|
|
217
|
+
numpy_roi_getter = NumpyRoiGetter(
|
|
221
218
|
zarr_array=self.zarr_array,
|
|
222
219
|
dimensions=self.dimensions,
|
|
223
220
|
roi=roi,
|
|
224
|
-
pixel_size=self.pixel_size,
|
|
225
221
|
axes_order=axes_order,
|
|
226
222
|
transforms=transforms,
|
|
227
223
|
slicing_dict=slicing_kwargs,
|
|
@@ -241,7 +237,7 @@ class AbstractImage(Generic[_image_handler]):
|
|
|
241
237
|
transforms: The transforms to apply to the array.
|
|
242
238
|
**slicing_kwargs: The slices to get the array.
|
|
243
239
|
"""
|
|
244
|
-
dask_getter =
|
|
240
|
+
dask_getter = DaskGetter(
|
|
245
241
|
zarr_array=self.zarr_array,
|
|
246
242
|
dimensions=self.dimensions,
|
|
247
243
|
axes_order=axes_order,
|
|
@@ -265,11 +261,10 @@ class AbstractImage(Generic[_image_handler]):
|
|
|
265
261
|
transforms: The transforms to apply to the array.
|
|
266
262
|
**slicing_kwargs: The slices to get the array.
|
|
267
263
|
"""
|
|
268
|
-
roi_dask_getter =
|
|
264
|
+
roi_dask_getter = DaskRoiGetter(
|
|
269
265
|
zarr_array=self.zarr_array,
|
|
270
266
|
dimensions=self.dimensions,
|
|
271
267
|
roi=roi,
|
|
272
|
-
pixel_size=self.pixel_size,
|
|
273
268
|
axes_order=axes_order,
|
|
274
269
|
transforms=transforms,
|
|
275
270
|
slicing_dict=slicing_kwargs,
|
|
@@ -282,7 +277,7 @@ class AbstractImage(Generic[_image_handler]):
|
|
|
282
277
|
transforms: Sequence[TransformProtocol] | None = None,
|
|
283
278
|
mode: Literal["numpy", "dask"] = "numpy",
|
|
284
279
|
**slicing_kwargs: SlicingInputType,
|
|
285
|
-
) ->
|
|
280
|
+
) -> np.ndarray | da.Array:
|
|
286
281
|
"""Get a slice of the image.
|
|
287
282
|
|
|
288
283
|
Args:
|
|
@@ -305,7 +300,7 @@ class AbstractImage(Generic[_image_handler]):
|
|
|
305
300
|
)
|
|
306
301
|
else:
|
|
307
302
|
raise ValueError(
|
|
308
|
-
f"
|
|
303
|
+
f"Unsupported mode: {mode}. Supported modes are: numpy, dask."
|
|
309
304
|
)
|
|
310
305
|
|
|
311
306
|
def _get_roi(
|
|
@@ -315,7 +310,7 @@ class AbstractImage(Generic[_image_handler]):
|
|
|
315
310
|
transforms: Sequence[TransformProtocol] | None = None,
|
|
316
311
|
mode: Literal["numpy", "dask"] = "numpy",
|
|
317
312
|
**slice_kwargs: SlicingInputType,
|
|
318
|
-
) ->
|
|
313
|
+
) -> np.ndarray | da.Array:
|
|
319
314
|
"""Get a slice of the image.
|
|
320
315
|
|
|
321
316
|
Args:
|
|
@@ -339,12 +334,12 @@ class AbstractImage(Generic[_image_handler]):
|
|
|
339
334
|
)
|
|
340
335
|
else:
|
|
341
336
|
raise ValueError(
|
|
342
|
-
f"
|
|
337
|
+
f"Unsupported mode: {mode}. Supported modes are: numpy, dask."
|
|
343
338
|
)
|
|
344
339
|
|
|
345
340
|
def _set_array(
|
|
346
341
|
self,
|
|
347
|
-
patch:
|
|
342
|
+
patch: np.ndarray | da.Array,
|
|
348
343
|
axes_order: Sequence[str] | None = None,
|
|
349
344
|
transforms: Sequence[TransformProtocol] | None = None,
|
|
350
345
|
**slicing_kwargs: SlicingInputType,
|
|
@@ -359,7 +354,7 @@ class AbstractImage(Generic[_image_handler]):
|
|
|
359
354
|
|
|
360
355
|
"""
|
|
361
356
|
if isinstance(patch, np.ndarray):
|
|
362
|
-
numpy_setter =
|
|
357
|
+
numpy_setter = NumpySetter(
|
|
363
358
|
zarr_array=self.zarr_array,
|
|
364
359
|
dimensions=self.dimensions,
|
|
365
360
|
axes_order=axes_order,
|
|
@@ -369,7 +364,7 @@ class AbstractImage(Generic[_image_handler]):
|
|
|
369
364
|
numpy_setter(patch)
|
|
370
365
|
|
|
371
366
|
elif isinstance(patch, da.Array):
|
|
372
|
-
dask_setter =
|
|
367
|
+
dask_setter = DaskSetter(
|
|
373
368
|
zarr_array=self.zarr_array,
|
|
374
369
|
dimensions=self.dimensions,
|
|
375
370
|
axes_order=axes_order,
|
|
@@ -387,7 +382,7 @@ class AbstractImage(Generic[_image_handler]):
|
|
|
387
382
|
def _set_roi(
|
|
388
383
|
self,
|
|
389
384
|
roi: Roi | RoiPixels,
|
|
390
|
-
patch:
|
|
385
|
+
patch: np.ndarray | da.Array,
|
|
391
386
|
axes_order: Sequence[str] | None = None,
|
|
392
387
|
transforms: Sequence[TransformProtocol] | None = None,
|
|
393
388
|
**slicing_kwargs: SlicingInputType,
|
|
@@ -403,11 +398,10 @@ class AbstractImage(Generic[_image_handler]):
|
|
|
403
398
|
|
|
404
399
|
"""
|
|
405
400
|
if isinstance(patch, np.ndarray):
|
|
406
|
-
roi_numpy_setter =
|
|
401
|
+
roi_numpy_setter = NumpyRoiSetter(
|
|
407
402
|
zarr_array=self.zarr_array,
|
|
408
403
|
dimensions=self.dimensions,
|
|
409
404
|
roi=roi,
|
|
410
|
-
pixel_size=self.pixel_size,
|
|
411
405
|
axes_order=axes_order,
|
|
412
406
|
transforms=transforms,
|
|
413
407
|
slicing_dict=slicing_kwargs,
|
|
@@ -415,11 +409,10 @@ class AbstractImage(Generic[_image_handler]):
|
|
|
415
409
|
roi_numpy_setter(patch)
|
|
416
410
|
|
|
417
411
|
elif isinstance(patch, da.Array):
|
|
418
|
-
roi_dask_setter =
|
|
412
|
+
roi_dask_setter = DaskRoiSetter(
|
|
419
413
|
zarr_array=self.zarr_array,
|
|
420
414
|
dimensions=self.dimensions,
|
|
421
415
|
roi=roi,
|
|
422
|
-
pixel_size=self.pixel_size,
|
|
423
416
|
axes_order=axes_order,
|
|
424
417
|
transforms=transforms,
|
|
425
418
|
slicing_dict=slicing_kwargs,
|
|
@@ -434,7 +427,7 @@ class AbstractImage(Generic[_image_handler]):
|
|
|
434
427
|
|
|
435
428
|
def _consolidate(
|
|
436
429
|
self,
|
|
437
|
-
order:
|
|
430
|
+
order: InterpolationOrder = "linear",
|
|
438
431
|
mode: Literal["dask", "numpy", "coarsen"] = "dask",
|
|
439
432
|
) -> None:
|
|
440
433
|
"""Consolidate the image on disk.
|
|
@@ -445,14 +438,86 @@ class AbstractImage(Generic[_image_handler]):
|
|
|
445
438
|
"""
|
|
446
439
|
consolidate_image(image=self, order=order, mode=mode)
|
|
447
440
|
|
|
441
|
+
def roi(self, name: str | None = "image") -> Roi:
|
|
442
|
+
"""Return the ROI covering the entire image."""
|
|
443
|
+
dim_x = self.dimensions.get("x")
|
|
444
|
+
dim_y = self.dimensions.get("y")
|
|
445
|
+
assert dim_x is not None and dim_y is not None
|
|
446
|
+
dim_z = self.dimensions.get("z")
|
|
447
|
+
z = None if dim_z is None else 0
|
|
448
|
+
dim_t = self.dimensions.get("t")
|
|
449
|
+
t = None if dim_t is None else 0
|
|
450
|
+
roi_px = RoiPixels(
|
|
451
|
+
name=name,
|
|
452
|
+
x=0,
|
|
453
|
+
y=0,
|
|
454
|
+
z=z,
|
|
455
|
+
t=t,
|
|
456
|
+
x_length=dim_x,
|
|
457
|
+
y_length=dim_y,
|
|
458
|
+
z_length=dim_z,
|
|
459
|
+
t_length=dim_t,
|
|
460
|
+
)
|
|
461
|
+
return roi_px.to_roi(pixel_size=self.pixel_size)
|
|
462
|
+
|
|
448
463
|
def build_image_roi_table(self, name: str | None = "image") -> RoiTable:
|
|
449
464
|
"""Build the ROI table for an image."""
|
|
450
|
-
return
|
|
465
|
+
return RoiTable(rois=[self.roi(name=name)])
|
|
466
|
+
|
|
467
|
+
def require_dimensions_match(
|
|
468
|
+
self,
|
|
469
|
+
other: "AbstractImage",
|
|
470
|
+
allow_singleton: bool = False,
|
|
471
|
+
) -> None:
|
|
472
|
+
"""Assert that two images have matching spatial dimensions.
|
|
473
|
+
|
|
474
|
+
Args:
|
|
475
|
+
other: The other image to compare to.
|
|
476
|
+
allow_singleton: If True, allow singleton dimensions to be
|
|
477
|
+
compatible with non-singleton dimensions.
|
|
478
|
+
|
|
479
|
+
Raises:
|
|
480
|
+
NgioValueError: If the images do not have compatible dimensions.
|
|
481
|
+
"""
|
|
482
|
+
self.dimensions.require_dimensions_match(
|
|
483
|
+
other.dimensions, allow_singleton=allow_singleton
|
|
484
|
+
)
|
|
485
|
+
|
|
486
|
+
def require_axes_match(
|
|
487
|
+
self,
|
|
488
|
+
other: "AbstractImage",
|
|
489
|
+
) -> None:
|
|
490
|
+
"""Assert that two images have compatible axes.
|
|
491
|
+
|
|
492
|
+
Args:
|
|
493
|
+
other: The other image to compare to.
|
|
494
|
+
|
|
495
|
+
Raises:
|
|
496
|
+
NgioValueError: If the images do not have compatible axes.
|
|
497
|
+
"""
|
|
498
|
+
self.dimensions.require_axes_match(other.dimensions)
|
|
499
|
+
|
|
500
|
+
def require_can_be_rescaled(
|
|
501
|
+
self,
|
|
502
|
+
other: "AbstractImage",
|
|
503
|
+
) -> None:
|
|
504
|
+
"""Assert that two images can be rescaled to each other.
|
|
505
|
+
|
|
506
|
+
For this to be true, the images must have the same axes, and
|
|
507
|
+
the pixel sizes must be compatible (i.e. one can be scaled to the other).
|
|
508
|
+
|
|
509
|
+
Args:
|
|
510
|
+
other: The other image to compare to.
|
|
511
|
+
|
|
512
|
+
Raises:
|
|
513
|
+
NgioValueError: If the images cannot be scaled to each other.
|
|
514
|
+
"""
|
|
515
|
+
self.dimensions.require_can_be_rescaled(other.dimensions)
|
|
451
516
|
|
|
452
517
|
|
|
453
518
|
def consolidate_image(
|
|
454
519
|
image: AbstractImage,
|
|
455
|
-
order:
|
|
520
|
+
order: InterpolationOrder = "linear",
|
|
456
521
|
mode: Literal["dask", "numpy", "coarsen"] = "dask",
|
|
457
522
|
) -> None:
|
|
458
523
|
"""Consolidate the image on disk."""
|
|
@@ -465,26 +530,3 @@ def consolidate_image(
|
|
|
465
530
|
consolidate_pyramid(
|
|
466
531
|
source=image.zarr_array, targets=targets, order=order, mode=mode
|
|
467
532
|
)
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
def build_image_roi_table(image: AbstractImage, name: str | None = "image") -> RoiTable:
|
|
471
|
-
"""Build the ROI table for an image."""
|
|
472
|
-
dim_x = image.dimensions.get("x")
|
|
473
|
-
dim_y = image.dimensions.get("y")
|
|
474
|
-
assert dim_x is not None and dim_y is not None
|
|
475
|
-
dim_z = image.dimensions.get("z")
|
|
476
|
-
z = None if dim_z is None else 0
|
|
477
|
-
dim_t = image.dimensions.get("t")
|
|
478
|
-
t = None if dim_t is None else 0
|
|
479
|
-
image_roi = RoiPixels(
|
|
480
|
-
name=name,
|
|
481
|
-
x=0,
|
|
482
|
-
y=0,
|
|
483
|
-
z=z,
|
|
484
|
-
t=t,
|
|
485
|
-
x_length=dim_x,
|
|
486
|
-
y_length=dim_y,
|
|
487
|
-
z_length=dim_z,
|
|
488
|
-
t_length=dim_t,
|
|
489
|
-
)
|
|
490
|
-
return RoiTable(rois=[image_roi.to_roi(pixel_size=image.pixel_size)])
|
ngio/images/_create.py
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
from collections.abc import Sequence
|
|
4
4
|
from typing import TypeVar
|
|
5
5
|
|
|
6
|
+
from zarr.types import DIMENSION_SEPARATOR
|
|
7
|
+
|
|
6
8
|
from ngio.common._pyramid import init_empty_pyramid
|
|
7
9
|
from ngio.ome_zarr_meta import (
|
|
8
10
|
NgioImageMeta,
|
|
@@ -93,6 +95,8 @@ def create_empty_label_container(
|
|
|
93
95
|
name: str | None = None,
|
|
94
96
|
chunks: Sequence[int] | None = None,
|
|
95
97
|
dtype: str = "uint32",
|
|
98
|
+
dimension_separator: DIMENSION_SEPARATOR = "/",
|
|
99
|
+
compressor="default",
|
|
96
100
|
overwrite: bool = False,
|
|
97
101
|
version: NgffVersions = DefaultNgffVersion,
|
|
98
102
|
) -> ZarrGroupHandler:
|
|
@@ -120,6 +124,9 @@ def create_empty_label_container(
|
|
|
120
124
|
name (str | None, optional): The name of the image. Defaults to None.
|
|
121
125
|
chunks (Sequence[int] | None, optional): The chunk shape. If None the shape
|
|
122
126
|
is used. Defaults to None.
|
|
127
|
+
dimension_separator (DIMENSION_SEPARATOR): The separator to use for
|
|
128
|
+
dimensions. Defaults to "/".
|
|
129
|
+
compressor: The compressor to use. Defaults to "default".
|
|
123
130
|
dtype (str, optional): The data type of the image. Defaults to "uint16".
|
|
124
131
|
overwrite (bool, optional): Whether to overwrite an existing image.
|
|
125
132
|
Defaults to True.
|
|
@@ -164,6 +171,8 @@ def create_empty_label_container(
|
|
|
164
171
|
chunks=chunks,
|
|
165
172
|
dtype=dtype,
|
|
166
173
|
mode="a",
|
|
174
|
+
dimension_separator=dimension_separator,
|
|
175
|
+
compressor=compressor,
|
|
167
176
|
)
|
|
168
177
|
group_handler._mode = "r+"
|
|
169
178
|
return group_handler
|
|
@@ -184,6 +193,8 @@ def create_empty_image_container(
|
|
|
184
193
|
name: str | None = None,
|
|
185
194
|
chunks: Sequence[int] | None = None,
|
|
186
195
|
dtype: str = "uint16",
|
|
196
|
+
dimension_separator: DIMENSION_SEPARATOR = "/",
|
|
197
|
+
compressor="default",
|
|
187
198
|
overwrite: bool = False,
|
|
188
199
|
version: NgffVersions = DefaultNgffVersion,
|
|
189
200
|
) -> ZarrGroupHandler:
|
|
@@ -212,6 +223,9 @@ def create_empty_image_container(
|
|
|
212
223
|
chunks (Sequence[int] | None, optional): The chunk shape. If None the shape
|
|
213
224
|
is used. Defaults to None.
|
|
214
225
|
dtype (str, optional): The data type of the image. Defaults to "uint16".
|
|
226
|
+
dimension_separator (DIMENSION_SEPARATOR): The separator to use for
|
|
227
|
+
dimensions. Defaults to "/".
|
|
228
|
+
compressor: The compressor to use. Defaults to "default".
|
|
215
229
|
overwrite (bool, optional): Whether to overwrite an existing image.
|
|
216
230
|
Defaults to True.
|
|
217
231
|
version (str, optional): The version of the OME-Zarr specification.
|
|
@@ -254,6 +268,8 @@ def create_empty_image_container(
|
|
|
254
268
|
chunks=chunks,
|
|
255
269
|
dtype=dtype,
|
|
256
270
|
mode="a",
|
|
271
|
+
dimension_separator=dimension_separator,
|
|
272
|
+
compressor=compressor,
|
|
257
273
|
)
|
|
258
274
|
|
|
259
275
|
group_handler._mode = "r+"
|
|
@@ -4,6 +4,7 @@ from collections.abc import Sequence
|
|
|
4
4
|
|
|
5
5
|
import numpy as np
|
|
6
6
|
import PIL.Image
|
|
7
|
+
from zarr.types import DIMENSION_SEPARATOR
|
|
7
8
|
|
|
8
9
|
from ngio.common._synt_images_utils import fit_to_shape
|
|
9
10
|
from ngio.images._ome_zarr_container import OmeZarrContainer, create_ome_zarr_from_array
|
|
@@ -35,6 +36,8 @@ def create_synthetic_ome_zarr(
|
|
|
35
36
|
channel_colors: Sequence[str] | None = None,
|
|
36
37
|
channel_active: Sequence[bool] | None = None,
|
|
37
38
|
table_backend: TableBackend = DefaultTableBackend,
|
|
39
|
+
dimension_separator: DIMENSION_SEPARATOR = "/",
|
|
40
|
+
compressor="default",
|
|
38
41
|
overwrite: bool = False,
|
|
39
42
|
version: NgffVersions = DefaultNgffVersion,
|
|
40
43
|
) -> OmeZarrContainer:
|
|
@@ -63,6 +66,9 @@ def create_synthetic_ome_zarr(
|
|
|
63
66
|
channel_active (Sequence[bool] | None, optional): Whether the channels are
|
|
64
67
|
active. Defaults to None.
|
|
65
68
|
table_backend (TableBackend): Table backend to be used to store tables
|
|
69
|
+
dimension_separator (DIMENSION_SEPARATOR): The separator to use for
|
|
70
|
+
dimensions. Defaults to "/".
|
|
71
|
+
compressor: The compressor to use. Defaults to "default".
|
|
66
72
|
overwrite (bool, optional): Whether to overwrite an existing image.
|
|
67
73
|
Defaults to True.
|
|
68
74
|
version (NgffVersion, optional): The version of the OME-Zarr specification.
|
|
@@ -96,6 +102,8 @@ def create_synthetic_ome_zarr(
|
|
|
96
102
|
name=sample_info.name,
|
|
97
103
|
chunks=chunks,
|
|
98
104
|
overwrite=overwrite,
|
|
105
|
+
dimension_separator=dimension_separator,
|
|
106
|
+
compressor=compressor,
|
|
99
107
|
version=version,
|
|
100
108
|
)
|
|
101
109
|
|
|
@@ -108,6 +116,8 @@ def create_synthetic_ome_zarr(
|
|
|
108
116
|
label = ome_zarr.get_label(name=label_info.name)
|
|
109
117
|
|
|
110
118
|
ref_label = np.asarray(PIL.Image.open(label_info.label_path))
|
|
119
|
+
ref_label = ref_label.astype(label_info.dtype)
|
|
120
|
+
|
|
111
121
|
ref_label = fit_to_shape(
|
|
112
122
|
arr=ref_label,
|
|
113
123
|
out_shape=label.shape,
|
ngio/images/_image.py
CHANGED
|
@@ -6,17 +6,20 @@ from typing import Literal
|
|
|
6
6
|
import dask.array as da
|
|
7
7
|
import numpy as np
|
|
8
8
|
from pydantic import BaseModel, model_validator
|
|
9
|
+
from zarr.types import DIMENSION_SEPARATOR
|
|
9
10
|
|
|
10
11
|
from ngio.common import (
|
|
11
|
-
ArrayLike,
|
|
12
12
|
Dimensions,
|
|
13
|
+
InterpolationOrder,
|
|
13
14
|
Roi,
|
|
14
15
|
RoiPixels,
|
|
15
|
-
SlicingInputType,
|
|
16
|
-
TransformProtocol,
|
|
17
16
|
)
|
|
18
17
|
from ngio.images._abstract_image import AbstractImage
|
|
19
18
|
from ngio.images._create import create_empty_image_container
|
|
19
|
+
from ngio.io_pipes import (
|
|
20
|
+
SlicingInputType,
|
|
21
|
+
TransformProtocol,
|
|
22
|
+
)
|
|
20
23
|
from ngio.ome_zarr_meta import (
|
|
21
24
|
ImageMetaHandler,
|
|
22
25
|
NgioImageMeta,
|
|
@@ -269,7 +272,7 @@ class Image(AbstractImage[ImageMetaHandler]):
|
|
|
269
272
|
transforms: Sequence[TransformProtocol] | None = None,
|
|
270
273
|
mode: Literal["numpy", "dask"] = "numpy",
|
|
271
274
|
**slicing_kwargs: SlicingInputType,
|
|
272
|
-
) ->
|
|
275
|
+
) -> np.ndarray | da.Array:
|
|
273
276
|
"""Get the image as a zarr array.
|
|
274
277
|
|
|
275
278
|
Args:
|
|
@@ -299,7 +302,7 @@ class Image(AbstractImage[ImageMetaHandler]):
|
|
|
299
302
|
transforms: Sequence[TransformProtocol] | None = None,
|
|
300
303
|
mode: Literal["numpy", "dask"] = "numpy",
|
|
301
304
|
**slicing_kwargs: SlicingInputType,
|
|
302
|
-
) ->
|
|
305
|
+
) -> np.ndarray | da.Array:
|
|
303
306
|
"""Get the image as a zarr array for a region of interest.
|
|
304
307
|
|
|
305
308
|
Args:
|
|
@@ -328,7 +331,7 @@ class Image(AbstractImage[ImageMetaHandler]):
|
|
|
328
331
|
|
|
329
332
|
def set_array(
|
|
330
333
|
self,
|
|
331
|
-
patch:
|
|
334
|
+
patch: np.ndarray | da.Array,
|
|
332
335
|
channel_selection: ChannelSlicingInputType = None,
|
|
333
336
|
axes_order: Sequence[str] | None = None,
|
|
334
337
|
transforms: Sequence[TransformProtocol] | None = None,
|
|
@@ -354,7 +357,7 @@ class Image(AbstractImage[ImageMetaHandler]):
|
|
|
354
357
|
def set_roi(
|
|
355
358
|
self,
|
|
356
359
|
roi: Roi | RoiPixels,
|
|
357
|
-
patch:
|
|
360
|
+
patch: np.ndarray | da.Array,
|
|
358
361
|
channel_selection: ChannelSlicingInputType = None,
|
|
359
362
|
axes_order: Sequence[str] | None = None,
|
|
360
363
|
transforms: Sequence[TransformProtocol] | None = None,
|
|
@@ -383,7 +386,7 @@ class Image(AbstractImage[ImageMetaHandler]):
|
|
|
383
386
|
|
|
384
387
|
def consolidate(
|
|
385
388
|
self,
|
|
386
|
-
order:
|
|
389
|
+
order: InterpolationOrder = "linear",
|
|
387
390
|
mode: Literal["dask", "numpy", "coarsen"] = "dask",
|
|
388
391
|
) -> None:
|
|
389
392
|
"""Consolidate the label on disk."""
|
|
@@ -601,6 +604,8 @@ class ImagesContainer:
|
|
|
601
604
|
name: str | None = None,
|
|
602
605
|
chunks: Sequence[int] | None = None,
|
|
603
606
|
dtype: str | None = None,
|
|
607
|
+
dimension_separator: DIMENSION_SEPARATOR | None = None,
|
|
608
|
+
compressor: str | None = None,
|
|
604
609
|
overwrite: bool = False,
|
|
605
610
|
) -> "ImagesContainer":
|
|
606
611
|
"""Create an empty OME-Zarr image from an existing image.
|
|
@@ -615,6 +620,10 @@ class ImagesContainer:
|
|
|
615
620
|
axes_names (Sequence[str] | None): The axes names of the new image.
|
|
616
621
|
name (str | None): The name of the new image.
|
|
617
622
|
chunks (Sequence[int] | None): The chunk shape of the new image.
|
|
623
|
+
dimension_separator (DIMENSION_SEPARATOR | None): The separator to use for
|
|
624
|
+
dimensions. If None it will use the same as the reference image.
|
|
625
|
+
compressor (str | None): The compressor to use. If None it will use
|
|
626
|
+
the same as the reference image.
|
|
618
627
|
dtype (str | None): The data type of the new image.
|
|
619
628
|
overwrite (bool): Whether to overwrite an existing image.
|
|
620
629
|
|
|
@@ -714,6 +723,8 @@ def derive_image_container(
|
|
|
714
723
|
name: str | None = None,
|
|
715
724
|
chunks: Sequence[int] | None = None,
|
|
716
725
|
dtype: str | None = None,
|
|
726
|
+
dimension_separator: DIMENSION_SEPARATOR | None = None,
|
|
727
|
+
compressor=None,
|
|
717
728
|
overwrite: bool = False,
|
|
718
729
|
) -> ImagesContainer:
|
|
719
730
|
"""Create an empty OME-Zarr image from an existing image.
|
|
@@ -728,6 +739,10 @@ def derive_image_container(
|
|
|
728
739
|
axes_names (Sequence[str] | None): The axes names of the new image.
|
|
729
740
|
name (str | None): The name of the new image.
|
|
730
741
|
chunks (Sequence[int] | None): The chunk shape of the new image.
|
|
742
|
+
dimension_separator (DIMENSION_SEPARATOR | None): The separator to use for
|
|
743
|
+
dimensions. If None it will use the same as the reference image.
|
|
744
|
+
compressor: The compressor to use. If None it will use
|
|
745
|
+
the same as the reference image.
|
|
731
746
|
dtype (str | None): The data type of the new image.
|
|
732
747
|
overwrite (bool): Whether to overwrite an existing image.
|
|
733
748
|
|
|
@@ -749,7 +764,7 @@ def derive_image_container(
|
|
|
749
764
|
pixel_size = ref_image.pixel_size
|
|
750
765
|
|
|
751
766
|
if axes_names is None:
|
|
752
|
-
axes_names = ref_meta.
|
|
767
|
+
axes_names = ref_meta.axes_handler.axes_names
|
|
753
768
|
|
|
754
769
|
if len(axes_names) != len(shape):
|
|
755
770
|
raise NgioValidationError(
|
|
@@ -771,6 +786,13 @@ def derive_image_container(
|
|
|
771
786
|
|
|
772
787
|
if dtype is None:
|
|
773
788
|
dtype = ref_image.dtype
|
|
789
|
+
|
|
790
|
+
if dimension_separator is None:
|
|
791
|
+
dimension_separator = ref_image.zarr_array._dimension_separator # type: ignore
|
|
792
|
+
|
|
793
|
+
if compressor is None:
|
|
794
|
+
compressor = ref_image.zarr_array.compressor # type: ignore
|
|
795
|
+
|
|
774
796
|
handler = create_empty_image_container(
|
|
775
797
|
store=store,
|
|
776
798
|
shape=shape,
|
|
@@ -786,6 +808,8 @@ def derive_image_container(
|
|
|
786
808
|
name=name,
|
|
787
809
|
chunks=chunks,
|
|
788
810
|
dtype=dtype,
|
|
811
|
+
dimension_separator=dimension_separator, # type: ignore
|
|
812
|
+
compressor=compressor, # type: ignore
|
|
789
813
|
overwrite=overwrite,
|
|
790
814
|
version=ref_meta.version,
|
|
791
815
|
)
|