# Figure design standards (Nature submission, 2026-05-02)

These standards apply to every figure in the submission bundle. They are operationalised by `figure_regen_2026-05-02/_style.py` (shared module that every regen script imports).

## Hard requirements (no exceptions)

1. **Real data only.** No `np.random.normal`, `rng.uniform`, `rng.choice`, `rng.integers`, or `np.random.*` outside null-model construction (where the input series is real and the rng is producing IAAFT / permutation surrogates from that real series). Every script must begin with `pd.read_csv(...)` or `np.load(...)` against a real-data file present in `04_supplementary_data/`.

2. **Caption-number reproducibility.** Every quantitative claim in a caption must be reproducible by re-running the regen script. The script's verify-print block must show real-vs-claimed value side by side for every caption number. Where the manuscript caption number doesn't reproduce, the figure shows the real-data-derived value and the discrepancy is logged in `FIGURE_PROVENANCE.md`.

3. **Single set of outer panel letters.** Lowercase bold `a/b/c/...` placed top-left of each axis via `panel_letter(fig, ax, 'a')` from `_style.py`. No inner `A.` / `B.` titles. No double-letter doubling.

4. **Vector SVG, not wrapped PNG.** Every SVG must be matplotlib's native vector output (`<text>` and `<path>` nodes, no `data:image/png;base64` embeds). The `savefig_both()` helper writes both PNG (300 dpi) and SVG (vector) from the same matplotlib `Figure` object.

5. **Draft-then-promote workflow.** Run script → `savefig_both()` writes to `_drafts/`. Inspect rendered PNG. Iterate. Only `PROMOTE=1 python script.py` writes to canonical `02_figures/` paths. This was the corner I cut on the first ED Fig 11 attempt; the rule is now absolute.

## Visual hierarchy

| Element | Spec |
|---|---|
| Figure title (panel action title) | 10 pt bold, `loc='left'`, `pad=8`. Action titles state the FINDING ("Period lengthens 2.7× over differentiation") not the variable ("Per-day period bar chart"). |
| Panel letter | 12 pt bold lowercase, top-left of axis bbox via `fig.text` in `ScaledTranslation(-0.10, +0.04, fig.dpi_scale_trans)`. |
| Axis label | 9 pt regular |
| Tick labels | 8 pt regular |
| Legend | 8–8.5 pt, frame `framealpha=0.92`. Place in lowest-density region of the data. Never let the legend overlap data. |
| In-panel annotation boxes | 7.5–8 pt, white box `boxstyle='round,pad=0.3'`, `edgecolor='0.7'`, `lw=0.4`. |
| Value annotations on bars | 7.5–8.5 pt bold, placed above bar tops with consistent offset (~3% of axis range). |

## Colour vocabulary (Wong palette, semantic)

| Concept | Colour | Hex | Wong label |
|---|---|---|---|
| A / active / interior / speckle / G2 | blue | `#0072B2` | blue |
| B / repressive / periphery / lamina / Prophase | vermilion | `#D55E00` | vermil |
| Null / control / not-significant | grey | `#7F7F7F` | grey |
| Key finding / hero | gold | `#B8860B` | gold |
| Secondary blue / sky | sky | `#56B4E9` | sky |
| Supporting / OK / null-passing | green | `#009E73` | green |
| Accent / warm / mid-spectrum | orange | `#E69F00` | orange |
| Pink / contrast | pink | `#CC79A7` | pink |

## Layout principles

- **Hero panel = ~50% of figure area** when one panel carries the headline finding. Wide panel a in ED Fig 11 (mitotic collapse trajectory across 24 chromosomes); wide panel a in ED Fig 7 (240+60 sorted neurons); polar panel a in Main Fig 3 (TSA-seq octant means).
- **Aspect ratio**: figure width 10–14 inches; height set so each panel reads cleanly without overlap. For multi-panel main figures, use `gridspec` with explicit `width_ratios` and `height_ratios` rather than letting `subplots()` choose.
- **Inter-panel spacing**: `wspace ≥ 0.35`, `hspace ≥ 0.45` for figures with multi-line titles. Tighten only after visual verification at final dpi.
- **Margins**: `left=0.06, right=0.985, top=0.93, bottom=0.075` is the Nature-column-width starting point. Adjust `top` if action titles wrap.
- **No panel borders, no gridlines** (unless on log axes where grid aids reading). `axes.spines.top` and `axes.spines.right` always off.

## Data density

- **Show every chromosome, every cell, every donor** when the data permits — never aggregate when the per-unit picture tells a stronger story. Per-cell scatter > pooled box; per-chromosome bar > median table; per-donor strip > meta-analytic summary.
- **Always plot the null** alongside the observed for any test where a null exists (IAAFT surrogate distribution, permutation null, sin(θ)/2 random-3D null for MERFISH, AR(1) red-noise null for CWT).
- **Error bars or CI bands always visible** where uncertainty matters. Bootstrap SE as black error bars over coloured bars. Confidence intervals as semi-transparent shaded bands.

## Honesty rules

- **Negative results report honestly.** When a per-pair test fails (chr3, chr15 in ED Fig 3 panel d), they are coloured vermilion and labelled. Don't drop them.
- **Caption numbers update if real data disagrees.** ED Fig 1 (5-chromosome scope honestly reported), ED Fig 3 (pipeline-update note), Supp Fig 1 (4.5° → 0.4°), Main Fig 3 (47/50 → 91 sig+ vs 30 sig−), Supp Fig 6 (condA → condB column correction).
- **Pipeline differences disclosed.** When a number comes from an older pipeline (200-surrogate IAAFT vs 1000-surrogate), the caption notes which pipeline produced which number.
- **Manuscript-caption-vs-figure-data discrepancies flagged in `FIGURE_PROVENANCE.md`** with the specific line numbers in the .tex and the resolution path.

## Reviewer-rerun standard

A reviewer with the bundle alone must be able to:
1. `cd 05_code/figure_regen/`
2. `pip install -r requirements.txt`
3. `python <figure_script>.py`
4. Reproduce the figure to within rendering precision against the canonical PNG.
5. Reproduce every quantitative caption claim from the script's verify-print output.

This is the falsifiability gate. If any figure fails this test in the assembled bundle, it is removed from the bundle until fixed.

## Excluded pre-2026-05-02 patterns (now forbidden)

- `figure_regen_v73/scripts/` synthetic-placeholder pattern (rng-seed-baked numbers): forbidden in canonical figures. Used only for very early draft visualisation; the current bundle ships the regenerated real-data versions.
- Wrap-PNG-as-SVG (the Main Fig 4 stopgap): forbidden as canonical; replaced by vector regen in next bundle iteration.
- Inner `A.` / `B.` panel-subtitle prefixes inside `ax.set_title(...)` overlapping with outer panel letters: forbidden; one set of panel letters only, via `panel_letter()`.
- Caption claims that don't reproduce from real data: forbidden; either (a) re-derive from real data and update caption, or (b) remove the claim. Never bake a synthetic number to match a manuscript claim.

— *Drafted 2026-05-02 in the rebuild that produced 11 real-data regens (Main Fig 3, ED Fig 1, ED Fig 2, ED Fig 3, ED Fig 6, ED Fig 7, ED Fig 11, Supp Fig 1, Supp Fig 6, Supp Fig 14, Supp Fig 19) and batch-verified the remaining 49 figures in the v95 bundle.*
