GANDLF 0.1.4.dev20250609__py3-none-any.whl → 0.1.4.dev20250610__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.
Potentially problematic release.
This version of GANDLF might be problematic. Click here for more details.
- GANDLF/cli/generate_metrics.py +20 -7
- GANDLF/metrics/panoptica_config_brats.yaml +12 -6
- GANDLF/utils/__init__.py +1 -0
- GANDLF/utils/imaging.py +55 -33
- GANDLF/version.py +1 -1
- {gandlf-0.1.4.dev20250609.dist-info → gandlf-0.1.4.dev20250610.dist-info}/METADATA +1 -1
- {gandlf-0.1.4.dev20250609.dist-info → gandlf-0.1.4.dev20250610.dist-info}/RECORD +11 -11
- {gandlf-0.1.4.dev20250609.dist-info → gandlf-0.1.4.dev20250610.dist-info}/WHEEL +0 -0
- {gandlf-0.1.4.dev20250609.dist-info → gandlf-0.1.4.dev20250610.dist-info}/entry_points.txt +0 -0
- {gandlf-0.1.4.dev20250609.dist-info → gandlf-0.1.4.dev20250610.dist-info}/licenses/LICENSE +0 -0
- {gandlf-0.1.4.dev20250609.dist-info → gandlf-0.1.4.dev20250610.dist-info}/top_level.txt +0 -0
GANDLF/cli/generate_metrics.py
CHANGED
|
@@ -10,7 +10,11 @@ import SimpleITK as sitk
|
|
|
10
10
|
import numpy as np
|
|
11
11
|
|
|
12
12
|
from GANDLF.config_manager import ConfigManager
|
|
13
|
-
from GANDLF.utils import
|
|
13
|
+
from GANDLF.utils import (
|
|
14
|
+
find_problem_type_from_parameters,
|
|
15
|
+
one_hot,
|
|
16
|
+
sanity_check_on_file_readers,
|
|
17
|
+
)
|
|
14
18
|
from GANDLF.metrics import (
|
|
15
19
|
overall_stats,
|
|
16
20
|
structural_similarity_index,
|
|
@@ -176,6 +180,9 @@ def generate_metrics_dict(
|
|
|
176
180
|
for _, row in tqdm(input_df.iterrows(), total=input_df.shape[0]):
|
|
177
181
|
current_subject_id = row["SubjectID"]
|
|
178
182
|
overall_stats_dict[current_subject_id] = {}
|
|
183
|
+
sanity_check_on_file_readers(
|
|
184
|
+
row["Target"], row["Prediction"], current_subject_id
|
|
185
|
+
)
|
|
179
186
|
label_image = torchio.LabelMap(row["Target"])
|
|
180
187
|
pred_image = torchio.LabelMap(row["Prediction"])
|
|
181
188
|
label_tensor = label_image.data
|
|
@@ -264,17 +271,20 @@ def generate_metrics_dict(
|
|
|
264
271
|
for _, row in tqdm(input_df.iterrows(), total=input_df.shape[0]):
|
|
265
272
|
current_subject_id = row["SubjectID"]
|
|
266
273
|
overall_stats_dict[current_subject_id] = {}
|
|
274
|
+
sanity_check_on_file_readers(
|
|
275
|
+
row["Target"], row["Prediction"], current_subject_id
|
|
276
|
+
)
|
|
267
277
|
label_image = torchio.LabelMap(row["Target"])
|
|
268
278
|
pred_image = torchio.LabelMap(row["Prediction"])
|
|
269
279
|
label_tensor = label_image.data
|
|
270
280
|
pred_tensor = pred_image.data
|
|
271
281
|
spacing = label_image.spacing
|
|
272
|
-
if label_tensor.data.shape[-1] == 1:
|
|
273
|
-
|
|
274
|
-
#
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
282
|
+
# if label_tensor.data.shape[-1] == 1:
|
|
283
|
+
# spacing = spacing[0:2]
|
|
284
|
+
# remove dimension to ensure 3D tensors
|
|
285
|
+
if label_tensor.data.ndim == 4:
|
|
286
|
+
label_array = label_tensor.squeeze(0).numpy().astype(int)
|
|
287
|
+
pred_array = pred_tensor.squeeze(0).numpy().astype(int)
|
|
278
288
|
|
|
279
289
|
overall_stats_dict[current_subject_id] = generate_instance_segmentation(
|
|
280
290
|
prediction=pred_array, target=label_array
|
|
@@ -340,6 +350,9 @@ def generate_metrics_dict(
|
|
|
340
350
|
for _, row in tqdm(input_df.iterrows(), total=input_df.shape[0]):
|
|
341
351
|
current_subject_id = row["SubjectID"]
|
|
342
352
|
overall_stats_dict[current_subject_id] = {}
|
|
353
|
+
sanity_check_on_file_readers(
|
|
354
|
+
row["Target"], row["Prediction"], current_subject_id
|
|
355
|
+
)
|
|
343
356
|
target_image = __fix_2d_tensor(torchio.ScalarImage(row["Target"]).data)
|
|
344
357
|
pred_image = __fix_2d_tensor(torchio.ScalarImage(row["Prediction"]).data)
|
|
345
358
|
# if "Mask" is not in the row, we assume that the whole image is the mask
|
|
@@ -13,7 +13,10 @@ edge_case_handler: !EdgeCaseHandler
|
|
|
13
13
|
!Metric IOU: !MetricZeroTPEdgeCaseHandling {empty_prediction_result: !EdgeCaseResult ZERO,
|
|
14
14
|
empty_reference_result: !EdgeCaseResult ZERO, no_instances_result: !EdgeCaseResult NAN,
|
|
15
15
|
normal: !EdgeCaseResult ZERO}
|
|
16
|
-
!Metric
|
|
16
|
+
!Metric NSD: !MetricZeroTPEdgeCaseHandling {empty_prediction_result: !EdgeCaseResult INF,
|
|
17
|
+
empty_reference_result: !EdgeCaseResult INF, no_instances_result: !EdgeCaseResult NAN,
|
|
18
|
+
normal: !EdgeCaseResult INF}
|
|
19
|
+
!Metric HD95: !MetricZeroTPEdgeCaseHandling {empty_prediction_result: !EdgeCaseResult INF,
|
|
17
20
|
empty_reference_result: !EdgeCaseResult INF, no_instances_result: !EdgeCaseResult NAN,
|
|
18
21
|
normal: !EdgeCaseResult INF}
|
|
19
22
|
!Metric RVD: !MetricZeroTPEdgeCaseHandling {empty_prediction_result: !EdgeCaseResult NAN,
|
|
@@ -27,24 +30,27 @@ global_metrics: [!Metric DSC]
|
|
|
27
30
|
instance_approximator: !ConnectedComponentsInstanceApproximator {cca_backend: null}
|
|
28
31
|
instance_matcher: !NaiveThresholdMatching {allow_many_to_one: false, matching_metric: !Metric IOU,
|
|
29
32
|
matching_threshold: 0.5}
|
|
30
|
-
instance_metrics: [!Metric DSC, !Metric IOU, !Metric
|
|
33
|
+
instance_metrics: [!Metric DSC, !Metric IOU, !Metric RVD, !Metric NSD, !Metric HD95]
|
|
31
34
|
log_times: false
|
|
32
35
|
save_group_times: false
|
|
33
36
|
segmentation_class_groups: !SegmentationClassGroups
|
|
34
37
|
groups:
|
|
35
|
-
|
|
38
|
+
snfh: !LabelGroup
|
|
36
39
|
single_instance: false
|
|
37
40
|
value_labels: [2]
|
|
38
41
|
et: !LabelGroup
|
|
39
42
|
single_instance: false
|
|
40
43
|
value_labels: [3]
|
|
41
|
-
|
|
44
|
+
netc: !LabelGroup
|
|
42
45
|
single_instance: false
|
|
43
46
|
value_labels: [1]
|
|
47
|
+
rc: !LabelGroup
|
|
48
|
+
single_instance: false
|
|
49
|
+
value_labels: [4]
|
|
44
50
|
tc: !LabelMergeGroup
|
|
45
51
|
single_instance: false
|
|
46
|
-
value_labels: [1, 3]
|
|
52
|
+
value_labels: [1, 3, 4]
|
|
47
53
|
wt: !LabelMergeGroup
|
|
48
54
|
single_instance: false
|
|
49
|
-
value_labels: [1, 2, 3]
|
|
55
|
+
value_labels: [1, 2, 3, 4]
|
|
50
56
|
verbose: false
|
GANDLF/utils/__init__.py
CHANGED
GANDLF/utils/imaging.py
CHANGED
|
@@ -123,6 +123,56 @@ def softer_sanity_check(
|
|
|
123
123
|
return result
|
|
124
124
|
|
|
125
125
|
|
|
126
|
+
def sanity_check_on_file_readers(
|
|
127
|
+
file_reader_0: Union[str, sitk.ImageFileReader],
|
|
128
|
+
file_reader_1: Union[str, sitk.ImageFileReader],
|
|
129
|
+
subject_id: Optional[str] = "",
|
|
130
|
+
threshold: Optional[float] = 0.00001,
|
|
131
|
+
) -> bool:
|
|
132
|
+
"""
|
|
133
|
+
This function performs a sanity check on the file readers to ensure that the properties of the images are consistent.
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
file_reader_0 (Union[str, sitk.ImageFileReader]): The first file reader.
|
|
137
|
+
file_reader_1 (Union[str, sitk.ImageFileReader]): The second file reader.
|
|
138
|
+
threshold (Optional[float], optional): The threshold for comparison. Defaults to 0.00001.
|
|
139
|
+
|
|
140
|
+
Returns:
|
|
141
|
+
bool: True if the sanity check passes.
|
|
142
|
+
"""
|
|
143
|
+
|
|
144
|
+
if isinstance(file_reader_0, str):
|
|
145
|
+
temp_file = file_reader_0
|
|
146
|
+
file_reader_0 = sitk.ImageFileReader()
|
|
147
|
+
file_reader_0.SetFileName(temp_file)
|
|
148
|
+
file_reader_0.ReadImageInformation()
|
|
149
|
+
|
|
150
|
+
if isinstance(file_reader_1, str):
|
|
151
|
+
temp_file = file_reader_1
|
|
152
|
+
file_reader_1 = sitk.ImageFileReader()
|
|
153
|
+
file_reader_1.SetFileName(temp_file)
|
|
154
|
+
file_reader_1.ReadImageInformation()
|
|
155
|
+
# this check needs to be absolute
|
|
156
|
+
assert file_reader_0.GetDimension() == file_reader_1.GetDimension(), (
|
|
157
|
+
"Dimensions for Subject '" + subject_id + "' are not consistent."
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
# other checks can be softer
|
|
161
|
+
assert softer_sanity_check(
|
|
162
|
+
file_reader_0.GetOrigin(), file_reader_1.GetOrigin(), threshold=threshold
|
|
163
|
+
), ("Origin for Subject '" + subject_id + "' are not consistent.")
|
|
164
|
+
|
|
165
|
+
assert softer_sanity_check(
|
|
166
|
+
file_reader_0.GetDirection(), file_reader_1.GetDirection(), threshold=threshold
|
|
167
|
+
), ("Orientation for Subject '" + subject_id + "' are not consistent.")
|
|
168
|
+
|
|
169
|
+
assert softer_sanity_check(
|
|
170
|
+
file_reader_0.GetSpacing(), file_reader_1.GetSpacing(), threshold=threshold
|
|
171
|
+
), ("Spacing for Subject '" + subject_id + "' are not consistent.")
|
|
172
|
+
|
|
173
|
+
return True
|
|
174
|
+
|
|
175
|
+
|
|
126
176
|
def perform_sanity_check_on_subject(subject: torchio.Subject, parameters: dict) -> bool:
|
|
127
177
|
"""
|
|
128
178
|
This function performs a sanity check on the image modalities in input subject to ensure that they are consistent.
|
|
@@ -169,39 +219,11 @@ def perform_sanity_check_on_subject(subject: torchio.Subject, parameters: dict)
|
|
|
169
219
|
else:
|
|
170
220
|
file_reader_current = _get_itkimage_or_filereader(subject[str(key)])
|
|
171
221
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
"Dimensions for Subject '"
|
|
178
|
-
+ subject["subject_id"]
|
|
179
|
-
+ "' are not consistent."
|
|
180
|
-
)
|
|
181
|
-
|
|
182
|
-
# other checks can be softer
|
|
183
|
-
assert softer_sanity_check(
|
|
184
|
-
file_reader_base.GetOrigin(), file_reader_current.GetOrigin()
|
|
185
|
-
), (
|
|
186
|
-
"Origin for Subject '"
|
|
187
|
-
+ subject["subject_id"]
|
|
188
|
-
+ "' are not consistent."
|
|
189
|
-
)
|
|
190
|
-
|
|
191
|
-
assert softer_sanity_check(
|
|
192
|
-
file_reader_base.GetDirection(), file_reader_current.GetDirection()
|
|
193
|
-
), (
|
|
194
|
-
"Orientation for Subject '"
|
|
195
|
-
+ subject["subject_id"]
|
|
196
|
-
+ "' are not consistent."
|
|
197
|
-
)
|
|
198
|
-
|
|
199
|
-
assert softer_sanity_check(
|
|
200
|
-
file_reader_base.GetSpacing(), file_reader_current.GetSpacing()
|
|
201
|
-
), (
|
|
202
|
-
"Spacing for Subject '"
|
|
203
|
-
+ subject["subject_id"]
|
|
204
|
-
+ "' are not consistent."
|
|
222
|
+
sanity_check_on_file_readers(
|
|
223
|
+
file_reader_base,
|
|
224
|
+
file_reader_current,
|
|
225
|
+
subject_id=subject["subject_id"],
|
|
226
|
+
threshold=parameters.get("sanity_check_threshold", 0.00001),
|
|
205
227
|
)
|
|
206
228
|
|
|
207
229
|
return True
|
GANDLF/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.1.4-
|
|
1
|
+
__version__ = "0.1.4-dev20250610"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: GANDLF
|
|
3
|
-
Version: 0.1.4.
|
|
3
|
+
Version: 0.1.4.dev20250610
|
|
4
4
|
Summary: PyTorch-based framework that handles segmentation/regression/classification using various DL architectures for medical imaging.
|
|
5
5
|
Author: MLCommons
|
|
6
6
|
Author-email: gandlf@mlcommons.org
|
|
@@ -5,14 +5,14 @@ GANDLF/logger.py,sha256=oamQ1SOTTpAnC8vQ67o211Q6_bExGg_hAuqlHGlJfAI,2951
|
|
|
5
5
|
GANDLF/logging_config.yaml,sha256=9XxRxAKtLn5ehT1khpR8wEiJGW64sx1lylAspM5KaWk,1337
|
|
6
6
|
GANDLF/parseConfig.py,sha256=jO-ybIPxLw23OWDvFdTukbft0ZM8UOofGnoL2C5CEps,754
|
|
7
7
|
GANDLF/training_manager.py,sha256=AZlf-fl7KAwZgyre8-0M5lAyma6NvtiGX6XT51AJdxU,11436
|
|
8
|
-
GANDLF/version.py,sha256=
|
|
8
|
+
GANDLF/version.py,sha256=TSEmkWJ598nnrig3HD41R2tUwAc3_g0b31QBDWk3VBc,34
|
|
9
9
|
GANDLF/anonymize/__init__.py,sha256=Nxig-jM-a-aKlK09PNi1zhNulEpLTyjnsY_oGQKdjhQ,1953
|
|
10
10
|
GANDLF/anonymize/convert_to_nifti.py,sha256=MOfSDncFGJGb-EQP9sFGn0yuKpX010Ioi2KNwttaex8,1339
|
|
11
11
|
GANDLF/cli/__init__.py,sha256=F05eyL2HKyWkHczRZuPE_Z2Yg685P9ARYxTwz6njGeQ,784
|
|
12
12
|
GANDLF/cli/config_generator.py,sha256=_j0aRV3puiIItJ1WOHRNVII_TkGJuH9ep6SuwPblcnc,4502
|
|
13
13
|
GANDLF/cli/data_split_saver.py,sha256=72ygy9s3INt2NFAfSW4j9dxxmuuvfzfBTF0Hwh0nYBU,1720
|
|
14
14
|
GANDLF/cli/deploy.py,sha256=7yPqRox6e5MB-VzHxmA4kt-W5dWwElxDm1mm019jN74,15155
|
|
15
|
-
GANDLF/cli/generate_metrics.py,sha256=
|
|
15
|
+
GANDLF/cli/generate_metrics.py,sha256=CsQC8oWWEFRfZXQet_qrtTYfWn16o3jXdOh_3976GvU,20406
|
|
16
16
|
GANDLF/cli/huggingface_hub_handler.py,sha256=vGQYwDiT3Y8yk_xLNkB8DgW1rYpEcwYp0TCdCO5oWTs,4631
|
|
17
17
|
GANDLF/cli/main_run.py,sha256=gYNJQGvmwqBjj3ARRxj-y3R1PMOP4qTwcwFSRBbkh0k,4352
|
|
18
18
|
GANDLF/cli/patch_extraction.py,sha256=30RpBfjpwE9GLRSSD7JRqwoHngESQL0eOt09n_5r18Q,3555
|
|
@@ -108,7 +108,7 @@ GANDLF/metrics/__init__.py,sha256=k8xcpujpUg22R33keOUNetzrLnGSHsEAmClkFeDHZxc,44
|
|
|
108
108
|
GANDLF/metrics/classification.py,sha256=6rVZjXxHwfJFqw19UiRMYK3uF656QgfMwWDz-LOHUaw,4692
|
|
109
109
|
GANDLF/metrics/generic.py,sha256=N-h9sDwuAsskK7AdZ2N0otcbFTmKxh9kdyi6MQkDO60,4983
|
|
110
110
|
GANDLF/metrics/metric_calculators.py,sha256=c-NAl84yniTWjMKePBlf0TsCIJnYHODplt8HeEk9Uac,3610
|
|
111
|
-
GANDLF/metrics/panoptica_config_brats.yaml,sha256=
|
|
111
|
+
GANDLF/metrics/panoptica_config_brats.yaml,sha256=mTGSQuJoENuy84gZd2tHV0Dfl7GX5nIeE_46q5Vczx4,2685
|
|
112
112
|
GANDLF/metrics/regression.py,sha256=Ca58jo9OL1GdjB2ZvQCcrKWz9F67iY5rcbnQxT-LpcU,4584
|
|
113
113
|
GANDLF/metrics/segmentation.py,sha256=zqWEI6LuphFM0Nsm0sG2XeqAxpNJnoK1Z9q4FJt58c8,25645
|
|
114
114
|
GANDLF/metrics/segmentation_panoptica.py,sha256=ExbobmLhlyKYRKE7zEhZmuHtu5fdIUDs-53K-u4AKX8,1026
|
|
@@ -169,22 +169,22 @@ GANDLF/privacy/opacus/training_utils.py,sha256=ejXUIhLNjRzTebF-7uCYUluK7jyINDOpL
|
|
|
169
169
|
GANDLF/schedulers/__init__.py,sha256=jMTea7kX7zawFrtjVDKHDLIfBgt7GD-G2z9_eKjI1_A,1320
|
|
170
170
|
GANDLF/schedulers/wrap_monai.py,sha256=_kP3ArUIFK3x3u0nQV8Gi2oPruMIGGTSZxa4bSygGPs,400
|
|
171
171
|
GANDLF/schedulers/wrap_torch.py,sha256=NuCAmYMKgYeFzO1PEiHfnFaHpzuQU0DsK5NOi-gVxOo,6746
|
|
172
|
-
GANDLF/utils/__init__.py,sha256=
|
|
172
|
+
GANDLF/utils/__init__.py,sha256=F74QIQ6dZL8cOIsZkU-VfDdcHewUW959GXRvDfphGCk,1725
|
|
173
173
|
GANDLF/utils/data_splitter.py,sha256=IBVsLYo4y28G6LedbLPYWyiAUiaLxD4wWZD4EZC2D6I,10174
|
|
174
174
|
GANDLF/utils/exceptions.py,sha256=SmEGzCbc5mXxjylmA9XE4PXZdmkkfOjrEh473cWTAvA,100
|
|
175
175
|
GANDLF/utils/gandlf_logging.py,sha256=a1yV4244BGO5gp4OuAIKJUZgR21U1OPdovJ5nH1uUrs,2162
|
|
176
176
|
GANDLF/utils/generic.py,sha256=NyJgaeCdryBlHMziPPLmWtIk450u042NWQgs_qh7knw,11744
|
|
177
177
|
GANDLF/utils/handle_collisions.py,sha256=UFgfrddQqeipOdpKk0Mo-wwJ-TYTESNZyXzEyQeaLdI,3082
|
|
178
|
-
GANDLF/utils/imaging.py,sha256=
|
|
178
|
+
GANDLF/utils/imaging.py,sha256=_qCgvIXHZW_k_IUYLU95G5L5yoozxCRCYxo65TI-95U,15983
|
|
179
179
|
GANDLF/utils/modelbase.py,sha256=MJ1ufJGQ-ZgfYWTg7o4f-Iz78d7SYiyxN7MT8bnNDaw,950
|
|
180
180
|
GANDLF/utils/modelio.py,sha256=9koLUn3wCODtNOYA2abtxkqxfLgEG07Bhh-NYIrtWOc,8084
|
|
181
181
|
GANDLF/utils/parameter_processing.py,sha256=DA7ZEsizWWLJZnCxBnDNh1NyA-bw5oirOvodiZZWbIk,5675
|
|
182
182
|
GANDLF/utils/pred_target_processors.py,sha256=aatXJ6jdJaNAHa_tPzHfC1gOQrPYJLtg-cYeUFvkM_s,2701
|
|
183
183
|
GANDLF/utils/tensor.py,sha256=AOwNTQfw9mnsomGwOF2Q_rdDS1WANlIatB0hhZN0gSg,21504
|
|
184
184
|
GANDLF/utils/write_parse.py,sha256=HROxskhet-uIdUJmz16z_7p9r0mf8hWsqQFygwZ8ap0,9202
|
|
185
|
-
gandlf-0.1.4.
|
|
186
|
-
gandlf-0.1.4.
|
|
187
|
-
gandlf-0.1.4.
|
|
188
|
-
gandlf-0.1.4.
|
|
189
|
-
gandlf-0.1.4.
|
|
190
|
-
gandlf-0.1.4.
|
|
185
|
+
gandlf-0.1.4.dev20250610.dist-info/licenses/LICENSE,sha256=GlZPAfA4eckod8IVayhBXkqCpESXf6cc9BGli_Jwims,11357
|
|
186
|
+
gandlf-0.1.4.dev20250610.dist-info/METADATA,sha256=uWMTZ9ZfIKwMqRkWwoUfAw21WLGvGHSwAbHdOH7-4Tg,9932
|
|
187
|
+
gandlf-0.1.4.dev20250610.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
188
|
+
gandlf-0.1.4.dev20250610.dist-info/entry_points.txt,sha256=agwocNI7Upi-sFDe1rMl71dGN8YhCBB7WJmtBHRF4jg,902
|
|
189
|
+
gandlf-0.1.4.dev20250610.dist-info/top_level.txt,sha256=i5D9wEbQhl085_9Lx2m7x-9Zu6nlx1tjYYbuSihG09E,7
|
|
190
|
+
gandlf-0.1.4.dev20250610.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|