Commit
·
ac29da8
1
Parent(s):
7968536
combine_metrics_files.py
Browse files-----------------------------
Combine metrics.csv files from the different models into a single file, to be used by the statistics.p script
compare_ai_vs_human_annots.py
-----------------------------
Comparison between the AI and humman made segmentations on the OSLO-COMET dataset.
EvaluationScripts/combine_metrics_files.py
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
import os
|
| 3 |
+
from argparse import ArgumentParser
|
| 4 |
+
import re
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
DICT_MODEL_NAMES = {'BASELINE': 'BL',
|
| 8 |
+
'SEGGUIDED': 'SG',
|
| 9 |
+
'UW': 'UW'}
|
| 10 |
+
|
| 11 |
+
DICT_METRICS_NAMES = {'NCC': 'N',
|
| 12 |
+
'SSIM': 'S',
|
| 13 |
+
'DICE': 'D',
|
| 14 |
+
'DICE MACRO': 'D',
|
| 15 |
+
'HD': 'H', }
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
DF_COLS = ['SSIM', 'NCC', 'MSE', 'DICE_MACRO', 'HD', 'HD95', 'Time', 'TRE', 'Experiment', 'Model']
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
def get_model_name(in_path: str) -> str:
|
| 22 |
+
model = re.search('((UW|SEGGUIDED|BASELINE).*)_\d', in_path)
|
| 23 |
+
if model:
|
| 24 |
+
model = model.group(1).rstrip('_')
|
| 25 |
+
model = model.replace('_Lsim', '')
|
| 26 |
+
model = model.replace('_Lseg', '')
|
| 27 |
+
model = model.replace('_L', '')
|
| 28 |
+
model = model.replace('_', ' ')
|
| 29 |
+
model = model.upper()
|
| 30 |
+
elements = model.split()
|
| 31 |
+
model = elements[0]
|
| 32 |
+
metrics = list()
|
| 33 |
+
model = DICT_MODEL_NAMES[model]
|
| 34 |
+
for m in elements[1:]:
|
| 35 |
+
if m != 'MACRO':
|
| 36 |
+
metrics.append(DICT_METRICS_NAMES[m])
|
| 37 |
+
|
| 38 |
+
return '{}-{}'.format(model, ''.join(metrics))
|
| 39 |
+
else:
|
| 40 |
+
try:
|
| 41 |
+
model = re.search('(SyNCC|SyN)', in_path).group(1)
|
| 42 |
+
except AttributeError:
|
| 43 |
+
raise ValueError('Unknown folder name/model: '+ in_path)
|
| 44 |
+
return model
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
def find_metric_files(root_path: str, folder_filter: str) -> dict:
|
| 48 |
+
metric_files = dict()
|
| 49 |
+
starting_level = root_path.count(os.sep)
|
| 50 |
+
for r, d, f in os.walk(root_path):
|
| 51 |
+
level = r.count(os.sep) - starting_level
|
| 52 |
+
if level < 3:
|
| 53 |
+
for name in f:
|
| 54 |
+
if 'metrics.csv' == name and folder_filter in r.split(os.sep):
|
| 55 |
+
model = get_model_name(os.path.join(r, name))
|
| 56 |
+
metric_files[model] = os.path.join(r, name)
|
| 57 |
+
return metric_files
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
def read_metrics_files(metrics: dict, experiment: str) -> pd.DataFrame:
|
| 61 |
+
df = pd.DataFrame(columns=DF_COLS)
|
| 62 |
+
for k in metrics.keys():
|
| 63 |
+
csv = pd.read_csv(metrics[k], sep=';')
|
| 64 |
+
csv['Experiment'] = experiment
|
| 65 |
+
csv['Model'] = k
|
| 66 |
+
df = df.append(csv[DF_COLS], ignore_index=True)
|
| 67 |
+
return df
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
if __name__ == '__main__':
|
| 71 |
+
parser = ArgumentParser()
|
| 72 |
+
parser.add_argument('--output-dir', help='Output directory', default='./')
|
| 73 |
+
parser.add_argument('--ixi-runs', help='Directory were the evaluation outputs are stored')
|
| 74 |
+
parser.add_argument('--comet-runs', help='Directory were the evaluation outputs are stored')
|
| 75 |
+
parser.add_argument('--comet-tl-freezenone-runs', help='Directory were the evaluation outputs are stored')
|
| 76 |
+
parser.add_argument('--comet-tl-encoder-runs', help='Directory were the evaluation outputs are stored')
|
| 77 |
+
parser.add_argument('--ants-runs', help='Directory were the evaluation outputs are stored')
|
| 78 |
+
parser.add_argument('--folder-filter', default='Evaluate')
|
| 79 |
+
|
| 80 |
+
args = parser.parse_args()
|
| 81 |
+
|
| 82 |
+
assert os.path.exists(args.ixi_runs), 'IXI directory not found'
|
| 83 |
+
assert os.path.exists(args.comet_runs), 'COMET directory not found'
|
| 84 |
+
assert os.path.exists(args.comet_tl_freezenone_runs), 'COMET TL Fine Tuned Froze None directory not found'
|
| 85 |
+
assert os.path.exists(args.comet_tl_encoder_runs), 'COMET TL Fine Tuned in 2 Steps directory not found'
|
| 86 |
+
assert os.path.exists(args.ants_runs), 'COMET TL Fine Tuned in 2 Steps directory not found'
|
| 87 |
+
|
| 88 |
+
IXI_metrics = find_metric_files(args.ixi_runs, args.folder_filter)
|
| 89 |
+
COMET_metrics = find_metric_files(args.comet_runs, args.folder_filter)
|
| 90 |
+
COMET_TL_FTFN_metrics = find_metric_files(args.comet_tl_freezenone_runs, args.folder_filter)
|
| 91 |
+
COMET_TL_FT2S_metrics = find_metric_files(args.comet_tl_encoder_runs, args.folder_filter)
|
| 92 |
+
ANTS_metrics = find_metric_files(args.ants_runs, args.folder_filter)
|
| 93 |
+
|
| 94 |
+
IXI_df = read_metrics_files(IXI_metrics, 'IXI')
|
| 95 |
+
COMET_df = read_metrics_files(COMET_metrics, 'COMET')
|
| 96 |
+
COMET_TL_FtFn_df = read_metrics_files(COMET_TL_FTFN_metrics, 'COMET_TL_FtFn')
|
| 97 |
+
COMET_TL_Ft2S_df = read_metrics_files(COMET_TL_FT2S_metrics, 'COMET_TL_Ft2Stp')
|
| 98 |
+
ANTS_df = read_metrics_files(ANTS_metrics, 'ANTs')
|
| 99 |
+
|
| 100 |
+
df = pd.concat([IXI_df, COMET_df, COMET_TL_FtFn_df, COMET_TL_Ft2S_df, ANTS_df], ignore_index=True)
|
| 101 |
+
out_file_path = os.path.join(args.output_dir, 'Combined_metrics.csv')
|
| 102 |
+
if os.path.exists(out_file_path):
|
| 103 |
+
os.remove(out_file_path)
|
| 104 |
+
df.to_csv(out_file_path, sep=';', index=False)
|
| 105 |
+
print('Output file: ' + out_file_path)
|
EvaluationScripts/compare_ai_vs_human_annots.py
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os, sys
|
| 2 |
+
currentdir = os.path.dirname(os.path.realpath(__file__))
|
| 3 |
+
parentdir = os.path.dirname(currentdir)
|
| 4 |
+
sys.path.append(parentdir) # PYTHON > 3.3 does not allow relative referencing
|
| 5 |
+
|
| 6 |
+
import nibabel as nib
|
| 7 |
+
import re
|
| 8 |
+
import medpy.metric as medpy_metrics
|
| 9 |
+
|
| 10 |
+
import pandas as pd
|
| 11 |
+
|
| 12 |
+
import numpy as np
|
| 13 |
+
|
| 14 |
+
from tqdm import tqdm
|
| 15 |
+
|
| 16 |
+
import multiprocessing as mp
|
| 17 |
+
IMG_DIRECTORY = '/mnt/EncryptedData1/Laparoscopy/OSLO_COMET_dataset/OSLO_COMET_CT/Volumes_nii/test_set'
|
| 18 |
+
VES_SEG_DIRECTORY = '/mnt/EncryptedData1/Laparoscopy/OSLO_COMET_dataset/OSLO_COMET_CT/Vessels'
|
| 19 |
+
PAR_SEG_DIRECTORY = '/mnt/EncryptedData1/Laparoscopy/OSLO_COMET_dataset/OSLO_COMET_CT/Parenchyma'
|
| 20 |
+
|
| 21 |
+
LM_SEG_DIRECTORY = '/mnt/EncryptedData1/Laparoscopy/OSLO_COMET_dataset/OSLO_COMET_CT/LiverMask/test_set'
|
| 22 |
+
|
| 23 |
+
nii_FILENAME_PATTERN = '(.*)_CT.nii'
|
| 24 |
+
LV_VESSEL_FILENAME_PATTERN = '(.*)-vessels.nii'
|
| 25 |
+
LV_PARENCHYMA_FILENAME_PATTERN = '(.*)-livermask.nii'
|
| 26 |
+
|
| 27 |
+
OUT_DIRECTORY = '/mnt/EncryptedData1/Users/javier/ext_datasets/COMET_ai_vs_human'
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
def process_group(file_list):
|
| 31 |
+
# print('Got: ' + ','.join(file_list))
|
| 32 |
+
img_file, par_file, ves_file, lm_par_file, lm_ves_file = file_list
|
| 33 |
+
img_num = int(re.match(nii_FILENAME_PATTERN, os.path.split(img_file)[-1])[1])
|
| 34 |
+
|
| 35 |
+
human_par = nib.load(par_file)
|
| 36 |
+
header = human_par.header
|
| 37 |
+
human_par = np.asarray(human_par.dataobj)
|
| 38 |
+
human_ves = np.asarray(nib.load(ves_file).dataobj)
|
| 39 |
+
|
| 40 |
+
lm_par = np.asarray(nib.load(lm_par_file).dataobj)
|
| 41 |
+
lm_ves = np.asarray(nib.load(lm_ves_file).dataobj)
|
| 42 |
+
lm_ves[lm_ves > 0] = 1
|
| 43 |
+
|
| 44 |
+
dsc_par = medpy_metrics.dc(human_par, lm_par)
|
| 45 |
+
dsc_ves = medpy_metrics.dc(human_ves, lm_ves)
|
| 46 |
+
|
| 47 |
+
hd_par = medpy_metrics.hd(human_par, lm_par, voxelspacing=header['pixdim'][1:4])
|
| 48 |
+
hd_ves = medpy_metrics.hd(human_ves, lm_ves, voxelspacing=header['pixdim'][1:4])
|
| 49 |
+
|
| 50 |
+
hd95_par = medpy_metrics.hd95(human_par, lm_par, voxelspacing=header['pixdim'][1:4])
|
| 51 |
+
hd95_ves = medpy_metrics.hd95(human_ves, lm_ves, voxelspacing=header['pixdim'][1:4])
|
| 52 |
+
|
| 53 |
+
return img_num, dsc_par, dsc_ves, hd_par, hd_ves, hd95_par, hd95_ves
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
if __name__ == '__main__':
|
| 57 |
+
img_list = [os.path.join(IMG_DIRECTORY, f) for f in os.listdir(IMG_DIRECTORY) if f.endswith('.nii')]
|
| 58 |
+
img_list.sort()
|
| 59 |
+
|
| 60 |
+
ves_seg_list = [os.path.join(VES_SEG_DIRECTORY, os.path.split(f)[-1]+'.gz') for f in img_list]
|
| 61 |
+
ves_seg_list.sort()
|
| 62 |
+
|
| 63 |
+
par_seg_list = [os.path.join(PAR_SEG_DIRECTORY, os.path.split(f)[-1]+'.gz') for f in img_list]
|
| 64 |
+
par_seg_list.sort()
|
| 65 |
+
|
| 66 |
+
lm_ves_seg_list = [os.path.join(LM_SEG_DIRECTORY, f) for f in os.listdir(LM_SEG_DIRECTORY) if f.endswith('-vessels.nii')]
|
| 67 |
+
lm_ves_seg_list.sort()
|
| 68 |
+
|
| 69 |
+
lm_par_seg_list = [os.path.join(LM_SEG_DIRECTORY, f) for f in os.listdir(LM_SEG_DIRECTORY) if f.endswith('-livermask.nii')]
|
| 70 |
+
lm_par_seg_list.sort()
|
| 71 |
+
|
| 72 |
+
os.makedirs(OUT_DIRECTORY, exist_ok=True)
|
| 73 |
+
|
| 74 |
+
zip_lists = zip(img_list, par_seg_list, ves_seg_list, lm_par_seg_list, lm_ves_seg_list)
|
| 75 |
+
mets = ['DSC', 'DSC', 'HD', 'HD', 'H95', 'H95']
|
| 76 |
+
segs = ['Parenchyma', 'Vessels', 'Parenchyma', 'Vessels', 'Parenchyma', 'Vessels']
|
| 77 |
+
cols = list(zip(*[mets, segs]))
|
| 78 |
+
idx = pd.MultiIndex.from_tuples(cols, names=['Metrics', 'Labels'])
|
| 79 |
+
df = pd.DataFrame(index=idx)
|
| 80 |
+
|
| 81 |
+
print('\nLaunching processes...')
|
| 82 |
+
with mp.Pool(11, maxtasksperchild=1) as p:
|
| 83 |
+
results = p.map_async(process_group, zip_lists)
|
| 84 |
+
for v in results.get():
|
| 85 |
+
df[v[0]] = v[1:]
|
| 86 |
+
|
| 87 |
+
# for i, (img_file, par_file, ves_file, lm_par_file, lm_ves_file) in tqdm(enumerate(zip_lists), total=len(img_list)):
|
| 88 |
+
# img_name = re.match(nii_FILENAME_PATTERN, os.path.split(img_file)[-1])[1]
|
| 89 |
+
#
|
| 90 |
+
# img = nib.load(img_file)
|
| 91 |
+
# human_par = nib.load(par_file)
|
| 92 |
+
# header = human_par.header
|
| 93 |
+
# human_par = np.asarray(human_par.dataobj)
|
| 94 |
+
# human_ves = np.asarray(nib.load(ves_file).dataobj)
|
| 95 |
+
#
|
| 96 |
+
# lm_par = np.asarray(nib.load(lm_par_file).dataobj)
|
| 97 |
+
# lm_ves = np.asarray(nib.load(lm_ves_file).dataobj)
|
| 98 |
+
# lm_ves[lm_ves > 0] = 1
|
| 99 |
+
#
|
| 100 |
+
# dsc_par = medpy_metrics.dc(human_par, lm_par)
|
| 101 |
+
# dsc_ves = medpy_metrics.dc(human_ves, lm_ves)
|
| 102 |
+
#
|
| 103 |
+
# hd_par = medpy_metrics.hd(human_par, lm_par, voxelspacing=header['pixdim'][1:4])
|
| 104 |
+
# hd_ves = medpy_metrics.hd(human_ves, lm_ves, voxelspacing=header['pixdim'][1:4])
|
| 105 |
+
#
|
| 106 |
+
# hd95_par = medpy_metrics.hd95(human_par, lm_par, voxelspacing=header['pixdim'][1:4])
|
| 107 |
+
# hd95_ves = medpy_metrics.hd95(human_ves, lm_ves, voxelspacing=header['pixdim'][1:4])
|
| 108 |
+
#
|
| 109 |
+
# df[i] = [dsc_par, dsc_ves, hd_par, hd_ves, hd95_par, hd95_ves]
|
| 110 |
+
print('\nResults...')
|
| 111 |
+
print(df)
|
| 112 |
+
|
| 113 |
+
print('\nSummary...')
|
| 114 |
+
print(df.describe())
|
| 115 |
+
|
| 116 |
+
df.to_csv('comparison.csv', sep=';')
|