torch_em.data.datasets.medical.prostate158
The Prostate158 dataset contains annotations for prostate zone and prostate cancer segmentation in biparametric 3T MRI.
Each study provides a T2-weighted sequence ('t2'), a diffusion-weighted sequence ('dwi') and the corresponding apparent diffusion coefficient map ('adc'). All sequences of a study were resampled to the same grid, so that the labels can be used with any of them.
NOTE: The label legends are described as following: 1: For the anatomical zones ('anatomy', annotated by reader 1 in the T2-weighted sequence):
- background: 0, transition zone (central gland): 1 and peripheral zone: 2. 2: For the prostate cancer lesions ('tumor', annotated by reader 1 in the ADC map):
- background: 0 and tumor: 1. Studies without a lesion have an empty label volume.
The official split provides 119 training and 20 validation studies (record https://zenodo.org/records/6481141) and 19 test studies with additional annotations from a second reader (record https://zenodo.org/records/6592345).
The dataset is located at https://github.com/kbressem/prostate158.
This dataset is from the publication https://doi.org/10.1016/j.compbiomed.2022.105817. Please cite it if you use this dataset in your research.
1"""The Prostate158 dataset contains annotations for prostate zone and prostate cancer segmentation 2in biparametric 3T MRI. 3 4Each study provides a T2-weighted sequence ('t2'), a diffusion-weighted sequence ('dwi') and the corresponding 5apparent diffusion coefficient map ('adc'). All sequences of a study were resampled to the same grid, 6so that the labels can be used with any of them. 7 8NOTE: The label legends are described as following: 91: For the anatomical zones ('anatomy', annotated by reader 1 in the T2-weighted sequence): 10- background: 0, transition zone (central gland): 1 and peripheral zone: 2. 112: For the prostate cancer lesions ('tumor', annotated by reader 1 in the ADC map): 12- background: 0 and tumor: 1. Studies without a lesion have an empty label volume. 13 14The official split provides 119 training and 20 validation studies (record https://zenodo.org/records/6481141) 15and 19 test studies with additional annotations from a second reader (record https://zenodo.org/records/6592345). 16 17The dataset is located at https://github.com/kbressem/prostate158. 18 19This dataset is from the publication https://doi.org/10.1016/j.compbiomed.2022.105817. 20Please cite it if you use this dataset in your research. 21""" 22 23import os 24import csv 25from typing import Union, Tuple, Literal, List 26 27from torch.utils.data import Dataset, DataLoader 28 29import torch_em 30 31from .. import util 32 33 34URLS = { 35 "train": "https://zenodo.org/records/6481141/files/prostate158_train.zip?download=1", 36 "test": "https://zenodo.org/records/6592345/files/prostate158_test.zip?download=1", 37} 38 39CHECKSUMS = { 40 "train": "7a97b263be1bdbc79f6c8a3461e010b2cea9a266249af47671616dadff77da2e", 41 "test": "d64a7b94f0654de21150af9b7a5734b2921ec4793bc129b98803ef9ae9d459c4", 42} 43 44LABEL_COLUMNS = {"anatomy": "t2_anatomy_reader1", "tumor": "adc_tumor_reader1"} 45 46 47def get_prostate158_data( 48 path: Union[os.PathLike, str], split: Literal["train", "valid", "test"], download: bool = False 49) -> str: 50 """Download the Prostate158 dataset. 51 52 Args: 53 path: Filepath to a folder where the data is downloaded for further processing. 54 split: The choice of data split. The 'train' and 'valid' splits share one archive, 'test' has its own. 55 download: Whether to download the data if it is not present. 56 57 Returns: 58 Filepath to the folder with the data of the requested split. 59 """ 60 if split not in ("train", "valid", "test"): 61 raise ValueError(f"'{split}' is not a valid split.") 62 63 archive = "test" if split == "test" else "train" 64 data_dir = os.path.join(path, f"prostate158_{archive}") 65 if os.path.exists(data_dir): 66 return data_dir 67 68 os.makedirs(path, exist_ok=True) 69 70 zip_path = os.path.join(path, f"prostate158_{archive}.zip") 71 util.download_source(path=zip_path, url=URLS[archive], download=download, checksum=CHECKSUMS[archive]) 72 util.unzip(zip_path=zip_path, dst=path) 73 74 return data_dir 75 76 77def get_prostate158_paths( 78 path: Union[os.PathLike, str], 79 split: Literal["train", "valid", "test"], 80 sequence: Literal["t2", "adc", "dwi"] = "t2", 81 label_type: Literal["anatomy", "tumor"] = "anatomy", 82 download: bool = False, 83) -> Tuple[List[str], List[str]]: 84 """Get paths to the Prostate158 data. 85 86 Args: 87 path: Filepath to a folder where the data is downloaded for further processing. 88 split: The choice of data split. Either 'train', 'valid' or 'test'. 89 sequence: The MRI sequence to use as input. Either 't2', 'adc' or 'dwi'. 90 label_type: The type of annotations. Either 'anatomy' (prostate zones) or 'tumor' (cancer lesions). 91 download: Whether to download the data if it is not present. 92 93 Returns: 94 List of filepaths for the image data. 95 List of filepaths for the label data. 96 """ 97 if sequence not in ("t2", "adc", "dwi"): 98 raise ValueError(f"'{sequence}' is not a valid sequence.") 99 if label_type not in LABEL_COLUMNS: 100 raise ValueError(f"'{label_type}' is not a valid label type.") 101 102 data_dir = get_prostate158_data(path, split, download) 103 104 # The official csv files list the volumes per study, including empty tumor labels for studies without lesion. 105 with open(os.path.join(data_dir, f"{split}.csv"), "r") as f: 106 rows = list(csv.DictReader(f)) 107 108 raw_paths = [os.path.join(data_dir, row[sequence]) for row in rows] 109 label_paths = [os.path.join(data_dir, row[LABEL_COLUMNS[label_type]]) for row in rows] 110 111 missing = [p for p in raw_paths + label_paths if not os.path.exists(p)] 112 assert len(missing) == 0, f"The following files are missing: {missing}" 113 114 return raw_paths, label_paths 115 116 117def get_prostate158_dataset( 118 path: Union[os.PathLike, str], 119 patch_shape: Tuple[int, ...], 120 split: Literal["train", "valid", "test"], 121 sequence: Literal["t2", "adc", "dwi"] = "t2", 122 label_type: Literal["anatomy", "tumor"] = "anatomy", 123 resize_inputs: bool = False, 124 download: bool = False, 125 **kwargs 126) -> Dataset: 127 """Get the Prostate158 dataset for prostate zone and prostate cancer segmentation. 128 129 Args: 130 path: Filepath to a folder where the data is downloaded for further processing. 131 patch_shape: The patch shape to use for training. 132 split: The choice of data split. Either 'train', 'valid' or 'test'. 133 sequence: The MRI sequence to use as input. Either 't2', 'adc' or 'dwi'. 134 label_type: The type of annotations. Either 'anatomy' (prostate zones) or 'tumor' (cancer lesions). 135 resize_inputs: Whether to resize inputs to the desired patch shape. 136 download: Whether to download the data if it is not present. 137 kwargs: Additional keyword arguments for `torch_em.default_segmentation_dataset`. 138 139 Returns: 140 The segmentation dataset. 141 """ 142 raw_paths, label_paths = get_prostate158_paths(path, split, sequence, label_type, download) 143 144 if resize_inputs: 145 resize_kwargs = {"patch_shape": patch_shape, "is_rgb": False} 146 kwargs, patch_shape = util.update_kwargs_for_resize_trafo( 147 kwargs=kwargs, patch_shape=patch_shape, resize_inputs=resize_inputs, resize_kwargs=resize_kwargs 148 ) 149 150 return torch_em.default_segmentation_dataset( 151 raw_paths=raw_paths, 152 raw_key="data", 153 label_paths=label_paths, 154 label_key="data", 155 patch_shape=patch_shape, 156 is_seg_dataset=True, 157 **kwargs 158 ) 159 160 161def get_prostate158_loader( 162 path: Union[os.PathLike, str], 163 batch_size: int, 164 patch_shape: Tuple[int, ...], 165 split: Literal["train", "valid", "test"], 166 sequence: Literal["t2", "adc", "dwi"] = "t2", 167 label_type: Literal["anatomy", "tumor"] = "anatomy", 168 resize_inputs: bool = False, 169 download: bool = False, 170 **kwargs 171) -> DataLoader: 172 """Get the Prostate158 dataloader for prostate zone and prostate cancer segmentation. 173 174 Args: 175 path: Filepath to a folder where the data is downloaded for further processing. 176 batch_size: The batch size for training. 177 patch_shape: The patch shape to use for training. 178 split: The choice of data split. Either 'train', 'valid' or 'test'. 179 sequence: The MRI sequence to use as input. Either 't2', 'adc' or 'dwi'. 180 label_type: The type of annotations. Either 'anatomy' (prostate zones) or 'tumor' (cancer lesions). 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_prostate158_dataset( 190 path, patch_shape, split, sequence, label_type, resize_inputs, download, **ds_kwargs 191 ) 192 return torch_em.get_data_loader(dataset, batch_size, **loader_kwargs)
48def get_prostate158_data( 49 path: Union[os.PathLike, str], split: Literal["train", "valid", "test"], download: bool = False 50) -> str: 51 """Download the Prostate158 dataset. 52 53 Args: 54 path: Filepath to a folder where the data is downloaded for further processing. 55 split: The choice of data split. The 'train' and 'valid' splits share one archive, 'test' has its own. 56 download: Whether to download the data if it is not present. 57 58 Returns: 59 Filepath to the folder with the data of the requested split. 60 """ 61 if split not in ("train", "valid", "test"): 62 raise ValueError(f"'{split}' is not a valid split.") 63 64 archive = "test" if split == "test" else "train" 65 data_dir = os.path.join(path, f"prostate158_{archive}") 66 if os.path.exists(data_dir): 67 return data_dir 68 69 os.makedirs(path, exist_ok=True) 70 71 zip_path = os.path.join(path, f"prostate158_{archive}.zip") 72 util.download_source(path=zip_path, url=URLS[archive], download=download, checksum=CHECKSUMS[archive]) 73 util.unzip(zip_path=zip_path, dst=path) 74 75 return data_dir
Download the Prostate158 dataset.
Arguments:
- path: Filepath to a folder where the data is downloaded for further processing.
- split: The choice of data split. The 'train' and 'valid' splits share one archive, 'test' has its own.
- download: Whether to download the data if it is not present.
Returns:
Filepath to the folder with the data of the requested split.
78def get_prostate158_paths( 79 path: Union[os.PathLike, str], 80 split: Literal["train", "valid", "test"], 81 sequence: Literal["t2", "adc", "dwi"] = "t2", 82 label_type: Literal["anatomy", "tumor"] = "anatomy", 83 download: bool = False, 84) -> Tuple[List[str], List[str]]: 85 """Get paths to the Prostate158 data. 86 87 Args: 88 path: Filepath to a folder where the data is downloaded for further processing. 89 split: The choice of data split. Either 'train', 'valid' or 'test'. 90 sequence: The MRI sequence to use as input. Either 't2', 'adc' or 'dwi'. 91 label_type: The type of annotations. Either 'anatomy' (prostate zones) or 'tumor' (cancer lesions). 92 download: Whether to download the data if it is not present. 93 94 Returns: 95 List of filepaths for the image data. 96 List of filepaths for the label data. 97 """ 98 if sequence not in ("t2", "adc", "dwi"): 99 raise ValueError(f"'{sequence}' is not a valid sequence.") 100 if label_type not in LABEL_COLUMNS: 101 raise ValueError(f"'{label_type}' is not a valid label type.") 102 103 data_dir = get_prostate158_data(path, split, download) 104 105 # The official csv files list the volumes per study, including empty tumor labels for studies without lesion. 106 with open(os.path.join(data_dir, f"{split}.csv"), "r") as f: 107 rows = list(csv.DictReader(f)) 108 109 raw_paths = [os.path.join(data_dir, row[sequence]) for row in rows] 110 label_paths = [os.path.join(data_dir, row[LABEL_COLUMNS[label_type]]) for row in rows] 111 112 missing = [p for p in raw_paths + label_paths if not os.path.exists(p)] 113 assert len(missing) == 0, f"The following files are missing: {missing}" 114 115 return raw_paths, label_paths
Get paths to the Prostate158 data.
Arguments:
- path: Filepath to a folder where the data is downloaded for further processing.
- split: The choice of data split. Either 'train', 'valid' or 'test'.
- sequence: The MRI sequence to use as input. Either 't2', 'adc' or 'dwi'.
- label_type: The type of annotations. Either 'anatomy' (prostate zones) or 'tumor' (cancer lesions).
- 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.
118def get_prostate158_dataset( 119 path: Union[os.PathLike, str], 120 patch_shape: Tuple[int, ...], 121 split: Literal["train", "valid", "test"], 122 sequence: Literal["t2", "adc", "dwi"] = "t2", 123 label_type: Literal["anatomy", "tumor"] = "anatomy", 124 resize_inputs: bool = False, 125 download: bool = False, 126 **kwargs 127) -> Dataset: 128 """Get the Prostate158 dataset for prostate zone and prostate cancer segmentation. 129 130 Args: 131 path: Filepath to a folder where the data is downloaded for further processing. 132 patch_shape: The patch shape to use for training. 133 split: The choice of data split. Either 'train', 'valid' or 'test'. 134 sequence: The MRI sequence to use as input. Either 't2', 'adc' or 'dwi'. 135 label_type: The type of annotations. Either 'anatomy' (prostate zones) or 'tumor' (cancer lesions). 136 resize_inputs: Whether to resize inputs to the desired patch shape. 137 download: Whether to download the data if it is not present. 138 kwargs: Additional keyword arguments for `torch_em.default_segmentation_dataset`. 139 140 Returns: 141 The segmentation dataset. 142 """ 143 raw_paths, label_paths = get_prostate158_paths(path, split, sequence, label_type, download) 144 145 if resize_inputs: 146 resize_kwargs = {"patch_shape": patch_shape, "is_rgb": False} 147 kwargs, patch_shape = util.update_kwargs_for_resize_trafo( 148 kwargs=kwargs, patch_shape=patch_shape, resize_inputs=resize_inputs, resize_kwargs=resize_kwargs 149 ) 150 151 return torch_em.default_segmentation_dataset( 152 raw_paths=raw_paths, 153 raw_key="data", 154 label_paths=label_paths, 155 label_key="data", 156 patch_shape=patch_shape, 157 is_seg_dataset=True, 158 **kwargs 159 )
Get the Prostate158 dataset for prostate zone and prostate cancer segmentation.
Arguments:
- path: Filepath to a folder where the data is downloaded for further processing.
- patch_shape: The patch shape to use for training.
- split: The choice of data split. Either 'train', 'valid' or 'test'.
- sequence: The MRI sequence to use as input. Either 't2', 'adc' or 'dwi'.
- label_type: The type of annotations. Either 'anatomy' (prostate zones) or 'tumor' (cancer lesions).
- 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.
162def get_prostate158_loader( 163 path: Union[os.PathLike, str], 164 batch_size: int, 165 patch_shape: Tuple[int, ...], 166 split: Literal["train", "valid", "test"], 167 sequence: Literal["t2", "adc", "dwi"] = "t2", 168 label_type: Literal["anatomy", "tumor"] = "anatomy", 169 resize_inputs: bool = False, 170 download: bool = False, 171 **kwargs 172) -> DataLoader: 173 """Get the Prostate158 dataloader for prostate zone and prostate cancer 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 split: The choice of data split. Either 'train', 'valid' or 'test'. 180 sequence: The MRI sequence to use as input. Either 't2', 'adc' or 'dwi'. 181 label_type: The type of annotations. Either 'anatomy' (prostate zones) or 'tumor' (cancer lesions). 182 resize_inputs: Whether to resize inputs to the desired patch shape. 183 download: Whether to download the data if it is not present. 184 kwargs: Additional keyword arguments for `torch_em.default_segmentation_dataset` or for the PyTorch DataLoader. 185 186 Returns: 187 The DataLoader. 188 """ 189 ds_kwargs, loader_kwargs = util.split_kwargs(torch_em.default_segmentation_dataset, **kwargs) 190 dataset = get_prostate158_dataset( 191 path, patch_shape, split, sequence, label_type, resize_inputs, download, **ds_kwargs 192 ) 193 return torch_em.get_data_loader(dataset, batch_size, **loader_kwargs)
Get the Prostate158 dataloader for prostate zone and prostate cancer 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.
- split: The choice of data split. Either 'train', 'valid' or 'test'.
- sequence: The MRI sequence to use as input. Either 't2', 'adc' or 'dwi'.
- label_type: The type of annotations. Either 'anatomy' (prostate zones) or 'tumor' (cancer lesions).
- 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_datasetor for the PyTorch DataLoader.
Returns:
The DataLoader.