torch_em.data.datasets.histopathology.histo_miner
The Histo-Miner dataset contains annotations for nucleus instance and semantic segmentation (NucSeg) and for tumor region segmentation (TumSeg) in H&E stained cutaneous squamous cell carcinoma (cSCC) histopathology images.
NOTE: The public deposit only exposes train and validation splits; the held-out TumSeg test split is released in a separate Zenodo record and is not covered by this loader.
This dataset is located at https://zenodo.org/records/15973142. This dataset is from the publication https://doi.org/10.1371/journal.pcbi.1013907. Please cite it if you use this dataset for your research.
1"""The Histo-Miner dataset contains annotations for nucleus instance and semantic segmentation 2(NucSeg) and for tumor region segmentation (TumSeg) in H&E stained cutaneous squamous cell 3carcinoma (cSCC) histopathology images. 4 5NOTE: The public deposit only exposes train and validation splits; the held-out TumSeg test 6split is released in a separate Zenodo record and is not covered by this loader. 7 8This dataset is located at https://zenodo.org/records/15973142. 9This dataset is from the publication https://doi.org/10.1371/journal.pcbi.1013907. 10Please cite it if you use this dataset for your research. 11""" 12 13import os 14from glob import glob 15from natsort import natsorted 16from typing import Union, Literal, Tuple, List 17 18import numpy as np 19import imageio.v3 as imageio 20 21from torch.utils.data import Dataset, DataLoader 22 23import torch_em 24 25from .. import util 26 27 28URLS = { 29 "nuclei": "https://zenodo.org/api/records/15973142/files/NucSeg_OriginalFormat.zip/content", 30 "tumor": "https://zenodo.org/api/records/15973142/files/TumSeg.zip/content", 31} 32 33CHECKSUMS = { 34 "nuclei": "6316b027ef50ce874e3f147f20a069f6c5ad9af5688d919c1ecf836301e6eccb", 35 "tumor": "8091907d84ef75cfa7cf5deff113f6d9d2a76f9269c29f095703165c4f91f682", 36} 37 38DATA_DIRNAMES = {"nuclei": "NucSeg_OriginalFormat", "tumor": "TumSeg"} 39 40 41def get_histo_miner_data( 42 path: Union[os.PathLike, str], task: Literal["nuclei", "tumor"], download: bool = False 43) -> str: 44 """Download the Histo-Miner data. 45 46 Args: 47 path: Filepath to a folder where the downloaded data will be saved. 48 task: The choice of task, either nucleus segmentation ('nuclei') or tumor region segmentation ('tumor'). 49 download: Whether to download the data if it is not present. 50 51 Returns: 52 Filepath where the dataset is downloaded and stored for further preprocessing. 53 """ 54 data_dir = os.path.join(path, DATA_DIRNAMES[task]) 55 if os.path.exists(data_dir): 56 return data_dir 57 58 os.makedirs(path, exist_ok=True) 59 zip_path = os.path.join(path, f"histo_miner_{task}.zip") 60 util.download_source(path=zip_path, url=URLS[task], download=download, checksum=CHECKSUMS[task]) 61 util.unzip(zip_path=zip_path, dst=path) 62 63 return data_dir 64 65 66def _convert_nuclei_npy_to_tif(data_dir, split_dir, label_choice): 67 label_dirname = "InstanceMaps" if label_choice == "instances" else "ClassMaps" 68 raw_dir = os.path.join(data_dir, split_dir, "RawImages") 69 label_dir = os.path.join(data_dir, split_dir, label_dirname) 70 71 converted_raw_dir = os.path.join(data_dir, split_dir, "RawImages_tif") 72 converted_label_dir = os.path.join(data_dir, split_dir, f"{label_dirname}_tif") 73 os.makedirs(converted_raw_dir, exist_ok=True) 74 os.makedirs(converted_label_dir, exist_ok=True) 75 76 raw_paths, label_paths = [], [] 77 for raw_path in natsorted(glob(os.path.join(raw_dir, "*.npy"))): 78 fname = os.path.basename(raw_path).replace(".npy", ".tif") 79 80 out_raw_path = os.path.join(converted_raw_dir, fname) 81 if not os.path.exists(out_raw_path): 82 imageio.imwrite(out_raw_path, np.load(raw_path)) 83 raw_paths.append(out_raw_path) 84 85 label_path = os.path.join(label_dir, os.path.basename(raw_path)) 86 out_label_path = os.path.join(converted_label_dir, fname) 87 if not os.path.exists(out_label_path): 88 imageio.imwrite(out_label_path, np.load(label_path).astype("int32")) 89 label_paths.append(out_label_path) 90 91 return raw_paths, label_paths 92 93 94def get_histo_miner_paths( 95 path: Union[os.PathLike, str], 96 split: Literal["train", "val"], 97 task: Literal["nuclei", "tumor"] = "nuclei", 98 label_choice: Literal["instances", "semantic"] = "instances", 99 download: bool = False, 100) -> Tuple[List[str], List[str]]: 101 """Get paths to the Histo-Miner data. 102 103 Args: 104 path: Filepath to a folder where the downloaded data will be saved. 105 split: The choice of data split. 106 task: The choice of task, either nucleus segmentation ('nuclei') or tumor region segmentation ('tumor'). 107 label_choice: The choice of label representation for the 'nuclei' task, either instance or semantic labels. 108 download: Whether to download the data if it is not present. 109 110 Returns: 111 List of filepaths to the image data. 112 List of filepaths to the label data. 113 """ 114 data_dir = get_histo_miner_data(path, task, download) 115 split_dir = "Train" if split == "train" else "Val" 116 117 if task == "nuclei": 118 raw_paths, label_paths = _convert_nuclei_npy_to_tif(data_dir, split_dir, label_choice) 119 else: 120 raw_paths = natsorted(glob(os.path.join(data_dir, split_dir, "images", "*.tif"))) 121 label_paths = natsorted(glob(os.path.join(data_dir, split_dir, "annotations", "*.png"))) 122 123 assert len(raw_paths) == len(label_paths) and len(raw_paths) > 0 124 return raw_paths, label_paths 125 126 127def get_histo_miner_dataset( 128 path: Union[os.PathLike, str], 129 patch_shape: Tuple[int, int], 130 split: Literal["train", "val"], 131 task: Literal["nuclei", "tumor"] = "nuclei", 132 label_choice: Literal["instances", "semantic"] = "instances", 133 resize_inputs: bool = False, 134 download: bool = False, 135 **kwargs 136) -> Dataset: 137 """Get the Histo-Miner dataset for nucleus or tumor region segmentation. 138 139 Args: 140 path: Filepath to a folder where the downloaded data will be saved. 141 patch_shape: The patch shape to use for training. 142 split: The choice of data split. 143 task: The choice of task, either nucleus segmentation ('nuclei') or tumor region segmentation ('tumor'). 144 label_choice: The choice of label representation for the 'nuclei' task, either instance or semantic labels. 145 resize_inputs: Whether to resize the inputs. 146 download: Whether to download the data if it is not present. 147 kwargs: Additional keyword arguments for `torch_em.default_segmentation_dataset`. 148 149 Returns: 150 The segmentation dataset. 151 """ 152 raw_paths, label_paths = get_histo_miner_paths(path, split, task, label_choice, download) 153 154 if resize_inputs: 155 resize_kwargs = {"patch_shape": patch_shape, "is_rgb": True} 156 kwargs, patch_shape = util.update_kwargs_for_resize_trafo( 157 kwargs=kwargs, patch_shape=patch_shape, resize_inputs=resize_inputs, resize_kwargs=resize_kwargs 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 with_channels=True, 168 ndim=2, 169 **kwargs 170 ) 171 172 173def get_histo_miner_loader( 174 path: Union[os.PathLike, str], 175 batch_size: int, 176 patch_shape: Tuple[int, int], 177 split: Literal["train", "val"], 178 task: Literal["nuclei", "tumor"] = "nuclei", 179 label_choice: Literal["instances", "semantic"] = "instances", 180 resize_inputs: bool = False, 181 download: bool = False, 182 **kwargs 183) -> DataLoader: 184 """Get the Histo-Miner dataloader for nucleus or tumor region segmentation. 185 186 Args: 187 path: Filepath to a folder where the downloaded data will be saved. 188 batch_size: The batch size for training. 189 patch_shape: The patch shape to use for training. 190 split: The choice of data split. 191 task: The choice of task, either nucleus segmentation ('nuclei') or tumor region segmentation ('tumor'). 192 label_choice: The choice of label representation for the 'nuclei' task, either instance or semantic labels. 193 resize_inputs: Whether to resize the inputs. 194 download: Whether to download the data if it is not present. 195 kwargs: Additional keyword arguments for `torch_em.default_segmentation_dataset` or for the PyTorch DataLoader. 196 197 Returns: 198 The DataLoader. 199 """ 200 ds_kwargs, loader_kwargs = util.split_kwargs(torch_em.default_segmentation_dataset, **kwargs) 201 dataset = get_histo_miner_dataset( 202 path, patch_shape, split, task, label_choice, resize_inputs, download, **ds_kwargs 203 ) 204 return torch_em.get_data_loader(dataset, batch_size, **loader_kwargs)
42def get_histo_miner_data( 43 path: Union[os.PathLike, str], task: Literal["nuclei", "tumor"], download: bool = False 44) -> str: 45 """Download the Histo-Miner data. 46 47 Args: 48 path: Filepath to a folder where the downloaded data will be saved. 49 task: The choice of task, either nucleus segmentation ('nuclei') or tumor region segmentation ('tumor'). 50 download: Whether to download the data if it is not present. 51 52 Returns: 53 Filepath where the dataset is downloaded and stored for further preprocessing. 54 """ 55 data_dir = os.path.join(path, DATA_DIRNAMES[task]) 56 if os.path.exists(data_dir): 57 return data_dir 58 59 os.makedirs(path, exist_ok=True) 60 zip_path = os.path.join(path, f"histo_miner_{task}.zip") 61 util.download_source(path=zip_path, url=URLS[task], download=download, checksum=CHECKSUMS[task]) 62 util.unzip(zip_path=zip_path, dst=path) 63 64 return data_dir
Download the Histo-Miner data.
Arguments:
- path: Filepath to a folder where the downloaded data will be saved.
- task: The choice of task, either nucleus segmentation ('nuclei') or tumor region segmentation ('tumor').
- download: Whether to download the data if it is not present.
Returns:
Filepath where the dataset is downloaded and stored for further preprocessing.
95def get_histo_miner_paths( 96 path: Union[os.PathLike, str], 97 split: Literal["train", "val"], 98 task: Literal["nuclei", "tumor"] = "nuclei", 99 label_choice: Literal["instances", "semantic"] = "instances", 100 download: bool = False, 101) -> Tuple[List[str], List[str]]: 102 """Get paths to the Histo-Miner data. 103 104 Args: 105 path: Filepath to a folder where the downloaded data will be saved. 106 split: The choice of data split. 107 task: The choice of task, either nucleus segmentation ('nuclei') or tumor region segmentation ('tumor'). 108 label_choice: The choice of label representation for the 'nuclei' task, either instance or semantic labels. 109 download: Whether to download the data if it is not present. 110 111 Returns: 112 List of filepaths to the image data. 113 List of filepaths to the label data. 114 """ 115 data_dir = get_histo_miner_data(path, task, download) 116 split_dir = "Train" if split == "train" else "Val" 117 118 if task == "nuclei": 119 raw_paths, label_paths = _convert_nuclei_npy_to_tif(data_dir, split_dir, label_choice) 120 else: 121 raw_paths = natsorted(glob(os.path.join(data_dir, split_dir, "images", "*.tif"))) 122 label_paths = natsorted(glob(os.path.join(data_dir, split_dir, "annotations", "*.png"))) 123 124 assert len(raw_paths) == len(label_paths) and len(raw_paths) > 0 125 return raw_paths, label_paths
Get paths to the Histo-Miner data.
Arguments:
- path: Filepath to a folder where the downloaded data will be saved.
- split: The choice of data split.
- task: The choice of task, either nucleus segmentation ('nuclei') or tumor region segmentation ('tumor').
- label_choice: The choice of label representation for the 'nuclei' task, either instance or semantic labels.
- download: Whether to download the data if it is not present.
Returns:
List of filepaths to the image data. List of filepaths to the label data.
128def get_histo_miner_dataset( 129 path: Union[os.PathLike, str], 130 patch_shape: Tuple[int, int], 131 split: Literal["train", "val"], 132 task: Literal["nuclei", "tumor"] = "nuclei", 133 label_choice: Literal["instances", "semantic"] = "instances", 134 resize_inputs: bool = False, 135 download: bool = False, 136 **kwargs 137) -> Dataset: 138 """Get the Histo-Miner dataset for nucleus or tumor region segmentation. 139 140 Args: 141 path: Filepath to a folder where the downloaded data will be saved. 142 patch_shape: The patch shape to use for training. 143 split: The choice of data split. 144 task: The choice of task, either nucleus segmentation ('nuclei') or tumor region segmentation ('tumor'). 145 label_choice: The choice of label representation for the 'nuclei' task, either instance or semantic labels. 146 resize_inputs: Whether to resize the inputs. 147 download: Whether to download the data if it is not present. 148 kwargs: Additional keyword arguments for `torch_em.default_segmentation_dataset`. 149 150 Returns: 151 The segmentation dataset. 152 """ 153 raw_paths, label_paths = get_histo_miner_paths(path, split, task, label_choice, download) 154 155 if resize_inputs: 156 resize_kwargs = {"patch_shape": patch_shape, "is_rgb": True} 157 kwargs, patch_shape = util.update_kwargs_for_resize_trafo( 158 kwargs=kwargs, patch_shape=patch_shape, resize_inputs=resize_inputs, resize_kwargs=resize_kwargs 159 ) 160 161 return torch_em.default_segmentation_dataset( 162 raw_paths=raw_paths, 163 raw_key=None, 164 label_paths=label_paths, 165 label_key=None, 166 is_seg_dataset=False, 167 patch_shape=patch_shape, 168 with_channels=True, 169 ndim=2, 170 **kwargs 171 )
Get the Histo-Miner dataset for nucleus or tumor region 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 choice of data split.
- task: The choice of task, either nucleus segmentation ('nuclei') or tumor region segmentation ('tumor').
- label_choice: The choice of label representation for the 'nuclei' task, either instance or semantic labels.
- resize_inputs: Whether to resize the inputs.
- 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.
174def get_histo_miner_loader( 175 path: Union[os.PathLike, str], 176 batch_size: int, 177 patch_shape: Tuple[int, int], 178 split: Literal["train", "val"], 179 task: Literal["nuclei", "tumor"] = "nuclei", 180 label_choice: Literal["instances", "semantic"] = "instances", 181 resize_inputs: bool = False, 182 download: bool = False, 183 **kwargs 184) -> DataLoader: 185 """Get the Histo-Miner dataloader for nucleus or tumor region segmentation. 186 187 Args: 188 path: Filepath to a folder where the downloaded data will be saved. 189 batch_size: The batch size for training. 190 patch_shape: The patch shape to use for training. 191 split: The choice of data split. 192 task: The choice of task, either nucleus segmentation ('nuclei') or tumor region segmentation ('tumor'). 193 label_choice: The choice of label representation for the 'nuclei' task, either instance or semantic labels. 194 resize_inputs: Whether to resize the inputs. 195 download: Whether to download the data if it is not present. 196 kwargs: Additional keyword arguments for `torch_em.default_segmentation_dataset` or for the PyTorch DataLoader. 197 198 Returns: 199 The DataLoader. 200 """ 201 ds_kwargs, loader_kwargs = util.split_kwargs(torch_em.default_segmentation_dataset, **kwargs) 202 dataset = get_histo_miner_dataset( 203 path, patch_shape, split, task, label_choice, resize_inputs, download, **ds_kwargs 204 ) 205 return torch_em.get_data_loader(dataset, batch_size, **loader_kwargs)
Get the Histo-Miner dataloader for nucleus or tumor region 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 choice of data split.
- task: The choice of task, either nucleus segmentation ('nuclei') or tumor region segmentation ('tumor').
- label_choice: The choice of label representation for the 'nuclei' task, either instance or semantic labels.
- resize_inputs: Whether to resize the inputs.
- 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.