torch_em.data.datasets.histopathology.nusec

The NuSeC dataset contains nucleus annotations for H&E stained images of invasive breast carcinoma.

The dataset holds 100 images of 1024 x 1024 pixels at 40x magnification from 25 patients of Ankara University, 75 for training and 25 for testing. The nuclei were outlined by hand in QuPath and checked by pathologists. NOTE: The annotations are not exhaustive. Many nuclei, most of all the stromal nuclei, carry no annotation and become background in the label images. Take this into account when you train on this data, and when you measure the recall of a model on it.

The data is located at https://doi.org/10.6084/m9.figshare.29525111 (CC BY 4.0), together with the MiDeSeC mitosis dataset of the same group, which this module does not use. This dataset is from the publication https://doi.org/10.48550/arXiv.2507.14272. Please cite it if you use this dataset for your research.

  1"""The NuSeC dataset contains nucleus annotations for H&E stained images of invasive breast carcinoma.
  2
  3The dataset holds 100 images of 1024 x 1024 pixels at 40x magnification from 25 patients of Ankara University,
  475 for training and 25 for testing. The nuclei were outlined by hand in QuPath and checked by pathologists.
  5NOTE: The annotations are not exhaustive. Many nuclei, most of all the stromal nuclei, carry no annotation
  6and become background in the label images. Take this into account when you train on this data, and when you
  7measure the recall of a model on it.
  8
  9The data is located at https://doi.org/10.6084/m9.figshare.29525111 (CC BY 4.0), together with the
 10MiDeSeC mitosis dataset of the same group, which this module does not use.
 11This dataset is from the publication https://doi.org/10.48550/arXiv.2507.14272.
 12Please cite it if you use this dataset for your research.
 13"""
 14
 15import os
 16import zipfile
 17from tqdm import tqdm
 18from glob import glob
 19from natsort import natsorted
 20from typing import Union, Tuple, List, Literal
 21
 22import numpy as np
 23import imageio.v3 as imageio
 24
 25from torch.utils.data import Dataset, DataLoader
 26
 27import torch_em
 28
 29from .. import util
 30
 31
 32URL = "https://ndownloader.figshare.com/files/56111276"
 33CHECKSUM = "71102cec12a74f643d727b80e0a24ff12b1446a5fe3e0a94905617b28432ddf3"
 34ZIP_ROOT = "Ankara university datasets/NuSeC"
 35
 36
 37def _create_h5_files(path, zip_path):
 38    import h5py
 39
 40    with zipfile.ZipFile(zip_path) as archive:
 41        for split in ("train", "test"):
 42            out_dir = os.path.join(path, "preprocessed", split)
 43            os.makedirs(out_dir, exist_ok=True)
 44            prefix = f"{ZIP_ROOT}/{split} nuclei/"
 45            names = [n for n in archive.namelist() if n.startswith(prefix) and not n.endswith("/")]
 46            for name in tqdm(names, desc=f"Preprocess NuSeC {split} images"):
 47                fname = os.path.basename(name)
 48                image = imageio.imread(archive.read(name), extension=".tif")[..., :3]
 49                labels = imageio.imread(archive.read(f"{ZIP_ROOT}/mask of {split} nuclei/{fname}"), extension=".tif")
 50                # The masks are stored as float, but hold integer instance ids.
 51                assert np.array_equal(labels, np.round(labels)), fname
 52                labels = labels.astype("uint32")
 53                assert image.shape[:2] == labels.shape, (fname, image.shape, labels.shape)
 54
 55                with h5py.File(os.path.join(out_dir, f"{os.path.splitext(fname)[0]}.h5"), "w") as f:
 56                    f.create_dataset("raw", data=image.transpose(2, 0, 1), compression="gzip")
 57                    f.create_dataset("labels/instances", data=labels, compression="gzip")
 58
 59
 60def get_nusec_data(path: Union[os.PathLike, str], download: bool = False) -> str:
 61    """Download the NuSeC dataset.
 62
 63    Args:
 64        path: Filepath to a folder where the downloaded data is saved.
 65        download: Whether to download the data if it is not present.
 66
 67    Returns:
 68        Filepath where the preprocessed data is stored.
 69    """
 70    data_dir = os.path.join(path, "preprocessed")
 71    if os.path.exists(data_dir):
 72        return data_dir
 73
 74    os.makedirs(path, exist_ok=True)
 75    zip_path = os.path.join(path, "nusec_midesec.zip")
 76    util.download_source(zip_path, URL, download, checksum=CHECKSUM)
 77    _create_h5_files(path, zip_path)
 78    return data_dir
 79
 80
 81def get_nusec_paths(
 82    path: Union[os.PathLike, str], split: Literal["train", "test"], download: bool = False
 83) -> List[str]:
 84    """Get paths to the NuSeC data.
 85
 86    Args:
 87        path: Filepath to a folder where the downloaded data is saved.
 88        split: The choice of data split. Either 'train' or 'test'.
 89        download: Whether to download the data if it is not present.
 90
 91    Returns:
 92        List of filepaths for the input data.
 93    """
 94    assert split in ("train", "test"), split
 95    data_dir = get_nusec_data(path, download)
 96    return natsorted(glob(os.path.join(data_dir, split, "*.h5")))
 97
 98
 99def get_nusec_dataset(
100    path: Union[os.PathLike, str],
101    patch_shape: Tuple[int, int],
102    split: Literal["train", "test"],
103    download: bool = False,
104    **kwargs
105) -> Dataset:
106    """Get the NuSeC dataset for nucleus segmentation.
107
108    Args:
109        path: Filepath to a folder where the downloaded data is saved.
110        patch_shape: The patch shape to use for training.
111        split: The choice of data split. Either 'train' or 'test'.
112        download: Whether to download the data if it is not present.
113        kwargs: Additional keyword arguments for `torch_em.default_segmentation_dataset`.
114
115    Returns:
116        The segmentation dataset.
117    """
118    paths = get_nusec_paths(path, split, download)
119    return torch_em.default_segmentation_dataset(
120        raw_paths=paths,
121        raw_key="raw",
122        label_paths=paths,
123        label_key="labels/instances",
124        patch_shape=patch_shape,
125        ndim=2,
126        with_channels=True,
127        **kwargs
128    )
129
130
131def get_nusec_loader(
132    path: Union[os.PathLike, str],
133    batch_size: int,
134    patch_shape: Tuple[int, int],
135    split: Literal["train", "test"],
136    download: bool = False,
137    **kwargs
138) -> DataLoader:
139    """Get the NuSeC dataloader for nucleus segmentation.
140
141    Args:
142        path: Filepath to a folder where the downloaded data is saved.
143        batch_size: The batch size for training.
144        patch_shape: The patch shape to use for training.
145        split: The choice of data split. Either 'train' or 'test'.
146        download: Whether to download the data if it is not present.
147        kwargs: Additional keyword arguments for `torch_em.default_segmentation_dataset` or for the PyTorch DataLoader.
148
149    Returns:
150        The DataLoader.
151    """
152    ds_kwargs, loader_kwargs = util.split_kwargs(torch_em.default_segmentation_dataset, **kwargs)
153    dataset = get_nusec_dataset(path, patch_shape, split, download, **ds_kwargs)
154    return torch_em.get_data_loader(dataset, batch_size, **loader_kwargs)
URL = 'https://ndownloader.figshare.com/files/56111276'
CHECKSUM = '71102cec12a74f643d727b80e0a24ff12b1446a5fe3e0a94905617b28432ddf3'
ZIP_ROOT = 'Ankara university datasets/NuSeC'
def get_nusec_data(path: Union[os.PathLike, str], download: bool = False) -> str:
61def get_nusec_data(path: Union[os.PathLike, str], download: bool = False) -> str:
62    """Download the NuSeC dataset.
63
64    Args:
65        path: Filepath to a folder where the downloaded data is saved.
66        download: Whether to download the data if it is not present.
67
68    Returns:
69        Filepath where the preprocessed data is stored.
70    """
71    data_dir = os.path.join(path, "preprocessed")
72    if os.path.exists(data_dir):
73        return data_dir
74
75    os.makedirs(path, exist_ok=True)
76    zip_path = os.path.join(path, "nusec_midesec.zip")
77    util.download_source(zip_path, URL, download, checksum=CHECKSUM)
78    _create_h5_files(path, zip_path)
79    return data_dir

Download the NuSeC dataset.

Arguments:
  • path: Filepath to a folder where the downloaded data is saved.
  • download: Whether to download the data if it is not present.
Returns:

Filepath where the preprocessed data is stored.

def get_nusec_paths( path: Union[os.PathLike, str], split: Literal['train', 'test'], download: bool = False) -> List[str]:
82def get_nusec_paths(
83    path: Union[os.PathLike, str], split: Literal["train", "test"], download: bool = False
84) -> List[str]:
85    """Get paths to the NuSeC data.
86
87    Args:
88        path: Filepath to a folder where the downloaded data is saved.
89        split: The choice of data split. Either 'train' or 'test'.
90        download: Whether to download the data if it is not present.
91
92    Returns:
93        List of filepaths for the input data.
94    """
95    assert split in ("train", "test"), split
96    data_dir = get_nusec_data(path, download)
97    return natsorted(glob(os.path.join(data_dir, split, "*.h5")))

Get paths to the NuSeC data.

Arguments:
  • path: Filepath to a folder where the downloaded data is saved.
  • split: The choice of data split. Either 'train' or 'test'.
  • download: Whether to download the data if it is not present.
Returns:

List of filepaths for the input data.

def get_nusec_dataset( path: Union[os.PathLike, str], patch_shape: Tuple[int, int], split: Literal['train', 'test'], download: bool = False, **kwargs) -> torch.utils.data.dataset.Dataset:
100def get_nusec_dataset(
101    path: Union[os.PathLike, str],
102    patch_shape: Tuple[int, int],
103    split: Literal["train", "test"],
104    download: bool = False,
105    **kwargs
106) -> Dataset:
107    """Get the NuSeC dataset for nucleus segmentation.
108
109    Args:
110        path: Filepath to a folder where the downloaded data is saved.
111        patch_shape: The patch shape to use for training.
112        split: The choice of data split. Either 'train' or 'test'.
113        download: Whether to download the data if it is not present.
114        kwargs: Additional keyword arguments for `torch_em.default_segmentation_dataset`.
115
116    Returns:
117        The segmentation dataset.
118    """
119    paths = get_nusec_paths(path, split, download)
120    return torch_em.default_segmentation_dataset(
121        raw_paths=paths,
122        raw_key="raw",
123        label_paths=paths,
124        label_key="labels/instances",
125        patch_shape=patch_shape,
126        ndim=2,
127        with_channels=True,
128        **kwargs
129    )

Get the NuSeC dataset for nucleus segmentation.

Arguments:
  • path: Filepath to a folder where the downloaded data is saved.
  • patch_shape: The patch shape to use for training.
  • split: The choice of data split. Either 'train' or 'test'.
  • 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_nusec_loader( path: Union[os.PathLike, str], batch_size: int, patch_shape: Tuple[int, int], split: Literal['train', 'test'], download: bool = False, **kwargs) -> torch.utils.data.dataloader.DataLoader:
132def get_nusec_loader(
133    path: Union[os.PathLike, str],
134    batch_size: int,
135    patch_shape: Tuple[int, int],
136    split: Literal["train", "test"],
137    download: bool = False,
138    **kwargs
139) -> DataLoader:
140    """Get the NuSeC dataloader for nucleus segmentation.
141
142    Args:
143        path: Filepath to a folder where the downloaded data is saved.
144        batch_size: The batch size for training.
145        patch_shape: The patch shape to use for training.
146        split: The choice of data split. Either 'train' or 'test'.
147        download: Whether to download the data if it is not present.
148        kwargs: Additional keyword arguments for `torch_em.default_segmentation_dataset` or for the PyTorch DataLoader.
149
150    Returns:
151        The DataLoader.
152    """
153    ds_kwargs, loader_kwargs = util.split_kwargs(torch_em.default_segmentation_dataset, **kwargs)
154    dataset = get_nusec_dataset(path, patch_shape, split, download, **ds_kwargs)
155    return torch_em.get_data_loader(dataset, batch_size, **loader_kwargs)

Get the NuSeC dataloader for nucleus segmentation.

Arguments:
  • path: Filepath to a folder where the downloaded data is saved.
  • batch_size: The batch size for training.
  • patch_shape: The patch shape to use for training.
  • split: The choice of data split. Either 'train' or 'test'.
  • 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.