ngio 0.5.0a2__py3-none-any.whl → 0.5.0a3__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 (47) hide show
  1. ngio/__init__.py +2 -2
  2. ngio/common/__init__.py +11 -6
  3. ngio/common/_masking_roi.py +12 -41
  4. ngio/common/_pyramid.py +206 -76
  5. ngio/common/_roi.py +257 -329
  6. ngio/experimental/iterators/_feature.py +3 -3
  7. ngio/experimental/iterators/_rois_utils.py +10 -11
  8. ngio/hcs/_plate.py +50 -43
  9. ngio/images/_abstract_image.py +417 -35
  10. ngio/images/_create_synt_container.py +35 -42
  11. ngio/images/_create_utils.py +423 -0
  12. ngio/images/_image.py +154 -176
  13. ngio/images/_label.py +144 -119
  14. ngio/images/_ome_zarr_container.py +361 -196
  15. ngio/io_pipes/_io_pipes.py +9 -9
  16. ngio/io_pipes/_io_pipes_masked.py +7 -7
  17. ngio/io_pipes/_io_pipes_roi.py +6 -6
  18. ngio/io_pipes/_io_pipes_types.py +3 -3
  19. ngio/io_pipes/_match_shape.py +5 -4
  20. ngio/io_pipes/_ops_slices_utils.py +8 -5
  21. ngio/ome_zarr_meta/__init__.py +15 -18
  22. ngio/ome_zarr_meta/_meta_handlers.py +334 -713
  23. ngio/ome_zarr_meta/ngio_specs/_axes.py +1 -0
  24. ngio/ome_zarr_meta/ngio_specs/_dataset.py +13 -22
  25. ngio/ome_zarr_meta/ngio_specs/_ngio_hcs.py +54 -61
  26. ngio/ome_zarr_meta/ngio_specs/_ngio_image.py +14 -68
  27. ngio/ome_zarr_meta/v04/__init__.py +1 -1
  28. ngio/ome_zarr_meta/v04/{_v04_spec_utils.py → _v04_spec.py} +16 -61
  29. ngio/ome_zarr_meta/v05/__init__.py +1 -1
  30. ngio/ome_zarr_meta/v05/{_v05_spec_utils.py → _v05_spec.py} +18 -61
  31. ngio/tables/_tables_container.py +2 -4
  32. ngio/tables/backends/_anndata.py +57 -8
  33. ngio/tables/backends/_anndata_utils.py +1 -6
  34. ngio/tables/backends/_csv.py +3 -19
  35. ngio/tables/backends/_json.py +10 -13
  36. ngio/tables/backends/_parquet.py +3 -31
  37. ngio/tables/backends/_py_arrow_backends.py +222 -0
  38. ngio/tables/v1/_roi_table.py +41 -24
  39. ngio/utils/__init__.py +4 -12
  40. ngio/utils/_zarr_utils.py +160 -53
  41. {ngio-0.5.0a2.dist-info → ngio-0.5.0a3.dist-info}/METADATA +6 -2
  42. {ngio-0.5.0a2.dist-info → ngio-0.5.0a3.dist-info}/RECORD +44 -45
  43. {ngio-0.5.0a2.dist-info → ngio-0.5.0a3.dist-info}/WHEEL +1 -1
  44. ngio/images/_create.py +0 -287
  45. ngio/tables/backends/_non_zarr_backends.py +0 -196
  46. ngio/utils/_logger.py +0 -50
  47. {ngio-0.5.0a2.dist-info → ngio-0.5.0a3.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.images._abstract_image import AbstractImage
18
- from ngio.images._create import create_empty_image_container
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
- NgioValidationError,
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 NgioValidationError(
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[ImageMetaHandler]):
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 = find_image_meta_handler(group_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
- return self._meta_handler.meta
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 | RoiPixels,
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 | RoiPixels,
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 | RoiPixels,
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 | RoiPixels,
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 = find_image_meta_handler(group_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.meta
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.meta.levels
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.meta.paths
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 NgioValidationError(
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 NgioValidationError(
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 NgioValidationError(
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 NgioValidationError(
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 NgioValidationError(
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 NgioValidationError("The channels meta is not initialized.")
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.write_meta(meta)
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.write_meta(meta)
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
- labels: Sequence[str] | None = None,
604
- pixel_size: PixelSize | None = None,
605
- axes_names: Sequence[str] | None = None,
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
- chunks: Sequence[int] | None = None,
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
- the image container.
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
- labels (Sequence[str] | None): The labels of the new image.
622
- pixel_size (PixelSize | None): The pixel size of the new image.
623
- axes_names (Sequence[str] | None): The axes names of the new image.
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
- chunks (Sequence[int] | Literal["auto"]): The chunk shape of the new image.
626
- dimension_separator (DIMENSION_SEPARATOR | None): The separator to use for
627
- dimensions. If None it will use the same as the reference image.
628
- compressors: The compressor to use. If None it will use
629
- the same as the reference image.
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
- ngff_version (NgffVersions): The NGFF version to use.
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
- labels=labels,
643
- pixel_size=pixel_size,
644
- axes_names=axes_names,
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
- ngff_version=ngff_version,
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.meta.get_dataset(
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,90 @@ 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
- labels: Sequence[str] | None = None,
728
- pixel_size: PixelSize | None = None,
729
- axes_names: Sequence[str] | None = None,
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
- chunks: Sequence[int] | None = None,
768
+ channels_meta: Sequence[str | Channel] | None = None,
769
+ ngff_version: NgffVersions | None = None,
770
+ # Zarr Array parameters
771
+ chunks: ChunksLike = "auto",
772
+ shards: ShardsLike | None = None,
732
773
  dtype: str | None = None,
733
774
  dimension_separator: Literal[".", "/"] | None = None,
734
775
  compressors: CompressorLike | None = None,
735
- ngff_version: NgffVersions | None = None,
776
+ extra_array_kwargs: Mapping[str, Any] | None = None,
736
777
  overwrite: bool = False,
778
+ # Deprecated arguments
779
+ labels: Sequence[str] | None = None,
780
+ pixel_size: PixelSize | None = None,
737
781
  ) -> ImagesContainer:
738
- """Create an empty OME-Zarr image from an existing image.
782
+ """Derive a new OME-Zarr image container from an existing image.
783
+
784
+ If a kwarg is not provided, the value from the reference image will be used.
739
785
 
740
786
  Args:
741
- image_container (ImagesContainer): The image container to derive the new image.
787
+ image_container (ImagesContainer): The image container to derive the new image
788
+ from.
742
789
  store (StoreOrGroup): The Zarr store or group to create the image in.
743
790
  ref_path (str | None): The path to the reference image in the image container.
744
791
  shape (Sequence[int] | None): The shape of the new image.
745
- labels (Sequence[str] | None): The labels of the new image.
746
- pixel_size (PixelSize | None): The pixel size of the new image.
747
- axes_names (Sequence[str] | None): The axes names of the new image.
792
+ pixelsize (float | tuple[float, float] | None): The pixel size of the new image.
793
+ z_spacing (float | None): The z spacing of the new image.
794
+ time_spacing (float | None): The time spacing of the new image.
748
795
  name (str | None): The name of the new image.
749
- chunks (Sequence[int] | None): The chunk shape of the new image.
750
- dimension_separator (DIMENSION_SEPARATOR | None): The separator to use for
751
- dimensions. If None it will use the same as the reference image.
752
- compressors (CompressorLike | None): The compressors to use. If None it will use
753
- the same as the reference image.
754
- ngff_version (NgffVersions): The NGFF version to use.
796
+ channels_meta (Sequence[str | Channel] | None): The channels metadata
797
+ of the new image.
798
+ ngff_version (NgffVersions | None): The NGFF version to use.
799
+ chunks (ChunksLike): The chunk shape of the new image. Defaults to "auto".
800
+ shards (ShardsLike | None): The shard shape of the new image.
755
801
  dtype (str | None): The data type of the new image.
756
- overwrite (bool): Whether to overwrite an existing image.
802
+ dimension_separator (Literal[".", "/"] | None): The separator to use for
803
+ dimensions.
804
+ compressors (CompressorLike | None): The compressors to use.
805
+ extra_array_kwargs (Mapping[str, Any] | None): Extra arguments to pass to
806
+ the zarr array creation.
807
+ overwrite (bool): Whether to overwrite an existing image. Defaults to False.
808
+ labels (Sequence[str] | None): Deprecated. This argument is deprecated,
809
+ please use channels_meta instead.
810
+ pixel_size (PixelSize | None): Deprecated. The pixel size of the new image.
811
+ This argument is deprecated, please use pixelsize, z_spacing,
812
+ and time_spacing instead.
757
813
 
758
814
  Returns:
759
- ImagesContainer: The new image
815
+ ImagesContainer: The new derived image container.
760
816
 
761
817
  """
762
- if ref_path is None:
763
- ref_image = image_container.get()
764
- else:
765
- ref_image = image_container.get(path=ref_path)
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(
818
+ ref_image = image_container.get(path=ref_path)
819
+ group_handler = abstract_derive(
820
+ ref_image=ref_image,
821
+ meta_type=NgioImageMeta,
809
822
  store=store,
810
823
  shape=shape,
811
- pixelsize=pixel_size.x,
812
- z_spacing=pixel_size.z,
813
- time_spacing=pixel_size.t,
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,
824
+ pixelsize=pixelsize,
825
+ z_spacing=z_spacing,
826
+ time_spacing=time_spacing,
820
827
  name=name,
828
+ channels_meta=channels_meta,
829
+ channels_policy="same",
830
+ ngff_version=ngff_version,
821
831
  chunks=chunks,
832
+ shards=shards,
822
833
  dtype=dtype,
823
834
  dimension_separator=dimension_separator,
824
835
  compressors=compressors,
836
+ extra_array_kwargs=extra_array_kwargs,
825
837
  overwrite=overwrite,
826
- ngff_version=ngff_version,
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,
838
+ labels=labels,
839
+ pixel_size=pixel_size,
862
840
  )
863
- return image_container
841
+ return ImagesContainer(group_handler=group_handler)
864
842
 
865
843
 
866
844
  def _parse_str_or_model(
@@ -869,9 +847,9 @@ def _parse_str_or_model(
869
847
  """Parse a string or ChannelSelectionModel to an integer channel index."""
870
848
  if isinstance(channel_selection, int):
871
849
  if channel_selection < 0:
872
- raise NgioValidationError("Channel index must be a non-negative integer.")
850
+ raise NgioValueError("Channel index must be a non-negative integer.")
873
851
  if channel_selection >= image.num_channels:
874
- raise NgioValidationError(
852
+ raise NgioValueError(
875
853
  "Channel index must be less than the number "
876
854
  f"of channels ({image.num_channels})."
877
855
  )
@@ -889,7 +867,7 @@ def _parse_str_or_model(
889
867
  )
890
868
  elif channel_selection.mode == "index":
891
869
  return int(channel_selection.identifier)
892
- raise NgioValidationError(
870
+ raise NgioValueError(
893
871
  "Invalid channel selection type. "
894
872
  f"{channel_selection} is of type {type(channel_selection)} ",
895
873
  "supported types are str, ChannelSelectionModel, and int.",
@@ -908,7 +886,7 @@ def _parse_channel_selection(
908
886
  elif isinstance(channel_selection, Sequence):
909
887
  _sequence = [_parse_str_or_model(image, cs) for cs in channel_selection]
910
888
  return {"c": _sequence}
911
- raise NgioValidationError(
889
+ raise NgioValueError(
912
890
  f"Invalid channel selection type {type(channel_selection)}. "
913
891
  "Supported types are int, str, ChannelSelectionModel, and Sequence."
914
892
  )
@@ -922,7 +900,7 @@ def add_channel_selection_to_slicing_dict(
922
900
  """Add channel selection information to the slicing dictionary."""
923
901
  channel_info = _parse_channel_selection(image, channel_selection)
924
902
  if "c" in slicing_dict and channel_info:
925
- raise NgioValidationError(
903
+ raise NgioValueError(
926
904
  "Both channel_selection and 'c' in slicing_kwargs are provided. "
927
905
  "Which channel selection should be used is ambiguous. "
928
906
  "Please provide only one."