Figures
A figure in a paper is an argument, not a screenshot of an array. It makes one claim, and a
reader who skips the prose should still get that claim right. Default plotting output does
not clear that bar: it is sized for a screen, titled where a caption belongs, colored from
a cycle that collapses in greyscale, and rasterized where the document wants vector.
Non-negotiables
- Build at the final printed size. Pick the width from the document (
COLUMN 3.25 in,
TEXT 5.5 in, WIDE 6.75 in in the style module) and include it with
width=\linewidth. Never build big and rescale: a 15-inch canvas dropped into a
5.5-inch column turns 11 pt tick labels into 4 pt.
- Vector out. PDF for
\includegraphics, SVG beside it for preview. A rasterized plot
blurs under the zoom every reviewer uses. PNG is only for genuinely raster content: a
photograph, a sample grid, an attention map at pixel resolution.
- Every number comes from a run. Read tracked metrics with the experiments tool
(
experiments series, experiments compare) or from the run's own output files. Never
plot a remembered, rounded or plausible number, and never leave demo data in a script
that ships.
- The caption is the title. No axes title on a paper figure; panel letters (a,
b) name the parts of a multi-panel figure.
- Show the uncertainty, or say there is none. One seed is an anecdote. Plot the
interval across seeds and state the seed count in the caption; with one run, write
"single seed".
- Label axes with units. "Loss" is a label; "step" without saying whether it counts
optimizer steps or tokens is not.
- Colorblind-safe, greyscale-safe. Use the module's Okabe-Ito palette. Never
jet,
rainbow or hsv; they invent structure the data does not have. Baselines and chance
levels are grey: color belongs to the things being compared.
- One sans-serif face across every figure, diagrams included.
use_style() sets it.
Pass use_style(family="serif") only for a figure carrying heavy math on a serif page.
Set up once per project
Copy the style module beside the figure scripts so a figure stays reproducible after this
session ends. The module lives in this skill's directory at assets/figstyle.py; read it
and write it to figs/figstyle.py in the working folder (do not import it from the skill
path, which is not part of the project).
from figstyle import COLUMN, PALETTE, figure, save, use_style
use_style()
fig, ax = figure(width=COLUMN)
ax.plot(x, y, color=PALETTE["blue"])
save(fig, "figs/loss_curve") # writes .pdf and .svg, prints an audit line
Plots that only need matplotlib and numpy run in the session's Python; plots that import
project code run in the project environment. Keep the script beside its output
(figs/loss_curve.py next to figs/loss_curve.pdf); a figure whose script is gone cannot
be corrected when a reviewer asks for one more seed.
Where the figure goes
Write the figure and its script into the working folder, under figs/ beside the .tex
for a paper, or under the report's own folder otherwise. Never write a figure you intend to
show into a temporary directory; link the saved path in the answer.
\begin{figure}[t] % figure* for a WIDE figure in a two-column paper
\centering
\includegraphics[width=\linewidth]{figs/loss_curve.pdf}
\caption{\textbf{LPO reaches the reward plateau in a third of the compute.}
Held-out reward against training compute for LPO and two baselines; mean of 5 seeds,
bands are 95\% intervals. The dotted line is the pretrained model.}
\label{fig:loss}
\end{figure}
Write the caption with the figure
Captions in current papers run about 28 words, often three sentences: a short bold phrase
naming the claim, then the detail a reader needs to trust it.
- Lead with the finding, not the setup. "Training curves for LPO and baselines" names the
axes, which the axes already do.
- The figure must stand alone; a reader who skipped the section should still get the claim.
- Put the method facts here: seed count, what the band or bar means, smoothing,
normalization, which points were fitted and which excluded, whether a frontier line is
measured or a guide.
- Say what is not shown when it matters: a single seed, a truncated axis, a run cut short.
- Do not restate axis labels in prose.
Multi-panel figures
- Label every panel
(a), (b), ... at the top-left with panel_labels().
- Share the axis when panels share a quantity (
sharey=True); two panels of one metric on
silently different ranges is the multi-panel version of a truncated bar axis.
- One legend for the figure, not one per panel.
- Panels read in argument order, left to right, top to bottom.
- If the panels do not support one claim, they are separate figures.
Build them with figure_grid(nrows, ncols, width=TEXT, sharey=True).
Read exactly one reference
Pick by the question the figure answers, not by the shape in mind.
| The figure answers |
Read |
| How does a metric move over training, and is the gap bigger than seed noise? |
references/curves.md |
| How does performance change with scale, and what does the trend predict? |
references/scaling.md |
| Which method wins across benchmarks, or which ablated component mattered? |
references/comparison.md |
| What is traded off against what: reward vs KL, quality vs cost or latency? |
references/pareto.md |
| What does this 2D grid, confusion matrix or sweep look like? |
references/matrix.md |
For a method, architecture or pipeline diagram, load the schematics skill instead; a TikZ
scaffold that matches this palette is in assets/tikz-preamble.tex for the cases where an
editable vector diagram is the right medium.
Before you hand it over
- Read the audit line
save() prints. It checks the printed width, font embedding, stray
axes titles, missing axis labels, text under 5 pt, overlapping text and text off the
canvas. clean is the bar; anything else is a defect to fix, not a warning to note.
- If the audit reports no publication font on the machine, say so rather than installing
fonts; that changes the environment and needs the user's say.
- A label placed at a reference line or data point is the usual overlap; move it or give
it
backgroundcolor="white".
- Open the PDF and read it at printed size. A tick label unreadable on screen at 100% is
unreadable on paper.
- Every axis labelled with units; no stray title; uncertainty shown with n stated; no legend
entry for a series that was cut; the script reruns from scratch and reproduces the file.
1---2name: figures3description: Makes publication-quality plots from data with matplotlib or TikZ, learning curves, scaling laws, benchmark and ablation comparisons, Pareto trade-offs, heatmaps and confusion matrices, sized for the page, vector, with uncertainty shown. Use whenever results are plotted, charted or visualized for a paper, report or answer, or an existing plot looks unpolished. Not for conceptual diagrams or schematics (use schematics) and never for drawing numbers that did not come from a run.4license: MIT5---67# Figures89A figure in a paper is an argument, not a screenshot of an array. It makes one claim, and a10reader who skips the prose should still get that claim right. Default plotting output does11not clear that bar: it is sized for a screen, titled where a caption belongs, colored from12a cycle that collapses in greyscale, and rasterized where the document wants vector.1314## Non-negotiables15161. **Build at the final printed size.** Pick the width from the document (`COLUMN` 3.25 in,17 `TEXT` 5.5 in, `WIDE` 6.75 in in the style module) and include it with18 `width=\linewidth`. Never build big and rescale: a 15-inch canvas dropped into a19 5.5-inch column turns 11 pt tick labels into 4 pt.202. **Vector out.** PDF for `\includegraphics`, SVG beside it for preview. A rasterized plot21 blurs under the zoom every reviewer uses. PNG is only for genuinely raster content: a22 photograph, a sample grid, an attention map at pixel resolution.233. **Every number comes from a run.** Read tracked metrics with the experiments tool24 (`experiments series`, `experiments compare`) or from the run's own output files. Never25 plot a remembered, rounded or plausible number, and never leave demo data in a script26 that ships.274. **The caption is the title.** No axes title on a paper figure; panel letters (**a**,28 **b**) name the parts of a multi-panel figure.295. **Show the uncertainty, or say there is none.** One seed is an anecdote. Plot the30 interval across seeds and state the seed count in the caption; with one run, write31 "single seed".326. **Label axes with units.** "Loss" is a label; "step" without saying whether it counts33 optimizer steps or tokens is not.347. **Colorblind-safe, greyscale-safe.** Use the module's Okabe-Ito palette. Never `jet`,35 `rainbow` or `hsv`; they invent structure the data does not have. Baselines and chance36 levels are grey: color belongs to the things being compared.378. **One sans-serif face across every figure**, diagrams included. `use_style()` sets it.38 Pass `use_style(family="serif")` only for a figure carrying heavy math on a serif page.3940## Set up once per project4142Copy the style module beside the figure scripts so a figure stays reproducible after this43session ends. The module lives in this skill's directory at `assets/figstyle.py`; read it44and write it to `figs/figstyle.py` in the working folder (do not import it from the skill45path, which is not part of the project).4647```python48from figstyle import COLUMN, PALETTE, figure, save, use_style4950use_style()51fig, ax = figure(width=COLUMN)52ax.plot(x, y, color=PALETTE["blue"])53save(fig, "figs/loss_curve") # writes .pdf and .svg, prints an audit line54```5556Plots that only need matplotlib and numpy run in the session's Python; plots that import57project code run in the project environment. Keep the script beside its output58(`figs/loss_curve.py` next to `figs/loss_curve.pdf`); a figure whose script is gone cannot59be corrected when a reviewer asks for one more seed.6061## Where the figure goes6263Write the figure and its script into the working folder, under `figs/` beside the `.tex`64for a paper, or under the report's own folder otherwise. Never write a figure you intend to65show into a temporary directory; link the saved path in the answer.6667```latex68\begin{figure}[t] % figure* for a WIDE figure in a two-column paper69 \centering70 \includegraphics[width=\linewidth]{figs/loss_curve.pdf}71 \caption{\textbf{LPO reaches the reward plateau in a third of the compute.}72 Held-out reward against training compute for LPO and two baselines; mean of 5 seeds,73 bands are 95\% intervals. The dotted line is the pretrained model.}74 \label{fig:loss}75\end{figure}76```7778## Write the caption with the figure7980Captions in current papers run about 28 words, often three sentences: a short bold phrase81naming the claim, then the detail a reader needs to trust it.8283- Lead with the finding, not the setup. "Training curves for LPO and baselines" names the84 axes, which the axes already do.85- The figure must stand alone; a reader who skipped the section should still get the claim.86- Put the method facts here: seed count, what the band or bar means, smoothing,87 normalization, which points were fitted and which excluded, whether a frontier line is88 measured or a guide.89- Say what is not shown when it matters: a single seed, a truncated axis, a run cut short.90- Do not restate axis labels in prose.9192## Multi-panel figures9394- Label every panel `(a)`, `(b)`, ... at the top-left with `panel_labels()`.95- Share the axis when panels share a quantity (`sharey=True`); two panels of one metric on96 silently different ranges is the multi-panel version of a truncated bar axis.97- One legend for the figure, not one per panel.98- Panels read in argument order, left to right, top to bottom.99- If the panels do not support one claim, they are separate figures.100101Build them with `figure_grid(nrows, ncols, width=TEXT, sharey=True)`.102103## Read exactly one reference104105Pick by the question the figure answers, not by the shape in mind.106107| The figure answers | Read |108| --- | --- |109| How does a metric move over training, and is the gap bigger than seed noise? | `references/curves.md` |110| How does performance change with scale, and what does the trend predict? | `references/scaling.md` |111| Which method wins across benchmarks, or which ablated component mattered? | `references/comparison.md` |112| What is traded off against what: reward vs KL, quality vs cost or latency? | `references/pareto.md` |113| What does this 2D grid, confusion matrix or sweep look like? | `references/matrix.md` |114115For a method, architecture or pipeline diagram, load the schematics skill instead; a TikZ116scaffold that matches this palette is in `assets/tikz-preamble.tex` for the cases where an117editable vector diagram is the right medium.118119## Before you hand it over120121- Read the audit line `save()` prints. It checks the printed width, font embedding, stray122 axes titles, missing axis labels, text under 5 pt, overlapping text and text off the123 canvas. `clean` is the bar; anything else is a defect to fix, not a warning to note.124- If the audit reports no publication font on the machine, say so rather than installing125 fonts; that changes the environment and needs the user's say.126- A label placed at a reference line or data point is the usual overlap; move it or give127 it `backgroundcolor="white"`.128- Open the PDF and read it at printed size. A tick label unreadable on screen at 100% is129 unreadable on paper.130- Every axis labelled with units; no stray title; uncertainty shown with n stated; no legend131 entry for a series that was cut; the script reruns from scratch and reproduces the file.