torch_em.data.datasets.medical.tongue_mri

The Tongue MRI dataset contains annotations for tongue musculature segmentation in MRI.

The dataset consists of 47 healthy subjects collated from three studies: BMC (24 subjects, T1-weighted MRI), EATT4MND (19 subjects, T2-weighted MRI) and BeLong (4 subjects, T2-weighted MRI). Each subject has a manually corrected semantic segmentation of four tongue muscles, following LABEL_IDS: the genioglossus, the superior longitudinal, the inferior longitudinal, and the combined transverse / vertical muscle.

The dataset also ships study templates for each site (in the 'template' folders next to the 'images' and 'labels' folders that this module uses), which are not returned by this module.

The dataset is located at https://osf.io/wt9fc/ and is distributed under the CC0 1.0 license.

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

  1"""The Tongue MRI dataset contains annotations for tongue musculature segmentation in MRI.
  2
  3The dataset consists of 47 healthy subjects collated from three studies: BMC (24 subjects,
  4T1-weighted MRI), EATT4MND (19 subjects, T2-weighted MRI) and BeLong (4 subjects, T2-weighted
  5MRI). Each subject has a manually corrected semantic segmentation of four tongue muscles,
  6following `LABEL_IDS`: the genioglossus, the superior longitudinal, the inferior longitudinal,
  7and the combined transverse / vertical muscle.
  8
  9The dataset also ships study templates for each site (in the 'template' folders next to the
 10'images' and 'labels' folders that this module uses), which are not returned by this module.
 11
 12The dataset is located at https://osf.io/wt9fc/ and is distributed under the CC0 1.0 license.
 13
 14This dataset is from the publication https://doi.org/10.1038/s41597-025-05092-8.
 15Please cite it if you use this dataset in your research.
 16"""
 17
 18import os
 19from glob import glob
 20from natsort import natsorted
 21from typing import Union, Tuple, Literal, List, Optional
 22
 23from torch.utils.data import Dataset, DataLoader
 24
 25import torch_em
 26
 27from .. import util
 28
 29
 30# The site sub-folders are generated on-the-fly by OSF, hence the checksums of the archives are not reliable.
 31URLS = {
 32    "BMC": {
 33        "images": "https://files.osf.io/v1/resources/wt9fc/providers/osfstorage/66e224fb34c37b7bbdcb074e/?zip=",
 34        "labels": "https://files.osf.io/v1/resources/wt9fc/providers/osfstorage/66e224ff87c914991b64b5cb/?zip=",
 35    },
 36    "EATT4MND": {
 37        "images": "https://files.osf.io/v1/resources/wt9fc/providers/osfstorage/66e2259e2d9d10b9f9cb0ab2/?zip=",
 38        "labels": "https://files.osf.io/v1/resources/wt9fc/providers/osfstorage/66e225a28cec7392871d9456/?zip=",
 39    },
 40    "BeLong": {
 41        "images": "https://files.osf.io/v1/resources/wt9fc/providers/osfstorage/66e2248cf57074722a64c057/?zip=",
 42        "labels": "https://files.osf.io/v1/resources/wt9fc/providers/osfstorage/66e224931bc7424b3dc05a46/?zip=",
 43    },
 44}
 45
 46SITES = list(URLS.keys())
 47
 48LABEL_IDS = {
 49    "background": 0,
 50    "genioglossus": 1,
 51    "superior_longitudinal": 2,
 52    "inferior_longitudinal": 3,
 53    "transverse_vertical": 4,
 54}
 55"""The semantic label ids of the tongue muscle classes."""
 56
 57
 58def get_tongue_mri_data(
 59    path: Union[os.PathLike, str], site: Literal["BMC", "EATT4MND", "BeLong"] = "BMC", download: bool = False
 60) -> str:
 61    """Download the Tongue MRI dataset.
 62
 63    Args:
 64        path: Filepath to a folder where the data is downloaded for further processing.
 65        site: The study site to download. One of 'BMC', 'EATT4MND', 'BeLong'.
 66        download: Whether to download the data if it is not present.
 67
 68    Returns:
 69        Filepath to the site folder where the data is downloaded.
 70    """
 71    if site not in SITES:
 72        raise ValueError(f"'{site}' is not a valid site. Choose one of {SITES}.")
 73
 74    site_dir = os.path.join(path, site)
 75    os.makedirs(site_dir, exist_ok=True)
 76
 77    for name in ["images", "labels"]:
 78        data_dir = os.path.join(site_dir, name)
 79        if os.path.exists(data_dir):
 80            continue
 81
 82        zip_path = os.path.join(site_dir, f"{name}.zip")
 83        util.download_source(path=zip_path, url=URLS[site][name], download=download, checksum=None)
 84        util.unzip(zip_path=zip_path, dst=data_dir)
 85
 86    return site_dir
 87
 88
 89def get_tongue_mri_paths(
 90    path: Union[os.PathLike, str],
 91    site: Optional[Literal["BMC", "EATT4MND", "BeLong"]] = None,
 92    download: bool = False,
 93) -> Tuple[List[str], List[str]]:
 94    """Get paths to the Tongue MRI data.
 95
 96    Args:
 97        path: Filepath to a folder where the data is downloaded for further processing.
 98        site: The study site to use. One of 'BMC', 'EATT4MND', 'BeLong'. By default, all sites are used.
 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    sites = SITES if site is None else [site]
106
107    raw_paths, label_paths = [], []
108    for s in sites:
109        site_dir = get_tongue_mri_data(path, s, download)
110        cur_label_paths = natsorted(glob(os.path.join(site_dir, "labels", "*_labels.nii.gz")))
111        cur_raw_paths = [
112            os.path.join(site_dir, "images", os.path.basename(p).replace("_labels.nii.gz", ".nii.gz"))
113            for p in cur_label_paths
114        ]
115        assert all(os.path.exists(p) for p in cur_raw_paths), f"Some image volumes are missing for site '{s}'."
116        raw_paths.extend(cur_raw_paths)
117        label_paths.extend(cur_label_paths)
118
119    assert len(raw_paths) == len(label_paths) and len(raw_paths) > 0
120
121    return raw_paths, label_paths
122
123
124def get_tongue_mri_dataset(
125    path: Union[os.PathLike, str],
126    patch_shape: Tuple[int, ...],
127    site: Optional[Literal["BMC", "EATT4MND", "BeLong"]] = None,
128    resize_inputs: bool = False,
129    download: bool = False,
130    **kwargs
131) -> Dataset:
132    """Get the Tongue MRI dataset for tongue musculature segmentation.
133
134    Args:
135        path: Filepath to a folder where the data is downloaded for further processing.
136        patch_shape: The patch shape to use for training.
137        site: The study site to use. One of 'BMC', 'EATT4MND', 'BeLong'. By default, all sites are used.
138        resize_inputs: Whether to resize inputs to the desired patch shape.
139        download: Whether to download the data if it is not present.
140        kwargs: Additional keyword arguments for `torch_em.default_segmentation_dataset`.
141
142    Returns:
143        The segmentation dataset.
144    """
145    raw_paths, label_paths = get_tongue_mri_paths(path, site, download)
146
147    if resize_inputs:
148        resize_kwargs = {"patch_shape": patch_shape, "is_rgb": False}
149        kwargs, patch_shape = util.update_kwargs_for_resize_trafo(
150            kwargs=kwargs, patch_shape=patch_shape, resize_inputs=resize_inputs, resize_kwargs=resize_kwargs
151        )
152
153    return torch_em.default_segmentation_dataset(
154        raw_paths=raw_paths,
155        raw_key="data",
156        label_paths=label_paths,
157        label_key="data",
158        patch_shape=patch_shape,
159        is_seg_dataset=True,
160        **kwargs
161    )
162
163
164def get_tongue_mri_loader(
165    path: Union[os.PathLike, str],
166    batch_size: int,
167    patch_shape: Tuple[int, ...],
168    site: Optional[Literal["BMC", "EATT4MND", "BeLong"]] = None,
169    resize_inputs: bool = False,
170    download: bool = False,
171    **kwargs
172) -> DataLoader:
173    """Get the Tongue MRI dataloader for tongue musculature segmentation.
174
175    Args:
176        path: Filepath to a folder where the data is downloaded for further processing.
177        batch_size: The batch size for training.
178        patch_shape: The patch shape to use for training.
179        site: The study site to use. One of 'BMC', 'EATT4MND', 'BeLong'. By default, all sites are used.
180        resize_inputs: Whether to resize inputs to the desired patch shape.
181        download: Whether to download the data if it is not present.
182        kwargs: Additional keyword arguments for `torch_em.default_segmentation_dataset` or for the PyTorch DataLoader.
183
184    Returns:
185        The DataLoader.
186    """
187    ds_kwargs, loader_kwargs = util.split_kwargs(torch_em.default_segmentation_dataset, **kwargs)
188    dataset = get_tongue_mri_dataset(path, patch_shape, site, resize_inputs, download, **ds_kwargs)
189    return torch_em.get_data_loader(dataset, batch_size, **loader_kwargs)
URLS = {'BMC': {'images': 'https://files.osf.io/v1/resources/wt9fc/providers/osfstorage/66e224fb34c37b7bbdcb074e/?zip=', 'labels': 'https://files.osf.io/v1/resources/wt9fc/providers/osfstorage/66e224ff87c914991b64b5cb/?zip='}, 'EATT4MND': {'images': 'https://files.osf.io/v1/resources/wt9fc/providers/osfstorage/66e2259e2d9d10b9f9cb0ab2/?zip=', 'labels': 'https://files.osf.io/v1/resources/wt9fc/providers/osfstorage/66e225a28cec7392871d9456/?zip='}, 'BeLong': {'images': 'https://files.osf.io/v1/resources/wt9fc/providers/osfstorage/66e2248cf57074722a64c057/?zip=', 'labels': 'https://files.osf.io/v1/resources/wt9fc/providers/osfstorage/66e224931bc7424b3dc05a46/?zip='}}
SITES = ['BMC', 'EATT4MND', 'BeLong']
LABEL_IDS = {'background': 0, 'genioglossus': 1, 'superior_longitudinal': 2, 'inferior_longitudinal': 3, 'transverse_vertical': 4}

The semantic label ids of the tongue muscle classes.

def get_tongue_mri_data( path: Union[os.PathLike, str], site: Literal['BMC', 'EATT4MND', 'BeLong'] = 'BMC', download: bool = False) -> str:
59def get_tongue_mri_data(
60    path: Union[os.PathLike, str], site: Literal["BMC", "EATT4MND", "BeLong"] = "BMC", download: bool = False
61) -> str:
62    """Download the Tongue MRI dataset.
63
64    Args:
65        path: Filepath to a folder where the data is downloaded for further processing.
66        site: The study site to download. One of 'BMC', 'EATT4MND', 'BeLong'.
67        download: Whether to download the data if it is not present.
68
69    Returns:
70        Filepath to the site folder where the data is downloaded.
71    """
72    if site not in SITES:
73        raise ValueError(f"'{site}' is not a valid site. Choose one of {SITES}.")
74
75    site_dir = os.path.join(path, site)
76    os.makedirs(site_dir, exist_ok=True)
77
78    for name in ["images", "labels"]:
79        data_dir = os.path.join(site_dir, name)
80        if os.path.exists(data_dir):
81            continue
82
83        zip_path = os.path.join(site_dir, f"{name}.zip")
84        util.download_source(path=zip_path, url=URLS[site][name], download=download, checksum=None)
85        util.unzip(zip_path=zip_path, dst=data_dir)
86
87    return site_dir

Download the Tongue MRI dataset.

Arguments:
  • path: Filepath to a folder where the data is downloaded for further processing.
  • site: The study site to download. One of 'BMC', 'EATT4MND', 'BeLong'.
  • download: Whether to download the data if it is not present.
Returns:

Filepath to the site folder where the data is downloaded.

def get_tongue_mri_paths( path: Union[os.PathLike, str], site: Optional[Literal['BMC', 'EATT4MND', 'BeLong']] = None, download: bool = False) -> Tuple[List[str], List[str]]:
 90def get_tongue_mri_paths(
 91    path: Union[os.PathLike, str],
 92    site: Optional[Literal["BMC", "EATT4MND", "BeLong"]] = None,
 93    download: bool = False,
 94) -> Tuple[List[str], List[str]]:
 95    """Get paths to the Tongue MRI data.
 96
 97    Args:
 98        path: Filepath to a folder where the data is downloaded for further processing.
 99        site: The study site to use. One of 'BMC', 'EATT4MND', 'BeLong'. By default, all sites are used.
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    sites = SITES if site is None else [site]
107
108    raw_paths, label_paths = [], []
109    for s in sites:
110        site_dir = get_tongue_mri_data(path, s, download)
111        cur_label_paths = natsorted(glob(os.path.join(site_dir, "labels", "*_labels.nii.gz")))
112        cur_raw_paths = [
113            os.path.join(site_dir, "images", os.path.basename(p).replace("_labels.nii.gz", ".nii.gz"))
114            for p in cur_label_paths
115        ]
116        assert all(os.path.exists(p) for p in cur_raw_paths), f"Some image volumes are missing for site '{s}'."
117        raw_paths.extend(cur_raw_paths)
118        label_paths.extend(cur_label_paths)
119
120    assert len(raw_paths) == len(label_paths) and len(raw_paths) > 0
121
122    return raw_paths, label_paths

Get paths to the Tongue MRI data.

Arguments:
  • path: Filepath to a folder where the data is downloaded for further processing.
  • site: The study site to use. One of 'BMC', 'EATT4MND', 'BeLong'. By default, all sites are used.
  • 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_tongue_mri_dataset( path: Union[os.PathLike, str], patch_shape: Tuple[int, ...], site: Optional[Literal['BMC', 'EATT4MND', 'BeLong']] = None, resize_inputs: bool = False, download: bool = False, **kwargs) -> torch.utils.data.dataset.Dataset:
125def get_tongue_mri_dataset(
126    path: Union[os.PathLike, str],
127    patch_shape: Tuple[int, ...],
128    site: Optional[Literal["BMC", "EATT4MND", "BeLong"]] = None,
129    resize_inputs: bool = False,
130    download: bool = False,
131    **kwargs
132) -> Dataset:
133    """Get the Tongue MRI dataset for tongue musculature segmentation.
134
135    Args:
136        path: Filepath to a folder where the data is downloaded for further processing.
137        patch_shape: The patch shape to use for training.
138        site: The study site to use. One of 'BMC', 'EATT4MND', 'BeLong'. By default, all sites are used.
139        resize_inputs: Whether to resize inputs to the desired patch shape.
140        download: Whether to download the data if it is not present.
141        kwargs: Additional keyword arguments for `torch_em.default_segmentation_dataset`.
142
143    Returns:
144        The segmentation dataset.
145    """
146    raw_paths, label_paths = get_tongue_mri_paths(path, site, download)
147
148    if resize_inputs:
149        resize_kwargs = {"patch_shape": patch_shape, "is_rgb": False}
150        kwargs, patch_shape = util.update_kwargs_for_resize_trafo(
151            kwargs=kwargs, patch_shape=patch_shape, resize_inputs=resize_inputs, resize_kwargs=resize_kwargs
152        )
153
154    return torch_em.default_segmentation_dataset(
155        raw_paths=raw_paths,
156        raw_key="data",
157        label_paths=label_paths,
158        label_key="data",
159        patch_shape=patch_shape,
160        is_seg_dataset=True,
161        **kwargs
162    )

Get the Tongue MRI dataset for tongue musculature segmentation.

Arguments:
  • path: Filepath to a folder where the data is downloaded for further processing.
  • patch_shape: The patch shape to use for training.
  • site: The study site to use. One of 'BMC', 'EATT4MND', 'BeLong'. By default, all sites are used.
  • resize_inputs: Whether to resize inputs to the desired 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_tongue_mri_loader( path: Union[os.PathLike, str], batch_size: int, patch_shape: Tuple[int, ...], site: Optional[Literal['BMC', 'EATT4MND', 'BeLong']] = None, resize_inputs: bool = False, download: bool = False, **kwargs) -> torch.utils.data.dataloader.DataLoader:
165def get_tongue_mri_loader(
166    path: Union[os.PathLike, str],
167    batch_size: int,
168    patch_shape: Tuple[int, ...],
169    site: Optional[Literal["BMC", "EATT4MND", "BeLong"]] = None,
170    resize_inputs: bool = False,
171    download: bool = False,
172    **kwargs
173) -> DataLoader:
174    """Get the Tongue MRI dataloader for tongue musculature segmentation.
175
176    Args:
177        path: Filepath to a folder where the data is downloaded for further processing.
178        batch_size: The batch size for training.
179        patch_shape: The patch shape to use for training.
180        site: The study site to use. One of 'BMC', 'EATT4MND', 'BeLong'. By default, all sites are used.
181        resize_inputs: Whether to resize inputs to the desired patch shape.
182        download: Whether to download the data if it is not present.
183        kwargs: Additional keyword arguments for `torch_em.default_segmentation_dataset` or for the PyTorch DataLoader.
184
185    Returns:
186        The DataLoader.
187    """
188    ds_kwargs, loader_kwargs = util.split_kwargs(torch_em.default_segmentation_dataset, **kwargs)
189    dataset = get_tongue_mri_dataset(path, patch_shape, site, resize_inputs, download, **ds_kwargs)
190    return torch_em.get_data_loader(dataset, batch_size, **loader_kwargs)

Get the Tongue MRI dataloader for tongue musculature segmentation.

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.
  • site: The study site to use. One of 'BMC', 'EATT4MND', 'BeLong'. By default, all sites are used.
  • resize_inputs: Whether to resize inputs to the desired 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.