ngio 0.2.8__py3-none-any.whl → 0.3.0a0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ngio/common/__init__.py +16 -0
- ngio/common/_table_ops.py +471 -0
- ngio/hcs/plate.py +430 -72
- ngio/images/ome_zarr_container.py +99 -68
- ngio/tables/__init__.py +8 -1
- ngio/tables/abstract_table.py +268 -0
- ngio/tables/backends/__init__.py +18 -0
- ngio/tables/backends/_abstract_backend.py +58 -80
- ngio/tables/backends/_anndata_v1.py +4 -0
- ngio/tables/backends/_csv_v1.py +23 -150
- ngio/tables/backends/_json_v1.py +3 -0
- ngio/tables/backends/_non_zarr_backends_v1.py +196 -0
- ngio/tables/backends/_parquet_v1.py +47 -0
- ngio/tables/backends/_table_backends.py +34 -15
- ngio/tables/backends/_utils.py +147 -1
- ngio/tables/tables_container.py +180 -92
- ngio/tables/v1/__init__.py +8 -1
- ngio/tables/v1/_condition_table.py +67 -0
- ngio/tables/v1/_feature_table.py +62 -126
- ngio/tables/v1/_generic_table.py +14 -163
- ngio/tables/v1/_roi_table.py +281 -201
- ngio/utils/_fractal_fsspec_store.py +29 -0
- {ngio-0.2.8.dist-info → ngio-0.3.0a0.dist-info}/METADATA +3 -3
- {ngio-0.2.8.dist-info → ngio-0.3.0a0.dist-info}/RECORD +26 -22
- ngio/tables/_validators.py +0 -108
- {ngio-0.2.8.dist-info → ngio-0.3.0a0.dist-info}/WHEEL +0 -0
- {ngio-0.2.8.dist-info → ngio-0.3.0a0.dist-info}/licenses/LICENSE +0 -0
ngio/common/__init__.py
CHANGED
|
@@ -24,6 +24,15 @@ from ngio.common._slicer import (
|
|
|
24
24
|
numpy_get_slice,
|
|
25
25
|
numpy_set_slice,
|
|
26
26
|
)
|
|
27
|
+
from ngio.common._table_ops import (
|
|
28
|
+
concatenate_image_tables,
|
|
29
|
+
concatenate_image_tables_as,
|
|
30
|
+
concatenate_image_tables_as_async,
|
|
31
|
+
concatenate_image_tables_async,
|
|
32
|
+
conctatenate_tables,
|
|
33
|
+
list_image_tables,
|
|
34
|
+
list_image_tables_async,
|
|
35
|
+
)
|
|
27
36
|
from ngio.common._zoom import dask_zoom, numpy_zoom
|
|
28
37
|
|
|
29
38
|
__all__ = [
|
|
@@ -34,6 +43,11 @@ __all__ = [
|
|
|
34
43
|
"SliceTransform",
|
|
35
44
|
"compute_and_slices",
|
|
36
45
|
"compute_masking_roi",
|
|
46
|
+
"concatenate_image_tables",
|
|
47
|
+
"concatenate_image_tables_as",
|
|
48
|
+
"concatenate_image_tables_as_async",
|
|
49
|
+
"concatenate_image_tables_async",
|
|
50
|
+
"conctatenate_tables",
|
|
37
51
|
"consolidate_pyramid",
|
|
38
52
|
"dask_get_slice",
|
|
39
53
|
"dask_set_slice",
|
|
@@ -41,6 +55,8 @@ __all__ = [
|
|
|
41
55
|
"get_masked_pipe",
|
|
42
56
|
"get_pipe",
|
|
43
57
|
"init_empty_pyramid",
|
|
58
|
+
"list_image_tables",
|
|
59
|
+
"list_image_tables_async",
|
|
44
60
|
"numpy_get_slice",
|
|
45
61
|
"numpy_set_slice",
|
|
46
62
|
"numpy_zoom",
|
|
@@ -0,0 +1,471 @@
|
|
|
1
|
+
"""Aggregation and filtering operations for tables."""
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
from collections import Counter
|
|
5
|
+
from collections.abc import Collection
|
|
6
|
+
from dataclasses import dataclass, field
|
|
7
|
+
from typing import Literal
|
|
8
|
+
|
|
9
|
+
import pandas as pd
|
|
10
|
+
import polars as pl
|
|
11
|
+
|
|
12
|
+
from ngio.images.ome_zarr_container import OmeZarrContainer
|
|
13
|
+
from ngio.tables import Table, TableType
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass
|
|
17
|
+
class TableWithExtras:
|
|
18
|
+
"""A class to hold a table and its extras."""
|
|
19
|
+
|
|
20
|
+
table: Table
|
|
21
|
+
extras: dict[str, str] = field(default_factory=dict)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _reindex_dataframe(
|
|
25
|
+
dataframe, index_cols: list[str], index_key: str | None = None
|
|
26
|
+
) -> pd.DataFrame:
|
|
27
|
+
"""Reindex a dataframe using an hash of the index columns."""
|
|
28
|
+
# Reindex the dataframe
|
|
29
|
+
old_index = dataframe.index.name
|
|
30
|
+
if old_index is not None:
|
|
31
|
+
dataframe = dataframe.reset_index()
|
|
32
|
+
index_cols.append(old_index)
|
|
33
|
+
dataframe.index = dataframe[index_cols].astype(str).agg("_".join, axis=1)
|
|
34
|
+
|
|
35
|
+
if index_key is None:
|
|
36
|
+
dataframe.index.name = index_key
|
|
37
|
+
return dataframe
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _add_const_columns(
|
|
41
|
+
dataframe: pd.DataFrame,
|
|
42
|
+
new_cols: dict[str, str],
|
|
43
|
+
index_key: str | None = None,
|
|
44
|
+
) -> pd.DataFrame:
|
|
45
|
+
for col, value in new_cols.items():
|
|
46
|
+
dataframe[col] = value
|
|
47
|
+
|
|
48
|
+
if index_key is not None:
|
|
49
|
+
dataframe = _reindex_dataframe(
|
|
50
|
+
dataframe=dataframe,
|
|
51
|
+
index_cols=list(new_cols.keys()),
|
|
52
|
+
index_key=index_key,
|
|
53
|
+
)
|
|
54
|
+
return dataframe
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _add_const_columns_pl(
|
|
58
|
+
dataframe: pl.LazyFrame,
|
|
59
|
+
new_cols: dict[str, str],
|
|
60
|
+
index_key: str | None = None,
|
|
61
|
+
) -> pl.LazyFrame:
|
|
62
|
+
dataframe = dataframe.with_columns(
|
|
63
|
+
[pl.lit(value, dtype=pl.String()).alias(col) for col, value in new_cols.items()]
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
if index_key is not None:
|
|
67
|
+
dataframe = dataframe.with_columns(
|
|
68
|
+
[
|
|
69
|
+
pl.concat_str(
|
|
70
|
+
[pl.col(col) for col in new_cols.keys()],
|
|
71
|
+
separator="_",
|
|
72
|
+
).alias(index_key)
|
|
73
|
+
]
|
|
74
|
+
)
|
|
75
|
+
return dataframe
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def _pd_concat(
|
|
79
|
+
tables: Collection[TableWithExtras], index_key: str | None = None
|
|
80
|
+
) -> pd.DataFrame:
|
|
81
|
+
"""Concatenate tables from different plates into a single table."""
|
|
82
|
+
if len(tables) == 0:
|
|
83
|
+
raise ValueError("No tables to concatenate.")
|
|
84
|
+
|
|
85
|
+
dataframes = []
|
|
86
|
+
for table in tables:
|
|
87
|
+
dataframe = _add_const_columns(
|
|
88
|
+
dataframe=table.table.dataframe, new_cols=table.extras, index_key=index_key
|
|
89
|
+
)
|
|
90
|
+
dataframes.append(dataframe)
|
|
91
|
+
concatenated_table = pd.concat(dataframes, axis=0)
|
|
92
|
+
return concatenated_table
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _pl_concat(
|
|
96
|
+
tables: Collection[TableWithExtras], index_key: str | None = None
|
|
97
|
+
) -> pl.LazyFrame:
|
|
98
|
+
"""Concatenate tables from different plates into a single table."""
|
|
99
|
+
if len(tables) == 0:
|
|
100
|
+
raise ValueError("No tables to concatenate.")
|
|
101
|
+
|
|
102
|
+
dataframes = []
|
|
103
|
+
for table in tables:
|
|
104
|
+
polars_ls = _add_const_columns_pl(
|
|
105
|
+
dataframe=table.table.lazy_frame,
|
|
106
|
+
new_cols=table.extras,
|
|
107
|
+
index_key=index_key,
|
|
108
|
+
)
|
|
109
|
+
dataframes.append(polars_ls)
|
|
110
|
+
|
|
111
|
+
concatenated_table = pl.concat(dataframes, how="vertical")
|
|
112
|
+
return concatenated_table
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def conctatenate_tables(
|
|
116
|
+
tables: Collection[TableWithExtras],
|
|
117
|
+
mode: Literal["eager", "lazy"] = "eager",
|
|
118
|
+
index_key: str | None = None,
|
|
119
|
+
table_cls: type[TableType] | None = None,
|
|
120
|
+
) -> Table:
|
|
121
|
+
"""Concatenate tables from different plates into a single table."""
|
|
122
|
+
if len(tables) == 0:
|
|
123
|
+
raise ValueError("No tables to concatenate.")
|
|
124
|
+
|
|
125
|
+
table0 = next(iter(tables)).table
|
|
126
|
+
|
|
127
|
+
if mode == "lazy":
|
|
128
|
+
concatenated_table = _pl_concat(tables=tables, index_key=index_key)
|
|
129
|
+
elif mode == "eager":
|
|
130
|
+
concatenated_table = _pd_concat(tables=tables, index_key=index_key)
|
|
131
|
+
else:
|
|
132
|
+
raise ValueError(f"Unknown mode: {mode}. Use 'eager' or 'lazy'.")
|
|
133
|
+
|
|
134
|
+
meta = table0.meta
|
|
135
|
+
meta.index_key = index_key
|
|
136
|
+
meta.index_type = "str"
|
|
137
|
+
|
|
138
|
+
if table_cls is not None:
|
|
139
|
+
return table_cls.from_table_data(
|
|
140
|
+
table_data=concatenated_table,
|
|
141
|
+
meta=meta,
|
|
142
|
+
)
|
|
143
|
+
return table0.from_table_data(
|
|
144
|
+
table_data=concatenated_table,
|
|
145
|
+
meta=meta,
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def _check_images_and_extras(
|
|
150
|
+
images: Collection[OmeZarrContainer],
|
|
151
|
+
extras: Collection[dict[str, str]],
|
|
152
|
+
) -> None:
|
|
153
|
+
"""Check if the images and extras are valid."""
|
|
154
|
+
if len(images) == 0:
|
|
155
|
+
raise ValueError("No images to concatenate.")
|
|
156
|
+
|
|
157
|
+
if len(images) != len(extras):
|
|
158
|
+
raise ValueError("The number of images and extras must be the same.")
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def _concatenate_image_tables(
|
|
162
|
+
images: Collection[OmeZarrContainer],
|
|
163
|
+
extras: Collection[dict[str, str]],
|
|
164
|
+
table_name: str,
|
|
165
|
+
table_cls: type[TableType] | None = None,
|
|
166
|
+
index_key: str | None = None,
|
|
167
|
+
strict: bool = True,
|
|
168
|
+
mode: Literal["eager", "lazy"] = "eager",
|
|
169
|
+
) -> Table:
|
|
170
|
+
"""Concatenate tables from different images into a single table."""
|
|
171
|
+
_check_images_and_extras(images=images, extras=extras)
|
|
172
|
+
|
|
173
|
+
tables = []
|
|
174
|
+
for image, extra in zip(images, extras, strict=True):
|
|
175
|
+
if not strict and table_name not in image.list_tables():
|
|
176
|
+
continue
|
|
177
|
+
table = image.get_table(table_name)
|
|
178
|
+
tables.append(TableWithExtras(table=table, extras=extra))
|
|
179
|
+
|
|
180
|
+
return conctatenate_tables(
|
|
181
|
+
tables=tables,
|
|
182
|
+
mode=mode,
|
|
183
|
+
index_key=index_key,
|
|
184
|
+
table_cls=table_cls,
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def concatenate_image_tables(
|
|
189
|
+
images: Collection[OmeZarrContainer],
|
|
190
|
+
extras: Collection[dict[str, str]],
|
|
191
|
+
table_name: str,
|
|
192
|
+
index_key: str | None = None,
|
|
193
|
+
strict: bool = True,
|
|
194
|
+
mode: Literal["eager", "lazy"] = "eager",
|
|
195
|
+
) -> Table:
|
|
196
|
+
"""Concatenate tables from different images into a single table.
|
|
197
|
+
|
|
198
|
+
Args:
|
|
199
|
+
images: A collection of images.
|
|
200
|
+
extras: A collection of extras dictionaries for each image.
|
|
201
|
+
this will be added as columns to the table, and will be
|
|
202
|
+
concatenated with the table index to create a new index.
|
|
203
|
+
table_name: The name of the table to concatenate.
|
|
204
|
+
index_key: The key to use for the index of the concatenated table.
|
|
205
|
+
strict: If True, raise an error if the table is not found in the image.
|
|
206
|
+
mode: The mode to use for concatenation. Can be 'eager' or 'lazy'.
|
|
207
|
+
if 'eager', the table will be loaded into memory.
|
|
208
|
+
if 'lazy', the table will be loaded as a lazy frame.
|
|
209
|
+
"""
|
|
210
|
+
return _concatenate_image_tables(
|
|
211
|
+
images=images,
|
|
212
|
+
extras=extras,
|
|
213
|
+
table_name=table_name,
|
|
214
|
+
table_cls=None,
|
|
215
|
+
index_key=index_key,
|
|
216
|
+
strict=strict,
|
|
217
|
+
mode=mode,
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def concatenate_image_tables_as(
|
|
222
|
+
images: Collection[OmeZarrContainer],
|
|
223
|
+
extras: Collection[dict[str, str]],
|
|
224
|
+
table_name: str,
|
|
225
|
+
table_cls: type[TableType],
|
|
226
|
+
index_key: str | None = None,
|
|
227
|
+
strict: bool = True,
|
|
228
|
+
mode: Literal["eager", "lazy"] = "eager",
|
|
229
|
+
) -> TableType:
|
|
230
|
+
"""Concatenate tables from different images into a single table.
|
|
231
|
+
|
|
232
|
+
Args:
|
|
233
|
+
images: A collection of images.
|
|
234
|
+
extras: A collection of extras dictionaries for each image.
|
|
235
|
+
this will be added as columns to the table, and will be
|
|
236
|
+
concatenated with the table index to create a new index.
|
|
237
|
+
table_name: The name of the table to concatenate.
|
|
238
|
+
table_cls: The output will be casted to this class, if the new table_cls is
|
|
239
|
+
compatible with the table_cls of the input tables.
|
|
240
|
+
index_key: The key to use for the index of the concatenated table.
|
|
241
|
+
strict: If True, raise an error if the table is not found in the image.
|
|
242
|
+
mode: The mode to use for concatenation. Can be 'eager' or 'lazy'.
|
|
243
|
+
if 'eager', the table will be loaded into memory.
|
|
244
|
+
if 'lazy', the table will be loaded as a lazy frame.
|
|
245
|
+
"""
|
|
246
|
+
table = _concatenate_image_tables(
|
|
247
|
+
images=images,
|
|
248
|
+
extras=extras,
|
|
249
|
+
table_name=table_name,
|
|
250
|
+
table_cls=table_cls,
|
|
251
|
+
index_key=index_key,
|
|
252
|
+
strict=strict,
|
|
253
|
+
mode=mode,
|
|
254
|
+
)
|
|
255
|
+
if not isinstance(table, table_cls):
|
|
256
|
+
raise ValueError(f"Table is not of type {table_cls}. Got {type(table)}")
|
|
257
|
+
return table
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
async def _concatenate_image_tables_async(
|
|
261
|
+
images: Collection[OmeZarrContainer],
|
|
262
|
+
extras: Collection[dict[str, str]],
|
|
263
|
+
table_name: str,
|
|
264
|
+
table_cls: type[TableType] | None = None,
|
|
265
|
+
index_key: str | None = None,
|
|
266
|
+
strict: bool = True,
|
|
267
|
+
mode: Literal["eager", "lazy"] = "eager",
|
|
268
|
+
) -> Table:
|
|
269
|
+
"""Concatenate tables from different images into a single table."""
|
|
270
|
+
_check_images_and_extras(images=images, extras=extras)
|
|
271
|
+
|
|
272
|
+
def process_image(
|
|
273
|
+
image: OmeZarrContainer,
|
|
274
|
+
table_name: str,
|
|
275
|
+
extra: dict[str, str],
|
|
276
|
+
mode: Literal["eager", "lazy"] = "eager",
|
|
277
|
+
strict: bool = True,
|
|
278
|
+
) -> TableWithExtras | None:
|
|
279
|
+
"""Process a single image and return the table."""
|
|
280
|
+
if not strict and table_name not in image.list_tables():
|
|
281
|
+
return None
|
|
282
|
+
_table = image.get_table(table_name)
|
|
283
|
+
if mode == "lazy":
|
|
284
|
+
# make sure the table is loaded lazily
|
|
285
|
+
# It the backend is not lazy, this will be
|
|
286
|
+
# loaded eagerly
|
|
287
|
+
_ = _table.lazy_frame
|
|
288
|
+
elif mode == "eager":
|
|
289
|
+
# make sure the table is loaded eagerly
|
|
290
|
+
_ = _table.dataframe
|
|
291
|
+
table = TableWithExtras(
|
|
292
|
+
table=_table,
|
|
293
|
+
extras=extra,
|
|
294
|
+
)
|
|
295
|
+
return table
|
|
296
|
+
|
|
297
|
+
tasks = []
|
|
298
|
+
for image, extra in zip(images, extras, strict=True):
|
|
299
|
+
task = asyncio.to_thread(
|
|
300
|
+
process_image,
|
|
301
|
+
image=image,
|
|
302
|
+
table_name=table_name,
|
|
303
|
+
extra=extra,
|
|
304
|
+
strict=strict,
|
|
305
|
+
)
|
|
306
|
+
tasks.append(task)
|
|
307
|
+
tables = await asyncio.gather(*tasks)
|
|
308
|
+
tables = [table for table in tables if table is not None]
|
|
309
|
+
return conctatenate_tables(
|
|
310
|
+
tables=tables,
|
|
311
|
+
mode=mode,
|
|
312
|
+
index_key=index_key,
|
|
313
|
+
table_cls=table_cls,
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
async def concatenate_image_tables_async(
|
|
318
|
+
images: Collection[OmeZarrContainer],
|
|
319
|
+
extras: Collection[dict[str, str]],
|
|
320
|
+
table_name: str,
|
|
321
|
+
index_key: str | None = None,
|
|
322
|
+
strict: bool = True,
|
|
323
|
+
mode: Literal["eager", "lazy"] = "eager",
|
|
324
|
+
) -> Table:
|
|
325
|
+
"""Concatenate tables from different images into a single table.
|
|
326
|
+
|
|
327
|
+
Args:
|
|
328
|
+
images: A collection of images.
|
|
329
|
+
extras: A collection of extras dictionaries for each image.
|
|
330
|
+
this will be added as columns to the table, and will be
|
|
331
|
+
concatenated with the table index to create a new index.
|
|
332
|
+
table_name: The name of the table to concatenate.
|
|
333
|
+
index_key: The key to use for the index of the concatenated table.
|
|
334
|
+
strict: If True, raise an error if the table is not found in the image.
|
|
335
|
+
mode: The mode to use for concatenation. Can be 'eager' or 'lazy'.
|
|
336
|
+
if 'eager', the table will be loaded into memory.
|
|
337
|
+
if 'lazy', the table will be loaded as a lazy frame.
|
|
338
|
+
"""
|
|
339
|
+
return await _concatenate_image_tables_async(
|
|
340
|
+
images=images,
|
|
341
|
+
extras=extras,
|
|
342
|
+
table_name=table_name,
|
|
343
|
+
table_cls=None,
|
|
344
|
+
index_key=index_key,
|
|
345
|
+
strict=strict,
|
|
346
|
+
mode=mode,
|
|
347
|
+
)
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
async def concatenate_image_tables_as_async(
|
|
351
|
+
images: Collection[OmeZarrContainer],
|
|
352
|
+
extras: Collection[dict[str, str]],
|
|
353
|
+
table_name: str,
|
|
354
|
+
table_cls: type[TableType],
|
|
355
|
+
index_key: str | None = None,
|
|
356
|
+
strict: bool = True,
|
|
357
|
+
mode: Literal["eager", "lazy"] = "eager",
|
|
358
|
+
) -> TableType:
|
|
359
|
+
"""Concatenate tables from different images into a single table.
|
|
360
|
+
|
|
361
|
+
Args:
|
|
362
|
+
images: A collection of images.
|
|
363
|
+
extras: A collection of extras dictionaries for each image.
|
|
364
|
+
this will be added as columns to the table, and will be
|
|
365
|
+
concatenated with the table index to create a new index.
|
|
366
|
+
table_name: The name of the table to concatenate.
|
|
367
|
+
table_cls: The output will be casted to this class, if the new table_cls is
|
|
368
|
+
compatible with the table_cls of the input tables.
|
|
369
|
+
index_key: The key to use for the index of the concatenated table.
|
|
370
|
+
strict: If True, raise an error if the table is not found in the image.
|
|
371
|
+
mode: The mode to use for concatenation. Can be 'eager' or 'lazy'.
|
|
372
|
+
if 'eager', the table will be loaded into memory.
|
|
373
|
+
if 'lazy', the table will be loaded as a lazy frame.
|
|
374
|
+
"""
|
|
375
|
+
table = await _concatenate_image_tables_async(
|
|
376
|
+
images=images,
|
|
377
|
+
extras=extras,
|
|
378
|
+
table_name=table_name,
|
|
379
|
+
table_cls=table_cls,
|
|
380
|
+
index_key=index_key,
|
|
381
|
+
strict=strict,
|
|
382
|
+
mode=mode,
|
|
383
|
+
)
|
|
384
|
+
if not isinstance(table, table_cls):
|
|
385
|
+
raise ValueError(f"Table is not of type {table_cls}. Got {type(table)}")
|
|
386
|
+
return table
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
def _tables_names_coalesce(
|
|
390
|
+
tables_names: list[list[str]],
|
|
391
|
+
mode: Literal["common", "all"] = "common",
|
|
392
|
+
) -> list[str]:
|
|
393
|
+
num_images = len(tables_names)
|
|
394
|
+
if num_images == 0:
|
|
395
|
+
raise ValueError("No images to concatenate.")
|
|
396
|
+
|
|
397
|
+
names = [name for _table_names in tables_names for name in _table_names]
|
|
398
|
+
names_counts = Counter(names)
|
|
399
|
+
|
|
400
|
+
if mode == "common":
|
|
401
|
+
# Get the names that are present in all images
|
|
402
|
+
common_names = [
|
|
403
|
+
name for name, count in names_counts.items() if count == num_images
|
|
404
|
+
]
|
|
405
|
+
return common_names
|
|
406
|
+
elif mode == "all":
|
|
407
|
+
# Get all names
|
|
408
|
+
return list(names_counts.keys())
|
|
409
|
+
else:
|
|
410
|
+
raise ValueError(f"Unknown mode: {mode}. Use 'common' or 'all'.")
|
|
411
|
+
|
|
412
|
+
|
|
413
|
+
def list_image_tables(
|
|
414
|
+
images: Collection[OmeZarrContainer],
|
|
415
|
+
filter_types: str | None = None,
|
|
416
|
+
mode: Literal["common", "all"] = "common",
|
|
417
|
+
) -> list[str]:
|
|
418
|
+
"""List all table names in the images.
|
|
419
|
+
|
|
420
|
+
Args:
|
|
421
|
+
images: A collection of images.
|
|
422
|
+
filter_types (str | None): The type of tables to filter. If None,
|
|
423
|
+
return all tables. Defaults to None.
|
|
424
|
+
mode (Literal["common", "all"]): Whether to return only common tables
|
|
425
|
+
between all images or all tables. Defaults to "common".
|
|
426
|
+
"""
|
|
427
|
+
tables_names = []
|
|
428
|
+
for image in images:
|
|
429
|
+
tables = image.list_tables(filter_types=filter_types)
|
|
430
|
+
tables_names.append(tables)
|
|
431
|
+
|
|
432
|
+
return _tables_names_coalesce(
|
|
433
|
+
tables_names=tables_names,
|
|
434
|
+
mode=mode,
|
|
435
|
+
)
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
async def list_image_tables_async(
|
|
439
|
+
images: Collection[OmeZarrContainer],
|
|
440
|
+
filter_types: str | None = None,
|
|
441
|
+
mode: Literal["common", "all"] = "common",
|
|
442
|
+
) -> list[str]:
|
|
443
|
+
"""List all image tables in the image asynchronously.
|
|
444
|
+
|
|
445
|
+
Args:
|
|
446
|
+
images: A collection of images.
|
|
447
|
+
filter_types (str | None): The type of tables to filter. If None,
|
|
448
|
+
return all tables. Defaults to None.
|
|
449
|
+
mode (Literal["common", "all"]): Whether to return only common tables
|
|
450
|
+
between all images or all tables. Defaults to "common".
|
|
451
|
+
"""
|
|
452
|
+
images_ids = []
|
|
453
|
+
|
|
454
|
+
# key table name, value list of paths
|
|
455
|
+
def process_image(
|
|
456
|
+
image: OmeZarrContainer, filter_types: str | None = None
|
|
457
|
+
) -> list[str]:
|
|
458
|
+
tables = image.list_tables(filter_types=filter_types)
|
|
459
|
+
return tables
|
|
460
|
+
|
|
461
|
+
tasks = []
|
|
462
|
+
for i, image in enumerate(images):
|
|
463
|
+
images_ids.append(i)
|
|
464
|
+
task = asyncio.to_thread(process_image, image, filter_types=filter_types)
|
|
465
|
+
tasks.append(task)
|
|
466
|
+
|
|
467
|
+
tables_names = await asyncio.gather(*tasks)
|
|
468
|
+
return _tables_names_coalesce(
|
|
469
|
+
tables_names=tables_names,
|
|
470
|
+
mode=mode,
|
|
471
|
+
)
|