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.
Files changed (37) hide show
  1. brats/__init__.py +16 -0
  2. brats/constants.py +268 -0
  3. brats/core/__init__.py +0 -0
  4. brats/core/brats_algorithm.py +264 -0
  5. brats/core/docker.py +474 -0
  6. brats/core/inpainting_algorithms.py +155 -0
  7. brats/core/missing_mri_algorithms.py +185 -0
  8. brats/core/segmentation_algorithms.py +491 -0
  9. brats/core/singularity.py +268 -0
  10. brats/data/meta/adult_glioma_pre_and_post_treatment.yml +123 -0
  11. brats/data/meta/adult_glioma_pre_treatment.yml +64 -0
  12. brats/data/meta/africa.yml +185 -0
  13. brats/data/meta/goat.yml +84 -0
  14. brats/data/meta/inpainting.yml +163 -0
  15. brats/data/meta/meningioma.yml +96 -0
  16. brats/data/meta/meningioma_rt.yml +113 -0
  17. brats/data/meta/metastases.yml +94 -0
  18. brats/data/meta/missing_mri.yml +125 -0
  19. brats/data/meta/pediatric.yml +168 -0
  20. brats/data/parameters/brats23_africa_sparkunn.yml +63 -0
  21. brats/data/parameters/brats23_inpainting_domaso.yml +44 -0
  22. brats/data/parameters/brats23_missing_mri_onembyte.yml +5 -0
  23. brats/data/parameters/brats24_adult_glioma_mist.yml +6 -0
  24. brats/data/parameters/brats24_inpainting_smint.yml +37 -0
  25. brats/data/parameters/brats24_missing_mri_cgv.yml +72 -0
  26. brats/data/parameters/dummy.yml +0 -0
  27. brats/preprocessing.py +435 -0
  28. brats/utils/__init__.py +0 -0
  29. brats/utils/algorithm_config.py +102 -0
  30. brats/utils/data_handling.py +116 -0
  31. brats/utils/exceptions.py +25 -0
  32. brats/utils/logging.py +73 -0
  33. brats/utils/zenodo.py +217 -0
  34. brats-0.0.0.dev0.dist-info/METADATA +581 -0
  35. brats-0.0.0.dev0.dist-info/RECORD +37 -0
  36. brats-0.0.0.dev0.dist-info/WHEEL +4 -0
  37. 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
+ )