Install
$ agentstack add skill-neuromechanist-research-skills-plot-styling ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Plot Styling
Choose the right Python plotting library for the chart type, then apply journal-quality defaults so the panel that comes out of savefig is ready for the [[scientific-figure]] composer — no manual cleanup, no font-size firefighting, no chart junk.
Two questions, two minutes
- What chart type am I drawing? That answer picks the library (
references/library-decision-tree.md). - Which journal am I targeting? That answer picks the style sheet and font minimum (
references/sciplots-recipes.md).
Run those choices through the export conventions below and the output SVG should pass figure-qa's plot-script branch and feed scientific-figure without scale-down surprises.
Library decision tree (summary)
| Chart type | Library | Why | |---|---|---| | Line / scatter / bar with custom layout | matplotlib | Most control; the lingua franca. Pair with SciencePlots styles to fix defaults. | | Statistical (box, violin, regression, faceted) | seaborn | Better defaults than matplotlib; less code for the common cases. Built on top of matplotlib so the SciencePlots style still applies. | | Grammar-of-graphics / R-style faceting | plotnine | Same geom_* API as ggplot2 without the rpy2 bridge. | | Interactive HTML supplement (deck / dashboard) | plotly | Use plotly for the interactive companion; ship a matplotlib version for print. | | 3D / volumetric / mesh | PyVista (when interactive matters) or matplotlib 3d (for static print) | matplotlib 3d is acceptable for simple panels; PyVista when the figure is the interaction. | | Already in matplotlib, output looks ugly | stay matplotlib + SciencePlots | plt.style.use(['science', 'nature']) fixes 80% of "ugly defaults" complaints without rewriting. |
Full decision tree with concrete code snippets per branch: references/library-decision-tree.md.
Journal-quality defaults (matplotlib / seaborn)
The cleanest path is to install SciencePlots and apply its style sheet at the top of every plot script. The relevant style names:
science— base style (sans-serif, no chart junk, tight margins)nature— Nature column dimensions and font sizingieee— IEEE narrow-column with grayscale-safe palettevibrant/bright/high-contrast— colorblind-safe palettes from Paul Tolnotebook— slightly larger fonts for screen reading (avoid for paper)
import matplotlib.pyplot as plt
import scienceplots # noqa: F401 (registers the styles)
plt.style.use(["science", "nature", "no-latex"])
no-latex is non-optional unless you have system LaTeX installed AND want path-rendered text (in which case validate_fonts.py cannot inspect font sizes — see the "no-latex" note in references/sciplots-recipes.md).
For a Nature panel at 1-column width with three lines:
import numpy as np
import matplotlib.pyplot as plt
import scienceplots # noqa: F401
plt.style.use(["science", "nature", "no-latex"])
fig, ax = plt.subplots(figsize=(3.5, 2.5)) # 89 mm x ~63 mm
t = np.linspace(0, 1, 200)
for k, label in enumerate(("control", "drug A", "drug B")):
ax.plot(t, np.sin(2 * np.pi * (k + 1) * t), label=label, linewidth=1.0)
ax.set_xlabel("time (s)")
ax.set_ylabel("amplitude (a.u.)")
ax.legend(frameon=False, loc="upper right")
fig.savefig("panel_a.svg", bbox_inches="tight", transparent=True)
That single style declaration sets sans-serif fonts at journal-appropriate sizes (Nature 5–7 pt range), removes the right and top spines, applies tight margin defaults, and picks a colorblind-safe palette. See references/sciplots-recipes.md for IEEE, Science, and APS variants.
Export conventions
Every plot panel that will be composed by [[scientific-figure]] should:
- Save as SVG.
savefig("panel.svg", ...). SVG preserves text as `sovalidate_fonts.py` can inspect every label. - Use
transparent=True. The composer expects panels with transparent backgrounds so they composite cleanly onto the figure canvas.figure-qa's plot-script branch flagstransparent=Falseand missing-transparentas issues. - Use
bbox_inches='tight'. Trim whitespace at save time so the panel's bounding box matches its visual extent. The composer'sadd_panel(..., scale=...)math assumes this. - Embed text, not paths. Default matplotlib SVG output embeds text. If you ever set
svg.fonttype = 'path', font validation breaks because there are no `` elements to inspect. - Size the figure in inches to match the final mm panel size. A Nature 1-column panel is 89 mm = ~3.5 in.
figsize=(3.5, ...)produces a panel that the composer can place at scale 1.0 with no font-size shrinkage.
The figure-qa plot-script branch (check_plot_script.py) checks all of these statically from the script's AST. It reports savefig_not_transparent, savefig_missing_bbox_inches, and any rcparam_font_sizes below the journal minimum. See examples/sciplots_panel.py for a script that passes the QA branch cleanly.
When matplotlib defaults bite you
Common matplotlib output failures and the SciencePlots-style fix:
| Failure | Cause | Fix | |---|---|---| | Axis labels are 12pt sans-serif by default — fine on screen, oversized for a Nature panel | matplotlib default font.size is 10 in the source, scaled to 12 at SVG export | Apply plt.style.use(['science', 'nature']) which sets 7 pt body | | Top and right spines visible | matplotlib default | SciencePlots removes them; or manually ax.spines[['top','right']].set_visible(False) | | Legend has a heavy black frame | matplotlib default | ax.legend(frameon=False) | | Tick marks point inward when you wanted outward | SciencePlots science style sets xtick.direction = 'in' (matplotlib's bare default is 'out') | Intentional in the SciencePlots style; override only if your journal requires outward ticks: plt.rcParams['xtick.direction'] = 'out' | | Color cycle uses default tableau colors (not colorblind-safe) | matplotlib default | SciencePlots' bright palette (Paul Tol), or ['#0072B2', '#D55E00', '#009E73', '#CC79A7'] (Okabe-Ito) | | Tick labels render at different sizes than axis labels | matplotlib defaults differ across rcparams | SciencePlots harmonizes; or set xtick.labelsize / ytick.labelsize explicitly | | Saved PNG is at 100 DPI | matplotlib default | savefig(..., dpi=300) for raster output; prefer SVG for print | | Math text uses Computer Modern by default | matplotlib default text.usetex=False, mathtext.fontset='dejavusans' | plt.style.use(['science']) sets serif math via mathtext; or text.usetex=True if you have a LaTeX install |
Quality assurance
After authoring a plot script, run [[figure-qa]]:
uv run python "$FIGURE_QA_SCRIPTS/check_plot_script.py" panel.py --journal nature
The plot-script branch detects the libraries used, reports rcParams font sizes (numeric and dynamic), inspects every savefig call, and offers a library-switch recommendation when the chart type would benefit. After running the script for real and producing the SVG, the raster/SVG branches verify the output too.
Additional resources
references/library-decision-tree.md— full decision tree with concrete snippets per branch (statistical, grammar-of-graphics, interactive, 3D, R-bridge)references/sciplots-recipes.md— Nature, IEEE, Science, APS style recipes; per-journal font and color setupreferences/element-plots.md— original matplotlib / seaborn / plotly / ggplot2 element guide ported from the legacy pluginexamples/matplotlib-element.py— canonical matplotlib panelexamples/sciplots_panel.py— SciencePlots-styled panel passingfigure-qa's plot-script branch
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: neuromechanist
- Source: neuromechanist/research-skills
- License: BSD-3-Clause
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.