| import numpy as np |
| import statsmodels |
| import scipy |
| from statsmodels.stats.multicomp import pairwise_tukeyhsd |
| from statsmodels.stats.multitest import fdrcorrection |
| from scipy import stats |
| import pandas as pd |
|
|
| import argparse |
| import os |
|
|
| |
| pd.options.display.max_colwidth = 100 |
|
|
|
|
| def post_hoc_ixi(df_in: pd.DataFrame, outdir: str = './'): |
| df = df_in[df_in["Experiment"] == "IXI"] |
|
|
| TRE_values = df["TRE"] |
| m_comp = pairwise_tukeyhsd(df["TRE"], df["Model"], alpha=0.05) |
| model_names = np.unique(df["Model"]) |
|
|
| all_pvalues = -1 * np.ones((len(model_names), len(model_names)), dtype=np.float32) |
| pvs = m_comp.pvalues |
| cnt = 0 |
| for i in range(len(model_names)): |
| for j in range(i + 1, len(model_names)): |
| all_pvalues[i, j] = pvs[cnt] |
| cnt += 1 |
| all_pvalues = np.round(all_pvalues, 6) |
| all_pvalues = all_pvalues[:-1, 1:] |
|
|
| col_new_names = ["\textbf{\rot{\multicolumn{1}{r}{" + n + "}}}" for n in model_names] |
|
|
| out_pd = pd.DataFrame(data=all_pvalues, index=model_names[:-1], columns=col_new_names[1:]) |
| stack = out_pd.stack() |
| stack[(0 < stack) & (stack <= 0.001)] = '\cellcolor{green!25}$<$0.001' |
|
|
| for i in range(stack.shape[0]): |
| try: |
| curr = stack[i] |
| if (float(curr) > 0.0011) & (float(curr) < 0.05): |
| stack[i] = '\cellcolor{green!50}' + str(np.round(stack[i], 3)) |
| elif (float(curr) >= 0.05) & (float(curr) < 0.1): |
| stack[i] = '\cellcolor{red!50}' + str(np.round(stack[i], 3)) |
| elif (float(curr) >= 0.1): |
| stack[i] = '\cellcolor{red!25}' + str(np.round(stack[i], 3)) |
| except Exception: |
| continue |
|
|
| out_pd = stack.unstack() |
| out_pd = out_pd.replace(-1.0, "-") |
| out_pd = out_pd.replace(-0.0, '\cellcolor{green!25}$<$0.001') |
|
|
| with open(os.path.join(outdir, "tukey_pvalues_result_IXI.txt"), "w") as pfile: |
| pfile.write("{}".format(out_pd.to_latex(escape=False, column_format="r" + "c"*all_pvalues.shape[1], bold_rows=True))) |
| |
| print(out_pd) |
|
|
|
|
| def study_seg_guided_ANTs(df_in: pd.DataFrame): |
| tre_sg = df_in[(df_in["Experiment"] == "COMET_TL_Ft2Stp") & (df_in["Model"] == "SG-NSD")]["TRE"] |
| tre_syn = df_in[(df_in["Experiment"] == "ANTs") & (df_in["Model"] == "SyN")]["TRE"] |
| tre_syncc = df_in[(df_in["Experiment"] == "ANTs") & (df_in["Model"] == "SyNCC")]["TRE"] |
|
|
| pvs = list() |
| pvs.append(stats.wilcoxon(tre_sg, tre_syn, alternative="less").pvalue) |
| pvs.append(stats.wilcoxon(tre_sg, tre_syncc, alternative="less").pvalue) |
|
|
| |
| corrected_pvs = fdrcorrection(pvs, alpha=0.05, method="indep")[1] |
|
|
| print("SG-NSD vs SyN:", corrected_pvs[0]) |
| print("SG-NSD vs SyNCC:", corrected_pvs[1]) |
|
|
|
|
| def study_baseline_ANTs(df_in: pd.DataFrame): |
| tre_bl = df_in[(df_in["Experiment"] == "COMET_TL_Ft2Stp") & (df_in["Model"] == "BL-N")]["TRE"] |
| tre_syn = df_in[(df_in["Experiment"] == "ANTs") & (df_in["Model"] == "SyN")]["TRE"] |
| tre_syncc = df_in[(df_in["Experiment"] == "ANTs") & (df_in["Model"] == "SyNCC")]["TRE"] |
|
|
| pvs = list() |
| pvs.append(stats.wilcoxon(tre_bl, tre_syn, alternative="less").pvalue) |
| pvs.append(stats.wilcoxon(tre_bl, tre_syncc, alternative="less").pvalue) |
|
|
| |
| corrected_pvs = fdrcorrection(pvs, alpha=0.05, method="indep")[1] |
|
|
| print("BL-N vs SyN:", corrected_pvs[0]) |
| print("BL-N vs SyNCC:", corrected_pvs[1]) |
|
|
|
|
| def study_transfer_learning_benefit(df_in: pd.DataFrame): |
| df_tl = df_in[df_in["Experiment"] == "COMET_TL_Ft2Stp"] |
| df_orig = df[df["Experiment"] == "COMET"] |
|
|
| pvs = [] |
| for model in ["BL-N", "SG-NSD", "UW-NSD"]: |
|
|
| curr_tl = df_tl[df_tl["Model"] == model] |
| curr_orig = df_orig[df_orig["Model"] == model] |
|
|
| TRE_tl = curr_tl["TRE"] |
| TRE_orig = curr_orig["TRE"] |
|
|
| |
| ret = stats.wilcoxon(TRE_tl, TRE_orig, alternative="less") |
| pv = ret.pvalue |
| pvs.append(pv) |
|
|
| |
| corrected_pvs = fdrcorrection(pvs, alpha=0.05, method="indep")[1] |
|
|
| print("BL-N:", corrected_pvs[0]) |
| print("SG-NSD:", corrected_pvs[1]) |
| print("UW-NSD:", corrected_pvs[2]) |
|
|
| def post_hoc_comet(df_in: pd.DataFrame): |
| df_tl = df_in[df_in["Experiment"] == "COMET_TL_Ft2Stp"] |
|
|
| filter_ = np.array([x in ["BL-N", "SG-NSD", "UW-NSD"] for x in df_tl["Model"]]) |
|
|
| df_tl = df_tl[filter_] |
|
|
| |
| ret1 = stats.wilcoxon( |
| df_tl[df_tl["Model"] == "SG-NSD"]["TRE"], |
| df_tl[df_tl["Model"] == "BL-N"]["TRE"], |
| alternative="less" |
| ) |
| pv1 = ret1.pvalue |
|
|
| |
| ret2 = stats.wilcoxon( |
| df_tl[df_tl["Model"] == "UW-NSD"]["TRE"], |
| df_tl[df_tl["Model"] == "SG-NSD"]["TRE"], |
| alternative="less" |
| ) |
| pv2 = ret2.pvalue |
|
|
| |
| pvs = [pv1, pv2] |
| corrected_pvs = fdrcorrection(pvs, alpha=0.05, method="indep")[1] |
|
|
| print("Seg-guiding benefit:", corrected_pvs[0]) |
| print("Uncertainty-weighting benefit:", corrected_pvs[1]) |
|
|
|
|
| if __name__ == "__main__": |
| parser = argparse.ArgumentParser() |
| parser.add_argument('--file', '-f', type=str, help='CSV file with the metrics') |
| parser.add_argument('--sep', type=str, help='CSV Separator (default: ;)', default=';') |
| parser.add_argument('--outdir', type=str, help='Output directory (default: .)', default='./') |
| args = parser.parse_args() |
|
|
| assert os.path.exists(args.file), 'CSV file not found' |
| os.makedirs(args.outdir, exist_ok=True) |
| df = pd.read_csv(args.file, sep=args.sep) |
| if "Unnamed" in df.columns[0]: |
| df = df.iloc[:, 1:] |
| if any(['_' in m for m in df["Model"].unique()]): |
| df["Model"] = [x.replace("_", "-") for x in df["Model"]] |
|
|
| print("\nComparing all contrasts in TRE of all models in the IXI dataset:") |
| post_hoc_ixi(df, args.outdir) |
|
|
| print("\nTransfer learning benefit (COMET):") |
| study_transfer_learning_benefit(df) |
|
|
| print("\nAssessing whether there is a benefit to segmentation-guiding and uncertainty weighting (COMET):") |
| post_hoc_comet(df) |
|
|
| print("\nAssessing the performance of BL-N vs ANTs registration (COMET):") |
| study_baseline_ANTs(df) |
|
|
| print("\nAssessing the performance of SG-NSD vs ANTs registration (COMET):") |
| study_seg_guided_ANTs(df) |
|
|
| print('Statsmodels v.: ' + statsmodels.__version__) |
| print('Scipy v.: ' + scipy.__version__) |
|
|