bioimage_py.io

Native file-format IO layer: array-like handles for hdf5, zarr, n5, mrc, nifti, msr, tif, knossos.

Indexing contract: the assemble-from-pieces wrappers (nifti, knossos, msr, image-stack) accept only integer, slice (step 1), and ellipsis indices -- non-trivial steps (e.g. src[::2]) are rejected, unlike numpy / zarr / mrc which support them. Index these formats with contiguous slices.

 1"""Native file-format IO layer: array-like handles for hdf5, zarr, n5, mrc, nifti, msr, tif, knossos.
 2
 3Indexing contract: the assemble-from-pieces wrappers (nifti, knossos, msr, image-stack) accept only
 4integer, slice (step 1), and ellipsis indices -- non-trivial steps (e.g. ``src[::2]``) are rejected,
 5unlike numpy / zarr / mrc which support them. Index these formats with contiguous slices.
 6"""
 7from .files import infer_format, open_file
 8from .registry import (
 9    constructor_for_format,
10    format_for_extension,
11    is_writable_format,
12    register_format,
13    supported_extensions,
14    supported_formats,
15)
16
17__all__ = [
18    "open_file",
19    "infer_format",
20    "register_format",
21    "supported_extensions",
22    "supported_formats",
23    "format_for_extension",
24    "constructor_for_format",
25    "is_writable_format",
26]
def open_file( path: Union[os.PathLike, str], mode: str = 'r', ext: Optional[str] = None, format: Optional[str] = None, **kwargs: Any) -> Any:
58def open_file(
59    path: PathLike,
60    mode: str = "r",
61    ext: Optional[str] = None,
62    format: Optional[str] = None,
63    **kwargs: Any,
64) -> Any:
65    """Open a file as an array-like handle, dispatching on the (inferred) format.
66
67    Args:
68        path: Path to the file or folder to open.
69        mode: Mode in which to open the file. ``"r"`` (read) is supported by all formats; some
70            formats also support write modes (``"a"``, ``"w"``).
71        ext: Force a specific extension when it cannot be inferred from ``path``.
72        format: Force a specific (registered) format name, overriding extension inference.
73        kwargs: Extra keyword arguments forwarded to the backend constructor.
74
75    Returns:
76        A file handle (a mapping of datasets, or an array-like dataset).
77    """
78    fmt = format if format is not None else infer_format(path, ext)
79    constructor = constructor_for_format(fmt)
80    return constructor(path, mode=mode, **kwargs)

Open a file as an array-like handle, dispatching on the (inferred) format.

Args: path: Path to the file or folder to open. mode: Mode in which to open the file. "r" (read) is supported by all formats; some formats also support write modes ("a", "w"). ext: Force a specific extension when it cannot be inferred from path. format: Force a specific (registered) format name, overriding extension inference. kwargs: Extra keyword arguments forwarded to the backend constructor.

Returns: A file handle (a mapping of datasets, or an array-like dataset).

def infer_format(path: Union[os.PathLike, str], ext: Optional[str] = None) -> str:
34def infer_format(path: PathLike, ext: Optional[str] = None) -> str:
35    """Infer the format name for a path (optionally with an explicit extension).
36
37    Args:
38        path: The path to open.
39        ext: An explicit extension to force, overriding inference from ``path``.
40
41    Returns:
42        The registered format name.
43
44    Raises:
45        ValueError: If no installed backend handles the (inferred) extension.
46    """
47    ext = infer_extension(path) if ext is None else ext.lower()
48    fmt = format_for_extension(ext)
49    if fmt is None:
50        raise ValueError(
51            f"Could not infer a file format from extension {ext!r}; "
52            f"it is not among the supported extensions: {sorted(supported_extensions())}. "
53            "You may need to install an additional dependency (h5py, z5py, zarr, mrcfile, nibabel, ...)."
54        )
55    return fmt

Infer the format name for a path (optionally with an explicit extension).

Args: path: The path to open. ext: An explicit extension to force, overriding inference from path.

Returns: The registered format name.

Raises: ValueError: If no installed backend handles the (inferred) extension.

def register_format( name: str, extensions: Sequence[str], constructor: Callable, *, writable: bool = False) -> None:
17def register_format(
18    name: str,
19    extensions: Sequence[str],
20    constructor: Callable,
21    *,
22    writable: bool = False,
23) -> None:
24    """Register a file-format backend.
25
26    Args:
27        name: The format name, recorded in the source spec (e.g. ``"hdf5"``, ``"mrc"``).
28        extensions: The file extensions this format claims (lower-case; ``""`` for folders).
29        constructor: A callable ``(path, mode="r", **kwargs)`` returning an array-like file handle.
30        writable: Whether the format supports writing.
31    """
32    _FORMAT_TO_CONSTRUCTOR[name] = constructor
33    _FORMAT_WRITABLE[name] = writable
34    for ext in extensions:
35        _EXT_TO_FORMAT.setdefault(ext.lower(), name)

Register a file-format backend.

Args: name: The format name, recorded in the source spec (e.g. "hdf5", "mrc"). extensions: The file extensions this format claims (lower-case; "" for folders). constructor: A callable (path, mode="r", **kwargs) returning an array-like file handle. writable: Whether the format supports writing.

def supported_extensions() -> List[str]:
43def supported_extensions() -> List[str]:
44    """Return all file extensions for which a backend is installed."""
45    return list(_EXT_TO_FORMAT.keys())

Return all file extensions for which a backend is installed.

def supported_formats() -> List[str]:
38def supported_formats() -> List[str]:
39    """Return the names of all registered (i.e. installed) formats."""
40    return list(_FORMAT_TO_CONSTRUCTOR.keys())

Return the names of all registered (i.e. installed) formats.

def format_for_extension(ext: str) -> Optional[str]:
48def format_for_extension(ext: str) -> Optional[str]:
49    """Return the format name registered for ``ext``, or ``None``."""
50    return _EXT_TO_FORMAT.get(ext.lower())

Return the format name registered for ext, or None.

def constructor_for_format(name: str) -> Callable:
53def constructor_for_format(name: str) -> Callable:
54    """Return the file constructor for a registered format, raising a clear error otherwise."""
55    try:
56        return _FORMAT_TO_CONSTRUCTOR[name]
57    except KeyError:
58        raise ValueError(
59            f"Unknown or unavailable format {name!r}. Supported formats: {sorted(supported_formats())}. "
60            "You may need to install the corresponding optional dependency."
61        )

Return the file constructor for a registered format, raising a clear error otherwise.

def is_writable_format(name: str) -> bool:
64def is_writable_format(name: str) -> bool:
65    """Return whether a registered format supports writing."""
66    return _FORMAT_WRITABLE.get(name, False)

Return whether a registered format supports writing.