| """merge every paper figure into one browsable pdf.
|
|
|
| section-title pages divide main / supplement / biology; each figure gets
|
| a small header page with its filename so a reader can find the source.
|
| """
|
| from __future__ import annotations
|
| from pathlib import Path
|
| from pypdf import PdfWriter
|
| import matplotlib
|
| matplotlib.use("Agg")
|
| import matplotlib.pyplot as plt
|
|
|
| import os as _os
|
| from pathlib import Path as _Path
|
| PANDA_ROOT = _Path(_os.environ.get("PANDA_ROOT", str(_Path(__file__).resolve().parents[2])))
|
| ROOT = Path(str(PANDA_ROOT))
|
| FIG = ROOT / "figures"
|
| OUT = FIG / "PANDA_all_figures.pdf"
|
| TMP = FIG / "_tmp_titlepages.pdf"
|
|
|
|
|
|
|
| MAIN = [
|
| ("Figure 1", "fig1_perclass_f1.pdf", "Per-class held-out 5-fold F1 across three systems"),
|
| ("Figure 2", "fig5_dingwall_umap.pdf", "Dingwall UMAP (predicted class and En1 genotype)"),
|
| ("Figure 3", "fig3_dahlin_heatmap.pdf", "Dahlin Kit-W41 vs WT within-class pathway module deltas"),
|
| ("Figure 4", "fig4_veres_stage_stack.pdf", "Veres predicted class fraction per protocol stage"),
|
| ("Figure 5", "fig6_multi_umap.pdf", "Discovery-target UMAPs across skin / HSC / pancreas"),
|
| ]
|
|
|
| SUPP = [
|
| ("S1", "supplement/01_cv_summary.pdf", "CV summary"),
|
| ("S2", "supplement/02_per_class_f1.pdf", "Per-class F1"),
|
| ("S3", "supplement/03_prototype_cosine.pdf", "Prototype intra-cosine"),
|
|
|
| ("S5", "supplement/05_adversary_purification.pdf", "Adversary purification"),
|
| ("S6", "supplement/06_cross_system_prototypes.pdf", "Cross-system prototype map"),
|
|
|
|
|
|
|
|
|
| ("S11", "supplement/11_novel_populations.pdf", "Novel populations (legacy)"),
|
|
|
| ("S13", "supplement/13_dingwall_umap.pdf", "Dingwall UMAP (legacy)"),
|
| ("S14", "supplement/14_dahlin_umap.pdf", "Dahlin UMAP (legacy)"),
|
| ("S15", "supplement/15_veres_umap.pdf", "Veres UMAP (legacy)"),
|
| ("S16", "supplement/16_dingwall_discovery.pdf", "Dingwall discovery (legacy)"),
|
| ("S17", "supplement/17_dahlin_discovery.pdf", "Dahlin discovery (legacy)"),
|
| ("S18", "supplement/18_veres_discovery.pdf", "Veres discovery (legacy)"),
|
| ("S19", "supplement/19_myeloid_network.pdf", "Myeloid gene-gene network"),
|
| ("S20", "supplement/20_placode_wnt_module.pdf", "Placode WNT module"),
|
| ("S23", "supplement/23_anchor_delta_recall.pdf", "Anchor delta recall"),
|
| ("S24", "supplement/24_pca_vs_marker_umaps_dingwall_by_genotype.pdf", "PCA vs Marker: Dingwall by genotype"),
|
| ("S24b","supplement/24b_pca_vs_marker_umaps_dingwall_by_class.pdf", "PCA vs Marker: Dingwall by class"),
|
| ("S25", "supplement/25_pca_vs_marker_umaps_dahlin_by_genotype.pdf", "PCA vs Marker: Dahlin by genotype"),
|
| ("S25b","supplement/25b_pca_vs_marker_umaps_dahlin_by_class.pdf", "PCA vs Marker: Dahlin by class"),
|
| ("S26", "supplement/26_pca_vs_marker_umaps_veres_by_stage.pdf", "PCA vs Marker: Veres by stage"),
|
| ("S26b","supplement/26b_pca_vs_marker_umaps_veres_by_class.pdf", "PCA vs Marker: Veres by class"),
|
| ("S27", "supplement/27_dingwall_en1_enrichment.pdf", "Dingwall En1 class enrichment"),
|
| ("S28", "supplement/28_melanocyte_pathway_modules.pdf", "Melanocyte pathway modules"),
|
| ]
|
|
|
| BIO = [
|
| ("B1", "biology/biology_01_dingwall_umap.pdf", "Dingwall UMAP (biology)"),
|
| ("B2", "biology/biology_02_primary_eden.pdf", "Primary EDEN candidate: Derm2"),
|
| ("B3", "biology/biology_03_melanoblast_mitf.pdf", "Melanoblast MITF-axis quadrant"),
|
| ("B4", "biology/biology_04_dahlin_metabolism.pdf", "Dahlin per-lineage metabolism"),
|
| ("B5", "biology/biology_05_dahlin_composition.pdf", "Dahlin composition shift"),
|
| ("B6", "biology/biology_06_veres_beta_quadrant.pdf", "Veres beta-lineage quadrant"),
|
| ("B7", "biology/biology_07_veres_polyhormonal.pdf", "Veres polyhormonal SC-alpha"),
|
| ("B8", "biology/biology_08_prototype_geometry.pdf", "Prototype geometry"),
|
| ]
|
|
|
|
|
| def make_title_page(text_top, text_body):
|
| fig = plt.figure(figsize=(8.5, 11))
|
| fig.text(0.5, 0.55, text_top, ha="center", va="center", fontsize=17, weight="bold")
|
| fig.text(0.5, 0.45, text_body, ha="center", va="center", fontsize=12)
|
| |
| |
| fig.savefig(TMP)
|
| plt.close(fig)
|
|
|
|
|
| def append_group(w, title, items):
|
| make_title_page(title, "")
|
| w.append(str(TMP))
|
| for tag, path, desc in items:
|
| p = FIG / path
|
| if not p.exists():
|
| print(f" [skip] {path} missing")
|
| continue
|
| make_title_page(tag, f"{desc}\n\n{path}")
|
| w.append(str(TMP))
|
| w.append(str(p))
|
| print(f" + {tag} {p.name}")
|
|
|
|
|
| def main():
|
| w = PdfWriter()
|
| make_title_page("PANDA — all figures", "main text · supplement · biology")
|
| w.append(str(TMP))
|
| append_group(w, "Main text", MAIN)
|
| append_group(w, "Supplement", SUPP)
|
| append_group(w, "Biology", BIO)
|
| with open(OUT, "wb") as f:
|
| w.write(f)
|
| TMP.unlink(missing_ok=True)
|
| print(f"\n[all] wrote {OUT} ({OUT.stat().st_size / 1024:.0f} KB, "
|
| f"{len(w.pages)} pages)")
|
|
|
|
|
| if __name__ == "__main__":
|
| main()
|
|
|