ngio 0.2.0a2__py3-none-any.whl → 0.2.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 +4 -4
- ngio/common/__init__.py +12 -2
- ngio/common/_array_pipe.py +106 -0
- ngio/common/_axes_transforms.py +3 -2
- ngio/common/_dimensions.py +7 -0
- ngio/common/_masking_roi.py +158 -0
- ngio/common/_pyramid.py +16 -11
- ngio/common/_roi.py +74 -0
- ngio/common/_slicer.py +1 -2
- ngio/common/_zoom.py +5 -3
- ngio/hcs/__init__.py +2 -57
- ngio/hcs/plate.py +399 -0
- ngio/images/abstract_image.py +97 -28
- ngio/images/create.py +48 -29
- ngio/images/image.py +121 -57
- ngio/images/label.py +131 -86
- ngio/images/masked_image.py +259 -0
- ngio/images/omezarr_container.py +250 -77
- ngio/ome_zarr_meta/__init__.py +25 -13
- ngio/ome_zarr_meta/_meta_handlers.py +718 -69
- ngio/ome_zarr_meta/ngio_specs/__init__.py +8 -0
- ngio/ome_zarr_meta/ngio_specs/_channels.py +11 -0
- ngio/ome_zarr_meta/ngio_specs/_ngio_hcs.py +374 -2
- ngio/ome_zarr_meta/ngio_specs/_ngio_image.py +174 -113
- ngio/ome_zarr_meta/ngio_specs/_pixel_size.py +35 -3
- ngio/ome_zarr_meta/v04/__init__.py +17 -5
- ngio/ome_zarr_meta/v04/_v04_spec_utils.py +85 -12
- ngio/tables/__init__.py +2 -0
- ngio/tables/_validators.py +2 -4
- ngio/tables/backends/_anndata_utils.py +2 -1
- ngio/tables/backends/_anndata_v1.py +2 -1
- ngio/tables/backends/_json_v1.py +1 -1
- ngio/tables/tables_container.py +12 -2
- ngio/tables/v1/__init__.py +1 -2
- ngio/tables/v1/_feature_table.py +7 -5
- ngio/tables/v1/_generic_table.py +65 -11
- ngio/tables/v1/_roi_table.py +145 -27
- ngio/utils/__init__.py +3 -0
- ngio/utils/_datasets.py +4 -2
- ngio/utils/_fractal_fsspec_store.py +13 -0
- ngio/utils/_logger.py +3 -1
- ngio/utils/_zarr_utils.py +25 -2
- {ngio-0.2.0a2.dist-info → ngio-0.2.0b1.dist-info}/METADATA +4 -1
- ngio-0.2.0b1.dist-info/RECORD +54 -0
- ngio/ome_zarr_meta/_generic_handlers.py +0 -320
- ngio/ome_zarr_meta/v04/_meta_handlers.py +0 -54
- ngio/tables/v1/_masking_roi_table.py +0 -175
- ngio-0.2.0a2.dist-info/RECORD +0 -53
- {ngio-0.2.0a2.dist-info → ngio-0.2.0b1.dist-info}/WHEEL +0 -0
- {ngio-0.2.0a2.dist-info → ngio-0.2.0b1.dist-info}/licenses/LICENSE +0 -0
ngio/hcs/plate.py
ADDED
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
"""A module for handling the Plate Collection in an OME-Zarr file."""
|
|
2
|
+
|
|
3
|
+
from ngio.images import OmeZarrContainer
|
|
4
|
+
from ngio.ome_zarr_meta import (
|
|
5
|
+
ImageInWellPath,
|
|
6
|
+
NgioPlateMeta,
|
|
7
|
+
NgioWellMeta,
|
|
8
|
+
find_plate_meta_handler,
|
|
9
|
+
find_well_meta_handler,
|
|
10
|
+
get_plate_meta_handler,
|
|
11
|
+
get_well_meta_handler,
|
|
12
|
+
)
|
|
13
|
+
from ngio.utils import (
|
|
14
|
+
AccessModeLiteral,
|
|
15
|
+
StoreOrGroup,
|
|
16
|
+
ZarrGroupHandler,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# Mock lock class that does nothing
|
|
21
|
+
class MockLock:
|
|
22
|
+
"""A mock lock class that does nothing."""
|
|
23
|
+
|
|
24
|
+
def __enter__(self):
|
|
25
|
+
"""Enter the lock."""
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
def __exit__(self, exc_type, exc_value, traceback):
|
|
29
|
+
"""Exit the lock."""
|
|
30
|
+
pass
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class OmeZarrWell:
|
|
34
|
+
"""A class to handle the Well Collection in an OME-Zarr file."""
|
|
35
|
+
|
|
36
|
+
def __init__(self, group_handler: ZarrGroupHandler) -> None:
|
|
37
|
+
"""Initialize the LabelGroupHandler.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
group_handler: The Zarr group handler that contains the Well.
|
|
41
|
+
"""
|
|
42
|
+
self._group_handler = group_handler
|
|
43
|
+
self._meta_handler = find_well_meta_handler(group_handler)
|
|
44
|
+
|
|
45
|
+
@property
|
|
46
|
+
def meta_handler(self):
|
|
47
|
+
"""Return the metadata handler."""
|
|
48
|
+
return self._meta_handler
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def meta(self):
|
|
52
|
+
"""Return the metadata."""
|
|
53
|
+
return self._meta_handler.meta
|
|
54
|
+
|
|
55
|
+
def paths(self, acquisition: int | None = None) -> list[str]:
|
|
56
|
+
"""Return the images paths in the well.
|
|
57
|
+
|
|
58
|
+
If acquisition is None, return all images paths in the well.
|
|
59
|
+
Else, return the images paths in the well for the given acquisition.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
acquisition (int | None): The acquisition id to filter the images.
|
|
63
|
+
"""
|
|
64
|
+
return self.meta.paths(acquisition)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class OmeZarrPlate:
|
|
68
|
+
"""A class to handle the Plate Collection in an OME-Zarr file."""
|
|
69
|
+
|
|
70
|
+
def __init__(self, group_handler: ZarrGroupHandler) -> None:
|
|
71
|
+
"""Initialize the LabelGroupHandler.
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
group_handler: The Zarr group handler that contains the Plate.
|
|
75
|
+
"""
|
|
76
|
+
self._group_handler = group_handler
|
|
77
|
+
self._meta_handler = find_plate_meta_handler(group_handler)
|
|
78
|
+
|
|
79
|
+
def __repr__(self) -> str:
|
|
80
|
+
"""Return a string representation of the plate."""
|
|
81
|
+
return f"Plate([rows x columns] ({len(self.rows)} x {len(self.columns)})"
|
|
82
|
+
|
|
83
|
+
@property
|
|
84
|
+
def meta_handler(self):
|
|
85
|
+
"""Return the metadata handler."""
|
|
86
|
+
return self._meta_handler
|
|
87
|
+
|
|
88
|
+
@property
|
|
89
|
+
def meta(self):
|
|
90
|
+
"""Return the metadata."""
|
|
91
|
+
return self._meta_handler.meta
|
|
92
|
+
|
|
93
|
+
@property
|
|
94
|
+
def columns(self) -> list[str]:
|
|
95
|
+
"""Return the number of columns in the plate."""
|
|
96
|
+
return self.meta.columns
|
|
97
|
+
|
|
98
|
+
@property
|
|
99
|
+
def rows(self) -> list[str]:
|
|
100
|
+
"""Return the number of rows in the plate."""
|
|
101
|
+
return self.meta.rows
|
|
102
|
+
|
|
103
|
+
@property
|
|
104
|
+
def acquisitions_names(self) -> list[str | None]:
|
|
105
|
+
"""Return the acquisitions in the plate."""
|
|
106
|
+
return self.meta.acquisitions_names
|
|
107
|
+
|
|
108
|
+
@property
|
|
109
|
+
def acquisitions_ids(self) -> list[int]:
|
|
110
|
+
"""Return the acquisitions ids in the plate."""
|
|
111
|
+
return self.meta.acquisitions_ids
|
|
112
|
+
|
|
113
|
+
@property
|
|
114
|
+
def wells_paths(self) -> list[str]:
|
|
115
|
+
"""Return the wells paths in the plate."""
|
|
116
|
+
return self.meta.wells_paths
|
|
117
|
+
|
|
118
|
+
def get_well_path(self, row: str, column: int | str) -> str:
|
|
119
|
+
"""Return the well path in the plate."""
|
|
120
|
+
return self.meta.get_well_path(row=row, column=column)
|
|
121
|
+
|
|
122
|
+
def get_image_path(self, row: str, column: int | str, path: str) -> str:
|
|
123
|
+
"""Return the image path in the plate."""
|
|
124
|
+
well = self.get_well(row, column)
|
|
125
|
+
if path not in well.paths():
|
|
126
|
+
raise ValueError(f"Image {path} does not exist in well {row}{column}")
|
|
127
|
+
return f"{self.get_well_path(row, column)}/{path}"
|
|
128
|
+
|
|
129
|
+
def get_well(self, row: str, column: int | str) -> OmeZarrWell:
|
|
130
|
+
"""Get a well from the plate.
|
|
131
|
+
|
|
132
|
+
Args:
|
|
133
|
+
row (str): The row of the well.
|
|
134
|
+
column (int | str): The column of the well.
|
|
135
|
+
|
|
136
|
+
Returns:
|
|
137
|
+
OmeZarrWell: The well.
|
|
138
|
+
"""
|
|
139
|
+
well_path = self.meta.get_well_path(row=row, column=column)
|
|
140
|
+
group_handler = self._group_handler.derive_handler(well_path)
|
|
141
|
+
return OmeZarrWell(group_handler)
|
|
142
|
+
|
|
143
|
+
def get_wells(self) -> dict[str, OmeZarrWell]:
|
|
144
|
+
"""Get all wells in the plate."""
|
|
145
|
+
wells = {}
|
|
146
|
+
for well_path in self.wells_paths:
|
|
147
|
+
group_handler = self._group_handler.derive_handler(well_path)
|
|
148
|
+
well = OmeZarrWell(group_handler)
|
|
149
|
+
wells[well_path] = well
|
|
150
|
+
return wells
|
|
151
|
+
|
|
152
|
+
def get_images(self, acquisition: int | None = None) -> list[OmeZarrContainer]:
|
|
153
|
+
"""Get all images in the plate.
|
|
154
|
+
|
|
155
|
+
Args:
|
|
156
|
+
acquisition: The acquisition id to filter the images.
|
|
157
|
+
"""
|
|
158
|
+
images = []
|
|
159
|
+
for well_path, well in self.get_wells().items():
|
|
160
|
+
for img_path in well.paths(acquisition):
|
|
161
|
+
full_path = f"{well_path}/{img_path}"
|
|
162
|
+
img_group_handler = self._group_handler.derive_handler(full_path)
|
|
163
|
+
images.append(OmeZarrContainer(img_group_handler))
|
|
164
|
+
return images
|
|
165
|
+
|
|
166
|
+
def get_well_images(
|
|
167
|
+
self, row: str, column: str | int, acquisition: int | None = None
|
|
168
|
+
) -> list[OmeZarrContainer]:
|
|
169
|
+
"""Get all images in a well.
|
|
170
|
+
|
|
171
|
+
Args:
|
|
172
|
+
row: The row of the well.
|
|
173
|
+
column: The column of the well.
|
|
174
|
+
acquisition: The acquisition id to filter the images.
|
|
175
|
+
"""
|
|
176
|
+
well_path = self.meta.get_well_path(row=row, column=column)
|
|
177
|
+
group_handler = self._group_handler.derive_handler(well_path)
|
|
178
|
+
well = OmeZarrWell(group_handler)
|
|
179
|
+
|
|
180
|
+
images = []
|
|
181
|
+
for path in well.paths(acquisition):
|
|
182
|
+
image_path = f"{well_path}/{path}"
|
|
183
|
+
group_handler = self._group_handler.derive_handler(image_path)
|
|
184
|
+
images.append(OmeZarrContainer(group_handler))
|
|
185
|
+
|
|
186
|
+
return images
|
|
187
|
+
|
|
188
|
+
def _add_image(
|
|
189
|
+
self,
|
|
190
|
+
row: str,
|
|
191
|
+
column: int | str,
|
|
192
|
+
image_path: str,
|
|
193
|
+
acquisition_id: int | None = None,
|
|
194
|
+
acquisition_name: str | None = None,
|
|
195
|
+
atomic: bool = False,
|
|
196
|
+
) -> StoreOrGroup:
|
|
197
|
+
"""Add an image to an ome-zarr plate."""
|
|
198
|
+
if atomic:
|
|
199
|
+
plate_lock = self._group_handler.lock
|
|
200
|
+
else:
|
|
201
|
+
plate_lock = MockLock()
|
|
202
|
+
|
|
203
|
+
with plate_lock:
|
|
204
|
+
meta = self.meta
|
|
205
|
+
meta = meta.add_well(row, column, acquisition_id, acquisition_name)
|
|
206
|
+
self.meta_handler.write_meta(meta)
|
|
207
|
+
self.meta_handler._group_handler.clean_cache()
|
|
208
|
+
|
|
209
|
+
well_path = self.meta.get_well_path(row=row, column=column)
|
|
210
|
+
group_handler = self._group_handler.derive_handler(well_path)
|
|
211
|
+
|
|
212
|
+
if atomic:
|
|
213
|
+
well_lock = group_handler.lock
|
|
214
|
+
else:
|
|
215
|
+
well_lock = MockLock()
|
|
216
|
+
|
|
217
|
+
with well_lock:
|
|
218
|
+
attrs = group_handler.load_attrs()
|
|
219
|
+
if len(attrs) == 0:
|
|
220
|
+
# Initialize the well metadata
|
|
221
|
+
# if the group is empty
|
|
222
|
+
well_meta = NgioWellMeta.default_init()
|
|
223
|
+
meta_handler = get_well_meta_handler(group_handler, version="0.4")
|
|
224
|
+
else:
|
|
225
|
+
meta_handler = find_well_meta_handler(group_handler)
|
|
226
|
+
well_meta = meta_handler.meta
|
|
227
|
+
|
|
228
|
+
group_handler = self._group_handler.derive_handler(well_path)
|
|
229
|
+
|
|
230
|
+
well_meta = well_meta.add_image(path=image_path, acquisition=acquisition_id)
|
|
231
|
+
meta_handler.write_meta(well_meta)
|
|
232
|
+
meta_handler._group_handler.clean_cache()
|
|
233
|
+
|
|
234
|
+
return group_handler.get_group(image_path, create_mode=True)
|
|
235
|
+
|
|
236
|
+
def atomic_add_image(
|
|
237
|
+
self,
|
|
238
|
+
row: str,
|
|
239
|
+
column: int | str,
|
|
240
|
+
image_path: str,
|
|
241
|
+
acquisition_id: int | None = None,
|
|
242
|
+
acquisition_name: str | None = None,
|
|
243
|
+
) -> StoreOrGroup:
|
|
244
|
+
"""Parallel safe version of add_image."""
|
|
245
|
+
return self._add_image(
|
|
246
|
+
row=row,
|
|
247
|
+
column=column,
|
|
248
|
+
image_path=image_path,
|
|
249
|
+
acquisition_id=acquisition_id,
|
|
250
|
+
acquisition_name=acquisition_name,
|
|
251
|
+
atomic=True,
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
def add_image(
|
|
255
|
+
self,
|
|
256
|
+
row: str,
|
|
257
|
+
column: int | str,
|
|
258
|
+
image_path: str,
|
|
259
|
+
acquisition_id: int | None = None,
|
|
260
|
+
acquisition_name: str | None = None,
|
|
261
|
+
) -> StoreOrGroup:
|
|
262
|
+
"""Add an image to an ome-zarr plate."""
|
|
263
|
+
return self._add_image(
|
|
264
|
+
row=row,
|
|
265
|
+
column=column,
|
|
266
|
+
image_path=image_path,
|
|
267
|
+
acquisition_id=acquisition_id,
|
|
268
|
+
acquisition_name=acquisition_name,
|
|
269
|
+
atomic=False,
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
def _remove_well(
|
|
273
|
+
self,
|
|
274
|
+
row: str,
|
|
275
|
+
column: int | str,
|
|
276
|
+
atomic: bool = False,
|
|
277
|
+
):
|
|
278
|
+
"""Remove a well from an ome-zarr plate."""
|
|
279
|
+
if atomic:
|
|
280
|
+
plate_lock = self._group_handler.lock
|
|
281
|
+
else:
|
|
282
|
+
plate_lock = MockLock()
|
|
283
|
+
|
|
284
|
+
with plate_lock:
|
|
285
|
+
meta = self.meta
|
|
286
|
+
meta = meta.remove_well(row, column)
|
|
287
|
+
self.meta_handler.write_meta(meta)
|
|
288
|
+
self.meta_handler._group_handler.clean_cache()
|
|
289
|
+
|
|
290
|
+
def _remove_image(
|
|
291
|
+
self,
|
|
292
|
+
row: str,
|
|
293
|
+
column: int | str,
|
|
294
|
+
image_path: str,
|
|
295
|
+
atomic: bool = False,
|
|
296
|
+
):
|
|
297
|
+
"""Remove an image from an ome-zarr plate."""
|
|
298
|
+
well = self.get_well(row, column)
|
|
299
|
+
|
|
300
|
+
if atomic:
|
|
301
|
+
well_lock = well.meta_handler._group_handler.lock
|
|
302
|
+
else:
|
|
303
|
+
well_lock = MockLock()
|
|
304
|
+
|
|
305
|
+
with well_lock:
|
|
306
|
+
well_meta = well.meta
|
|
307
|
+
well_meta = well_meta.remove_image(path=image_path)
|
|
308
|
+
well.meta_handler.write_meta(well_meta)
|
|
309
|
+
well.meta_handler._group_handler.clean_cache()
|
|
310
|
+
if len(well_meta.paths()) == 0:
|
|
311
|
+
self._remove_well(row, column, atomic=atomic)
|
|
312
|
+
|
|
313
|
+
def atomic_remove_image(
|
|
314
|
+
self,
|
|
315
|
+
row: str,
|
|
316
|
+
column: int | str,
|
|
317
|
+
image_path: str,
|
|
318
|
+
):
|
|
319
|
+
"""Parallel safe version of remove_image."""
|
|
320
|
+
return self._remove_image(
|
|
321
|
+
row=row,
|
|
322
|
+
column=column,
|
|
323
|
+
image_path=image_path,
|
|
324
|
+
atomic=True,
|
|
325
|
+
)
|
|
326
|
+
|
|
327
|
+
def remove_image(
|
|
328
|
+
self,
|
|
329
|
+
row: str,
|
|
330
|
+
column: int | str,
|
|
331
|
+
image_path: str,
|
|
332
|
+
):
|
|
333
|
+
"""Remove an image from an ome-zarr plate."""
|
|
334
|
+
return self._remove_image(
|
|
335
|
+
row=row,
|
|
336
|
+
column=column,
|
|
337
|
+
image_path=image_path,
|
|
338
|
+
atomic=False,
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
def open_omezarr_plate(
|
|
343
|
+
store: StoreOrGroup,
|
|
344
|
+
cache: bool = False,
|
|
345
|
+
mode: AccessModeLiteral = "r+",
|
|
346
|
+
parallel_safe: bool = True,
|
|
347
|
+
) -> OmeZarrPlate:
|
|
348
|
+
"""Open an OME-Zarr plate.
|
|
349
|
+
|
|
350
|
+
Args:
|
|
351
|
+
store (StoreOrGroup): The Zarr store or group that stores the plate.
|
|
352
|
+
cache (bool): Whether to use a cache for the zarr group metadata.
|
|
353
|
+
mode (AccessModeLiteral): The
|
|
354
|
+
access mode for the image. Defaults to "r+".
|
|
355
|
+
parallel_safe (bool): Whether the group handler is parallel safe.
|
|
356
|
+
"""
|
|
357
|
+
group_handler = ZarrGroupHandler(
|
|
358
|
+
store=store, cache=cache, mode=mode, parallel_safe=parallel_safe
|
|
359
|
+
)
|
|
360
|
+
return OmeZarrPlate(group_handler)
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
def create_empty_plate(
|
|
364
|
+
store: StoreOrGroup,
|
|
365
|
+
name: str,
|
|
366
|
+
images: list[ImageInWellPath] | None = None,
|
|
367
|
+
version: str = "0.4",
|
|
368
|
+
cache: bool = False,
|
|
369
|
+
overwrite: bool = False,
|
|
370
|
+
parallel_safe: bool = True,
|
|
371
|
+
) -> OmeZarrPlate:
|
|
372
|
+
"""Initialize and create an empty OME-Zarr plate."""
|
|
373
|
+
mode = "w" if overwrite else "w-"
|
|
374
|
+
group_handler = ZarrGroupHandler(
|
|
375
|
+
store=store, cache=True, mode=mode, parallel_safe=False
|
|
376
|
+
)
|
|
377
|
+
meta_handler = get_plate_meta_handler(group_handler, version=version)
|
|
378
|
+
plate_meta = NgioPlateMeta.default_init(
|
|
379
|
+
name=name,
|
|
380
|
+
version=version,
|
|
381
|
+
)
|
|
382
|
+
meta_handler.write_meta(plate_meta)
|
|
383
|
+
|
|
384
|
+
if images is not None:
|
|
385
|
+
plate = OmeZarrPlate(group_handler)
|
|
386
|
+
for image in images:
|
|
387
|
+
plate.add_image(
|
|
388
|
+
row=image.row,
|
|
389
|
+
column=image.column,
|
|
390
|
+
image_path=image.path,
|
|
391
|
+
acquisition_id=image.acquisition_id,
|
|
392
|
+
acquisition_name=image.acquisition_name,
|
|
393
|
+
)
|
|
394
|
+
return open_omezarr_plate(
|
|
395
|
+
store=store,
|
|
396
|
+
cache=cache,
|
|
397
|
+
mode="r+",
|
|
398
|
+
parallel_safe=parallel_safe,
|
|
399
|
+
)
|
ngio/images/abstract_image.py
CHANGED
|
@@ -8,9 +8,11 @@ import zarr
|
|
|
8
8
|
from ngio.common import (
|
|
9
9
|
ArrayLike,
|
|
10
10
|
Dimensions,
|
|
11
|
+
RasterCooROI,
|
|
11
12
|
WorldCooROI,
|
|
12
13
|
consolidate_pyramid,
|
|
13
14
|
get_pipe,
|
|
15
|
+
roi_to_slice_kwargs,
|
|
14
16
|
set_pipe,
|
|
15
17
|
)
|
|
16
18
|
from ngio.ome_zarr_meta import (
|
|
@@ -19,10 +21,8 @@ from ngio.ome_zarr_meta import (
|
|
|
19
21
|
LabelMetaHandler,
|
|
20
22
|
PixelSize,
|
|
21
23
|
)
|
|
22
|
-
from ngio.
|
|
23
|
-
|
|
24
|
-
ZarrGroupHandler,
|
|
25
|
-
)
|
|
24
|
+
from ngio.tables import RoiTable
|
|
25
|
+
from ngio.utils import NgioFileExistsError, ZarrGroupHandler
|
|
26
26
|
|
|
27
27
|
_image_handler = TypeVar("_image_handler", ImageMetaHandler, LabelMetaHandler)
|
|
28
28
|
|
|
@@ -156,19 +156,8 @@ class AbstractImage(Generic[_image_handler]):
|
|
|
156
156
|
Returns:
|
|
157
157
|
The array of the region of interest.
|
|
158
158
|
"""
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
).to_slices()
|
|
162
|
-
|
|
163
|
-
for key in slice_kwargs.keys():
|
|
164
|
-
if key in raster_roi:
|
|
165
|
-
raise ValueError(
|
|
166
|
-
f"Key {key} is already in the slice_kwargs. "
|
|
167
|
-
"Ambiguous which one to use: "
|
|
168
|
-
f"{key}={slice_kwargs[key]} or roi_{key}={raster_roi[key]}"
|
|
169
|
-
)
|
|
170
|
-
return self.get_array(
|
|
171
|
-
axes_order=axes_order, mode=mode, **raster_roi, **slice_kwargs
|
|
159
|
+
return get_roi_pipe(
|
|
160
|
+
image=self, roi=roi, axes_order=axes_order, mode=mode, **slice_kwargs
|
|
172
161
|
)
|
|
173
162
|
|
|
174
163
|
def set_array(
|
|
@@ -209,18 +198,13 @@ class AbstractImage(Generic[_image_handler]):
|
|
|
209
198
|
**slice_kwargs: The slices to set the patch.
|
|
210
199
|
|
|
211
200
|
"""
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
)
|
|
201
|
+
return set_roi_pipe(
|
|
202
|
+
image=self, roi=roi, patch=patch, axes_order=axes_order, **slice_kwargs
|
|
203
|
+
)
|
|
215
204
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
f"Key {key} is already in the slice_kwargs. "
|
|
220
|
-
"Ambiguous which one to use: "
|
|
221
|
-
f"{key}={slice_kwargs[key]} or roi_{key}={raster_roi[key]}"
|
|
222
|
-
)
|
|
223
|
-
self.set_array(patch=patch, axes_order=axes_order, **raster_roi, **slice_kwargs)
|
|
205
|
+
def build_image_roi_table(self, name: str = "image") -> RoiTable:
|
|
206
|
+
"""Build the ROI table for an image."""
|
|
207
|
+
return build_image_roi_table(image=self, name=name)
|
|
224
208
|
|
|
225
209
|
|
|
226
210
|
def consolidate_image(
|
|
@@ -238,3 +222,88 @@ def consolidate_image(
|
|
|
238
222
|
consolidate_pyramid(
|
|
239
223
|
source=image.zarr_array, targets=targets, order=order, mode=mode
|
|
240
224
|
)
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def get_roi_pipe(
|
|
228
|
+
image: AbstractImage,
|
|
229
|
+
roi: WorldCooROI,
|
|
230
|
+
axes_order: Collection[str] | None = None,
|
|
231
|
+
mode: Literal["numpy", "dask", "delayed"] = "numpy",
|
|
232
|
+
**slice_kwargs: slice | int | Iterable[int],
|
|
233
|
+
) -> ArrayLike:
|
|
234
|
+
"""Get a slice of the image.
|
|
235
|
+
|
|
236
|
+
Args:
|
|
237
|
+
image: The image to get the ROI.
|
|
238
|
+
roi: The region of interest to get the array.
|
|
239
|
+
axes_order: The order of the axes to return the array.
|
|
240
|
+
mode: The mode to return the array.
|
|
241
|
+
**slice_kwargs: The slices to get the array.
|
|
242
|
+
|
|
243
|
+
Returns:
|
|
244
|
+
The array of the region of interest.
|
|
245
|
+
"""
|
|
246
|
+
slice_kwargs = roi_to_slice_kwargs(
|
|
247
|
+
roi=roi,
|
|
248
|
+
pixel_size=image.pixel_size,
|
|
249
|
+
dimensions=image.dimensions,
|
|
250
|
+
**slice_kwargs,
|
|
251
|
+
)
|
|
252
|
+
return get_pipe(
|
|
253
|
+
array=image.zarr_array,
|
|
254
|
+
dimensions=image.dimensions,
|
|
255
|
+
axes_order=axes_order,
|
|
256
|
+
mode=mode,
|
|
257
|
+
**slice_kwargs,
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
def set_roi_pipe(
|
|
262
|
+
image: AbstractImage,
|
|
263
|
+
roi: WorldCooROI,
|
|
264
|
+
patch: ArrayLike,
|
|
265
|
+
axes_order: Collection[str] | None = None,
|
|
266
|
+
**slice_kwargs: slice | int | Iterable[int],
|
|
267
|
+
) -> None:
|
|
268
|
+
"""Set a slice of the image.
|
|
269
|
+
|
|
270
|
+
Args:
|
|
271
|
+
image: The image to set the ROI.
|
|
272
|
+
roi: The region of interest to set the patch.
|
|
273
|
+
patch: The patch to set.
|
|
274
|
+
axes_order: The order of the axes to set the patch.
|
|
275
|
+
**slice_kwargs: The slices to set the patch.
|
|
276
|
+
|
|
277
|
+
"""
|
|
278
|
+
slice_kwargs = roi_to_slice_kwargs(
|
|
279
|
+
roi=roi,
|
|
280
|
+
pixel_size=image.pixel_size,
|
|
281
|
+
dimensions=image.dimensions,
|
|
282
|
+
**slice_kwargs,
|
|
283
|
+
)
|
|
284
|
+
set_pipe(
|
|
285
|
+
array=image.zarr_array,
|
|
286
|
+
patch=patch,
|
|
287
|
+
dimensions=image.dimensions,
|
|
288
|
+
axes_order=axes_order,
|
|
289
|
+
**slice_kwargs,
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
def build_image_roi_table(image: AbstractImage, name: str = "image") -> RoiTable:
|
|
294
|
+
"""Build the ROI table for an image."""
|
|
295
|
+
dim_z, dim_y, dim_x = (
|
|
296
|
+
image.dimensions.get("z", strict=False),
|
|
297
|
+
image.dimensions.get("y"),
|
|
298
|
+
image.dimensions.get("x"),
|
|
299
|
+
)
|
|
300
|
+
image_roi = RasterCooROI(
|
|
301
|
+
name=name,
|
|
302
|
+
x=0,
|
|
303
|
+
y=0,
|
|
304
|
+
z=0,
|
|
305
|
+
x_length=dim_x,
|
|
306
|
+
y_length=dim_y,
|
|
307
|
+
z_length=dim_z,
|
|
308
|
+
)
|
|
309
|
+
return RoiTable(rois=[image_roi.to_world_coo_roi(pixel_size=image.pixel_size)])
|