BraTS 0.0.0.dev0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- brats/__init__.py +16 -0
- brats/constants.py +268 -0
- brats/core/__init__.py +0 -0
- brats/core/brats_algorithm.py +264 -0
- brats/core/docker.py +474 -0
- brats/core/inpainting_algorithms.py +155 -0
- brats/core/missing_mri_algorithms.py +185 -0
- brats/core/segmentation_algorithms.py +491 -0
- brats/core/singularity.py +268 -0
- brats/data/meta/adult_glioma_pre_and_post_treatment.yml +123 -0
- brats/data/meta/adult_glioma_pre_treatment.yml +64 -0
- brats/data/meta/africa.yml +185 -0
- brats/data/meta/goat.yml +84 -0
- brats/data/meta/inpainting.yml +163 -0
- brats/data/meta/meningioma.yml +96 -0
- brats/data/meta/meningioma_rt.yml +113 -0
- brats/data/meta/metastases.yml +94 -0
- brats/data/meta/missing_mri.yml +125 -0
- brats/data/meta/pediatric.yml +168 -0
- brats/data/parameters/brats23_africa_sparkunn.yml +63 -0
- brats/data/parameters/brats23_inpainting_domaso.yml +44 -0
- brats/data/parameters/brats23_missing_mri_onembyte.yml +5 -0
- brats/data/parameters/brats24_adult_glioma_mist.yml +6 -0
- brats/data/parameters/brats24_inpainting_smint.yml +37 -0
- brats/data/parameters/brats24_missing_mri_cgv.yml +72 -0
- brats/data/parameters/dummy.yml +0 -0
- brats/preprocessing.py +435 -0
- brats/utils/__init__.py +0 -0
- brats/utils/algorithm_config.py +102 -0
- brats/utils/data_handling.py +116 -0
- brats/utils/exceptions.py +25 -0
- brats/utils/logging.py +73 -0
- brats/utils/zenodo.py +217 -0
- brats-0.0.0.dev0.dist-info/METADATA +581 -0
- brats-0.0.0.dev0.dist-info/RECORD +37 -0
- brats-0.0.0.dev0.dist-info/WHEEL +4 -0
- brats-0.0.0.dev0.dist-info/licenses/LICENSE +201 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import shutil
|
|
4
|
+
import sys
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Dict, List, Optional, Union
|
|
7
|
+
|
|
8
|
+
from loguru import logger
|
|
9
|
+
|
|
10
|
+
from brats.constants import MISSING_MRI_ALGORITHMS, MissingMRIAlgorithms, Task, Backends
|
|
11
|
+
from brats.core.brats_algorithm import BraTSAlgorithm
|
|
12
|
+
from brats.utils.data_handling import input_sanity_check
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class MissingMRI(BraTSAlgorithm):
|
|
16
|
+
|
|
17
|
+
def __init__(
|
|
18
|
+
self,
|
|
19
|
+
algorithm: MissingMRIAlgorithms = MissingMRIAlgorithms.BraTS24_1,
|
|
20
|
+
cuda_devices: str | None = "0",
|
|
21
|
+
force_cpu: bool = False,
|
|
22
|
+
):
|
|
23
|
+
super().__init__(
|
|
24
|
+
algorithm=algorithm,
|
|
25
|
+
algorithms_file_path=MISSING_MRI_ALGORITHMS,
|
|
26
|
+
task=Task.MISSING_MRI,
|
|
27
|
+
cuda_devices=cuda_devices,
|
|
28
|
+
force_cpu=force_cpu,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
def _standardize_single_inputs(
|
|
32
|
+
self,
|
|
33
|
+
data_folder: Path,
|
|
34
|
+
subject_id: str,
|
|
35
|
+
inputs: dict[str, Path | str],
|
|
36
|
+
subject_modality_separator: str,
|
|
37
|
+
) -> None:
|
|
38
|
+
"""
|
|
39
|
+
Standardize the input data to match the requirements of the selected algorithm.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
data_folder (Path): Path to the data folder
|
|
43
|
+
subject_id (str): Subject ID
|
|
44
|
+
inputs (dict[str, Path | str]): Dictionary with the input data
|
|
45
|
+
subject_modality_separator (str): Separator between the subject ID and the modality
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
subject_folder = data_folder / subject_id
|
|
49
|
+
subject_folder.mkdir(parents=True, exist_ok=True)
|
|
50
|
+
|
|
51
|
+
try:
|
|
52
|
+
for modality, path in inputs.items():
|
|
53
|
+
shutil.copy(
|
|
54
|
+
path,
|
|
55
|
+
subject_folder
|
|
56
|
+
/ f"{subject_id}{subject_modality_separator}{modality}.nii.gz",
|
|
57
|
+
)
|
|
58
|
+
except FileNotFoundError as e:
|
|
59
|
+
logger.error(f"Error while standardizing files: {e}")
|
|
60
|
+
raise
|
|
61
|
+
|
|
62
|
+
# sanity check inputs
|
|
63
|
+
input_sanity_check(
|
|
64
|
+
t1c=inputs.get("t1c"),
|
|
65
|
+
t1n=inputs.get("t1n"),
|
|
66
|
+
t2f=inputs.get("t2f"),
|
|
67
|
+
t2w=inputs.get("t2w"),
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
def _standardize_batch_inputs(
|
|
71
|
+
self,
|
|
72
|
+
data_folder: Path,
|
|
73
|
+
subjects: List[Path],
|
|
74
|
+
input_name_schema: str,
|
|
75
|
+
) -> Dict[str, str]:
|
|
76
|
+
"""Standardize the input images for a list of subjects to match requirements of all algorithms and save them in @tmp_data_folder/@subject_id.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
subjects (List[Path]): List of subject folders, each with a t1c, t1n, t2f, t2w image in standard format
|
|
80
|
+
data_folder (Path): Parent folder where the subject folders will be created
|
|
81
|
+
input_name_schema (str): Schema to be used for the subject folder and filenames depending on the BraTS Challenge
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
Dict[str, str]: Dictionary mapping internal name (in standardized format) to external subject name provided by user
|
|
85
|
+
"""
|
|
86
|
+
internal_external_name_map = {}
|
|
87
|
+
for i, subject in enumerate(subjects):
|
|
88
|
+
internal_name = input_name_schema.format(id=i)
|
|
89
|
+
internal_external_name_map[internal_name] = subject.name
|
|
90
|
+
|
|
91
|
+
# find relevant files in the subject folder
|
|
92
|
+
possible_inputs = {
|
|
93
|
+
"t1c": subject / f"{subject.name}-t1c.nii.gz",
|
|
94
|
+
"t1n": subject / f"{subject.name}-t1n.nii.gz",
|
|
95
|
+
"t2f": subject / f"{subject.name}-t2f.nii.gz",
|
|
96
|
+
"t2w": subject / f"{subject.name}-t2w.nii.gz",
|
|
97
|
+
}
|
|
98
|
+
valid_inputs = {k: v for k, v in possible_inputs.items() if v.exists()}
|
|
99
|
+
assert (
|
|
100
|
+
len(valid_inputs) == 3
|
|
101
|
+
), "Exactly 3 inputs are required to perform synthesis of the missing modality"
|
|
102
|
+
|
|
103
|
+
self._standardize_single_inputs(
|
|
104
|
+
data_folder=data_folder,
|
|
105
|
+
subject_id=internal_name,
|
|
106
|
+
inputs=valid_inputs,
|
|
107
|
+
subject_modality_separator=self.algorithm.run_args.subject_modality_separator,
|
|
108
|
+
)
|
|
109
|
+
return internal_external_name_map
|
|
110
|
+
|
|
111
|
+
def infer_single(
|
|
112
|
+
self,
|
|
113
|
+
output_file: Path | str,
|
|
114
|
+
t1c: Optional[Union[Path, str]] = None,
|
|
115
|
+
t1n: Optional[Union[Path, str]] = None,
|
|
116
|
+
t2f: Optional[Union[Path, str]] = None,
|
|
117
|
+
t2w: Optional[Union[Path, str]] = None,
|
|
118
|
+
log_file: Optional[Path | str] = None,
|
|
119
|
+
backend: Optional[Backends] = Backends.DOCKER,
|
|
120
|
+
) -> None:
|
|
121
|
+
"""
|
|
122
|
+
Perform synthesis of the missing modality for a single subject with the provided images and save the result to the output file.
|
|
123
|
+
|
|
124
|
+
Note:
|
|
125
|
+
Exactly 3 input modalities are required to perform synthesis of the missing modality.
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
output_file (Path | str): Output file to save the synthesized image
|
|
129
|
+
t1c (Optional[Union[Path, str]], optional): Path to the T1c image. Defaults to None.
|
|
130
|
+
t1n (Optional[Union[Path, str]], optional): Path to the T1n image. Defaults to None.
|
|
131
|
+
t2f (Optional[Union[Path, str]], optional): Path to the T2f image. Defaults to None.
|
|
132
|
+
t2w (Optional[Union[Path, str]], optional): Path to the T2w image. Defaults to None.
|
|
133
|
+
log_file (Optional[Path | str], optional): Save logs to this file. Defaults to None.
|
|
134
|
+
backend (Backends, optional): Backend to use for inference. Defaults to Backends.DOCKER.
|
|
135
|
+
"""
|
|
136
|
+
|
|
137
|
+
inputs = {"t1c": t1c, "t1n": t1n, "t2f": t2f, "t2w": t2w}
|
|
138
|
+
# filter out None values
|
|
139
|
+
inputs = {k: v for k, v in inputs.items() if v is not None}
|
|
140
|
+
|
|
141
|
+
# assert exactly 3 inputs are given (to compute the missing one)
|
|
142
|
+
assert (
|
|
143
|
+
len(inputs) == 3
|
|
144
|
+
), "Exactly 3 inputs are required to perform synthesis of the missing modality"
|
|
145
|
+
|
|
146
|
+
self._infer_single(
|
|
147
|
+
inputs=inputs,
|
|
148
|
+
output_file=output_file,
|
|
149
|
+
log_file=log_file,
|
|
150
|
+
backend=backend,
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
def infer_batch(
|
|
154
|
+
self,
|
|
155
|
+
data_folder: Path | str,
|
|
156
|
+
output_folder: Path | str,
|
|
157
|
+
log_file: Path | str | None = None,
|
|
158
|
+
backend: Optional[Backends] = Backends.DOCKER,
|
|
159
|
+
) -> None:
|
|
160
|
+
"""Perform synthesis on a batch of subjects with the provided images and save the results to the output folder. \n
|
|
161
|
+
|
|
162
|
+
Requires the following structure (if e.g. t2f should be synthesized):\n
|
|
163
|
+
data_folder\n
|
|
164
|
+
┣ A\n
|
|
165
|
+
┃ ┣ A-t1c.nii.gz\n
|
|
166
|
+
┃ ┣ A-t1n.nii.gz\n
|
|
167
|
+
┃ ┗ A-t2w.nii.gz\n
|
|
168
|
+
┣ B\n
|
|
169
|
+
┃ ┣ B-t1c.nii.gz\n
|
|
170
|
+
┃ ┣ ...\n
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
Args:
|
|
174
|
+
data_folder (Path | str): Folder containing the subjects with required structure
|
|
175
|
+
output_folder (Path | str): Output folder to save the segmentation
|
|
176
|
+
log_file (Path | str, optional): Save logs to this file
|
|
177
|
+
backend (Backends, optional): Backend to use for inference. Defaults to Backends.DOCKER.
|
|
178
|
+
"""
|
|
179
|
+
|
|
180
|
+
return self._infer_batch(
|
|
181
|
+
data_folder=data_folder,
|
|
182
|
+
output_folder=output_folder,
|
|
183
|
+
log_file=log_file,
|
|
184
|
+
backend=backend,
|
|
185
|
+
)
|
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import shutil
|
|
4
|
+
from abc import abstractmethod
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Dict, List, Mapping, Optional, Union
|
|
7
|
+
|
|
8
|
+
from loguru import logger
|
|
9
|
+
|
|
10
|
+
from brats.constants import (
|
|
11
|
+
ADULT_GLIOMA_PRE_AND_POST_TREATMENT_SEGMENTATION_ALGORITHMS,
|
|
12
|
+
ADULT_GLIOMA_PRE_TREATMENT_SEGMENTATION_ALGORITHMS,
|
|
13
|
+
AFRICA_SEGMENTATION_ALGORITHMS,
|
|
14
|
+
GOAT_SEGMENTATION_ALGORITHMS,
|
|
15
|
+
MENINGIOMA_RT_SEGMENTATION_ALGORITHMS,
|
|
16
|
+
MENINGIOMA_SEGMENTATION_ALGORITHMS,
|
|
17
|
+
METASTASES_SEGMENTATION_ALGORITHMS,
|
|
18
|
+
PEDIATRIC_SEGMENTATION_ALGORITHMS,
|
|
19
|
+
AdultGliomaPreAndPostTreatmentAlgorithms,
|
|
20
|
+
AdultGliomaPreTreatmentAlgorithms,
|
|
21
|
+
AfricaAlgorithms,
|
|
22
|
+
Algorithms,
|
|
23
|
+
GoATAlgorithms,
|
|
24
|
+
MeningiomaAlgorithms,
|
|
25
|
+
MeningiomaRTAlgorithms,
|
|
26
|
+
MetastasesAlgorithms,
|
|
27
|
+
PediatricAlgorithms,
|
|
28
|
+
Task,
|
|
29
|
+
Backends,
|
|
30
|
+
)
|
|
31
|
+
from brats.core.brats_algorithm import BraTSAlgorithm
|
|
32
|
+
from brats.utils.data_handling import input_sanity_check
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class SegmentationAlgorithm(BraTSAlgorithm):
|
|
36
|
+
"""This class provides algorithms to perform tumor segmentation on MRI data. It is the base class for all segmentation algorithms and provides the common interface for single and batch inference."""
|
|
37
|
+
|
|
38
|
+
def __init__(
|
|
39
|
+
self,
|
|
40
|
+
algorithm: Algorithms,
|
|
41
|
+
algorithms_file_path: Path,
|
|
42
|
+
cuda_devices: str = "0",
|
|
43
|
+
force_cpu: bool = False,
|
|
44
|
+
):
|
|
45
|
+
super().__init__(
|
|
46
|
+
algorithm=algorithm,
|
|
47
|
+
algorithms_file_path=algorithms_file_path,
|
|
48
|
+
task=Task.SEGMENTATION,
|
|
49
|
+
cuda_devices=cuda_devices,
|
|
50
|
+
force_cpu=force_cpu,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
def _standardize_single_inputs(
|
|
54
|
+
self,
|
|
55
|
+
data_folder: Path,
|
|
56
|
+
subject_id: str,
|
|
57
|
+
inputs: Mapping[str, Path | str],
|
|
58
|
+
subject_modality_separator: str,
|
|
59
|
+
) -> None:
|
|
60
|
+
"""Standardize the input images for a single subject to match requirements of all algorithms and save them in @data_folder/@subject_id.
|
|
61
|
+
Example:
|
|
62
|
+
Meaning, e.g. for adult glioma:
|
|
63
|
+
BraTS-GLI-00000-000 \n
|
|
64
|
+
┣ BraTS-GLI-00000-000-t1c.nii.gz \n
|
|
65
|
+
┣ BraTS-GLI-00000-000-t1n.nii.gz \n
|
|
66
|
+
┣ BraTS-GLI-00000-000-t2f.nii.gz \n
|
|
67
|
+
┗ BraTS-GLI-00000-000-t2w.nii.gz \n
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
data_folder (Path): Parent folder where the subject folder will be created
|
|
71
|
+
subject_id (str): Subject ID to be used for the folder and filenames
|
|
72
|
+
inputs (Dict[str, Path | str]): Dictionary with the input images
|
|
73
|
+
subject_modality_separator (str): Separator between the subject ID and the modality
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
subject_folder = data_folder / subject_id
|
|
77
|
+
subject_folder.mkdir(parents=True, exist_ok=True)
|
|
78
|
+
# TODO: investigate usage of symlinks (might cause issues on windows and would probably require different volume handling)
|
|
79
|
+
try:
|
|
80
|
+
for modality, path in inputs.items():
|
|
81
|
+
shutil.copy(
|
|
82
|
+
path,
|
|
83
|
+
subject_folder
|
|
84
|
+
/ f"{subject_id}{subject_modality_separator}{modality}.nii.gz",
|
|
85
|
+
)
|
|
86
|
+
except FileNotFoundError as e:
|
|
87
|
+
logger.error(f"Error while standardizing files: {e}")
|
|
88
|
+
logger.error(
|
|
89
|
+
"If you use batch processing please ensure the input files are in the correct format, i.e.:\n A/A-t1c.nii.gz, A/A-t1n.nii.gz, A/A-t2f.nii.gz, A/A-t2w.nii.gz"
|
|
90
|
+
)
|
|
91
|
+
raise
|
|
92
|
+
|
|
93
|
+
# sanity check inputs
|
|
94
|
+
input_sanity_check(
|
|
95
|
+
t1c=inputs.get("t1c"),
|
|
96
|
+
t1n=inputs.get("t1n"),
|
|
97
|
+
t2f=inputs.get("t2f"),
|
|
98
|
+
t2w=inputs.get("t2w"),
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
def _standardize_batch_inputs(
|
|
102
|
+
self,
|
|
103
|
+
data_folder: Path,
|
|
104
|
+
subjects: List[Path],
|
|
105
|
+
input_name_schema: str,
|
|
106
|
+
only_t1c: bool = False,
|
|
107
|
+
) -> Dict[str, str]:
|
|
108
|
+
"""Standardize the input images for a list of subjects to match requirements of all algorithms and save them in @tmp_data_folder/@subject_id.
|
|
109
|
+
|
|
110
|
+
Args:
|
|
111
|
+
subjects (List[Path]): List of subject folders, each with a t1c, t1n, t2f, t2w image in standard format
|
|
112
|
+
data_folder (Path): Parent folder where the subject folders will be created
|
|
113
|
+
input_name_schema (str): Schema to be used for the subject folder and filenames depending on the BraTS Challenge
|
|
114
|
+
only_t1c (bool, optional): If True, only the t1c image will be used. Defaults to False.
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
Dict[str, str]: Dictionary mapping internal name (in standardized format) to external subject name provided by user
|
|
118
|
+
"""
|
|
119
|
+
internal_external_name_map = {}
|
|
120
|
+
for i, subject in enumerate(subjects):
|
|
121
|
+
internal_name = input_name_schema.format(id=i)
|
|
122
|
+
internal_external_name_map[internal_name] = subject.name
|
|
123
|
+
|
|
124
|
+
inputs = {
|
|
125
|
+
"t1c": subject / f"{subject.name}-t1c.nii.gz",
|
|
126
|
+
}
|
|
127
|
+
if not only_t1c:
|
|
128
|
+
inputs["t1n"] = subject / f"{subject.name}-t1n.nii.gz"
|
|
129
|
+
inputs["t2f"] = subject / f"{subject.name}-t2f.nii.gz"
|
|
130
|
+
inputs["t2w"] = subject / f"{subject.name}-t2w.nii.gz"
|
|
131
|
+
|
|
132
|
+
self._standardize_single_inputs(
|
|
133
|
+
data_folder=data_folder,
|
|
134
|
+
subject_id=internal_name,
|
|
135
|
+
inputs=inputs,
|
|
136
|
+
subject_modality_separator=self.algorithm.run_args.subject_modality_separator,
|
|
137
|
+
)
|
|
138
|
+
return internal_external_name_map
|
|
139
|
+
|
|
140
|
+
@abstractmethod
|
|
141
|
+
def infer_single(
|
|
142
|
+
self,
|
|
143
|
+
*args,
|
|
144
|
+
**kwargs,
|
|
145
|
+
) -> None:
|
|
146
|
+
pass
|
|
147
|
+
|
|
148
|
+
@abstractmethod
|
|
149
|
+
def infer_batch(
|
|
150
|
+
self,
|
|
151
|
+
data_folder: Path | str,
|
|
152
|
+
output_folder: Path | str,
|
|
153
|
+
log_file: Path | str | None = None,
|
|
154
|
+
) -> None:
|
|
155
|
+
pass
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
class SegmentationAlgorithmWith4Modalities(SegmentationAlgorithm):
|
|
159
|
+
"""Segmentation algorithm that works with 4 modalities (T1c, T1n, T2f, T2w)."""
|
|
160
|
+
|
|
161
|
+
def infer_single(
|
|
162
|
+
self,
|
|
163
|
+
t1c: Path | str,
|
|
164
|
+
t1n: Path | str,
|
|
165
|
+
t2f: Path | str,
|
|
166
|
+
t2w: Path | str,
|
|
167
|
+
output_file: Path | str,
|
|
168
|
+
log_file: Optional[Path | str] = None,
|
|
169
|
+
backend: Optional[Backends] = Backends.DOCKER,
|
|
170
|
+
) -> None:
|
|
171
|
+
"""Perform segmentation on a single subject with the provided images and save the result to the output file.
|
|
172
|
+
|
|
173
|
+
Args:
|
|
174
|
+
t1c (Path | str): Path to the T1c image
|
|
175
|
+
t1n (Path | str): Path to the T1n image
|
|
176
|
+
t2f (Path | str): Path to the T2f image
|
|
177
|
+
t2w (Path | str): Path to the T2w image
|
|
178
|
+
output_file (Path | str): Path to save the segmentation
|
|
179
|
+
log_file (Path | str, optional): Save logs to this file
|
|
180
|
+
backend (Backends, optional): Backend to use for inference. Defaults to Backends.DOCKER.
|
|
181
|
+
"""
|
|
182
|
+
|
|
183
|
+
self._infer_single(
|
|
184
|
+
inputs={"t1c": t1c, "t1n": t1n, "t2f": t2f, "t2w": t2w},
|
|
185
|
+
output_file=output_file,
|
|
186
|
+
log_file=log_file,
|
|
187
|
+
backend=backend,
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
def infer_batch(
|
|
191
|
+
self,
|
|
192
|
+
data_folder: Path | str,
|
|
193
|
+
output_folder: Path | str,
|
|
194
|
+
log_file: Path | str | None = None,
|
|
195
|
+
backend: Optional[Backends] = Backends.DOCKER,
|
|
196
|
+
) -> None:
|
|
197
|
+
"""Perform segmentation on a batch of subjects with the provided images and save the results to the output folder. \n
|
|
198
|
+
Requires the following structure:\n
|
|
199
|
+
data_folder\n
|
|
200
|
+
┣ A\n
|
|
201
|
+
┃ ┣ A-t1c.nii.gz\n
|
|
202
|
+
┃ ┣ A-t1n.nii.gz\n
|
|
203
|
+
┃ ┣ A-t2f.nii.gz\n
|
|
204
|
+
┃ ┗ A-t2w.nii.gz\n
|
|
205
|
+
┣ B\n
|
|
206
|
+
┃ ┣ B-t1c.nii.gz\n
|
|
207
|
+
┃ ┣ ...\n
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
Args:
|
|
211
|
+
data_folder (Path | str): Folder containing the subjects with required structure
|
|
212
|
+
output_folder (Path | str): Output folder to save the segmentations
|
|
213
|
+
log_file (Path | str, optional): Save logs to this file
|
|
214
|
+
backend (Backends, optional): Backend to use for inference. Defaults to Backends.DOCKER.
|
|
215
|
+
"""
|
|
216
|
+
|
|
217
|
+
return self._infer_batch(
|
|
218
|
+
data_folder=data_folder,
|
|
219
|
+
output_folder=output_folder,
|
|
220
|
+
log_file=log_file,
|
|
221
|
+
backend=backend,
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
class AdultGliomaPreTreatmentSegmenter(SegmentationAlgorithmWith4Modalities):
|
|
226
|
+
"""Provides algorithms to perform tumor segmentation on adult glioma pre treatment MRI data.
|
|
227
|
+
|
|
228
|
+
Args:
|
|
229
|
+
algorithm (AdultGliomaPreTreatmentAlgorithms, optional): Select an algorithm. Defaults to AdultGliomaPreTreatmentAlgorithms.BraTS23_1.
|
|
230
|
+
cuda_devices (Optional[str], optional): Which cuda devices to use. Defaults to "0".
|
|
231
|
+
force_cpu (bool, optional): Execution will default to GPU, this flag allows forced CPU execution if the algorithm is compatible. Defaults to False.
|
|
232
|
+
"""
|
|
233
|
+
|
|
234
|
+
def __init__(
|
|
235
|
+
self,
|
|
236
|
+
algorithm: AdultGliomaPreTreatmentAlgorithms = AdultGliomaPreTreatmentAlgorithms.BraTS23_1,
|
|
237
|
+
cuda_devices: str = "0",
|
|
238
|
+
force_cpu: bool = False,
|
|
239
|
+
):
|
|
240
|
+
super().__init__(
|
|
241
|
+
algorithm=algorithm,
|
|
242
|
+
algorithms_file_path=ADULT_GLIOMA_PRE_TREATMENT_SEGMENTATION_ALGORITHMS,
|
|
243
|
+
cuda_devices=cuda_devices,
|
|
244
|
+
force_cpu=force_cpu,
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
class AdultGliomaPreAndPostTreatmentSegmenter(SegmentationAlgorithmWith4Modalities):
|
|
249
|
+
"""Provides algorithms to perform tumor segmentation on adult glioma pre and post treatment MRI data.
|
|
250
|
+
|
|
251
|
+
Args:
|
|
252
|
+
algorithm (AdultGliomaPreAndPostTreatmentAlgorithms, optional): Select an algorithm. Defaults to AdultGliomaPreAndPostTreatmentAlgorithms.BraTS25_1.
|
|
253
|
+
cuda_devices (Optional[str], optional): Which cuda devices to use. Defaults to "0".
|
|
254
|
+
force_cpu (bool, optional): Execution will default to GPU, this flag allows forced CPU execution if the algorithm is compatible. Defaults to False.
|
|
255
|
+
"""
|
|
256
|
+
|
|
257
|
+
def __init__(
|
|
258
|
+
self,
|
|
259
|
+
algorithm: AdultGliomaPreAndPostTreatmentAlgorithms = AdultGliomaPreAndPostTreatmentAlgorithms.BraTS25_1,
|
|
260
|
+
cuda_devices: str = "0",
|
|
261
|
+
force_cpu: bool = False,
|
|
262
|
+
):
|
|
263
|
+
super().__init__(
|
|
264
|
+
algorithm=algorithm,
|
|
265
|
+
algorithms_file_path=ADULT_GLIOMA_PRE_AND_POST_TREATMENT_SEGMENTATION_ALGORITHMS,
|
|
266
|
+
cuda_devices=cuda_devices,
|
|
267
|
+
force_cpu=force_cpu,
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
class MeningiomaSegmenter(SegmentationAlgorithmWith4Modalities):
|
|
272
|
+
"""Provides algorithms to perform tumor segmentation on adult meningioma MRI data.
|
|
273
|
+
|
|
274
|
+
Args:
|
|
275
|
+
algorithm (MeningiomaAlgorithms, optional): Select an algorithm. Defaults to MeningiomaAlgorithms.BraTS23_1.
|
|
276
|
+
cuda_devices (Optional[str], optional): Which cuda devices to use. Defaults to "0".
|
|
277
|
+
force_cpu (bool, optional): Execution will default to GPU, this flag allows forced CPU execution if the algorithm is compatible. Defaults to False.
|
|
278
|
+
"""
|
|
279
|
+
|
|
280
|
+
def __init__(
|
|
281
|
+
self,
|
|
282
|
+
algorithm: MeningiomaAlgorithms = MeningiomaAlgorithms.BraTS25_1,
|
|
283
|
+
cuda_devices: str = "0",
|
|
284
|
+
force_cpu: bool = False,
|
|
285
|
+
):
|
|
286
|
+
super().__init__(
|
|
287
|
+
algorithm=algorithm,
|
|
288
|
+
algorithms_file_path=MENINGIOMA_SEGMENTATION_ALGORITHMS,
|
|
289
|
+
cuda_devices=cuda_devices,
|
|
290
|
+
force_cpu=force_cpu,
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
class PediatricSegmenter(SegmentationAlgorithmWith4Modalities):
|
|
295
|
+
"""Provides algorithms to perform tumor segmentation on pediatric MRI data
|
|
296
|
+
|
|
297
|
+
Args:
|
|
298
|
+
algorithm (PediatricAlgorithms, optional): Select an algorithm. Defaults to PediatricAlgorithms.BraTS23_1.
|
|
299
|
+
cuda_devices (Optional[str], optional): Which cuda devices to use. Defaults to "0".
|
|
300
|
+
force_cpu (bool, optional): Execution will default to GPU, this flag allows forced CPU execution if the algorithm is compatible. Defaults to False.
|
|
301
|
+
"""
|
|
302
|
+
|
|
303
|
+
def __init__(
|
|
304
|
+
self,
|
|
305
|
+
algorithm: PediatricAlgorithms = PediatricAlgorithms.BraTS25_1,
|
|
306
|
+
cuda_devices: str = "0",
|
|
307
|
+
force_cpu: bool = False,
|
|
308
|
+
):
|
|
309
|
+
super().__init__(
|
|
310
|
+
algorithm=algorithm,
|
|
311
|
+
algorithms_file_path=PEDIATRIC_SEGMENTATION_ALGORITHMS,
|
|
312
|
+
cuda_devices=cuda_devices,
|
|
313
|
+
force_cpu=force_cpu,
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
class AfricaSegmenter(SegmentationAlgorithmWith4Modalities):
|
|
318
|
+
"""Provides algorithms from the BraTSAfrica challenge
|
|
319
|
+
|
|
320
|
+
Args:
|
|
321
|
+
algorithm (AfricaAlgorithms, optional): Select an algorithm. Defaults to AfricaAlgorithms.BraTS23_1.
|
|
322
|
+
cuda_devices (Optional[str], optional): Which cuda devices to use. Defaults to "0".
|
|
323
|
+
force_cpu (bool, optional): Execution will default to GPU, this flag allows forced CPU execution if the algorithm is compatible. Defaults to False.
|
|
324
|
+
"""
|
|
325
|
+
|
|
326
|
+
def __init__(
|
|
327
|
+
self,
|
|
328
|
+
algorithm: AfricaAlgorithms = AfricaAlgorithms.BraTS25_1,
|
|
329
|
+
cuda_devices: str = "0",
|
|
330
|
+
force_cpu: bool = False,
|
|
331
|
+
):
|
|
332
|
+
super().__init__(
|
|
333
|
+
algorithm=algorithm,
|
|
334
|
+
algorithms_file_path=AFRICA_SEGMENTATION_ALGORITHMS,
|
|
335
|
+
cuda_devices=cuda_devices,
|
|
336
|
+
force_cpu=force_cpu,
|
|
337
|
+
)
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
class MetastasesSegmenter(SegmentationAlgorithmWith4Modalities):
|
|
341
|
+
"""Provides algorithms from the Brain Metastases Segmentation challenge
|
|
342
|
+
|
|
343
|
+
Args:
|
|
344
|
+
algorithm (MetastasesAlgorithms, optional): Select an algorithm. Defaults to MetastasesAlgorithms.BraTS23_1.
|
|
345
|
+
cuda_devices (Optional[str], optional): Which cuda devices to use. Defaults to "0".
|
|
346
|
+
force_cpu (bool, optional): Execution will default to GPU, this flag allows forced CPU execution if the algorithm is compatible. Defaults to False.
|
|
347
|
+
"""
|
|
348
|
+
|
|
349
|
+
def __init__(
|
|
350
|
+
self,
|
|
351
|
+
algorithm: MetastasesAlgorithms = MetastasesAlgorithms.BraTS25_1,
|
|
352
|
+
cuda_devices: str = "0",
|
|
353
|
+
force_cpu: bool = False,
|
|
354
|
+
):
|
|
355
|
+
super().__init__(
|
|
356
|
+
algorithm=algorithm,
|
|
357
|
+
algorithms_file_path=METASTASES_SEGMENTATION_ALGORITHMS,
|
|
358
|
+
cuda_devices=cuda_devices,
|
|
359
|
+
force_cpu=force_cpu,
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
class GoATSegmenter(SegmentationAlgorithmWith4Modalities):
|
|
364
|
+
"""Provides algorithms from the BraTS Generalizability Across Tumors (BraTS-GoAT)
|
|
365
|
+
|
|
366
|
+
Args:
|
|
367
|
+
algorithm (GoATAlgorithms, optional): Select an algorithm. Defaults to GoATAlgorithms.BraTS23_1.
|
|
368
|
+
cuda_devices (Optional[str], optional): Which cuda devices to use. Defaults to "0".
|
|
369
|
+
force_cpu (bool, optional): Execution will default to GPU, this flag allows forced CPU execution if the algorithm is compatible. Defaults to False.
|
|
370
|
+
"""
|
|
371
|
+
|
|
372
|
+
def __init__(
|
|
373
|
+
self,
|
|
374
|
+
algorithm: GoATAlgorithms = GoATAlgorithms.BraTS25_1A,
|
|
375
|
+
cuda_devices: str = "0",
|
|
376
|
+
force_cpu: bool = False,
|
|
377
|
+
):
|
|
378
|
+
super().__init__(
|
|
379
|
+
algorithm=algorithm,
|
|
380
|
+
algorithms_file_path=GOAT_SEGMENTATION_ALGORITHMS,
|
|
381
|
+
cuda_devices=cuda_devices,
|
|
382
|
+
force_cpu=force_cpu,
|
|
383
|
+
)
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
### Radio Therapy specific segmenter (only T1C) ###
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
class MeningiomaRTSegmenter(SegmentationAlgorithm):
|
|
390
|
+
"""Provides algorithms to perform tumor segmentation on adult meningioma Radio Therapy MRI data.
|
|
391
|
+
|
|
392
|
+
Args:
|
|
393
|
+
algorithm (MeningiomaAlgorithms, optional): Select an algorithm. Defaults to MeningiomaAlgorithms.BraTS23_1.
|
|
394
|
+
cuda_devices (Optional[str], optional): Which cuda devices to use. Defaults to "0".
|
|
395
|
+
force_cpu (bool, optional): Execution will default to GPU, this flag allows forced CPU execution if the algorithm is compatible. Defaults to False.
|
|
396
|
+
"""
|
|
397
|
+
|
|
398
|
+
def __init__(
|
|
399
|
+
self,
|
|
400
|
+
algorithm: MeningiomaRTAlgorithms = MeningiomaRTAlgorithms.BraTS25_1,
|
|
401
|
+
cuda_devices: str = "0",
|
|
402
|
+
force_cpu: bool = False,
|
|
403
|
+
):
|
|
404
|
+
super().__init__(
|
|
405
|
+
algorithm=algorithm,
|
|
406
|
+
algorithms_file_path=MENINGIOMA_RT_SEGMENTATION_ALGORITHMS,
|
|
407
|
+
cuda_devices=cuda_devices,
|
|
408
|
+
force_cpu=force_cpu,
|
|
409
|
+
)
|
|
410
|
+
|
|
411
|
+
def _standardize_batch_inputs(
|
|
412
|
+
self,
|
|
413
|
+
data_folder: Path,
|
|
414
|
+
subjects: List[Path],
|
|
415
|
+
input_name_schema: str,
|
|
416
|
+
only_t1c: bool = False,
|
|
417
|
+
) -> Dict[str, str]:
|
|
418
|
+
"""Standardize the input images for a list of subjects to match requirements of all algorithms and save them in @tmp_data_folder/@subject_id.
|
|
419
|
+
|
|
420
|
+
Args:
|
|
421
|
+
subjects (List[Path]): List of subject folders, each with a t1c image in standard format
|
|
422
|
+
data_folder (Path): Parent folder where the subject folders will be created
|
|
423
|
+
input_name_schema (str): Schema to be used for the subject folder and filenames depending on the BraTS Challenge
|
|
424
|
+
|
|
425
|
+
Returns:
|
|
426
|
+
Dict[str, str]: Dictionary mapping internal name (in standardized format) to external subject name provided by user
|
|
427
|
+
"""
|
|
428
|
+
return super()._standardize_batch_inputs(
|
|
429
|
+
data_folder=data_folder,
|
|
430
|
+
subjects=subjects,
|
|
431
|
+
input_name_schema=input_name_schema,
|
|
432
|
+
only_t1c=True,
|
|
433
|
+
)
|
|
434
|
+
|
|
435
|
+
def infer_single(
|
|
436
|
+
self,
|
|
437
|
+
t1c: Union[Path, str],
|
|
438
|
+
output_file: Path | str,
|
|
439
|
+
log_file: Optional[Path | str] = None,
|
|
440
|
+
backend: Optional[Backends] = Backends.DOCKER,
|
|
441
|
+
) -> None:
|
|
442
|
+
"""
|
|
443
|
+
Perform segmentation on a single subject with the provided T1C image and save the result to the output file.
|
|
444
|
+
|
|
445
|
+
Args:
|
|
446
|
+
t1c (Path | str): Path to the T1c image
|
|
447
|
+
output_file (Path | str): Output file to save the segmentation.
|
|
448
|
+
log_file (Optional[Path | str], optional): Save logs to this file. Defaults to None.
|
|
449
|
+
backend (Backends, optional): Backend to use for inference. Defaults to Backends.DOCKER.
|
|
450
|
+
"""
|
|
451
|
+
|
|
452
|
+
self._infer_single(
|
|
453
|
+
inputs={"t1c": t1c},
|
|
454
|
+
output_file=output_file,
|
|
455
|
+
log_file=log_file,
|
|
456
|
+
backend=backend,
|
|
457
|
+
)
|
|
458
|
+
|
|
459
|
+
def infer_batch(
|
|
460
|
+
self,
|
|
461
|
+
data_folder: Path | str,
|
|
462
|
+
output_folder: Path | str,
|
|
463
|
+
log_file: Path | str | None = None,
|
|
464
|
+
backend: Optional[Backends] = Backends.DOCKER,
|
|
465
|
+
) -> None:
|
|
466
|
+
"""
|
|
467
|
+
Perform segmentation on a batch of subjects with the provided T1C images and save the results to the output folder. \n
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
Requires the following structure:\n
|
|
471
|
+
data_folder\n
|
|
472
|
+
┣ A\n
|
|
473
|
+
┃ ┗ A-t1c.nii.gz\n
|
|
474
|
+
┣ B\n
|
|
475
|
+
┃ ┗ B-t1c.nii.gz\n
|
|
476
|
+
┃ ...\n
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
Args:
|
|
480
|
+
data_folder (Path | str): Folder containing the subjects with required structure
|
|
481
|
+
output_folder (Path | str): Output folder to save the segmentations
|
|
482
|
+
log_file (Path | str, optional): Save logs to this file
|
|
483
|
+
backend (Backends, optional): Backend to use for inference. Defaults to Backends.DOCKER.
|
|
484
|
+
"""
|
|
485
|
+
|
|
486
|
+
return self._infer_batch(
|
|
487
|
+
data_folder=data_folder,
|
|
488
|
+
output_folder=output_folder,
|
|
489
|
+
log_file=log_file,
|
|
490
|
+
backend=backend,
|
|
491
|
+
)
|