ngio 0.3.0a1__py3-none-any.whl → 0.3.2__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/_array_pipe.py +50 -27
- ngio/common/_roi.py +2 -0
- ngio/common/_table_ops.py +1 -1
- ngio/hcs/__init__.py +1 -1
- ngio/hcs/{plate.py → _plate.py} +25 -9
- ngio/images/__init__.py +3 -3
- ngio/images/{image.py → _image.py} +26 -21
- ngio/images/{label.py → _label.py} +6 -4
- ngio/images/{masked_image.py → _masked_image.py} +2 -2
- ngio/images/{ome_zarr_container.py → _ome_zarr_container.py} +58 -22
- ngio/ome_zarr_meta/ngio_specs/_axes.py +4 -7
- ngio/ome_zarr_meta/ngio_specs/_channels.py +41 -29
- ngio/tables/__init__.py +8 -6
- ngio/tables/{abstract_table.py → _abstract_table.py} +2 -1
- ngio/tables/{tables_container.py → _tables_container.py} +33 -19
- ngio/tables/backends/__init__.py +2 -0
- ngio/tables/backends/_abstract_backend.py +1 -1
- ngio/tables/backends/_table_backends.py +35 -12
- ngio/tables/v1/_condition_table.py +1 -1
- ngio/tables/v1/_feature_table.py +2 -2
- ngio/tables/v1/_generic_table.py +1 -1
- ngio/tables/v1/_roi_table.py +13 -3
- ngio/utils/_fractal_fsspec_store.py +1 -1
- {ngio-0.3.0a1.dist-info → ngio-0.3.2.dist-info}/METADATA +68 -35
- {ngio-0.3.0a1.dist-info → ngio-0.3.2.dist-info}/RECORD +29 -29
- /ngio/images/{abstract_image.py → _abstract_image.py} +0 -0
- /ngio/images/{create.py → _create.py} +0 -0
- {ngio-0.3.0a1.dist-info → ngio-0.3.2.dist-info}/WHEEL +0 -0
- {ngio-0.3.0a1.dist-info → ngio-0.3.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -329,33 +329,35 @@ class ChannelsMeta(BaseModel):
|
|
|
329
329
|
@classmethod
|
|
330
330
|
def default_init(
|
|
331
331
|
cls,
|
|
332
|
-
labels: Collection[str] | int,
|
|
333
|
-
wavelength_id: Collection[str] | None = None,
|
|
334
|
-
colors: Collection[str | NgioColors] | None = None,
|
|
335
|
-
start: Collection[int | float] | int | float | None = None,
|
|
336
|
-
end: Collection[int | float] | int | float | None = None,
|
|
337
|
-
active: Collection[bool] | None = None,
|
|
332
|
+
labels: Collection[str | None] | int,
|
|
333
|
+
wavelength_id: Collection[str | None] | None = None,
|
|
334
|
+
colors: Collection[str | NgioColors | None] | None = None,
|
|
335
|
+
start: Collection[int | float | None] | int | float | None = None,
|
|
336
|
+
end: Collection[int | float | None] | int | float | None = None,
|
|
337
|
+
active: Collection[bool | None] | None = None,
|
|
338
338
|
data_type: Any = np.uint16,
|
|
339
339
|
**omero_kwargs: dict,
|
|
340
340
|
) -> "ChannelsMeta":
|
|
341
341
|
"""Create a ChannelsMeta object with the default unit.
|
|
342
342
|
|
|
343
343
|
Args:
|
|
344
|
-
labels(Collection[str] | int): The list of channels names
|
|
345
|
-
If an integer is provided, the channels will be
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
344
|
+
labels(Collection[str | None] | int): The list of channels names
|
|
345
|
+
in the image. If an integer is provided, the channels will be
|
|
346
|
+
named "channel_i".
|
|
347
|
+
wavelength_id(Collection[str | None] | None): The wavelength ID of the
|
|
348
|
+
channel. If None, the wavelength ID will be the same as the
|
|
349
|
+
channel name.
|
|
350
|
+
colors(Collection[str | NgioColors | None] | None): The list of
|
|
351
|
+
colors for the channels. If None, the colors will be random.
|
|
352
|
+
start(Collection[int | float | None] | int | float | None): The start
|
|
353
|
+
value of the channel. If None, the start value will be the
|
|
354
|
+
minimum value of the data type.
|
|
355
|
+
end(Collection[int | float | None] | int | float | None): The end
|
|
356
|
+
value of the channel. If None, the end value will be the
|
|
357
|
+
maximum value of the data type.
|
|
356
358
|
data_type(Any): The data type of the channel. Will be used to set the
|
|
357
359
|
min and max values of the channel.
|
|
358
|
-
active (Collection[bool] | None):
|
|
360
|
+
active (Collection[bool | None] | None): Whether the channel should
|
|
359
361
|
be shown by default.
|
|
360
362
|
omero_kwargs(dict): Extra fields to store in the omero attributes.
|
|
361
363
|
"""
|
|
@@ -366,25 +368,35 @@ class ChannelsMeta(BaseModel):
|
|
|
366
368
|
labels = _check_unique(labels)
|
|
367
369
|
|
|
368
370
|
_wavelength_id: Collection[str | None] = [None] * len(labels)
|
|
369
|
-
if
|
|
371
|
+
if wavelength_id is None:
|
|
372
|
+
_wavelength_id: Collection[str | None] = [None] * len(labels)
|
|
373
|
+
else:
|
|
370
374
|
_wavelength_id = _check_elements(wavelength_id, str)
|
|
371
375
|
_wavelength_id = _check_unique(wavelength_id)
|
|
372
376
|
|
|
373
|
-
|
|
374
|
-
|
|
377
|
+
if colors is None:
|
|
378
|
+
_colors = [NgioColors.semi_random_pick(label) for label in labels]
|
|
379
|
+
else:
|
|
375
380
|
_colors = _check_elements(colors, str | NgioColors)
|
|
376
381
|
|
|
377
|
-
|
|
378
|
-
|
|
382
|
+
if start is None:
|
|
383
|
+
_start = [None] * len(labels)
|
|
384
|
+
elif isinstance(start, int | float):
|
|
385
|
+
_start = [start] * len(labels)
|
|
386
|
+
else:
|
|
379
387
|
_start = _check_elements(start, (int, float))
|
|
380
388
|
|
|
381
|
-
|
|
382
|
-
|
|
389
|
+
if end is None:
|
|
390
|
+
_end = [None] * len(labels)
|
|
391
|
+
elif isinstance(end, int | float):
|
|
392
|
+
_end = [end] * len(labels)
|
|
393
|
+
else:
|
|
383
394
|
_end = _check_elements(end, (int, float))
|
|
384
395
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
396
|
+
if active is None:
|
|
397
|
+
_active = [True] * len(labels)
|
|
398
|
+
else:
|
|
399
|
+
_active = _check_elements(active, (bool,))
|
|
388
400
|
|
|
389
401
|
all_lengths = [
|
|
390
402
|
len(labels),
|
ngio/tables/__init__.py
CHANGED
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
"""Ngio Tables implementations."""
|
|
2
2
|
|
|
3
|
-
from ngio.tables.
|
|
4
|
-
ImplementedTableBackends,
|
|
5
|
-
TableBackend,
|
|
6
|
-
TableBackendProtocol,
|
|
7
|
-
)
|
|
8
|
-
from ngio.tables.tables_container import (
|
|
3
|
+
from ngio.tables._tables_container import (
|
|
9
4
|
ConditionTable,
|
|
10
5
|
FeatureTable,
|
|
11
6
|
GenericRoiTable,
|
|
@@ -19,10 +14,17 @@ from ngio.tables.tables_container import (
|
|
|
19
14
|
open_table_as,
|
|
20
15
|
open_tables_container,
|
|
21
16
|
)
|
|
17
|
+
from ngio.tables.backends import (
|
|
18
|
+
DefaultTableBackend,
|
|
19
|
+
ImplementedTableBackends,
|
|
20
|
+
TableBackend,
|
|
21
|
+
TableBackendProtocol,
|
|
22
|
+
)
|
|
22
23
|
from ngio.tables.v1._generic_table import GenericTable
|
|
23
24
|
|
|
24
25
|
__all__ = [
|
|
25
26
|
"ConditionTable",
|
|
27
|
+
"DefaultTableBackend",
|
|
26
28
|
"FeatureTable",
|
|
27
29
|
"GenericRoiTable",
|
|
28
30
|
"GenericTable",
|
|
@@ -10,6 +10,7 @@ from anndata import AnnData
|
|
|
10
10
|
|
|
11
11
|
from ngio.tables.backends import (
|
|
12
12
|
BackendMeta,
|
|
13
|
+
DefaultTableBackend,
|
|
13
14
|
ImplementedTableBackends,
|
|
14
15
|
TableBackend,
|
|
15
16
|
TableBackendProtocol,
|
|
@@ -203,7 +204,7 @@ class AbstractBaseTable(ABC):
|
|
|
203
204
|
def set_backend(
|
|
204
205
|
self,
|
|
205
206
|
handler: ZarrGroupHandler | None = None,
|
|
206
|
-
backend: TableBackend =
|
|
207
|
+
backend: TableBackend = DefaultTableBackend,
|
|
207
208
|
) -> None:
|
|
208
209
|
"""Set the backend of the table."""
|
|
209
210
|
if handler is None:
|
|
@@ -8,6 +8,7 @@ import polars as pl
|
|
|
8
8
|
|
|
9
9
|
from ngio.tables.backends import (
|
|
10
10
|
BackendMeta,
|
|
11
|
+
DefaultTableBackend,
|
|
11
12
|
TableBackend,
|
|
12
13
|
TabularData,
|
|
13
14
|
)
|
|
@@ -90,7 +91,7 @@ class Table(Protocol):
|
|
|
90
91
|
def set_backend(
|
|
91
92
|
self,
|
|
92
93
|
handler: ZarrGroupHandler | None = None,
|
|
93
|
-
backend: TableBackend =
|
|
94
|
+
backend: TableBackend = DefaultTableBackend,
|
|
94
95
|
) -> None:
|
|
95
96
|
"""Set the backend store and path for the table.
|
|
96
97
|
|
|
@@ -126,13 +127,18 @@ class Table(Protocol):
|
|
|
126
127
|
|
|
127
128
|
|
|
128
129
|
TypedTable = Literal[
|
|
130
|
+
"generic_table",
|
|
129
131
|
"roi_table",
|
|
130
132
|
"masking_roi_table",
|
|
131
133
|
"feature_table",
|
|
132
|
-
"generic_roi_table",
|
|
133
134
|
"condition_table",
|
|
134
135
|
]
|
|
135
136
|
|
|
137
|
+
TypedRoiTable = Literal[
|
|
138
|
+
"roi_table",
|
|
139
|
+
"masking_roi_table",
|
|
140
|
+
]
|
|
141
|
+
|
|
136
142
|
TableType = TypeVar("TableType", bound=Table)
|
|
137
143
|
|
|
138
144
|
|
|
@@ -192,19 +198,34 @@ class ImplementedTables:
|
|
|
192
198
|
table = table_cls.from_handler(handler=handler, backend=backend)
|
|
193
199
|
return table
|
|
194
200
|
|
|
195
|
-
def
|
|
201
|
+
def _add_implementation(
|
|
202
|
+
self, handler: type[Table], name: str, overwrite: bool = False
|
|
203
|
+
) -> None:
|
|
204
|
+
"""Register a new table handler."""
|
|
205
|
+
if name in self._implemented_tables and not overwrite:
|
|
206
|
+
raise NgioValueError(
|
|
207
|
+
f"Table handler for {name} already implemented. "
|
|
208
|
+
"Use overwrite=True to replace it."
|
|
209
|
+
)
|
|
210
|
+
self._implemented_tables[name] = handler
|
|
211
|
+
|
|
212
|
+
def add_implementation(
|
|
213
|
+
self,
|
|
214
|
+
handler: type[Table],
|
|
215
|
+
overwrite: bool = False,
|
|
216
|
+
aliases: list[str] | None = None,
|
|
217
|
+
) -> None:
|
|
196
218
|
"""Register a new table handler."""
|
|
197
219
|
meta = TableMeta(
|
|
198
220
|
type=handler.table_type(),
|
|
199
221
|
table_version=handler.version(),
|
|
200
222
|
)
|
|
201
223
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
self._implemented_tables[meta.unique_name()] = handler
|
|
224
|
+
self._add_implementation(handler, meta.unique_name(), overwrite)
|
|
225
|
+
|
|
226
|
+
if aliases is not None:
|
|
227
|
+
for alias in aliases:
|
|
228
|
+
self._add_implementation(handler, alias, overwrite)
|
|
208
229
|
|
|
209
230
|
|
|
210
231
|
class TablesContainer:
|
|
@@ -240,14 +261,7 @@ class TablesContainer:
|
|
|
240
261
|
handler = self._group_handler.derive_handler(path=name)
|
|
241
262
|
return handler
|
|
242
263
|
|
|
243
|
-
def
|
|
244
|
-
"""List all ROI tables in the group."""
|
|
245
|
-
_tables = []
|
|
246
|
-
for _type in ["roi_table", "masking_roi_table"]:
|
|
247
|
-
_tables.extend(self.list(_type))
|
|
248
|
-
return _tables
|
|
249
|
-
|
|
250
|
-
def list(self, filter_types: str | None = None) -> list[str]:
|
|
264
|
+
def list(self, filter_types: TypedTable | str | None = None) -> list[str]:
|
|
251
265
|
"""List all labels in the group."""
|
|
252
266
|
tables = self._get_tables_list()
|
|
253
267
|
if filter_types is None:
|
|
@@ -301,7 +315,7 @@ class TablesContainer:
|
|
|
301
315
|
self,
|
|
302
316
|
name: str,
|
|
303
317
|
table: Table,
|
|
304
|
-
backend: TableBackend =
|
|
318
|
+
backend: TableBackend = DefaultTableBackend,
|
|
305
319
|
overwrite: bool = False,
|
|
306
320
|
) -> None:
|
|
307
321
|
"""Add a table to the group."""
|
|
@@ -393,7 +407,7 @@ def open_table_as(
|
|
|
393
407
|
def write_table(
|
|
394
408
|
store: StoreOrGroup,
|
|
395
409
|
table: Table,
|
|
396
|
-
backend: TableBackend =
|
|
410
|
+
backend: TableBackend = DefaultTableBackend,
|
|
397
411
|
cache: bool = False,
|
|
398
412
|
mode: AccessModeLiteral = "a",
|
|
399
413
|
parallel_safe: bool = False,
|
ngio/tables/backends/__init__.py
CHANGED
|
@@ -6,6 +6,7 @@ from ngio.tables.backends._csv import CsvTableBackend
|
|
|
6
6
|
from ngio.tables.backends._json import JsonTableBackend
|
|
7
7
|
from ngio.tables.backends._parquet import ParquetTableBackend
|
|
8
8
|
from ngio.tables.backends._table_backends import (
|
|
9
|
+
DefaultTableBackend,
|
|
9
10
|
ImplementedTableBackends,
|
|
10
11
|
TableBackend,
|
|
11
12
|
TableBackendProtocol,
|
|
@@ -32,6 +33,7 @@ __all__ = [
|
|
|
32
33
|
"AnnDataBackend",
|
|
33
34
|
"BackendMeta",
|
|
34
35
|
"CsvTableBackend",
|
|
36
|
+
"DefaultTableBackend",
|
|
35
37
|
"ImplementedTableBackends",
|
|
36
38
|
"JsonTableBackend",
|
|
37
39
|
"ParquetTableBackend",
|
|
@@ -19,7 +19,7 @@ from ngio.utils import NgioValueError, ZarrGroupHandler
|
|
|
19
19
|
class BackendMeta(BaseModel):
|
|
20
20
|
"""Metadata for the backend."""
|
|
21
21
|
|
|
22
|
-
backend: str = "
|
|
22
|
+
backend: str = "anndata_v1"
|
|
23
23
|
index_key: str | None = None
|
|
24
24
|
index_type: Literal["int", "str"] | None = None
|
|
25
25
|
|
|
@@ -180,24 +180,47 @@ class ImplementedTableBackends:
|
|
|
180
180
|
)
|
|
181
181
|
return backend
|
|
182
182
|
|
|
183
|
-
def
|
|
183
|
+
def _add_backend(
|
|
184
184
|
self,
|
|
185
|
-
|
|
185
|
+
table_backend: type[TableBackendProtocol],
|
|
186
|
+
name: str,
|
|
186
187
|
overwrite: bool = False,
|
|
187
|
-
):
|
|
188
|
+
) -> None:
|
|
188
189
|
"""Register a new handler."""
|
|
189
|
-
|
|
190
|
-
if backend_name in self._implemented_backends and not overwrite:
|
|
190
|
+
if name in self._implemented_backends and not overwrite:
|
|
191
191
|
raise NgioValueError(
|
|
192
|
-
f"Table backend {
|
|
192
|
+
f"Table backend {name} already implemented. "
|
|
193
193
|
"Use the `overwrite=True` parameter to overwrite it."
|
|
194
194
|
)
|
|
195
|
-
self._implemented_backends[
|
|
196
|
-
|
|
195
|
+
self._implemented_backends[name] = table_backend
|
|
197
196
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
197
|
+
def add_backend(
|
|
198
|
+
self,
|
|
199
|
+
table_backend: type[TableBackendProtocol],
|
|
200
|
+
overwrite: bool = False,
|
|
201
|
+
aliases: list[str] | None = None,
|
|
202
|
+
) -> None:
|
|
203
|
+
"""Register a new handler."""
|
|
204
|
+
self._add_backend(
|
|
205
|
+
table_backend=table_backend,
|
|
206
|
+
name=table_backend.backend_name(),
|
|
207
|
+
overwrite=overwrite,
|
|
208
|
+
)
|
|
209
|
+
if aliases is not None:
|
|
210
|
+
for alias in aliases:
|
|
211
|
+
self._add_backend(
|
|
212
|
+
table_backend=table_backend, name=alias, overwrite=overwrite
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
ImplementedTableBackends().add_backend(AnnDataBackend, aliases=["anndata_v1"])
|
|
217
|
+
ImplementedTableBackends().add_backend(
|
|
218
|
+
JsonTableBackend, aliases=["experimental_json_v1"]
|
|
219
|
+
)
|
|
220
|
+
ImplementedTableBackends().add_backend(CsvTableBackend, aliases=["experimental_csv_v1"])
|
|
221
|
+
ImplementedTableBackends().add_backend(
|
|
222
|
+
ParquetTableBackend, aliases=["experimental_parquet_v1"]
|
|
223
|
+
)
|
|
202
224
|
|
|
203
225
|
TableBackend = Literal["anndata", "json", "csv", "parquet"] | str | TableBackendProtocol
|
|
226
|
+
DefaultTableBackend = "anndata_v1"
|
ngio/tables/v1/_feature_table.py
CHANGED
|
@@ -8,7 +8,7 @@ from typing import Literal
|
|
|
8
8
|
|
|
9
9
|
from pydantic import BaseModel, Field
|
|
10
10
|
|
|
11
|
-
from ngio.tables.
|
|
11
|
+
from ngio.tables._abstract_table import AbstractBaseTable
|
|
12
12
|
from ngio.tables.backends import BackendMeta, TableBackend, TabularData
|
|
13
13
|
from ngio.utils import NgioValueError
|
|
14
14
|
from ngio.utils._zarr_utils import ZarrGroupHandler
|
|
@@ -26,7 +26,7 @@ class FeatureTableMeta(BackendMeta):
|
|
|
26
26
|
table_version: Literal["1"] = "1"
|
|
27
27
|
type: Literal["feature_table"] = "feature_table"
|
|
28
28
|
region: RegionMeta | None = None
|
|
29
|
-
instance_key: str = "label"
|
|
29
|
+
instance_key: str = "label" # Legacy field, kept for compatibility
|
|
30
30
|
# Backend metadata
|
|
31
31
|
index_key: str | None = "label"
|
|
32
32
|
index_type: Literal["int", "str"] | None = "int"
|
ngio/tables/v1/_generic_table.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Implementation of a generic table class."""
|
|
2
2
|
|
|
3
|
-
from ngio.tables.
|
|
3
|
+
from ngio.tables._abstract_table import AbstractBaseTable
|
|
4
4
|
from ngio.tables.backends import BackendMeta, TableBackend
|
|
5
5
|
from ngio.utils import ZarrGroupHandler
|
|
6
6
|
|
ngio/tables/v1/_roi_table.py
CHANGED
|
@@ -13,7 +13,7 @@ import pandas as pd
|
|
|
13
13
|
from pydantic import BaseModel
|
|
14
14
|
|
|
15
15
|
from ngio.common import Roi
|
|
16
|
-
from ngio.tables.
|
|
16
|
+
from ngio.tables._abstract_table import (
|
|
17
17
|
AbstractBaseTable,
|
|
18
18
|
TabularData,
|
|
19
19
|
)
|
|
@@ -47,11 +47,20 @@ REQUIRED_COLUMNS = [
|
|
|
47
47
|
ORIGIN_COLUMNS = [
|
|
48
48
|
"x_micrometer_original",
|
|
49
49
|
"y_micrometer_original",
|
|
50
|
+
"z_micrometer_original",
|
|
50
51
|
]
|
|
51
52
|
|
|
52
53
|
TRANSLATION_COLUMNS = ["translation_x", "translation_y", "translation_z"]
|
|
53
54
|
|
|
54
|
-
PLATE_COLUMNS = [
|
|
55
|
+
PLATE_COLUMNS = [
|
|
56
|
+
"plate_name",
|
|
57
|
+
"row",
|
|
58
|
+
"column",
|
|
59
|
+
"path_in_well",
|
|
60
|
+
"path_in_plate",
|
|
61
|
+
"acquisition_id",
|
|
62
|
+
"acquisition_name",
|
|
63
|
+
]
|
|
55
64
|
|
|
56
65
|
INDEX_COLUMNS = [
|
|
57
66
|
"FieldIndex",
|
|
@@ -390,7 +399,8 @@ class MaskingRoiTableV1(GenericRoiTableV1):
|
|
|
390
399
|
meta = MaskingRoiTableV1Meta()
|
|
391
400
|
|
|
392
401
|
if reference_label is not None:
|
|
393
|
-
|
|
402
|
+
path = f"../labels/{reference_label}"
|
|
403
|
+
meta.region = RegionMeta(path=path)
|
|
394
404
|
|
|
395
405
|
if meta.index_key is None:
|
|
396
406
|
meta.index_key = "label"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ngio
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2
|
|
4
4
|
Summary: Next Generation file format IO
|
|
5
5
|
Project-URL: homepage, https://github.com/fractal-analytics-platform/ngio
|
|
6
6
|
Project-URL: repository, https://github.com/fractal-analytics-platform/ngio
|
|
@@ -63,7 +63,7 @@ Requires-Dist: pytest-cov; extra == 'test'
|
|
|
63
63
|
Requires-Dist: scikit-image; extra == 'test'
|
|
64
64
|
Description-Content-Type: text/markdown
|
|
65
65
|
|
|
66
|
-
#
|
|
66
|
+
# Ngio - Next Generation file format IO
|
|
67
67
|
|
|
68
68
|
[](https://github.com/lorenzocerrone/ngio/raw/main/LICENSE)
|
|
69
69
|
[](https://pypi.org/project/ngio)
|
|
@@ -71,36 +71,69 @@ Description-Content-Type: text/markdown
|
|
|
71
71
|
[](https://github.com/fractal-analytics-platform/ngio/actions/workflows/ci.yml)
|
|
72
72
|
[](https://codecov.io/gh/fractal-analytics-platform/ngio)
|
|
73
73
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
74
|
+
ngio is a Python library designed to simplify bioimage analysis workflows, offering an intuitive interface for working with OME-Zarr files.
|
|
75
|
+
|
|
76
|
+
## What is Ngio?
|
|
77
|
+
|
|
78
|
+
Ngio is built for the [OME-Zarr](https://ngff.openmicroscopy.org/) file format, a modern, cloud-optimized format for biological imaging data. OME-Zarr stores large, multi-dimensional microscopy images and metadata in an efficient and scalable way.
|
|
79
|
+
|
|
80
|
+
Ngio's mission is to streamline working with OME-Zarr files by providing a simple, object-based API for opening, exploring, and manipulating OME-Zarr images and high-content screening (HCS) plates. It also offers comprehensive support for labels, tables and regions of interest (ROIs), making it easy to extract and analyze specific regions in your data.
|
|
81
|
+
|
|
82
|
+
## Key Features
|
|
83
|
+
|
|
84
|
+
### 📊 Simple Object-Based API
|
|
85
|
+
|
|
86
|
+
- Easily open, explore, and manipulate OME-Zarr images and HCS plates
|
|
87
|
+
- Create and derive new images and labels with minimal boilerplate code
|
|
88
|
+
|
|
89
|
+
### 🔍 Rich Tables and Regions of Interest (ROI) Support
|
|
90
|
+
|
|
91
|
+
- Extract and analyze specific regions of interest
|
|
92
|
+
- Tight integration with [Tabular Data](https://fractal-analytics-platform.github.io/ngio/stable/table_specs/overview/)
|
|
93
|
+
|
|
94
|
+
### 🔄 Scalable Data Processing (Coming Soon)
|
|
95
|
+
|
|
96
|
+
- Powerful iterators for processing data at scale
|
|
97
|
+
- Efficient memory management for large datasets
|
|
98
|
+
|
|
99
|
+
## Installation
|
|
100
|
+
|
|
101
|
+
You can install ngio via pip:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
pip install ngio
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
To get started check out the [Quickstart Guide](https://fractal-analytics-platform.github.io/ngio/stable/getting_started/0_quickstart/).
|
|
108
|
+
|
|
109
|
+
## Supported OME-Zarr versions
|
|
110
|
+
|
|
111
|
+
Currently, ngio only supports OME-Zarr v0.4. Support for version 0.5 and higher is planned for future releases.
|
|
112
|
+
|
|
113
|
+
## Development Status
|
|
114
|
+
|
|
115
|
+
!!! warning
|
|
116
|
+
Ngio is under active development and is not yet stable. The API is subject to change, and bugs and breaking changes are expected.
|
|
117
|
+
We follow [Semantic Versioning](https://semver.org/). Which means for 0.x releases potentially breaking changes can be introduced in minor releases.
|
|
118
|
+
|
|
119
|
+
### Available Features
|
|
120
|
+
|
|
121
|
+
- ✅ OME-Zarr metadata handling and validation
|
|
122
|
+
- ✅ Image and label access across pyramid levels
|
|
123
|
+
- ✅ ROI and table support
|
|
124
|
+
- ✅ Streaming from remote sources
|
|
125
|
+
- ✅ Documentation and examples
|
|
126
|
+
|
|
127
|
+
### Upcoming Features
|
|
128
|
+
|
|
129
|
+
- Advanced image processing iterators
|
|
130
|
+
- Parallel processing capabilities
|
|
131
|
+
- Support for OME-Zarr v0.5 and Zarr v3
|
|
132
|
+
|
|
133
|
+
## Contributors
|
|
134
|
+
|
|
135
|
+
Ngio is developed at the [BioVisionCenter](https://www.biovisioncenter.uzh.ch/en.html), University of Zurich, by [@lorenzocerrone](https://github.com/lorenzocerrone) and [@jluethi](https://github.com/jluethi).
|
|
136
|
+
|
|
137
|
+
## License
|
|
138
|
+
|
|
139
|
+
Ngio is released under the BSD-3-Clause License. See [LICENSE](https://github.com/fractal-analytics-platform/ngio/blob/main/LICENSE) for details.
|