ngio 0.1.6__py3-none-any.whl → 0.2.0__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 +33 -5
- ngio/common/__init__.py +54 -0
- ngio/common/_array_pipe.py +265 -0
- ngio/common/_axes_transforms.py +64 -0
- ngio/common/_common_types.py +5 -0
- ngio/common/_dimensions.py +120 -0
- ngio/common/_masking_roi.py +158 -0
- ngio/common/_pyramid.py +228 -0
- ngio/common/_roi.py +165 -0
- ngio/common/_slicer.py +96 -0
- ngio/{pipes/_zoom_utils.py → common/_zoom.py} +7 -81
- ngio/hcs/__init__.py +5 -0
- ngio/hcs/plate.py +448 -0
- ngio/images/__init__.py +23 -0
- ngio/images/abstract_image.py +349 -0
- ngio/images/create.py +270 -0
- ngio/images/image.py +453 -0
- ngio/images/label.py +285 -0
- ngio/images/masked_image.py +273 -0
- ngio/images/ome_zarr_container.py +738 -0
- ngio/ome_zarr_meta/__init__.py +47 -0
- ngio/ome_zarr_meta/_meta_handlers.py +791 -0
- ngio/ome_zarr_meta/ngio_specs/__init__.py +71 -0
- ngio/ome_zarr_meta/ngio_specs/_axes.py +481 -0
- ngio/ome_zarr_meta/ngio_specs/_channels.py +389 -0
- ngio/ome_zarr_meta/ngio_specs/_dataset.py +134 -0
- ngio/ome_zarr_meta/ngio_specs/_ngio_hcs.py +377 -0
- ngio/ome_zarr_meta/ngio_specs/_ngio_image.py +489 -0
- ngio/ome_zarr_meta/ngio_specs/_pixel_size.py +116 -0
- ngio/ome_zarr_meta/v04/__init__.py +23 -0
- ngio/ome_zarr_meta/v04/_v04_spec_utils.py +485 -0
- ngio/tables/__init__.py +24 -6
- ngio/tables/_validators.py +190 -0
- ngio/tables/backends/__init__.py +8 -0
- ngio/tables/backends/_abstract_backend.py +71 -0
- ngio/tables/backends/_anndata_utils.py +198 -0
- ngio/tables/backends/_anndata_v1.py +76 -0
- ngio/tables/backends/_json_v1.py +56 -0
- ngio/tables/backends/_table_backends.py +102 -0
- ngio/tables/tables_container.py +310 -0
- ngio/tables/v1/__init__.py +5 -5
- ngio/tables/v1/_feature_table.py +182 -0
- ngio/tables/v1/_generic_table.py +160 -179
- ngio/tables/v1/_roi_table.py +366 -0
- ngio/utils/__init__.py +26 -10
- ngio/utils/_datasets.py +53 -0
- ngio/utils/_errors.py +10 -4
- ngio/utils/_fractal_fsspec_store.py +13 -0
- ngio/utils/_logger.py +3 -1
- ngio/utils/_zarr_utils.py +401 -0
- {ngio-0.1.6.dist-info → ngio-0.2.0.dist-info}/METADATA +30 -43
- ngio-0.2.0.dist-info/RECORD +54 -0
- ngio/core/__init__.py +0 -7
- ngio/core/dimensions.py +0 -122
- ngio/core/image_handler.py +0 -228
- ngio/core/image_like_handler.py +0 -549
- ngio/core/label_handler.py +0 -410
- ngio/core/ngff_image.py +0 -387
- ngio/core/roi.py +0 -92
- ngio/core/utils.py +0 -287
- ngio/io/__init__.py +0 -19
- ngio/io/_zarr.py +0 -88
- ngio/io/_zarr_array_utils.py +0 -0
- ngio/io/_zarr_group_utils.py +0 -60
- ngio/iterators/__init__.py +0 -1
- ngio/ngff_meta/__init__.py +0 -27
- ngio/ngff_meta/fractal_image_meta.py +0 -1267
- ngio/ngff_meta/meta_handler.py +0 -92
- ngio/ngff_meta/utils.py +0 -235
- ngio/ngff_meta/v04/__init__.py +0 -6
- ngio/ngff_meta/v04/specs.py +0 -158
- ngio/ngff_meta/v04/zarr_utils.py +0 -376
- ngio/pipes/__init__.py +0 -7
- ngio/pipes/_slicer_transforms.py +0 -176
- ngio/pipes/_transforms.py +0 -33
- ngio/pipes/data_pipe.py +0 -52
- ngio/tables/_ad_reader.py +0 -80
- ngio/tables/_utils.py +0 -301
- ngio/tables/tables_group.py +0 -252
- ngio/tables/v1/feature_tables.py +0 -182
- ngio/tables/v1/masking_roi_tables.py +0 -243
- ngio/tables/v1/roi_tables.py +0 -285
- ngio/utils/_common_types.py +0 -5
- ngio/utils/_pydantic_utils.py +0 -52
- ngio-0.1.6.dist-info/RECORD +0 -44
- {ngio-0.1.6.dist-info → ngio-0.2.0.dist-info}/WHEEL +0 -0
- {ngio-0.1.6.dist-info → ngio-0.2.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
"""Generic class to handle Image-like data in a OME-NGFF file."""
|
|
2
|
+
|
|
3
|
+
from collections.abc import Collection, Iterable
|
|
4
|
+
from typing import Generic, Literal, TypeVar
|
|
5
|
+
|
|
6
|
+
import zarr
|
|
7
|
+
|
|
8
|
+
from ngio.common import (
|
|
9
|
+
ArrayLike,
|
|
10
|
+
Dimensions,
|
|
11
|
+
Roi,
|
|
12
|
+
RoiPixels,
|
|
13
|
+
consolidate_pyramid,
|
|
14
|
+
get_pipe,
|
|
15
|
+
roi_to_slice_kwargs,
|
|
16
|
+
set_pipe,
|
|
17
|
+
)
|
|
18
|
+
from ngio.ome_zarr_meta import (
|
|
19
|
+
AxesMapper,
|
|
20
|
+
Dataset,
|
|
21
|
+
ImageMetaHandler,
|
|
22
|
+
LabelMetaHandler,
|
|
23
|
+
PixelSize,
|
|
24
|
+
)
|
|
25
|
+
from ngio.tables import RoiTable
|
|
26
|
+
from ngio.utils import NgioFileExistsError, ZarrGroupHandler
|
|
27
|
+
|
|
28
|
+
_image_handler = TypeVar("_image_handler", ImageMetaHandler, LabelMetaHandler)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class AbstractImage(Generic[_image_handler]):
|
|
32
|
+
"""A class to handle a single image (or level) in an OME-Zarr image.
|
|
33
|
+
|
|
34
|
+
This class is meant to be subclassed by specific image types.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
def __init__(
|
|
38
|
+
self,
|
|
39
|
+
group_handler: ZarrGroupHandler,
|
|
40
|
+
path: str,
|
|
41
|
+
meta_handler: _image_handler,
|
|
42
|
+
) -> None:
|
|
43
|
+
"""Initialize the Image at a single level.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
group_handler: The Zarr group handler.
|
|
47
|
+
path: The path to the image in the ome_zarr file.
|
|
48
|
+
meta_handler: The image metadata handler.
|
|
49
|
+
|
|
50
|
+
"""
|
|
51
|
+
self._path = path
|
|
52
|
+
self._group_handler = group_handler
|
|
53
|
+
self._meta_handler = meta_handler
|
|
54
|
+
|
|
55
|
+
self._dataset = self._meta_handler.meta.get_dataset(path=path)
|
|
56
|
+
self._pixel_size = self._dataset.pixel_size
|
|
57
|
+
|
|
58
|
+
try:
|
|
59
|
+
self._zarr_array = self._group_handler.get_array(self._dataset.path)
|
|
60
|
+
except NgioFileExistsError as e:
|
|
61
|
+
raise NgioFileExistsError(f"Could not find the dataset at {path}.") from e
|
|
62
|
+
|
|
63
|
+
self._dimensions = Dimensions(
|
|
64
|
+
shape=self._zarr_array.shape, axes_mapper=self._dataset.axes_mapper
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
self._axes_mapper = self._dataset.axes_mapper
|
|
68
|
+
|
|
69
|
+
def __repr__(self) -> str:
|
|
70
|
+
"""Return a string representation of the image."""
|
|
71
|
+
return f"Image(path={self.path}, {self.dimensions})"
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def meta_handler(self) -> _image_handler:
|
|
75
|
+
"""Return the metadata."""
|
|
76
|
+
return self._meta_handler
|
|
77
|
+
|
|
78
|
+
@property
|
|
79
|
+
def zarr_array(self) -> zarr.Array:
|
|
80
|
+
"""Return the Zarr array."""
|
|
81
|
+
return self._zarr_array
|
|
82
|
+
|
|
83
|
+
@property
|
|
84
|
+
def shape(self) -> tuple[int, ...]:
|
|
85
|
+
"""Return the shape of the image."""
|
|
86
|
+
return self.zarr_array.shape
|
|
87
|
+
|
|
88
|
+
@property
|
|
89
|
+
def dtype(self) -> str:
|
|
90
|
+
"""Return the dtype of the image."""
|
|
91
|
+
return str(self.zarr_array.dtype)
|
|
92
|
+
|
|
93
|
+
@property
|
|
94
|
+
def chunks(self) -> tuple[int, ...]:
|
|
95
|
+
"""Return the chunks of the image."""
|
|
96
|
+
return self.zarr_array.chunks
|
|
97
|
+
|
|
98
|
+
@property
|
|
99
|
+
def dimensions(self) -> Dimensions:
|
|
100
|
+
"""Return the dimensions of the image."""
|
|
101
|
+
return self._dimensions
|
|
102
|
+
|
|
103
|
+
@property
|
|
104
|
+
def axes_mapper(self) -> AxesMapper:
|
|
105
|
+
"""Return the axes mapper of the image."""
|
|
106
|
+
return self._axes_mapper
|
|
107
|
+
|
|
108
|
+
@property
|
|
109
|
+
def is_3d(self) -> bool:
|
|
110
|
+
"""Return True if the image is 3D."""
|
|
111
|
+
return self.dimensions.is_3d
|
|
112
|
+
|
|
113
|
+
@property
|
|
114
|
+
def is_2d(self) -> bool:
|
|
115
|
+
"""Return True if the image is 2D."""
|
|
116
|
+
return self.dimensions.is_2d
|
|
117
|
+
|
|
118
|
+
@property
|
|
119
|
+
def is_time_series(self) -> bool:
|
|
120
|
+
"""Return True if the image is a time series."""
|
|
121
|
+
return self.dimensions.is_time_series
|
|
122
|
+
|
|
123
|
+
@property
|
|
124
|
+
def is_2d_time_series(self) -> bool:
|
|
125
|
+
"""Return True if the image is a 2D time series."""
|
|
126
|
+
return self.dimensions.is_2d_time_series
|
|
127
|
+
|
|
128
|
+
@property
|
|
129
|
+
def is_3d_time_series(self) -> bool:
|
|
130
|
+
"""Return True if the image is a 3D time series."""
|
|
131
|
+
return self.dimensions.is_3d_time_series
|
|
132
|
+
|
|
133
|
+
@property
|
|
134
|
+
def is_multi_channels(self) -> bool:
|
|
135
|
+
"""Return True if the image is multichannel."""
|
|
136
|
+
return self.dimensions.is_multi_channels
|
|
137
|
+
|
|
138
|
+
@property
|
|
139
|
+
def pixel_size(self) -> PixelSize:
|
|
140
|
+
"""Return the pixel size of the image."""
|
|
141
|
+
return self._pixel_size
|
|
142
|
+
|
|
143
|
+
@property
|
|
144
|
+
def dataset(self) -> Dataset:
|
|
145
|
+
"""Return the dataset of the image."""
|
|
146
|
+
return self._dataset
|
|
147
|
+
|
|
148
|
+
@property
|
|
149
|
+
def path(self) -> str:
|
|
150
|
+
"""Return the path of the image."""
|
|
151
|
+
return self._dataset.path
|
|
152
|
+
|
|
153
|
+
def has_axis(self, axis: str) -> bool:
|
|
154
|
+
"""Return True if the image has the given axis."""
|
|
155
|
+
return self.dimensions.has_axis(axis)
|
|
156
|
+
|
|
157
|
+
def get_array(
|
|
158
|
+
self,
|
|
159
|
+
axes_order: Collection[str] | None = None,
|
|
160
|
+
mode: Literal["numpy", "dask", "delayed"] = "numpy",
|
|
161
|
+
**slice_kwargs: slice | int | Iterable[int],
|
|
162
|
+
) -> ArrayLike:
|
|
163
|
+
"""Get a slice of the image.
|
|
164
|
+
|
|
165
|
+
Args:
|
|
166
|
+
axes_order: The order of the axes to return the array.
|
|
167
|
+
mode: The mode to return the array.
|
|
168
|
+
**slice_kwargs: The slices to get the array.
|
|
169
|
+
|
|
170
|
+
Returns:
|
|
171
|
+
The array of the region of interest.
|
|
172
|
+
"""
|
|
173
|
+
return get_pipe(
|
|
174
|
+
array=self.zarr_array,
|
|
175
|
+
dimensions=self.dimensions,
|
|
176
|
+
axes_order=axes_order,
|
|
177
|
+
mode=mode,
|
|
178
|
+
**slice_kwargs,
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
def get_roi(
|
|
182
|
+
self,
|
|
183
|
+
roi: Roi,
|
|
184
|
+
axes_order: Collection[str] | None = None,
|
|
185
|
+
mode: Literal["numpy", "dask", "delayed"] = "numpy",
|
|
186
|
+
**slice_kwargs: slice | int | Iterable[int],
|
|
187
|
+
) -> ArrayLike:
|
|
188
|
+
"""Get a slice of the image.
|
|
189
|
+
|
|
190
|
+
Args:
|
|
191
|
+
roi: The region of interest to get the array.
|
|
192
|
+
axes_order: The order of the axes to return the array.
|
|
193
|
+
mode: The mode to return the array.
|
|
194
|
+
**slice_kwargs: The slices to get the array.
|
|
195
|
+
|
|
196
|
+
Returns:
|
|
197
|
+
The array of the region of interest.
|
|
198
|
+
"""
|
|
199
|
+
return get_roi_pipe(
|
|
200
|
+
image=self, roi=roi, axes_order=axes_order, mode=mode, **slice_kwargs
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
def set_array(
|
|
204
|
+
self,
|
|
205
|
+
patch: ArrayLike,
|
|
206
|
+
axes_order: Collection[str] | None = None,
|
|
207
|
+
**slice_kwargs: slice | int | Iterable[int],
|
|
208
|
+
) -> None:
|
|
209
|
+
"""Set a slice of the image.
|
|
210
|
+
|
|
211
|
+
Args:
|
|
212
|
+
patch: The patch to set.
|
|
213
|
+
axes_order: The order of the axes to set the patch.
|
|
214
|
+
**slice_kwargs: The slices to set the patch.
|
|
215
|
+
|
|
216
|
+
"""
|
|
217
|
+
set_pipe(
|
|
218
|
+
array=self.zarr_array,
|
|
219
|
+
patch=patch,
|
|
220
|
+
dimensions=self.dimensions,
|
|
221
|
+
axes_order=axes_order,
|
|
222
|
+
**slice_kwargs,
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
def set_roi(
|
|
226
|
+
self,
|
|
227
|
+
roi: Roi,
|
|
228
|
+
patch: ArrayLike,
|
|
229
|
+
axes_order: Collection[str] | None = None,
|
|
230
|
+
**slice_kwargs: slice | int | Iterable[int],
|
|
231
|
+
) -> None:
|
|
232
|
+
"""Set a slice of the image.
|
|
233
|
+
|
|
234
|
+
Args:
|
|
235
|
+
roi: The region of interest to set the patch.
|
|
236
|
+
patch: The patch to set.
|
|
237
|
+
axes_order: The order of the axes to set the patch.
|
|
238
|
+
**slice_kwargs: The slices to set the patch.
|
|
239
|
+
|
|
240
|
+
"""
|
|
241
|
+
return set_roi_pipe(
|
|
242
|
+
image=self, roi=roi, patch=patch, axes_order=axes_order, **slice_kwargs
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
def build_image_roi_table(self, name: str = "image") -> RoiTable:
|
|
246
|
+
"""Build the ROI table for an image."""
|
|
247
|
+
return build_image_roi_table(image=self, name=name)
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def consolidate_image(
|
|
251
|
+
image: AbstractImage,
|
|
252
|
+
order: Literal[0, 1, 2] = 1,
|
|
253
|
+
mode: Literal["dask", "numpy", "coarsen"] = "dask",
|
|
254
|
+
) -> None:
|
|
255
|
+
"""Consolidate the image on disk."""
|
|
256
|
+
target_paths = image._meta_handler.meta.paths
|
|
257
|
+
targets = [
|
|
258
|
+
image._group_handler.get_array(path)
|
|
259
|
+
for path in target_paths
|
|
260
|
+
if path != image.path
|
|
261
|
+
]
|
|
262
|
+
consolidate_pyramid(
|
|
263
|
+
source=image.zarr_array, targets=targets, order=order, mode=mode
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
def get_roi_pipe(
|
|
268
|
+
image: AbstractImage,
|
|
269
|
+
roi: Roi,
|
|
270
|
+
axes_order: Collection[str] | None = None,
|
|
271
|
+
mode: Literal["numpy", "dask", "delayed"] = "numpy",
|
|
272
|
+
**slice_kwargs: slice | int | Iterable[int],
|
|
273
|
+
) -> ArrayLike:
|
|
274
|
+
"""Get a slice of the image.
|
|
275
|
+
|
|
276
|
+
Args:
|
|
277
|
+
image: The image to get the ROI.
|
|
278
|
+
roi: The region of interest to get the array.
|
|
279
|
+
axes_order: The order of the axes to return the array.
|
|
280
|
+
mode: The mode to return the array.
|
|
281
|
+
**slice_kwargs: The slices to get the array.
|
|
282
|
+
|
|
283
|
+
Returns:
|
|
284
|
+
The array of the region of interest.
|
|
285
|
+
"""
|
|
286
|
+
slice_kwargs = roi_to_slice_kwargs(
|
|
287
|
+
roi=roi,
|
|
288
|
+
pixel_size=image.pixel_size,
|
|
289
|
+
dimensions=image.dimensions,
|
|
290
|
+
**slice_kwargs,
|
|
291
|
+
)
|
|
292
|
+
return get_pipe(
|
|
293
|
+
array=image.zarr_array,
|
|
294
|
+
dimensions=image.dimensions,
|
|
295
|
+
axes_order=axes_order,
|
|
296
|
+
mode=mode,
|
|
297
|
+
**slice_kwargs,
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def set_roi_pipe(
|
|
302
|
+
image: AbstractImage,
|
|
303
|
+
roi: Roi,
|
|
304
|
+
patch: ArrayLike,
|
|
305
|
+
axes_order: Collection[str] | None = None,
|
|
306
|
+
**slice_kwargs: slice | int | Iterable[int],
|
|
307
|
+
) -> None:
|
|
308
|
+
"""Set a slice of the image.
|
|
309
|
+
|
|
310
|
+
Args:
|
|
311
|
+
image: The image to set the ROI.
|
|
312
|
+
roi: The region of interest to set the patch.
|
|
313
|
+
patch: The patch to set.
|
|
314
|
+
axes_order: The order of the axes to set the patch.
|
|
315
|
+
**slice_kwargs: The slices to set the patch.
|
|
316
|
+
|
|
317
|
+
"""
|
|
318
|
+
slice_kwargs = roi_to_slice_kwargs(
|
|
319
|
+
roi=roi,
|
|
320
|
+
pixel_size=image.pixel_size,
|
|
321
|
+
dimensions=image.dimensions,
|
|
322
|
+
**slice_kwargs,
|
|
323
|
+
)
|
|
324
|
+
set_pipe(
|
|
325
|
+
array=image.zarr_array,
|
|
326
|
+
patch=patch,
|
|
327
|
+
dimensions=image.dimensions,
|
|
328
|
+
axes_order=axes_order,
|
|
329
|
+
**slice_kwargs,
|
|
330
|
+
)
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
def build_image_roi_table(image: AbstractImage, name: str = "image") -> RoiTable:
|
|
334
|
+
"""Build the ROI table for an image."""
|
|
335
|
+
dim_z, dim_y, dim_x = (
|
|
336
|
+
image.dimensions.get("z", strict=False),
|
|
337
|
+
image.dimensions.get("y"),
|
|
338
|
+
image.dimensions.get("x"),
|
|
339
|
+
)
|
|
340
|
+
image_roi = RoiPixels(
|
|
341
|
+
name=name,
|
|
342
|
+
x=0,
|
|
343
|
+
y=0,
|
|
344
|
+
z=0,
|
|
345
|
+
x_length=dim_x,
|
|
346
|
+
y_length=dim_y,
|
|
347
|
+
z_length=dim_z,
|
|
348
|
+
)
|
|
349
|
+
return RoiTable(rois=[image_roi.to_roi(pixel_size=image.pixel_size)])
|
ngio/images/create.py
ADDED
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
"""Utility functions for working with OME-Zarr images."""
|
|
2
|
+
|
|
3
|
+
from collections.abc import Collection
|
|
4
|
+
from typing import TypeVar
|
|
5
|
+
|
|
6
|
+
from ngio.common._pyramid import init_empty_pyramid
|
|
7
|
+
from ngio.ome_zarr_meta import (
|
|
8
|
+
NgioImageMeta,
|
|
9
|
+
NgioLabelMeta,
|
|
10
|
+
PixelSize,
|
|
11
|
+
get_image_meta_handler,
|
|
12
|
+
get_label_meta_handler,
|
|
13
|
+
)
|
|
14
|
+
from ngio.ome_zarr_meta.ngio_specs import (
|
|
15
|
+
SpaceUnits,
|
|
16
|
+
TimeUnits,
|
|
17
|
+
canonical_axes_order,
|
|
18
|
+
canonical_label_axes_order,
|
|
19
|
+
)
|
|
20
|
+
from ngio.utils import NgioValueError, StoreOrGroup, ZarrGroupHandler
|
|
21
|
+
|
|
22
|
+
_image_or_label_meta = TypeVar("_image_or_label_meta", NgioImageMeta, NgioLabelMeta)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _init_generic_meta(
|
|
26
|
+
meta_type: type[_image_or_label_meta],
|
|
27
|
+
pixelsize: float,
|
|
28
|
+
axes_names: Collection[str],
|
|
29
|
+
z_spacing: float = 1.0,
|
|
30
|
+
time_spacing: float = 1.0,
|
|
31
|
+
levels: int | list[str] = 5,
|
|
32
|
+
yx_scaling_factor: float | tuple[float, float] = 2.0,
|
|
33
|
+
z_scaling_factor: float = 1.0,
|
|
34
|
+
space_unit: SpaceUnits | str | None = None,
|
|
35
|
+
time_unit: TimeUnits | str | None = None,
|
|
36
|
+
name: str | None = None,
|
|
37
|
+
version: str = "0.4",
|
|
38
|
+
) -> tuple[_image_or_label_meta, list[float]]:
|
|
39
|
+
"""Initialize the metadata for an image or label."""
|
|
40
|
+
scaling_factors = []
|
|
41
|
+
for ax in axes_names:
|
|
42
|
+
if ax == "z":
|
|
43
|
+
scaling_factors.append(z_scaling_factor)
|
|
44
|
+
elif ax in ["x"]:
|
|
45
|
+
if isinstance(yx_scaling_factor, tuple):
|
|
46
|
+
scaling_factors.append(yx_scaling_factor[1])
|
|
47
|
+
else:
|
|
48
|
+
scaling_factors.append(yx_scaling_factor)
|
|
49
|
+
elif ax in ["y"]:
|
|
50
|
+
if isinstance(yx_scaling_factor, tuple):
|
|
51
|
+
scaling_factors.append(yx_scaling_factor[0])
|
|
52
|
+
else:
|
|
53
|
+
scaling_factors.append(yx_scaling_factor)
|
|
54
|
+
else:
|
|
55
|
+
scaling_factors.append(1.0)
|
|
56
|
+
|
|
57
|
+
if space_unit is None:
|
|
58
|
+
space_unit = SpaceUnits.micrometer
|
|
59
|
+
elif isinstance(space_unit, str):
|
|
60
|
+
space_unit = SpaceUnits(space_unit)
|
|
61
|
+
elif not isinstance(space_unit, SpaceUnits):
|
|
62
|
+
raise NgioValueError(f"space_unit can not be {type(space_unit)}.")
|
|
63
|
+
|
|
64
|
+
if time_unit is None:
|
|
65
|
+
time_unit = TimeUnits.seconds
|
|
66
|
+
elif isinstance(time_unit, str):
|
|
67
|
+
time_unit = TimeUnits(time_unit)
|
|
68
|
+
elif not isinstance(time_unit, TimeUnits):
|
|
69
|
+
raise NgioValueError(f"time_units can not be {type(time_unit)}.")
|
|
70
|
+
|
|
71
|
+
pixel_sizes = PixelSize(
|
|
72
|
+
x=pixelsize,
|
|
73
|
+
y=pixelsize,
|
|
74
|
+
z=z_spacing,
|
|
75
|
+
t=time_spacing,
|
|
76
|
+
space_unit=space_unit,
|
|
77
|
+
time_unit=time_unit,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
meta = meta_type.default_init(
|
|
81
|
+
name=name,
|
|
82
|
+
levels=levels,
|
|
83
|
+
axes_names=axes_names,
|
|
84
|
+
pixel_size=pixel_sizes,
|
|
85
|
+
scaling_factors=scaling_factors,
|
|
86
|
+
version=version,
|
|
87
|
+
)
|
|
88
|
+
return meta, scaling_factors
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def _create_empty_label(
|
|
92
|
+
store: StoreOrGroup,
|
|
93
|
+
shape: Collection[int],
|
|
94
|
+
pixelsize: float,
|
|
95
|
+
z_spacing: float = 1.0,
|
|
96
|
+
time_spacing: float = 1.0,
|
|
97
|
+
levels: int | list[str] = 5,
|
|
98
|
+
yx_scaling_factor: float | tuple[float, float] = 2.0,
|
|
99
|
+
z_scaling_factor: float = 1.0,
|
|
100
|
+
space_unit: SpaceUnits | str | None = None,
|
|
101
|
+
time_unit: TimeUnits | str | None = None,
|
|
102
|
+
axes_names: Collection[str] | None = None,
|
|
103
|
+
name: str | None = None,
|
|
104
|
+
chunks: Collection[int] | None = None,
|
|
105
|
+
dtype: str = "uint16",
|
|
106
|
+
overwrite: bool = False,
|
|
107
|
+
version: str = "0.4",
|
|
108
|
+
) -> ZarrGroupHandler:
|
|
109
|
+
"""Create an empty label with the given shape and metadata.
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
store (StoreOrGroup): The Zarr store or group to create the image in.
|
|
113
|
+
shape (Collection[int]): The shape of the image.
|
|
114
|
+
pixelsize (float): The pixel size in x and y dimensions.
|
|
115
|
+
z_spacing (float, optional): The spacing between z slices. Defaults to 1.0.
|
|
116
|
+
time_spacing (float, optional): The spacing between time points.
|
|
117
|
+
Defaults to 1.0.
|
|
118
|
+
levels (int | list[str], optional): The number of levels in the pyramid or a
|
|
119
|
+
list of level names. Defaults to 5.
|
|
120
|
+
yx_scaling_factor (float, optional): The down-scaling factor in x and y
|
|
121
|
+
dimensions. Defaults to 2.0.
|
|
122
|
+
z_scaling_factor (float, optional): The down-scaling factor in z dimension.
|
|
123
|
+
Defaults to 1.0.
|
|
124
|
+
space_unit (SpaceUnits | str | None, optional): The unit of space. Defaults to
|
|
125
|
+
None.
|
|
126
|
+
time_unit (TimeUnits | str | None, optional): The unit of time. Defaults to
|
|
127
|
+
None.
|
|
128
|
+
axes_names (Collection[str] | None, optional): The names of the axes.
|
|
129
|
+
If None the canonical names are used. Defaults to None.
|
|
130
|
+
name (str | None, optional): The name of the image. Defaults to None.
|
|
131
|
+
chunks (Collection[int] | None, optional): The chunk shape. If None the shape
|
|
132
|
+
is used. Defaults to None.
|
|
133
|
+
dtype (str, optional): The data type of the image. Defaults to "uint16".
|
|
134
|
+
overwrite (bool, optional): Whether to overwrite an existing image.
|
|
135
|
+
Defaults to True.
|
|
136
|
+
version (str, optional): The version of the OME-Zarr specification.
|
|
137
|
+
Defaults to "0.4".
|
|
138
|
+
|
|
139
|
+
"""
|
|
140
|
+
if axes_names is None:
|
|
141
|
+
axes_names = canonical_label_axes_order()[-len(shape) :]
|
|
142
|
+
|
|
143
|
+
if len(axes_names) != len(shape):
|
|
144
|
+
raise NgioValueError(
|
|
145
|
+
f"Number of axes names {axes_names} does not match the number of "
|
|
146
|
+
f"dimensions {shape}."
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
meta, scaling_factors = _init_generic_meta(
|
|
150
|
+
meta_type=NgioLabelMeta,
|
|
151
|
+
pixelsize=pixelsize,
|
|
152
|
+
z_spacing=z_spacing,
|
|
153
|
+
time_spacing=time_spacing,
|
|
154
|
+
levels=levels,
|
|
155
|
+
yx_scaling_factor=yx_scaling_factor,
|
|
156
|
+
z_scaling_factor=z_scaling_factor,
|
|
157
|
+
space_unit=space_unit,
|
|
158
|
+
time_unit=time_unit,
|
|
159
|
+
axes_names=axes_names,
|
|
160
|
+
name=name,
|
|
161
|
+
version=version,
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
mode = "w" if overwrite else "w-"
|
|
165
|
+
group_handler = ZarrGroupHandler(store=store, mode=mode, cache=False)
|
|
166
|
+
image_handler = get_label_meta_handler(version=version, group_handler=group_handler)
|
|
167
|
+
image_handler.write_meta(meta)
|
|
168
|
+
|
|
169
|
+
init_empty_pyramid(
|
|
170
|
+
store=store,
|
|
171
|
+
paths=meta.paths,
|
|
172
|
+
scaling_factors=scaling_factors,
|
|
173
|
+
ref_shape=shape,
|
|
174
|
+
chunks=chunks,
|
|
175
|
+
dtype=dtype,
|
|
176
|
+
mode="a",
|
|
177
|
+
)
|
|
178
|
+
group_handler._mode = "r+"
|
|
179
|
+
return group_handler
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def _create_empty_image(
|
|
183
|
+
store: StoreOrGroup,
|
|
184
|
+
shape: Collection[int],
|
|
185
|
+
pixelsize: float,
|
|
186
|
+
z_spacing: float = 1.0,
|
|
187
|
+
time_spacing: float = 1.0,
|
|
188
|
+
levels: int | list[str] = 5,
|
|
189
|
+
yx_scaling_factor: float | tuple[float, float] = 2,
|
|
190
|
+
z_scaling_factor: float = 1.0,
|
|
191
|
+
space_unit: SpaceUnits | str | None = None,
|
|
192
|
+
time_unit: TimeUnits | str | None = None,
|
|
193
|
+
axes_names: Collection[str] | None = None,
|
|
194
|
+
name: str | None = None,
|
|
195
|
+
chunks: Collection[int] | None = None,
|
|
196
|
+
dtype: str = "uint16",
|
|
197
|
+
overwrite: bool = False,
|
|
198
|
+
version: str = "0.4",
|
|
199
|
+
) -> ZarrGroupHandler:
|
|
200
|
+
"""Create an empty OME-Zarr image with the given shape and metadata.
|
|
201
|
+
|
|
202
|
+
Args:
|
|
203
|
+
store (StoreOrGroup): The Zarr store or group to create the image in.
|
|
204
|
+
shape (Collection[int]): The shape of the image.
|
|
205
|
+
pixelsize (float): The pixel size in x and y dimensions.
|
|
206
|
+
z_spacing (float, optional): The spacing between z slices. Defaults to 1.0.
|
|
207
|
+
time_spacing (float, optional): The spacing between time points.
|
|
208
|
+
Defaults to 1.0.
|
|
209
|
+
levels (int | list[str], optional): The number of levels in the pyramid or a
|
|
210
|
+
list of level names. Defaults to 5.
|
|
211
|
+
yx_scaling_factor (float, optional): The down-scaling factor in x and y
|
|
212
|
+
dimensions. Defaults to 2.0.
|
|
213
|
+
z_scaling_factor (float, optional): The down-scaling factor in z dimension.
|
|
214
|
+
Defaults to 1.0.
|
|
215
|
+
space_unit (SpaceUnits | str | None, optional): The unit of space. Defaults to
|
|
216
|
+
None.
|
|
217
|
+
time_unit (TimeUnits | str | None, optional): The unit of time. Defaults to
|
|
218
|
+
None.
|
|
219
|
+
axes_names (Collection[str] | None, optional): The names of the axes.
|
|
220
|
+
If None the canonical names are used. Defaults to None.
|
|
221
|
+
name (str | None, optional): The name of the image. Defaults to None.
|
|
222
|
+
chunks (Collection[int] | None, optional): The chunk shape. If None the shape
|
|
223
|
+
is used. Defaults to None.
|
|
224
|
+
dtype (str, optional): The data type of the image. Defaults to "uint16".
|
|
225
|
+
overwrite (bool, optional): Whether to overwrite an existing image.
|
|
226
|
+
Defaults to True.
|
|
227
|
+
version (str, optional): The version of the OME-Zarr specification.
|
|
228
|
+
Defaults to "0.4".
|
|
229
|
+
|
|
230
|
+
"""
|
|
231
|
+
if axes_names is None:
|
|
232
|
+
axes_names = canonical_axes_order()[-len(shape) :]
|
|
233
|
+
|
|
234
|
+
if len(axes_names) != len(shape):
|
|
235
|
+
raise NgioValueError(
|
|
236
|
+
f"Number of axes names {axes_names} does not match the number of "
|
|
237
|
+
f"dimensions {shape}."
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
meta, scaling_factors = _init_generic_meta(
|
|
241
|
+
meta_type=NgioImageMeta,
|
|
242
|
+
pixelsize=pixelsize,
|
|
243
|
+
z_spacing=z_spacing,
|
|
244
|
+
time_spacing=time_spacing,
|
|
245
|
+
levels=levels,
|
|
246
|
+
yx_scaling_factor=yx_scaling_factor,
|
|
247
|
+
z_scaling_factor=z_scaling_factor,
|
|
248
|
+
space_unit=space_unit,
|
|
249
|
+
time_unit=time_unit,
|
|
250
|
+
axes_names=axes_names,
|
|
251
|
+
name=name,
|
|
252
|
+
version=version,
|
|
253
|
+
)
|
|
254
|
+
mode = "w" if overwrite else "w-"
|
|
255
|
+
group_handler = ZarrGroupHandler(store=store, mode=mode, cache=False)
|
|
256
|
+
image_handler = get_image_meta_handler(version=version, group_handler=group_handler)
|
|
257
|
+
image_handler.write_meta(meta)
|
|
258
|
+
|
|
259
|
+
init_empty_pyramid(
|
|
260
|
+
store=store,
|
|
261
|
+
paths=meta.paths,
|
|
262
|
+
scaling_factors=scaling_factors,
|
|
263
|
+
ref_shape=shape,
|
|
264
|
+
chunks=chunks,
|
|
265
|
+
dtype=dtype,
|
|
266
|
+
mode="a",
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
group_handler._mode = "r+"
|
|
270
|
+
return group_handler
|