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/tables/tables_container.py
DELETED
|
@@ -1,300 +0,0 @@
|
|
|
1
|
-
"""Module for handling the /tables group in an OME-NGFF file."""
|
|
2
|
-
|
|
3
|
-
from typing import Literal, Protocol
|
|
4
|
-
|
|
5
|
-
from ngio.tables.v1 import FeatureTableV1, MaskingROITableV1, RoiTableV1
|
|
6
|
-
from ngio.tables.v1._generic_table import GenericTable
|
|
7
|
-
from ngio.utils import (
|
|
8
|
-
AccessModeLiteral,
|
|
9
|
-
NgioValidationError,
|
|
10
|
-
NgioValueError,
|
|
11
|
-
StoreOrGroup,
|
|
12
|
-
ZarrGroupHandler,
|
|
13
|
-
)
|
|
14
|
-
|
|
15
|
-
RoiTable = RoiTableV1
|
|
16
|
-
MaskingROITable = MaskingROITableV1
|
|
17
|
-
FeatureTable = FeatureTableV1
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
class Table(Protocol):
|
|
21
|
-
"""Placeholder class for a table."""
|
|
22
|
-
|
|
23
|
-
@staticmethod
|
|
24
|
-
def type() -> str | None:
|
|
25
|
-
"""Return the type of the table."""
|
|
26
|
-
...
|
|
27
|
-
|
|
28
|
-
@staticmethod
|
|
29
|
-
def version() -> str | None:
|
|
30
|
-
"""Return the version of the table."""
|
|
31
|
-
...
|
|
32
|
-
|
|
33
|
-
@property
|
|
34
|
-
def backend_name(self) -> str | None:
|
|
35
|
-
"""The name of the backend."""
|
|
36
|
-
...
|
|
37
|
-
|
|
38
|
-
@classmethod
|
|
39
|
-
def _from_handler(
|
|
40
|
-
cls, handler: ZarrGroupHandler, backend_name: str | None = None
|
|
41
|
-
) -> "Table":
|
|
42
|
-
"""Create a new table from a Zarr group handler."""
|
|
43
|
-
...
|
|
44
|
-
|
|
45
|
-
def _set_backend(
|
|
46
|
-
self,
|
|
47
|
-
handler: ZarrGroupHandler,
|
|
48
|
-
backend_name: str | None = None,
|
|
49
|
-
) -> None:
|
|
50
|
-
"""Set the backend store and path for the table."""
|
|
51
|
-
...
|
|
52
|
-
|
|
53
|
-
def consolidate(self) -> None:
|
|
54
|
-
"""Consolidate the table on disk."""
|
|
55
|
-
...
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
TypedTable = Literal["roi_table", "masking_roi_table", "feature_table"]
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
def _unique_table_name(type_name, version) -> str:
|
|
62
|
-
"""Return the unique name for a table."""
|
|
63
|
-
return f"{type_name}_v{version}"
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
class ImplementedTables:
|
|
67
|
-
"""A singleton class to manage the available table handler plugins."""
|
|
68
|
-
|
|
69
|
-
_instance = None
|
|
70
|
-
_implemented_tables: dict[str, type[Table]]
|
|
71
|
-
|
|
72
|
-
def __new__(cls):
|
|
73
|
-
"""Create a new instance of the class if it does not exist."""
|
|
74
|
-
if cls._instance is None:
|
|
75
|
-
cls._instance = super().__new__(cls)
|
|
76
|
-
cls._instance._implemented_tables = {}
|
|
77
|
-
return cls._instance
|
|
78
|
-
|
|
79
|
-
def available_implementations(self) -> list[str]:
|
|
80
|
-
"""Get the available table handler versions."""
|
|
81
|
-
return list(self._implemented_tables.keys())
|
|
82
|
-
|
|
83
|
-
def get_table(
|
|
84
|
-
self,
|
|
85
|
-
type: str,
|
|
86
|
-
version: str,
|
|
87
|
-
handler: ZarrGroupHandler,
|
|
88
|
-
backend_name: str | None = None,
|
|
89
|
-
) -> Table:
|
|
90
|
-
"""Try to get a handler for the given store based on the metadata version."""
|
|
91
|
-
_errors = {}
|
|
92
|
-
for name, table_cls in self._implemented_tables.items():
|
|
93
|
-
if name != _unique_table_name(type, version):
|
|
94
|
-
continue
|
|
95
|
-
try:
|
|
96
|
-
table = table_cls._from_handler(
|
|
97
|
-
handler=handler, backend_name=backend_name
|
|
98
|
-
)
|
|
99
|
-
return table
|
|
100
|
-
except Exception as e:
|
|
101
|
-
_errors[name] = e
|
|
102
|
-
print(_errors)
|
|
103
|
-
# If no table was found, we can try to load the table from a generic table
|
|
104
|
-
try:
|
|
105
|
-
table = GenericTable._from_handler(
|
|
106
|
-
handler=handler, backend_name=backend_name
|
|
107
|
-
)
|
|
108
|
-
return table
|
|
109
|
-
except Exception as e:
|
|
110
|
-
_errors["generic"] = e
|
|
111
|
-
|
|
112
|
-
if len(_errors) == 0:
|
|
113
|
-
raise NgioValidationError(
|
|
114
|
-
f"Could not find a table implementation for {type} v{version}. "
|
|
115
|
-
f"Available tables: {self.available_implementations()}"
|
|
116
|
-
)
|
|
117
|
-
|
|
118
|
-
raise NgioValidationError(
|
|
119
|
-
f"Could not load table from any known version. Errors: {_errors}"
|
|
120
|
-
)
|
|
121
|
-
|
|
122
|
-
def add_implementation(self, handler: type[Table], overwrite: bool = False):
|
|
123
|
-
"""Register a new table handler."""
|
|
124
|
-
table_type = handler.type()
|
|
125
|
-
version = handler.version()
|
|
126
|
-
if table_type is None:
|
|
127
|
-
raise NgioValueError("Table handler must have a type.")
|
|
128
|
-
|
|
129
|
-
if version is None:
|
|
130
|
-
raise NgioValueError("Table handler must have a version.")
|
|
131
|
-
|
|
132
|
-
table_unique_name = _unique_table_name(table_type, version)
|
|
133
|
-
if table_unique_name in self._implemented_tables and not overwrite:
|
|
134
|
-
raise NgioValueError(
|
|
135
|
-
f"Table handler for {table_unique_name} already exists. "
|
|
136
|
-
"Use overwrite=True to replace it."
|
|
137
|
-
)
|
|
138
|
-
self._implemented_tables[table_unique_name] = handler
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
def _get_table_type(handler: ZarrGroupHandler) -> str:
|
|
142
|
-
"""Get the type of the table from the handler."""
|
|
143
|
-
attrs = handler.load_attrs()
|
|
144
|
-
return attrs.get("type", "None")
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
def _get_table_version(handler: ZarrGroupHandler) -> str:
|
|
148
|
-
"""Get the version of the table from the handler."""
|
|
149
|
-
attrs = handler.load_attrs()
|
|
150
|
-
return attrs.get("fractal_table_version", "None")
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
class TablesContainer:
|
|
154
|
-
"""A class to handle the /labels group in an OME-NGFF file."""
|
|
155
|
-
|
|
156
|
-
def __init__(self, group_handler: ZarrGroupHandler) -> None:
|
|
157
|
-
"""Initialize the LabelGroupHandler."""
|
|
158
|
-
self._group_handler = group_handler
|
|
159
|
-
|
|
160
|
-
# Validate the group
|
|
161
|
-
# Either contains a tables attribute or is empty
|
|
162
|
-
attrs = self._group_handler.load_attrs()
|
|
163
|
-
if len(attrs) == 0:
|
|
164
|
-
# It's an empty group
|
|
165
|
-
pass
|
|
166
|
-
elif "tables" in attrs and isinstance(attrs["tables"], list):
|
|
167
|
-
# It's a valid group
|
|
168
|
-
pass
|
|
169
|
-
else:
|
|
170
|
-
raise NgioValidationError(
|
|
171
|
-
f"Invalid /tables group. "
|
|
172
|
-
f"Expected a single tables attribute with a list of table names. "
|
|
173
|
-
f"Found: {attrs}"
|
|
174
|
-
)
|
|
175
|
-
|
|
176
|
-
def _get_tables_list(self) -> list[str]:
|
|
177
|
-
"""Create the /tables group if it doesn't exist."""
|
|
178
|
-
attrs = self._group_handler.load_attrs()
|
|
179
|
-
return attrs.get("tables", [])
|
|
180
|
-
|
|
181
|
-
def _get_table_group_handler(self, name: str) -> ZarrGroupHandler:
|
|
182
|
-
"""Get the group handler for a table."""
|
|
183
|
-
handler = self._group_handler.derive_handler(path=name)
|
|
184
|
-
return handler
|
|
185
|
-
|
|
186
|
-
def list(self, filter_types: str | None = None) -> list[str]:
|
|
187
|
-
"""List all labels in the group."""
|
|
188
|
-
tables = self._get_tables_list()
|
|
189
|
-
if filter_types is None:
|
|
190
|
-
return tables
|
|
191
|
-
|
|
192
|
-
filtered_tables = []
|
|
193
|
-
for table_name in tables:
|
|
194
|
-
tb_handler = self._get_table_group_handler(table_name)
|
|
195
|
-
table_type = _get_table_type(tb_handler)
|
|
196
|
-
if table_type == filter_types:
|
|
197
|
-
filtered_tables.append(table_name)
|
|
198
|
-
return filtered_tables
|
|
199
|
-
|
|
200
|
-
def get(self, name: str, backend_name: str | None = None) -> Table:
|
|
201
|
-
"""Get a label from the group."""
|
|
202
|
-
if name not in self.list():
|
|
203
|
-
raise KeyError(f"Table '{name}' not found in the group.")
|
|
204
|
-
|
|
205
|
-
table_handler = self._get_table_group_handler(name)
|
|
206
|
-
table_type = _get_table_type(table_handler)
|
|
207
|
-
table_version = _get_table_version(table_handler)
|
|
208
|
-
return ImplementedTables().get_table(
|
|
209
|
-
type=table_type,
|
|
210
|
-
version=table_version,
|
|
211
|
-
handler=table_handler,
|
|
212
|
-
backend_name=backend_name,
|
|
213
|
-
)
|
|
214
|
-
|
|
215
|
-
def add(
|
|
216
|
-
self,
|
|
217
|
-
name: str,
|
|
218
|
-
table: Table,
|
|
219
|
-
backend: str | None = None,
|
|
220
|
-
overwrite: bool = False,
|
|
221
|
-
) -> None:
|
|
222
|
-
"""Add a table to the group."""
|
|
223
|
-
existing_tables = self._get_tables_list()
|
|
224
|
-
if name in existing_tables and not overwrite:
|
|
225
|
-
raise NgioValueError(
|
|
226
|
-
f"Table '{name}' already exists in the group. "
|
|
227
|
-
"Use overwrite=True to replace it."
|
|
228
|
-
)
|
|
229
|
-
|
|
230
|
-
table_handler = self._group_handler.derive_handler(path=name)
|
|
231
|
-
|
|
232
|
-
if backend is None:
|
|
233
|
-
backend = table.backend_name
|
|
234
|
-
|
|
235
|
-
table._set_backend(
|
|
236
|
-
handler=table_handler,
|
|
237
|
-
backend_name=backend,
|
|
238
|
-
)
|
|
239
|
-
table.consolidate()
|
|
240
|
-
if name not in existing_tables:
|
|
241
|
-
existing_tables.append(name)
|
|
242
|
-
self._group_handler.write_attrs({"tables": existing_tables})
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
ImplementedTables().add_implementation(RoiTableV1)
|
|
246
|
-
ImplementedTables().add_implementation(MaskingROITableV1)
|
|
247
|
-
ImplementedTables().add_implementation(FeatureTableV1)
|
|
248
|
-
|
|
249
|
-
###################################################################################
|
|
250
|
-
#
|
|
251
|
-
# Utility functions to open and write tables
|
|
252
|
-
#
|
|
253
|
-
###################################################################################
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
def open_tables_container(
|
|
257
|
-
store: StoreOrGroup,
|
|
258
|
-
cache: bool = False,
|
|
259
|
-
mode: AccessModeLiteral = "a",
|
|
260
|
-
parallel_safe: bool = False,
|
|
261
|
-
) -> TablesContainer:
|
|
262
|
-
"""Open a table handler from a Zarr store."""
|
|
263
|
-
handler = ZarrGroupHandler(
|
|
264
|
-
store=store, cache=cache, mode=mode, parallel_safe=parallel_safe
|
|
265
|
-
)
|
|
266
|
-
return TablesContainer(handler)
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
def open_table(
|
|
270
|
-
store: StoreOrGroup,
|
|
271
|
-
cache: bool = False,
|
|
272
|
-
mode: AccessModeLiteral = "a",
|
|
273
|
-
parallel_safe: bool = False,
|
|
274
|
-
) -> Table:
|
|
275
|
-
"""Open a table from a Zarr store."""
|
|
276
|
-
handler = ZarrGroupHandler(
|
|
277
|
-
store=store, cache=cache, mode=mode, parallel_safe=parallel_safe
|
|
278
|
-
)
|
|
279
|
-
return ImplementedTables().get_table(
|
|
280
|
-
_get_table_type(handler), _get_table_version(handler), handler
|
|
281
|
-
)
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
def write_table(
|
|
285
|
-
store: StoreOrGroup,
|
|
286
|
-
table: Table,
|
|
287
|
-
backend: str | None = None,
|
|
288
|
-
cache: bool = False,
|
|
289
|
-
mode: AccessModeLiteral = "a",
|
|
290
|
-
parallel_safe: bool = False,
|
|
291
|
-
) -> None:
|
|
292
|
-
"""Write a table to a Zarr store."""
|
|
293
|
-
handler = ZarrGroupHandler(
|
|
294
|
-
store=store, cache=cache, mode=mode, parallel_safe=parallel_safe
|
|
295
|
-
)
|
|
296
|
-
table._set_backend(
|
|
297
|
-
handler=handler,
|
|
298
|
-
backend_name=backend,
|
|
299
|
-
)
|
|
300
|
-
table.consolidate()
|
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
"""Implementation of the Masking ROI table class.
|
|
2
|
-
|
|
3
|
-
This class follows the roi_table specification at:
|
|
4
|
-
https://fractal-analytics-platform.github.io/fractal-tasks-core/tables/
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
from collections.abc import Iterable
|
|
8
|
-
from typing import Literal
|
|
9
|
-
|
|
10
|
-
from pydantic import BaseModel
|
|
11
|
-
|
|
12
|
-
from ngio.common import WorldCooROI
|
|
13
|
-
from ngio.tables._validators import validate_columns
|
|
14
|
-
from ngio.tables.backends import ImplementedTableBackends
|
|
15
|
-
from ngio.tables.v1._roi_table import (
|
|
16
|
-
OPTIONAL_COLUMNS,
|
|
17
|
-
REQUIRED_COLUMNS,
|
|
18
|
-
_dataframe_to_rois,
|
|
19
|
-
_rois_to_dataframe,
|
|
20
|
-
)
|
|
21
|
-
from ngio.utils import NgioValueError, ZarrGroupHandler
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
class RegionMeta(BaseModel):
|
|
25
|
-
"""Metadata for the region."""
|
|
26
|
-
|
|
27
|
-
path: str
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
class MaskingROITableV1Meta(BaseModel):
|
|
31
|
-
"""Metadata for the ROI table."""
|
|
32
|
-
|
|
33
|
-
fractal_table_version: Literal["1"] = "1"
|
|
34
|
-
type: Literal["masking_roi_table"] = "masking_roi_table"
|
|
35
|
-
backend: str | None = None
|
|
36
|
-
region: RegionMeta | None = None
|
|
37
|
-
instance_key: str = "label"
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
class MaskingROITableV1:
|
|
41
|
-
"""Class to handle fractal ROI tables.
|
|
42
|
-
|
|
43
|
-
To know more about the ROI table format, please refer to the
|
|
44
|
-
specification at:
|
|
45
|
-
https://fractal-analytics-platform.github.io/fractal-tasks-core/tables/
|
|
46
|
-
"""
|
|
47
|
-
|
|
48
|
-
def __init__(
|
|
49
|
-
self,
|
|
50
|
-
rois: Iterable[WorldCooROI] | None = None,
|
|
51
|
-
reference_label: str | None = None,
|
|
52
|
-
) -> None:
|
|
53
|
-
"""Create a new ROI table."""
|
|
54
|
-
if reference_label is None:
|
|
55
|
-
self._meta = MaskingROITableV1Meta()
|
|
56
|
-
else:
|
|
57
|
-
path = f"../labels/{reference_label}"
|
|
58
|
-
self._meta = MaskingROITableV1Meta(region=RegionMeta(path=path))
|
|
59
|
-
self._table_backend = None
|
|
60
|
-
|
|
61
|
-
self._rois = {}
|
|
62
|
-
if rois is not None:
|
|
63
|
-
self.add(rois)
|
|
64
|
-
|
|
65
|
-
@staticmethod
|
|
66
|
-
def type() -> Literal["masking_roi_table"]:
|
|
67
|
-
"""Return the type of the table."""
|
|
68
|
-
return "masking_roi_table"
|
|
69
|
-
|
|
70
|
-
@staticmethod
|
|
71
|
-
def version() -> Literal["1"]:
|
|
72
|
-
"""Return the version of the fractal table."""
|
|
73
|
-
return "1"
|
|
74
|
-
|
|
75
|
-
@property
|
|
76
|
-
def backend_name(self) -> str | None:
|
|
77
|
-
"""Return the name of the backend."""
|
|
78
|
-
if self._table_backend is None:
|
|
79
|
-
return None
|
|
80
|
-
return self._table_backend.backend_name()
|
|
81
|
-
|
|
82
|
-
@classmethod
|
|
83
|
-
def _from_handler(
|
|
84
|
-
cls, handler: ZarrGroupHandler, backend_name: str | None = None
|
|
85
|
-
) -> "MaskingROITableV1":
|
|
86
|
-
"""Create a new ROI table from a Zarr store."""
|
|
87
|
-
meta = MaskingROITableV1Meta(**handler.load_attrs())
|
|
88
|
-
|
|
89
|
-
if backend_name is None:
|
|
90
|
-
backend = ImplementedTableBackends().get_backend(
|
|
91
|
-
backend_name=meta.backend,
|
|
92
|
-
group_handler=handler,
|
|
93
|
-
index_key="label",
|
|
94
|
-
index_type="int",
|
|
95
|
-
)
|
|
96
|
-
else:
|
|
97
|
-
backend = ImplementedTableBackends().get_backend(
|
|
98
|
-
backend_name=backend_name,
|
|
99
|
-
group_handler=handler,
|
|
100
|
-
index_key="label",
|
|
101
|
-
index_type="int",
|
|
102
|
-
)
|
|
103
|
-
meta.backend = backend_name
|
|
104
|
-
|
|
105
|
-
if not backend.implements_dataframe:
|
|
106
|
-
raise NgioValueError(
|
|
107
|
-
"The backend does not implement the dataframe protocol."
|
|
108
|
-
)
|
|
109
|
-
|
|
110
|
-
table = cls()
|
|
111
|
-
table._meta = meta
|
|
112
|
-
table._table_backend = backend
|
|
113
|
-
|
|
114
|
-
dataframe = backend.load_as_dataframe()
|
|
115
|
-
dataframe = validate_columns(
|
|
116
|
-
dataframe,
|
|
117
|
-
required_columns=REQUIRED_COLUMNS,
|
|
118
|
-
optional_columns=OPTIONAL_COLUMNS,
|
|
119
|
-
)
|
|
120
|
-
table._rois = _dataframe_to_rois(dataframe)
|
|
121
|
-
return table
|
|
122
|
-
|
|
123
|
-
def _set_backend(
|
|
124
|
-
self,
|
|
125
|
-
handler: ZarrGroupHandler,
|
|
126
|
-
backend_name: str | None = None,
|
|
127
|
-
) -> None:
|
|
128
|
-
"""Set the backend of the table."""
|
|
129
|
-
backend = ImplementedTableBackends().get_backend(
|
|
130
|
-
backend_name=backend_name,
|
|
131
|
-
group_handler=handler,
|
|
132
|
-
index_key="label",
|
|
133
|
-
index_type="int",
|
|
134
|
-
)
|
|
135
|
-
self._meta.backend = backend_name
|
|
136
|
-
self._table_backend = backend
|
|
137
|
-
|
|
138
|
-
def rois(self) -> list[WorldCooROI]:
|
|
139
|
-
"""List all ROIs in the table."""
|
|
140
|
-
return list(self._rois.values())
|
|
141
|
-
|
|
142
|
-
def get(self, label: int) -> WorldCooROI:
|
|
143
|
-
"""Get an ROI from the table."""
|
|
144
|
-
_label = str(label)
|
|
145
|
-
if _label not in self._rois:
|
|
146
|
-
raise KeyError(f"ROI {_label} not found in the table.")
|
|
147
|
-
return self._rois[_label]
|
|
148
|
-
|
|
149
|
-
def add(self, roi: WorldCooROI | Iterable[WorldCooROI]) -> None:
|
|
150
|
-
"""Append ROIs to the current table."""
|
|
151
|
-
if isinstance(roi, WorldCooROI):
|
|
152
|
-
roi = [roi]
|
|
153
|
-
|
|
154
|
-
for _roi in roi:
|
|
155
|
-
if _roi.name in self._rois:
|
|
156
|
-
raise NgioValueError(f"ROI {_roi.name} already exists in the table.")
|
|
157
|
-
self._rois[_roi.name] = _roi
|
|
158
|
-
|
|
159
|
-
def consolidate(self) -> None:
|
|
160
|
-
"""Write the current state of the table to the Zarr file."""
|
|
161
|
-
if self._table_backend is None:
|
|
162
|
-
raise NgioValueError(
|
|
163
|
-
"No backend set for the table. "
|
|
164
|
-
"Please add the table to a OME-Zarr Image before calling consolidate."
|
|
165
|
-
)
|
|
166
|
-
|
|
167
|
-
dataframe = _rois_to_dataframe(self._rois, index_key="label")
|
|
168
|
-
dataframe = validate_columns(
|
|
169
|
-
dataframe,
|
|
170
|
-
required_columns=REQUIRED_COLUMNS,
|
|
171
|
-
optional_columns=OPTIONAL_COLUMNS,
|
|
172
|
-
)
|
|
173
|
-
self._table_backend.write_from_dataframe(
|
|
174
|
-
dataframe, metadata=self._meta.model_dump(exclude_none=True)
|
|
175
|
-
)
|
ngio/utils/_logger.py
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
|
|
3
|
-
# Configure the logger
|
|
4
|
-
ngio_logger = logging.getLogger("NgioLogger")
|
|
5
|
-
ngio_logger.setLevel(logging.ERROR)
|
|
6
|
-
|
|
7
|
-
# Set up a console handler with a custom format
|
|
8
|
-
console_handler = logging.StreamHandler()
|
|
9
|
-
formatter = logging.Formatter(
|
|
10
|
-
"%(asctime)s - %(levelname)s - %(name)s - "
|
|
11
|
-
"[%(module)s.%(funcName)s:%(lineno)d]: %(message)s"
|
|
12
|
-
)
|
|
13
|
-
console_handler.setFormatter(formatter)
|
|
14
|
-
|
|
15
|
-
# Add the handler to the logger
|
|
16
|
-
ngio_logger.addHandler(console_handler)
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def set_logger_level(level: str) -> None:
|
|
20
|
-
"""Set the logger level.
|
|
21
|
-
|
|
22
|
-
Args:
|
|
23
|
-
level: The level to set the logger to.
|
|
24
|
-
Must be one of "DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL".
|
|
25
|
-
"""
|
|
26
|
-
if level not in ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]:
|
|
27
|
-
raise ValueError(f"Invalid log level: {level}")
|
|
28
|
-
|
|
29
|
-
ngio_logger.setLevel(level)
|
ngio-0.2.0a2.dist-info/METADATA
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: ngio
|
|
3
|
-
Version: 0.2.0a2
|
|
4
|
-
Summary: Next Generation file format IO
|
|
5
|
-
Project-URL: homepage, https://github.com/lorenzocerrone/ngio
|
|
6
|
-
Project-URL: repository, https://github.com/lorenzocerrone/ngio
|
|
7
|
-
Author-email: Lorenzo Cerrone <lorenzo.cerrone@uzh.ch>
|
|
8
|
-
License: BSD-3-Clause
|
|
9
|
-
License-File: LICENSE
|
|
10
|
-
Classifier: Development Status :: 3 - Alpha
|
|
11
|
-
Classifier: License :: OSI Approved :: BSD License
|
|
12
|
-
Classifier: Programming Language :: Python :: 3
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
-
Classifier: Typing :: Typed
|
|
17
|
-
Requires-Python: <3.14,>=3.11
|
|
18
|
-
Requires-Dist: aiohttp
|
|
19
|
-
Requires-Dist: anndata>=0.8.0
|
|
20
|
-
Requires-Dist: dask[array]
|
|
21
|
-
Requires-Dist: dask[distributed]
|
|
22
|
-
Requires-Dist: filelock
|
|
23
|
-
Requires-Dist: numpy
|
|
24
|
-
Requires-Dist: ome-zarr-models
|
|
25
|
-
Requires-Dist: pandas>=1.2.0
|
|
26
|
-
Requires-Dist: pooch
|
|
27
|
-
Requires-Dist: pydantic
|
|
28
|
-
Requires-Dist: requests
|
|
29
|
-
Requires-Dist: xarray
|
|
30
|
-
Requires-Dist: zarr<3
|
|
31
|
-
Provides-Extra: dev
|
|
32
|
-
Requires-Dist: matplotlib; extra == 'dev'
|
|
33
|
-
Requires-Dist: mypy; extra == 'dev'
|
|
34
|
-
Requires-Dist: napari; extra == 'dev'
|
|
35
|
-
Requires-Dist: notebook; extra == 'dev'
|
|
36
|
-
Requires-Dist: pdbpp; extra == 'dev'
|
|
37
|
-
Requires-Dist: pre-commit; extra == 'dev'
|
|
38
|
-
Requires-Dist: pyqt5; extra == 'dev'
|
|
39
|
-
Requires-Dist: rich; extra == 'dev'
|
|
40
|
-
Requires-Dist: ruff; extra == 'dev'
|
|
41
|
-
Provides-Extra: docs
|
|
42
|
-
Requires-Dist: mkdocs; extra == 'docs'
|
|
43
|
-
Requires-Dist: mkdocs-autorefs; extra == 'docs'
|
|
44
|
-
Requires-Dist: mkdocs-git-committers-plugin-2; extra == 'docs'
|
|
45
|
-
Requires-Dist: mkdocs-git-revision-date-localized-plugin; extra == 'docs'
|
|
46
|
-
Requires-Dist: mkdocs-jupyter; extra == 'docs'
|
|
47
|
-
Requires-Dist: mkdocs-material; extra == 'docs'
|
|
48
|
-
Requires-Dist: mkdocstrings[python]; extra == 'docs'
|
|
49
|
-
Requires-Dist: scikit-image; extra == 'docs'
|
|
50
|
-
Provides-Extra: test
|
|
51
|
-
Requires-Dist: pytest; extra == 'test'
|
|
52
|
-
Requires-Dist: pytest-cov; extra == 'test'
|
|
53
|
-
Description-Content-Type: text/markdown
|
|
54
|
-
|
|
55
|
-
# NGIO - Next Generation file format IO
|
|
56
|
-
|
|
57
|
-
[](https://github.com/lorenzocerrone/ngio/raw/main/LICENSE)
|
|
58
|
-
[](https://pypi.org/project/ngio)
|
|
59
|
-
[](https://python.org)
|
|
60
|
-
[](https://github.com/lorenzocerrone/ngio/actions/workflows/ci.yml)
|
|
61
|
-
[](https://codecov.io/gh/fractal-analytics-platform/ngio)
|
|
62
|
-
|
|
63
|
-
NGIO is a Python library to streamline OME-Zarr image analysis workflows.
|
|
64
|
-
|
|
65
|
-
**Main Goals:**
|
|
66
|
-
|
|
67
|
-
- Abstract object base API for handling OME-Zarr files
|
|
68
|
-
- Powefull iterators for processing data using common access patterns
|
|
69
|
-
- Tight integration with [Fractal's Table Fractal](https://fractal-analytics-platform.github.io/fractal-tasks-core/tables/)
|
|
70
|
-
- Validate OME-Zarr files
|
|
71
|
-
|
|
72
|
-
To get started, check out the [Getting Started](https://fractal-analytics-platform.github.io/ngio/getting-started/) guide. Or checkout our [Documentation](https://fractal-analytics-platform.github.io/ngio/)
|
|
73
|
-
|
|
74
|
-
## 🚧 Ngio is Under active Development 🚧
|
|
75
|
-
|
|
76
|
-
### Roadmap
|
|
77
|
-
|
|
78
|
-
| Feature | Status | ETA | Description |
|
|
79
|
-
|---------|--------|-----|-------------|
|
|
80
|
-
| Metadata Handling | ✅ | | Read, Write, Validate OME-Zarr Metadata (0.4 supported, 0.5 ready) |
|
|
81
|
-
| OME-Zarr Validation | ✅ | | Validate OME-Zarr files for compliance with the OME-Zarr Specification + Compliance between Metadata and Data |
|
|
82
|
-
| Base Image Handling | ✅ | | Load data from OME-Zarr files, retrieve basic metadata, and write data |
|
|
83
|
-
| ROI Handling | ✅ | | Common ROI models |
|
|
84
|
-
| Label Handling | ✅ | Mid-September | Based on Image Handling |
|
|
85
|
-
| Table Validation | ✅ | Mid-September | Validate Table fractal V1 + Compliance between Metadata and Data |
|
|
86
|
-
| Table Handling | ✅ | Mid-September | Read, Write ROI, Features, and Masked Tables |
|
|
87
|
-
| Basic Iterators | Ongoing | End-September | Read and Write Iterators for common access patterns |
|
|
88
|
-
| Base Documentation | ✅ | End-September | API Documentation and Examples |
|
|
89
|
-
| Beta Ready Testing | ✅ | End-September | Beta Testing; Library is ready for testing, but the API is not stable |
|
|
90
|
-
| Streaming from Fractal | Ongoing | December | Ngio can stream ome-zarr from fractal |
|
|
91
|
-
| Mask Iterators | Ongoing | Early 2025 | Iterators over Masked Tables |
|
|
92
|
-
| Advanced Iterators | Not started | mid-2025 | Iterators for advanced access patterns |
|
|
93
|
-
| Parallel Iterators | Not started | mid-2025 | Concurrent Iterators for parallel read and write |
|
|
94
|
-
| Full Documentation | Not started | 2025 | Complete Documentation |
|
|
95
|
-
| Release 1.0 (Commitment to API) | Not started | 2025 | API is stable; breaking changes will be avoided |
|
ngio-0.2.0a2.dist-info/RECORD
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
ngio/__init__.py,sha256=8FKJLwwoat9eykBHWa-U93PkzIlkQcde-sRZvtOdDYg,991
|
|
2
|
-
ngio/common/__init__.py,sha256=1vyK1i1ueu2BKKI-gaUhEyERVtHOtfKjQuPJOKDbrLA,1140
|
|
3
|
-
ngio/common/_array_pipe.py,sha256=DyYjGTy2L74zBtD6S2jGPsFG4zj7KaY39TwPGWsSf8g,4877
|
|
4
|
-
ngio/common/_axes_transforms.py,sha256=Dmrta3ZT1IgZAWomdUeTZVje8TBF_oU3RMKBv1r4EvM,1989
|
|
5
|
-
ngio/common/_common_types.py,sha256=OkAYNSNjZkixL1MI-HPBVuXamheFBr862uJ4PvTxmhk,129
|
|
6
|
-
ngio/common/_dimensions.py,sha256=t3X2wzqCl3-UeocqIpQgKRdcWYagijtKsaHTQz5bfT4,3680
|
|
7
|
-
ngio/common/_pyramid.py,sha256=aBxRBjW7y6D-Rj8f9B3dtqIErxk2eq20O58C33NBU0Q,7231
|
|
8
|
-
ngio/common/_roi.py,sha256=q7HZg2lPbnJ6flKRgK9e4nfOIgkGpDjDcdz-tE8F0Ys,2869
|
|
9
|
-
ngio/common/_slicer.py,sha256=Qk7XXmd4W9T3w55LvFTjAyloyIcS9tt9NTXiDZNwOx8,3076
|
|
10
|
-
ngio/common/_zoom.py,sha256=z2UjgotoDw7pvpeZVrxiGx4PXx65nk1vwQH3osTFACI,5422
|
|
11
|
-
ngio/hcs/__init__.py,sha256=ugnRl22hM9dic5XRsqQr-HCyyyY1qXTqYOAOzyOZm4M,1624
|
|
12
|
-
ngio/images/__init__.py,sha256=aijqG14eyqVgHtnlcKVNx37FRfT6QvKt8V6bwBpX_r8,526
|
|
13
|
-
ngio/images/abstract_image.py,sha256=n4akBHWQul7vmo4OlYtKWZwpsYl8IYg82AThJrvDrxc,7113
|
|
14
|
-
ngio/images/create.py,sha256=DMyiNVmj3uaJmJQqsL9ftzZNvXxeqgZ0-Pjo63WqWoM,8991
|
|
15
|
-
ngio/images/image.py,sha256=QiSdOaZSLWtAweecMj69hXXAdVnPIkO3Qfjvs8QII3o,12586
|
|
16
|
-
ngio/images/label.py,sha256=wzpIsIFuKdTOcTU57PHpIf_U4Fh6TwRhM-tLpEt4GbI,7520
|
|
17
|
-
ngio/images/omezarr_container.py,sha256=E0uDyBM1vZ8kCwXI6tIyPDl7QEdi5e91hI5AIWf8kFY,19161
|
|
18
|
-
ngio/ome_zarr_meta/__init__.py,sha256=9kYdyuCc3ouQCLDyUCB_lCVXUJ69Ls0fYwtodk3GtYI,798
|
|
19
|
-
ngio/ome_zarr_meta/_generic_handlers.py,sha256=4zRm3P1CRKgUQgD5Z2C9j8VVv659DZIifrmzkQ7o31I,10987
|
|
20
|
-
ngio/ome_zarr_meta/_meta_handlers.py,sha256=b6r1zX3SBBTKoQdKfEqvJaSnTOen5t1EPO3rh0I9VH4,4925
|
|
21
|
-
ngio/ome_zarr_meta/ngio_specs/__init__.py,sha256=S2bNEhqrUhp2muDCCiVik3E6HrbaG91Q9mfT9EXnWNs,1370
|
|
22
|
-
ngio/ome_zarr_meta/ngio_specs/_axes.py,sha256=zgAE0-2DHzJfqGqBhyjY7y_6qAgDLdV9iuWz-YsHe9Y,16682
|
|
23
|
-
ngio/ome_zarr_meta/ngio_specs/_channels.py,sha256=KLQAo7eerBXa5NN3-QWSFxeAfM_bvXXaxFjFNM6OMoA,13762
|
|
24
|
-
ngio/ome_zarr_meta/ngio_specs/_dataset.py,sha256=xT4GY2mdIsm6nAP8bXRj5E9-P6rS-iwzcXT_o3pZajo,4696
|
|
25
|
-
ngio/ome_zarr_meta/ngio_specs/_ngio_hcs.py,sha256=Gk29MJ4Vn4TLFK4M7X_33BumCLiZWRuXtSeLX6H56s4,115
|
|
26
|
-
ngio/ome_zarr_meta/ngio_specs/_ngio_image.py,sha256=FnVSupNHHsUxlQOfDXQP2fBZqL8BOX7bB_c1gHP0iWk,14703
|
|
27
|
-
ngio/ome_zarr_meta/ngio_specs/_pixel_size.py,sha256=Ny4F0Wa7uVCKdDQhvFJPCQFUEtKP_DpwId8vdVxkVyQ,2777
|
|
28
|
-
ngio/ome_zarr_meta/v04/__init__.py,sha256=0sb_CaJNgC1AOYeR6LDB91oUmSk6edJyQTTo3Lnh5Y4,226
|
|
29
|
-
ngio/ome_zarr_meta/v04/_meta_handlers.py,sha256=aRvuq9ofzQQCB-CJehD3e2T1eKBtZwKg6r2OkpTG1Oo,1768
|
|
30
|
-
ngio/ome_zarr_meta/v04/_v04_spec_utils.py,sha256=_vszk3ORSLObwW_0xbR61ptekvwgFiXsBLZ-5wgWli8,13775
|
|
31
|
-
ngio/tables/__init__.py,sha256=7Mz0kzssaM4k39az__6F9L8s46RaN0Vbw1JkfkysCPU,565
|
|
32
|
-
ngio/tables/_validators.py,sha256=Cg2sFb__G60RwSbNv4n9g_941R4Dzbp_LnaQBdVyaWw,6457
|
|
33
|
-
ngio/tables/tables_container.py,sha256=d7PVerDkAtrhWRmv8BVVE0tbrdugPSxZEa8w9tR5KrA,9508
|
|
34
|
-
ngio/tables/backends/__init__.py,sha256=NlOXmZXDA1kOCVONUyo_aqSjdMHmfqk-3xuKBLXpaUM,217
|
|
35
|
-
ngio/tables/backends/_abstract_backend.py,sha256=JlaHqLjDm2uVnXFWxsHMojNeKo3leg6uauzoFMSF5O4,2256
|
|
36
|
-
ngio/tables/backends/_anndata_utils.py,sha256=xqkm52XMMWC-jJ126oK7x1w7s4Y2jDjtgP8dmHSB3uU,6792
|
|
37
|
-
ngio/tables/backends/_anndata_v1.py,sha256=rzr471-Ae76KFJ0vjgzbGyW2m2Gb0El7JcmnT6mwGJY,2573
|
|
38
|
-
ngio/tables/backends/_json_v1.py,sha256=mT7qJY2U4vhwromZnT9foz_vVtNh_fwmsASGnLZbIac,1897
|
|
39
|
-
ngio/tables/backends/_table_backends.py,sha256=XXtnZqVDbMqFkbUkHbf9IBNz4teCouLpa5fWgEgVtfg,3269
|
|
40
|
-
ngio/tables/v1/__init__.py,sha256=C35WD3vSqB-AcATi7MRhGbCw5Z5VK7gGb8E8cMgL_L0,359
|
|
41
|
-
ngio/tables/v1/_feature_table.py,sha256=WOkFOb0UDxwM-MPZGdv-nLIiqfiGL8etVkMett9iQic,5099
|
|
42
|
-
ngio/tables/v1/_generic_table.py,sha256=KOVzbeUs8AwVvI83Os5gBZky948ucEKjxXl2CGzSQqQ,3483
|
|
43
|
-
ngio/tables/v1/_masking_roi_table.py,sha256=vPlUWGQalxDJ7G4NcSmzsOFqSEIJFXbuCLD_ucBj7ew,5492
|
|
44
|
-
ngio/tables/v1/_roi_table.py,sha256=UMwJEMkOAgDf-80z0qPfIiB6fsQInjzjDlR4OkBYH4o,7147
|
|
45
|
-
ngio/utils/__init__.py,sha256=fhT4CUTk3obQHzjfTcZYOwjZrSuuI1uXQ8qJmyH17iY,1021
|
|
46
|
-
ngio/utils/_datasets.py,sha256=Ir5-DUaplJoWXIsFCVp6yaJNfEKXKygj6RbGsy275uE,1669
|
|
47
|
-
ngio/utils/_errors.py,sha256=pKQ12LUjQLYE1nUawemA5h7HsgznjaSvV1n2PQU33N0,759
|
|
48
|
-
ngio/utils/_logger.py,sha256=zvFG-Ta3ZIJxTyY93zYoPGp2A6TTUf7mSO0zr_uFy4A,837
|
|
49
|
-
ngio/utils/_zarr_utils.py,sha256=5Mo8Nfb7oww7rGVqEWUH29VvOkhD3-Despb3c1SlENM,12172
|
|
50
|
-
ngio-0.2.0a2.dist-info/METADATA,sha256=-NUZl0xeZ-rFEqPilWo_hFfbQ-uuyCFa2cv2bLxkABo,4804
|
|
51
|
-
ngio-0.2.0a2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
52
|
-
ngio-0.2.0a2.dist-info/licenses/LICENSE,sha256=UgN_a1QCeNh9rZWfz-wORQFxE3elQzLWPQaoK6N6fxQ,1502
|
|
53
|
-
ngio-0.2.0a2.dist-info/RECORD,,
|
|
File without changes
|