"""Master entry point: generate the whole figures_paper set. Usage: python figures_paper/scripts/make_all_figures.py --package-root . Behaviour: * auto-creates figures_paper/{pdf,png,svg,data}; * each figure is isolated in try/except so one failure never aborts the rest; * reads real CSV/NPY files where present, otherwise uses reported fallback numbers; * prints a per-figure status table; * writes figures_paper/README_figures.md with captions, sources, file paths and notes. """ from __future__ import annotations import argparse import importlib.util import sys import traceback from pathlib import Path import style # ordered list of (module_file, suggested LaTeX position) FIGURES = [ ("fig1_graph_overview.py", "Sec. Introduction / Task definition"), ("fig2_sparsity.py", "Sec. Dataset"), ("fig3_roadmap.py", "Sec. Results (overview)"), ("fig4_architecture.py", "Sec. Method"), ("fig5_ablation_highorder.py", "Sec. Ablation"), ("fig6_rank_vs_threshold.py", "Sec. Method / Decision rule"), ("fig7_error_heatmap.py", "Sec. Error analysis"), ("figA1_hyperparam.py", "Appendix"), ("figA2_rw_ablation.py", "Appendix"), ("figA3_feature_importance.py", "Appendix"), ("figA4_oof_pr.py", "Appendix"), ] def _load(fname, scripts): spec = importlib.util.spec_from_file_location(fname[:-3], scripts / fname) mod = importlib.util.module_from_spec(spec) spec.loader.exec_module(mod) return mod def main(): ap = argparse.ArgumentParser() ap.add_argument("--package-root", default=".", help="repo root containing data_and_docs/ and validation_runs/") args = ap.parse_args() root = Path(args.package_root).resolve() scripts = Path(__file__).resolve().parent out = style.ensure_dirs(root) results = [] for fname, latex in FIGURES: try: mod = _load(fname, scripts) res = mod.make(root, out) except Exception as e: # noqa: BLE001 res = dict(key=fname[:-3], title=fname, status="error", files=[], sources=[], caption="", note=f"{type(e).__name__}: {e}", traceback=traceback.format_exc()) res["latex"] = latex results.append(res) print(f"[{res.get('status','?'):>8}] {res['key']}") _write_readme(root, results) print("\n=== summary ===") for r in results: print(f" {r['key']:<28} {r.get('status','?'):<8} -> {', '.join(r.get('files', [])) or '(no files)'}") print("\nREADME -> figures_paper/README_figures.md") def _write_readme(root, results): lines = [ "# Figures for the CS3319 Project 2 paper\n", "Auto-generated by `figures_paper/scripts/make_all_figures.py`. Every figure is emitted as " "`.pdf` (vector, `pdf.fonttype=42` TrueType-embedded — venue-safe), `.png` (300 dpi preview) " "and `.svg`. Widths follow ACM `sigconf`: single-column 3.25 in, double-column 6.75 in.\n", "## Generation\n", "```bash\npython figures_paper/scripts/make_all_figures.py --package-root .\n```\n", "## Status\n", "| figure | status | files | suggested placement |\n|---|---|---|---|", ] for r in results: status = r.get("status", "?") files = ", ".join(r.get("files", [])) or "—" lines.append(f"| {r['key']} | {status} | {files} | {r.get('latex','')} |") lines.append("\n## Captions, sources and notes\n") for r in results: lines.append(f"### {r['title']}") lines.append(f"- **status:** {r.get('status','?')}") if r.get("sources"): lines.append("- **data sources:** " + "; ".join(r["sources"])) if r.get("files"): lines.append("- **files:** " + ", ".join( f"`figures_paper/{{pdf,png,svg}}/{f}`" for f in r["files"])) cap = r.get("caption", "").strip() if cap: lines.append(f"- **caption draft:** {cap}") if r.get("note"): lines.append(f"- **note:** {r['note']}") if r.get("traceback"): lines.append("```python\n" + r["traceback"] + "\n```") lines.append("") lines += [ "## Inserting into LaTeX (ACM sigconf)\n", "```latex\n\\usepackage{graphicx}\n", "% single-column (3.25 in)\n\\begin{figure}\n \\centering\n \\includegraphics[width=\\columnwidth]{figures_paper/pdf/fig2_sparsity.pdf}\n \\caption{...}\n\\end{figure}\n", "% double-column (6.75 in)\n\\begin{figure*}\n \\centering\n \\includegraphics[width=\\textwidth]{figures_paper/pdf/fig3_roadmap.pdf}\n \\caption{...}\n\\end{figure*}\n```\n", "Use the `.pdf` for the camera-ready (vector, embedded fonts); the `.png` is only for " "previews / draft review.\n", ] (root / "figures_paper" / "README_figures.md").write_text("\n".join(lines), encoding="utf-8") if __name__ == "__main__": # make the scripts dir importable so `import style` / sibling fig modules work sys.path.insert(0, str(Path(__file__).resolve().parent)) main()