torch_em.data.datasets.medical.lss_mri_aisslab

The LSS MRI AISSLab dataset contains annotations for vertebra, intervertebral disc, sacrum and posterior structure segmentation in sagittal lumbar spine MRI.

The dataset consists of 500 patients with sagittal lumbar spine MRI, approved by the IRB of Firat University and clinically validated by neurosurgeons. For each patient, the middle sagittal slice is provided as a PNG image together with a pixel-level segmentation mask that was AI-initialized and then manually refined / verified by the neurosurgeons. The mask labels are (pixel value: label): 0 = anterior background, 50 = vertebra, 100 = intervertebral disc, 150 = sacrum, 200 = posterior A, 255 = posterior B.

NOTE: The full release also ships the raw sagittal DICOM series per patient and PNG / XML foraminal stenosis bounding box annotations on all slices. This module only downloads and exposes the middle-slice images and their pixel-level segmentation masks, as the DICOM series and the stenosis bounding boxes are not relevant for segmentation.

The dataset is located at https://data.mendeley.com/datasets/rgb77xm3jf/4 (CC BY 4.0). This dataset is from the publication https://doi.org/10.1038/s41597-026-07138-x. Please cite it if you use this dataset for your research.

  1"""The LSS MRI AISSLab dataset contains annotations for vertebra, intervertebral disc, sacrum
  2and posterior structure segmentation in sagittal lumbar spine MRI.
  3
  4The dataset consists of 500 patients with sagittal lumbar spine MRI, approved by the IRB of
  5Firat University and clinically validated by neurosurgeons. For each patient, the middle sagittal
  6slice is provided as a PNG image together with a pixel-level segmentation mask that was AI-initialized
  7and then manually refined / verified by the neurosurgeons. The mask labels are (pixel value: label):
  80 = anterior background, 50 = vertebra, 100 = intervertebral disc, 150 = sacrum,
  9200 = posterior A, 255 = posterior B.
 10
 11NOTE: The full release also ships the raw sagittal DICOM series per patient and PNG / XML foraminal
 12stenosis bounding box annotations on all slices. This module only downloads and exposes the
 13middle-slice images and their pixel-level segmentation masks, as the DICOM series and the stenosis
 14bounding boxes are not relevant for segmentation.
 15
 16The dataset is located at https://data.mendeley.com/datasets/rgb77xm3jf/4 (CC BY 4.0).
 17This dataset is from the publication https://doi.org/10.1038/s41597-026-07138-x.
 18Please cite it if you use this dataset for your research.
 19"""
 20
 21import os
 22from glob import glob
 23from natsort import natsorted
 24from typing import Union, Tuple, List
 25
 26import numpy as np
 27import imageio.v3 as imageio
 28
 29from torch.utils.data import Dataset, DataLoader
 30
 31import torch_em
 32
 33from .. import util
 34
 35
 36URL = "https://data.mendeley.com/public-files/datasets/rgb77xm3jf/files/6d9a0116-925d-4111-acb0-1e679f7dfd71/file_downloaded"  # noqa
 37CHECKSUM = "592a294f93d575a16bccc2681c793eb1cfc6679fa2746ac50cbc8970f806b4b1"
 38
 39# The pixel values used in the 'Segmentation/Masks/*M.png' files, mapped to contiguous label ids.
 40LABEL_IDS = {0: 0, 50: 1, 100: 2, 150: 3, 200: 4, 255: 5}
 41
 42
 43def get_lss_mri_aisslab_data(path: Union[os.PathLike, str], download: bool = False) -> str:
 44    """Download the LSS MRI AISSLab dataset.
 45
 46    Args:
 47        path: Filepath to a folder where the data is downloaded for further processing.
 48        download: Whether to download the data if it is not present.
 49
 50    Returns:
 51        Filepath to the folder where the 'Segmentation' data is stored.
 52    """
 53    data_dir = os.path.join(path, "Segmentation")
 54    if os.path.exists(data_dir):
 55        return data_dir
 56
 57    os.makedirs(path, exist_ok=True)
 58
 59    zip_path = os.path.join(path, "LSS_MRI_AISSLab.zip")
 60    util.download_source(path=zip_path, url=URL, download=download, checksum=CHECKSUM)
 61
 62    import zipfile
 63    with zipfile.ZipFile(zip_path) as f:
 64        members = [
 65            m for m in f.namelist()
 66            if m.startswith("Segmentation/Middle_Slice/") or m.startswith("Segmentation/Masks/")
 67        ]
 68        f.extractall(path, members=members)
 69    os.remove(zip_path)
 70
 71    return data_dir
 72
 73
 74def _preprocess_masks(data_dir):
 75    mask_paths = natsorted(glob(os.path.join(data_dir, "Masks", "*M.png")))
 76    neu_dir = os.path.join(data_dir, "preprocessed_masks")
 77    os.makedirs(neu_dir, exist_ok=True)
 78
 79    neu_mask_paths = []
 80    for mask_path in mask_paths:
 81        neu_path = os.path.join(neu_dir, os.path.basename(mask_path))
 82        if not os.path.exists(neu_path):
 83            mask = imageio.imread(mask_path)
 84            neu_mask = np.zeros_like(mask, dtype="uint8")
 85            for value, label_id in LABEL_IDS.items():
 86                neu_mask[mask == value] = label_id
 87            imageio.imwrite(neu_path, neu_mask)
 88        neu_mask_paths.append(neu_path)
 89
 90    return neu_mask_paths
 91
 92
 93def get_lss_mri_aisslab_paths(
 94    path: Union[os.PathLike, str], download: bool = False
 95) -> Tuple[List[str], List[str]]:
 96    """Get paths to the LSS MRI AISSLab data.
 97
 98    Args:
 99        path: Filepath to a folder where the data is downloaded for further processing.
100        download: Whether to download the data if it is not present.
101
102    Returns:
103        List of filepaths for the image data.
104        List of filepaths for the label data.
105    """
106    data_dir = get_lss_mri_aisslab_data(path, download)
107
108    image_paths = natsorted(glob(os.path.join(data_dir, "Middle_Slice", "*.png")))
109    label_paths = _preprocess_masks(data_dir)
110
111    assert len(image_paths) > 0 and len(image_paths) == len(label_paths), (
112        f"Expected the same number of images and masks, got {len(image_paths)} and {len(label_paths)}."
113    )
114
115    return image_paths, label_paths
116
117
118def get_lss_mri_aisslab_dataset(
119    path: Union[os.PathLike, str],
120    patch_shape: Tuple[int, int],
121    resize_inputs: bool = False,
122    download: bool = False,
123    **kwargs
124) -> Dataset:
125    """Get the LSS MRI AISSLab dataset for lumbar spine segmentation in sagittal MRI.
126
127    Args:
128        path: Filepath to a folder where the data is downloaded for further processing.
129        patch_shape: The patch shape to use for training.
130        resize_inputs: Whether to resize the inputs to the expected patch shape.
131        download: Whether to download the data if it is not present.
132        kwargs: Additional keyword arguments for `torch_em.default_segmentation_dataset`.
133
134    Returns:
135        The segmentation dataset.
136    """
137    image_paths, label_paths = get_lss_mri_aisslab_paths(path, download)
138
139    if resize_inputs:
140        resize_kwargs = {"patch_shape": patch_shape, "is_rgb": False}
141        kwargs, patch_shape = util.update_kwargs_for_resize_trafo(
142            kwargs=kwargs, patch_shape=patch_shape, resize_inputs=resize_inputs, resize_kwargs=resize_kwargs
143        )
144
145    return torch_em.default_segmentation_dataset(
146        raw_paths=image_paths,
147        raw_key=None,
148        label_paths=label_paths,
149        label_key=None,
150        is_seg_dataset=False,
151        patch_shape=patch_shape,
152        **kwargs
153    )
154
155
156def get_lss_mri_aisslab_loader(
157    path: Union[os.PathLike, str],
158    batch_size: int,
159    patch_shape: Tuple[int, int],
160    resize_inputs: bool = False,
161    download: bool = False,
162    **kwargs
163) -> DataLoader:
164    """Get the LSS MRI AISSLab dataloader for lumbar spine segmentation in sagittal MRI.
165
166    Args:
167        path: Filepath to a folder where the data is downloaded for further processing.
168        batch_size: The batch size for training.
169        patch_shape: The patch shape to use for training.
170        resize_inputs: Whether to resize the inputs to the expected patch shape.
171        download: Whether to download the data if it is not present.
172        kwargs: Additional keyword arguments for `torch_em.default_segmentation_dataset` or for the PyTorch DataLoader.
173
174    Returns:
175        The DataLoader.
176    """
177    ds_kwargs, loader_kwargs = util.split_kwargs(torch_em.default_segmentation_dataset, **kwargs)
178    dataset = get_lss_mri_aisslab_dataset(path, patch_shape, resize_inputs, download, **ds_kwargs)
179    return torch_em.get_data_loader(dataset, batch_size, **loader_kwargs)
URL = 'https://data.mendeley.com/public-files/datasets/rgb77xm3jf/files/6d9a0116-925d-4111-acb0-1e679f7dfd71/file_downloaded'
CHECKSUM = '592a294f93d575a16bccc2681c793eb1cfc6679fa2746ac50cbc8970f806b4b1'
LABEL_IDS = {0: 0, 50: 1, 100: 2, 150: 3, 200: 4, 255: 5}
def get_lss_mri_aisslab_data(path: Union[os.PathLike, str], download: bool = False) -> str:
44def get_lss_mri_aisslab_data(path: Union[os.PathLike, str], download: bool = False) -> str:
45    """Download the LSS MRI AISSLab dataset.
46
47    Args:
48        path: Filepath to a folder where the data is downloaded for further processing.
49        download: Whether to download the data if it is not present.
50
51    Returns:
52        Filepath to the folder where the 'Segmentation' data is stored.
53    """
54    data_dir = os.path.join(path, "Segmentation")
55    if os.path.exists(data_dir):
56        return data_dir
57
58    os.makedirs(path, exist_ok=True)
59
60    zip_path = os.path.join(path, "LSS_MRI_AISSLab.zip")
61    util.download_source(path=zip_path, url=URL, download=download, checksum=CHECKSUM)
62
63    import zipfile
64    with zipfile.ZipFile(zip_path) as f:
65        members = [
66            m for m in f.namelist()
67            if m.startswith("Segmentation/Middle_Slice/") or m.startswith("Segmentation/Masks/")
68        ]
69        f.extractall(path, members=members)
70    os.remove(zip_path)
71
72    return data_dir

Download the LSS MRI AISSLab dataset.

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

Filepath to the folder where the 'Segmentation' data is stored.

def get_lss_mri_aisslab_paths( path: Union[os.PathLike, str], download: bool = False) -> Tuple[List[str], List[str]]:
 94def get_lss_mri_aisslab_paths(
 95    path: Union[os.PathLike, str], download: bool = False
 96) -> Tuple[List[str], List[str]]:
 97    """Get paths to the LSS MRI AISSLab data.
 98
 99    Args:
100        path: Filepath to a folder where the data is downloaded for further processing.
101        download: Whether to download the data if it is not present.
102
103    Returns:
104        List of filepaths for the image data.
105        List of filepaths for the label data.
106    """
107    data_dir = get_lss_mri_aisslab_data(path, download)
108
109    image_paths = natsorted(glob(os.path.join(data_dir, "Middle_Slice", "*.png")))
110    label_paths = _preprocess_masks(data_dir)
111
112    assert len(image_paths) > 0 and len(image_paths) == len(label_paths), (
113        f"Expected the same number of images and masks, got {len(image_paths)} and {len(label_paths)}."
114    )
115
116    return image_paths, label_paths

Get paths to the LSS MRI AISSLab data.

Arguments:
  • path: Filepath to a folder where the data is downloaded for further processing.
  • 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_lss_mri_aisslab_dataset( path: Union[os.PathLike, str], patch_shape: Tuple[int, int], resize_inputs: bool = False, download: bool = False, **kwargs) -> torch.utils.data.dataset.Dataset:
119def get_lss_mri_aisslab_dataset(
120    path: Union[os.PathLike, str],
121    patch_shape: Tuple[int, int],
122    resize_inputs: bool = False,
123    download: bool = False,
124    **kwargs
125) -> Dataset:
126    """Get the LSS MRI AISSLab dataset for lumbar spine segmentation in sagittal MRI.
127
128    Args:
129        path: Filepath to a folder where the data is downloaded for further processing.
130        patch_shape: The patch shape to use for training.
131        resize_inputs: Whether to resize the inputs to the expected patch shape.
132        download: Whether to download the data if it is not present.
133        kwargs: Additional keyword arguments for `torch_em.default_segmentation_dataset`.
134
135    Returns:
136        The segmentation dataset.
137    """
138    image_paths, label_paths = get_lss_mri_aisslab_paths(path, download)
139
140    if resize_inputs:
141        resize_kwargs = {"patch_shape": patch_shape, "is_rgb": False}
142        kwargs, patch_shape = util.update_kwargs_for_resize_trafo(
143            kwargs=kwargs, patch_shape=patch_shape, resize_inputs=resize_inputs, resize_kwargs=resize_kwargs
144        )
145
146    return torch_em.default_segmentation_dataset(
147        raw_paths=image_paths,
148        raw_key=None,
149        label_paths=label_paths,
150        label_key=None,
151        is_seg_dataset=False,
152        patch_shape=patch_shape,
153        **kwargs
154    )

Get the LSS MRI AISSLab dataset for lumbar spine segmentation in sagittal MRI.

Arguments:
  • path: Filepath to a folder where the data is downloaded for further processing.
  • patch_shape: The patch shape to use for training.
  • resize_inputs: Whether to resize the inputs to the expected patch shape.
  • 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_lss_mri_aisslab_loader( path: Union[os.PathLike, str], batch_size: int, patch_shape: Tuple[int, int], resize_inputs: bool = False, download: bool = False, **kwargs) -> torch.utils.data.dataloader.DataLoader:
157def get_lss_mri_aisslab_loader(
158    path: Union[os.PathLike, str],
159    batch_size: int,
160    patch_shape: Tuple[int, int],
161    resize_inputs: bool = False,
162    download: bool = False,
163    **kwargs
164) -> DataLoader:
165    """Get the LSS MRI AISSLab dataloader for lumbar spine segmentation in sagittal MRI.
166
167    Args:
168        path: Filepath to a folder where the data is downloaded for further processing.
169        batch_size: The batch size for training.
170        patch_shape: The patch shape to use for training.
171        resize_inputs: Whether to resize the inputs to the expected patch shape.
172        download: Whether to download the data if it is not present.
173        kwargs: Additional keyword arguments for `torch_em.default_segmentation_dataset` or for the PyTorch DataLoader.
174
175    Returns:
176        The DataLoader.
177    """
178    ds_kwargs, loader_kwargs = util.split_kwargs(torch_em.default_segmentation_dataset, **kwargs)
179    dataset = get_lss_mri_aisslab_dataset(path, patch_shape, resize_inputs, download, **ds_kwargs)
180    return torch_em.get_data_loader(dataset, batch_size, **loader_kwargs)

Get the LSS MRI AISSLab dataloader for lumbar spine segmentation in sagittal MRI.

Arguments:
  • path: Filepath to a folder where the data is downloaded for further processing.
  • batch_size: The batch size for training.
  • patch_shape: The patch shape to use for training.
  • resize_inputs: Whether to resize the inputs to the expected patch shape.
  • 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.