ngio 0.5.0a2__py3-none-any.whl → 0.5.0b1__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 +2 -2
- ngio/common/__init__.py +11 -6
- ngio/common/_masking_roi.py +12 -41
- ngio/common/_pyramid.py +206 -76
- ngio/common/_roi.py +257 -329
- ngio/experimental/iterators/_feature.py +3 -3
- ngio/experimental/iterators/_rois_utils.py +10 -11
- ngio/hcs/_plate.py +50 -43
- ngio/images/_abstract_image.py +418 -35
- ngio/images/_create_synt_container.py +35 -42
- ngio/images/_create_utils.py +423 -0
- ngio/images/_image.py +162 -176
- ngio/images/_label.py +182 -137
- ngio/images/_ome_zarr_container.py +372 -197
- ngio/io_pipes/_io_pipes.py +9 -9
- ngio/io_pipes/_io_pipes_masked.py +7 -7
- ngio/io_pipes/_io_pipes_roi.py +6 -6
- ngio/io_pipes/_io_pipes_types.py +3 -3
- ngio/io_pipes/_match_shape.py +5 -4
- ngio/io_pipes/_ops_slices_utils.py +8 -5
- ngio/ome_zarr_meta/__init__.py +21 -18
- ngio/ome_zarr_meta/_meta_handlers.py +409 -701
- ngio/ome_zarr_meta/ngio_specs/__init__.py +2 -0
- ngio/ome_zarr_meta/ngio_specs/_axes.py +1 -0
- ngio/ome_zarr_meta/ngio_specs/_dataset.py +13 -22
- ngio/ome_zarr_meta/ngio_specs/_ngio_hcs.py +54 -61
- ngio/ome_zarr_meta/ngio_specs/_ngio_image.py +21 -68
- ngio/ome_zarr_meta/v04/__init__.py +5 -1
- ngio/ome_zarr_meta/v04/{_v04_spec_utils.py → _v04_spec.py} +49 -63
- ngio/ome_zarr_meta/v05/__init__.py +5 -1
- ngio/ome_zarr_meta/v05/{_v05_spec_utils.py → _v05_spec.py} +57 -64
- ngio/tables/_tables_container.py +2 -4
- ngio/tables/backends/_anndata.py +58 -8
- ngio/tables/backends/_anndata_utils.py +1 -6
- ngio/tables/backends/_csv.py +3 -19
- ngio/tables/backends/_json.py +10 -13
- ngio/tables/backends/_parquet.py +3 -31
- ngio/tables/backends/_py_arrow_backends.py +222 -0
- ngio/tables/v1/_roi_table.py +41 -24
- ngio/utils/__init__.py +4 -12
- ngio/utils/_zarr_utils.py +163 -53
- {ngio-0.5.0a2.dist-info → ngio-0.5.0b1.dist-info}/METADATA +6 -2
- ngio-0.5.0b1.dist-info/RECORD +88 -0
- {ngio-0.5.0a2.dist-info → ngio-0.5.0b1.dist-info}/WHEEL +1 -1
- ngio/images/_create.py +0 -287
- ngio/tables/backends/_non_zarr_backends.py +0 -196
- ngio/utils/_logger.py +0 -50
- ngio-0.5.0a2.dist-info/RECORD +0 -89
- {ngio-0.5.0a2.dist-info → ngio-0.5.0b1.dist-info}/licenses/LICENSE +0 -0
ngio/images/_image.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""Generic class to handle Image-like data in a OME-NGFF file."""
|
|
2
2
|
|
|
3
|
-
from collections.abc import Sequence
|
|
4
|
-
from typing import Literal
|
|
3
|
+
from collections.abc import Mapping, Sequence
|
|
4
|
+
from typing import Any, Literal
|
|
5
5
|
|
|
6
6
|
import dask.array as da
|
|
7
7
|
import numpy as np
|
|
@@ -12,10 +12,9 @@ from ngio.common import (
|
|
|
12
12
|
Dimensions,
|
|
13
13
|
InterpolationOrder,
|
|
14
14
|
Roi,
|
|
15
|
-
RoiPixels,
|
|
16
15
|
)
|
|
17
|
-
from ngio.
|
|
18
|
-
from ngio.images.
|
|
16
|
+
from ngio.common._pyramid import ChunksLike, ShardsLike
|
|
17
|
+
from ngio.images._abstract_image import AbstractImage, abstract_derive
|
|
19
18
|
from ngio.io_pipes import (
|
|
20
19
|
SlicingInputType,
|
|
21
20
|
TransformProtocol,
|
|
@@ -24,7 +23,6 @@ from ngio.ome_zarr_meta import (
|
|
|
24
23
|
ImageMetaHandler,
|
|
25
24
|
NgioImageMeta,
|
|
26
25
|
PixelSize,
|
|
27
|
-
find_image_meta_handler,
|
|
28
26
|
)
|
|
29
27
|
from ngio.ome_zarr_meta.ngio_specs import (
|
|
30
28
|
Channel,
|
|
@@ -37,11 +35,10 @@ from ngio.ome_zarr_meta.ngio_specs import (
|
|
|
37
35
|
TimeUnits,
|
|
38
36
|
)
|
|
39
37
|
from ngio.utils import (
|
|
40
|
-
|
|
38
|
+
NgioValueError,
|
|
41
39
|
StoreOrGroup,
|
|
42
40
|
ZarrGroupHandler,
|
|
43
41
|
)
|
|
44
|
-
from ngio.utils._zarr_utils import find_dimension_separator
|
|
45
42
|
|
|
46
43
|
|
|
47
44
|
class ChannelSelectionModel(BaseModel):
|
|
@@ -90,7 +87,7 @@ def _check_channel_meta(meta: NgioImageMeta, dimension: Dimensions) -> ChannelsM
|
|
|
90
87
|
return ChannelsMeta.default_init(labels=c_dim)
|
|
91
88
|
|
|
92
89
|
if len(meta.channels_meta.channels) != c_dim:
|
|
93
|
-
raise
|
|
90
|
+
raise NgioValueError(
|
|
94
91
|
"The number of channels does not match the image. "
|
|
95
92
|
f"Expected {len(meta.channels_meta.channels)} channels, got {c_dim}."
|
|
96
93
|
)
|
|
@@ -98,7 +95,7 @@ def _check_channel_meta(meta: NgioImageMeta, dimension: Dimensions) -> ChannelsM
|
|
|
98
95
|
return meta.channels_meta
|
|
99
96
|
|
|
100
97
|
|
|
101
|
-
class Image(AbstractImage
|
|
98
|
+
class Image(AbstractImage):
|
|
102
99
|
"""A class to handle a single image (or level) in an OME-Zarr image.
|
|
103
100
|
|
|
104
101
|
This class is meant to be subclassed by specific image types.
|
|
@@ -119,15 +116,23 @@ class Image(AbstractImage[ImageMetaHandler]):
|
|
|
119
116
|
|
|
120
117
|
"""
|
|
121
118
|
if meta_handler is None:
|
|
122
|
-
meta_handler =
|
|
119
|
+
meta_handler = ImageMetaHandler(group_handler)
|
|
123
120
|
super().__init__(
|
|
124
121
|
group_handler=group_handler, path=path, meta_handler=meta_handler
|
|
125
122
|
)
|
|
126
123
|
|
|
124
|
+
@property
|
|
125
|
+
def meta_handler(self) -> ImageMetaHandler:
|
|
126
|
+
"""Return the metadata handler."""
|
|
127
|
+
assert isinstance(self._meta_handler, ImageMetaHandler)
|
|
128
|
+
return self._meta_handler
|
|
129
|
+
|
|
127
130
|
@property
|
|
128
131
|
def meta(self) -> NgioImageMeta:
|
|
129
132
|
"""Return the metadata."""
|
|
130
|
-
|
|
133
|
+
meta = self.meta_handler.get_meta()
|
|
134
|
+
assert isinstance(meta, NgioImageMeta)
|
|
135
|
+
return meta
|
|
131
136
|
|
|
132
137
|
@property
|
|
133
138
|
def channels_meta(self) -> ChannelsMeta:
|
|
@@ -187,7 +192,7 @@ class Image(AbstractImage[ImageMetaHandler]):
|
|
|
187
192
|
|
|
188
193
|
def get_roi_as_numpy(
|
|
189
194
|
self,
|
|
190
|
-
roi: Roi
|
|
195
|
+
roi: Roi,
|
|
191
196
|
channel_selection: ChannelSlicingInputType = None,
|
|
192
197
|
axes_order: Sequence[str] | None = None,
|
|
193
198
|
transforms: Sequence[TransformProtocol] | None = None,
|
|
@@ -241,7 +246,7 @@ class Image(AbstractImage[ImageMetaHandler]):
|
|
|
241
246
|
|
|
242
247
|
def get_roi_as_dask(
|
|
243
248
|
self,
|
|
244
|
-
roi: Roi
|
|
249
|
+
roi: Roi,
|
|
245
250
|
channel_selection: ChannelSlicingInputType = None,
|
|
246
251
|
axes_order: Sequence[str] | None = None,
|
|
247
252
|
transforms: Sequence[TransformProtocol] | None = None,
|
|
@@ -298,7 +303,7 @@ class Image(AbstractImage[ImageMetaHandler]):
|
|
|
298
303
|
|
|
299
304
|
def get_roi(
|
|
300
305
|
self,
|
|
301
|
-
roi: Roi
|
|
306
|
+
roi: Roi,
|
|
302
307
|
channel_selection: ChannelSlicingInputType = None,
|
|
303
308
|
axes_order: Sequence[str] | None = None,
|
|
304
309
|
transforms: Sequence[TransformProtocol] | None = None,
|
|
@@ -358,7 +363,7 @@ class Image(AbstractImage[ImageMetaHandler]):
|
|
|
358
363
|
|
|
359
364
|
def set_roi(
|
|
360
365
|
self,
|
|
361
|
-
roi: Roi
|
|
366
|
+
roi: Roi,
|
|
362
367
|
patch: np.ndarray | da.Array,
|
|
363
368
|
channel_selection: ChannelSlicingInputType = None,
|
|
364
369
|
axes_order: Sequence[str] | None = None,
|
|
@@ -401,22 +406,22 @@ class ImagesContainer:
|
|
|
401
406
|
def __init__(self, group_handler: ZarrGroupHandler) -> None:
|
|
402
407
|
"""Initialize the LabelGroupHandler."""
|
|
403
408
|
self._group_handler = group_handler
|
|
404
|
-
self._meta_handler =
|
|
409
|
+
self._meta_handler = ImageMetaHandler(group_handler)
|
|
405
410
|
|
|
406
411
|
@property
|
|
407
412
|
def meta(self) -> NgioImageMeta:
|
|
408
413
|
"""Return the metadata."""
|
|
409
|
-
return self._meta_handler.
|
|
414
|
+
return self._meta_handler.get_meta()
|
|
410
415
|
|
|
411
416
|
@property
|
|
412
417
|
def levels(self) -> int:
|
|
413
418
|
"""Return the number of levels in the image."""
|
|
414
|
-
return self._meta_handler.
|
|
419
|
+
return self._meta_handler.get_meta().levels
|
|
415
420
|
|
|
416
421
|
@property
|
|
417
422
|
def levels_paths(self) -> list[str]:
|
|
418
423
|
"""Return the paths of the levels in the image."""
|
|
419
|
-
return self._meta_handler.
|
|
424
|
+
return self._meta_handler.get_meta().paths
|
|
420
425
|
|
|
421
426
|
@property
|
|
422
427
|
def num_channels(self) -> int:
|
|
@@ -456,6 +461,15 @@ class ImagesContainer:
|
|
|
456
461
|
channel_label=channel_label, wavelength_id=wavelength_id
|
|
457
462
|
)
|
|
458
463
|
|
|
464
|
+
def _set_channel_meta(
|
|
465
|
+
self,
|
|
466
|
+
channels_meta: ChannelsMeta,
|
|
467
|
+
) -> None:
|
|
468
|
+
"""Set the channels metadata."""
|
|
469
|
+
meta = self.meta
|
|
470
|
+
meta.set_channels_meta(channels_meta)
|
|
471
|
+
self._meta_handler.update_meta(meta)
|
|
472
|
+
|
|
459
473
|
def set_channel_meta(
|
|
460
474
|
self,
|
|
461
475
|
labels: Sequence[str | None] | int | None = None,
|
|
@@ -492,16 +506,12 @@ class ImagesContainer:
|
|
|
492
506
|
ref_image = self.get(path=low_res_dataset.path)
|
|
493
507
|
|
|
494
508
|
if start is not None and end is None:
|
|
495
|
-
raise
|
|
496
|
-
"If start is provided, end must be provided as well."
|
|
497
|
-
)
|
|
509
|
+
raise NgioValueError("If start is provided, end must be provided as well.")
|
|
498
510
|
if end is not None and start is None:
|
|
499
|
-
raise
|
|
500
|
-
"If end is provided, start must be provided as well."
|
|
501
|
-
)
|
|
511
|
+
raise NgioValueError("If end is provided, start must be provided as well.")
|
|
502
512
|
|
|
503
513
|
if start is not None and percentiles is not None:
|
|
504
|
-
raise
|
|
514
|
+
raise NgioValueError(
|
|
505
515
|
"If start and end are provided, percentiles must be None."
|
|
506
516
|
)
|
|
507
517
|
|
|
@@ -513,11 +523,11 @@ class ImagesContainer:
|
|
|
513
523
|
)
|
|
514
524
|
elif start is not None and end is not None:
|
|
515
525
|
if len(start) != len(end):
|
|
516
|
-
raise
|
|
526
|
+
raise NgioValueError(
|
|
517
527
|
"The start and end lists must have the same length."
|
|
518
528
|
)
|
|
519
529
|
if len(start) != self.num_channels:
|
|
520
|
-
raise
|
|
530
|
+
raise NgioValueError(
|
|
521
531
|
"The start and end lists must have the same length as "
|
|
522
532
|
"the number of channels."
|
|
523
533
|
)
|
|
@@ -541,10 +551,7 @@ class ImagesContainer:
|
|
|
541
551
|
data_type=ref_image.dtype,
|
|
542
552
|
**omero_kwargs,
|
|
543
553
|
)
|
|
544
|
-
|
|
545
|
-
meta = self.meta
|
|
546
|
-
meta.set_channels_meta(channel_meta)
|
|
547
|
-
self._meta_handler.write_meta(meta)
|
|
554
|
+
self._set_channel_meta(channel_meta)
|
|
548
555
|
|
|
549
556
|
def set_channel_percentiles(
|
|
550
557
|
self,
|
|
@@ -553,7 +560,7 @@ class ImagesContainer:
|
|
|
553
560
|
) -> None:
|
|
554
561
|
"""Update the percentiles of the channels."""
|
|
555
562
|
if self.meta._channels_meta is None:
|
|
556
|
-
raise
|
|
563
|
+
raise NgioValueError("The channels meta is not initialized.")
|
|
557
564
|
|
|
558
565
|
low_res_dataset = self.meta.get_lowest_resolution_dataset()
|
|
559
566
|
ref_image = self.get(path=low_res_dataset.path)
|
|
@@ -578,7 +585,7 @@ class ImagesContainer:
|
|
|
578
585
|
|
|
579
586
|
meta = self.meta
|
|
580
587
|
meta.set_channels_meta(new_meta)
|
|
581
|
-
self._meta_handler.
|
|
588
|
+
self._meta_handler.update_meta(meta)
|
|
582
589
|
|
|
583
590
|
def set_axes_unit(
|
|
584
591
|
self,
|
|
@@ -593,62 +600,90 @@ class ImagesContainer:
|
|
|
593
600
|
"""
|
|
594
601
|
meta = self.meta
|
|
595
602
|
meta = meta.to_units(space_unit=space_unit, time_unit=time_unit)
|
|
596
|
-
self._meta_handler.
|
|
603
|
+
self._meta_handler.update_meta(meta)
|
|
597
604
|
|
|
598
605
|
def derive(
|
|
599
606
|
self,
|
|
600
607
|
store: StoreOrGroup,
|
|
601
608
|
ref_path: str | None = None,
|
|
609
|
+
# Metadata parameters
|
|
602
610
|
shape: Sequence[int] | None = None,
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
611
|
+
pixelsize: float | tuple[float, float] | None = None,
|
|
612
|
+
z_spacing: float | None = None,
|
|
613
|
+
time_spacing: float | None = None,
|
|
606
614
|
name: str | None = None,
|
|
607
|
-
|
|
608
|
-
dtype: str | None = None,
|
|
609
|
-
dimension_separator: Literal[".", "/"] | None = None,
|
|
610
|
-
compressors: CompressorLike | None = None,
|
|
615
|
+
channels_meta: Sequence[str | Channel] | None = None,
|
|
611
616
|
ngff_version: NgffVersions | None = None,
|
|
617
|
+
# Zarr Array parameters
|
|
618
|
+
chunks: ChunksLike = "auto",
|
|
619
|
+
shards: ShardsLike | None = None,
|
|
620
|
+
dtype: str = "uint16",
|
|
621
|
+
dimension_separator: Literal[".", "/"] = "/",
|
|
622
|
+
compressors: CompressorLike = "auto",
|
|
623
|
+
extra_array_kwargs: Mapping[str, Any] | None = None,
|
|
612
624
|
overwrite: bool = False,
|
|
625
|
+
# Deprecated arguments
|
|
626
|
+
labels: Sequence[str] | None = None,
|
|
627
|
+
pixel_size: PixelSize | None = None,
|
|
613
628
|
) -> "ImagesContainer":
|
|
614
629
|
"""Create an empty OME-Zarr image from an existing image.
|
|
615
630
|
|
|
631
|
+
If a kwarg is not provided, the value from the reference image will be used.
|
|
632
|
+
|
|
616
633
|
Args:
|
|
634
|
+
image_container (ImagesContainer): The image container to derive the new
|
|
635
|
+
image.
|
|
617
636
|
store (StoreOrGroup): The Zarr store or group to create the image in.
|
|
618
|
-
ref_path (str | None): The path to the reference image in
|
|
619
|
-
|
|
637
|
+
ref_path (str | None): The path to the reference image in the image
|
|
638
|
+
container.
|
|
620
639
|
shape (Sequence[int] | None): The shape of the new image.
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
640
|
+
pixelsize (float | tuple[float, float] | None): The pixel size of the new
|
|
641
|
+
image.
|
|
642
|
+
z_spacing (float | None): The z spacing of the new image.
|
|
643
|
+
time_spacing (float | None): The time spacing of the new image.
|
|
624
644
|
name (str | None): The name of the new image.
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
645
|
+
channels_meta (Sequence[str | Channel] | None): The channels metadata
|
|
646
|
+
of the new image.
|
|
647
|
+
ngff_version (NgffVersions | None): The NGFF version to use.
|
|
648
|
+
chunks (Sequence[int] | None): The chunk shape of the new image.
|
|
649
|
+
shards (ShardsLike | None): The shard shape of the new image.
|
|
630
650
|
dtype (str | None): The data type of the new image.
|
|
631
|
-
|
|
651
|
+
dimension_separator (DIMENSION_SEPARATOR | None): The separator to use for
|
|
652
|
+
dimensions.
|
|
653
|
+
compressors (CompressorLike | None): The compressors to use.
|
|
654
|
+
extra_array_kwargs (Mapping[str, Any] | None): Extra arguments to pass to
|
|
655
|
+
the zarr array creation.
|
|
632
656
|
overwrite (bool): Whether to overwrite an existing image.
|
|
657
|
+
labels (Sequence[str] | None): The labels of the new image.
|
|
658
|
+
This argument is deprecated please use channels_meta instead.
|
|
659
|
+
pixel_size (PixelSize | None): The pixel size of the new image.
|
|
660
|
+
This argument is deprecated please use pixelsize, z_spacing,
|
|
661
|
+
and time_spacing instead.
|
|
633
662
|
|
|
634
663
|
Returns:
|
|
635
|
-
ImagesContainer: The new image
|
|
664
|
+
ImagesContainer: The new derived image.
|
|
665
|
+
|
|
636
666
|
"""
|
|
637
667
|
return derive_image_container(
|
|
638
668
|
image_container=self,
|
|
639
669
|
store=store,
|
|
640
670
|
ref_path=ref_path,
|
|
641
671
|
shape=shape,
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
672
|
+
pixelsize=pixelsize,
|
|
673
|
+
z_spacing=z_spacing,
|
|
674
|
+
time_spacing=time_spacing,
|
|
645
675
|
name=name,
|
|
676
|
+
channels_meta=channels_meta,
|
|
677
|
+
ngff_version=ngff_version,
|
|
646
678
|
chunks=chunks,
|
|
679
|
+
shards=shards,
|
|
647
680
|
dtype=dtype,
|
|
648
681
|
dimension_separator=dimension_separator,
|
|
649
682
|
compressors=compressors,
|
|
650
|
-
|
|
683
|
+
extra_array_kwargs=extra_array_kwargs,
|
|
651
684
|
overwrite=overwrite,
|
|
685
|
+
labels=labels,
|
|
686
|
+
pixel_size=pixel_size,
|
|
652
687
|
)
|
|
653
688
|
|
|
654
689
|
def get(
|
|
@@ -667,7 +702,7 @@ class ImagesContainer:
|
|
|
667
702
|
closest pixel size level will be returned.
|
|
668
703
|
|
|
669
704
|
"""
|
|
670
|
-
dataset = self._meta_handler.
|
|
705
|
+
dataset = self._meta_handler.get_meta().get_dataset(
|
|
671
706
|
path=path, pixel_size=pixel_size, strict=strict
|
|
672
707
|
)
|
|
673
708
|
return Image(
|
|
@@ -720,147 +755,98 @@ def compute_image_percentile(
|
|
|
720
755
|
|
|
721
756
|
|
|
722
757
|
def derive_image_container(
|
|
758
|
+
*,
|
|
723
759
|
image_container: ImagesContainer,
|
|
724
760
|
store: StoreOrGroup,
|
|
725
761
|
ref_path: str | None = None,
|
|
762
|
+
# Metadata parameters
|
|
726
763
|
shape: Sequence[int] | None = None,
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
764
|
+
pixelsize: float | tuple[float, float] | None = None,
|
|
765
|
+
z_spacing: float | None = None,
|
|
766
|
+
time_spacing: float | None = None,
|
|
730
767
|
name: str | None = None,
|
|
731
|
-
|
|
768
|
+
channels_policy: Literal["same", "squeeze", "singleton"] | int = "same",
|
|
769
|
+
channels_meta: Sequence[str | Channel] | None = None,
|
|
770
|
+
ngff_version: NgffVersions | None = None,
|
|
771
|
+
# Zarr Array parameters
|
|
772
|
+
chunks: ChunksLike = "auto",
|
|
773
|
+
shards: ShardsLike | None = None,
|
|
732
774
|
dtype: str | None = None,
|
|
733
775
|
dimension_separator: Literal[".", "/"] | None = None,
|
|
734
776
|
compressors: CompressorLike | None = None,
|
|
735
|
-
|
|
777
|
+
extra_array_kwargs: Mapping[str, Any] | None = None,
|
|
736
778
|
overwrite: bool = False,
|
|
779
|
+
# Deprecated arguments
|
|
780
|
+
labels: Sequence[str] | None = None,
|
|
781
|
+
pixel_size: PixelSize | None = None,
|
|
737
782
|
) -> ImagesContainer:
|
|
738
|
-
"""
|
|
783
|
+
"""Derive a new OME-Zarr image container from an existing image.
|
|
784
|
+
|
|
785
|
+
If a kwarg is not provided, the value from the reference image will be used.
|
|
739
786
|
|
|
740
787
|
Args:
|
|
741
|
-
image_container (ImagesContainer): The image container to derive the new image
|
|
788
|
+
image_container (ImagesContainer): The image container to derive the new image
|
|
789
|
+
from.
|
|
742
790
|
store (StoreOrGroup): The Zarr store or group to create the image in.
|
|
743
791
|
ref_path (str | None): The path to the reference image in the image container.
|
|
744
792
|
shape (Sequence[int] | None): The shape of the new image.
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
793
|
+
pixelsize (float | tuple[float, float] | None): The pixel size of the new image.
|
|
794
|
+
z_spacing (float | None): The z spacing of the new image.
|
|
795
|
+
time_spacing (float | None): The time spacing of the new image.
|
|
748
796
|
name (str | None): The name of the new image.
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
797
|
+
channels_policy (Literal["squeeze", "same", "singleton"] | int): Possible
|
|
798
|
+
policies:
|
|
799
|
+
- If "squeeze", the channels axis will be removed (no matter its size).
|
|
800
|
+
- If "same", the channels axis will be kept as is (if it exists).
|
|
801
|
+
- If "singleton", the channels axis will be set to size 1.
|
|
802
|
+
- If an integer is provided, the channels axis will be changed to have
|
|
803
|
+
that size.
|
|
804
|
+
channels_meta (Sequence[str | Channel] | None): The channels metadata
|
|
805
|
+
of the new image.
|
|
806
|
+
ngff_version (NgffVersions | None): The NGFF version to use.
|
|
807
|
+
chunks (ChunksLike): The chunk shape of the new image. Defaults to "auto".
|
|
808
|
+
shards (ShardsLike | None): The shard shape of the new image.
|
|
755
809
|
dtype (str | None): The data type of the new image.
|
|
756
|
-
|
|
810
|
+
dimension_separator (Literal[".", "/"] | None): The separator to use for
|
|
811
|
+
dimensions.
|
|
812
|
+
compressors (CompressorLike | None): The compressors to use.
|
|
813
|
+
extra_array_kwargs (Mapping[str, Any] | None): Extra arguments to pass to
|
|
814
|
+
the zarr array creation.
|
|
815
|
+
overwrite (bool): Whether to overwrite an existing image. Defaults to False.
|
|
816
|
+
labels (Sequence[str] | None): Deprecated. This argument is deprecated,
|
|
817
|
+
please use channels_meta instead.
|
|
818
|
+
pixel_size (PixelSize | None): Deprecated. The pixel size of the new image.
|
|
819
|
+
This argument is deprecated, please use pixelsize, z_spacing,
|
|
820
|
+
and time_spacing instead.
|
|
757
821
|
|
|
758
822
|
Returns:
|
|
759
|
-
ImagesContainer: The new image
|
|
823
|
+
ImagesContainer: The new derived image container.
|
|
760
824
|
|
|
761
825
|
"""
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
ref_meta = ref_image.meta
|
|
768
|
-
|
|
769
|
-
if shape is None:
|
|
770
|
-
shape = ref_image.shape
|
|
771
|
-
|
|
772
|
-
if pixel_size is None:
|
|
773
|
-
pixel_size = ref_image.pixel_size
|
|
774
|
-
|
|
775
|
-
if axes_names is None:
|
|
776
|
-
axes_names = ref_meta.axes_handler.axes_names
|
|
777
|
-
|
|
778
|
-
if len(axes_names) != len(shape):
|
|
779
|
-
raise NgioValidationError(
|
|
780
|
-
"The axes names of the new image does not match the reference image."
|
|
781
|
-
f"Got {axes_names} for shape {shape}."
|
|
782
|
-
)
|
|
783
|
-
|
|
784
|
-
if chunks is None:
|
|
785
|
-
chunks = ref_image.chunks
|
|
786
|
-
|
|
787
|
-
if len(chunks) != len(shape):
|
|
788
|
-
raise NgioValidationError(
|
|
789
|
-
"The chunks of the new image does not match the reference image."
|
|
790
|
-
f"Got {chunks} for shape {shape}."
|
|
791
|
-
)
|
|
792
|
-
|
|
793
|
-
if name is None:
|
|
794
|
-
name = ref_meta.name
|
|
795
|
-
|
|
796
|
-
if dtype is None:
|
|
797
|
-
dtype = ref_image.dtype
|
|
798
|
-
|
|
799
|
-
if dimension_separator is None:
|
|
800
|
-
dimension_separator = find_dimension_separator(ref_image.zarr_array)
|
|
801
|
-
|
|
802
|
-
if compressors is None:
|
|
803
|
-
compressors = ref_image.zarr_array.compressors # type: ignore
|
|
804
|
-
|
|
805
|
-
if ngff_version is None:
|
|
806
|
-
ngff_version = ref_meta.version
|
|
807
|
-
|
|
808
|
-
handler = create_empty_image_container(
|
|
826
|
+
ref_image = image_container.get(path=ref_path)
|
|
827
|
+
group_handler = abstract_derive(
|
|
828
|
+
ref_image=ref_image,
|
|
829
|
+
meta_type=NgioImageMeta,
|
|
809
830
|
store=store,
|
|
810
831
|
shape=shape,
|
|
811
|
-
pixelsize=
|
|
812
|
-
z_spacing=
|
|
813
|
-
time_spacing=
|
|
814
|
-
levels=ref_meta.paths,
|
|
815
|
-
yx_scaling_factor=ref_meta.yx_scaling(),
|
|
816
|
-
z_scaling_factor=ref_meta.z_scaling(),
|
|
817
|
-
time_unit=pixel_size.time_unit,
|
|
818
|
-
space_unit=pixel_size.space_unit,
|
|
819
|
-
axes_names=axes_names,
|
|
832
|
+
pixelsize=pixelsize,
|
|
833
|
+
z_spacing=z_spacing,
|
|
834
|
+
time_spacing=time_spacing,
|
|
820
835
|
name=name,
|
|
836
|
+
channels_meta=channels_meta,
|
|
837
|
+
channels_policy=channels_policy,
|
|
838
|
+
ngff_version=ngff_version,
|
|
821
839
|
chunks=chunks,
|
|
840
|
+
shards=shards,
|
|
822
841
|
dtype=dtype,
|
|
823
842
|
dimension_separator=dimension_separator,
|
|
824
843
|
compressors=compressors,
|
|
844
|
+
extra_array_kwargs=extra_array_kwargs,
|
|
825
845
|
overwrite=overwrite,
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
image_container = ImagesContainer(handler)
|
|
829
|
-
|
|
830
|
-
if ref_image.num_channels == image_container.num_channels:
|
|
831
|
-
_labels = ref_image.channel_labels
|
|
832
|
-
wavelength_id = ref_image.wavelength_ids
|
|
833
|
-
|
|
834
|
-
channel_meta = ref_image.channels_meta
|
|
835
|
-
colors = [c.channel_visualisation.color for c in channel_meta.channels]
|
|
836
|
-
active = [c.channel_visualisation.active for c in channel_meta.channels]
|
|
837
|
-
start = [c.channel_visualisation.start for c in channel_meta.channels]
|
|
838
|
-
end = [c.channel_visualisation.end for c in channel_meta.channels]
|
|
839
|
-
else:
|
|
840
|
-
_labels = None
|
|
841
|
-
wavelength_id = None
|
|
842
|
-
colors = None
|
|
843
|
-
active = None
|
|
844
|
-
start = None
|
|
845
|
-
end = None
|
|
846
|
-
|
|
847
|
-
if labels is not None:
|
|
848
|
-
if len(labels) != image_container.num_channels:
|
|
849
|
-
raise NgioValidationError(
|
|
850
|
-
"The number of labels does not match the number of channels."
|
|
851
|
-
)
|
|
852
|
-
_labels = labels
|
|
853
|
-
|
|
854
|
-
image_container.set_channel_meta(
|
|
855
|
-
labels=_labels,
|
|
856
|
-
wavelength_id=wavelength_id,
|
|
857
|
-
percentiles=None,
|
|
858
|
-
colors=colors,
|
|
859
|
-
active=active,
|
|
860
|
-
start=start,
|
|
861
|
-
end=end,
|
|
846
|
+
labels=labels,
|
|
847
|
+
pixel_size=pixel_size,
|
|
862
848
|
)
|
|
863
|
-
return
|
|
849
|
+
return ImagesContainer(group_handler=group_handler)
|
|
864
850
|
|
|
865
851
|
|
|
866
852
|
def _parse_str_or_model(
|
|
@@ -869,9 +855,9 @@ def _parse_str_or_model(
|
|
|
869
855
|
"""Parse a string or ChannelSelectionModel to an integer channel index."""
|
|
870
856
|
if isinstance(channel_selection, int):
|
|
871
857
|
if channel_selection < 0:
|
|
872
|
-
raise
|
|
858
|
+
raise NgioValueError("Channel index must be a non-negative integer.")
|
|
873
859
|
if channel_selection >= image.num_channels:
|
|
874
|
-
raise
|
|
860
|
+
raise NgioValueError(
|
|
875
861
|
"Channel index must be less than the number "
|
|
876
862
|
f"of channels ({image.num_channels})."
|
|
877
863
|
)
|
|
@@ -889,7 +875,7 @@ def _parse_str_or_model(
|
|
|
889
875
|
)
|
|
890
876
|
elif channel_selection.mode == "index":
|
|
891
877
|
return int(channel_selection.identifier)
|
|
892
|
-
raise
|
|
878
|
+
raise NgioValueError(
|
|
893
879
|
"Invalid channel selection type. "
|
|
894
880
|
f"{channel_selection} is of type {type(channel_selection)} ",
|
|
895
881
|
"supported types are str, ChannelSelectionModel, and int.",
|
|
@@ -908,7 +894,7 @@ def _parse_channel_selection(
|
|
|
908
894
|
elif isinstance(channel_selection, Sequence):
|
|
909
895
|
_sequence = [_parse_str_or_model(image, cs) for cs in channel_selection]
|
|
910
896
|
return {"c": _sequence}
|
|
911
|
-
raise
|
|
897
|
+
raise NgioValueError(
|
|
912
898
|
f"Invalid channel selection type {type(channel_selection)}. "
|
|
913
899
|
"Supported types are int, str, ChannelSelectionModel, and Sequence."
|
|
914
900
|
)
|
|
@@ -922,7 +908,7 @@ def add_channel_selection_to_slicing_dict(
|
|
|
922
908
|
"""Add channel selection information to the slicing dictionary."""
|
|
923
909
|
channel_info = _parse_channel_selection(image, channel_selection)
|
|
924
910
|
if "c" in slicing_dict and channel_info:
|
|
925
|
-
raise
|
|
911
|
+
raise NgioValueError(
|
|
926
912
|
"Both channel_selection and 'c' in slicing_kwargs are provided. "
|
|
927
913
|
"Which channel selection should be used is ambiguous. "
|
|
928
914
|
"Please provide only one."
|