|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import shutil |
|
from collections import OrderedDict |
|
from copy import deepcopy |
|
from multiprocessing.pool import Pool |
|
from typing import Tuple |
|
|
|
import SimpleITK as sitk |
|
import numpy as np |
|
import scipy.stats as ss |
|
from batchgenerators.utilities.file_and_folder_operations import * |
|
from medpy.metric import dc, hd95 |
|
from nnunet.dataset_conversion.Task032_BraTS_2018 import convert_labels_back_to_BraTS_2018_2019_convention |
|
from nnunet.dataset_conversion.Task043_BraTS_2019 import copy_BraTS_segmentation_and_convert_labels |
|
from nnunet.evaluation.region_based_evaluation import get_brats_regions, evaluate_regions |
|
from nnunet.paths import nnUNet_raw_data |
|
from nnunet.postprocessing.consolidate_postprocessing import collect_cv_niftis |
|
|
|
|
|
def apply_brats_threshold(fname, out_dir, threshold, replace_with): |
|
img_itk = sitk.ReadImage(fname) |
|
img_npy = sitk.GetArrayFromImage(img_itk) |
|
s = np.sum(img_npy == 3) |
|
if s < threshold: |
|
|
|
img_npy[img_npy == 3] = replace_with |
|
img_itk_postprocessed = sitk.GetImageFromArray(img_npy) |
|
img_itk_postprocessed.CopyInformation(img_itk) |
|
sitk.WriteImage(img_itk_postprocessed, join(out_dir, fname.split("/")[-1])) |
|
|
|
|
|
def load_niftis_threshold_compute_dice(gt_file, pred_file, thresholds: Tuple[list, tuple]): |
|
gt = sitk.GetArrayFromImage(sitk.ReadImage(gt_file)) |
|
pred = sitk.GetArrayFromImage(sitk.ReadImage(pred_file)) |
|
mask_pred = pred == 3 |
|
mask_gt = gt == 3 |
|
num_pred = np.sum(mask_pred) |
|
|
|
num_gt = np.sum(mask_gt) |
|
dice = dc(mask_pred, mask_gt) |
|
|
|
res_dice = {} |
|
res_was_smaller = {} |
|
|
|
for t in thresholds: |
|
was_smaller = False |
|
|
|
if num_pred < t: |
|
was_smaller = True |
|
if num_gt == 0: |
|
dice_here = 1. |
|
else: |
|
dice_here = 0. |
|
else: |
|
dice_here = deepcopy(dice) |
|
|
|
res_dice[t] = dice_here |
|
res_was_smaller[t] = was_smaller |
|
|
|
return res_was_smaller, res_dice |
|
|
|
|
|
def apply_threshold_to_folder(folder_in, folder_out, threshold, replace_with, processes=24): |
|
maybe_mkdir_p(folder_out) |
|
niftis = subfiles(folder_in, suffix='.nii.gz', join=True) |
|
|
|
p = Pool(processes) |
|
p.starmap(apply_brats_threshold, zip(niftis, [folder_out]*len(niftis), [threshold]*len(niftis), [replace_with] * len(niftis))) |
|
|
|
p.close() |
|
p.join() |
|
|
|
|
|
def determine_brats_postprocessing(folder_with_preds, folder_with_gt, postprocessed_output_dir, processes=8, |
|
thresholds=(0, 10, 50, 100, 200, 500, 750, 1000, 1500, 2500, 10000), replace_with=2): |
|
|
|
nifti_gt = subfiles(folder_with_gt, suffix=".nii.gz", sort=True) |
|
|
|
p = Pool(processes) |
|
|
|
nifti_pred = subfiles(folder_with_preds, suffix='.nii.gz', sort=True) |
|
|
|
results = p.starmap_async(load_niftis_threshold_compute_dice, zip(nifti_gt, nifti_pred, [thresholds] * len(nifti_pred))) |
|
results = results.get() |
|
|
|
all_dc_per_threshold = {} |
|
for t in thresholds: |
|
all_dc_per_threshold[t] = np.array([i[1][t] for i in results]) |
|
print(t, np.mean(all_dc_per_threshold[t])) |
|
|
|
means = [np.mean(all_dc_per_threshold[t]) for t in thresholds] |
|
best_threshold = thresholds[np.argmax(means)] |
|
print('best', best_threshold, means[np.argmax(means)]) |
|
|
|
maybe_mkdir_p(postprocessed_output_dir) |
|
|
|
p.starmap(apply_brats_threshold, zip(nifti_pred, [postprocessed_output_dir]*len(nifti_pred), [best_threshold]*len(nifti_pred), [replace_with] * len(nifti_pred))) |
|
|
|
p.close() |
|
p.join() |
|
|
|
save_pickle((thresholds, means, best_threshold, all_dc_per_threshold), join(postprocessed_output_dir, "threshold.pkl")) |
|
|
|
|
|
def collect_and_prepare(base_dir, num_processes = 12, clean=False): |
|
""" |
|
collect all cv_niftis, compute brats metrics, compute enh tumor thresholds and summarize in csv |
|
:param base_dir: |
|
:return: |
|
""" |
|
out = join(base_dir, 'cv_results') |
|
out_pp = join(base_dir, 'cv_results_pp') |
|
experiments = subfolders(base_dir, join=False, prefix='nnUNetTrainer') |
|
regions = get_brats_regions() |
|
gt_dir = join(base_dir, 'gt_niftis') |
|
replace_with = 2 |
|
|
|
failed = [] |
|
successful = [] |
|
for e in experiments: |
|
print(e) |
|
try: |
|
o = join(out, e) |
|
o_p = join(out_pp, e) |
|
maybe_mkdir_p(o) |
|
maybe_mkdir_p(o_p) |
|
collect_cv_niftis(join(base_dir, e), o) |
|
if clean or not isfile(join(o, 'summary.csv')): |
|
evaluate_regions(o, gt_dir, regions, num_processes) |
|
if clean or not isfile(join(o_p, 'threshold.pkl')): |
|
determine_brats_postprocessing(o, gt_dir, o_p, num_processes, thresholds=list(np.arange(0, 760, 10)), replace_with=replace_with) |
|
if clean or not isfile(join(o_p, 'summary.csv')): |
|
evaluate_regions(o_p, gt_dir, regions, num_processes) |
|
successful.append(e) |
|
except Exception as ex: |
|
print("\nERROR\n", e, ex, "\n") |
|
failed.append(e) |
|
|
|
|
|
with open(join(base_dir, 'cv_summary.csv'), 'w') as f: |
|
f.write('name,whole,core,enh,mean\n') |
|
for e in successful: |
|
expected_nopp = join(out, e, 'summary.csv') |
|
expected_pp = join(out, out_pp, e, 'summary.csv') |
|
if isfile(expected_nopp): |
|
res = np.loadtxt(expected_nopp, dtype=str, skiprows=0, delimiter=',')[-2] |
|
as_numeric = [float(i) for i in res[1:]] |
|
f.write(e + '_noPP,') |
|
f.write("%0.4f," % as_numeric[0]) |
|
f.write("%0.4f," % as_numeric[1]) |
|
f.write("%0.4f," % as_numeric[2]) |
|
f.write("%0.4f\n" % np.mean(as_numeric)) |
|
if isfile(expected_pp): |
|
res = np.loadtxt(expected_pp, dtype=str, skiprows=0, delimiter=',')[-2] |
|
as_numeric = [float(i) for i in res[1:]] |
|
f.write(e + '_PP,') |
|
f.write("%0.4f," % as_numeric[0]) |
|
f.write("%0.4f," % as_numeric[1]) |
|
f.write("%0.4f," % as_numeric[2]) |
|
f.write("%0.4f\n" % np.mean(as_numeric)) |
|
|
|
|
|
with open(join(base_dir, 'cv_summary2.csv'), 'w') as f: |
|
for folder in ['cv_results', 'cv_results_pp']: |
|
for ex in subdirs(join(base_dir, folder), join=False): |
|
print(folder, ex) |
|
expected = join(base_dir, folder, ex, 'summary.csv') |
|
if clean or not isfile(expected): |
|
evaluate_regions(join(base_dir, folder, ex), gt_dir, regions, num_processes) |
|
if isfile(expected): |
|
res = np.loadtxt(expected, dtype=str, skiprows=0, delimiter=',')[-2] |
|
as_numeric = [float(i) for i in res[1:]] |
|
f.write('%s__%s,' % (folder, ex)) |
|
f.write("%0.4f," % as_numeric[0]) |
|
f.write("%0.4f," % as_numeric[1]) |
|
f.write("%0.4f," % as_numeric[2]) |
|
f.write("%0.4f\n" % np.mean(as_numeric)) |
|
|
|
f.write('name,whole,core,enh,mean\n') |
|
for e in successful: |
|
expected_nopp = join(out, e, 'summary.csv') |
|
expected_pp = join(out, out_pp, e, 'summary.csv') |
|
if isfile(expected_nopp): |
|
res = np.loadtxt(expected_nopp, dtype=str, skiprows=0, delimiter=',')[-2] |
|
as_numeric = [float(i) for i in res[1:]] |
|
f.write(e + '_noPP,') |
|
f.write("%0.4f," % as_numeric[0]) |
|
f.write("%0.4f," % as_numeric[1]) |
|
f.write("%0.4f," % as_numeric[2]) |
|
f.write("%0.4f\n" % np.mean(as_numeric)) |
|
if isfile(expected_pp): |
|
res = np.loadtxt(expected_pp, dtype=str, skiprows=0, delimiter=',')[-2] |
|
as_numeric = [float(i) for i in res[1:]] |
|
f.write(e + '_PP,') |
|
f.write("%0.4f," % as_numeric[0]) |
|
f.write("%0.4f," % as_numeric[1]) |
|
f.write("%0.4f," % as_numeric[2]) |
|
f.write("%0.4f\n" % np.mean(as_numeric)) |
|
|
|
|
|
expected_num_cases = 125 |
|
missing_valset = [] |
|
has_val_pred = [] |
|
for e in successful: |
|
if isdir(join(base_dir, 'predVal', e)): |
|
currdir = join(base_dir, 'predVal', e) |
|
files = subfiles(currdir, suffix='.nii.gz', join=False) |
|
if len(files) != expected_num_cases: |
|
print(e, 'prediction not done, found %d files, expected %s' % (len(files), expected_num_cases)) |
|
continue |
|
output_folder = join(base_dir, 'predVal_PP', e) |
|
maybe_mkdir_p(output_folder) |
|
threshold = load_pickle(join(out_pp, e, 'threshold.pkl'))[2] |
|
if threshold > 1000: threshold = 750 |
|
apply_threshold_to_folder(currdir, output_folder, threshold, replace_with, num_processes) |
|
has_val_pred.append(e) |
|
else: |
|
print(e, 'has no valset predictions') |
|
missing_valset.append(e) |
|
|
|
|
|
e = 'nnUNetTrainerV2BraTSRegions_DA3_BN__nnUNetPlansv2.1_bs5' |
|
currdir = join(base_dir, 'predVal', 'nnUNetTrainerV2BraTSRegions_DA3_BN__nnUNetPlansv2.1_bs5_15fold') |
|
output_folder = join(base_dir, 'predVal_PP', 'nnUNetTrainerV2BraTSRegions_DA3_BN__nnUNetPlansv2.1_bs5_15fold') |
|
maybe_mkdir_p(output_folder) |
|
threshold = load_pickle(join(out_pp, e, 'threshold.pkl'))[2] |
|
if threshold > 1000: threshold = 750 |
|
apply_threshold_to_folder(currdir, output_folder, threshold, replace_with, num_processes) |
|
|
|
|
|
e = 'nnUNetTrainerV2BraTSRegions_DA4_BN__nnUNetPlansv2.1_bs5' |
|
currdir = join(base_dir, 'predVal', 'nnUNetTrainerV2BraTSRegions_DA4_BN__nnUNetPlansv2.1_bs5_15fold') |
|
output_folder = join(base_dir, 'predVal_PP', 'nnUNetTrainerV2BraTSRegions_DA4_BN__nnUNetPlansv2.1_bs5_15fold') |
|
maybe_mkdir_p(output_folder) |
|
threshold = load_pickle(join(out_pp, e, 'threshold.pkl'))[2] |
|
if threshold > 1000: threshold = 750 |
|
apply_threshold_to_folder(currdir, output_folder, threshold, replace_with, num_processes) |
|
|
|
|
|
output_converted = join(base_dir, 'converted_valSet') |
|
|
|
for source in ['predVal', 'predVal_PP']: |
|
for e in has_val_pred + ['nnUNetTrainerV2BraTSRegions_DA3_BN__nnUNetPlansv2.1_bs5_15fold', 'nnUNetTrainerV2BraTSRegions_DA4_BN__nnUNetPlansv2.1_bs5_15fold']: |
|
expected_source_folder = join(base_dir, source, e) |
|
if not isdir(expected_source_folder): |
|
print(e, 'has no', source) |
|
raise RuntimeError() |
|
files = subfiles(expected_source_folder, suffix='.nii.gz', join=False) |
|
if len(files) != expected_num_cases: |
|
print(e, 'prediction not done, found %d files, expected %s' % (len(files), expected_num_cases)) |
|
continue |
|
target_folder = join(output_converted, source, e) |
|
maybe_mkdir_p(target_folder) |
|
convert_labels_back_to_BraTS_2018_2019_convention(expected_source_folder, target_folder) |
|
|
|
summarize_validation_set_predictions(output_converted) |
|
|
|
|
|
def summarize_validation_set_predictions(base): |
|
with open(join(base, 'summary.csv'), 'w') as f: |
|
f.write('name,whole,core,enh,mean,whole,core,enh,mean\n') |
|
for subf in subfolders(base, join=False): |
|
for e in subfolders(join(base, subf), join=False): |
|
expected = join(base, subf, e, 'Stats_Validation_final.csv') |
|
if not isfile(expected): |
|
print(subf, e, 'has missing csv') |
|
continue |
|
a = np.loadtxt(expected, delimiter=',', dtype=str) |
|
assert a.shape[0] == 131, 'did not evaluate all 125 cases!' |
|
selected_row = a[-5] |
|
values = [float(i) for i in selected_row[1:4]] |
|
f.write(e + "_" + subf + ',') |
|
f.write("%0.4f," % values[1]) |
|
f.write("%0.4f," % values[2]) |
|
f.write("%0.4f," % values[0]) |
|
f.write("%0.4f," % np.mean(values)) |
|
values = [float(i) for i in selected_row[-3:]] |
|
f.write("%0.4f," % values[1]) |
|
f.write("%0.4f," % values[2]) |
|
f.write("%0.4f," % values[0]) |
|
f.write("%0.4f\n" % np.mean(values)) |
|
|
|
|
|
def compute_BraTS_dice(ref, pred): |
|
""" |
|
ref and gt are binary integer numpy.ndarray s |
|
:param ref: |
|
:param gt: |
|
:return: |
|
""" |
|
num_ref = np.sum(ref) |
|
num_pred = np.sum(pred) |
|
|
|
if num_ref == 0: |
|
if num_pred == 0: |
|
return 1 |
|
else: |
|
return 0 |
|
else: |
|
return dc(pred, ref) |
|
|
|
|
|
def convert_all_to_BraTS(input_folder, output_folder, expected_num_cases=125): |
|
for s in subdirs(input_folder, join=False): |
|
nii = subfiles(join(input_folder, s), suffix='.nii.gz', join=False) |
|
if len(nii) != expected_num_cases: |
|
print(s) |
|
else: |
|
target_dir = join(output_folder, s) |
|
convert_labels_back_to_BraTS_2018_2019_convention(join(input_folder, s), target_dir, num_processes=6) |
|
|
|
|
|
def compute_BraTS_HD95(ref, pred): |
|
""" |
|
ref and gt are binary integer numpy.ndarray s |
|
spacing is assumed to be (1, 1, 1) |
|
:param ref: |
|
:param pred: |
|
:return: |
|
""" |
|
num_ref = np.sum(ref) |
|
num_pred = np.sum(pred) |
|
|
|
if num_ref == 0: |
|
if num_pred == 0: |
|
return 0 |
|
else: |
|
return 373.12866 |
|
elif num_pred == 0 and num_ref != 0: |
|
return 373.12866 |
|
else: |
|
return hd95(pred, ref, (1, 1, 1)) |
|
|
|
|
|
def evaluate_BraTS_case(arr: np.ndarray, arr_gt: np.ndarray): |
|
""" |
|
attempting to reimplement the brats evaluation scheme |
|
assumes edema=1, non_enh=2, enh=3 |
|
:param arr: |
|
:param arr_gt: |
|
:return: |
|
""" |
|
|
|
mask_gt = (arr_gt != 0).astype(int) |
|
mask_pred = (arr != 0).astype(int) |
|
dc_whole = compute_BraTS_dice(mask_gt, mask_pred) |
|
hd95_whole = compute_BraTS_HD95(mask_gt, mask_pred) |
|
del mask_gt, mask_pred |
|
|
|
|
|
mask_gt = (arr_gt > 1).astype(int) |
|
mask_pred = (arr > 1).astype(int) |
|
dc_core = compute_BraTS_dice(mask_gt, mask_pred) |
|
hd95_core = compute_BraTS_HD95(mask_gt, mask_pred) |
|
del mask_gt, mask_pred |
|
|
|
|
|
mask_gt = (arr_gt == 3).astype(int) |
|
mask_pred = (arr == 3).astype(int) |
|
dc_enh = compute_BraTS_dice(mask_gt, mask_pred) |
|
hd95_enh = compute_BraTS_HD95(mask_gt, mask_pred) |
|
del mask_gt, mask_pred |
|
|
|
return dc_whole, dc_core, dc_enh, hd95_whole, hd95_core, hd95_enh |
|
|
|
|
|
def load_evaluate(filename_gt: str, filename_pred: str): |
|
arr_pred = sitk.GetArrayFromImage(sitk.ReadImage(filename_pred)) |
|
arr_gt = sitk.GetArrayFromImage(sitk.ReadImage(filename_gt)) |
|
return evaluate_BraTS_case(arr_pred, arr_gt) |
|
|
|
|
|
def evaluate_BraTS_folder(folder_pred, folder_gt, num_processes: int = 24, strict=False): |
|
nii_pred = subfiles(folder_pred, suffix='.nii.gz', join=False) |
|
if len(nii_pred) == 0: |
|
return |
|
nii_gt = subfiles(folder_gt, suffix='.nii.gz', join=False) |
|
assert all([i in nii_gt for i in nii_pred]), 'not all predicted niftis have a reference file!' |
|
if strict: |
|
assert all([i in nii_pred for i in nii_gt]), 'not all gt niftis have a predicted file!' |
|
p = Pool(num_processes) |
|
nii_pred_fullpath = [join(folder_pred, i) for i in nii_pred] |
|
nii_gt_fullpath = [join(folder_gt, i) for i in nii_pred] |
|
results = p.starmap(load_evaluate, zip(nii_gt_fullpath, nii_pred_fullpath)) |
|
|
|
with open(join(folder_pred, 'results.csv'), 'w') as f: |
|
f.write("name,dc_whole,dc_core,dc_enh,hd95_whole,hd95_core,hd95_enh\n") |
|
for fname, r in zip(nii_pred, results): |
|
f.write(fname) |
|
f.write(",%0.4f,%0.4f,%0.4f,%3.3f,%3.3f,%3.3f\n" % r) |
|
|
|
|
|
def load_csv_for_ranking(csv_file: str): |
|
res = np.loadtxt(csv_file, dtype='str', delimiter=',') |
|
scores = res[1:, [1, 2, 3, -3, -2, -1]].astype(float) |
|
scores[:, -3:] *= -1 |
|
scores[:, -3:] += 373.129 |
|
assert np.all(scores <= 373.129) |
|
assert np.all(scores >= 0) |
|
return scores |
|
|
|
|
|
def rank_algorithms(data:np.ndarray): |
|
""" |
|
data is (metrics x experiments x cases) |
|
:param data: |
|
:return: |
|
""" |
|
num_metrics, num_experiments, num_cases = data.shape |
|
ranks = np.zeros((num_metrics, num_experiments)) |
|
for m in range(6): |
|
r = np.apply_along_axis(ss.rankdata, 0, -data[m], 'min') |
|
ranks[m] = r.mean(1) |
|
average_rank = np.mean(ranks, 0) |
|
final_ranks = ss.rankdata(average_rank, 'min') |
|
return final_ranks, average_rank, ranks |
|
|
|
|
|
def score_and_postprocess_model_based_on_rank_then_aggregate(): |
|
""" |
|
Similarly to BraTS 2017 - BraTS 2019, each participant will be ranked for each of the X test cases. Each case |
|
includes 3 regions of evaluation, and the metrics used to produce the rankings will be the Dice Similarity |
|
Coefficient and the 95% Hausdorff distance. Thus, for X number of cases included in the BraTS 2020, each |
|
participant ends up having X*3*2 rankings. The final ranking score is the average of all these rankings normalized |
|
by the number of teams. |
|
https://zenodo.org/record/3718904 |
|
|
|
-> let's optimize for this. |
|
|
|
Important: the outcome very much depends on the competing models. We need some references. We only got our own, |
|
so let's hope this still works |
|
:return: |
|
""" |
|
base = "/media/fabian/Results/nnUNet/3d_fullres/Task082_BraTS2020" |
|
replace_with = 2 |
|
num_processes = 24 |
|
expected_num_cases_val = 125 |
|
|
|
|
|
output_base_here = join(base, 'use_brats_ranking') |
|
maybe_mkdir_p(output_base_here) |
|
|
|
|
|
out = join(output_base_here, 'cv_results') |
|
experiments = subfolders(base, join=False, prefix='nnUNetTrainer') |
|
gt_dir = join(base, 'gt_niftis') |
|
|
|
experiments_with_full_cv = [] |
|
for e in experiments: |
|
print(e) |
|
o = join(out, e) |
|
maybe_mkdir_p(o) |
|
try: |
|
collect_cv_niftis(join(base, e), o) |
|
if not isfile(join(o, 'results.csv')): |
|
evaluate_BraTS_folder(o, gt_dir, num_processes, strict=True) |
|
experiments_with_full_cv.append(e) |
|
except Exception as ex: |
|
print("\nERROR\n", e, ex, "\n") |
|
if isfile(join(o, 'results.csv')): |
|
os.remove(join(o, 'results.csv')) |
|
|
|
|
|
tmp = np.loadtxt(join(out, experiments_with_full_cv[0], 'results.csv'), dtype='str', delimiter=',') |
|
num_cases = len(tmp) - 1 |
|
data_for_ranking = np.zeros((6, len(experiments_with_full_cv), num_cases)) |
|
for i, e in enumerate(experiments_with_full_cv): |
|
scores = load_csv_for_ranking(join(out, e, 'results.csv')) |
|
for metric in range(6): |
|
data_for_ranking[metric, i] = scores[:, metric] |
|
|
|
final_ranks, average_rank, ranks = rank_algorithms(data_for_ranking) |
|
|
|
for t in np.argsort(final_ranks): |
|
print(final_ranks[t], average_rank[t], experiments_with_full_cv[t]) |
|
|
|
|
|
thresholds = np.arange(25, 751, 25) |
|
output_pp_tmp = join(output_base_here, 'cv_determine_pp_thresholds') |
|
for e in experiments_with_full_cv: |
|
input_folder = join(out, e) |
|
for t in thresholds: |
|
output_directory = join(output_pp_tmp, e, str(t)) |
|
maybe_mkdir_p(output_directory) |
|
if not isfile(join(output_directory, 'results.csv')): |
|
apply_threshold_to_folder(input_folder, output_directory, t, replace_with, processes=16) |
|
evaluate_BraTS_folder(output_directory, gt_dir, num_processes) |
|
|
|
|
|
results = [] |
|
experiment_names = [] |
|
for e in experiments_with_full_cv: |
|
for t in thresholds: |
|
output_directory = join(output_pp_tmp, e, str(t)) |
|
expected_file = join(output_directory, 'results.csv') |
|
if not isfile(expected_file): |
|
print(e, 'does not have a results file for threshold', t) |
|
continue |
|
results.append(load_csv_for_ranking(expected_file)) |
|
experiment_names.append("%s___%d" % (e, t)) |
|
all_results = np.concatenate([i[None] for i in results], 0).transpose((2, 0, 1)) |
|
|
|
|
|
all_results = np.concatenate((data_for_ranking, all_results), 1) |
|
experiment_names += experiments_with_full_cv |
|
|
|
final_ranks, average_rank, ranks = rank_algorithms(all_results) |
|
|
|
for t in np.argsort(final_ranks): |
|
print(final_ranks[t], average_rank[t], experiment_names[t]) |
|
|
|
|
|
|
|
pred_val_base = join(base, 'predVal_PP_rank') |
|
has_val_pred = [] |
|
for e in experiments_with_full_cv: |
|
rank_nonpp = final_ranks[experiment_names.index(e)] |
|
avg_rank_nonpp = average_rank[experiment_names.index(e)] |
|
print(e, avg_rank_nonpp, rank_nonpp) |
|
predicted_val = join(base, 'predVal', e) |
|
|
|
pp_models = [j for j, i in enumerate(experiment_names) if i.split("___")[0] == e and i != e] |
|
if len(pp_models) > 0: |
|
ranks = [final_ranks[i] for i in pp_models] |
|
best_idx = np.argmin(ranks) |
|
best = experiment_names[pp_models[best_idx]] |
|
best_avg_rank = average_rank[pp_models[best_idx]] |
|
print(best, best_avg_rank, min(ranks)) |
|
print('') |
|
|
|
best_threshold = int(best.split('___')[-1]) |
|
if not isdir(predicted_val): |
|
print(e, 'has not valset predictions') |
|
else: |
|
files = subfiles(predicted_val, suffix='.nii.gz') |
|
if len(files) != expected_num_cases_val: |
|
print(e, 'has missing val cases. found: %d expected: %d' % (len(files), expected_num_cases_val)) |
|
else: |
|
apply_threshold_to_folder(predicted_val, join(pred_val_base, e), best_threshold, replace_with, num_processes) |
|
has_val_pred.append(e) |
|
else: |
|
print(e, 'not found in ranking') |
|
|
|
|
|
e = 'nnUNetTrainerV2BraTSRegions_DA3_BN__nnUNetPlansv2.1_bs5' |
|
pp_models = [j for j, i in enumerate(experiment_names) if i.split("___")[0] == e and i != e] |
|
ranks = [final_ranks[i] for i in pp_models] |
|
best_idx = np.argmin(ranks) |
|
best = experiment_names[pp_models[best_idx]] |
|
best_avg_rank = average_rank[pp_models[best_idx]] |
|
best_threshold = int(best.split('___')[-1]) |
|
predicted_val = join(base, 'predVal', 'nnUNetTrainerV2BraTSRegions_DA3_BN__nnUNetPlansv2.1_bs5_15fold') |
|
apply_threshold_to_folder(predicted_val, join(pred_val_base, 'nnUNetTrainerV2BraTSRegions_DA3_BN__nnUNetPlansv2.1_bs5_15fold'), best_threshold, replace_with, num_processes) |
|
has_val_pred.append('nnUNetTrainerV2BraTSRegions_DA3_BN__nnUNetPlansv2.1_bs5_15fold') |
|
|
|
|
|
e = 'nnUNetTrainerV2BraTSRegions_DA4_BN__nnUNetPlansv2.1_bs5' |
|
pp_models = [j for j, i in enumerate(experiment_names) if i.split("___")[0] == e and i != e] |
|
ranks = [final_ranks[i] for i in pp_models] |
|
best_idx = np.argmin(ranks) |
|
best = experiment_names[pp_models[best_idx]] |
|
best_avg_rank = average_rank[pp_models[best_idx]] |
|
best_threshold = int(best.split('___')[-1]) |
|
predicted_val = join(base, 'predVal', 'nnUNetTrainerV2BraTSRegions_DA4_BN__nnUNetPlansv2.1_bs5_15fold') |
|
apply_threshold_to_folder(predicted_val, join(pred_val_base, 'nnUNetTrainerV2BraTSRegions_DA4_BN__nnUNetPlansv2.1_bs5_15fold'), best_threshold, replace_with, num_processes) |
|
has_val_pred.append('nnUNetTrainerV2BraTSRegions_DA4_BN__nnUNetPlansv2.1_bs5_15fold') |
|
|
|
|
|
output_converted = join(base, 'converted_valSet') |
|
for e in has_val_pred: |
|
expected_source_folder = join(base, 'predVal_PP_rank', e) |
|
if not isdir(expected_source_folder): |
|
print(e, 'has no predVal_PP_rank') |
|
raise RuntimeError() |
|
files = subfiles(expected_source_folder, suffix='.nii.gz', join=False) |
|
if len(files) != expected_num_cases_val: |
|
print(e, 'prediction not done, found %d files, expected %s' % (len(files), expected_num_cases_val)) |
|
continue |
|
target_folder = join(output_converted, 'predVal_PP_rank', e) |
|
maybe_mkdir_p(target_folder) |
|
convert_labels_back_to_BraTS_2018_2019_convention(expected_source_folder, target_folder) |
|
|
|
|
|
|
|
flds = subdirs(output_converted, join=False) |
|
results_valset = [] |
|
names_valset = [] |
|
for f in flds: |
|
curr = join(output_converted, f) |
|
experiments = subdirs(curr, join=False) |
|
for e in experiments: |
|
currr = join(curr, e) |
|
expected_file = join(currr, 'Stats_Validation_final.csv') |
|
if not isfile(expected_file): |
|
print(f, e, "has not been evaluated yet!") |
|
else: |
|
res = load_csv_for_ranking(expected_file)[:-5] |
|
assert res.shape[0] == expected_num_cases_val |
|
results_valset.append(res[None]) |
|
names_valset.append("%s___%s" % (f, e)) |
|
results_valset = np.concatenate(results_valset, 0) |
|
|
|
results_valset = results_valset.transpose((2, 0, 1)) |
|
final_ranks, average_rank, ranks = rank_algorithms(results_valset) |
|
for t in np.argsort(final_ranks): |
|
print(final_ranks[t], average_rank[t], names_valset[t]) |
|
|
|
|
|
if __name__ == "__main__": |
|
""" |
|
THIS CODE IS A MESS. IT IS PROVIDED AS IS WITH NO GUARANTEES. YOU HAVE TO DIG THROUGH IT YOURSELF. GOOD LUCK ;-) |
|
|
|
REMEMBER TO CONVERT LABELS BACK TO BRATS CONVENTION AFTER PREDICTION! |
|
""" |
|
|
|
task_name = "Task082_BraTS2020" |
|
downloaded_data_dir = "/home/fabian/Downloads/MICCAI_BraTS2020_TrainingData" |
|
downloaded_data_dir_val = "/home/fabian/Downloads/MICCAI_BraTS2020_ValidationData" |
|
|
|
target_base = join(nnUNet_raw_data, task_name) |
|
target_imagesTr = join(target_base, "imagesTr") |
|
target_imagesVal = join(target_base, "imagesVal") |
|
target_imagesTs = join(target_base, "imagesTs") |
|
target_labelsTr = join(target_base, "labelsTr") |
|
|
|
maybe_mkdir_p(target_imagesTr) |
|
maybe_mkdir_p(target_imagesVal) |
|
maybe_mkdir_p(target_imagesTs) |
|
maybe_mkdir_p(target_labelsTr) |
|
|
|
patient_names = [] |
|
cur = join(downloaded_data_dir) |
|
for p in subdirs(cur, join=False): |
|
patdir = join(cur, p) |
|
patient_name = p |
|
patient_names.append(patient_name) |
|
t1 = join(patdir, p + "_t1.nii.gz") |
|
t1c = join(patdir, p + "_t1ce.nii.gz") |
|
t2 = join(patdir, p + "_t2.nii.gz") |
|
flair = join(patdir, p + "_flair.nii.gz") |
|
seg = join(patdir, p + "_seg.nii.gz") |
|
|
|
assert all([ |
|
isfile(t1), |
|
isfile(t1c), |
|
isfile(t2), |
|
isfile(flair), |
|
isfile(seg) |
|
]), "%s" % patient_name |
|
|
|
shutil.copy(t1, join(target_imagesTr, patient_name + "_0000.nii.gz")) |
|
shutil.copy(t1c, join(target_imagesTr, patient_name + "_0001.nii.gz")) |
|
shutil.copy(t2, join(target_imagesTr, patient_name + "_0002.nii.gz")) |
|
shutil.copy(flair, join(target_imagesTr, patient_name + "_0003.nii.gz")) |
|
|
|
copy_BraTS_segmentation_and_convert_labels(seg, join(target_labelsTr, patient_name + ".nii.gz")) |
|
|
|
|
|
json_dict = OrderedDict() |
|
json_dict['name'] = "BraTS2020" |
|
json_dict['description'] = "nothing" |
|
json_dict['tensorImageSize'] = "4D" |
|
json_dict['reference'] = "see BraTS2020" |
|
json_dict['licence'] = "see BraTS2020 license" |
|
json_dict['release'] = "0.0" |
|
json_dict['modality'] = { |
|
"0": "T1", |
|
"1": "T1ce", |
|
"2": "T2", |
|
"3": "FLAIR" |
|
} |
|
json_dict['labels'] = { |
|
"0": "background", |
|
"1": "edema", |
|
"2": "non-enhancing", |
|
"3": "enhancing", |
|
} |
|
json_dict['numTraining'] = len(patient_names) |
|
json_dict['numTest'] = 0 |
|
json_dict['training'] = [{'image': "./imagesTr/%s.nii.gz" % i, "label": "./labelsTr/%s.nii.gz" % i} for i in |
|
patient_names] |
|
json_dict['test'] = [] |
|
|
|
save_json(json_dict, join(target_base, "dataset.json")) |
|
|
|
if downloaded_data_dir_val is not None: |
|
for p in subdirs(downloaded_data_dir_val, join=False): |
|
patdir = join(downloaded_data_dir_val, p) |
|
patient_name = p |
|
t1 = join(patdir, p + "_t1.nii.gz") |
|
t1c = join(patdir, p + "_t1ce.nii.gz") |
|
t2 = join(patdir, p + "_t2.nii.gz") |
|
flair = join(patdir, p + "_flair.nii.gz") |
|
|
|
assert all([ |
|
isfile(t1), |
|
isfile(t1c), |
|
isfile(t2), |
|
isfile(flair), |
|
]), "%s" % patient_name |
|
|
|
shutil.copy(t1, join(target_imagesVal, patient_name + "_0000.nii.gz")) |
|
shutil.copy(t1c, join(target_imagesVal, patient_name + "_0001.nii.gz")) |
|
shutil.copy(t2, join(target_imagesVal, patient_name + "_0002.nii.gz")) |
|
shutil.copy(flair, join(target_imagesVal, patient_name + "_0003.nii.gz")) |
|
|
|
|
|
downloaded_data_dir_test = "/home/fabian/Downloads/MICCAI_BraTS2020_TestingData" |
|
|
|
if isdir(downloaded_data_dir_test): |
|
for p in subdirs(downloaded_data_dir_test, join=False): |
|
patdir = join(downloaded_data_dir_test, p) |
|
patient_name = p |
|
t1 = join(patdir, p + "_t1.nii.gz") |
|
t1c = join(patdir, p + "_t1ce.nii.gz") |
|
t2 = join(patdir, p + "_t2.nii.gz") |
|
flair = join(patdir, p + "_flair.nii.gz") |
|
|
|
assert all([ |
|
isfile(t1), |
|
isfile(t1c), |
|
isfile(t2), |
|
isfile(flair), |
|
]), "%s" % patient_name |
|
|
|
shutil.copy(t1, join(target_imagesTs, patient_name + "_0000.nii.gz")) |
|
shutil.copy(t1c, join(target_imagesTs, patient_name + "_0001.nii.gz")) |
|
shutil.copy(t2, join(target_imagesTs, patient_name + "_0002.nii.gz")) |
|
shutil.copy(flair, join(target_imagesTs, patient_name + "_0003.nii.gz")) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|