90 lines
2.9 KiB
Python
90 lines
2.9 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
Assemble a metadata-explainability comparison panel.
|
||
|
||
Layout (2 rows × 4 cols):
|
||
row 0 = binary, row 1 = multiclass
|
||
|
||
col 0: single md_importance
|
||
col 1: ensemble md_importance
|
||
col 2: nocrop ROC
|
||
col 3: excl_phakic_axial ROC
|
||
|
||
Usage
|
||
-----
|
||
python scripts/output_analysis/visualizations/build_md_explainability_panel.py \
|
||
--nocrop-dir analysis_data/pipeline_nocrop \
|
||
--excl-dir analysis_data/pipeline_nocrop_excl_phakic_axial \
|
||
--out analysis_data/pipeline_nocrop/md_explainability_panel.png
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
import argparse
|
||
from pathlib import Path
|
||
|
||
import matplotlib
|
||
matplotlib.use("Agg")
|
||
import matplotlib.pyplot as plt
|
||
import matplotlib.image as mpimg
|
||
|
||
|
||
# (row, col, dir_key, rel_path, label)
|
||
# dir_key: "nocrop" or "excl"
|
||
CELLS = [
|
||
# ---- binary row (row 0) ----
|
||
(0, 0, "nocrop", "binary/single/explainability_md_importance_summary.png",
|
||
"Binary — Single"),
|
||
(0, 1, "nocrop", "binary/ensemble/explainability_md_importance_summary.png",
|
||
"Binary — Ensemble"),
|
||
(0, 2, "nocrop", "binary/ensemble/plots/roc_probs_fused_mean_ovr.png",
|
||
"Binary — nocrop ROC"),
|
||
(0, 3, "excl", "binary/ensemble/plots/roc_probs_fused_mean_ovr.png",
|
||
"Binary — excl phakic+axial ROC"),
|
||
# ---- multiclass row (row 1) ----
|
||
(1, 0, "nocrop", "multiclass/single/explainability_md_importance_summary.png",
|
||
"Multiclass — Single"),
|
||
(1, 1, "nocrop", "multiclass/ensemble/explainability_md_importance_summary.png",
|
||
"Multiclass — Ensemble"),
|
||
(1, 2, "nocrop", "multiclass/ensemble/plots/roc_probs_fused_mean_ovr.png",
|
||
"Multiclass — nocrop ROC"),
|
||
(1, 3, "excl", "multiclass/ensemble/plots/roc_probs_fused_mean_ovr.png",
|
||
"Multiclass — excl phakic+axial ROC"),
|
||
]
|
||
|
||
|
||
def main():
|
||
ap = argparse.ArgumentParser()
|
||
ap.add_argument("--nocrop-dir", default="analysis_data/pipeline_nocrop")
|
||
ap.add_argument("--excl-dir", default="analysis_data/pipeline_nocrop_excl_phakic_axial")
|
||
ap.add_argument("--out", default=None)
|
||
args = ap.parse_args()
|
||
|
||
nocrop_dir = Path(args.nocrop_dir)
|
||
excl_dir = Path(args.excl_dir)
|
||
out = Path(args.out) if args.out else nocrop_dir / "md_explainability_panel.png"
|
||
|
||
fig = plt.figure(figsize=(24, 12))
|
||
gs = fig.add_gridspec(
|
||
2, 4,
|
||
hspace=0.08,
|
||
wspace=0.04,
|
||
)
|
||
|
||
dirs = {"nocrop": nocrop_dir, "excl": excl_dir}
|
||
|
||
for row, col, dir_key, rel, label in CELLS:
|
||
ax = fig.add_subplot(gs[row, col])
|
||
img = mpimg.imread(str(dirs[dir_key] / rel))
|
||
ax.imshow(img)
|
||
ax.axis("off")
|
||
ax.set_title(label, fontsize=11, pad=5)
|
||
|
||
out.parent.mkdir(parents=True, exist_ok=True)
|
||
fig.savefig(out, dpi=150, bbox_inches="tight")
|
||
plt.close(fig)
|
||
print(f"Saved → {out}")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|