ngio 0.2.0a2__py3-none-any.whl → 0.5.0b4__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 +40 -12
- ngio/common/__init__.py +16 -32
- ngio/common/_dimensions.py +270 -48
- ngio/common/_masking_roi.py +153 -0
- ngio/common/_pyramid.py +267 -73
- ngio/common/_roi.py +290 -66
- ngio/common/_synt_images_utils.py +101 -0
- ngio/common/_zoom.py +54 -22
- ngio/experimental/__init__.py +5 -0
- ngio/experimental/iterators/__init__.py +15 -0
- ngio/experimental/iterators/_abstract_iterator.py +390 -0
- ngio/experimental/iterators/_feature.py +189 -0
- ngio/experimental/iterators/_image_processing.py +130 -0
- ngio/experimental/iterators/_mappers.py +48 -0
- ngio/experimental/iterators/_rois_utils.py +126 -0
- ngio/experimental/iterators/_segmentation.py +235 -0
- ngio/hcs/__init__.py +17 -58
- ngio/hcs/_plate.py +1354 -0
- ngio/images/__init__.py +30 -9
- ngio/images/_abstract_image.py +968 -0
- ngio/images/_create_synt_container.py +132 -0
- ngio/images/_create_utils.py +423 -0
- ngio/images/_image.py +926 -0
- ngio/images/_label.py +417 -0
- ngio/images/_masked_image.py +531 -0
- ngio/images/_ome_zarr_container.py +1235 -0
- ngio/images/_table_ops.py +471 -0
- ngio/io_pipes/__init__.py +75 -0
- ngio/io_pipes/_io_pipes.py +361 -0
- ngio/io_pipes/_io_pipes_masked.py +488 -0
- ngio/io_pipes/_io_pipes_roi.py +146 -0
- ngio/io_pipes/_io_pipes_types.py +56 -0
- ngio/io_pipes/_match_shape.py +377 -0
- ngio/io_pipes/_ops_axes.py +344 -0
- ngio/io_pipes/_ops_slices.py +411 -0
- ngio/io_pipes/_ops_slices_utils.py +199 -0
- ngio/io_pipes/_ops_transforms.py +104 -0
- ngio/io_pipes/_zoom_transform.py +180 -0
- ngio/ome_zarr_meta/__init__.py +39 -15
- ngio/ome_zarr_meta/_meta_handlers.py +490 -96
- ngio/ome_zarr_meta/ngio_specs/__init__.py +24 -10
- ngio/ome_zarr_meta/ngio_specs/_axes.py +268 -234
- ngio/ome_zarr_meta/ngio_specs/_channels.py +125 -41
- ngio/ome_zarr_meta/ngio_specs/_dataset.py +42 -87
- ngio/ome_zarr_meta/ngio_specs/_ngio_hcs.py +536 -2
- ngio/ome_zarr_meta/ngio_specs/_ngio_image.py +202 -198
- ngio/ome_zarr_meta/ngio_specs/_pixel_size.py +72 -34
- ngio/ome_zarr_meta/v04/__init__.py +21 -5
- ngio/ome_zarr_meta/v04/_custom_models.py +18 -0
- ngio/ome_zarr_meta/v04/{_v04_spec_utils.py → _v04_spec.py} +151 -90
- ngio/ome_zarr_meta/v05/__init__.py +27 -0
- ngio/ome_zarr_meta/v05/_custom_models.py +18 -0
- ngio/ome_zarr_meta/v05/_v05_spec.py +511 -0
- ngio/resources/20200812-CardiomyocyteDifferentiation14-Cycle1_B03/mask.png +0 -0
- ngio/resources/20200812-CardiomyocyteDifferentiation14-Cycle1_B03/nuclei.png +0 -0
- ngio/resources/20200812-CardiomyocyteDifferentiation14-Cycle1_B03/raw.jpg +0 -0
- ngio/resources/__init__.py +55 -0
- ngio/resources/resource_model.py +36 -0
- ngio/tables/__init__.py +20 -4
- ngio/tables/_abstract_table.py +270 -0
- ngio/tables/_tables_container.py +449 -0
- ngio/tables/backends/__init__.py +50 -1
- ngio/tables/backends/_abstract_backend.py +200 -31
- ngio/tables/backends/_anndata.py +139 -0
- ngio/tables/backends/_anndata_utils.py +10 -114
- ngio/tables/backends/_csv.py +19 -0
- ngio/tables/backends/_json.py +92 -0
- ngio/tables/backends/_parquet.py +19 -0
- ngio/tables/backends/_py_arrow_backends.py +222 -0
- ngio/tables/backends/_table_backends.py +162 -38
- ngio/tables/backends/_utils.py +608 -0
- ngio/tables/v1/__init__.py +19 -4
- ngio/tables/v1/_condition_table.py +71 -0
- ngio/tables/v1/_feature_table.py +79 -115
- ngio/tables/v1/_generic_table.py +21 -90
- ngio/tables/v1/_roi_table.py +486 -137
- ngio/transforms/__init__.py +5 -0
- ngio/transforms/_zoom.py +19 -0
- ngio/utils/__init__.py +16 -14
- ngio/utils/_cache.py +48 -0
- ngio/utils/_datasets.py +121 -13
- ngio/utils/_fractal_fsspec_store.py +42 -0
- ngio/utils/_zarr_utils.py +374 -218
- ngio-0.5.0b4.dist-info/METADATA +147 -0
- ngio-0.5.0b4.dist-info/RECORD +88 -0
- {ngio-0.2.0a2.dist-info → ngio-0.5.0b4.dist-info}/WHEEL +1 -1
- ngio/common/_array_pipe.py +0 -160
- ngio/common/_axes_transforms.py +0 -63
- ngio/common/_common_types.py +0 -5
- ngio/common/_slicer.py +0 -97
- ngio/images/abstract_image.py +0 -240
- ngio/images/create.py +0 -251
- ngio/images/image.py +0 -389
- ngio/images/label.py +0 -236
- ngio/images/omezarr_container.py +0 -535
- ngio/ome_zarr_meta/_generic_handlers.py +0 -320
- ngio/ome_zarr_meta/v04/_meta_handlers.py +0 -54
- ngio/tables/_validators.py +0 -192
- ngio/tables/backends/_anndata_v1.py +0 -75
- ngio/tables/backends/_json_v1.py +0 -56
- ngio/tables/tables_container.py +0 -300
- ngio/tables/v1/_masking_roi_table.py +0 -175
- ngio/utils/_logger.py +0 -29
- ngio-0.2.0a2.dist-info/METADATA +0 -95
- ngio-0.2.0a2.dist-info/RECORD +0 -53
- {ngio-0.2.0a2.dist-info → ngio-0.5.0b4.dist-info}/licenses/LICENSE +0 -0
ngio/hcs/_plate.py
ADDED
|
@@ -0,0 +1,1354 @@
|
|
|
1
|
+
"""A module for handling the Plate Sequence in an OME-Zarr file."""
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import warnings
|
|
5
|
+
from collections.abc import Sequence
|
|
6
|
+
from typing import Literal
|
|
7
|
+
|
|
8
|
+
from ngio.images import (
|
|
9
|
+
OmeZarrContainer,
|
|
10
|
+
concatenate_image_tables,
|
|
11
|
+
concatenate_image_tables_as,
|
|
12
|
+
concatenate_image_tables_as_async,
|
|
13
|
+
concatenate_image_tables_async,
|
|
14
|
+
list_image_tables,
|
|
15
|
+
list_image_tables_async,
|
|
16
|
+
)
|
|
17
|
+
from ngio.ome_zarr_meta import (
|
|
18
|
+
DefaultNgffVersion,
|
|
19
|
+
ImageInWellPath,
|
|
20
|
+
NgffVersions,
|
|
21
|
+
NgioPlateMeta,
|
|
22
|
+
NgioWellMeta,
|
|
23
|
+
PlateMetaHandler,
|
|
24
|
+
WellMetaHandler,
|
|
25
|
+
path_in_well_validation,
|
|
26
|
+
update_ngio_plate_meta,
|
|
27
|
+
update_ngio_well_meta,
|
|
28
|
+
)
|
|
29
|
+
from ngio.tables import (
|
|
30
|
+
ConditionTable,
|
|
31
|
+
DefaultTableBackend,
|
|
32
|
+
FeatureTable,
|
|
33
|
+
GenericRoiTable,
|
|
34
|
+
MaskingRoiTable,
|
|
35
|
+
RoiTable,
|
|
36
|
+
Table,
|
|
37
|
+
TableBackend,
|
|
38
|
+
TablesContainer,
|
|
39
|
+
TableType,
|
|
40
|
+
TypedTable,
|
|
41
|
+
)
|
|
42
|
+
from ngio.utils import (
|
|
43
|
+
AccessModeLiteral,
|
|
44
|
+
NgioCache,
|
|
45
|
+
NgioError,
|
|
46
|
+
NgioValueError,
|
|
47
|
+
StoreOrGroup,
|
|
48
|
+
ZarrGroupHandler,
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _try_get_table_container(
|
|
53
|
+
handler: ZarrGroupHandler, create_mode: bool = True
|
|
54
|
+
) -> TablesContainer | None:
|
|
55
|
+
"""Return a default table container."""
|
|
56
|
+
try:
|
|
57
|
+
table_handler = handler.get_handler("tables", create_mode=create_mode)
|
|
58
|
+
return TablesContainer(table_handler)
|
|
59
|
+
except NgioError:
|
|
60
|
+
return None
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
# Mock lock class that does nothing
|
|
64
|
+
class MockLock:
|
|
65
|
+
"""A mock lock class that does nothing."""
|
|
66
|
+
|
|
67
|
+
def __enter__(self):
|
|
68
|
+
"""Enter the lock."""
|
|
69
|
+
pass
|
|
70
|
+
|
|
71
|
+
def __exit__(self, exc_type, exc_value, traceback):
|
|
72
|
+
"""Exit the lock."""
|
|
73
|
+
pass
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class OmeZarrWell:
|
|
77
|
+
"""A class to handle the Well Sequence in an OME-Zarr file."""
|
|
78
|
+
|
|
79
|
+
def __init__(self, group_handler: ZarrGroupHandler) -> None:
|
|
80
|
+
"""Initialize the LabelGroupHandler.
|
|
81
|
+
|
|
82
|
+
Args:
|
|
83
|
+
group_handler: The Zarr group handler that contains the Well.
|
|
84
|
+
"""
|
|
85
|
+
self._group_handler = group_handler
|
|
86
|
+
self._meta_handler = WellMetaHandler(group_handler)
|
|
87
|
+
|
|
88
|
+
def __repr__(self) -> str:
|
|
89
|
+
"""Return a string representation of the well."""
|
|
90
|
+
return f"Well(#images: {len(self.paths())})"
|
|
91
|
+
|
|
92
|
+
@property
|
|
93
|
+
def meta_handler(self):
|
|
94
|
+
"""Return the metadata handler."""
|
|
95
|
+
return self._meta_handler
|
|
96
|
+
|
|
97
|
+
@property
|
|
98
|
+
def meta(self):
|
|
99
|
+
"""Return the metadata."""
|
|
100
|
+
return self._meta_handler.get_meta()
|
|
101
|
+
|
|
102
|
+
@property
|
|
103
|
+
def acquisition_ids(self) -> list[int]:
|
|
104
|
+
"""Return the acquisitions ids in the well."""
|
|
105
|
+
return self.meta.acquisition_ids
|
|
106
|
+
|
|
107
|
+
def paths(self, acquisition: int | None = None) -> list[str]:
|
|
108
|
+
"""Return the images paths in the well.
|
|
109
|
+
|
|
110
|
+
If acquisition is None, return all images paths in the well.
|
|
111
|
+
Else, return the images paths in the well for the given acquisition.
|
|
112
|
+
|
|
113
|
+
Args:
|
|
114
|
+
acquisition (int | None): The acquisition id to filter the images.
|
|
115
|
+
"""
|
|
116
|
+
return self.meta.paths(acquisition)
|
|
117
|
+
|
|
118
|
+
def get_image_store(self, image_path: str) -> StoreOrGroup:
|
|
119
|
+
"""Get the image store from the well.
|
|
120
|
+
|
|
121
|
+
Args:
|
|
122
|
+
image_path (str): The path of the image.
|
|
123
|
+
"""
|
|
124
|
+
return self._group_handler.get_group(image_path, create_mode=True)
|
|
125
|
+
|
|
126
|
+
def get_image_acquisition_id(self, image_path: str) -> int | None:
|
|
127
|
+
"""Get the acquisition id of an image in the well.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
image_path (str): The path of the image.
|
|
131
|
+
|
|
132
|
+
Returns:
|
|
133
|
+
int | None: The acquisition id of the image.
|
|
134
|
+
"""
|
|
135
|
+
return self.meta.get_image_acquisition_id(image_path=image_path)
|
|
136
|
+
|
|
137
|
+
def get_image(self, image_path: str) -> OmeZarrContainer:
|
|
138
|
+
"""Get an image from the well.
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
image_path (str): The path of the image.
|
|
142
|
+
|
|
143
|
+
Returns:
|
|
144
|
+
OmeZarrContainer: The image.
|
|
145
|
+
"""
|
|
146
|
+
handler = self._group_handler.get_handler(image_path)
|
|
147
|
+
return OmeZarrContainer(handler)
|
|
148
|
+
|
|
149
|
+
def _add_image(
|
|
150
|
+
self,
|
|
151
|
+
image_path: str,
|
|
152
|
+
acquisition_id: int | None = None,
|
|
153
|
+
strict: bool = True,
|
|
154
|
+
atomic: bool = False,
|
|
155
|
+
) -> StoreOrGroup:
|
|
156
|
+
"""Add an image to an ome-zarr well."""
|
|
157
|
+
image_path = path_in_well_validation(path=image_path)
|
|
158
|
+
|
|
159
|
+
if atomic:
|
|
160
|
+
well_lock = self._group_handler.lock
|
|
161
|
+
else:
|
|
162
|
+
well_lock = MockLock()
|
|
163
|
+
|
|
164
|
+
with well_lock:
|
|
165
|
+
meta = self.meta.add_image(
|
|
166
|
+
path=image_path, acquisition=acquisition_id, strict=strict
|
|
167
|
+
)
|
|
168
|
+
self.meta_handler.update_meta(meta)
|
|
169
|
+
self.meta_handler._group_handler.clean_cache()
|
|
170
|
+
|
|
171
|
+
return self._group_handler.get_group(image_path, create_mode=True)
|
|
172
|
+
|
|
173
|
+
def atomic_add_image(
|
|
174
|
+
self,
|
|
175
|
+
image_path: str,
|
|
176
|
+
acquisition_id: int | None = None,
|
|
177
|
+
strict: bool = True,
|
|
178
|
+
) -> StoreOrGroup:
|
|
179
|
+
"""Parallel safe version of add_image."""
|
|
180
|
+
return self._add_image(
|
|
181
|
+
image_path=image_path,
|
|
182
|
+
acquisition_id=acquisition_id,
|
|
183
|
+
atomic=True,
|
|
184
|
+
strict=strict,
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
def add_image(
|
|
188
|
+
self,
|
|
189
|
+
image_path: str,
|
|
190
|
+
acquisition_id: int | None = None,
|
|
191
|
+
strict: bool = True,
|
|
192
|
+
) -> StoreOrGroup:
|
|
193
|
+
"""Add an image to an ome-zarr well.
|
|
194
|
+
|
|
195
|
+
Args:
|
|
196
|
+
image_path (str): The path of the image.
|
|
197
|
+
acquisition_id (int | None): The acquisition id to filter the images.
|
|
198
|
+
strict (bool): Whether to check if the acquisition id is already exists
|
|
199
|
+
in the well. Defaults to True. If False this might lead to
|
|
200
|
+
acquisition in a well that does not exist at the plate level.
|
|
201
|
+
"""
|
|
202
|
+
return self._add_image(
|
|
203
|
+
image_path=image_path,
|
|
204
|
+
acquisition_id=acquisition_id,
|
|
205
|
+
atomic=False,
|
|
206
|
+
strict=strict,
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def _build_extras(paths: Sequence[str]) -> list[dict[str, str]]:
|
|
211
|
+
"""Build the extras for the images.
|
|
212
|
+
|
|
213
|
+
Args:
|
|
214
|
+
paths (Sequence[str]): The paths of the images.
|
|
215
|
+
|
|
216
|
+
Returns:
|
|
217
|
+
list[dict[str, str]]: The extras for the images.
|
|
218
|
+
"""
|
|
219
|
+
extras = []
|
|
220
|
+
for path in paths:
|
|
221
|
+
row, column, path_in_well = path.split("/")
|
|
222
|
+
extras.append(
|
|
223
|
+
{
|
|
224
|
+
"row": row,
|
|
225
|
+
"column": column,
|
|
226
|
+
"path_in_well": path_in_well,
|
|
227
|
+
}
|
|
228
|
+
)
|
|
229
|
+
return extras
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
class OmeZarrPlate:
|
|
233
|
+
"""A class to handle the Plate Sequence in an OME-Zarr file."""
|
|
234
|
+
|
|
235
|
+
def __init__(
|
|
236
|
+
self,
|
|
237
|
+
group_handler: ZarrGroupHandler,
|
|
238
|
+
table_container: TablesContainer | None = None,
|
|
239
|
+
) -> None:
|
|
240
|
+
"""Initialize the LabelGroupHandler.
|
|
241
|
+
|
|
242
|
+
Args:
|
|
243
|
+
group_handler: The Zarr group handler that contains the Plate.
|
|
244
|
+
table_container: The tables container that contains plate level tables.
|
|
245
|
+
"""
|
|
246
|
+
self._group_handler = group_handler
|
|
247
|
+
self._meta_handler = PlateMetaHandler(group_handler)
|
|
248
|
+
self._tables_container = table_container
|
|
249
|
+
self._wells_cache: NgioCache[OmeZarrWell] = NgioCache(
|
|
250
|
+
use_cache=self._group_handler.use_cache
|
|
251
|
+
)
|
|
252
|
+
self._images_cache: NgioCache[OmeZarrContainer] = NgioCache(
|
|
253
|
+
use_cache=self._group_handler.use_cache
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
def __repr__(self) -> str:
|
|
257
|
+
"""Return a string representation of the plate."""
|
|
258
|
+
return f"Plate([rows x columns] ({len(self.rows)} x {len(self.columns)}))"
|
|
259
|
+
|
|
260
|
+
@property
|
|
261
|
+
def meta_handler(self):
|
|
262
|
+
"""Return the metadata handler."""
|
|
263
|
+
return self._meta_handler
|
|
264
|
+
|
|
265
|
+
@property
|
|
266
|
+
def meta(self):
|
|
267
|
+
"""Return the metadata."""
|
|
268
|
+
return self._meta_handler.get_meta()
|
|
269
|
+
|
|
270
|
+
@property
|
|
271
|
+
def columns(self) -> list[str]:
|
|
272
|
+
"""Return the number of columns in the plate."""
|
|
273
|
+
return self.meta.columns
|
|
274
|
+
|
|
275
|
+
@property
|
|
276
|
+
def rows(self) -> list[str]:
|
|
277
|
+
"""Return the number of rows in the plate."""
|
|
278
|
+
return self.meta.rows
|
|
279
|
+
|
|
280
|
+
@property
|
|
281
|
+
def acquisitions_names(self) -> list[str | None]:
|
|
282
|
+
"""Return the acquisitions in the plate."""
|
|
283
|
+
return self.meta.acquisitions_names
|
|
284
|
+
|
|
285
|
+
@property
|
|
286
|
+
def acquisition_ids(self) -> list[int]:
|
|
287
|
+
"""Return the acquisitions ids in the plate."""
|
|
288
|
+
return self.meta.acquisition_ids
|
|
289
|
+
|
|
290
|
+
def _well_path(self, row: str, column: int | str) -> str:
|
|
291
|
+
"""Return the well path in the plate."""
|
|
292
|
+
return self.meta.get_well_path(row=row, column=column)
|
|
293
|
+
|
|
294
|
+
def _image_path(self, row: str, column: int | str, path: str) -> str:
|
|
295
|
+
"""Return the image path in the plate."""
|
|
296
|
+
well = self.get_well(row, column)
|
|
297
|
+
if path not in well.paths():
|
|
298
|
+
raise ValueError(f"Image {path} does not exist in well {row}{column}")
|
|
299
|
+
return f"{self._well_path(row, column)}/{path}"
|
|
300
|
+
|
|
301
|
+
def wells_paths(self) -> list[str]:
|
|
302
|
+
"""Return the wells paths in the plate."""
|
|
303
|
+
return self.meta.wells_paths
|
|
304
|
+
|
|
305
|
+
async def images_paths_async(self, acquisition: int | None = None) -> list[str]:
|
|
306
|
+
"""Return the images paths in the plate asynchronously.
|
|
307
|
+
|
|
308
|
+
If acquisition is None, return all images paths in the plate.
|
|
309
|
+
Else, return the images paths in the plate for the given acquisition.
|
|
310
|
+
|
|
311
|
+
Args:
|
|
312
|
+
acquisition (int | None): The acquisition id to filter the images.
|
|
313
|
+
"""
|
|
314
|
+
wells = await self.get_wells_async()
|
|
315
|
+
paths = []
|
|
316
|
+
for well_path, well in wells.items():
|
|
317
|
+
for img_path in well.paths(acquisition):
|
|
318
|
+
paths.append(f"{well_path}/{img_path}")
|
|
319
|
+
return paths
|
|
320
|
+
|
|
321
|
+
def images_paths(self, acquisition: int | None = None) -> list[str]:
|
|
322
|
+
"""Return the images paths in the plate.
|
|
323
|
+
|
|
324
|
+
If acquisition is None, return all images paths in the plate.
|
|
325
|
+
Else, return the images paths in the plate for the given acquisition.
|
|
326
|
+
|
|
327
|
+
Args:
|
|
328
|
+
acquisition (int | None): The acquisition id to filter the images.
|
|
329
|
+
"""
|
|
330
|
+
wells = self.get_wells()
|
|
331
|
+
images = []
|
|
332
|
+
for well_path, well in wells.items():
|
|
333
|
+
for img_path in well.paths(acquisition):
|
|
334
|
+
images.append(f"{well_path}/{img_path}")
|
|
335
|
+
return images
|
|
336
|
+
|
|
337
|
+
def well_images_paths(
|
|
338
|
+
self, row: str, column: int | str, acquisition: int | None = None
|
|
339
|
+
) -> list[str]:
|
|
340
|
+
"""Return the images paths in a well.
|
|
341
|
+
|
|
342
|
+
If acquisition is None, return all images paths in the well.
|
|
343
|
+
Else, return the images paths in the well for the given acquisition.
|
|
344
|
+
|
|
345
|
+
Args:
|
|
346
|
+
row (str): The row of the well.
|
|
347
|
+
column (int | str): The column of the well.
|
|
348
|
+
acquisition (int | None): The acquisition id to filter the images.
|
|
349
|
+
"""
|
|
350
|
+
images = []
|
|
351
|
+
well = self.get_well(row=row, column=column)
|
|
352
|
+
for path in well.paths(acquisition):
|
|
353
|
+
images.append(self._image_path(row=row, column=column, path=path))
|
|
354
|
+
return images
|
|
355
|
+
|
|
356
|
+
def get_image_acquisition_id(
|
|
357
|
+
self, row: str, column: int | str, image_path: str
|
|
358
|
+
) -> int | None:
|
|
359
|
+
"""Get the acquisition id of an image in a well.
|
|
360
|
+
|
|
361
|
+
Args:
|
|
362
|
+
row (str): The row of the well.
|
|
363
|
+
column (int | str): The column of the well.
|
|
364
|
+
image_path (str): The path of the image.
|
|
365
|
+
|
|
366
|
+
Returns:
|
|
367
|
+
int | None: The acquisition id of the image.
|
|
368
|
+
"""
|
|
369
|
+
well = self.get_well(row=row, column=column)
|
|
370
|
+
return well.get_image_acquisition_id(image_path=image_path)
|
|
371
|
+
|
|
372
|
+
def _get_well(self, well_path: str) -> OmeZarrWell:
|
|
373
|
+
"""Get a well from the plate by its path.
|
|
374
|
+
|
|
375
|
+
Args:
|
|
376
|
+
well_path (str): The path of the well.
|
|
377
|
+
|
|
378
|
+
Returns:
|
|
379
|
+
OmeZarrWell: The well.
|
|
380
|
+
|
|
381
|
+
"""
|
|
382
|
+
cached_well = self._wells_cache.get(well_path)
|
|
383
|
+
if cached_well is not None:
|
|
384
|
+
return cached_well
|
|
385
|
+
|
|
386
|
+
group_handler = self._group_handler.get_handler(well_path)
|
|
387
|
+
self._wells_cache.set(well_path, OmeZarrWell(group_handler))
|
|
388
|
+
return OmeZarrWell(group_handler)
|
|
389
|
+
|
|
390
|
+
def get_well(self, row: str, column: int | str) -> OmeZarrWell:
|
|
391
|
+
"""Get a well from the plate.
|
|
392
|
+
|
|
393
|
+
Args:
|
|
394
|
+
row (str): The row of the well.
|
|
395
|
+
column (int | str): The column of the well.
|
|
396
|
+
|
|
397
|
+
Returns:
|
|
398
|
+
OmeZarrWell: The well.
|
|
399
|
+
"""
|
|
400
|
+
well_path = self._well_path(row=row, column=column)
|
|
401
|
+
return self._get_well(well_path=well_path)
|
|
402
|
+
|
|
403
|
+
async def get_wells_async(self) -> dict[str, OmeZarrWell]:
|
|
404
|
+
"""Get all wells in the plate asynchronously.
|
|
405
|
+
|
|
406
|
+
This method processes wells in parallel for improved performance
|
|
407
|
+
when working with a large number of wells.
|
|
408
|
+
|
|
409
|
+
Returns:
|
|
410
|
+
dict[str, OmeZarrWell]: A dictionary of wells, where the key is the well
|
|
411
|
+
path and the value is the well object.
|
|
412
|
+
"""
|
|
413
|
+
wells, tasks = {}, []
|
|
414
|
+
for well_path in self.wells_paths():
|
|
415
|
+
task = asyncio.to_thread(
|
|
416
|
+
lambda well_path: (well_path, self._get_well(well_path)), well_path
|
|
417
|
+
)
|
|
418
|
+
tasks.append(task)
|
|
419
|
+
|
|
420
|
+
results = await asyncio.gather(*tasks)
|
|
421
|
+
for well_path, well in results:
|
|
422
|
+
wells[well_path] = well
|
|
423
|
+
|
|
424
|
+
return wells
|
|
425
|
+
|
|
426
|
+
def get_wells(self) -> dict[str, OmeZarrWell]:
|
|
427
|
+
"""Get all wells in the plate.
|
|
428
|
+
|
|
429
|
+
Returns:
|
|
430
|
+
dict[str, OmeZarrWell]: A dictionary of wells, where the key is the well
|
|
431
|
+
path and the value is the well object.
|
|
432
|
+
"""
|
|
433
|
+
wells = {}
|
|
434
|
+
for well_path in self.wells_paths():
|
|
435
|
+
wells[well_path] = self._get_well(well_path)
|
|
436
|
+
return wells
|
|
437
|
+
|
|
438
|
+
def _get_image(self, image_path: str) -> OmeZarrContainer:
|
|
439
|
+
"""Get an image from the plate by its path.
|
|
440
|
+
|
|
441
|
+
Args:
|
|
442
|
+
image_path (str): The path of the image.
|
|
443
|
+
"""
|
|
444
|
+
cached_image = self._images_cache.get(image_path)
|
|
445
|
+
if cached_image is not None:
|
|
446
|
+
return cached_image
|
|
447
|
+
img_group_handler = self._group_handler.get_handler(image_path)
|
|
448
|
+
image = OmeZarrContainer(img_group_handler)
|
|
449
|
+
self._images_cache.set(image_path, image)
|
|
450
|
+
return image
|
|
451
|
+
|
|
452
|
+
async def get_images_async(
|
|
453
|
+
self, acquisition: int | None = None
|
|
454
|
+
) -> dict[str, OmeZarrContainer]:
|
|
455
|
+
"""Get all images in the plate asynchronously.
|
|
456
|
+
|
|
457
|
+
This method processes images in parallel for improved performance
|
|
458
|
+
when working with a large number of images.
|
|
459
|
+
|
|
460
|
+
Args:
|
|
461
|
+
acquisition: The acquisition id to filter the images.
|
|
462
|
+
|
|
463
|
+
Returns:
|
|
464
|
+
dict[str, OmeZarrContainer]: A dictionary of images, where the key is the
|
|
465
|
+
image path and the value is the image object.
|
|
466
|
+
"""
|
|
467
|
+
paths = await self.images_paths_async(acquisition=acquisition)
|
|
468
|
+
|
|
469
|
+
images, tasks = {}, []
|
|
470
|
+
for image_path in paths:
|
|
471
|
+
task = asyncio.to_thread(
|
|
472
|
+
lambda image_path: (image_path, self._get_image(image_path)), image_path
|
|
473
|
+
)
|
|
474
|
+
tasks.append(task)
|
|
475
|
+
|
|
476
|
+
results = await asyncio.gather(*tasks)
|
|
477
|
+
|
|
478
|
+
for image_path, image in results:
|
|
479
|
+
images[image_path] = image
|
|
480
|
+
return images
|
|
481
|
+
|
|
482
|
+
def get_images(self, acquisition: int | None = None) -> dict[str, OmeZarrContainer]:
|
|
483
|
+
"""Get all images in the plate.
|
|
484
|
+
|
|
485
|
+
Args:
|
|
486
|
+
acquisition: The acquisition id to filter the images.
|
|
487
|
+
"""
|
|
488
|
+
paths = self.images_paths(acquisition=acquisition)
|
|
489
|
+
images = {}
|
|
490
|
+
for image_path in paths:
|
|
491
|
+
images[image_path] = self._get_image(image_path)
|
|
492
|
+
|
|
493
|
+
return images
|
|
494
|
+
|
|
495
|
+
def get_image(
|
|
496
|
+
self, row: str, column: int | str, image_path: str
|
|
497
|
+
) -> OmeZarrContainer:
|
|
498
|
+
"""Get an image from the plate.
|
|
499
|
+
|
|
500
|
+
Args:
|
|
501
|
+
row (str): The row of the well.
|
|
502
|
+
column (int | str): The column of the well.
|
|
503
|
+
image_path (str): The path of the image.
|
|
504
|
+
|
|
505
|
+
Returns:
|
|
506
|
+
OmeZarrContainer: The image.
|
|
507
|
+
"""
|
|
508
|
+
image_path = self._image_path(row=row, column=column, path=image_path)
|
|
509
|
+
return self._get_image(image_path)
|
|
510
|
+
|
|
511
|
+
def get_image_store(
|
|
512
|
+
self, row: str, column: int | str, image_path: str
|
|
513
|
+
) -> StoreOrGroup:
|
|
514
|
+
"""Get the image store from the plate.
|
|
515
|
+
|
|
516
|
+
Args:
|
|
517
|
+
row (str): The row of the well.
|
|
518
|
+
column (int | str): The column of the well.
|
|
519
|
+
image_path (str): The path of the image.
|
|
520
|
+
"""
|
|
521
|
+
well = self.get_well(row=row, column=column)
|
|
522
|
+
return well.get_image_store(image_path=image_path)
|
|
523
|
+
|
|
524
|
+
def get_well_images(
|
|
525
|
+
self, row: str, column: str | int, acquisition: int | None = None
|
|
526
|
+
) -> dict[str, OmeZarrContainer]:
|
|
527
|
+
"""Get all images in a well.
|
|
528
|
+
|
|
529
|
+
Args:
|
|
530
|
+
row: The row of the well.
|
|
531
|
+
column: The column of the well.
|
|
532
|
+
acquisition: The acquisition id to filter the images.
|
|
533
|
+
"""
|
|
534
|
+
images = {}
|
|
535
|
+
for image_paths in self.well_images_paths(
|
|
536
|
+
row=row, column=column, acquisition=acquisition
|
|
537
|
+
):
|
|
538
|
+
group_handler = self._group_handler.get_handler(image_paths)
|
|
539
|
+
images[image_paths] = OmeZarrContainer(group_handler)
|
|
540
|
+
return images
|
|
541
|
+
|
|
542
|
+
def _add_image(
|
|
543
|
+
self,
|
|
544
|
+
row: str,
|
|
545
|
+
column: int | str,
|
|
546
|
+
image_path: str | None = None,
|
|
547
|
+
acquisition_id: int | None = None,
|
|
548
|
+
acquisition_name: str | None = None,
|
|
549
|
+
atomic: bool = False,
|
|
550
|
+
) -> str:
|
|
551
|
+
"""Add an image to an ome-zarr plate."""
|
|
552
|
+
if image_path is not None:
|
|
553
|
+
image_path = path_in_well_validation(path=image_path)
|
|
554
|
+
|
|
555
|
+
if atomic:
|
|
556
|
+
plate_lock = self._group_handler.lock
|
|
557
|
+
else:
|
|
558
|
+
plate_lock = MockLock()
|
|
559
|
+
|
|
560
|
+
with plate_lock:
|
|
561
|
+
meta = self.meta
|
|
562
|
+
meta = meta.add_well(row=row, column=column)
|
|
563
|
+
if acquisition_id is not None:
|
|
564
|
+
meta = meta.add_acquisition(
|
|
565
|
+
acquisition_id=acquisition_id, acquisition_name=acquisition_name
|
|
566
|
+
)
|
|
567
|
+
self.meta_handler.update_meta(meta)
|
|
568
|
+
self.meta_handler._group_handler.clean_cache()
|
|
569
|
+
|
|
570
|
+
well_path = self.meta.get_well_path(row=row, column=column)
|
|
571
|
+
group_handler = self._group_handler.get_handler(well_path)
|
|
572
|
+
|
|
573
|
+
if atomic:
|
|
574
|
+
well_lock = group_handler.lock
|
|
575
|
+
else:
|
|
576
|
+
well_lock = MockLock()
|
|
577
|
+
|
|
578
|
+
with well_lock:
|
|
579
|
+
attrs = group_handler.load_attrs()
|
|
580
|
+
if len(attrs) == 0:
|
|
581
|
+
# Initialize the well metadata
|
|
582
|
+
# if the group is empty
|
|
583
|
+
well_meta = NgioWellMeta.default_init()
|
|
584
|
+
version = self.meta.plate.version
|
|
585
|
+
version = version if version is not None else "0.4"
|
|
586
|
+
update_ngio_well_meta(group_handler, well_meta)
|
|
587
|
+
meta_handler = WellMetaHandler(group_handler=group_handler)
|
|
588
|
+
else:
|
|
589
|
+
meta_handler = WellMetaHandler(group_handler=group_handler)
|
|
590
|
+
well_meta = meta_handler.get_meta()
|
|
591
|
+
|
|
592
|
+
group_handler = self._group_handler.get_handler(well_path)
|
|
593
|
+
|
|
594
|
+
if image_path is not None:
|
|
595
|
+
well_meta = well_meta.add_image(
|
|
596
|
+
path=image_path, acquisition=acquisition_id, strict=False
|
|
597
|
+
)
|
|
598
|
+
meta_handler.update_meta(well_meta)
|
|
599
|
+
meta_handler._group_handler.clean_cache()
|
|
600
|
+
|
|
601
|
+
if image_path is not None:
|
|
602
|
+
return f"{well_path}/{image_path}"
|
|
603
|
+
return well_path
|
|
604
|
+
|
|
605
|
+
def atomic_add_image(
|
|
606
|
+
self,
|
|
607
|
+
row: str,
|
|
608
|
+
column: int | str,
|
|
609
|
+
image_path: str,
|
|
610
|
+
acquisition_id: int | None = None,
|
|
611
|
+
acquisition_name: str | None = None,
|
|
612
|
+
) -> str:
|
|
613
|
+
"""Parallel safe version of add_image."""
|
|
614
|
+
if image_path is None:
|
|
615
|
+
raise ValueError(
|
|
616
|
+
"Image path cannot be None for atomic add_image. "
|
|
617
|
+
"If your intent is to add a well, use add_well instead."
|
|
618
|
+
)
|
|
619
|
+
path = self._add_image(
|
|
620
|
+
row=row,
|
|
621
|
+
column=column,
|
|
622
|
+
image_path=image_path,
|
|
623
|
+
acquisition_id=acquisition_id,
|
|
624
|
+
acquisition_name=acquisition_name,
|
|
625
|
+
atomic=True,
|
|
626
|
+
)
|
|
627
|
+
return path
|
|
628
|
+
|
|
629
|
+
def add_image(
|
|
630
|
+
self,
|
|
631
|
+
row: str,
|
|
632
|
+
column: int | str,
|
|
633
|
+
image_path: str,
|
|
634
|
+
acquisition_id: int | None = None,
|
|
635
|
+
acquisition_name: str | None = None,
|
|
636
|
+
) -> str:
|
|
637
|
+
"""Add an image to an ome-zarr plate."""
|
|
638
|
+
if image_path is None:
|
|
639
|
+
raise ValueError(
|
|
640
|
+
"Image path cannot be None for atomic add_image. "
|
|
641
|
+
"If your intent is to add a well, use add_well instead."
|
|
642
|
+
)
|
|
643
|
+
path = self._add_image(
|
|
644
|
+
row=row,
|
|
645
|
+
column=column,
|
|
646
|
+
image_path=image_path,
|
|
647
|
+
acquisition_id=acquisition_id,
|
|
648
|
+
acquisition_name=acquisition_name,
|
|
649
|
+
atomic=False,
|
|
650
|
+
)
|
|
651
|
+
return path
|
|
652
|
+
|
|
653
|
+
def add_well(
|
|
654
|
+
self,
|
|
655
|
+
row: str,
|
|
656
|
+
column: int | str,
|
|
657
|
+
) -> OmeZarrWell:
|
|
658
|
+
"""Add a well to an ome-zarr plate."""
|
|
659
|
+
_ = self._add_image(
|
|
660
|
+
row=row,
|
|
661
|
+
column=column,
|
|
662
|
+
image_path=None,
|
|
663
|
+
acquisition_id=None,
|
|
664
|
+
acquisition_name=None,
|
|
665
|
+
atomic=False,
|
|
666
|
+
)
|
|
667
|
+
return self.get_well(row=row, column=column)
|
|
668
|
+
|
|
669
|
+
def add_column(
|
|
670
|
+
self,
|
|
671
|
+
column: int | str,
|
|
672
|
+
) -> "OmeZarrPlate":
|
|
673
|
+
"""Add a column to an ome-zarr plate."""
|
|
674
|
+
meta, _ = self.meta.add_column(column)
|
|
675
|
+
self.meta_handler.update_meta(meta)
|
|
676
|
+
self.meta_handler._group_handler.clean_cache()
|
|
677
|
+
return self
|
|
678
|
+
|
|
679
|
+
def add_row(
|
|
680
|
+
self,
|
|
681
|
+
row: str,
|
|
682
|
+
) -> "OmeZarrPlate":
|
|
683
|
+
"""Add a row to an ome-zarr plate."""
|
|
684
|
+
meta, _ = self.meta.add_row(row)
|
|
685
|
+
self.meta_handler.update_meta(meta)
|
|
686
|
+
self.meta_handler._group_handler.clean_cache()
|
|
687
|
+
return self
|
|
688
|
+
|
|
689
|
+
def add_acquisition(
|
|
690
|
+
self,
|
|
691
|
+
acquisition_id: int,
|
|
692
|
+
acquisition_name: str,
|
|
693
|
+
) -> "OmeZarrPlate":
|
|
694
|
+
"""Add an acquisition to an ome-zarr plate.
|
|
695
|
+
|
|
696
|
+
Be aware that this is not a parallel safe operation.
|
|
697
|
+
|
|
698
|
+
Args:
|
|
699
|
+
acquisition_id (int): The acquisition id.
|
|
700
|
+
acquisition_name (str): The acquisition name.
|
|
701
|
+
"""
|
|
702
|
+
meta = self.meta.add_acquisition(
|
|
703
|
+
acquisition_id=acquisition_id, acquisition_name=acquisition_name
|
|
704
|
+
)
|
|
705
|
+
self.meta_handler.update_meta(meta)
|
|
706
|
+
self.meta_handler._group_handler.clean_cache()
|
|
707
|
+
return self
|
|
708
|
+
|
|
709
|
+
def _remove_well(
|
|
710
|
+
self,
|
|
711
|
+
row: str,
|
|
712
|
+
column: int | str,
|
|
713
|
+
atomic: bool = False,
|
|
714
|
+
):
|
|
715
|
+
"""Remove a well from an ome-zarr plate."""
|
|
716
|
+
if atomic:
|
|
717
|
+
plate_lock = self._group_handler.lock
|
|
718
|
+
else:
|
|
719
|
+
plate_lock = MockLock()
|
|
720
|
+
|
|
721
|
+
with plate_lock:
|
|
722
|
+
meta = self.meta
|
|
723
|
+
meta = meta.remove_well(row, column)
|
|
724
|
+
self.meta_handler.update_meta(meta)
|
|
725
|
+
self.meta_handler._group_handler.clean_cache()
|
|
726
|
+
|
|
727
|
+
def _remove_image(
|
|
728
|
+
self,
|
|
729
|
+
row: str,
|
|
730
|
+
column: int | str,
|
|
731
|
+
image_path: str,
|
|
732
|
+
atomic: bool = False,
|
|
733
|
+
):
|
|
734
|
+
"""Remove an image from an ome-zarr plate."""
|
|
735
|
+
well = self.get_well(row, column)
|
|
736
|
+
|
|
737
|
+
if atomic:
|
|
738
|
+
well_lock = well.meta_handler._group_handler.lock
|
|
739
|
+
else:
|
|
740
|
+
well_lock = MockLock()
|
|
741
|
+
|
|
742
|
+
with well_lock:
|
|
743
|
+
well_meta = well.meta
|
|
744
|
+
well_meta = well_meta.remove_image(path=image_path)
|
|
745
|
+
well.meta_handler.update_meta(well_meta)
|
|
746
|
+
well.meta_handler._group_handler.clean_cache()
|
|
747
|
+
if len(well_meta.paths()) == 0:
|
|
748
|
+
self._remove_well(row, column, atomic=atomic)
|
|
749
|
+
|
|
750
|
+
def atomic_remove_image(
|
|
751
|
+
self,
|
|
752
|
+
row: str,
|
|
753
|
+
column: int | str,
|
|
754
|
+
image_path: str,
|
|
755
|
+
):
|
|
756
|
+
"""Parallel safe version of remove_image."""
|
|
757
|
+
return self._remove_image(
|
|
758
|
+
row=row,
|
|
759
|
+
column=column,
|
|
760
|
+
image_path=image_path,
|
|
761
|
+
atomic=True,
|
|
762
|
+
)
|
|
763
|
+
|
|
764
|
+
def remove_image(
|
|
765
|
+
self,
|
|
766
|
+
row: str,
|
|
767
|
+
column: int | str,
|
|
768
|
+
image_path: str,
|
|
769
|
+
):
|
|
770
|
+
"""Remove an image from an ome-zarr plate."""
|
|
771
|
+
return self._remove_image(
|
|
772
|
+
row=row,
|
|
773
|
+
column=column,
|
|
774
|
+
image_path=image_path,
|
|
775
|
+
atomic=False,
|
|
776
|
+
)
|
|
777
|
+
|
|
778
|
+
def derive_plate(
|
|
779
|
+
self,
|
|
780
|
+
store: StoreOrGroup,
|
|
781
|
+
plate_name: str | None = None,
|
|
782
|
+
version: NgffVersions | None = None,
|
|
783
|
+
ngff_version: NgffVersions = DefaultNgffVersion,
|
|
784
|
+
keep_acquisitions: bool = False,
|
|
785
|
+
cache: bool = False,
|
|
786
|
+
overwrite: bool = False,
|
|
787
|
+
) -> "OmeZarrPlate":
|
|
788
|
+
"""Derive a new OME-Zarr plate from an existing one.
|
|
789
|
+
|
|
790
|
+
Args:
|
|
791
|
+
store (StoreOrGroup): The Zarr store or group that stores the plate.
|
|
792
|
+
plate_name (str | None): The name of the new plate.
|
|
793
|
+
version (NgffVersion | None): Deprecated. Please use 'ngff_version' instead.
|
|
794
|
+
ngff_version (NgffVersion): The NGFF version to use for the new plate.
|
|
795
|
+
keep_acquisitions (bool): Whether to keep the acquisitions in the new plate.
|
|
796
|
+
cache (bool): Whether to use a cache for the zarr group metadata.
|
|
797
|
+
overwrite (bool): Whether to overwrite the existing plate.
|
|
798
|
+
"""
|
|
799
|
+
return derive_ome_zarr_plate(
|
|
800
|
+
ome_zarr_plate=self,
|
|
801
|
+
store=store,
|
|
802
|
+
plate_name=plate_name,
|
|
803
|
+
ngff_version=ngff_version,
|
|
804
|
+
version=version,
|
|
805
|
+
keep_acquisitions=keep_acquisitions,
|
|
806
|
+
cache=cache,
|
|
807
|
+
overwrite=overwrite,
|
|
808
|
+
)
|
|
809
|
+
|
|
810
|
+
def _get_tables_container(self, create_mode: bool = True) -> TablesContainer | None:
|
|
811
|
+
"""Return the tables container."""
|
|
812
|
+
if self._tables_container is not None:
|
|
813
|
+
return self._tables_container
|
|
814
|
+
_tables_container = _try_get_table_container(
|
|
815
|
+
self._group_handler, create_mode=create_mode
|
|
816
|
+
)
|
|
817
|
+
self._tables_container = _tables_container
|
|
818
|
+
return self._tables_container
|
|
819
|
+
|
|
820
|
+
@property
|
|
821
|
+
def tables_container(self) -> TablesContainer:
|
|
822
|
+
"""Return the tables container."""
|
|
823
|
+
_table_container = self._get_tables_container()
|
|
824
|
+
if _table_container is None:
|
|
825
|
+
raise NgioValueError(
|
|
826
|
+
"No tables container found. Please add a tables container to the plate."
|
|
827
|
+
)
|
|
828
|
+
return _table_container
|
|
829
|
+
|
|
830
|
+
def list_tables(self, filter_types: TypedTable | str | None = None) -> list[str]:
|
|
831
|
+
"""List all tables in the image."""
|
|
832
|
+
_tables_container = self._get_tables_container(create_mode=False)
|
|
833
|
+
if _tables_container is None:
|
|
834
|
+
return []
|
|
835
|
+
return self.tables_container.list(filter_types=filter_types)
|
|
836
|
+
|
|
837
|
+
def list_roi_tables(self) -> list[str]:
|
|
838
|
+
"""List all ROI tables in the image."""
|
|
839
|
+
roi = self.tables_container.list(
|
|
840
|
+
filter_types="roi_table",
|
|
841
|
+
)
|
|
842
|
+
masking_roi = self.tables_container.list(
|
|
843
|
+
filter_types="masking_roi_table",
|
|
844
|
+
)
|
|
845
|
+
return roi + masking_roi
|
|
846
|
+
|
|
847
|
+
def get_roi_table(self, name: str) -> RoiTable:
|
|
848
|
+
"""Get a ROI table from the image.
|
|
849
|
+
|
|
850
|
+
Args:
|
|
851
|
+
name (str): The name of the table.
|
|
852
|
+
"""
|
|
853
|
+
table = self.tables_container.get(name=name, strict=True)
|
|
854
|
+
if not isinstance(table, RoiTable):
|
|
855
|
+
raise NgioValueError(f"Table {name} is not a ROI table. Got {type(table)}")
|
|
856
|
+
return table
|
|
857
|
+
|
|
858
|
+
def get_masking_roi_table(self, name: str) -> MaskingRoiTable:
|
|
859
|
+
"""Get a masking ROI table from the image.
|
|
860
|
+
|
|
861
|
+
Args:
|
|
862
|
+
name (str): The name of the table.
|
|
863
|
+
"""
|
|
864
|
+
table = self.tables_container.get(name=name, strict=True)
|
|
865
|
+
if not isinstance(table, MaskingRoiTable):
|
|
866
|
+
raise NgioValueError(
|
|
867
|
+
f"Table {name} is not a masking ROI table. Got {type(table)}"
|
|
868
|
+
)
|
|
869
|
+
return table
|
|
870
|
+
|
|
871
|
+
def get_feature_table(self, name: str) -> FeatureTable:
|
|
872
|
+
"""Get a feature table from the image.
|
|
873
|
+
|
|
874
|
+
Args:
|
|
875
|
+
name (str): The name of the table.
|
|
876
|
+
"""
|
|
877
|
+
table = self.tables_container.get(name=name, strict=True)
|
|
878
|
+
if not isinstance(table, FeatureTable):
|
|
879
|
+
raise NgioValueError(
|
|
880
|
+
f"Table {name} is not a feature table. Got {type(table)}"
|
|
881
|
+
)
|
|
882
|
+
return table
|
|
883
|
+
|
|
884
|
+
def get_generic_roi_table(self, name: str) -> GenericRoiTable:
|
|
885
|
+
"""Get a generic ROI table from the image.
|
|
886
|
+
|
|
887
|
+
Args:
|
|
888
|
+
name (str): The name of the table.
|
|
889
|
+
"""
|
|
890
|
+
table = self.tables_container.get(name=name, strict=True)
|
|
891
|
+
if not isinstance(table, GenericRoiTable):
|
|
892
|
+
raise NgioValueError(
|
|
893
|
+
f"Table {name} is not a generic ROI table. Got {type(table)}"
|
|
894
|
+
)
|
|
895
|
+
return table
|
|
896
|
+
|
|
897
|
+
def get_condition_table(self, name: str) -> ConditionTable:
|
|
898
|
+
"""Get a condition table from the image.
|
|
899
|
+
|
|
900
|
+
Args:
|
|
901
|
+
name (str): The name of the table.
|
|
902
|
+
"""
|
|
903
|
+
table = self.tables_container.get(name=name, strict=True)
|
|
904
|
+
if not isinstance(table, ConditionTable):
|
|
905
|
+
raise NgioValueError(
|
|
906
|
+
f"Table {name} is not a condition table. Got {type(table)}"
|
|
907
|
+
)
|
|
908
|
+
return table
|
|
909
|
+
|
|
910
|
+
def get_table(self, name: str, check_type: TypedTable | None = None) -> Table:
|
|
911
|
+
"""Get a table from the image.
|
|
912
|
+
|
|
913
|
+
Args:
|
|
914
|
+
name (str): The name of the table.
|
|
915
|
+
check_type (TypedTable | None): Deprecated. Please use
|
|
916
|
+
'get_table_as' instead, or one of the type specific
|
|
917
|
+
get_*table() methods.
|
|
918
|
+
|
|
919
|
+
"""
|
|
920
|
+
if check_type is not None:
|
|
921
|
+
warnings.warn(
|
|
922
|
+
"The 'check_type' argument is deprecated, and will be removed in "
|
|
923
|
+
"ngio=0.3. Use 'get_table_as' instead or one of the "
|
|
924
|
+
"type specific get_*table() methods.",
|
|
925
|
+
DeprecationWarning,
|
|
926
|
+
stacklevel=2,
|
|
927
|
+
)
|
|
928
|
+
return self.tables_container.get(name=name, strict=False)
|
|
929
|
+
|
|
930
|
+
def get_table_as(
|
|
931
|
+
self,
|
|
932
|
+
name: str,
|
|
933
|
+
table_cls: type[TableType],
|
|
934
|
+
backend: TableBackend | None = None,
|
|
935
|
+
) -> TableType:
|
|
936
|
+
"""Get a table from the image as a specific type.
|
|
937
|
+
|
|
938
|
+
Args:
|
|
939
|
+
name (str): The name of the table.
|
|
940
|
+
table_cls (type[TableType]): The type of the table.
|
|
941
|
+
backend (TableBackend | None): The backend to use. If None,
|
|
942
|
+
the default backend is used.
|
|
943
|
+
"""
|
|
944
|
+
return self.tables_container.get_as(
|
|
945
|
+
name=name,
|
|
946
|
+
table_cls=table_cls,
|
|
947
|
+
backend=backend,
|
|
948
|
+
)
|
|
949
|
+
|
|
950
|
+
def add_table(
|
|
951
|
+
self,
|
|
952
|
+
name: str,
|
|
953
|
+
table: Table,
|
|
954
|
+
backend: TableBackend = DefaultTableBackend,
|
|
955
|
+
overwrite: bool = False,
|
|
956
|
+
) -> None:
|
|
957
|
+
"""Add a table to the image."""
|
|
958
|
+
self.tables_container.add(
|
|
959
|
+
name=name, table=table, backend=backend, overwrite=overwrite
|
|
960
|
+
)
|
|
961
|
+
|
|
962
|
+
def delete_table(self, name: str, missing_ok: bool = False) -> None:
|
|
963
|
+
"""Delete a table from the group.
|
|
964
|
+
|
|
965
|
+
Args:
|
|
966
|
+
name (str): The name of the table to delete.
|
|
967
|
+
missing_ok (bool): If True, do not raise an error if the table does not
|
|
968
|
+
exist.
|
|
969
|
+
|
|
970
|
+
"""
|
|
971
|
+
table_container = self._get_tables_container(create_mode=False)
|
|
972
|
+
if table_container is None and missing_ok:
|
|
973
|
+
return
|
|
974
|
+
if table_container is None:
|
|
975
|
+
raise NgioValueError(
|
|
976
|
+
f"No tables found in the image, cannot delete {name}. "
|
|
977
|
+
"Set missing_ok=True to ignore this error."
|
|
978
|
+
)
|
|
979
|
+
table_container.delete(name=name, missing_ok=missing_ok)
|
|
980
|
+
|
|
981
|
+
def list_image_tables(
|
|
982
|
+
self,
|
|
983
|
+
acquisition: int | None = None,
|
|
984
|
+
filter_types: str | None = None,
|
|
985
|
+
mode: Literal["common", "all"] = "common",
|
|
986
|
+
) -> list[str]:
|
|
987
|
+
"""List all image tables in the image.
|
|
988
|
+
|
|
989
|
+
Args:
|
|
990
|
+
acquisition (int | None): The acquisition id to filter the images.
|
|
991
|
+
filter_types (str | None): The type of tables to filter. If None,
|
|
992
|
+
return all tables. Defaults to None.
|
|
993
|
+
mode (Literal["common", "all"]): The mode to use for listing the tables.
|
|
994
|
+
If 'common', return only common tables between all images.
|
|
995
|
+
If 'all', return all tables. Defaults to 'common'.
|
|
996
|
+
"""
|
|
997
|
+
images = tuple(self.get_images(acquisition=acquisition).values())
|
|
998
|
+
return list_image_tables(
|
|
999
|
+
images=images,
|
|
1000
|
+
filter_types=filter_types,
|
|
1001
|
+
mode=mode,
|
|
1002
|
+
)
|
|
1003
|
+
|
|
1004
|
+
async def list_image_tables_async(
|
|
1005
|
+
self,
|
|
1006
|
+
acquisition: int | None = None,
|
|
1007
|
+
filter_types: str | None = None,
|
|
1008
|
+
mode: Literal["common", "all"] = "common",
|
|
1009
|
+
) -> list[str]:
|
|
1010
|
+
"""List all image tables in the image asynchronously.
|
|
1011
|
+
|
|
1012
|
+
Args:
|
|
1013
|
+
acquisition (int | None): The acquisition id to filter the images.
|
|
1014
|
+
filter_types (str | None): The type of tables to filter. If None,
|
|
1015
|
+
return all tables. Defaults to None.
|
|
1016
|
+
mode (Literal["common", "all"]): The mode to use for listing the tables.
|
|
1017
|
+
If 'common', return only common tables between all images.
|
|
1018
|
+
If 'all', return all tables. Defaults to 'common'.
|
|
1019
|
+
"""
|
|
1020
|
+
images = await self.get_images_async(acquisition=acquisition)
|
|
1021
|
+
images = tuple(images.values())
|
|
1022
|
+
return await list_image_tables_async(
|
|
1023
|
+
images=images,
|
|
1024
|
+
filter_types=filter_types,
|
|
1025
|
+
mode=mode,
|
|
1026
|
+
)
|
|
1027
|
+
|
|
1028
|
+
def concatenate_image_tables(
|
|
1029
|
+
self,
|
|
1030
|
+
name: str,
|
|
1031
|
+
acquisition: int | None = None,
|
|
1032
|
+
strict: bool = True,
|
|
1033
|
+
index_key: str | None = None,
|
|
1034
|
+
mode: Literal["eager", "lazy"] = "eager",
|
|
1035
|
+
) -> Table:
|
|
1036
|
+
"""Concatenate tables from all images in the plate.
|
|
1037
|
+
|
|
1038
|
+
Args:
|
|
1039
|
+
name: The name of the table to concatenate.
|
|
1040
|
+
index_key: The key to use for the index of the concatenated table.
|
|
1041
|
+
acquisition: The acquisition id to filter the images.
|
|
1042
|
+
strict: If True, raise an error if the table is not found in the image.
|
|
1043
|
+
index_key: If a string is provided, a new index column will be created
|
|
1044
|
+
new_index_pattern = {row}_{column}_{path_in_well}_{label}
|
|
1045
|
+
mode: The mode to use for concatenation. Can be 'eager' or 'lazy'.
|
|
1046
|
+
if 'eager', the table will be loaded into memory.
|
|
1047
|
+
if 'lazy', the table will be loaded as a lazy frame.
|
|
1048
|
+
"""
|
|
1049
|
+
images = self.get_images(acquisition=acquisition)
|
|
1050
|
+
extras = _build_extras(tuple(images.keys()))
|
|
1051
|
+
return concatenate_image_tables(
|
|
1052
|
+
images=tuple(images.values()),
|
|
1053
|
+
extras=extras,
|
|
1054
|
+
name=name,
|
|
1055
|
+
index_key=index_key,
|
|
1056
|
+
strict=strict,
|
|
1057
|
+
mode=mode,
|
|
1058
|
+
)
|
|
1059
|
+
|
|
1060
|
+
def concatenate_image_tables_as(
|
|
1061
|
+
self,
|
|
1062
|
+
name: str,
|
|
1063
|
+
table_cls: type[TableType],
|
|
1064
|
+
acquisition: int | None = None,
|
|
1065
|
+
index_key: str | None = None,
|
|
1066
|
+
strict: bool = True,
|
|
1067
|
+
mode: Literal["eager", "lazy"] = "eager",
|
|
1068
|
+
) -> TableType:
|
|
1069
|
+
"""Concatenate tables from all images in the plate as a specific type.
|
|
1070
|
+
|
|
1071
|
+
Args:
|
|
1072
|
+
name: The name of the table to concatenate.
|
|
1073
|
+
table_cls: The type of the table to concatenate.
|
|
1074
|
+
index_key: The key to use for the index of the concatenated table.
|
|
1075
|
+
acquisition: The acquisition id to filter the images.
|
|
1076
|
+
index_key: If a string is provided, a new index column will be created
|
|
1077
|
+
new_index_pattern = {row}_{column}_{path_in_well}_{label}
|
|
1078
|
+
strict: If True, raise an error if the table is not found in the image.
|
|
1079
|
+
mode: The mode to use for concatenation. Can be 'eager' or 'lazy'.
|
|
1080
|
+
if 'eager', the table will be loaded into memory.
|
|
1081
|
+
if 'lazy', the table will be loaded as a lazy frame.
|
|
1082
|
+
"""
|
|
1083
|
+
images = self.get_images(acquisition=acquisition)
|
|
1084
|
+
extras = _build_extras(tuple(images.keys()))
|
|
1085
|
+
return concatenate_image_tables_as(
|
|
1086
|
+
images=tuple(images.values()),
|
|
1087
|
+
extras=extras,
|
|
1088
|
+
name=name,
|
|
1089
|
+
table_cls=table_cls,
|
|
1090
|
+
index_key=index_key,
|
|
1091
|
+
strict=strict,
|
|
1092
|
+
mode=mode,
|
|
1093
|
+
)
|
|
1094
|
+
|
|
1095
|
+
async def concatenate_image_tables_async(
|
|
1096
|
+
self,
|
|
1097
|
+
name: str,
|
|
1098
|
+
acquisition: int | None = None,
|
|
1099
|
+
index_key: str | None = None,
|
|
1100
|
+
strict: bool = True,
|
|
1101
|
+
mode: Literal["eager", "lazy"] = "eager",
|
|
1102
|
+
) -> Table:
|
|
1103
|
+
"""Concatenate tables from all images in the plate asynchronously.
|
|
1104
|
+
|
|
1105
|
+
Args:
|
|
1106
|
+
name: The name of the table to concatenate.
|
|
1107
|
+
index_key: The key to use for the index of the concatenated table.
|
|
1108
|
+
acquisition: The acquisition id to filter the images.
|
|
1109
|
+
index_key: If a string is provided, a new index column will be created
|
|
1110
|
+
new_index_pattern = {row}_{column}_{path_in_well}_{label}
|
|
1111
|
+
strict: If True, raise an error if the table is not found in the image.
|
|
1112
|
+
mode: The mode to use for concatenation. Can be 'eager' or 'lazy'.
|
|
1113
|
+
if 'eager', the table will be loaded into memory.
|
|
1114
|
+
if 'lazy', the table will be loaded as a lazy frame.
|
|
1115
|
+
"""
|
|
1116
|
+
images = await self.get_images_async(acquisition=acquisition)
|
|
1117
|
+
extras = _build_extras(tuple(images.keys()))
|
|
1118
|
+
return await concatenate_image_tables_async(
|
|
1119
|
+
images=tuple(images.values()),
|
|
1120
|
+
extras=extras,
|
|
1121
|
+
name=name,
|
|
1122
|
+
index_key=index_key,
|
|
1123
|
+
strict=strict,
|
|
1124
|
+
mode=mode,
|
|
1125
|
+
)
|
|
1126
|
+
|
|
1127
|
+
async def concatenate_image_tables_as_async(
|
|
1128
|
+
self,
|
|
1129
|
+
name: str,
|
|
1130
|
+
table_cls: type[TableType],
|
|
1131
|
+
acquisition: int | None = None,
|
|
1132
|
+
index_key: str | None = None,
|
|
1133
|
+
strict: bool = True,
|
|
1134
|
+
mode: Literal["eager", "lazy"] = "eager",
|
|
1135
|
+
) -> TableType:
|
|
1136
|
+
"""Concatenate tables from all images in the plate as a specific type.
|
|
1137
|
+
|
|
1138
|
+
Args:
|
|
1139
|
+
name: The name of the table to concatenate.
|
|
1140
|
+
table_cls: The type of the table to concatenate.
|
|
1141
|
+
index_key: The key to use for the index of the concatenated table.
|
|
1142
|
+
acquisition: The acquisition id to filter the images.
|
|
1143
|
+
index_key: If a string is provided, a new index column will be created
|
|
1144
|
+
new_index_pattern = {row}_{column}_{path_in_well}_{label}
|
|
1145
|
+
strict: If True, raise an error if the table is not found in the image.
|
|
1146
|
+
mode: The mode to use for concatenation. Can be 'eager' or 'lazy'.
|
|
1147
|
+
if 'eager', the table will be loaded into memory.
|
|
1148
|
+
if 'lazy', the table will be loaded as a lazy frame.
|
|
1149
|
+
"""
|
|
1150
|
+
images = await self.get_images_async(acquisition=acquisition)
|
|
1151
|
+
extras = _build_extras(tuple(images.keys()))
|
|
1152
|
+
return await concatenate_image_tables_as_async(
|
|
1153
|
+
images=tuple(images.values()),
|
|
1154
|
+
extras=extras,
|
|
1155
|
+
name=name,
|
|
1156
|
+
table_cls=table_cls,
|
|
1157
|
+
index_key=index_key,
|
|
1158
|
+
strict=strict,
|
|
1159
|
+
mode=mode,
|
|
1160
|
+
)
|
|
1161
|
+
|
|
1162
|
+
|
|
1163
|
+
def open_ome_zarr_plate(
|
|
1164
|
+
store: StoreOrGroup,
|
|
1165
|
+
cache: bool = False,
|
|
1166
|
+
mode: AccessModeLiteral = "r+",
|
|
1167
|
+
) -> OmeZarrPlate:
|
|
1168
|
+
"""Open an OME-Zarr plate.
|
|
1169
|
+
|
|
1170
|
+
Args:
|
|
1171
|
+
store (StoreOrGroup): The Zarr store or group that stores the plate.
|
|
1172
|
+
cache (bool): Whether to use a cache for the zarr group metadata.
|
|
1173
|
+
mode (AccessModeLiteral): The
|
|
1174
|
+
access mode for the image. Defaults to "r+".
|
|
1175
|
+
"""
|
|
1176
|
+
group_handler = ZarrGroupHandler(store=store, cache=cache, mode=mode)
|
|
1177
|
+
return OmeZarrPlate(group_handler)
|
|
1178
|
+
|
|
1179
|
+
|
|
1180
|
+
def _create_empty_plate_from_meta(
|
|
1181
|
+
store: StoreOrGroup,
|
|
1182
|
+
meta: NgioPlateMeta,
|
|
1183
|
+
overwrite: bool = False,
|
|
1184
|
+
) -> ZarrGroupHandler:
|
|
1185
|
+
"""Create an empty OME-Zarr plate from metadata."""
|
|
1186
|
+
mode = "w" if overwrite else "w-"
|
|
1187
|
+
group_handler = ZarrGroupHandler(store=store, cache=True, mode=mode)
|
|
1188
|
+
update_ngio_plate_meta(group_handler, meta)
|
|
1189
|
+
return group_handler
|
|
1190
|
+
|
|
1191
|
+
|
|
1192
|
+
def create_empty_plate(
|
|
1193
|
+
store: StoreOrGroup,
|
|
1194
|
+
name: str,
|
|
1195
|
+
images: list[ImageInWellPath] | None = None,
|
|
1196
|
+
version: NgffVersions | None = None,
|
|
1197
|
+
ngff_version: NgffVersions = DefaultNgffVersion,
|
|
1198
|
+
cache: bool = False,
|
|
1199
|
+
overwrite: bool = False,
|
|
1200
|
+
) -> OmeZarrPlate:
|
|
1201
|
+
"""Initialize and create an empty OME-Zarr plate.
|
|
1202
|
+
|
|
1203
|
+
Args:
|
|
1204
|
+
store (StoreOrGroup): The Zarr store or group that stores the plate.
|
|
1205
|
+
name (str): The name of the plate.
|
|
1206
|
+
images (list[ImageInWellPath] | None): A list of images to add to the plate.
|
|
1207
|
+
If None, no images are added. Defaults to None.
|
|
1208
|
+
version (NgffVersion | None): Deprecated. Please use 'ngff_version' instead.
|
|
1209
|
+
ngff_version (NgffVersion): The NGFF version to use for the new plate.
|
|
1210
|
+
cache (bool): Whether to use a cache for the zarr group metadata.
|
|
1211
|
+
overwrite (bool): Whether to overwrite the existing plate.
|
|
1212
|
+
"""
|
|
1213
|
+
if version is not None:
|
|
1214
|
+
warnings.warn(
|
|
1215
|
+
"The 'version' argument is deprecated, and will be removed in ngio=0.3. "
|
|
1216
|
+
"Please use 'ngff_version' instead.",
|
|
1217
|
+
DeprecationWarning,
|
|
1218
|
+
stacklevel=2,
|
|
1219
|
+
)
|
|
1220
|
+
ngff_version = version
|
|
1221
|
+
plate_meta = NgioPlateMeta.default_init(
|
|
1222
|
+
name=name,
|
|
1223
|
+
ngff_version=ngff_version,
|
|
1224
|
+
)
|
|
1225
|
+
group_handler = _create_empty_plate_from_meta(
|
|
1226
|
+
store=store,
|
|
1227
|
+
meta=plate_meta,
|
|
1228
|
+
overwrite=overwrite,
|
|
1229
|
+
)
|
|
1230
|
+
|
|
1231
|
+
if images is not None:
|
|
1232
|
+
plate = OmeZarrPlate(group_handler)
|
|
1233
|
+
for image in images:
|
|
1234
|
+
plate.add_image(
|
|
1235
|
+
row=image.row,
|
|
1236
|
+
column=image.column,
|
|
1237
|
+
image_path=image.path,
|
|
1238
|
+
acquisition_id=image.acquisition_id,
|
|
1239
|
+
acquisition_name=image.acquisition_name,
|
|
1240
|
+
)
|
|
1241
|
+
return open_ome_zarr_plate(
|
|
1242
|
+
store=store,
|
|
1243
|
+
cache=cache,
|
|
1244
|
+
mode="r+",
|
|
1245
|
+
)
|
|
1246
|
+
|
|
1247
|
+
|
|
1248
|
+
def derive_ome_zarr_plate(
|
|
1249
|
+
ome_zarr_plate: OmeZarrPlate,
|
|
1250
|
+
store: StoreOrGroup,
|
|
1251
|
+
plate_name: str | None = None,
|
|
1252
|
+
version: NgffVersions | None = None,
|
|
1253
|
+
ngff_version: NgffVersions = DefaultNgffVersion,
|
|
1254
|
+
keep_acquisitions: bool = False,
|
|
1255
|
+
cache: bool = False,
|
|
1256
|
+
overwrite: bool = False,
|
|
1257
|
+
) -> OmeZarrPlate:
|
|
1258
|
+
"""Derive a new OME-Zarr plate from an existing one.
|
|
1259
|
+
|
|
1260
|
+
Args:
|
|
1261
|
+
ome_zarr_plate (OmeZarrPlate): The existing OME-Zarr plate.
|
|
1262
|
+
store (StoreOrGroup): The Zarr store or group that stores the plate.
|
|
1263
|
+
plate_name (str | None): The name of the new plate.
|
|
1264
|
+
version (NgffVersion | None): Deprecated. Please use 'ngff_version' instead.
|
|
1265
|
+
ngff_version (NgffVersion): The NGFF version to use for the new plate.
|
|
1266
|
+
keep_acquisitions (bool): Whether to keep the acquisitions in the new plate.
|
|
1267
|
+
cache (bool): Whether to use a cache for the zarr group metadata.
|
|
1268
|
+
overwrite (bool): Whether to overwrite the existing plate.
|
|
1269
|
+
"""
|
|
1270
|
+
if version is not None:
|
|
1271
|
+
warnings.warn(
|
|
1272
|
+
"The 'version' argument is deprecated, and will be removed in ngio=0.3. "
|
|
1273
|
+
"Please use 'ngff_version' instead.",
|
|
1274
|
+
DeprecationWarning,
|
|
1275
|
+
stacklevel=2,
|
|
1276
|
+
)
|
|
1277
|
+
ngff_version = version
|
|
1278
|
+
|
|
1279
|
+
if plate_name is None:
|
|
1280
|
+
plate_name = ome_zarr_plate.meta.plate.name
|
|
1281
|
+
|
|
1282
|
+
new_meta = ome_zarr_plate.meta.derive(
|
|
1283
|
+
name=plate_name,
|
|
1284
|
+
ngff_version=ngff_version,
|
|
1285
|
+
keep_acquisitions=keep_acquisitions,
|
|
1286
|
+
)
|
|
1287
|
+
_ = _create_empty_plate_from_meta(
|
|
1288
|
+
store=store,
|
|
1289
|
+
meta=new_meta,
|
|
1290
|
+
overwrite=overwrite,
|
|
1291
|
+
)
|
|
1292
|
+
return open_ome_zarr_plate(
|
|
1293
|
+
store=store,
|
|
1294
|
+
cache=cache,
|
|
1295
|
+
mode="r+",
|
|
1296
|
+
)
|
|
1297
|
+
|
|
1298
|
+
|
|
1299
|
+
def open_ome_zarr_well(
|
|
1300
|
+
store: StoreOrGroup,
|
|
1301
|
+
cache: bool = False,
|
|
1302
|
+
mode: AccessModeLiteral = "r+",
|
|
1303
|
+
) -> OmeZarrWell:
|
|
1304
|
+
"""Open an OME-Zarr well.
|
|
1305
|
+
|
|
1306
|
+
Args:
|
|
1307
|
+
store (StoreOrGroup): The Zarr store or group that stores the plate.
|
|
1308
|
+
cache (bool): Whether to use a cache for the zarr group metadata.
|
|
1309
|
+
mode (AccessModeLiteral): The access mode for the image. Defaults to "r+".
|
|
1310
|
+
"""
|
|
1311
|
+
group_handler = ZarrGroupHandler(
|
|
1312
|
+
store=store,
|
|
1313
|
+
cache=cache,
|
|
1314
|
+
mode=mode,
|
|
1315
|
+
)
|
|
1316
|
+
return OmeZarrWell(group_handler)
|
|
1317
|
+
|
|
1318
|
+
|
|
1319
|
+
def create_empty_well(
|
|
1320
|
+
store: StoreOrGroup,
|
|
1321
|
+
version: NgffVersions | None = None,
|
|
1322
|
+
ngff_version: NgffVersions = DefaultNgffVersion,
|
|
1323
|
+
cache: bool = False,
|
|
1324
|
+
overwrite: bool = False,
|
|
1325
|
+
) -> OmeZarrWell:
|
|
1326
|
+
"""Create an empty OME-Zarr well.
|
|
1327
|
+
|
|
1328
|
+
Args:
|
|
1329
|
+
store (StoreOrGroup): The Zarr store or group that stores the well.
|
|
1330
|
+
version (NgffVersion | None): Deprecated. Please use 'ngff_version' instead.
|
|
1331
|
+
ngff_version (NgffVersion): The version of the new well.
|
|
1332
|
+
cache (bool): Whether to use a cache for the zarr group metadata.
|
|
1333
|
+
overwrite (bool): Whether to overwrite the existing well.
|
|
1334
|
+
"""
|
|
1335
|
+
if version is not None:
|
|
1336
|
+
warnings.warn(
|
|
1337
|
+
"The 'version' argument is deprecated, and will be removed in ngio=0.3. "
|
|
1338
|
+
"Please use 'ngff_version' instead.",
|
|
1339
|
+
DeprecationWarning,
|
|
1340
|
+
stacklevel=2,
|
|
1341
|
+
)
|
|
1342
|
+
ngff_version = version
|
|
1343
|
+
group_handler = ZarrGroupHandler(
|
|
1344
|
+
store=store, cache=True, mode="w" if overwrite else "w-"
|
|
1345
|
+
)
|
|
1346
|
+
update_ngio_well_meta(
|
|
1347
|
+
group_handler, NgioWellMeta.default_init(ngff_version=ngff_version)
|
|
1348
|
+
)
|
|
1349
|
+
|
|
1350
|
+
return open_ome_zarr_well(
|
|
1351
|
+
store=store,
|
|
1352
|
+
cache=cache,
|
|
1353
|
+
mode="r+",
|
|
1354
|
+
)
|