torch_em.util.image

  1import os
  2from typing import Optional, Sequence, Union
  3
  4import imageio.v3 as imageio
  5import numpy as np
  6from elf.io import open_file
  7from numpy.typing import ArrayLike
  8
  9try:
 10    import tifffile
 11except ImportError:
 12    tifffile = None
 13
 14TIF_EXTS = (".tif", ".tiff")
 15
 16
 17def supports_memmap(image_path):
 18    """@private
 19    """
 20    if tifffile is None:
 21        return False
 22    ext = os.path.splitext(image_path)[1]
 23    if ext.lower() not in TIF_EXTS:
 24        return False
 25    try:
 26        tifffile.memmap(image_path, mode="r")
 27    except ValueError:
 28        return False
 29    return True
 30
 31
 32def load_image(image_path, memmap=True):
 33    """@private
 34    """
 35    if supports_memmap(image_path) and memmap:
 36        return tifffile.memmap(image_path, mode="r")
 37    elif tifffile is not None and os.path.splitext(image_path)[1].lower() in (".tiff", ".tif"):
 38        return tifffile.imread(image_path)
 39    elif os.path.splitext(image_path)[1].lower() == ".nrrd":
 40        import nrrd
 41        return nrrd.read(image_path)[0]
 42    elif os.path.splitext(image_path)[1].lower() == ".mha":
 43        import SimpleITK as sitk
 44        image = sitk.ReadImage(image_path)
 45        return sitk.GetArrayFromImage(image)
 46    else:
 47        return imageio.imread(image_path)
 48
 49
 50class MultiDatasetWrapper:
 51    """@private
 52    """
 53    def __init__(self, *file_datasets):
 54        # Make sure we have the same shapes.
 55        reference_shape = file_datasets[0].shape
 56        assert all(reference_shape == ds.shape for ds in file_datasets)
 57        self.file_datasets = file_datasets
 58
 59        self.shape = (len(self.file_datasets),) + reference_shape
 60
 61    def __getitem__(self, index):
 62        channel_index, spatial_index = index[:1], index[1:]
 63        data = []
 64        for ds in self.file_datasets:
 65            ds_data = ds[spatial_index]
 66            data.append(ds_data)
 67        data = np.stack(data)
 68        data = data[channel_index]
 69        return data
 70
 71
 72def load_data(
 73    path: Union[str, Sequence[str]],
 74    key: Optional[Union[str, Sequence[str]]] = None,
 75    mode: str = "r",
 76) -> ArrayLike:
 77    """Load data from a file or multiple files.
 78
 79    Supports loading regular image formats, such as tif or jpg, or container data formats, such as hdf5, n5 or zarr.
 80    For the latter case, specify the name of the internal dataset to load via the `key` argument.
 81
 82    Args:
 83        path: The file path or paths to the data.
 84        key: The key or keys to the internal datasets.
 85        mode: The mode for reading datasets.
 86
 87    Returns:
 88        The loaded data.
 89    """
 90    have_single_file = isinstance(path, str)
 91    have_single_key = isinstance(key, str)
 92
 93    # mrc files require key="data"; set it automatically if no key was provided
 94    if key is None:
 95        if have_single_file and str(path).endswith(".mrc"):
 96            key = "data"
 97            have_single_key = True
 98        elif not have_single_file and all(str(p).endswith(".mrc") for p in path):
 99            key = "data"
100            have_single_key = True
101
102    if key is None:
103        if have_single_file:
104            return load_image(path)
105        else:
106            return np.stack([load_image(p) for p in path])
107    else:
108        if have_single_key and have_single_file:
109            return open_file(path, mode=mode)[key]
110        elif have_single_key and not have_single_file:
111            return MultiDatasetWrapper(*[open_file(p, mode=mode)[key] for p in path])
112        elif not have_single_key and have_single_file:
113            return MultiDatasetWrapper(*[open_file(path, mode=mode)[k] for k in key])
114        else:  # have multipe keys and multiple files
115            return MultiDatasetWrapper(*[open_file(p, mode=mode)[k] for k in key for p in path])
TIF_EXTS = ('.tif', '.tiff')
def load_data( path: Union[str, Sequence[str]], key: Union[str, Sequence[str], NoneType] = None, mode: str = 'r') -> ArrayLike:
 73def load_data(
 74    path: Union[str, Sequence[str]],
 75    key: Optional[Union[str, Sequence[str]]] = None,
 76    mode: str = "r",
 77) -> ArrayLike:
 78    """Load data from a file or multiple files.
 79
 80    Supports loading regular image formats, such as tif or jpg, or container data formats, such as hdf5, n5 or zarr.
 81    For the latter case, specify the name of the internal dataset to load via the `key` argument.
 82
 83    Args:
 84        path: The file path or paths to the data.
 85        key: The key or keys to the internal datasets.
 86        mode: The mode for reading datasets.
 87
 88    Returns:
 89        The loaded data.
 90    """
 91    have_single_file = isinstance(path, str)
 92    have_single_key = isinstance(key, str)
 93
 94    # mrc files require key="data"; set it automatically if no key was provided
 95    if key is None:
 96        if have_single_file and str(path).endswith(".mrc"):
 97            key = "data"
 98            have_single_key = True
 99        elif not have_single_file and all(str(p).endswith(".mrc") for p in path):
100            key = "data"
101            have_single_key = True
102
103    if key is None:
104        if have_single_file:
105            return load_image(path)
106        else:
107            return np.stack([load_image(p) for p in path])
108    else:
109        if have_single_key and have_single_file:
110            return open_file(path, mode=mode)[key]
111        elif have_single_key and not have_single_file:
112            return MultiDatasetWrapper(*[open_file(p, mode=mode)[key] for p in path])
113        elif not have_single_key and have_single_file:
114            return MultiDatasetWrapper(*[open_file(path, mode=mode)[k] for k in key])
115        else:  # have multipe keys and multiple files
116            return MultiDatasetWrapper(*[open_file(p, mode=mode)[k] for k in key for p in path])

Load data from a file or multiple files.

Supports loading regular image formats, such as tif or jpg, or container data formats, such as hdf5, n5 or zarr. For the latter case, specify the name of the internal dataset to load via the key argument.

Arguments:
  • path: The file path or paths to the data.
  • key: The key or keys to the internal datasets.
  • mode: The mode for reading datasets.
Returns:

The loaded data.