torch_em.data.datasets.electron_microscopy.snemi_mito

The SNEMI Mito dataset contains annotations for mitochondria segmentation in electron microscopy (EM) images of mouse neocortex.

It provides mitochondria labels for the sections of the SNEMI3D challenge volume, which comes from the publication https://doi.org/10.1016/j.cell.2015.06.054. The data consists of 100 images (1024 x 1024 pixels, 8-bit, CLAHE contrast enhanced) that are split into 50 train, 20 validation and 30 test images. The images are consecutive sections of the volume (6 x 6 x 30 nm), so they can also be used as one 3D volume. The volume is stored as snemi_mito.h5 with 'raw' and binary 'labels', and the splits are its ROIs in VOLUME_ROIS.

The data is available at https://github.com/sumiya-kuroda/EMsegmentation-mito/tree/master/dataset/SNEMI3D_mito. The repository does not state a license. The mitochondria labels were prepared by members of the Kubota lab (see the repository for details). Please cite the SNEMI3D / Kasthuri et al. publication and the repository if you use this dataset in your research.

  1"""The SNEMI Mito dataset contains annotations for mitochondria segmentation in electron microscopy (EM)
  2images of mouse neocortex.
  3
  4It provides mitochondria labels for the sections of the SNEMI3D challenge volume, which comes from the publication
  5https://doi.org/10.1016/j.cell.2015.06.054. The data consists of 100 images (1024 x 1024 pixels, 8-bit, CLAHE contrast
  6enhanced) that are split into 50 train, 20 validation and 30 test images.
  7The images are consecutive sections of the volume (6 x 6 x 30 nm), so they can also be used as one 3D volume.
  8The volume is stored as `snemi_mito.h5` with 'raw' and binary 'labels', and the splits are its ROIs in `VOLUME_ROIS`.
  9
 10The data is available at https://github.com/sumiya-kuroda/EMsegmentation-mito/tree/master/dataset/SNEMI3D_mito.
 11The repository does not state a license. The mitochondria labels were prepared by members of the Kubota lab
 12(see the repository for details). Please cite the SNEMI3D / Kasthuri et al. publication and the repository
 13if you use this dataset in your research.
 14"""
 15
 16import os
 17import shutil
 18from glob import glob
 19from typing import List, Tuple, Union
 20
 21import h5py
 22import numpy as np
 23import imageio.v3 as imageio
 24from natsort import natsorted
 25
 26from torch.utils.data import Dataset, DataLoader
 27
 28import torch_em
 29
 30from .. import util
 31
 32
 33# The archive is pinned to a commit, so that the checksum does not change with new commits to the repository.
 34URL = "https://github.com/sumiya-kuroda/EMsegmentation-mito/archive/44134f6dc27b1ad7f04293398e482fec854bb658.zip"
 35CHECKSUM = "1d560ad05d0faab8e6fedd9347131c2a0f395dcdba079f8699a66c3e39d80a25"
 36SPLITS = {"train": "train", "val": "valid", "test": "test"}
 37# The splits are contiguous ranges of sections in the volume.
 38VOLUME_ROIS = {"train": np.s_[0:50, :, :], "val": np.s_[50:70, :, :], "test": np.s_[70:100, :, :]}
 39
 40
 41def _convert_rgba_labels(data_dir):
 42    """Convert the label images that are stored as RGBA, with the gray values in every channel, to one channel."""
 43    from PIL import Image
 44
 45    for label_path in glob(os.path.join(data_dir, "*", "labels", "*.png")):
 46        with Image.open(label_path) as image:
 47            if image.mode != "RGBA":
 48                continue
 49            labels = image.getchannel(0)
 50        labels.save(label_path)
 51
 52
 53def _create_volume(data_dir, volume_path):
 54    raw_paths, label_paths = [], []
 55    for split in SPLITS.values():
 56        raw_paths.extend(natsorted(glob(os.path.join(data_dir, split, "images", "*.png"))))
 57        label_paths.extend(natsorted(glob(os.path.join(data_dir, split, "labels", "*.png"))))
 58    names = [os.path.basename(raw_path) for raw_path in raw_paths]
 59    assert names == [os.path.basename(label_path) for label_path in label_paths]
 60    assert names == [f"{i:04}.png" for i in range(len(names))], "The sections are not consecutive."
 61
 62    raw = np.stack([imageio.imread(raw_path) for raw_path in raw_paths])
 63    labels = np.stack([imageio.imread(label_path) > 0 for label_path in label_paths]).astype("uint8")
 64
 65    tmp_path = f"{volume_path}.incomplete"
 66    with h5py.File(tmp_path, "w") as f:
 67        f.create_dataset("raw", data=raw, compression="gzip", chunks=(8, 256, 256))
 68        f.create_dataset("labels", data=labels, compression="gzip", chunks=(8, 256, 256))
 69        f.attrs["voxel_size_nm"] = [30, 6, 6]
 70    os.replace(tmp_path, volume_path)
 71
 72
 73def _download_data(path, data_dir, download):
 74    os.makedirs(path, exist_ok=True)
 75    zip_path = os.path.join(path, "snemi_mito.zip")
 76    util.download_source(zip_path, URL, download, checksum=CHECKSUM)
 77
 78    # The archive contains the whole repository, we only keep the SNEMI3D_mito folder.
 79    tmp_dir = os.path.join(path, "tmp")
 80    util.unzip(zip_path, tmp_dir, remove=True)
 81    extracted = glob(os.path.join(tmp_dir, "*", "dataset", "SNEMI3D_mito"))
 82    assert len(extracted) == 1, "Unexpected structure of the downloaded archive."
 83    shutil.move(extracted[0], data_dir)
 84    shutil.rmtree(tmp_dir)
 85
 86
 87def get_snemi_mito_data(path: Union[os.PathLike, str], download: bool = False, as_volume: bool = False) -> str:
 88    """Download the SNEMI Mito dataset.
 89
 90    Args:
 91        path: Filepath to a folder where the downloaded data will be saved.
 92        download: Whether to download the data if it is not present.
 93        as_volume: Whether to stack the sections into one 3D volume.
 94
 95    Returns:
 96        The filepath to the folder with the data, or the filepath to the volume if `as_volume` is set.
 97    """
 98    data_dir = os.path.join(path, "SNEMI3D_mito")
 99    volume_path = os.path.join(path, "snemi_mito.h5")
100    if as_volume and os.path.exists(volume_path):
101        return volume_path
102
103    if not os.path.exists(data_dir):
104        _download_data(path, data_dir, download)
105    _convert_rgba_labels(data_dir)
106
107    if as_volume:
108        _create_volume(data_dir, volume_path)
109        return volume_path
110    return data_dir
111
112
113def get_snemi_mito_paths(
114    path: Union[os.PathLike, str], split: str, download: bool = False, as_volume: bool = False
115) -> Union[Tuple[List[str], List[str]], Tuple[str, Tuple[slice, ...]]]:
116    """Get paths to the SNEMI Mito data.
117
118    Args:
119        path: Filepath to a folder where the downloaded data will be saved.
120        split: The data split to use. Either 'train', 'val' or 'test'.
121        download: Whether to download the data if it is not present.
122        as_volume: Whether to return the 3D volume and the ROI of the split instead of the 2D images.
123
124    Returns:
125        List of filepaths for the image data, or the filepath to the volume if `as_volume` is set.
126        List of filepaths for the label data, or the ROI of the split in the volume if `as_volume` is set.
127    """
128    if split not in SPLITS:
129        raise ValueError(f"'{split}' is not a valid split. Please choose from {list(SPLITS.keys())}.")
130
131    if as_volume:
132        return get_snemi_mito_data(path, download, as_volume=True), VOLUME_ROIS[split]
133
134    data_dir = get_snemi_mito_data(path, download)
135    raw_paths = natsorted(glob(os.path.join(data_dir, SPLITS[split], "images", "*.png")))
136    label_paths = natsorted(glob(os.path.join(data_dir, SPLITS[split], "labels", "*.png")))
137    assert len(raw_paths) > 0 and len(raw_paths) == len(label_paths)
138
139    return raw_paths, label_paths
140
141
142def _binary_labels(labels):
143    return (labels > 0).astype("uint8")
144
145
146def get_snemi_mito_dataset(
147    path: Union[os.PathLike, str],
148    patch_shape: Tuple[int, int],
149    split: str,
150    binary: bool = True,
151    download: bool = False,
152    as_volume: bool = False,
153    **kwargs
154) -> Dataset:
155    """Get the SNEMI Mito dataset for mitochondria segmentation in EM.
156
157    Args:
158        path: Filepath to a folder where the downloaded data will be saved.
159        patch_shape: The patch shape to use for training.
160        split: The data split to use. Either 'train', 'val' or 'test'.
161        binary: Whether to return a binary foreground mask. Otherwise the mask values are returned as they are.
162            The labels of the volume are always binary.
163        download: Whether to download the data if it is not present.
164        as_volume: Whether to use the split of the 3D volume instead of the 2D images.
165        kwargs: Additional keyword arguments for `torch_em.default_segmentation_dataset`.
166
167    Returns:
168        The segmentation dataset.
169    """
170    if as_volume:
171        volume_path, roi = get_snemi_mito_paths(path, split, download, as_volume=True)
172        return torch_em.default_segmentation_dataset(
173            raw_paths=volume_path,
174            raw_key="raw",
175            label_paths=volume_path,
176            label_key="labels",
177            patch_shape=patch_shape,
178            rois=roi,
179            is_seg_dataset=True,
180            **kwargs
181        )
182
183    raw_paths, label_paths = get_snemi_mito_paths(path, split, download)
184
185    if binary:
186        kwargs = util.update_kwargs(kwargs, "label_transform", _binary_labels)
187
188    return torch_em.default_segmentation_dataset(
189        raw_paths=raw_paths,
190        raw_key=None,
191        label_paths=label_paths,
192        label_key=None,
193        patch_shape=patch_shape,
194        is_seg_dataset=False,
195        **kwargs
196    )
197
198
199def get_snemi_mito_loader(
200    path: Union[os.PathLike, str],
201    batch_size: int,
202    patch_shape: Tuple[int, int],
203    split: str,
204    binary: bool = True,
205    download: bool = False,
206    as_volume: bool = False,
207    **kwargs
208) -> DataLoader:
209    """Get the SNEMI Mito dataloader for mitochondria segmentation in EM.
210
211    Args:
212        path: Filepath to a folder where the downloaded data will be saved.
213        batch_size: The batch size for training.
214        patch_shape: The patch shape to use for training.
215        split: The data split to use. Either 'train', 'val' or 'test'.
216        binary: Whether to return a binary foreground mask. Otherwise the mask values are returned as they are.
217            The labels of the volume are always binary.
218        download: Whether to download the data if it is not present.
219        as_volume: Whether to use the split of the 3D volume instead of the 2D images.
220        kwargs: Additional keyword arguments for `torch_em.default_segmentation_dataset` or for the PyTorch DataLoader.
221
222    Returns:
223        The DataLoader.
224    """
225    ds_kwargs, loader_kwargs = util.split_kwargs(torch_em.default_segmentation_dataset, **kwargs)
226    dataset = get_snemi_mito_dataset(path, patch_shape, split, binary, download, as_volume, **ds_kwargs)
227    return torch_em.get_data_loader(dataset, batch_size, **loader_kwargs)
URL = 'https://github.com/sumiya-kuroda/EMsegmentation-mito/archive/44134f6dc27b1ad7f04293398e482fec854bb658.zip'
CHECKSUM = '1d560ad05d0faab8e6fedd9347131c2a0f395dcdba079f8699a66c3e39d80a25'
SPLITS = {'train': 'train', 'val': 'valid', 'test': 'test'}
VOLUME_ROIS = {'train': (slice(0, 50, None), slice(None, None, None), slice(None, None, None)), 'val': (slice(50, 70, None), slice(None, None, None), slice(None, None, None)), 'test': (slice(70, 100, None), slice(None, None, None), slice(None, None, None))}
def get_snemi_mito_data( path: Union[os.PathLike, str], download: bool = False, as_volume: bool = False) -> str:
 88def get_snemi_mito_data(path: Union[os.PathLike, str], download: bool = False, as_volume: bool = False) -> str:
 89    """Download the SNEMI Mito dataset.
 90
 91    Args:
 92        path: Filepath to a folder where the downloaded data will be saved.
 93        download: Whether to download the data if it is not present.
 94        as_volume: Whether to stack the sections into one 3D volume.
 95
 96    Returns:
 97        The filepath to the folder with the data, or the filepath to the volume if `as_volume` is set.
 98    """
 99    data_dir = os.path.join(path, "SNEMI3D_mito")
100    volume_path = os.path.join(path, "snemi_mito.h5")
101    if as_volume and os.path.exists(volume_path):
102        return volume_path
103
104    if not os.path.exists(data_dir):
105        _download_data(path, data_dir, download)
106    _convert_rgba_labels(data_dir)
107
108    if as_volume:
109        _create_volume(data_dir, volume_path)
110        return volume_path
111    return data_dir

Download the SNEMI Mito dataset.

Arguments:
  • path: Filepath to a folder where the downloaded data will be saved.
  • download: Whether to download the data if it is not present.
  • as_volume: Whether to stack the sections into one 3D volume.
Returns:

The filepath to the folder with the data, or the filepath to the volume if as_volume is set.

def get_snemi_mito_paths( path: Union[os.PathLike, str], split: str, download: bool = False, as_volume: bool = False) -> Union[Tuple[List[str], List[str]], Tuple[str, Tuple[slice, ...]]]:
114def get_snemi_mito_paths(
115    path: Union[os.PathLike, str], split: str, download: bool = False, as_volume: bool = False
116) -> Union[Tuple[List[str], List[str]], Tuple[str, Tuple[slice, ...]]]:
117    """Get paths to the SNEMI Mito data.
118
119    Args:
120        path: Filepath to a folder where the downloaded data will be saved.
121        split: The data split to use. Either 'train', 'val' or 'test'.
122        download: Whether to download the data if it is not present.
123        as_volume: Whether to return the 3D volume and the ROI of the split instead of the 2D images.
124
125    Returns:
126        List of filepaths for the image data, or the filepath to the volume if `as_volume` is set.
127        List of filepaths for the label data, or the ROI of the split in the volume if `as_volume` is set.
128    """
129    if split not in SPLITS:
130        raise ValueError(f"'{split}' is not a valid split. Please choose from {list(SPLITS.keys())}.")
131
132    if as_volume:
133        return get_snemi_mito_data(path, download, as_volume=True), VOLUME_ROIS[split]
134
135    data_dir = get_snemi_mito_data(path, download)
136    raw_paths = natsorted(glob(os.path.join(data_dir, SPLITS[split], "images", "*.png")))
137    label_paths = natsorted(glob(os.path.join(data_dir, SPLITS[split], "labels", "*.png")))
138    assert len(raw_paths) > 0 and len(raw_paths) == len(label_paths)
139
140    return raw_paths, label_paths

Get paths to the SNEMI Mito data.

Arguments:
  • path: Filepath to a folder where the downloaded data will be saved.
  • split: The data split to use. Either 'train', 'val' or 'test'.
  • download: Whether to download the data if it is not present.
  • as_volume: Whether to return the 3D volume and the ROI of the split instead of the 2D images.
Returns:

List of filepaths for the image data, or the filepath to the volume if as_volume is set. List of filepaths for the label data, or the ROI of the split in the volume if as_volume is set.

def get_snemi_mito_dataset( path: Union[os.PathLike, str], patch_shape: Tuple[int, int], split: str, binary: bool = True, download: bool = False, as_volume: bool = False, **kwargs) -> torch.utils.data.dataset.Dataset:
147def get_snemi_mito_dataset(
148    path: Union[os.PathLike, str],
149    patch_shape: Tuple[int, int],
150    split: str,
151    binary: bool = True,
152    download: bool = False,
153    as_volume: bool = False,
154    **kwargs
155) -> Dataset:
156    """Get the SNEMI Mito dataset for mitochondria segmentation in EM.
157
158    Args:
159        path: Filepath to a folder where the downloaded data will be saved.
160        patch_shape: The patch shape to use for training.
161        split: The data split to use. Either 'train', 'val' or 'test'.
162        binary: Whether to return a binary foreground mask. Otherwise the mask values are returned as they are.
163            The labels of the volume are always binary.
164        download: Whether to download the data if it is not present.
165        as_volume: Whether to use the split of the 3D volume instead of the 2D images.
166        kwargs: Additional keyword arguments for `torch_em.default_segmentation_dataset`.
167
168    Returns:
169        The segmentation dataset.
170    """
171    if as_volume:
172        volume_path, roi = get_snemi_mito_paths(path, split, download, as_volume=True)
173        return torch_em.default_segmentation_dataset(
174            raw_paths=volume_path,
175            raw_key="raw",
176            label_paths=volume_path,
177            label_key="labels",
178            patch_shape=patch_shape,
179            rois=roi,
180            is_seg_dataset=True,
181            **kwargs
182        )
183
184    raw_paths, label_paths = get_snemi_mito_paths(path, split, download)
185
186    if binary:
187        kwargs = util.update_kwargs(kwargs, "label_transform", _binary_labels)
188
189    return torch_em.default_segmentation_dataset(
190        raw_paths=raw_paths,
191        raw_key=None,
192        label_paths=label_paths,
193        label_key=None,
194        patch_shape=patch_shape,
195        is_seg_dataset=False,
196        **kwargs
197    )

Get the SNEMI Mito dataset for mitochondria segmentation in EM.

Arguments:
  • path: Filepath to a folder where the downloaded data will be saved.
  • patch_shape: The patch shape to use for training.
  • split: The data split to use. Either 'train', 'val' or 'test'.
  • binary: Whether to return a binary foreground mask. Otherwise the mask values are returned as they are. The labels of the volume are always binary.
  • download: Whether to download the data if it is not present.
  • as_volume: Whether to use the split of the 3D volume instead of the 2D images.
  • kwargs: Additional keyword arguments for torch_em.default_segmentation_dataset.
Returns:

The segmentation dataset.

def get_snemi_mito_loader( path: Union[os.PathLike, str], batch_size: int, patch_shape: Tuple[int, int], split: str, binary: bool = True, download: bool = False, as_volume: bool = False, **kwargs) -> torch.utils.data.dataloader.DataLoader:
200def get_snemi_mito_loader(
201    path: Union[os.PathLike, str],
202    batch_size: int,
203    patch_shape: Tuple[int, int],
204    split: str,
205    binary: bool = True,
206    download: bool = False,
207    as_volume: bool = False,
208    **kwargs
209) -> DataLoader:
210    """Get the SNEMI Mito dataloader for mitochondria segmentation in EM.
211
212    Args:
213        path: Filepath to a folder where the downloaded data will be saved.
214        batch_size: The batch size for training.
215        patch_shape: The patch shape to use for training.
216        split: The data split to use. Either 'train', 'val' or 'test'.
217        binary: Whether to return a binary foreground mask. Otherwise the mask values are returned as they are.
218            The labels of the volume are always binary.
219        download: Whether to download the data if it is not present.
220        as_volume: Whether to use the split of the 3D volume instead of the 2D images.
221        kwargs: Additional keyword arguments for `torch_em.default_segmentation_dataset` or for the PyTorch DataLoader.
222
223    Returns:
224        The DataLoader.
225    """
226    ds_kwargs, loader_kwargs = util.split_kwargs(torch_em.default_segmentation_dataset, **kwargs)
227    dataset = get_snemi_mito_dataset(path, patch_shape, split, binary, download, as_volume, **ds_kwargs)
228    return torch_em.get_data_loader(dataset, batch_size, **loader_kwargs)

Get the SNEMI Mito dataloader for mitochondria segmentation in EM.

Arguments:
  • path: Filepath to a folder where the downloaded data will be saved.
  • batch_size: The batch size for training.
  • patch_shape: The patch shape to use for training.
  • split: The data split to use. Either 'train', 'val' or 'test'.
  • binary: Whether to return a binary foreground mask. Otherwise the mask values are returned as they are. The labels of the volume are always binary.
  • download: Whether to download the data if it is not present.
  • as_volume: Whether to use the split of the 3D volume instead of the 2D images.
  • kwargs: Additional keyword arguments for torch_em.default_segmentation_dataset or for the PyTorch DataLoader.
Returns:

The DataLoader.