File size: 6,134 Bytes
141bacd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
"""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"

# Labels are the numbers PAPER.tex actually resolves to (PAPER.aux), not the
# historical filenames: fig5_* is Figure 2 and fig6_* is Figure 5.
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"),
    # S4 removed -- contained stale class vocab
    ("S5",  "supplement/05_adversary_purification.pdf",                    "Adversary purification"),
    ("S6",  "supplement/06_cross_system_prototypes.pdf",                   "Cross-system prototype map"),
    # S7 removed -- contained stale class vocab
    # S8 removed -- contained stale class vocab
    # S9 removed -- contained stale class vocab
    # S10 removed -- contained stale class vocab
    ("S11", "supplement/11_novel_populations.pdf",                         "Novel populations (legacy)"),
    # S12 removed -- contained stale class vocab
    ("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)
    # NO bbox_inches="tight" here: it crops the page down to the text bbox,
    # so the heading fills the sheet no matter what fontsize is set.
    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()