| name | nature-figure |
| description | Nature-style publication figure generator. matplotlib + SVG-first vector output, semantic color contract (red=warning only, blue=primary/baseline only), colorblind-safe palettes, multi-panel grids with shared legends, mandatory error bars. Use when the user asks to make a journal-grade figure, plot results for a paper, or build a multi-panel comparison. |
nature-figure
Generates publication-grade figures that satisfy Nature-family house style without
the author having to remember every rule. Powered by
mcp-servers/pipeline-orchestrator/figure_engine.py.
When to invoke
- "make this plot Nature-ready" / "draw the figure for the paper"
- "two-panel comparison of Ours vs Baseline"
- experiment-runner asks for a result figure
- paper-writing reaches the Figures step in paper-writing/SKILL.md
Core contract (enforced, not advisory)
| Rule | Mechanism |
|---|
| SVG vector output by default | render_*() reads suffix; defaults to svg. Falls back to pdf / png only on explicit request. |
| Semantic colors | semantic_role='primary' / 'baseline' are pinned blue; 'warning' is the only role that yields red. Free-form red on a non-warning series produces a semantic_color_misuse violation. |
| Colorblind-safe categorical | Default palette okabe_ito; alternatives tol_bright, tol_muted. Sequential = viridis / cividis. |
| Sans-serif typography | rcParams pinned to Arial fallback chain; SVG fonts kept as text (svg.fonttype=none). |
| Minimum font sizes | tick ≥ 6 pt, axis label ≥ 7 pt — clamped in _apply_axis_style. |
| Error bars mandatory | Series without yerr AND without error_bar_disabled_reason produces an error violation. With a written reason: warning only. |
| Auto log/linear axis | Positive x or y spanning ≥ 2 decades → set_xscale('log') / set_yscale('log'). Override via log_x / log_y. |
| Column widths | NATURE_SINGLE_COL_MM = 89, NATURE_DOUBLE_COL_MM = 183 (Nature standard). |
Every render_*() returns a FigureRenderResult.violations list. A non-empty
level='error' entry must block QG5 publication standards.
Three standard figure kinds
from figure_engine import (
FigureSpec, GridSpec, PanelSpec, SeriesSpec,
render_line, render_bar, render_grid,
)
1. Single-panel line plot
spec = FigureSpec(
xlabel="Training step", ylabel="Validation accuracy",
series=[
SeriesSpec("Ours", x=[1,2,4,8,16], y=[.62,.71,.78,.83,.85],
yerr=[.02,.02,.015,.012,.010], semantic_role="primary"),
SeriesSpec("Baseline", x=[1,2,4,8,16], y=[.55,.60,.66,.70,.72],
yerr=[.025,.022,.018,.015,.014], semantic_role="baseline"),
],
)
render_line(spec, "figures/fig1.svg")
2. Grouped bar comparison
spec = FigureSpec(
xlabel="Model", ylabel="F1",
series=[
SeriesSpec("Ours", x=["A","B","C"], y=[.81,.79,.84],
yerr=[.01,.01,.012], semantic_role="primary"),
SeriesSpec("Baseline", x=["A","B","C"], y=[.74,.72,.78],
yerr=[.015,.014,.013], semantic_role="baseline"),
],
)
render_bar(spec, "figures/fig2.svg")
3. 2x2 multi-panel grid
See templates/figure_grid.py.
Templates
Failure modes & recovery
| Symptom | Cause | Fix |
|---|
missing_error_bar (error) | Series has neither yerr nor reason | Compute std across seeds (multi-seed runs are mandatory in QG4) or set error_bar_disabled_reason="..." if genuinely deterministic. |
semantic_color_misuse (warning) | Red used on a non-warning role | Switch to semantic_role='primary' (blue) for proposed methods; reserve red for failure cases. |
bar_category_mismatch (error) | Bar series have different x categories | Re-align inputs — grouped bars require shared x. |
Integration points
- paper-writing: Step "Figure Generation" (appended section) calls into this skill.
- experiment-runner: post-run, when
result_summary.json is available, this skill turns it into Fig 1 / Fig 2 candidates.
- QG5 publication standards: surfaces
violations list as part of the 14-item check.
Non-goals
- Not a general charting library — three kinds (line / bar / grid) only, by design.
- Not a layout designer — no Illustrator-style absolute positioning.
- Does not write metadata into evidence_graph.json (the calling skill owns that).