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/_abstract_image.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Generic class to handle Image-like data in a OME-NGFF file."""
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import logging
|
|
4
4
|
from abc import ABC, abstractmethod
|
|
5
5
|
from collections.abc import Mapping, Sequence
|
|
6
6
|
from typing import Any, Literal
|
|
@@ -16,9 +16,15 @@ from ngio.common import (
|
|
|
16
16
|
Roi,
|
|
17
17
|
consolidate_pyramid,
|
|
18
18
|
)
|
|
19
|
-
from ngio.common._pyramid import
|
|
19
|
+
from ngio.common._pyramid import (
|
|
20
|
+
ChunksLike,
|
|
21
|
+
ShardsLike,
|
|
22
|
+
compute_scales_from_shapes,
|
|
23
|
+
compute_shapes_from_scaling_factors,
|
|
24
|
+
)
|
|
20
25
|
from ngio.images._create_utils import (
|
|
21
26
|
_image_or_label_meta,
|
|
27
|
+
compute_base_scale,
|
|
22
28
|
init_image_like_from_shapes,
|
|
23
29
|
)
|
|
24
30
|
from ngio.io_pipes import (
|
|
@@ -46,6 +52,13 @@ from ngio.ome_zarr_meta.ngio_specs import (
|
|
|
46
52
|
NgffVersions,
|
|
47
53
|
NgioLabelMeta,
|
|
48
54
|
)
|
|
55
|
+
from ngio.ome_zarr_meta.ngio_specs._axes import (
|
|
56
|
+
AxesSetup,
|
|
57
|
+
DefaultSpaceUnit,
|
|
58
|
+
DefaultTimeUnit,
|
|
59
|
+
SpaceUnits,
|
|
60
|
+
TimeUnits,
|
|
61
|
+
)
|
|
49
62
|
from ngio.tables import RoiTable
|
|
50
63
|
from ngio.utils import (
|
|
51
64
|
NgioFileExistsError,
|
|
@@ -55,6 +68,8 @@ from ngio.utils import (
|
|
|
55
68
|
)
|
|
56
69
|
from ngio.utils._zarr_utils import find_dimension_separator
|
|
57
70
|
|
|
71
|
+
logger = logging.getLogger(f"ngio:{__name__}")
|
|
72
|
+
|
|
58
73
|
|
|
59
74
|
class AbstractImage(ABC):
|
|
60
75
|
"""A class to handle a single image (or level) in an OME-Zarr image.
|
|
@@ -130,6 +145,11 @@ class AbstractImage(ABC):
|
|
|
130
145
|
"""Return the axes handler of the image."""
|
|
131
146
|
return self.dataset.axes_handler
|
|
132
147
|
|
|
148
|
+
@property
|
|
149
|
+
def axes_setup(self) -> AxesSetup:
|
|
150
|
+
"""Return the axes setup of the image."""
|
|
151
|
+
return self.axes_handler.axes_setup
|
|
152
|
+
|
|
133
153
|
@property
|
|
134
154
|
def axes(self) -> tuple[str, ...]:
|
|
135
155
|
"""Return the axes of the image."""
|
|
@@ -199,6 +219,47 @@ class AbstractImage(ABC):
|
|
|
199
219
|
"""Return True if the image has the given axis."""
|
|
200
220
|
return self.axes_handler.has_axis(axis)
|
|
201
221
|
|
|
222
|
+
def set_axes_unit(
|
|
223
|
+
self,
|
|
224
|
+
space_unit: SpaceUnits = DefaultSpaceUnit,
|
|
225
|
+
time_unit: TimeUnits = DefaultTimeUnit,
|
|
226
|
+
) -> None:
|
|
227
|
+
"""Set the axes unit of the image.
|
|
228
|
+
|
|
229
|
+
Args:
|
|
230
|
+
space_unit (SpaceUnits): The space unit of the image.
|
|
231
|
+
time_unit (TimeUnits): The time unit of the image.
|
|
232
|
+
"""
|
|
233
|
+
meta = self._meta_handler.get_meta()
|
|
234
|
+
meta = meta.to_units(space_unit=space_unit, time_unit=time_unit)
|
|
235
|
+
self._meta_handler.update_meta(meta) # type: ignore
|
|
236
|
+
|
|
237
|
+
def set_axes_names(self, axes_names: Sequence[str]) -> None:
|
|
238
|
+
"""Set the axes names of the label.
|
|
239
|
+
|
|
240
|
+
Args:
|
|
241
|
+
axes_names (Sequence[str]): The axes names to set.
|
|
242
|
+
"""
|
|
243
|
+
meta = self._meta_handler.get_meta()
|
|
244
|
+
meta = meta.rename_axes(axes_names=axes_names)
|
|
245
|
+
self._meta_handler._axes_setup = meta.axes_handler.axes_setup
|
|
246
|
+
self._meta_handler.update_meta(meta) # type: ignore
|
|
247
|
+
|
|
248
|
+
def set_name(
|
|
249
|
+
self,
|
|
250
|
+
name: str,
|
|
251
|
+
) -> None:
|
|
252
|
+
"""Set the name of the image in the metadata.
|
|
253
|
+
|
|
254
|
+
This does not change the group name or any paths.
|
|
255
|
+
|
|
256
|
+
Args:
|
|
257
|
+
name (str): The name of the image.
|
|
258
|
+
"""
|
|
259
|
+
meta = self._meta_handler.get_meta()
|
|
260
|
+
meta = meta.rename_image(name=name)
|
|
261
|
+
self._meta_handler.update_meta(meta) # type: ignore
|
|
262
|
+
|
|
202
263
|
def _get_as_numpy(
|
|
203
264
|
self,
|
|
204
265
|
axes_order: Sequence[str] | None = None,
|
|
@@ -602,32 +663,39 @@ def consolidate_image(
|
|
|
602
663
|
|
|
603
664
|
def _shapes_from_ref_image(
|
|
604
665
|
ref_image: AbstractImage,
|
|
605
|
-
) -> list[tuple[int, ...]]:
|
|
666
|
+
) -> tuple[list[tuple[int, ...]], list[tuple[float, ...]]]:
|
|
606
667
|
"""Rebuild base shape based on a new shape."""
|
|
607
|
-
|
|
668
|
+
meta = ref_image.meta
|
|
669
|
+
paths = meta.paths
|
|
608
670
|
index_path = paths.index(ref_image.path)
|
|
609
671
|
sub_paths = paths[index_path:]
|
|
610
672
|
group_handler = ref_image._group_handler
|
|
611
|
-
shapes = []
|
|
673
|
+
shapes, scales = [], []
|
|
612
674
|
for path in sub_paths:
|
|
613
675
|
zarr_array = group_handler.get_array(path)
|
|
614
676
|
shapes.append(zarr_array.shape)
|
|
677
|
+
scales.append(meta.get_dataset(path=path).scale)
|
|
615
678
|
if len(shapes) == len(paths):
|
|
616
|
-
return shapes
|
|
679
|
+
return shapes, scales
|
|
617
680
|
missing_levels = len(paths) - len(shapes)
|
|
618
|
-
extended_shapes =
|
|
681
|
+
extended_shapes = compute_shapes_from_scaling_factors(
|
|
619
682
|
base_shape=shapes[-1],
|
|
620
683
|
scaling_factors=ref_image.meta.scaling_factor(),
|
|
621
684
|
num_levels=missing_levels + 1,
|
|
622
685
|
)
|
|
623
686
|
shapes.extend(extended_shapes[1:])
|
|
624
|
-
|
|
687
|
+
extended_scales = compute_scales_from_shapes(
|
|
688
|
+
shapes=extended_shapes,
|
|
689
|
+
base_scale=scales[-1],
|
|
690
|
+
)
|
|
691
|
+
scales.extend(extended_scales[1:])
|
|
692
|
+
return shapes, scales
|
|
625
693
|
|
|
626
694
|
|
|
627
695
|
def _shapes_from_new_shape(
|
|
628
696
|
ref_image: AbstractImage,
|
|
629
697
|
shape: Sequence[int],
|
|
630
|
-
) -> list[tuple[int, ...]]:
|
|
698
|
+
) -> tuple[list[tuple[int, ...]], list[tuple[float, ...]]]:
|
|
631
699
|
"""Rebuild pyramid shapes based on a new base shape."""
|
|
632
700
|
if len(shape) != len(ref_image.shape):
|
|
633
701
|
raise NgioValueError(
|
|
@@ -637,27 +705,33 @@ def _shapes_from_new_shape(
|
|
|
637
705
|
base_shape = tuple(shape)
|
|
638
706
|
scaling_factors = ref_image.meta.scaling_factor()
|
|
639
707
|
num_levels = len(ref_image.meta.paths)
|
|
640
|
-
|
|
708
|
+
shapes = compute_shapes_from_scaling_factors(
|
|
641
709
|
base_shape=base_shape,
|
|
642
710
|
scaling_factors=scaling_factors,
|
|
643
711
|
num_levels=num_levels,
|
|
644
712
|
)
|
|
713
|
+
scales = compute_scales_from_shapes(
|
|
714
|
+
shapes=shapes,
|
|
715
|
+
base_scale=ref_image.dataset.scale,
|
|
716
|
+
)
|
|
717
|
+
return shapes, scales
|
|
645
718
|
|
|
646
719
|
|
|
647
720
|
def _compute_pyramid_shapes(
|
|
648
721
|
ref_image: AbstractImage,
|
|
649
722
|
shape: Sequence[int] | None,
|
|
650
|
-
) -> list[tuple[int, ...]]:
|
|
723
|
+
) -> tuple[list[tuple[int, ...]], list[tuple[float, ...]]]:
|
|
651
724
|
"""Rebuild pyramid shapes based on a new base shape."""
|
|
652
725
|
if shape is None:
|
|
653
726
|
return _shapes_from_ref_image(ref_image=ref_image)
|
|
654
727
|
return _shapes_from_new_shape(ref_image=ref_image, shape=shape)
|
|
655
728
|
|
|
656
729
|
|
|
657
|
-
def
|
|
730
|
+
def _check_len_compatibility(
|
|
658
731
|
ref_shape: tuple[int, ...],
|
|
659
732
|
chunks: ChunksLike,
|
|
660
733
|
shards: ShardsLike | None,
|
|
734
|
+
translation: Sequence[float] | None = None,
|
|
661
735
|
) -> None:
|
|
662
736
|
"""Check if the chunks and shards are compatible with the reference shape.
|
|
663
737
|
|
|
@@ -665,6 +739,7 @@ def _check_chunks_and_shards_compatibility(
|
|
|
665
739
|
ref_shape: The reference shape.
|
|
666
740
|
chunks: The chunks to check.
|
|
667
741
|
shards: The shards to check.
|
|
742
|
+
translation: The translation to check.
|
|
668
743
|
"""
|
|
669
744
|
if chunks != "auto":
|
|
670
745
|
if len(chunks) != len(ref_shape):
|
|
@@ -676,6 +751,12 @@ def _check_chunks_and_shards_compatibility(
|
|
|
676
751
|
raise NgioValueError(
|
|
677
752
|
"The length of the shards must be the same as the number of dimensions."
|
|
678
753
|
)
|
|
754
|
+
if translation is not None:
|
|
755
|
+
if len(translation) != len(ref_shape):
|
|
756
|
+
raise NgioValueError(
|
|
757
|
+
"The length of the translation must be the same as the number of "
|
|
758
|
+
"dimensions."
|
|
759
|
+
)
|
|
679
760
|
|
|
680
761
|
|
|
681
762
|
def _apply_channel_policy(
|
|
@@ -685,7 +766,16 @@ def _apply_channel_policy(
|
|
|
685
766
|
axes: tuple[str, ...],
|
|
686
767
|
chunks: ChunksLike,
|
|
687
768
|
shards: ShardsLike | None,
|
|
688
|
-
|
|
769
|
+
translation: Sequence[float],
|
|
770
|
+
scales: list[tuple[float, ...]] | tuple[float, ...],
|
|
771
|
+
) -> tuple[
|
|
772
|
+
list[tuple[int, ...]],
|
|
773
|
+
tuple[str, ...],
|
|
774
|
+
ChunksLike,
|
|
775
|
+
ShardsLike | None,
|
|
776
|
+
tuple[float, ...],
|
|
777
|
+
list[tuple[float, ...]] | tuple[float, ...],
|
|
778
|
+
]:
|
|
689
779
|
"""Apply the channel policy to the shapes and axes.
|
|
690
780
|
|
|
691
781
|
Args:
|
|
@@ -695,12 +785,15 @@ def _apply_channel_policy(
|
|
|
695
785
|
axes: The axes of the image.
|
|
696
786
|
chunks: The chunks of the image.
|
|
697
787
|
shards: The shards of the image.
|
|
788
|
+
translation: The translation of the image.
|
|
789
|
+
scales: The scales of the image.
|
|
698
790
|
|
|
699
791
|
Returns:
|
|
700
792
|
The new shapes and axes after applying the channel policy.
|
|
701
793
|
"""
|
|
794
|
+
translation = tuple(translation)
|
|
702
795
|
if channels_policy == "same":
|
|
703
|
-
return shapes, axes, chunks, shards
|
|
796
|
+
return shapes, axes, chunks, shards, translation, scales
|
|
704
797
|
|
|
705
798
|
if channels_policy == "singleton":
|
|
706
799
|
# Treat 'singleton' as setting channel size to 1
|
|
@@ -709,7 +802,7 @@ def _apply_channel_policy(
|
|
|
709
802
|
channel_index = ref_image.axes_handler.get_index("c")
|
|
710
803
|
if channel_index is None:
|
|
711
804
|
if channels_policy == "squeeze":
|
|
712
|
-
return shapes, axes, chunks, shards
|
|
805
|
+
return shapes, axes, chunks, shards, translation, scales
|
|
713
806
|
raise NgioValueError(
|
|
714
807
|
f"Cannot apply channel policy {channels_policy=} to an image "
|
|
715
808
|
"without channels axis."
|
|
@@ -719,6 +812,15 @@ def _apply_channel_policy(
|
|
|
719
812
|
for shape in shapes:
|
|
720
813
|
new_shape = shape[:channel_index] + shape[channel_index + 1 :]
|
|
721
814
|
new_shapes.append(new_shape)
|
|
815
|
+
|
|
816
|
+
if isinstance(scales, tuple):
|
|
817
|
+
new_scales = scales[:channel_index] + scales[channel_index + 1 :]
|
|
818
|
+
else:
|
|
819
|
+
new_scales = []
|
|
820
|
+
for scale in scales:
|
|
821
|
+
new_scale = scale[:channel_index] + scale[channel_index + 1 :]
|
|
822
|
+
new_scales.append(new_scale)
|
|
823
|
+
|
|
722
824
|
new_axes = axes[:channel_index] + axes[channel_index + 1 :]
|
|
723
825
|
if chunks == "auto":
|
|
724
826
|
new_chunks: ChunksLike = "auto"
|
|
@@ -728,7 +830,9 @@ def _apply_channel_policy(
|
|
|
728
830
|
new_shards: ShardsLike | None = shards
|
|
729
831
|
else:
|
|
730
832
|
new_shards = shards[:channel_index] + shards[channel_index + 1 :]
|
|
731
|
-
|
|
833
|
+
|
|
834
|
+
translation = translation[:channel_index] + translation[channel_index + 1 :]
|
|
835
|
+
return new_shapes, new_axes, new_chunks, new_shards, translation, new_scales
|
|
732
836
|
elif isinstance(channels_policy, int):
|
|
733
837
|
new_shapes = []
|
|
734
838
|
for shape in shapes:
|
|
@@ -738,7 +842,7 @@ def _apply_channel_policy(
|
|
|
738
842
|
*shape[channel_index + 1 :],
|
|
739
843
|
)
|
|
740
844
|
new_shapes.append(new_shape)
|
|
741
|
-
return new_shapes, axes, chunks, shards
|
|
845
|
+
return new_shapes, axes, chunks, shards, translation, scales
|
|
742
846
|
else:
|
|
743
847
|
raise NgioValueError(
|
|
744
848
|
f"Invalid channels policy: {channels_policy}. "
|
|
@@ -783,6 +887,35 @@ def _check_channels_meta_compatibility(
|
|
|
783
887
|
return channels_meta_
|
|
784
888
|
|
|
785
889
|
|
|
890
|
+
def adapt_scales(
|
|
891
|
+
scales: list[tuple[float, ...]],
|
|
892
|
+
pixelsize: float | tuple[float, float] | None,
|
|
893
|
+
z_spacing: float | None,
|
|
894
|
+
time_spacing: float | None,
|
|
895
|
+
ref_image: AbstractImage,
|
|
896
|
+
) -> list[tuple[float, ...]] | tuple[float, ...]:
|
|
897
|
+
if pixelsize is None and z_spacing is None and time_spacing is None:
|
|
898
|
+
return scales
|
|
899
|
+
pixel_size = ref_image.pixel_size
|
|
900
|
+
if pixelsize is None:
|
|
901
|
+
pixelsize = (pixel_size.y, pixel_size.x)
|
|
902
|
+
if z_spacing is None:
|
|
903
|
+
z_spacing = pixel_size.z
|
|
904
|
+
else:
|
|
905
|
+
z_spacing = z_spacing
|
|
906
|
+
if time_spacing is None:
|
|
907
|
+
time_spacing = pixel_size.t
|
|
908
|
+
else:
|
|
909
|
+
time_spacing = time_spacing
|
|
910
|
+
base_scale = compute_base_scale(
|
|
911
|
+
pixelsize=pixelsize,
|
|
912
|
+
z_spacing=z_spacing,
|
|
913
|
+
time_spacing=time_spacing,
|
|
914
|
+
axes_handler=ref_image.axes_handler,
|
|
915
|
+
)
|
|
916
|
+
return base_scale
|
|
917
|
+
|
|
918
|
+
|
|
786
919
|
def abstract_derive(
|
|
787
920
|
*,
|
|
788
921
|
ref_image: AbstractImage,
|
|
@@ -795,6 +928,7 @@ def abstract_derive(
|
|
|
795
928
|
z_spacing: float | None = None,
|
|
796
929
|
time_spacing: float | None = None,
|
|
797
930
|
name: str | None = None,
|
|
931
|
+
translation: Sequence[float] | None = None,
|
|
798
932
|
channels_policy: Literal["squeeze", "same", "singleton"] | int = "same",
|
|
799
933
|
channels_meta: Sequence[str | Channel] | None = None,
|
|
800
934
|
ngff_version: NgffVersions | None = None,
|
|
@@ -808,7 +942,7 @@ def abstract_derive(
|
|
|
808
942
|
# Deprecated arguments
|
|
809
943
|
labels: Sequence[str] | None = None,
|
|
810
944
|
pixel_size: PixelSize | None = None,
|
|
811
|
-
) -> ZarrGroupHandler:
|
|
945
|
+
) -> tuple[ZarrGroupHandler, AxesSetup]:
|
|
812
946
|
"""Create an empty OME-Zarr image from an existing image.
|
|
813
947
|
|
|
814
948
|
If a kwarg is not provided, the value from the reference image will be used.
|
|
@@ -823,6 +957,8 @@ def abstract_derive(
|
|
|
823
957
|
z_spacing (float | None): The z spacing of the new image.
|
|
824
958
|
time_spacing (float | None): The time spacing of the new image.
|
|
825
959
|
name (str | None): The name of the new image.
|
|
960
|
+
translation (Sequence[float] | None): The translation for each axis
|
|
961
|
+
at the highest resolution level. Defaults to None.
|
|
826
962
|
channels_policy (Literal["squeeze", "same", "singleton"] | int):
|
|
827
963
|
Possible policies:
|
|
828
964
|
- If "squeeze", the channels axis will be removed (no matter its size).
|
|
@@ -853,54 +989,34 @@ def abstract_derive(
|
|
|
853
989
|
"""
|
|
854
990
|
# TODO: remove in ngio 0.6
|
|
855
991
|
if labels is not None:
|
|
856
|
-
|
|
992
|
+
logger.warning(
|
|
857
993
|
"The 'labels' argument is deprecated and will be removed in "
|
|
858
|
-
"
|
|
859
|
-
DeprecationWarning,
|
|
860
|
-
stacklevel=2,
|
|
994
|
+
"ngio=0.6. Please use 'channels_meta' instead."
|
|
861
995
|
)
|
|
862
996
|
channels_meta = list(labels)
|
|
863
997
|
if pixel_size is not None:
|
|
864
|
-
|
|
998
|
+
logger.warning(
|
|
865
999
|
"The 'pixel_size' argument is deprecated and will be removed in "
|
|
866
|
-
"
|
|
867
|
-
|
|
868
|
-
stacklevel=2,
|
|
1000
|
+
"ngio=0.6. Please use 'pixelsize', 'z_spacing', and 'time_spacing'"
|
|
1001
|
+
"instead."
|
|
869
1002
|
)
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
time_spacing_ = pixel_size.t
|
|
873
|
-
else:
|
|
874
|
-
if pixelsize is None:
|
|
875
|
-
pixelsize_ = (ref_image.pixel_size.y, ref_image.pixel_size.x)
|
|
876
|
-
else:
|
|
877
|
-
pixelsize_ = pixelsize
|
|
878
|
-
|
|
879
|
-
if z_spacing is None:
|
|
880
|
-
z_spacing_ = ref_image.pixel_size.z
|
|
881
|
-
else:
|
|
882
|
-
z_spacing_ = z_spacing
|
|
883
|
-
|
|
884
|
-
if time_spacing is None:
|
|
885
|
-
time_spacing_ = ref_image.pixel_size.t
|
|
886
|
-
else:
|
|
887
|
-
time_spacing_ = time_spacing
|
|
1003
|
+
pixelsize = (pixel_size.y, pixel_size.x)
|
|
1004
|
+
# End of deprecated arguments handling
|
|
888
1005
|
ref_meta = ref_image.meta
|
|
889
1006
|
|
|
890
|
-
shapes = _compute_pyramid_shapes(
|
|
1007
|
+
shapes, scales = _compute_pyramid_shapes(
|
|
891
1008
|
shape=shape,
|
|
892
1009
|
ref_image=ref_image,
|
|
893
1010
|
)
|
|
894
1011
|
ref_shape = next(iter(shapes))
|
|
895
1012
|
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
time_spacing = ref_image.pixel_size.t
|
|
1013
|
+
scales = adapt_scales(
|
|
1014
|
+
scales=scales,
|
|
1015
|
+
pixelsize=pixelsize,
|
|
1016
|
+
z_spacing=z_spacing,
|
|
1017
|
+
time_spacing=time_spacing,
|
|
1018
|
+
ref_image=ref_image,
|
|
1019
|
+
)
|
|
904
1020
|
|
|
905
1021
|
if name is None:
|
|
906
1022
|
name = ref_meta.name
|
|
@@ -914,27 +1030,33 @@ def abstract_derive(
|
|
|
914
1030
|
if compressors is None:
|
|
915
1031
|
compressors = ref_image.zarr_array.compressors # type: ignore
|
|
916
1032
|
|
|
1033
|
+
if translation is None:
|
|
1034
|
+
translation = ref_image.dataset.translation
|
|
1035
|
+
|
|
917
1036
|
if chunks is None:
|
|
918
1037
|
chunks = ref_image.zarr_array.chunks
|
|
919
1038
|
if shards is None:
|
|
920
1039
|
shards = ref_image.zarr_array.shards
|
|
921
1040
|
|
|
922
|
-
|
|
1041
|
+
_check_len_compatibility(
|
|
923
1042
|
ref_shape=ref_shape,
|
|
924
1043
|
chunks=chunks,
|
|
925
1044
|
shards=shards,
|
|
1045
|
+
translation=translation,
|
|
926
1046
|
)
|
|
927
1047
|
|
|
928
1048
|
if ngff_version is None:
|
|
929
1049
|
ngff_version = ref_meta.version
|
|
930
1050
|
|
|
931
|
-
shapes, axes, chunks, shards = _apply_channel_policy(
|
|
1051
|
+
shapes, axes, chunks, shards, translation, scales = _apply_channel_policy(
|
|
932
1052
|
ref_image=ref_image,
|
|
933
1053
|
channels_policy=channels_policy,
|
|
934
1054
|
shapes=shapes,
|
|
935
1055
|
axes=ref_image.axes,
|
|
936
1056
|
chunks=chunks,
|
|
937
1057
|
shards=shards,
|
|
1058
|
+
translation=translation,
|
|
1059
|
+
scales=scales,
|
|
938
1060
|
)
|
|
939
1061
|
channels_meta_ = _check_channels_meta_compatibility(
|
|
940
1062
|
meta_type=meta_type,
|
|
@@ -942,18 +1064,18 @@ def abstract_derive(
|
|
|
942
1064
|
channels_meta=channels_meta,
|
|
943
1065
|
)
|
|
944
1066
|
|
|
945
|
-
handler = init_image_like_from_shapes(
|
|
1067
|
+
handler, axes_setup = init_image_like_from_shapes(
|
|
946
1068
|
store=store,
|
|
947
1069
|
meta_type=meta_type,
|
|
948
1070
|
shapes=shapes,
|
|
949
|
-
|
|
950
|
-
z_spacing=z_spacing_,
|
|
951
|
-
time_spacing=time_spacing_,
|
|
1071
|
+
base_scale=scales,
|
|
952
1072
|
levels=ref_meta.paths,
|
|
1073
|
+
translation=translation,
|
|
953
1074
|
time_unit=ref_image.time_unit,
|
|
954
1075
|
space_unit=ref_image.space_unit,
|
|
955
1076
|
axes_names=axes,
|
|
956
1077
|
name=name,
|
|
1078
|
+
axes_setup=ref_image.axes_setup,
|
|
957
1079
|
channels_meta=channels_meta_,
|
|
958
1080
|
chunks=chunks,
|
|
959
1081
|
shards=shards,
|
|
@@ -964,4 +1086,4 @@ def abstract_derive(
|
|
|
964
1086
|
ngff_version=ngff_version,
|
|
965
1087
|
extra_array_kwargs=extra_array_kwargs,
|
|
966
1088
|
)
|
|
967
|
-
return handler
|
|
1089
|
+
return handler, axes_setup
|
|
@@ -30,6 +30,7 @@ def create_synthetic_ome_zarr(
|
|
|
30
30
|
shape: Sequence[int],
|
|
31
31
|
reference_sample: AVAILABLE_SAMPLES | SampleInfo = "Cardiomyocyte",
|
|
32
32
|
levels: int | list[str] = 5,
|
|
33
|
+
translation: Sequence[float] | None = None,
|
|
33
34
|
table_backend: TableBackend = DefaultTableBackend,
|
|
34
35
|
scaling_factors: Sequence[float] | Literal["auto"] = "auto",
|
|
35
36
|
axes_names: Sequence[str] | None = None,
|
|
@@ -51,6 +52,8 @@ def create_synthetic_ome_zarr(
|
|
|
51
52
|
Defaults to "Cardiomyocyte".
|
|
52
53
|
levels (int | list[str]): The number of levels in the pyramid or a list of
|
|
53
54
|
level names. Defaults to 5.
|
|
55
|
+
translation (Sequence[float] | None): The translation for each axis
|
|
56
|
+
at the highest resolution level. Defaults to None.
|
|
54
57
|
table_backend (TableBackend): Table backend to be used to store tables.
|
|
55
58
|
Defaults to DefaultTableBackend.
|
|
56
59
|
scaling_factors (Sequence[float] | Literal["auto"]): The down-scaling factors
|
|
@@ -82,10 +85,11 @@ def create_synthetic_ome_zarr(
|
|
|
82
85
|
ome_zarr = create_ome_zarr_from_array(
|
|
83
86
|
store=store,
|
|
84
87
|
array=raw,
|
|
85
|
-
pixelsize=sample_info.
|
|
88
|
+
pixelsize=sample_info.pixelsize,
|
|
86
89
|
z_spacing=sample_info.z_spacing,
|
|
87
90
|
time_spacing=sample_info.time_spacing,
|
|
88
91
|
levels=levels,
|
|
92
|
+
translation=translation,
|
|
89
93
|
space_unit=sample_info.space_unit,
|
|
90
94
|
time_unit=sample_info.time_unit,
|
|
91
95
|
axes_names=axes_names,
|