ngio 0.5.0b6__py3-none-any.whl → 0.5.1__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/common/_masking_roi.py +18 -5
- ngio/common/_pyramid.py +129 -30
- ngio/hcs/_plate.py +30 -24
- ngio/images/_abstract_image.py +182 -60
- ngio/images/_create_synt_container.py +5 -1
- ngio/images/_create_utils.py +69 -74
- ngio/images/_image.py +350 -86
- ngio/images/_label.py +39 -31
- ngio/images/_masked_image.py +2 -2
- ngio/images/_ome_zarr_container.py +263 -96
- ngio/io_pipes/_match_shape.py +10 -14
- ngio/io_pipes/_ops_slices.py +6 -4
- ngio/io_pipes/_ops_slices_utils.py +8 -7
- ngio/ome_zarr_meta/_meta_handlers.py +2 -26
- ngio/ome_zarr_meta/ngio_specs/__init__.py +2 -0
- ngio/ome_zarr_meta/ngio_specs/_axes.py +161 -58
- ngio/ome_zarr_meta/ngio_specs/_ngio_hcs.py +78 -32
- ngio/ome_zarr_meta/ngio_specs/_ngio_image.py +36 -0
- ngio/ome_zarr_meta/v04/_v04_spec.py +5 -22
- ngio/ome_zarr_meta/v05/_v05_spec.py +7 -23
- ngio/resources/__init__.py +1 -1
- ngio/resources/resource_model.py +1 -1
- ngio/tables/_tables_container.py +39 -7
- ngio/tables/v1/_roi_table.py +4 -4
- ngio/utils/_zarr_utils.py +8 -15
- {ngio-0.5.0b6.dist-info → ngio-0.5.1.dist-info}/METADATA +3 -2
- {ngio-0.5.0b6.dist-info → ngio-0.5.1.dist-info}/RECORD +29 -29
- {ngio-0.5.0b6.dist-info → ngio-0.5.1.dist-info}/WHEEL +0 -0
- {ngio-0.5.0b6.dist-info → ngio-0.5.1.dist-info}/licenses/LICENSE +0 -0
ngio/images/_create_utils.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Utility functions for working with OME-Zarr images."""
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import logging
|
|
4
4
|
from collections.abc import Mapping, Sequence
|
|
5
5
|
from typing import Any, Literal, TypeVar
|
|
6
6
|
|
|
@@ -22,6 +22,7 @@ from ngio.ome_zarr_meta.ngio_specs import (
|
|
|
22
22
|
NgffVersions,
|
|
23
23
|
SpaceUnits,
|
|
24
24
|
TimeUnits,
|
|
25
|
+
build_axes_handler,
|
|
25
26
|
build_canonical_axes_handler,
|
|
26
27
|
canonical_axes_order,
|
|
27
28
|
canonical_label_axes_order,
|
|
@@ -29,37 +30,9 @@ from ngio.ome_zarr_meta.ngio_specs import (
|
|
|
29
30
|
from ngio.ome_zarr_meta.ngio_specs._axes import AxesSetup
|
|
30
31
|
from ngio.utils import NgioValueError, StoreOrGroup, ZarrGroupHandler
|
|
31
32
|
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
logger = logging.getLogger(f"ngio:{__name__}")
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
*,
|
|
37
|
-
shape: tuple[int, ...],
|
|
38
|
-
axes_names: Sequence[str] | None,
|
|
39
|
-
default_channel_order: tuple[str, ...],
|
|
40
|
-
space_units: SpaceUnits | str | None = DefaultSpaceUnit,
|
|
41
|
-
time_units: TimeUnits | str | None = DefaultTimeUnit,
|
|
42
|
-
axes_setup: AxesSetup | None = None,
|
|
43
|
-
allow_non_canonical_axes: bool = False,
|
|
44
|
-
strict_canonical_order: bool = False,
|
|
45
|
-
) -> AxesHandler:
|
|
46
|
-
"""Compute axes names for given shape."""
|
|
47
|
-
if axes_names is None:
|
|
48
|
-
axes_names = default_channel_order[-len(shape) :]
|
|
49
|
-
# Validate length
|
|
50
|
-
if len(axes_names) != len(shape):
|
|
51
|
-
raise NgioValueError(
|
|
52
|
-
f"Number of axes names {axes_names} does not match the number of "
|
|
53
|
-
f"dimensions {shape}."
|
|
54
|
-
)
|
|
55
|
-
return build_canonical_axes_handler(
|
|
56
|
-
axes_names=axes_names,
|
|
57
|
-
space_units=space_units,
|
|
58
|
-
time_units=time_units,
|
|
59
|
-
axes_setup=axes_setup,
|
|
60
|
-
allow_non_canonical_axes=allow_non_canonical_axes,
|
|
61
|
-
strict_canonical_order=strict_canonical_order,
|
|
62
|
-
)
|
|
35
|
+
_image_or_label_meta = TypeVar("_image_or_label_meta", NgioImageMeta, NgioLabelMeta)
|
|
63
36
|
|
|
64
37
|
|
|
65
38
|
def _align_to_axes(
|
|
@@ -85,9 +58,9 @@ def _check_deprecated_scaling_factors(
|
|
|
85
58
|
shape: tuple[int, ...],
|
|
86
59
|
) -> Sequence[float] | Literal["auto"]:
|
|
87
60
|
if yx_scaling_factor is not None or z_scaling_factor is not None:
|
|
88
|
-
|
|
61
|
+
logger.warning(
|
|
89
62
|
"The 'yx_scaling_factor' and 'z_scaling_factor' arguments are deprecated "
|
|
90
|
-
"and will be removed in
|
|
63
|
+
"and will be removed in ngio=0.6. Please use the 'scaling_factors' "
|
|
91
64
|
"argument instead.",
|
|
92
65
|
DeprecationWarning,
|
|
93
66
|
stacklevel=2,
|
|
@@ -149,7 +122,7 @@ def _compute_scaling_factors(
|
|
|
149
122
|
return tuple(scaling_factors)
|
|
150
123
|
|
|
151
124
|
|
|
152
|
-
def
|
|
125
|
+
def compute_base_scale(
|
|
153
126
|
*,
|
|
154
127
|
pixelsize: float | tuple[float, float],
|
|
155
128
|
z_spacing: float,
|
|
@@ -231,6 +204,38 @@ def _add_channels_meta(
|
|
|
231
204
|
return meta
|
|
232
205
|
|
|
233
206
|
|
|
207
|
+
def _build_axes_handler(
|
|
208
|
+
*,
|
|
209
|
+
shape: tuple[int, ...],
|
|
210
|
+
meta_type: type[_image_or_label_meta],
|
|
211
|
+
axes_names: Sequence[str] | None = None,
|
|
212
|
+
axes_setup: AxesSetup | None = None,
|
|
213
|
+
space_unit: SpaceUnits | str | None = None,
|
|
214
|
+
time_unit: TimeUnits | str | None = None,
|
|
215
|
+
) -> AxesHandler:
|
|
216
|
+
"""Build axes handler for given shape and axes names."""
|
|
217
|
+
if meta_type is NgioImageMeta:
|
|
218
|
+
canonical_axes_order_ = canonical_axes_order()
|
|
219
|
+
else:
|
|
220
|
+
canonical_axes_order_ = canonical_label_axes_order()
|
|
221
|
+
if axes_names is None:
|
|
222
|
+
axes_names = canonical_axes_order_[-len(shape) :]
|
|
223
|
+
|
|
224
|
+
if axes_setup is None:
|
|
225
|
+
return build_canonical_axes_handler(
|
|
226
|
+
axes_names=axes_names,
|
|
227
|
+
canonical_channel_order=canonical_axes_order_,
|
|
228
|
+
space_unit=space_unit,
|
|
229
|
+
time_unit=time_unit,
|
|
230
|
+
)
|
|
231
|
+
return build_axes_handler(
|
|
232
|
+
axes_names=axes_names,
|
|
233
|
+
axes_setup=axes_setup,
|
|
234
|
+
space_unit=space_unit,
|
|
235
|
+
time_unit=time_unit,
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
|
|
234
239
|
def init_image_like(
|
|
235
240
|
*,
|
|
236
241
|
# Where to create the image
|
|
@@ -243,6 +248,7 @@ def init_image_like(
|
|
|
243
248
|
time_spacing: float = 1.0,
|
|
244
249
|
scaling_factors: Sequence[float] | Literal["auto"] = "auto",
|
|
245
250
|
levels: int | list[str] = 5,
|
|
251
|
+
translation: Sequence[float] | None = None,
|
|
246
252
|
space_unit: SpaceUnits | str | None = DefaultSpaceUnit,
|
|
247
253
|
time_unit: TimeUnits | str | None = DefaultTimeUnit,
|
|
248
254
|
axes_names: Sequence[str] | None = None,
|
|
@@ -258,32 +264,28 @@ def init_image_like(
|
|
|
258
264
|
extra_array_kwargs: Mapping[str, Any] | None = None,
|
|
259
265
|
# internal axes configuration for advanced use cases
|
|
260
266
|
axes_setup: AxesSetup | None = None,
|
|
261
|
-
allow_non_canonical_axes: bool = False,
|
|
262
|
-
strict_canonical_order: bool = False,
|
|
263
267
|
# Whether to overwrite existing image
|
|
264
268
|
overwrite: bool = False,
|
|
265
269
|
# Deprecated arguments
|
|
266
270
|
yx_scaling_factor: float | tuple[float, float] | None = None,
|
|
267
271
|
z_scaling_factor: float | None = None,
|
|
268
|
-
) -> ZarrGroupHandler:
|
|
272
|
+
) -> tuple[ZarrGroupHandler, AxesSetup]:
|
|
269
273
|
"""Create an empty OME-Zarr image with the given shape and metadata."""
|
|
270
274
|
shape = tuple(shape)
|
|
271
|
-
if meta_type is NgioImageMeta:
|
|
272
|
-
default_axes_order = canonical_axes_order()
|
|
273
|
-
else:
|
|
274
|
-
default_axes_order = canonical_label_axes_order()
|
|
275
|
-
|
|
276
275
|
axes_handler = _build_axes_handler(
|
|
277
276
|
shape=shape,
|
|
277
|
+
meta_type=meta_type,
|
|
278
278
|
axes_names=axes_names,
|
|
279
|
-
default_channel_order=default_axes_order,
|
|
280
|
-
space_units=space_unit,
|
|
281
|
-
time_units=time_unit,
|
|
282
279
|
axes_setup=axes_setup,
|
|
283
|
-
|
|
284
|
-
|
|
280
|
+
space_unit=space_unit,
|
|
281
|
+
time_unit=time_unit,
|
|
285
282
|
)
|
|
286
|
-
|
|
283
|
+
if len(shape) != len(axes_handler.axes_names):
|
|
284
|
+
raise NgioValueError(
|
|
285
|
+
f"Mismatch between shape {shape} "
|
|
286
|
+
f"and number of axes {len(axes_handler.axes_names)}."
|
|
287
|
+
)
|
|
288
|
+
base_scale = compute_base_scale(
|
|
287
289
|
pixelsize=pixelsize,
|
|
288
290
|
z_spacing=z_spacing,
|
|
289
291
|
time_spacing=time_spacing,
|
|
@@ -306,6 +308,7 @@ def init_image_like(
|
|
|
306
308
|
scaling_factors=scaling_factors,
|
|
307
309
|
base_shape=shape,
|
|
308
310
|
base_scale=base_scale,
|
|
311
|
+
base_translation=translation,
|
|
309
312
|
axes=axes_handler.axes_names,
|
|
310
313
|
chunks=chunks,
|
|
311
314
|
data_type=dtype,
|
|
@@ -319,18 +322,19 @@ def init_image_like(
|
|
|
319
322
|
levels=[p.path for p in pyramid_builder.levels],
|
|
320
323
|
axes_handler=axes_handler,
|
|
321
324
|
scales=[p.scale for p in pyramid_builder.levels],
|
|
322
|
-
translations=[
|
|
325
|
+
translations=[p.translation for p in pyramid_builder.levels],
|
|
323
326
|
name=name,
|
|
324
327
|
version=ngff_version,
|
|
325
328
|
)
|
|
326
329
|
meta = _add_channels_meta(meta=meta, channels_meta=channels_meta)
|
|
327
330
|
# Keep this creation at the end to avoid partial creations on errors
|
|
328
|
-
|
|
331
|
+
image_handler = _create_image_like_group(
|
|
329
332
|
store=store,
|
|
330
333
|
pyramid_builder=pyramid_builder,
|
|
331
334
|
meta=meta,
|
|
332
335
|
overwrite=overwrite,
|
|
333
336
|
)
|
|
337
|
+
return image_handler, axes_handler.axes_setup
|
|
334
338
|
|
|
335
339
|
|
|
336
340
|
def init_image_like_from_shapes(
|
|
@@ -340,10 +344,9 @@ def init_image_like_from_shapes(
|
|
|
340
344
|
# Ngff image parameters
|
|
341
345
|
meta_type: type[_image_or_label_meta],
|
|
342
346
|
shapes: Sequence[tuple[int, ...]],
|
|
343
|
-
|
|
344
|
-
z_spacing: float = 1.0,
|
|
345
|
-
time_spacing: float = 1.0,
|
|
347
|
+
base_scale: tuple[float, ...] | list[tuple[float, ...]],
|
|
346
348
|
levels: list[str] | None = None,
|
|
349
|
+
translation: Sequence[float] | None = None,
|
|
347
350
|
space_unit: SpaceUnits | str | None = DefaultSpaceUnit,
|
|
348
351
|
time_unit: TimeUnits | str | None = DefaultTimeUnit,
|
|
349
352
|
axes_names: Sequence[str] | None = None,
|
|
@@ -359,34 +362,24 @@ def init_image_like_from_shapes(
|
|
|
359
362
|
extra_array_kwargs: Mapping[str, Any] | None = None,
|
|
360
363
|
# internal axes configuration for advanced use cases
|
|
361
364
|
axes_setup: AxesSetup | None = None,
|
|
362
|
-
allow_non_canonical_axes: bool = False,
|
|
363
|
-
strict_canonical_order: bool = False,
|
|
364
365
|
# Whether to overwrite existing image
|
|
365
366
|
overwrite: bool = False,
|
|
366
|
-
) -> ZarrGroupHandler:
|
|
367
|
+
) -> tuple[ZarrGroupHandler, AxesSetup]:
|
|
367
368
|
"""Create an empty OME-Zarr image with the given shape and metadata."""
|
|
368
369
|
base_shape = shapes[0]
|
|
369
|
-
if meta_type is NgioImageMeta:
|
|
370
|
-
default_axes_order = canonical_axes_order()
|
|
371
|
-
else:
|
|
372
|
-
default_axes_order = canonical_label_axes_order()
|
|
373
|
-
|
|
374
370
|
axes_handler = _build_axes_handler(
|
|
375
371
|
shape=base_shape,
|
|
372
|
+
meta_type=meta_type,
|
|
376
373
|
axes_names=axes_names,
|
|
377
|
-
default_channel_order=default_axes_order,
|
|
378
|
-
space_units=space_unit,
|
|
379
|
-
time_units=time_unit,
|
|
380
374
|
axes_setup=axes_setup,
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
)
|
|
384
|
-
base_scale = _compute_base_scale(
|
|
385
|
-
pixelsize=pixelsize,
|
|
386
|
-
z_spacing=z_spacing,
|
|
387
|
-
time_spacing=time_spacing,
|
|
388
|
-
axes_handler=axes_handler,
|
|
375
|
+
space_unit=space_unit,
|
|
376
|
+
time_unit=time_unit,
|
|
389
377
|
)
|
|
378
|
+
if len(base_shape) != len(axes_handler.axes_names):
|
|
379
|
+
raise NgioValueError(
|
|
380
|
+
f"Mismatch between shape {base_shape} "
|
|
381
|
+
f"and number of axes {len(axes_handler.axes_names)}."
|
|
382
|
+
)
|
|
390
383
|
if levels is None:
|
|
391
384
|
levels_paths = tuple(str(i) for i in range(len(shapes)))
|
|
392
385
|
else:
|
|
@@ -395,6 +388,7 @@ def init_image_like_from_shapes(
|
|
|
395
388
|
pyramid_builder = ImagePyramidBuilder.from_shapes(
|
|
396
389
|
shapes=shapes,
|
|
397
390
|
base_scale=base_scale,
|
|
391
|
+
base_translation=translation,
|
|
398
392
|
levels_paths=levels_paths,
|
|
399
393
|
axes=axes_handler.axes_names,
|
|
400
394
|
chunks=chunks,
|
|
@@ -409,15 +403,16 @@ def init_image_like_from_shapes(
|
|
|
409
403
|
levels=[p.path for p in pyramid_builder.levels],
|
|
410
404
|
axes_handler=axes_handler,
|
|
411
405
|
scales=[p.scale for p in pyramid_builder.levels],
|
|
412
|
-
translations=[
|
|
406
|
+
translations=[p.translation for p in pyramid_builder.levels],
|
|
413
407
|
name=name,
|
|
414
408
|
version=ngff_version,
|
|
415
409
|
)
|
|
416
410
|
meta = _add_channels_meta(meta=meta, channels_meta=channels_meta)
|
|
417
411
|
# Keep this creation at the end to avoid partial creations on errors
|
|
418
|
-
|
|
412
|
+
image_handler = _create_image_like_group(
|
|
419
413
|
store=store,
|
|
420
414
|
pyramid_builder=pyramid_builder,
|
|
421
415
|
meta=meta,
|
|
422
416
|
overwrite=overwrite,
|
|
423
417
|
)
|
|
418
|
+
return image_handler, axes_handler.axes_setup
|