torch_em.data.datasets.electron_microscopy.u2os_fibsem

The U2OS FIB-SEM dataset contains training data for segmenting organelles in a FIB-SEM volume of a human U2-OS (bone osteosarcoma) cell.

It contains four sub-datasets with binary semantic annotations of 2D slices:

  • ne: Nuclear envelope (44 slices of 1235 x 530 pixels).
  • mitochondria: Mitochondria (45 slices of 692 x 1697 pixels).
  • er: Endoplasmic reticulum (45 slices of 1385 x 3394 pixels).
  • golgi: Golgi apparatus (45 slices of 1385 x 3394 pixels).

For mitochondria, ER and Golgi the data is distributed as small stacks (9 or 5 slices), where only the central slice is annotated. Only the annotated slices are used here.

The dataset is located at https://doi.org/10.5281/zenodo.10043461 and is distributed under the CC BY 4.0 license. The full FIB-SEM volume is available at EMPIAR-11746. The annotations were created for training the networks in DeepMIB (Belevich & Jokitalo, https://doi.org/10.1371/journal.pcbi.1008374). Please cite it if you use this dataset in your research.

  1"""The U2OS FIB-SEM dataset contains training data for segmenting organelles in a FIB-SEM volume
  2of a human U2-OS (bone osteosarcoma) cell.
  3
  4It contains four sub-datasets with binary semantic annotations of 2D slices:
  5- ne: Nuclear envelope (44 slices of 1235 x 530 pixels).
  6- mitochondria: Mitochondria (45 slices of 692 x 1697 pixels).
  7- er: Endoplasmic reticulum (45 slices of 1385 x 3394 pixels).
  8- golgi: Golgi apparatus (45 slices of 1385 x 3394 pixels).
  9
 10For mitochondria, ER and Golgi the data is distributed as small stacks (9 or 5 slices), where only the central slice
 11is annotated. Only the annotated slices are used here.
 12
 13The dataset is located at https://doi.org/10.5281/zenodo.10043461 and is distributed under the CC BY 4.0 license.
 14The full FIB-SEM volume is available at EMPIAR-11746. The annotations were created for training
 15the networks in DeepMIB (Belevich & Jokitalo, https://doi.org/10.1371/journal.pcbi.1008374).
 16Please cite it if you use this dataset in your research.
 17"""
 18
 19import os
 20import re
 21from glob import glob
 22from natsort import natsorted
 23from typing import Union, Tuple, List, Literal
 24
 25import numpy as np
 26
 27from torch.utils.data import Dataset, DataLoader
 28
 29import torch_em
 30
 31from .. import util
 32
 33
 34URLS = {
 35    "ne": "https://zenodo.org/records/10043461/files/1_NE.zip?download=1",
 36    "mitochondria": "https://zenodo.org/records/10043461/files/1_Mitochondria.zip?download=1",
 37    "er": "https://zenodo.org/records/10043461/files/1_ER.zip?download=1",
 38    "golgi": "https://zenodo.org/records/10043461/files/1_Golgi.zip?download=1",
 39}
 40CHECKSUMS = {
 41    "ne": "4ae915ce64632d1f27328cf3a79e85806d6b899cc51e0e85be619f3c161233bc",
 42    "mitochondria": "6725fb41ed7c14061ee96ab6110209aa0a6f9bd9fdb3a9aca2adb82a408f5680",
 43    "er": "1c5df4101b5f3f376124fc0b87da03198158d039ce146536542bc90c943feffc",
 44    "golgi": "594bf6a51dc9c85b2af504063759e8e46b39e604e3eb506728f8ba9254e31102",
 45}
 46# The folders with the training images and labels inside of the extracted archives.
 47FOLDERS = {
 48    "ne": ("1_NE", "1_Train_NE", "Images", "Labels"),
 49    "mitochondria": ("1_Mitochondria", "1_Train_Mito", "Images", "Labels"),
 50    "er": ("1_ER", "1_Train_ER", "Images", "Labels"),
 51    "golgi": ("1_Golgi", "1_Train_Golgi", "Images_for_patches", "Labels_for_patches"),
 52}
 53
 54
 55def _read_amira(am_path):
 56    with open(am_path, "rb") as f:
 57        content = f.read()
 58
 59    # The header is followed by the raw (uncompressed) voxel data, which starts after the '@1' marker.
 60    marker = content.find(b"\n@1\n")
 61    header = content[:marker].decode("latin1")
 62    assert "Lattice { byte Data } @1" in header, f"Unsupported Amira data type in {am_path}"
 63    x, y, z = map(int, re.search(r"define Lattice (\d+) (\d+) (\d+)", header).groups())
 64
 65    start = marker + len(b"\n@1\n")
 66    return np.frombuffer(content[start:start + x * y * z], dtype="uint8").reshape(z, y, x)
 67
 68
 69def _convert_to_annotated_slice(am_path, label_path, image_tif_path, label_tif_path):
 70    import tifffile
 71
 72    image = _read_amira(am_path)
 73    label = tifffile.imread(label_path)
 74    label = label[None] if label.ndim == 2 else label
 75    assert image.shape == label.shape, f"Image and label shapes differ for {am_path}: {image.shape}, {label.shape}"
 76
 77    # Only a single slice per stack is annotated.
 78    z = int(np.argmax((label > 0).reshape(len(label), -1).sum(axis=1)))
 79    tifffile.imwrite(image_tif_path, image[z], compression="zlib")
 80    tifffile.imwrite(label_tif_path, label[z], compression="zlib")
 81
 82
 83def get_u2os_fibsem_data(
 84    path: Union[os.PathLike, str], name: Literal["ne", "mitochondria", "er", "golgi"], download: bool = False
 85) -> str:
 86    """Download the U2OS FIB-SEM dataset.
 87
 88    The images are distributed in the Amira format and are converted to tif files after downloading.
 89    Only the annotated slice of each image / label stack is kept for training.
 90
 91    Args:
 92        path: Filepath to a folder where the downloaded data will be saved.
 93        name: The name of the sub-dataset. Either 'ne', 'mitochondria', 'er' or 'golgi'.
 94        download: Whether to download the data if it is not present.
 95
 96    Returns:
 97        The filepath to the folder with the data.
 98    """
 99    assert name in URLS, f"'{name}' is not a valid sub-dataset name. Choose from {list(URLS)}."
100    root, train_dir, _, _ = FOLDERS[name]
101
102    data_dir = os.path.join(path, root)
103    if os.path.exists(os.path.join(data_dir, train_dir)):
104        return data_dir
105
106    os.makedirs(path, exist_ok=True)
107    zip_path = os.path.join(path, f"{root}.zip")
108    util.download_source(path=zip_path, url=URLS[name], download=download, checksum=CHECKSUMS[name])
109    util.unzip(zip_path=zip_path, dst=path)
110
111    _, _, image_dir, label_dir = FOLDERS[name]
112    image_tif_dir = os.path.join(data_dir, train_dir, "images_tif")
113    label_tif_dir = os.path.join(data_dir, train_dir, "labels_tif")
114    os.makedirs(image_tif_dir, exist_ok=True)
115    os.makedirs(label_tif_dir, exist_ok=True)
116
117    am_paths = natsorted(glob(os.path.join(data_dir, train_dir, image_dir, "*.am")))
118    label_paths = natsorted(glob(os.path.join(data_dir, train_dir, label_dir, "*.tif")))
119    assert len(am_paths) > 0 and len(am_paths) == len(label_paths)
120    for am_path, label_path in zip(am_paths, label_paths):
121        fname = os.path.splitext(os.path.basename(am_path))[0]
122        _convert_to_annotated_slice(
123            am_path,
124            label_path,
125            os.path.join(image_tif_dir, f"{fname}.tif"),
126            os.path.join(label_tif_dir, f"{fname}.tif"),
127        )
128
129    return data_dir
130
131
132def get_u2os_fibsem_paths(
133    path: Union[os.PathLike, str],
134    name: Literal["ne", "mitochondria", "er", "golgi"],
135    download: bool = False,
136) -> Tuple[List[str], List[str]]:
137    """Get paths to the U2OS FIB-SEM data.
138
139    Args:
140        path: Filepath to a folder where the downloaded data will be saved.
141        name: The name of the sub-dataset. Either 'ne', 'mitochondria', 'er' or 'golgi'.
142        download: Whether to download the data if it is not present.
143
144    Returns:
145        List of filepaths for the image data.
146        List of filepaths for the label data.
147    """
148    data_dir = get_u2os_fibsem_data(path, name, download)
149    train_dir = FOLDERS[name][1]
150
151    image_paths = natsorted(glob(os.path.join(data_dir, train_dir, "images_tif", "*.tif")))
152    label_paths = natsorted(glob(os.path.join(data_dir, train_dir, "labels_tif", "*.tif")))
153    assert len(image_paths) > 0 and len(image_paths) == len(label_paths)
154    return image_paths, label_paths
155
156
157def get_u2os_fibsem_dataset(
158    path: Union[os.PathLike, str],
159    patch_shape: Tuple[int, int],
160    name: Literal["ne", "mitochondria", "er", "golgi"],
161    download: bool = False,
162    **kwargs
163) -> Dataset:
164    """Get the U2OS FIB-SEM dataset for organelle segmentation.
165
166    The labels are binary (1 is the organelle).
167
168    Args:
169        path: Filepath to a folder where the downloaded data will be saved.
170        patch_shape: The patch shape to use for training.
171        name: The name of the sub-dataset. Either 'ne', 'mitochondria', 'er' or 'golgi'.
172        download: Whether to download the data if it is not present.
173        kwargs: Additional keyword arguments for `torch_em.default_segmentation_dataset`.
174
175    Returns:
176        The segmentation dataset.
177    """
178    image_paths, label_paths = get_u2os_fibsem_paths(path, name, download)
179
180    kwargs = util.update_kwargs(kwargs, "label_transform", torch_em.transform.label.labels_to_binary)
181    kwargs = util.update_kwargs(kwargs, "ndim", 2)
182
183    return torch_em.default_segmentation_dataset(
184        raw_paths=image_paths,
185        raw_key=None,
186        label_paths=label_paths,
187        label_key=None,
188        patch_shape=patch_shape,
189        **kwargs
190    )
191
192
193def get_u2os_fibsem_loader(
194    path: Union[os.PathLike, str],
195    patch_shape: Tuple[int, int],
196    batch_size: int,
197    name: Literal["ne", "mitochondria", "er", "golgi"],
198    download: bool = False,
199    **kwargs
200) -> DataLoader:
201    """Get the DataLoader for organelle segmentation in the U2OS FIB-SEM dataset.
202
203    Args:
204        path: Filepath to a folder where the downloaded data will be saved.
205        patch_shape: The patch shape to use for training.
206        batch_size: The batch size for training.
207        name: The name of the sub-dataset. Either 'ne', 'mitochondria', 'er' or 'golgi'.
208        download: Whether to download the data if it is not present.
209        kwargs: Additional keyword arguments for `torch_em.default_segmentation_dataset` or for the PyTorch DataLoader.
210
211    Returns:
212        The DataLoader.
213    """
214    ds_kwargs, loader_kwargs = util.split_kwargs(torch_em.default_segmentation_dataset, **kwargs)
215    dataset = get_u2os_fibsem_dataset(path, patch_shape, name, download, **ds_kwargs)
216    return torch_em.get_data_loader(dataset, batch_size, **loader_kwargs)
URLS = {'ne': 'https://zenodo.org/records/10043461/files/1_NE.zip?download=1', 'mitochondria': 'https://zenodo.org/records/10043461/files/1_Mitochondria.zip?download=1', 'er': 'https://zenodo.org/records/10043461/files/1_ER.zip?download=1', 'golgi': 'https://zenodo.org/records/10043461/files/1_Golgi.zip?download=1'}
CHECKSUMS = {'ne': '4ae915ce64632d1f27328cf3a79e85806d6b899cc51e0e85be619f3c161233bc', 'mitochondria': '6725fb41ed7c14061ee96ab6110209aa0a6f9bd9fdb3a9aca2adb82a408f5680', 'er': '1c5df4101b5f3f376124fc0b87da03198158d039ce146536542bc90c943feffc', 'golgi': '594bf6a51dc9c85b2af504063759e8e46b39e604e3eb506728f8ba9254e31102'}
FOLDERS = {'ne': ('1_NE', '1_Train_NE', 'Images', 'Labels'), 'mitochondria': ('1_Mitochondria', '1_Train_Mito', 'Images', 'Labels'), 'er': ('1_ER', '1_Train_ER', 'Images', 'Labels'), 'golgi': ('1_Golgi', '1_Train_Golgi', 'Images_for_patches', 'Labels_for_patches')}
def get_u2os_fibsem_data( path: Union[os.PathLike, str], name: Literal['ne', 'mitochondria', 'er', 'golgi'], download: bool = False) -> str:
 84def get_u2os_fibsem_data(
 85    path: Union[os.PathLike, str], name: Literal["ne", "mitochondria", "er", "golgi"], download: bool = False
 86) -> str:
 87    """Download the U2OS FIB-SEM dataset.
 88
 89    The images are distributed in the Amira format and are converted to tif files after downloading.
 90    Only the annotated slice of each image / label stack is kept for training.
 91
 92    Args:
 93        path: Filepath to a folder where the downloaded data will be saved.
 94        name: The name of the sub-dataset. Either 'ne', 'mitochondria', 'er' or 'golgi'.
 95        download: Whether to download the data if it is not present.
 96
 97    Returns:
 98        The filepath to the folder with the data.
 99    """
100    assert name in URLS, f"'{name}' is not a valid sub-dataset name. Choose from {list(URLS)}."
101    root, train_dir, _, _ = FOLDERS[name]
102
103    data_dir = os.path.join(path, root)
104    if os.path.exists(os.path.join(data_dir, train_dir)):
105        return data_dir
106
107    os.makedirs(path, exist_ok=True)
108    zip_path = os.path.join(path, f"{root}.zip")
109    util.download_source(path=zip_path, url=URLS[name], download=download, checksum=CHECKSUMS[name])
110    util.unzip(zip_path=zip_path, dst=path)
111
112    _, _, image_dir, label_dir = FOLDERS[name]
113    image_tif_dir = os.path.join(data_dir, train_dir, "images_tif")
114    label_tif_dir = os.path.join(data_dir, train_dir, "labels_tif")
115    os.makedirs(image_tif_dir, exist_ok=True)
116    os.makedirs(label_tif_dir, exist_ok=True)
117
118    am_paths = natsorted(glob(os.path.join(data_dir, train_dir, image_dir, "*.am")))
119    label_paths = natsorted(glob(os.path.join(data_dir, train_dir, label_dir, "*.tif")))
120    assert len(am_paths) > 0 and len(am_paths) == len(label_paths)
121    for am_path, label_path in zip(am_paths, label_paths):
122        fname = os.path.splitext(os.path.basename(am_path))[0]
123        _convert_to_annotated_slice(
124            am_path,
125            label_path,
126            os.path.join(image_tif_dir, f"{fname}.tif"),
127            os.path.join(label_tif_dir, f"{fname}.tif"),
128        )
129
130    return data_dir

Download the U2OS FIB-SEM dataset.

The images are distributed in the Amira format and are converted to tif files after downloading. Only the annotated slice of each image / label stack is kept for training.

Arguments:
  • path: Filepath to a folder where the downloaded data will be saved.
  • name: The name of the sub-dataset. Either 'ne', 'mitochondria', 'er' or 'golgi'.
  • download: Whether to download the data if it is not present.
Returns:

The filepath to the folder with the data.

def get_u2os_fibsem_paths( path: Union[os.PathLike, str], name: Literal['ne', 'mitochondria', 'er', 'golgi'], download: bool = False) -> Tuple[List[str], List[str]]:
133def get_u2os_fibsem_paths(
134    path: Union[os.PathLike, str],
135    name: Literal["ne", "mitochondria", "er", "golgi"],
136    download: bool = False,
137) -> Tuple[List[str], List[str]]:
138    """Get paths to the U2OS FIB-SEM data.
139
140    Args:
141        path: Filepath to a folder where the downloaded data will be saved.
142        name: The name of the sub-dataset. Either 'ne', 'mitochondria', 'er' or 'golgi'.
143        download: Whether to download the data if it is not present.
144
145    Returns:
146        List of filepaths for the image data.
147        List of filepaths for the label data.
148    """
149    data_dir = get_u2os_fibsem_data(path, name, download)
150    train_dir = FOLDERS[name][1]
151
152    image_paths = natsorted(glob(os.path.join(data_dir, train_dir, "images_tif", "*.tif")))
153    label_paths = natsorted(glob(os.path.join(data_dir, train_dir, "labels_tif", "*.tif")))
154    assert len(image_paths) > 0 and len(image_paths) == len(label_paths)
155    return image_paths, label_paths

Get paths to the U2OS FIB-SEM data.

Arguments:
  • path: Filepath to a folder where the downloaded data will be saved.
  • name: The name of the sub-dataset. Either 'ne', 'mitochondria', 'er' or 'golgi'.
  • download: Whether to download the data if it is not present.
Returns:

List of filepaths for the image data. List of filepaths for the label data.

def get_u2os_fibsem_dataset( path: Union[os.PathLike, str], patch_shape: Tuple[int, int], name: Literal['ne', 'mitochondria', 'er', 'golgi'], download: bool = False, **kwargs) -> torch.utils.data.dataset.Dataset:
158def get_u2os_fibsem_dataset(
159    path: Union[os.PathLike, str],
160    patch_shape: Tuple[int, int],
161    name: Literal["ne", "mitochondria", "er", "golgi"],
162    download: bool = False,
163    **kwargs
164) -> Dataset:
165    """Get the U2OS FIB-SEM dataset for organelle segmentation.
166
167    The labels are binary (1 is the organelle).
168
169    Args:
170        path: Filepath to a folder where the downloaded data will be saved.
171        patch_shape: The patch shape to use for training.
172        name: The name of the sub-dataset. Either 'ne', 'mitochondria', 'er' or 'golgi'.
173        download: Whether to download the data if it is not present.
174        kwargs: Additional keyword arguments for `torch_em.default_segmentation_dataset`.
175
176    Returns:
177        The segmentation dataset.
178    """
179    image_paths, label_paths = get_u2os_fibsem_paths(path, name, download)
180
181    kwargs = util.update_kwargs(kwargs, "label_transform", torch_em.transform.label.labels_to_binary)
182    kwargs = util.update_kwargs(kwargs, "ndim", 2)
183
184    return torch_em.default_segmentation_dataset(
185        raw_paths=image_paths,
186        raw_key=None,
187        label_paths=label_paths,
188        label_key=None,
189        patch_shape=patch_shape,
190        **kwargs
191    )

Get the U2OS FIB-SEM dataset for organelle segmentation.

The labels are binary (1 is the organelle).

Arguments:
  • path: Filepath to a folder where the downloaded data will be saved.
  • patch_shape: The patch shape to use for training.
  • name: The name of the sub-dataset. Either 'ne', 'mitochondria', 'er' or 'golgi'.
  • download: Whether to download the data if it is not present.
  • kwargs: Additional keyword arguments for torch_em.default_segmentation_dataset.
Returns:

The segmentation dataset.

def get_u2os_fibsem_loader( path: Union[os.PathLike, str], patch_shape: Tuple[int, int], batch_size: int, name: Literal['ne', 'mitochondria', 'er', 'golgi'], download: bool = False, **kwargs) -> torch.utils.data.dataloader.DataLoader:
194def get_u2os_fibsem_loader(
195    path: Union[os.PathLike, str],
196    patch_shape: Tuple[int, int],
197    batch_size: int,
198    name: Literal["ne", "mitochondria", "er", "golgi"],
199    download: bool = False,
200    **kwargs
201) -> DataLoader:
202    """Get the DataLoader for organelle segmentation in the U2OS FIB-SEM dataset.
203
204    Args:
205        path: Filepath to a folder where the downloaded data will be saved.
206        patch_shape: The patch shape to use for training.
207        batch_size: The batch size for training.
208        name: The name of the sub-dataset. Either 'ne', 'mitochondria', 'er' or 'golgi'.
209        download: Whether to download the data if it is not present.
210        kwargs: Additional keyword arguments for `torch_em.default_segmentation_dataset` or for the PyTorch DataLoader.
211
212    Returns:
213        The DataLoader.
214    """
215    ds_kwargs, loader_kwargs = util.split_kwargs(torch_em.default_segmentation_dataset, **kwargs)
216    dataset = get_u2os_fibsem_dataset(path, patch_shape, name, download, **ds_kwargs)
217    return torch_em.get_data_loader(dataset, batch_size, **loader_kwargs)

Get the DataLoader for organelle segmentation in the U2OS FIB-SEM dataset.

Arguments:
  • path: Filepath to a folder where the downloaded data will be saved.
  • patch_shape: The patch shape to use for training.
  • batch_size: The batch size for training.
  • name: The name of the sub-dataset. Either 'ne', 'mitochondria', 'er' or 'golgi'.
  • download: Whether to download the data if it is not present.
  • kwargs: Additional keyword arguments for torch_em.default_segmentation_dataset or for the PyTorch DataLoader.
Returns:

The DataLoader.