From aa76c8dbb26d784284b4722c82a1e2ce52fd1074 Mon Sep 17 00:00:00 2001 From: Patrick Strasser Date: Fri, 19 Apr 2024 11:36:09 +0000 Subject: [PATCH 1/8] chore: add local setup --- nnunetv2/dataset_conversion/Dataset137_BraTS21.py | 2 +- train.sh | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100755 train.sh diff --git a/nnunetv2/dataset_conversion/Dataset137_BraTS21.py b/nnunetv2/dataset_conversion/Dataset137_BraTS21.py index b4817d282..74c259b95 100644 --- a/nnunetv2/dataset_conversion/Dataset137_BraTS21.py +++ b/nnunetv2/dataset_conversion/Dataset137_BraTS21.py @@ -57,7 +57,7 @@ def convert_folder_with_preds_back_to_BraTS_labeling_convention(input_folder: st if __name__ == '__main__': - brats_data_dir = '/home/isensee/drives/E132-Rohdaten/BraTS_2021/training' + brats_data_dir = '/home/stud/strasser/data/raw_downloaded_data' task_id = 137 task_name = "BraTS2021" diff --git a/train.sh b/train.sh new file mode 100755 index 000000000..34a93e16b --- /dev/null +++ b/train.sh @@ -0,0 +1,9 @@ +#!/bin/bash +source ~/env_file + +eval "$(conda shell.bash hook)" +conda activate generic-nnunet + + +echo "starting training with fold $fold" +nnUNetv2_train 137 3d_fullres $fold --npz --c From 44e4dc71cc84b7becab45d4626010e3af207ba9d Mon Sep 17 00:00:00 2001 From: Patrick Strasser Date: Fri, 19 Apr 2024 11:38:46 +0000 Subject: [PATCH 2/8] chore: refine train.sh script --- train.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/train.sh b/train.sh index 34a93e16b..4cc12761e 100755 --- a/train.sh +++ b/train.sh @@ -3,7 +3,7 @@ source ~/env_file eval "$(conda shell.bash hook)" conda activate generic-nnunet - +git checkout dev echo "starting training with fold $fold" nnUNetv2_train 137 3d_fullres $fold --npz --c From 433abe08ca045cf198c2733a0fcc73354802ecde Mon Sep 17 00:00:00 2001 From: Patrick Strasser Date: Sat, 20 Apr 2024 10:59:38 +0000 Subject: [PATCH 3/8] feat: add brats2019 preprocessing script --- .../dataset_conversion/Dataset043_BraTS19.py | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 nnunetv2/dataset_conversion/Dataset043_BraTS19.py diff --git a/nnunetv2/dataset_conversion/Dataset043_BraTS19.py b/nnunetv2/dataset_conversion/Dataset043_BraTS19.py new file mode 100644 index 000000000..756d96699 --- /dev/null +++ b/nnunetv2/dataset_conversion/Dataset043_BraTS19.py @@ -0,0 +1,110 @@ +import multiprocessing +import shutil +from multiprocessing import Pool + +import SimpleITK as sitk +import numpy as np +from tqdm import tqdm +from batchgenerators.utilities.file_and_folder_operations import * +from nnunetv2.dataset_conversion.generate_dataset_json import generate_dataset_json +from nnunetv2.paths import nnUNet_raw + + +def copy_BraTS_segmentation_and_convert_labels_to_nnUNet(in_file: str, out_file: str) -> None: + # use this for segmentation only!!! + # nnUNet wants the labels to be continuous. BraTS is 0, 1, 2, 4 -> we make that into 0, 1, 2, 3 + img = sitk.ReadImage(in_file) + img_npy = sitk.GetArrayFromImage(img) + + uniques = np.unique(img_npy) + for u in uniques: + if u not in [0, 1, 2, 4]: + raise RuntimeError('unexpected label') + + seg_new = np.zeros_like(img_npy) + seg_new[img_npy == 4] = 3 + seg_new[img_npy == 2] = 1 + seg_new[img_npy == 1] = 2 + img_corr = sitk.GetImageFromArray(seg_new) + img_corr.CopyInformation(img) + sitk.WriteImage(img_corr, out_file) + + +def convert_labels_back_to_BraTS(seg: np.ndarray): + new_seg = np.zeros_like(seg) + new_seg[seg == 1] = 2 + new_seg[seg == 3] = 4 + new_seg[seg == 2] = 1 + return new_seg + + +def load_convert_labels_back_to_BraTS(filename, input_folder, output_folder): + a = sitk.ReadImage(join(input_folder, filename)) + b = sitk.GetArrayFromImage(a) + c = convert_labels_back_to_BraTS(b) + d = sitk.GetImageFromArray(c) + d.CopyInformation(a) + sitk.WriteImage(d, join(output_folder, filename)) + + +def convert_folder_with_preds_back_to_BraTS_labeling_convention(input_folder: str, output_folder: str, num_processes: int = 12): + """ + reads all prediction files (nifti) in the input folder, converts the labels back to BraTS convention and saves the + """ + maybe_mkdir_p(output_folder) + nii = subfiles(input_folder, suffix='.nii.gz', join=False) + with multiprocessing.get_context("spawn").Pool(num_processes) as p: + p.starmap(load_convert_labels_back_to_BraTS, zip(nii, [input_folder] * len(nii), [output_folder] * len(nii))) + + +if __name__ == '__main__': + brats_data_dir = '/home/stud/strasser/archive/brats2019/MICCAI_BraTS_2019_Data_Training' + + task_id = 43 + task_name = "BraTS2019" + + foldername = "Dataset%03.0d_%s" % (task_id, task_name) + + # setting up nnU-Net folders + out_base = join(nnUNet_raw, foldername) + imagestr = join(out_base, "imagesTr") + labelstr = join(out_base, "labelsTr") + maybe_mkdir_p(imagestr) + maybe_mkdir_p(labelstr) + + case_ids_hgg = subdirs(join(brats_data_dir, "HGG"), prefix='BraTS', join=False) + case_ids_lgg = subdirs(join(brats_data_dir, "LGG"), prefix="BraTS", join=False) + + print("copying hggs") + for c in tqdm(case_ids_hgg): + shutil.copy(join(brats_data_dir, "HGG", c, c + "_t1.nii"), join(imagestr, c + '_0000.nii')) + shutil.copy(join(brats_data_dir, "HGG", c, c + "_t1ce.nii"), join(imagestr, c + '_0001.nii')) + shutil.copy(join(brats_data_dir, "HGG", c, c + "_t2.nii"), join(imagestr, c + '_0002.nii')) + shutil.copy(join(brats_data_dir, "HGG", c, c + "_flair.nii"), join(imagestr, c + '_0003.nii')) + + copy_BraTS_segmentation_and_convert_labels_to_nnUNet(join(brats_data_dir, "HGG", c, c + "_seg.nii"), + join(labelstr, c + '.nii')) + print("copying lggs") + for c in tqdm(case_ids_lgg): + shutil.copy(join(brats_data_dir, "LGG", c, c + "_t1.nii"), join(imagestr, c + '_0000.nii')) + shutil.copy(join(brats_data_dir, "LGG", c, c + "_t1ce.nii"), join(imagestr, c + '_0001.nii')) + shutil.copy(join(brats_data_dir, "LGG", c, c + "_t2.nii"), join(imagestr, c + '_0002.nii')) + shutil.copy(join(brats_data_dir, "LGG", c, c + "_flair.nii"), join(imagestr, c + '_0003.nii')) + + copy_BraTS_segmentation_and_convert_labels_to_nnUNet(join(brats_data_dir, "LGG", c, c + "_seg.nii"), + join(labelstr, c + '.nii')) + + generate_dataset_json(out_base, + channel_names={0: 'T1', 1: 'T1ce', 2: 'T2', 3: 'Flair'}, + labels={ + 'background': 0, + 'whole tumor': (1, 2, 3), + 'tumor core': (2, 3), + 'enhancing tumor': (3, ) + }, + num_training_cases=len(case_ids), + file_ending='.nii.gz', + regions_class_order=(1, 2, 3), + license='see https://www.synapse.org/#!Synapse:syn25829067/wiki/610863', + reference='see https://www.synapse.org/#!Synapse:syn25829067/wiki/610863', + dataset_release='1.0') From f8f1346a8dbb36cb62e568a7560092eff0229018 Mon Sep 17 00:00:00 2001 From: Patrick Strasser Date: Sat, 20 Apr 2024 11:10:10 +0000 Subject: [PATCH 4/8] fix: brats2019 preprocessing --- nnunetv2/dataset_conversion/Dataset043_BraTS19.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nnunetv2/dataset_conversion/Dataset043_BraTS19.py b/nnunetv2/dataset_conversion/Dataset043_BraTS19.py index 756d96699..12da53c27 100644 --- a/nnunetv2/dataset_conversion/Dataset043_BraTS19.py +++ b/nnunetv2/dataset_conversion/Dataset043_BraTS19.py @@ -102,7 +102,7 @@ def convert_folder_with_preds_back_to_BraTS_labeling_convention(input_folder: st 'tumor core': (2, 3), 'enhancing tumor': (3, ) }, - num_training_cases=len(case_ids), + num_training_cases=(len(case_ids_hgg) + len(case_ids_lgg)), file_ending='.nii.gz', regions_class_order=(1, 2, 3), license='see https://www.synapse.org/#!Synapse:syn25829067/wiki/610863', From 314b76779693b17c663f98768033a545ecb9f164 Mon Sep 17 00:00:00 2001 From: Patrick Strasser Date: Sat, 20 Apr 2024 11:25:40 +0000 Subject: [PATCH 5/8] fix: dataset.json --- .../Dataset042_BraTS2018.py | 110 ++++++++++++++++++ .../dataset_conversion/Dataset043_BraTS19.py | 2 +- 2 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 nnunetv2/dataset_conversion/Dataset042_BraTS2018.py diff --git a/nnunetv2/dataset_conversion/Dataset042_BraTS2018.py b/nnunetv2/dataset_conversion/Dataset042_BraTS2018.py new file mode 100644 index 000000000..0fe76bf13 --- /dev/null +++ b/nnunetv2/dataset_conversion/Dataset042_BraTS2018.py @@ -0,0 +1,110 @@ +import multiprocessing +import shutil +from multiprocessing import Pool + +import SimpleITK as sitk +import numpy as np +from tqdm import tqdm +from batchgenerators.utilities.file_and_folder_operations import * +from nnunetv2.dataset_conversion.generate_dataset_json import generate_dataset_json +from nnunetv2.paths import nnUNet_raw + + +def copy_BraTS_segmentation_and_convert_labels_to_nnUNet(in_file: str, out_file: str) -> None: + # use this for segmentation only!!! + # nnUNet wants the labels to be continuous. BraTS is 0, 1, 2, 4 -> we make that into 0, 1, 2, 3 + img = sitk.ReadImage(in_file) + img_npy = sitk.GetArrayFromImage(img) + + uniques = np.unique(img_npy) + for u in uniques: + if u not in [0, 1, 2, 4]: + raise RuntimeError('unexpected label') + + seg_new = np.zeros_like(img_npy) + seg_new[img_npy == 4] = 3 + seg_new[img_npy == 2] = 1 + seg_new[img_npy == 1] = 2 + img_corr = sitk.GetImageFromArray(seg_new) + img_corr.CopyInformation(img) + sitk.WriteImage(img_corr, out_file) + + +def convert_labels_back_to_BraTS(seg: np.ndarray): + new_seg = np.zeros_like(seg) + new_seg[seg == 1] = 2 + new_seg[seg == 3] = 4 + new_seg[seg == 2] = 1 + return new_seg + + +def load_convert_labels_back_to_BraTS(filename, input_folder, output_folder): + a = sitk.ReadImage(join(input_folder, filename)) + b = sitk.GetArrayFromImage(a) + c = convert_labels_back_to_BraTS(b) + d = sitk.GetImageFromArray(c) + d.CopyInformation(a) + sitk.WriteImage(d, join(output_folder, filename)) + + +def convert_folder_with_preds_back_to_BraTS_labeling_convention(input_folder: str, output_folder: str, num_processes: int = 12): + """ + reads all prediction files (nifti) in the input folder, converts the labels back to BraTS convention and saves the + """ + maybe_mkdir_p(output_folder) + nii = subfiles(input_folder, suffix='.nii.gz', join=False) + with multiprocessing.get_context("spawn").Pool(num_processes) as p: + p.starmap(load_convert_labels_back_to_BraTS, zip(nii, [input_folder] * len(nii), [output_folder] * len(nii))) + + +if __name__ == '__main__': + brats_data_dir = '/home/stud/strasser/archive/brats2018/MICCAI_BraTS_2018_Data_Training' + + task_id = 42 + task_name = "BraTS2018" + + foldername = "Dataset%03.0d_%s" % (task_id, task_name) + + # setting up nnU-Net folders + out_base = join(nnUNet_raw, foldername) + imagestr = join(out_base, "imagesTr") + labelstr = join(out_base, "labelsTr") + maybe_mkdir_p(imagestr) + maybe_mkdir_p(labelstr) + + case_ids_hgg = subdirs(join(brats_data_dir, "HGG"), prefix='Brats', join=False) + case_ids_lgg = subdirs(join(brats_data_dir, "LGG"), prefix="Brats", join=False) + + print("copying hggs") + for c in tqdm(case_ids_hgg): + shutil.copy(join(brats_data_dir, "HGG", c, c + "_t1.nii"), join(imagestr, c + '_0000.nii')) + shutil.copy(join(brats_data_dir, "HGG", c, c + "_t1ce.nii"), join(imagestr, c + '_0001.nii')) + shutil.copy(join(brats_data_dir, "HGG", c, c + "_t2.nii"), join(imagestr, c + '_0002.nii')) + shutil.copy(join(brats_data_dir, "HGG", c, c + "_flair.nii"), join(imagestr, c + '_0003.nii')) + + copy_BraTS_segmentation_and_convert_labels_to_nnUNet(join(brats_data_dir, "HGG", c, c + "_seg.nii"), + join(labelstr, c + '.nii')) + print("copying lggs") + for c in tqdm(case_ids_lgg): + shutil.copy(join(brats_data_dir, "LGG", c, c + "_t1.nii"), join(imagestr, c + '_0000.nii')) + shutil.copy(join(brats_data_dir, "LGG", c, c + "_t1ce.nii"), join(imagestr, c + '_0001.nii')) + shutil.copy(join(brats_data_dir, "LGG", c, c + "_t2.nii"), join(imagestr, c + '_0002.nii')) + shutil.copy(join(brats_data_dir, "LGG", c, c + "_flair.nii"), join(imagestr, c + '_0003.nii')) + + copy_BraTS_segmentation_and_convert_labels_to_nnUNet(join(brats_data_dir, "LGG", c, c + "_seg.nii"), + join(labelstr, c + '.nii')) + + generate_dataset_json(out_base, + channel_names={0: 'T1', 1: 'T1ce', 2: 'T2', 3: 'Flair'}, + labels={ + 'background': 0, + 'whole tumor': (1, 2, 3), + 'tumor core': (2, 3), + 'enhancing tumor': (3, ) + }, + num_training_cases=(len(case_ids_lgg) + len(case_ids_hgg)), + file_ending='.nii', + regions_class_order=(1, 2, 3), + license='see https://www.synapse.org/#!Synapse:syn25829067/wiki/610863', + reference='see https://www.synapse.org/#!Synapse:syn25829067/wiki/610863', + dataset_release='1.0') diff --git a/nnunetv2/dataset_conversion/Dataset043_BraTS19.py b/nnunetv2/dataset_conversion/Dataset043_BraTS19.py index 12da53c27..b03673708 100644 --- a/nnunetv2/dataset_conversion/Dataset043_BraTS19.py +++ b/nnunetv2/dataset_conversion/Dataset043_BraTS19.py @@ -103,7 +103,7 @@ def convert_folder_with_preds_back_to_BraTS_labeling_convention(input_folder: st 'enhancing tumor': (3, ) }, num_training_cases=(len(case_ids_hgg) + len(case_ids_lgg)), - file_ending='.nii.gz', + file_ending='.nii', regions_class_order=(1, 2, 3), license='see https://www.synapse.org/#!Synapse:syn25829067/wiki/610863', reference='see https://www.synapse.org/#!Synapse:syn25829067/wiki/610863', From 8a1a79422a551c20e4315a473f79e0f8a9845edf Mon Sep 17 00:00:00 2001 From: Patrick Strasser Date: Sat, 20 Apr 2024 11:30:32 +0000 Subject: [PATCH 6/8] fix: add .nii to supported file endings --- nnunetv2/imageio/nibabel_reader_writer.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nnunetv2/imageio/nibabel_reader_writer.py b/nnunetv2/imageio/nibabel_reader_writer.py index a7d288fc4..f88527ecb 100644 --- a/nnunetv2/imageio/nibabel_reader_writer.py +++ b/nnunetv2/imageio/nibabel_reader_writer.py @@ -29,6 +29,7 @@ class NibabelIO(BaseReaderWriter): IMPORTANT: Run nnUNetv2_plot_overlay_pngs to verify that this did not destroy the alignment of data and seg! """ supported_file_endings = [ + '.nii', '.nii.gz', '.nrrd', '.mha' @@ -107,6 +108,7 @@ class NibabelIOWithReorient(BaseReaderWriter): IMPORTANT: Run nnUNetv2_plot_overlay_pngs to verify that this did not destroy the alignment of data and seg! """ supported_file_endings = [ + '.nii', '.nii.gz', '.nrrd', '.mha' From 2c97db3cb42b09a569a3b78dc6ea2308d4b6a062 Mon Sep 17 00:00:00 2001 From: Patrick Strasser Date: Mon, 22 Apr 2024 19:13:55 +0000 Subject: [PATCH 7/8] feat: move train.sh to scripts folder --- train.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/train.sh b/train.sh index 4cc12761e..f728c332c 100755 --- a/train.sh +++ b/train.sh @@ -3,7 +3,8 @@ source ~/env_file eval "$(conda shell.bash hook)" conda activate generic-nnunet -git checkout dev + +cd /home/stud/strasser/workspace/nnUNet && git checkout dev echo "starting training with fold $fold" -nnUNetv2_train 137 3d_fullres $fold --npz --c +nnUNetv2_train 42 3d_fullres $fold --npz From 3b9a7700efb9177cbcd5ddc9fea3056fc9225f3b Mon Sep 17 00:00:00 2001 From: Patrick Strasser Date: Sun, 28 Apr 2024 20:43:07 +0200 Subject: [PATCH 8/8] chore: minor changes for pr --- .../{Dataset042_BraTS2018.py => Dataset042_BraTS18.py} | 8 ++++---- nnunetv2/dataset_conversion/Dataset043_BraTS19.py | 8 ++++---- nnunetv2/dataset_conversion/Dataset137_BraTS21.py | 2 +- train.sh | 10 ---------- 4 files changed, 9 insertions(+), 19 deletions(-) rename nnunetv2/dataset_conversion/{Dataset042_BraTS2018.py => Dataset042_BraTS18.py} (94%) delete mode 100755 train.sh diff --git a/nnunetv2/dataset_conversion/Dataset042_BraTS2018.py b/nnunetv2/dataset_conversion/Dataset042_BraTS18.py similarity index 94% rename from nnunetv2/dataset_conversion/Dataset042_BraTS2018.py rename to nnunetv2/dataset_conversion/Dataset042_BraTS18.py index 0fe76bf13..12a2b5022 100644 --- a/nnunetv2/dataset_conversion/Dataset042_BraTS2018.py +++ b/nnunetv2/dataset_conversion/Dataset042_BraTS18.py @@ -1,6 +1,5 @@ import multiprocessing import shutil -from multiprocessing import Pool import SimpleITK as sitk import numpy as np @@ -47,7 +46,8 @@ def load_convert_labels_back_to_BraTS(filename, input_folder, output_folder): sitk.WriteImage(d, join(output_folder, filename)) -def convert_folder_with_preds_back_to_BraTS_labeling_convention(input_folder: str, output_folder: str, num_processes: int = 12): +def convert_folder_with_preds_back_to_BraTS_labeling_convention(input_folder: str, output_folder: str, + num_processes: int = 12): """ reads all prediction files (nifti) in the input folder, converts the labels back to BraTS convention and saves the """ @@ -58,7 +58,7 @@ def convert_folder_with_preds_back_to_BraTS_labeling_convention(input_folder: st if __name__ == '__main__': - brats_data_dir = '/home/stud/strasser/archive/brats2018/MICCAI_BraTS_2018_Data_Training' + brats_data_dir = ... task_id = 42 task_name = "BraTS2018" @@ -100,7 +100,7 @@ def convert_folder_with_preds_back_to_BraTS_labeling_convention(input_folder: st 'background': 0, 'whole tumor': (1, 2, 3), 'tumor core': (2, 3), - 'enhancing tumor': (3, ) + 'enhancing tumor': (3,) }, num_training_cases=(len(case_ids_lgg) + len(case_ids_hgg)), file_ending='.nii', diff --git a/nnunetv2/dataset_conversion/Dataset043_BraTS19.py b/nnunetv2/dataset_conversion/Dataset043_BraTS19.py index b03673708..35a176f00 100644 --- a/nnunetv2/dataset_conversion/Dataset043_BraTS19.py +++ b/nnunetv2/dataset_conversion/Dataset043_BraTS19.py @@ -1,6 +1,5 @@ import multiprocessing import shutil -from multiprocessing import Pool import SimpleITK as sitk import numpy as np @@ -47,7 +46,8 @@ def load_convert_labels_back_to_BraTS(filename, input_folder, output_folder): sitk.WriteImage(d, join(output_folder, filename)) -def convert_folder_with_preds_back_to_BraTS_labeling_convention(input_folder: str, output_folder: str, num_processes: int = 12): +def convert_folder_with_preds_back_to_BraTS_labeling_convention(input_folder: str, output_folder: str, + num_processes: int = 12): """ reads all prediction files (nifti) in the input folder, converts the labels back to BraTS convention and saves the """ @@ -58,7 +58,7 @@ def convert_folder_with_preds_back_to_BraTS_labeling_convention(input_folder: st if __name__ == '__main__': - brats_data_dir = '/home/stud/strasser/archive/brats2019/MICCAI_BraTS_2019_Data_Training' + brats_data_dir = ... task_id = 43 task_name = "BraTS2019" @@ -100,7 +100,7 @@ def convert_folder_with_preds_back_to_BraTS_labeling_convention(input_folder: st 'background': 0, 'whole tumor': (1, 2, 3), 'tumor core': (2, 3), - 'enhancing tumor': (3, ) + 'enhancing tumor': (3,) }, num_training_cases=(len(case_ids_hgg) + len(case_ids_lgg)), file_ending='.nii', diff --git a/nnunetv2/dataset_conversion/Dataset137_BraTS21.py b/nnunetv2/dataset_conversion/Dataset137_BraTS21.py index 74c259b95..b4817d282 100644 --- a/nnunetv2/dataset_conversion/Dataset137_BraTS21.py +++ b/nnunetv2/dataset_conversion/Dataset137_BraTS21.py @@ -57,7 +57,7 @@ def convert_folder_with_preds_back_to_BraTS_labeling_convention(input_folder: st if __name__ == '__main__': - brats_data_dir = '/home/stud/strasser/data/raw_downloaded_data' + brats_data_dir = '/home/isensee/drives/E132-Rohdaten/BraTS_2021/training' task_id = 137 task_name = "BraTS2021" diff --git a/train.sh b/train.sh deleted file mode 100755 index f728c332c..000000000 --- a/train.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -source ~/env_file - -eval "$(conda shell.bash hook)" -conda activate generic-nnunet - -cd /home/stud/strasser/workspace/nnUNet && git checkout dev - -echo "starting training with fold $fold" -nnUNetv2_train 42 3d_fullres $fold --npz