ngio 0.5.0__py3-none-any.whl → 0.5.0a2__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 +2 -5
- ngio/common/__init__.py +6 -11
- ngio/common/_masking_roi.py +54 -34
- ngio/common/_pyramid.py +85 -309
- ngio/common/_roi.py +330 -258
- ngio/experimental/iterators/_feature.py +3 -3
- ngio/experimental/iterators/_rois_utils.py +11 -10
- ngio/hcs/_plate.py +60 -132
- ngio/images/_abstract_image.py +35 -539
- ngio/images/_create.py +287 -0
- ngio/images/_create_synt_container.py +42 -39
- ngio/images/_image.py +250 -516
- ngio/images/_label.py +172 -249
- ngio/images/_masked_image.py +2 -2
- ngio/images/_ome_zarr_container.py +241 -644
- ngio/io_pipes/_io_pipes.py +9 -9
- ngio/io_pipes/_io_pipes_masked.py +7 -7
- ngio/io_pipes/_io_pipes_roi.py +6 -6
- ngio/io_pipes/_io_pipes_types.py +3 -3
- ngio/io_pipes/_match_shape.py +8 -6
- ngio/io_pipes/_ops_slices_utils.py +5 -8
- ngio/ome_zarr_meta/__init__.py +18 -29
- ngio/ome_zarr_meta/_meta_handlers.py +708 -392
- ngio/ome_zarr_meta/ngio_specs/__init__.py +0 -4
- ngio/ome_zarr_meta/ngio_specs/_axes.py +51 -152
- ngio/ome_zarr_meta/ngio_specs/_dataset.py +22 -13
- ngio/ome_zarr_meta/ngio_specs/_ngio_hcs.py +91 -129
- ngio/ome_zarr_meta/ngio_specs/_ngio_image.py +68 -57
- ngio/ome_zarr_meta/v04/__init__.py +1 -5
- ngio/ome_zarr_meta/v04/{_v04_spec.py → _v04_spec_utils.py} +85 -54
- ngio/ome_zarr_meta/v05/__init__.py +1 -5
- ngio/ome_zarr_meta/v05/{_v05_spec.py → _v05_spec_utils.py} +87 -64
- ngio/resources/__init__.py +1 -1
- ngio/resources/resource_model.py +1 -1
- ngio/tables/_tables_container.py +11 -62
- ngio/tables/backends/_anndata.py +8 -58
- ngio/tables/backends/_anndata_utils.py +6 -1
- ngio/tables/backends/_csv.py +19 -3
- ngio/tables/backends/_json.py +13 -10
- ngio/tables/backends/_non_zarr_backends.py +196 -0
- ngio/tables/backends/_parquet.py +31 -3
- ngio/tables/v1/_roi_table.py +24 -41
- ngio/utils/__init__.py +12 -6
- ngio/utils/_datasets.py +0 -6
- ngio/utils/_logger.py +50 -0
- ngio/utils/_zarr_utils.py +58 -167
- {ngio-0.5.0.dist-info → ngio-0.5.0a2.dist-info}/METADATA +4 -11
- ngio-0.5.0a2.dist-info/RECORD +89 -0
- {ngio-0.5.0.dist-info → ngio-0.5.0a2.dist-info}/WHEEL +1 -1
- ngio/images/_create_utils.py +0 -406
- ngio/tables/backends/_py_arrow_backends.py +0 -222
- ngio-0.5.0.dist-info/RECORD +0 -88
- {ngio-0.5.0.dist-info → ngio-0.5.0a2.dist-info}/licenses/LICENSE +0 -0
ngio/utils/__init__.py
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
"""Various utilities for the ngio package."""
|
|
2
2
|
|
|
3
|
+
import os
|
|
4
|
+
|
|
3
5
|
from ngio.utils._datasets import (
|
|
4
6
|
download_ome_zarr_dataset,
|
|
5
7
|
list_ome_zarr_datasets,
|
|
6
8
|
print_datasets_infos,
|
|
7
9
|
)
|
|
8
10
|
from ngio.utils._errors import (
|
|
9
|
-
NgioError,
|
|
10
11
|
NgioFileExistsError,
|
|
11
12
|
NgioFileNotFoundError,
|
|
12
13
|
NgioTableValidationError,
|
|
@@ -14,32 +15,37 @@ from ngio.utils._errors import (
|
|
|
14
15
|
NgioValueError,
|
|
15
16
|
)
|
|
16
17
|
from ngio.utils._fractal_fsspec_store import fractal_fsspec_store
|
|
18
|
+
from ngio.utils._logger import ngio_logger, ngio_warn, set_logger_level
|
|
17
19
|
from ngio.utils._zarr_utils import (
|
|
18
20
|
AccessModeLiteral,
|
|
19
21
|
NgioCache,
|
|
20
|
-
NgioSupportedStore,
|
|
21
22
|
StoreOrGroup,
|
|
22
23
|
ZarrGroupHandler,
|
|
23
|
-
copy_group,
|
|
24
24
|
open_group_wrapper,
|
|
25
25
|
)
|
|
26
26
|
|
|
27
|
+
set_logger_level(os.getenv("NGIO_LOGGER_LEVEL", "WARNING"))
|
|
28
|
+
|
|
27
29
|
__all__ = [
|
|
30
|
+
# Zarr
|
|
28
31
|
"AccessModeLiteral",
|
|
29
32
|
"NgioCache",
|
|
30
|
-
|
|
33
|
+
# Errors
|
|
31
34
|
"NgioFileExistsError",
|
|
32
35
|
"NgioFileNotFoundError",
|
|
33
|
-
"NgioSupportedStore",
|
|
34
36
|
"NgioTableValidationError",
|
|
35
37
|
"NgioValidationError",
|
|
36
38
|
"NgioValueError",
|
|
37
39
|
"StoreOrGroup",
|
|
38
40
|
"ZarrGroupHandler",
|
|
39
|
-
|
|
41
|
+
# Other
|
|
40
42
|
"download_ome_zarr_dataset",
|
|
41
43
|
"fractal_fsspec_store",
|
|
42
44
|
"list_ome_zarr_datasets",
|
|
45
|
+
# Logger
|
|
46
|
+
"ngio_logger",
|
|
47
|
+
"ngio_warn",
|
|
43
48
|
"open_group_wrapper",
|
|
44
49
|
"print_datasets_infos",
|
|
50
|
+
"set_logger_level",
|
|
45
51
|
]
|
ngio/utils/_datasets.py
CHANGED
|
@@ -155,11 +155,5 @@ def download_ome_zarr_dataset(
|
|
|
155
155
|
path=download_dir,
|
|
156
156
|
processor=processor,
|
|
157
157
|
progressbar=progressbar,
|
|
158
|
-
# Add User-Agent to avoid 403 errors from Zenodo
|
|
159
|
-
downloader=pooch.HTTPDownloader(
|
|
160
|
-
headers={
|
|
161
|
-
"User-Agent": f"pooch/{pooch.__version__} (https://github.com/BioVisionCenter/ngio)"
|
|
162
|
-
}
|
|
163
|
-
),
|
|
164
158
|
)
|
|
165
159
|
return processor.output_file()
|
ngio/utils/_logger.py
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import time
|
|
3
|
+
from functools import cache
|
|
4
|
+
|
|
5
|
+
from ngio.utils._errors import NgioValueError
|
|
6
|
+
|
|
7
|
+
# Configure the logger
|
|
8
|
+
ngio_logger = logging.getLogger("NgioLogger")
|
|
9
|
+
ngio_logger.setLevel(logging.ERROR)
|
|
10
|
+
|
|
11
|
+
# Set up a console handler with a custom format
|
|
12
|
+
console_handler = logging.StreamHandler()
|
|
13
|
+
formatter = logging.Formatter(
|
|
14
|
+
"%(asctime)s - %(levelname)s - %(name)s - "
|
|
15
|
+
"[%(module)s.%(funcName)s:%(lineno)d]: %(message)s"
|
|
16
|
+
)
|
|
17
|
+
console_handler.setFormatter(formatter)
|
|
18
|
+
|
|
19
|
+
# Add the handler to the logger
|
|
20
|
+
ngio_logger.addHandler(console_handler)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def set_logger_level(level: str) -> None:
|
|
24
|
+
"""Set the logger level.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
level: The level to set the logger to.
|
|
28
|
+
Must be one of "DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL".
|
|
29
|
+
"""
|
|
30
|
+
if level not in ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]:
|
|
31
|
+
raise NgioValueError(f"Invalid log level: {level}")
|
|
32
|
+
|
|
33
|
+
ngio_logger.setLevel(level)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@cache
|
|
37
|
+
def _warn(message: str, ttl_hash: int) -> None:
|
|
38
|
+
"""Log a warning message with a time-to-live (TTL) hash."""
|
|
39
|
+
ngio_logger.warning(message, stacklevel=3)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def ngio_warn(message: str, cooldown: int = 2) -> None:
|
|
43
|
+
"""Log a warning message.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
message: The warning message to log.
|
|
47
|
+
cooldown: The cooldown period in seconds to avoid repeated logging.
|
|
48
|
+
"""
|
|
49
|
+
ttl_hash = time.time() // cooldown
|
|
50
|
+
_warn(message, ttl_hash)
|
ngio/utils/_zarr_utils.py
CHANGED
|
@@ -1,22 +1,19 @@
|
|
|
1
1
|
"""Common utilities for working with Zarr groups in consistent ways."""
|
|
2
2
|
|
|
3
|
-
import json
|
|
4
3
|
import warnings
|
|
5
4
|
from pathlib import Path
|
|
6
|
-
from typing import Literal
|
|
5
|
+
from typing import Literal
|
|
7
6
|
|
|
8
|
-
import dask.array as da
|
|
9
7
|
import fsspec
|
|
10
8
|
import zarr
|
|
11
9
|
from filelock import BaseFileLock, FileLock
|
|
12
|
-
from pydantic_zarr.v2 import ArraySpec as AnyArraySpecV2
|
|
13
|
-
from pydantic_zarr.v3 import ArraySpec as AnyArraySpecV3
|
|
14
10
|
from zarr.abc.store import Store
|
|
15
11
|
from zarr.errors import ContainsGroupError
|
|
16
|
-
from zarr.storage import FsspecStore, LocalStore, MemoryStore
|
|
12
|
+
from zarr.storage import FsspecStore, LocalStore, MemoryStore
|
|
17
13
|
|
|
18
14
|
from ngio.utils._cache import NgioCache
|
|
19
15
|
from ngio.utils._errors import (
|
|
16
|
+
NgioError,
|
|
20
17
|
NgioFileExistsError,
|
|
21
18
|
NgioFileNotFoundError,
|
|
22
19
|
NgioValueError,
|
|
@@ -26,11 +23,11 @@ AccessModeLiteral = Literal["r", "r+", "w", "w-", "a"]
|
|
|
26
23
|
# StoreLike is more restrictive than it could be
|
|
27
24
|
# but to make sure we can handle the store correctly
|
|
28
25
|
# we need to be more restrictive
|
|
29
|
-
NgioSupportedStore
|
|
30
|
-
str | Path | fsspec.mapping.FSMap | FsspecStore | MemoryStore |
|
|
26
|
+
NgioSupportedStore = (
|
|
27
|
+
str | Path | fsspec.mapping.FSMap | FsspecStore | MemoryStore | LocalStore
|
|
31
28
|
)
|
|
32
|
-
GenericStore
|
|
33
|
-
StoreOrGroup
|
|
29
|
+
GenericStore = Store | NgioSupportedStore
|
|
30
|
+
StoreOrGroup = GenericStore | zarr.Group
|
|
34
31
|
|
|
35
32
|
|
|
36
33
|
def _check_store(store) -> NgioSupportedStore:
|
|
@@ -114,6 +111,7 @@ class ZarrGroupHandler:
|
|
|
114
111
|
|
|
115
112
|
Args:
|
|
116
113
|
store (StoreOrGroup): The Zarr store or group containing the image data.
|
|
114
|
+
meta_mode (str): The mode of the metadata handler.
|
|
117
115
|
zarr_format (int | None): The Zarr format version to use.
|
|
118
116
|
cache (bool): Whether to cache the metadata.
|
|
119
117
|
mode (str | None): The mode of the store.
|
|
@@ -127,7 +125,6 @@ class ZarrGroupHandler:
|
|
|
127
125
|
|
|
128
126
|
self._group_cache: NgioCache[zarr.Group] = NgioCache(use_cache=cache)
|
|
129
127
|
self._array_cache: NgioCache[zarr.Array] = NgioCache(use_cache=cache)
|
|
130
|
-
self._handlers_cache: NgioCache[ZarrGroupHandler] = NgioCache(use_cache=cache)
|
|
131
128
|
self._lock: tuple[Path, BaseFileLock] | None = None
|
|
132
129
|
|
|
133
130
|
def __repr__(self) -> str:
|
|
@@ -147,17 +144,8 @@ class ZarrGroupHandler:
|
|
|
147
144
|
"""Return the store path."""
|
|
148
145
|
if isinstance(self.store, LocalStore):
|
|
149
146
|
return (self.store.root / self.group.path).as_posix()
|
|
150
|
-
|
|
151
|
-
return
|
|
152
|
-
elif isinstance(self.store, ZipStore):
|
|
153
|
-
return (self.store.path / self.group.path).as_posix()
|
|
154
|
-
elif isinstance(self.store, MemoryStore):
|
|
155
|
-
return None
|
|
156
|
-
warnings.warn(
|
|
157
|
-
f"Cannot determine full URL for store type {type(self.store)}. ",
|
|
158
|
-
UserWarning,
|
|
159
|
-
stacklevel=2,
|
|
160
|
-
)
|
|
147
|
+
if isinstance(self.store, FsspecStore):
|
|
148
|
+
return self.store.fs.map.root_path
|
|
161
149
|
return None
|
|
162
150
|
|
|
163
151
|
@property
|
|
@@ -337,6 +325,25 @@ class ZarrGroupHandler:
|
|
|
337
325
|
self._group_cache.set(path, group, overwrite=overwrite)
|
|
338
326
|
return group
|
|
339
327
|
|
|
328
|
+
def safe_get_group(
|
|
329
|
+
self, path: str, create_mode: bool = False
|
|
330
|
+
) -> tuple[bool, zarr.Group | NgioError]:
|
|
331
|
+
"""Get a group from the group.
|
|
332
|
+
|
|
333
|
+
Args:
|
|
334
|
+
path (str): The path to the group.
|
|
335
|
+
create_mode (bool): If True, create the group if it does not exist.
|
|
336
|
+
|
|
337
|
+
Returns:
|
|
338
|
+
zarr.Group | None: The Zarr group or None if it does not exist
|
|
339
|
+
or an error occurs.
|
|
340
|
+
|
|
341
|
+
"""
|
|
342
|
+
try:
|
|
343
|
+
return True, self.get_group(path, create_mode)
|
|
344
|
+
except NgioError as e:
|
|
345
|
+
return False, e
|
|
346
|
+
|
|
340
347
|
def get_array(self, path: str) -> zarr.Array:
|
|
341
348
|
"""Get an array from the group."""
|
|
342
349
|
array = self._array_cache.get(path)
|
|
@@ -351,55 +358,47 @@ class ZarrGroupHandler:
|
|
|
351
358
|
raise NgioValueError(f"The object at {path} is not an array, but a group.")
|
|
352
359
|
raise NgioFileNotFoundError(f"No array found at {path}")
|
|
353
360
|
|
|
354
|
-
def
|
|
361
|
+
def derive_handler(
|
|
355
362
|
self,
|
|
356
363
|
path: str,
|
|
357
|
-
create_mode: bool = True,
|
|
358
364
|
overwrite: bool = False,
|
|
359
365
|
) -> "ZarrGroupHandler":
|
|
360
|
-
"""
|
|
366
|
+
"""Derive a new handler from the current handler.
|
|
361
367
|
|
|
362
368
|
Args:
|
|
363
369
|
path (str): The path to the group.
|
|
364
|
-
create_mode (bool): If True, create the group if it does not exist.
|
|
365
370
|
overwrite (bool): If True, overwrite the group if it exists.
|
|
366
371
|
"""
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
group = self.get_group(path, create_mode=create_mode, overwrite=overwrite)
|
|
371
|
-
mode = "r" if group.read_only else "r+"
|
|
372
|
-
handler = ZarrGroupHandler(
|
|
373
|
-
store=group, zarr_format=self.zarr_format, cache=self.use_cache, mode=mode
|
|
372
|
+
group = self.get_group(path, create_mode=True, overwrite=overwrite)
|
|
373
|
+
return ZarrGroupHandler(
|
|
374
|
+
store=group, zarr_format=self.zarr_format, cache=self.use_cache, mode="r+"
|
|
374
375
|
)
|
|
375
|
-
self._handlers_cache.set(path, handler)
|
|
376
|
-
return handler
|
|
377
|
-
|
|
378
|
-
@property
|
|
379
|
-
def is_listable(self) -> bool:
|
|
380
|
-
return is_group_listable(self.group)
|
|
381
|
-
|
|
382
|
-
def delete_group(self, path: str) -> None:
|
|
383
|
-
"""Delete a group from the current group.
|
|
384
376
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
"""Delete the current group."""
|
|
396
|
-
if self.group.read_only:
|
|
397
|
-
raise NgioValueError("Cannot delete a group in read only mode.")
|
|
398
|
-
self.group.__delitem__("/")
|
|
377
|
+
def safe_derive_handler(
|
|
378
|
+
self,
|
|
379
|
+
path: str,
|
|
380
|
+
overwrite: bool = False,
|
|
381
|
+
) -> tuple[bool, "ZarrGroupHandler | NgioError"]:
|
|
382
|
+
"""Derive a new handler from the current handler."""
|
|
383
|
+
try:
|
|
384
|
+
return True, self.derive_handler(path, overwrite=overwrite)
|
|
385
|
+
except NgioError as e:
|
|
386
|
+
return False, e
|
|
399
387
|
|
|
400
|
-
def
|
|
388
|
+
def copy_handler(self, handler: "ZarrGroupHandler") -> None:
|
|
401
389
|
"""Copy the group to a new store."""
|
|
402
|
-
|
|
390
|
+
_, n_skipped, _ = zarr.copy_store(
|
|
391
|
+
source=self.group.store,
|
|
392
|
+
dest=handler.group.store,
|
|
393
|
+
source_path=self.group.path,
|
|
394
|
+
dest_path=handler.group.path,
|
|
395
|
+
if_exists="replace",
|
|
396
|
+
)
|
|
397
|
+
if n_skipped > 0:
|
|
398
|
+
raise NgioValueError(
|
|
399
|
+
f"Error copying group to {handler.full_url}, "
|
|
400
|
+
f"#{n_skipped} files where skipped."
|
|
401
|
+
)
|
|
403
402
|
|
|
404
403
|
|
|
405
404
|
def find_dimension_separator(array: zarr.Array) -> Literal[".", "/"]:
|
|
@@ -418,116 +417,8 @@ def find_dimension_separator(array: zarr.Array) -> Literal[".", "/"]:
|
|
|
418
417
|
else:
|
|
419
418
|
separator = array.metadata.chunk_key_encoding
|
|
420
419
|
if not isinstance(separator, DefaultChunkKeyEncoding):
|
|
421
|
-
raise
|
|
420
|
+
raise ValueError(
|
|
422
421
|
"Only DefaultChunkKeyEncoding is supported in this example."
|
|
423
422
|
)
|
|
424
423
|
separator = separator.separator
|
|
425
424
|
return separator
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
def is_group_listable(group: zarr.Group) -> bool:
|
|
429
|
-
"""Check if a Zarr group is listable.
|
|
430
|
-
|
|
431
|
-
A group is considered listable if it contains at least one array or subgroup.
|
|
432
|
-
|
|
433
|
-
Args:
|
|
434
|
-
group (zarr.Group): The Zarr group to check.
|
|
435
|
-
|
|
436
|
-
Returns:
|
|
437
|
-
bool: True if the group is listable, False otherwise.
|
|
438
|
-
"""
|
|
439
|
-
if not group.store.supports_listing:
|
|
440
|
-
# If the store does not support listing
|
|
441
|
-
# then for sure it is not listable
|
|
442
|
-
return False
|
|
443
|
-
try:
|
|
444
|
-
next(group.keys())
|
|
445
|
-
return True
|
|
446
|
-
except StopIteration:
|
|
447
|
-
# Group is listable but empty
|
|
448
|
-
return True
|
|
449
|
-
except Exception as _:
|
|
450
|
-
# Some stores may raise errors when listing
|
|
451
|
-
# consider those not listable
|
|
452
|
-
return False
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
def _make_sync_fs(fs: fsspec.AbstractFileSystem) -> fsspec.AbstractFileSystem:
|
|
456
|
-
fs_dict = json.loads(fs.to_json())
|
|
457
|
-
fs_dict["asynchronous"] = False
|
|
458
|
-
return fsspec.AbstractFileSystem.from_json(json.dumps(fs_dict))
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
def _get_mapper(store: LocalStore | FsspecStore, path: str):
|
|
462
|
-
if isinstance(store, LocalStore):
|
|
463
|
-
fs = fsspec.filesystem("file")
|
|
464
|
-
full_path = (store.root / path).as_posix()
|
|
465
|
-
else:
|
|
466
|
-
fs = _make_sync_fs(store.fs)
|
|
467
|
-
full_path = f"{store.path}/{path}"
|
|
468
|
-
return fs.get_mapper(full_path)
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
def _fsspec_copy(
|
|
472
|
-
src_fs: LocalStore | FsspecStore,
|
|
473
|
-
src_path: str,
|
|
474
|
-
dest_fs: LocalStore | FsspecStore,
|
|
475
|
-
dest_path: str,
|
|
476
|
-
):
|
|
477
|
-
src_mapper = _get_mapper(src_fs, src_path)
|
|
478
|
-
dest_mapper = _get_mapper(dest_fs, dest_path)
|
|
479
|
-
for key in src_mapper.keys():
|
|
480
|
-
dest_mapper[key] = src_mapper[key]
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
def _zarr_python_copy(src_group: zarr.Group, dest_group: zarr.Group):
|
|
484
|
-
# Copy attributes
|
|
485
|
-
dest_group.attrs.put(src_group.attrs.asdict())
|
|
486
|
-
# Copy arrays
|
|
487
|
-
for name, array in src_group.arrays():
|
|
488
|
-
if array.metadata.zarr_format == 2:
|
|
489
|
-
spec = AnyArraySpecV2.from_zarr(array)
|
|
490
|
-
else:
|
|
491
|
-
spec = AnyArraySpecV3.from_zarr(array)
|
|
492
|
-
dst = spec.to_zarr(
|
|
493
|
-
store=dest_group.store,
|
|
494
|
-
path=f"{dest_group.path}/{name}",
|
|
495
|
-
overwrite=True,
|
|
496
|
-
)
|
|
497
|
-
if array.ndim > 0:
|
|
498
|
-
dask_array = da.from_zarr(array)
|
|
499
|
-
da.to_zarr(dask_array, dst, overwrite=False)
|
|
500
|
-
# Copy subgroups
|
|
501
|
-
for name, subgroup in src_group.groups():
|
|
502
|
-
dest_subgroup = dest_group.create_group(name, overwrite=True)
|
|
503
|
-
_zarr_python_copy(subgroup, dest_subgroup)
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
def copy_group(
|
|
507
|
-
src_group: zarr.Group, dest_group: zarr.Group, suppress_warnings: bool = False
|
|
508
|
-
):
|
|
509
|
-
if src_group.metadata.zarr_format != dest_group.metadata.zarr_format:
|
|
510
|
-
raise NgioValueError(
|
|
511
|
-
"Different Zarr format versions between source and destination, "
|
|
512
|
-
"cannot copy."
|
|
513
|
-
)
|
|
514
|
-
|
|
515
|
-
if not is_group_listable(src_group):
|
|
516
|
-
raise NgioValueError("Source group is not listable, cannot copy.")
|
|
517
|
-
|
|
518
|
-
if dest_group.read_only:
|
|
519
|
-
raise NgioValueError("Destination group is read only, cannot copy.")
|
|
520
|
-
if isinstance(src_group.store, LocalStore | FsspecStore) and isinstance(
|
|
521
|
-
dest_group.store, LocalStore | FsspecStore
|
|
522
|
-
):
|
|
523
|
-
_fsspec_copy(src_group.store, src_group.path, dest_group.store, dest_group.path)
|
|
524
|
-
return
|
|
525
|
-
if not suppress_warnings:
|
|
526
|
-
warnings.warn(
|
|
527
|
-
"Fsspec copy not possible, falling back to Zarr Python API for the copy. "
|
|
528
|
-
"This will preserve some tabular data non-zarr native (parquet, and csv), "
|
|
529
|
-
"and it will be slower for large datasets.",
|
|
530
|
-
UserWarning,
|
|
531
|
-
stacklevel=2,
|
|
532
|
-
)
|
|
533
|
-
_zarr_python_copy(src_group, dest_group)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ngio
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.0a2
|
|
4
4
|
Summary: Next Generation file format IO
|
|
5
5
|
Project-URL: homepage, https://github.com/BioVisionCenter/ngio
|
|
6
6
|
Project-URL: repository, https://github.com/BioVisionCenter/ngio
|
|
@@ -13,9 +13,8 @@ Classifier: Programming Language :: Python :: 3
|
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.11
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.12
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.14
|
|
17
16
|
Classifier: Typing :: Typed
|
|
18
|
-
Requires-Python: <3.
|
|
17
|
+
Requires-Python: <3.14,>=3.11
|
|
19
18
|
Requires-Dist: aiohttp
|
|
20
19
|
Requires-Dist: anndata
|
|
21
20
|
Requires-Dist: dask[array]<2025.11.0
|
|
@@ -23,7 +22,7 @@ Requires-Dist: dask[distributed]<2025.11.0
|
|
|
23
22
|
Requires-Dist: filelock
|
|
24
23
|
Requires-Dist: numpy
|
|
25
24
|
Requires-Dist: ome-zarr-models
|
|
26
|
-
Requires-Dist: pandas
|
|
25
|
+
Requires-Dist: pandas>=1.2.0
|
|
27
26
|
Requires-Dist: pillow
|
|
28
27
|
Requires-Dist: polars
|
|
29
28
|
Requires-Dist: pooch
|
|
@@ -32,6 +31,7 @@ Requires-Dist: pydantic
|
|
|
32
31
|
Requires-Dist: requests
|
|
33
32
|
Requires-Dist: zarr>3
|
|
34
33
|
Provides-Extra: dev
|
|
34
|
+
Requires-Dist: devtools; extra == 'dev'
|
|
35
35
|
Requires-Dist: matplotlib; extra == 'dev'
|
|
36
36
|
Requires-Dist: mypy; extra == 'dev'
|
|
37
37
|
Requires-Dist: napari; extra == 'dev'
|
|
@@ -43,7 +43,6 @@ Requires-Dist: pyqt5; extra == 'dev'
|
|
|
43
43
|
Requires-Dist: rich; extra == 'dev'
|
|
44
44
|
Requires-Dist: ruff; extra == 'dev'
|
|
45
45
|
Requires-Dist: scikit-image; extra == 'dev'
|
|
46
|
-
Requires-Dist: zarrs; extra == 'dev'
|
|
47
46
|
Provides-Extra: docs
|
|
48
47
|
Requires-Dist: griffe-typingdoc; extra == 'docs'
|
|
49
48
|
Requires-Dist: markdown-exec[ansi]; extra == 'docs'
|
|
@@ -58,17 +57,11 @@ Requires-Dist: mkdocs-jupyter; extra == 'docs'
|
|
|
58
57
|
Requires-Dist: mkdocs-material; extra == 'docs'
|
|
59
58
|
Requires-Dist: mkdocstrings[python]; extra == 'docs'
|
|
60
59
|
Requires-Dist: rich; extra == 'docs'
|
|
61
|
-
Requires-Dist: ruff; extra == 'docs'
|
|
62
60
|
Requires-Dist: scikit-image; extra == 'docs'
|
|
63
61
|
Requires-Dist: tabulate; extra == 'docs'
|
|
64
62
|
Provides-Extra: test
|
|
65
|
-
Requires-Dist: boto; extra == 'test'
|
|
66
|
-
Requires-Dist: devtools; extra == 'test'
|
|
67
|
-
Requires-Dist: moto[server]; extra == 'test'
|
|
68
63
|
Requires-Dist: pytest; extra == 'test'
|
|
69
64
|
Requires-Dist: pytest-cov; extra == 'test'
|
|
70
|
-
Requires-Dist: pytest-httpserver; extra == 'test'
|
|
71
|
-
Requires-Dist: s3fs; extra == 'test'
|
|
72
65
|
Requires-Dist: scikit-image; extra == 'test'
|
|
73
66
|
Description-Content-Type: text/markdown
|
|
74
67
|
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
ngio/__init__.py,sha256=rEgnXuU6TCejUUGsxt4eKmjMhxjYh0fYBxWF4o5YjbE,1435
|
|
2
|
+
ngio/common/__init__.py,sha256=aPSuUbdGryrxbnlWrsVNe3LZoBAWC4GijR1BNH1UwuU,612
|
|
3
|
+
ngio/common/_dimensions.py,sha256=w8PYgyWxA8hgJETjFbw5CXf7WrasCL5FbzgfL1in86M,11361
|
|
4
|
+
ngio/common/_masking_roi.py,sha256=ZZTXordEZoq_ADk0OzADvq-5dPOwUBSuNobzFR8fpTw,5697
|
|
5
|
+
ngio/common/_pyramid.py,sha256=loQbtoGWs0g5Ke2s1tSBDsvos0235F-ElhFspsMsIr0,9238
|
|
6
|
+
ngio/common/_roi.py,sha256=9fKFTHoUiP0xmxvQiFkNmIuwWg3bFuRaAx-froCSqvA,11487
|
|
7
|
+
ngio/common/_synt_images_utils.py,sha256=B6uYOW1NyrM06YMR-csca3_YnAAkPRTbvnbLdy9tk9E,3188
|
|
8
|
+
ngio/common/_zoom.py,sha256=U01c-vqXjzZkrpd9Yvs24frVfTls_xPJeeaFCGmUwYI,6727
|
|
9
|
+
ngio/experimental/__init__.py,sha256=3pmBtHi-i8bKjTsvrOJM56ZyRX3Pv_dceCdt88-8COQ,147
|
|
10
|
+
ngio/experimental/iterators/__init__.py,sha256=TECOMGb5PEEZ0yXxt8pqIGvLKG41g_L1fTJU-zGPeV8,488
|
|
11
|
+
ngio/experimental/iterators/_abstract_iterator.py,sha256=7aAoMI-6vYGCMKxO3M10WpuBMTdqX4zr0K-TutAOp88,13195
|
|
12
|
+
ngio/experimental/iterators/_feature.py,sha256=g03yHIzYpTVeD3KUq2a4TwX29Dt48XaaGdZNSykYy7M,6749
|
|
13
|
+
ngio/experimental/iterators/_image_processing.py,sha256=cM7sL7xgdcjSOKAu-6367Aov89o6wgiJ_wqCGkU2Bsw,5091
|
|
14
|
+
ngio/experimental/iterators/_mappers.py,sha256=VVVsjems57wJUnWeufUFcgqa23k7VPeFL4Nc04HVw4o,1399
|
|
15
|
+
ngio/experimental/iterators/_rois_utils.py,sha256=Q-8lQ26neYn63h_RvfypYqvrq2UUN2O3xqVe57k_ufU,4363
|
|
16
|
+
ngio/experimental/iterators/_segmentation.py,sha256=xzotGvTn04HPeMeXZ_URnQqWco6d2lH6Ng6vkCUh9NM,9153
|
|
17
|
+
ngio/hcs/__init__.py,sha256=G8j9vD-liLeB_UeGtKYIgshWvJnUA6ks9GwjvWBLdHs,357
|
|
18
|
+
ngio/hcs/_plate.py,sha256=9kvvI_qu946xbRqWeY9q1bp45duREyOx-3a-QeKkrGU,43376
|
|
19
|
+
ngio/images/__init__.py,sha256=9Whvt7GTiCgT_vXaEEqGnDaY1-UsRk3dhLTv091F_g4,1211
|
|
20
|
+
ngio/images/_abstract_image.py,sha256=hrB9xn4MFRxnxE1d7HKnM8SXVPUGhMD9u32yBHTsFiU,18517
|
|
21
|
+
ngio/images/_create.py,sha256=IIdX0vER9J3c3aJYZRB7bDGMGv_kv0CbaJjGJM7yjyY,10536
|
|
22
|
+
ngio/images/_create_synt_container.py,sha256=HeRscNNWYHY3rJTO-oKDr5mMuQD6RHWThrv9Rc9yZdg,5539
|
|
23
|
+
ngio/images/_image.py,sha256=LP_XZrL0OLSasPTxaySldKSysyMZvznhFm-E3YLN5Tg,33488
|
|
24
|
+
ngio/images/_label.py,sha256=o7dFDfn-vAgBA80g-vR54M64av_tNebduQqtnG0AkIw,11926
|
|
25
|
+
ngio/images/_masked_image.py,sha256=YhbBzgPZMav6rX0WYue1BaxAzEIsfaQrxUIOK6ZWZcw,18848
|
|
26
|
+
ngio/images/_ome_zarr_container.py,sha256=IlXZojr9HDnfGboLAWD0TlV5Bv7J5fvzKqYc8U43WdU,38777
|
|
27
|
+
ngio/images/_table_ops.py,sha256=jFv_AMqoB4JBpoWsMtZppZVW7dAOC_u-JpfNm8b33kY,15292
|
|
28
|
+
ngio/io_pipes/__init__.py,sha256=arW_7GWzZs82kPNKdm_6B1sIDFV0lWwp-ZaORr9Q1FQ,2412
|
|
29
|
+
ngio/io_pipes/_io_pipes.py,sha256=KuwMYofE11EKx0iplWXBQZ-eE1A9YpGDprWh98cUlAI,10710
|
|
30
|
+
ngio/io_pipes/_io_pipes_masked.py,sha256=077j1XNgyCNOHlOsbjPOWcLtb2ccFvbLp-cPzWL1j3c,16999
|
|
31
|
+
ngio/io_pipes/_io_pipes_roi.py,sha256=cu_vd4MTDuyiabCWQ5ieMLI4v3tu_twSEe4X5-3bp84,4543
|
|
32
|
+
ngio/io_pipes/_io_pipes_types.py,sha256=xCeUd9rZe2wsgoZR1pUq6L4LSeawoPsb-9pmz5C6ztA,1393
|
|
33
|
+
ngio/io_pipes/_match_shape.py,sha256=eDy_Eqzld08m9zDuIjAvJnIhWh_HVjQS-5Pw9BMjdbw,13200
|
|
34
|
+
ngio/io_pipes/_ops_axes.py,sha256=Geg4ZXxB0njWWopX9YeiwRJJ9Ef2GKfG0NIUafOmi2c,10043
|
|
35
|
+
ngio/io_pipes/_ops_slices.py,sha256=hHMIOQ_niUSK9uFl8P2-10dP_K4GX3Do6vivN4fGRE0,14520
|
|
36
|
+
ngio/io_pipes/_ops_slices_utils.py,sha256=xjDaCVGmtME5Q0XSmGrY3nUKYgw5jOBQZW4YDq5s4vE,6580
|
|
37
|
+
ngio/io_pipes/_ops_transforms.py,sha256=uITs6v6sZ7DQ_Hpw3JdX8MuPOzir-bihvGzY84Qn4wY,2934
|
|
38
|
+
ngio/io_pipes/_zoom_transform.py,sha256=WBY1tO6_Qhf8FaDujfTdipuuqFf7PSi204wx5VKKs88,6884
|
|
39
|
+
ngio/ome_zarr_meta/__init__.py,sha256=tzxW2oVhfeMBVuv3XkcbOLzMnbDvUnie-AVsvSxRkdE,1265
|
|
40
|
+
ngio/ome_zarr_meta/_meta_handlers.py,sha256=P2Edraf2MlTMlwFOpXCkUqD1QTN2nTwGv5Ff0ab5csw,26715
|
|
41
|
+
ngio/ome_zarr_meta/ngio_specs/__init__.py,sha256=U2FqZR91Ob2N6CqKdyw-_Ll-wMgmGuPZGVRCr6wuRFY,1698
|
|
42
|
+
ngio/ome_zarr_meta/ngio_specs/_axes.py,sha256=gNzxCddn53m9dlNJlV5CL-aQS-nGJrbCDGfAp5L97LY,16412
|
|
43
|
+
ngio/ome_zarr_meta/ngio_specs/_channels.py,sha256=TDxIy-yVc2YaWPIFJRYnYwZbA8O5Ee_OiWppHYrEdpU,16647
|
|
44
|
+
ngio/ome_zarr_meta/ngio_specs/_dataset.py,sha256=CrHnjVWBGYPqErKkHR-E2DKrE3DmGznXMkd3Y9Z4uYo,3434
|
|
45
|
+
ngio/ome_zarr_meta/ngio_specs/_ngio_hcs.py,sha256=N1CGPOubwf0pvm8tiTnh-C1cOu9lToyDe3WagnEnPN4,17207
|
|
46
|
+
ngio/ome_zarr_meta/ngio_specs/_ngio_image.py,sha256=y44AVdB7IQD9t5yiZV6cXSvV9_-CGDiYrCfX3PeaclQ,16231
|
|
47
|
+
ngio/ome_zarr_meta/ngio_specs/_pixel_size.py,sha256=4VF1djY9T5tp6GCJXppFrUJwALI1XgIm0imoM5rNvdE,3876
|
|
48
|
+
ngio/ome_zarr_meta/v04/__init__.py,sha256=dJRzzxyYc81kf-0Hip_bqvbdManaM8XTdQX2meWyCSs,583
|
|
49
|
+
ngio/ome_zarr_meta/v04/_custom_models.py,sha256=5GxiDERvLuvq4QvApcA6EiKLS6hLFX1R0R_9rSaa85A,530
|
|
50
|
+
ngio/ome_zarr_meta/v04/_v04_spec_utils.py,sha256=xa3DT7VJJZyd-4EB-KGjlPcKkTmst_izTcoWj30mLiY,15766
|
|
51
|
+
ngio/ome_zarr_meta/v05/__init__.py,sha256=j6YuIKu2bxmhlhFCbhXg5UA4qD7V8CpyTAHl1vnIpq8,583
|
|
52
|
+
ngio/ome_zarr_meta/v05/_custom_models.py,sha256=ZN3bE9nwx4y3tElhsYafI4S2zp_WzdkQKcyuuBiaXXo,530
|
|
53
|
+
ngio/ome_zarr_meta/v05/_v05_spec_utils.py,sha256=vd9-EiZZjBpCXmwgLj8a1RWiwFpSjjxKBfbH8OpsG9M,16493
|
|
54
|
+
ngio/resources/__init__.py,sha256=4E4TXTNYEgRHt26C1XcC4pPobJJsmZRYm1Ml4uAuAkE,1664
|
|
55
|
+
ngio/resources/resource_model.py,sha256=eE1m0dyk-2psPC4X8Ifyan524QHUOd52TEQdvoU0m8I,861
|
|
56
|
+
ngio/resources/20200812-CardiomyocyteDifferentiation14-Cycle1_B03/mask.png,sha256=g3QmxQdmeciAtBe5cTCRfR6yw3keG9cBYfjizMo6EGo,11890
|
|
57
|
+
ngio/resources/20200812-CardiomyocyteDifferentiation14-Cycle1_B03/nuclei.png,sha256=Yw0k5pn2EHDMWTwyb7N51NX7WVk6-MlwfP9WZrhY-Ic,19446
|
|
58
|
+
ngio/resources/20200812-CardiomyocyteDifferentiation14-Cycle1_B03/raw.jpg,sha256=82lejQAIokj5w9g-qqhysDTWpHtNvJTkdURG_BjqIxQ,37743
|
|
59
|
+
ngio/tables/__init__.py,sha256=_BV3sclNMLITu_J8_3DkkUrCB6Kro0HzeWLDCD1ivKM,877
|
|
60
|
+
ngio/tables/_abstract_table.py,sha256=rwGa47TzbFmosucBWVfFq6JEXtgGvOdUVtU9DIelV88,8204
|
|
61
|
+
ngio/tables/_tables_container.py,sha256=BfwnCsJ3RGnQGRnRXO2XjdaYniL9sxO4HLiJYVgHkOs,12361
|
|
62
|
+
ngio/tables/backends/__init__.py,sha256=MwSRXNF1rWQBFOTDA_vT3oGoNZpviVgytsL5Txnu08I,1619
|
|
63
|
+
ngio/tables/backends/_abstract_backend.py,sha256=M1ogsBpWBiQMV65YweZhA845PAtkzG2BsZCPN_7Xp8U,7613
|
|
64
|
+
ngio/tables/backends/_anndata.py,sha256=KBzXVxaXstVx3ofcLYYFm8ECVFDaHxfUWcKdg5vQPqY,2992
|
|
65
|
+
ngio/tables/backends/_anndata_utils.py,sha256=g0mIfihXd4p75bvMvCYTljBKTP13EZ9p_SVMifDKE3Y,3208
|
|
66
|
+
ngio/tables/backends/_csv.py,sha256=Ev61D-AUKo4LIhXRmWPJgYbHI7eQdxiajQR574DevEM,932
|
|
67
|
+
ngio/tables/backends/_json.py,sha256=1ZsEuXDJm1rOZV_KjFm8CB0qhv7L1W7L2EGWPf4q_p0,3137
|
|
68
|
+
ngio/tables/backends/_non_zarr_backends.py,sha256=5a1fbxiVnUXt1tiA025BqN0T7SQJvIERFtQHp4PhFHw,7294
|
|
69
|
+
ngio/tables/backends/_parquet.py,sha256=ic-p86h8lce8q9luBJGRzy6vxlWyJvA0-2l5cUD6OqY,1398
|
|
70
|
+
ngio/tables/backends/_table_backends.py,sha256=ksP2NAosXZkNMZf-IMrLx7bjQgp_eKfvPYK4vMdT1A8,7250
|
|
71
|
+
ngio/tables/backends/_utils.py,sha256=t4dLXSPxx2AnJvVtj0GIwrLoO11h4Ges6U7hj4md0hY,19730
|
|
72
|
+
ngio/tables/v1/__init__.py,sha256=Wr1_9RZFpaN8FYMTnxT9Yjkw4AS7y9FMWailmB_uj5g,617
|
|
73
|
+
ngio/tables/v1/_condition_table.py,sha256=T0Uq5BKkmMoEspt_Rx0U99Ow6S9GAMZDHqvUO5obCAM,1780
|
|
74
|
+
ngio/tables/v1/_feature_table.py,sha256=n9uMHwoBh-_dlOhUXCFbmAjXFVXncNCR3SjE2qzXI68,3821
|
|
75
|
+
ngio/tables/v1/_generic_table.py,sha256=1ktJHeuv7U1g5Z8PFUuTkCjOzcYMQd8xegKHKUedJB8,1240
|
|
76
|
+
ngio/tables/v1/_roi_table.py,sha256=b7lwjsdCSUOCMT6Lx4hwAqGBKC25Q5bdzoK3DQWnAQM,17074
|
|
77
|
+
ngio/transforms/__init__.py,sha256=JA0-Ui7skbXkm9ofN-AEhU1FTLutkMkwTdVD-310frQ,113
|
|
78
|
+
ngio/transforms/_zoom.py,sha256=otyE-vxFnywUJ8U4mHjat-bNG_7_jv62ckTpqDMxyVQ,550
|
|
79
|
+
ngio/utils/__init__.py,sha256=w_v3BaphrlsVlZF3tZHlyp6dOfRdRHaauBmdwGsjaCE,1174
|
|
80
|
+
ngio/utils/_cache.py,sha256=Ey9fgc_BTdMyqg6c80C0CuGDhOafln8-3e_1MQ0MFzw,1283
|
|
81
|
+
ngio/utils/_datasets.py,sha256=6GtxfPkjutNaeg5BHuJDBP0GudvQXHLU6mmHp_o0bGA,5650
|
|
82
|
+
ngio/utils/_errors.py,sha256=pKQ12LUjQLYE1nUawemA5h7HsgznjaSvV1n2PQU33N0,759
|
|
83
|
+
ngio/utils/_fractal_fsspec_store.py,sha256=RdcCFOgHexRKX9zZvJV5RI-5OPc7VOPS6q_IeRxm24I,1548
|
|
84
|
+
ngio/utils/_logger.py,sha256=N5W0a_xwze4blS1MolidBkTMbjTbg8GPguJZNun3mAE,1392
|
|
85
|
+
ngio/utils/_zarr_utils.py,sha256=Ak3M07hxI9-5W1mG2jxZE8rUrSZnidJ-nEQenKuCqls,14114
|
|
86
|
+
ngio-0.5.0a2.dist-info/METADATA,sha256=Skm_1lG1u3unJ7Ij9mnIYm8RVyU0P-AFISHvl-HEz2M,6124
|
|
87
|
+
ngio-0.5.0a2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
88
|
+
ngio-0.5.0a2.dist-info/licenses/LICENSE,sha256=UgN_a1QCeNh9rZWfz-wORQFxE3elQzLWPQaoK6N6fxQ,1502
|
|
89
|
+
ngio-0.5.0a2.dist-info/RECORD,,
|