diff --git a/paper/pnas/figs/fig1a.pdf b/paper/pnas/figs/fig1a.pdf
index a668b95..5a1b16e 100644
Binary files a/paper/pnas/figs/fig1a.pdf and b/paper/pnas/figs/fig1a.pdf differ
diff --git a/paper/pnas/figs/icons/pea.png b/paper/pnas/figs/icons/pea.png
deleted file mode 100644
index 5a4f788..0000000
Binary files a/paper/pnas/figs/icons/pea.png and /dev/null differ
diff --git a/paper/pnas/figs/icons/pea.svg b/paper/pnas/figs/icons/pea.svg
new file mode 100644
index 0000000..d2d65a7
--- /dev/null
+++ b/paper/pnas/figs/icons/pea.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/paper/pnas/figs/icons/robot.png b/paper/pnas/figs/icons/robot.png
deleted file mode 100644
index d4fe920..0000000
Binary files a/paper/pnas/figs/icons/robot.png and /dev/null differ
diff --git a/paper/pnas/figs/icons/robot.svg b/paper/pnas/figs/icons/robot.svg
new file mode 100644
index 0000000..1e54892
--- /dev/null
+++ b/paper/pnas/figs/icons/robot.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/paper/pnas/main.pdf b/paper/pnas/main.pdf
index c96b4f8..5a69f3b 100644
Binary files a/paper/pnas/main.pdf and b/paper/pnas/main.pdf differ
diff --git a/paper/pnas/make_figs.py b/paper/pnas/make_figs.py
index 65e7a27..1e945db 100644
--- a/paper/pnas/make_figs.py
+++ b/paper/pnas/make_figs.py
@@ -42,21 +42,41 @@ def save(fig, name):
print("wrote", OUT / f"{name}.pdf")
+def _icon(svg_name: str):
+ """Rasterise a committed icon SVG at 2048 px (print-lossless at the ~0.3 in placed size).
+
+ Requires ``rsvg-convert`` (librsvg). The SVGs are the committed source of truth; no derived
+ PNGs are kept in the repo.
+ """
+ import subprocess
+ import tempfile
+
+ svg = OUT / "icons" / svg_name
+ with tempfile.NamedTemporaryFile(suffix=".png") as f:
+ try:
+ subprocess.run(["rsvg-convert", "-w", "2048", "-h", "2048", "-o", f.name, str(svg)],
+ check=True, capture_output=True)
+ except FileNotFoundError as e:
+ raise RuntimeError("rsvg-convert (librsvg) is required to rasterise the icon SVGs "
+ "for fig1a") from e
+ return plt.imread(f.name)
+
+
# ---------------------------------------------------------------- fig 1: experimental programme
def fig1a():
from matplotlib.patches import FancyBboxPatch
# (name, architecture, guarantee, edge, cell face, header fill, header text colour, icon)
- # Icons: Flaticon #2347052 (green pea, for Mendel) and #10479785 (robot), used under GG's
- # paid Flaticon licence.
+ # Icons: Flaticon #2347052 (green pea, for Mendel) and #10479785 (robot) as committed SVGs,
+ # used under GG's paid Flaticon licence; rasterised at build time by _icon().
TIERS = [
("Biological model", "Wright\u2013Fisher simulator (NumPy)", "closed forms \u00b7 bitwise-reproducible",
- "#4e8d4e", "#eef6ec", "#c5e0bd", "#2d5b2d", "icons/pea.png"),
+ "#4e8d4e", "#eef6ec", "#c5e0bd", "#2d5b2d", "pea.svg"),
("Trained networks", "RNN \u00b7 MLP \u00b7 VAE on a synthetic oracle;\nconvolutional VAE on MNIST",
"sign-level tests \u00b7 exact oracles", "#5b9bc9", "#eff6fb", "#c9e2f2", "#1f4e79",
- "icons/robot.png"),
+ "robot.svg"),
("Language models", "LoRA specialists on Qwen 0.5B & 7B;\nexact-match verifier",
- "seed-replicated signs", "#3c6ea5", "#e7eef8", "#adc8e8", "#1d3f66", "icons/robot.png"),
+ "seed-replicated signs", "#3c6ea5", "#e7eef8", "#adc8e8", "#1d3f66", "robot.svg"),
]
ROWS = [
("Grounding = immigration",
@@ -115,8 +135,8 @@ def fig1a():
linespacing=1.3, color=textcol)
ax.text(xc, 0.833, guarantee, ha="center", va="bottom", fontsize=6.4,
style="italic", color=textcol, alpha=0.85)
- img = plt.imread(str(OUT / icon))
- ax.add_artist(AnnotationBbox(OffsetImage(img, zoom=0.055),
+ img = _icon(icon)
+ ax.add_artist(AnnotationBbox(OffsetImage(img, zoom=28.0 / img.shape[0]),
(x + cw - gap - 0.024, 0.902), frameon=False))
for i2, (label, definition, cells) in enumerate(ROWS):