torch_em.data.datasets.light_microscopy.ifnuclei

The IFNuclei dataset contains annotations for nucleus segmentation of immuno and DAPI stained fluorescence images.

It contains 79 expert-annotated immunofluorescence and DAPI images with 7813 nuclei from normal and cancer samples. Pass split to use the train and test split of https://github.com/kreshuklab/model_ranking, which holds 42 and 37 images.

This dataset is from the publication https://doi.org/10.1038/s41597-020-00608-w. Please cite it if you use this dataset in your research.

  1"""The IFNuclei dataset contains annotations for nucleus segmentation
  2of immuno and DAPI stained fluorescence images.
  3
  4It contains 79 expert-annotated immunofluorescence and DAPI images with 7813 nuclei from normal and
  5cancer samples. Pass `split` to use the train and test split of
  6https://github.com/kreshuklab/model_ranking, which holds 42 and 37 images.
  7
  8This dataset is from the publication https://doi.org/10.1038/s41597-020-00608-w.
  9Please cite it if you use this dataset in your research.
 10"""
 11
 12import os
 13from glob import glob
 14from natsort import natsorted
 15from typing import List, Literal, Optional, Tuple, Union
 16
 17from torch.utils.data import Dataset, DataLoader
 18
 19import torch_em
 20
 21from .. import util
 22
 23
 24URL = "https://www.ebi.ac.uk/biostudies/files/S-BSST265/dataset.zip"
 25CHECKSUM = "8285987ed4d57c46a46a55a33c1c085875ea41f429b59cde31d249741aa07ad1"
 26
 27SAMPLES = {
 28    "train": (
 29        "Ganglioneuroblastoma_0", "Ganglioneuroblastoma_1", "Ganglioneuroblastoma_2",
 30        "Ganglioneuroblastoma_3", "Neuroblastoma_0", "Neuroblastoma_1",
 31        "Neuroblastoma_10", "Neuroblastoma_11", "Neuroblastoma_2",
 32        "Neuroblastoma_3", "Neuroblastoma_4", "Neuroblastoma_5",
 33        "Neuroblastoma_6", "Neuroblastoma_7", "Neuroblastoma_8",
 34        "Neuroblastoma_9", "normal_0", "normal_1",
 35        "normal_10", "normal_11", "normal_12",
 36        "normal_13", "normal_14", "normal_15",
 37        "normal_16", "normal_17", "normal_18",
 38        "normal_19", "normal_2", "normal_20",
 39        "normal_21", "normal_22", "normal_23",
 40        "normal_24", "normal_25", "normal_3",
 41        "normal_4", "normal_5", "normal_6",
 42        "normal_7", "normal_8", "normal_9",
 43    ),
 44    "test": (
 45        "Ganglioneuroblastoma_10", "Ganglioneuroblastoma_4", "Ganglioneuroblastoma_6",
 46        "Ganglioneuroblastoma_7", "Ganglioneuroblastoma_8", "Ganglioneuroblastoma_9",
 47        "Neuroblastoma_12", "Neuroblastoma_13", "Neuroblastoma_14",
 48        "Neuroblastoma_15", "Neuroblastoma_16", "Neuroblastoma_17",
 49        "normal_26", "normal_27", "normal_28",
 50        "normal_29", "normal_30", "normal_31",
 51        "normal_32", "normal_33", "normal_34",
 52        "normal_35", "normal_36", "normal_37",
 53        "normal_38", "normal_39", "normal_40",
 54        "otherspecimen_0", "otherspecimen_1", "otherspecimen_2",
 55        "otherspecimen_3", "otherspecimen_4", "otherspecimen_5",
 56        "otherspecimen_6", "otherspecimen_7", "otherspecimen_8",
 57        "otherspecimen_9",
 58    ),
 59}
 60
 61
 62def _select_grayscale(raw):
 63    if raw.ndim == 2:
 64        return raw
 65    if raw.ndim == 3 and raw.shape[0] == 3:
 66        return raw[0]
 67    raise ValueError(f"Expected a grayscale or RGB IFNuclei image, got shape {raw.shape}.")
 68
 69
 70def get_ifnuclei_data(path: Union[os.PathLike, str], download: bool = False):
 71    """Download the IFNuclei dataset for nucleus segmentation.
 72
 73    Args:
 74        path: Filepath to a folder where the downloaded data will be saved.
 75        download: Whether to download the data if it is not present.
 76    """
 77    data_dir = os.path.join(path, "rawimages")
 78    if os.path.exists(data_dir):
 79        return
 80
 81    os.makedirs(path, exist_ok=True)
 82
 83    zip_path = os.path.join(path, "dataset.zip")
 84    util.download_source(path=zip_path, url=URL, download=download, checksum=CHECKSUM)
 85    util.unzip(zip_path=zip_path, dst=path)
 86
 87
 88def get_ifnuclei_paths(
 89    path: Union[os.PathLike, str],
 90    split: Optional[Literal["train", "test"]] = None,
 91    download: bool = False,
 92) -> Tuple[List[str], List[str]]:
 93    """Get paths to the IFNuclei data.
 94
 95    Args:
 96        path: Filepath to a folder where the downloaded data will be saved.
 97        split: The data split. Either 'train' or 'test', or None for all images.
 98        download: Whether to download the data if it is not present.
 99
100    Returns:
101        List of filepaths for the image data.
102        List of filepaths for the label data.
103    """
104    get_ifnuclei_data(path, download)
105
106    if split is None:
107        raw_paths = natsorted(glob(os.path.join(path, "rawimages", "*.tif")))
108        label_paths = natsorted(glob(os.path.join(path, "groundtruth", "*")))
109    else:
110        if split not in SAMPLES:
111            raise ValueError(f"'{split}' is not a valid split. Choose from {list(SAMPLES)}, or None for all images.")
112        raw_paths = [os.path.join(path, "rawimages", f"{sample}.tif") for sample in SAMPLES[split]]
113        label_paths = [os.path.join(path, "groundtruth", f"{sample}.tif") for sample in SAMPLES[split]]
114        missing = [p for p in raw_paths + label_paths if not os.path.exists(p)]
115        if missing:
116            raise RuntimeError(f"Could not find {len(missing)} files of the '{split}' split, e.g. {missing[0]}.")
117
118    assert len(raw_paths) == len(label_paths) and len(raw_paths) > 0
119
120    return raw_paths, label_paths
121
122
123def get_ifnuclei_dataset(
124    path: Union[os.PathLike, str],
125    patch_shape: Tuple[int, int],
126    split: Optional[Literal["train", "test"]] = None,
127    offsets: Optional[List[List[int]]] = None,
128    boundaries: bool = False,
129    binary: bool = False,
130    download: bool = False,
131    **kwargs
132) -> Dataset:
133    """Get the IFNuclei dataset for nucleus segmentation.
134
135    Args:
136        path: Filepath to a folder where the downloaded data will be saved.
137        patch_shape: The patch shape to use for training.
138        split: The data split. Either 'train' or 'test', or None for all images.
139        offsets: Offset values for affinity computation used as target.
140        boundaries: Whether to compute boundaries as the target.
141        binary: Whether to use a binary segmentation target.
142        download: Whether to download the data if it is not present.
143        kwargs: Additional keyword arguments for `torch_em.default_segmentation_dataset`.
144
145    Returns:
146        The segmentation dataset.
147    """
148    raw_paths, label_paths = get_ifnuclei_paths(path, split, download)
149
150    raw_transform = kwargs.pop("raw_transform", None)
151    if raw_transform is None:
152        raw_transform = torch_em.transform.get_raw_transform()
153    kwargs["raw_transform"] = torch_em.transform.Compose(_select_grayscale, raw_transform, is_multi_tensor=False)
154
155    kwargs, _ = util.add_instance_label_transform(
156        kwargs, add_binary_target=True, offsets=offsets, boundaries=boundaries, binary=binary,
157    )
158
159    return torch_em.default_segmentation_dataset(
160        raw_paths=raw_paths,
161        raw_key=None,
162        label_paths=label_paths,
163        label_key=None,
164        is_seg_dataset=False,
165        patch_shape=patch_shape,
166        **kwargs
167    )
168
169
170def get_ifnuclei_loader(
171    path: Union[os.PathLike, str],
172    batch_size: int,
173    patch_shape: Tuple[int, int],
174    split: Optional[Literal["train", "test"]] = None,
175    offsets: Optional[List[List[int]]] = None,
176    boundaries: bool = False,
177    binary: bool = False,
178    download: bool = False,
179    **kwargs
180) -> DataLoader:
181    """Get the IFNuclei dataloader for nucleus segmentation.
182
183    Args:
184        path: Filepath to a folder where the downloaded data will be saved.
185        batch_size: The batch size for training.
186        patch_shape: The patch shape to use for training.
187        split: The data split. Either 'train' or 'test', or None for all images.
188        offsets: Offset values for affinity computation used as target.
189        boundaries: Whether to compute boundaries as the target.
190        binary: Whether to use a binary segmentation target.
191        download: Whether to download the data if it is not present.
192        kwargs: Additional keyword arguments for `torch_em.default_segmentation_dataset` or for the PyTorch DataLoader.
193
194    Returns:
195        The DataLoader.
196    """
197    ds_kwargs, loader_kwargs = util.split_kwargs(torch_em.default_segmentation_dataset, **kwargs)
198    dataset = get_ifnuclei_dataset(
199        path=path,
200        patch_shape=patch_shape,
201        split=split,
202        offsets=offsets,
203        boundaries=boundaries,
204        binary=binary,
205        download=download,
206        **ds_kwargs,
207    )
208    return torch_em.get_data_loader(dataset, batch_size, **loader_kwargs)
URL = 'https://www.ebi.ac.uk/biostudies/files/S-BSST265/dataset.zip'
CHECKSUM = '8285987ed4d57c46a46a55a33c1c085875ea41f429b59cde31d249741aa07ad1'
SAMPLES = {'train': ('Ganglioneuroblastoma_0', 'Ganglioneuroblastoma_1', 'Ganglioneuroblastoma_2', 'Ganglioneuroblastoma_3', 'Neuroblastoma_0', 'Neuroblastoma_1', 'Neuroblastoma_10', 'Neuroblastoma_11', 'Neuroblastoma_2', 'Neuroblastoma_3', 'Neuroblastoma_4', 'Neuroblastoma_5', 'Neuroblastoma_6', 'Neuroblastoma_7', 'Neuroblastoma_8', 'Neuroblastoma_9', 'normal_0', 'normal_1', 'normal_10', 'normal_11', 'normal_12', 'normal_13', 'normal_14', 'normal_15', 'normal_16', 'normal_17', 'normal_18', 'normal_19', 'normal_2', 'normal_20', 'normal_21', 'normal_22', 'normal_23', 'normal_24', 'normal_25', 'normal_3', 'normal_4', 'normal_5', 'normal_6', 'normal_7', 'normal_8', 'normal_9'), 'test': ('Ganglioneuroblastoma_10', 'Ganglioneuroblastoma_4', 'Ganglioneuroblastoma_6', 'Ganglioneuroblastoma_7', 'Ganglioneuroblastoma_8', 'Ganglioneuroblastoma_9', 'Neuroblastoma_12', 'Neuroblastoma_13', 'Neuroblastoma_14', 'Neuroblastoma_15', 'Neuroblastoma_16', 'Neuroblastoma_17', 'normal_26', 'normal_27', 'normal_28', 'normal_29', 'normal_30', 'normal_31', 'normal_32', 'normal_33', 'normal_34', 'normal_35', 'normal_36', 'normal_37', 'normal_38', 'normal_39', 'normal_40', 'otherspecimen_0', 'otherspecimen_1', 'otherspecimen_2', 'otherspecimen_3', 'otherspecimen_4', 'otherspecimen_5', 'otherspecimen_6', 'otherspecimen_7', 'otherspecimen_8', 'otherspecimen_9')}
def get_ifnuclei_data(path: Union[os.PathLike, str], download: bool = False):
71def get_ifnuclei_data(path: Union[os.PathLike, str], download: bool = False):
72    """Download the IFNuclei dataset for nucleus segmentation.
73
74    Args:
75        path: Filepath to a folder where the downloaded data will be saved.
76        download: Whether to download the data if it is not present.
77    """
78    data_dir = os.path.join(path, "rawimages")
79    if os.path.exists(data_dir):
80        return
81
82    os.makedirs(path, exist_ok=True)
83
84    zip_path = os.path.join(path, "dataset.zip")
85    util.download_source(path=zip_path, url=URL, download=download, checksum=CHECKSUM)
86    util.unzip(zip_path=zip_path, dst=path)

Download the IFNuclei dataset for nucleus segmentation.

Arguments:
  • path: Filepath to a folder where the downloaded data will be saved.
  • download: Whether to download the data if it is not present.
def get_ifnuclei_paths( path: Union[os.PathLike, str], split: Optional[Literal['train', 'test']] = None, download: bool = False) -> Tuple[List[str], List[str]]:
 89def get_ifnuclei_paths(
 90    path: Union[os.PathLike, str],
 91    split: Optional[Literal["train", "test"]] = None,
 92    download: bool = False,
 93) -> Tuple[List[str], List[str]]:
 94    """Get paths to the IFNuclei data.
 95
 96    Args:
 97        path: Filepath to a folder where the downloaded data will be saved.
 98        split: The data split. Either 'train' or 'test', or None for all images.
 99        download: Whether to download the data if it is not present.
100
101    Returns:
102        List of filepaths for the image data.
103        List of filepaths for the label data.
104    """
105    get_ifnuclei_data(path, download)
106
107    if split is None:
108        raw_paths = natsorted(glob(os.path.join(path, "rawimages", "*.tif")))
109        label_paths = natsorted(glob(os.path.join(path, "groundtruth", "*")))
110    else:
111        if split not in SAMPLES:
112            raise ValueError(f"'{split}' is not a valid split. Choose from {list(SAMPLES)}, or None for all images.")
113        raw_paths = [os.path.join(path, "rawimages", f"{sample}.tif") for sample in SAMPLES[split]]
114        label_paths = [os.path.join(path, "groundtruth", f"{sample}.tif") for sample in SAMPLES[split]]
115        missing = [p for p in raw_paths + label_paths if not os.path.exists(p)]
116        if missing:
117            raise RuntimeError(f"Could not find {len(missing)} files of the '{split}' split, e.g. {missing[0]}.")
118
119    assert len(raw_paths) == len(label_paths) and len(raw_paths) > 0
120
121    return raw_paths, label_paths

Get paths to the IFNuclei data.

Arguments:
  • path: Filepath to a folder where the downloaded data will be saved.
  • split: The data split. Either 'train' or 'test', or None for all images.
  • 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_ifnuclei_dataset( path: Union[os.PathLike, str], patch_shape: Tuple[int, int], split: Optional[Literal['train', 'test']] = None, offsets: Optional[List[List[int]]] = None, boundaries: bool = False, binary: bool = False, download: bool = False, **kwargs) -> torch.utils.data.dataset.Dataset:
124def get_ifnuclei_dataset(
125    path: Union[os.PathLike, str],
126    patch_shape: Tuple[int, int],
127    split: Optional[Literal["train", "test"]] = None,
128    offsets: Optional[List[List[int]]] = None,
129    boundaries: bool = False,
130    binary: bool = False,
131    download: bool = False,
132    **kwargs
133) -> Dataset:
134    """Get the IFNuclei dataset for nucleus segmentation.
135
136    Args:
137        path: Filepath to a folder where the downloaded data will be saved.
138        patch_shape: The patch shape to use for training.
139        split: The data split. Either 'train' or 'test', or None for all images.
140        offsets: Offset values for affinity computation used as target.
141        boundaries: Whether to compute boundaries as the target.
142        binary: Whether to use a binary segmentation target.
143        download: Whether to download the data if it is not present.
144        kwargs: Additional keyword arguments for `torch_em.default_segmentation_dataset`.
145
146    Returns:
147        The segmentation dataset.
148    """
149    raw_paths, label_paths = get_ifnuclei_paths(path, split, download)
150
151    raw_transform = kwargs.pop("raw_transform", None)
152    if raw_transform is None:
153        raw_transform = torch_em.transform.get_raw_transform()
154    kwargs["raw_transform"] = torch_em.transform.Compose(_select_grayscale, raw_transform, is_multi_tensor=False)
155
156    kwargs, _ = util.add_instance_label_transform(
157        kwargs, add_binary_target=True, offsets=offsets, boundaries=boundaries, binary=binary,
158    )
159
160    return torch_em.default_segmentation_dataset(
161        raw_paths=raw_paths,
162        raw_key=None,
163        label_paths=label_paths,
164        label_key=None,
165        is_seg_dataset=False,
166        patch_shape=patch_shape,
167        **kwargs
168    )

Get the IFNuclei dataset for nucleus segmentation.

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. Either 'train' or 'test', or None for all images.
  • offsets: Offset values for affinity computation used as target.
  • boundaries: Whether to compute boundaries as the target.
  • binary: Whether to use a binary segmentation target.
  • 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_ifnuclei_loader( path: Union[os.PathLike, str], batch_size: int, patch_shape: Tuple[int, int], split: Optional[Literal['train', 'test']] = None, offsets: Optional[List[List[int]]] = None, boundaries: bool = False, binary: bool = False, download: bool = False, **kwargs) -> torch.utils.data.dataloader.DataLoader:
171def get_ifnuclei_loader(
172    path: Union[os.PathLike, str],
173    batch_size: int,
174    patch_shape: Tuple[int, int],
175    split: Optional[Literal["train", "test"]] = None,
176    offsets: Optional[List[List[int]]] = None,
177    boundaries: bool = False,
178    binary: bool = False,
179    download: bool = False,
180    **kwargs
181) -> DataLoader:
182    """Get the IFNuclei dataloader for nucleus segmentation.
183
184    Args:
185        path: Filepath to a folder where the downloaded data will be saved.
186        batch_size: The batch size for training.
187        patch_shape: The patch shape to use for training.
188        split: The data split. Either 'train' or 'test', or None for all images.
189        offsets: Offset values for affinity computation used as target.
190        boundaries: Whether to compute boundaries as the target.
191        binary: Whether to use a binary segmentation target.
192        download: Whether to download the data if it is not present.
193        kwargs: Additional keyword arguments for `torch_em.default_segmentation_dataset` or for the PyTorch DataLoader.
194
195    Returns:
196        The DataLoader.
197    """
198    ds_kwargs, loader_kwargs = util.split_kwargs(torch_em.default_segmentation_dataset, **kwargs)
199    dataset = get_ifnuclei_dataset(
200        path=path,
201        patch_shape=patch_shape,
202        split=split,
203        offsets=offsets,
204        boundaries=boundaries,
205        binary=binary,
206        download=download,
207        **ds_kwargs,
208    )
209    return torch_em.get_data_loader(dataset, batch_size, **loader_kwargs)

Get the IFNuclei dataloader for nucleus segmentation.

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. Either 'train' or 'test', or None for all images.
  • offsets: Offset values for affinity computation used as target.
  • boundaries: Whether to compute boundaries as the target.
  • binary: Whether to use a binary segmentation target.
  • 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.