Standards (verbatim)¶
These pages are included directly from template/standards/, the same files every
workspace receives, so they are always current.
Plotting standards¶
Apply to every workspace type. standards/teamplot/ is the enforcement; this
page explains the intent. If they disagree, the code wins.
How to plot¶
import sys; sys.path.insert(0, "standards") # run from the workspace root
import teamplot
fig, ax = teamplot.figure("column") # "column" | "margin" | "full"
ax.plot(t, x, label="Measured")
ax.plot(t, x_hat, label="Filtered")
teamplot.label(ax, x="Time", x_unit="s", y="Position", y_unit="m")
teamplot.direct_labels(ax) # instead of a legend
teamplot.save(fig, "position_vs_time", settings={
"Data": "run_2026-10-12.csv",
"Sample rate": "100 Hz",
"Filter": "Kalman, Q = 0.01, R = 0.25",
})
The reproducibility rule¶
Every setting needed to reproduce a plot must appear in its caption, or in a margin note/footnote next to it. That means the data source, sample sizes, sample rates, filter/fit parameters, model choices, random seeds, and any preprocessing (decimation, outlier removal, normalization).
Pass these as
settings=toteamplot.save(). It writesfigures/<name>.settings.jsonandfigures/<name>.settings.tex.LaTeX:
\figsettingsof{<name>}inside the\caption{}(readsfigures/<name>.settings.tex).Notebooks / Markdown: put
teamplot.settings_text(settings)in the caption line directly under the figure.save()warns whensettingsis empty. Treat that warning as an error.
Size: figures are drawn at final size¶
Widths come from
standards/latex/layout.tex, the same file the LaTeX layout uses:"column"= main text width,"margin"= margin figure,"full"= text + margin.In LaTeX, include every figure with
\teamfig{name}(natural size, neverwidth=...). Scaling would break the 10 pt text match.\teamfigonly shrinks a figure if it is wider than the column, which ateamplotfigure never is.Saving uses
bbox="standard"so the file is exactly the requested width. Don’t passbbox_inches="tight".teamplot.save()writes PDF (for LaTeX), PNG (for notebooks/docs) and SVG (editable text, for human annotation).
Diagrams: Mermaid¶
Write diagrams as Mermaid source in
diagrams/<name>.mmd, then runpython scripts/render_diagrams.py→figures/<name>.{svg,pdf,png}.The shared style (
standards/mermaid/) sets Nimbus Sans 10 pt, thin gray strokes, no shadows, and real SVG text (no HTML labels) so humans can edit the SVG.Mark the one element the reader should notice with
class <node> accent. Don’t set colors or styles inline in the.mmd.Prefer
flowchart TB(top-to-bottom) so diagrams fit the column at natural size; useLRonly for short chains orfigure*(full width).Keep diagrams small: one idea per diagram, ≤ ~10 nodes, short labels.
If Mermaid can’t express a layout well, say so in TASK.md → Handoff rather than fighting it; a human may switch that diagram to Graphviz or annotate it by hand.
Diagrams are included and annotated exactly like plots (below).
Human annotations (figures/annotated/)¶
Generated figures can be improved by hand without giving up regeneration:
A human copies
figures/<name>.svgtofigures/annotated/<name>.svg, adds arrows, callouts, or labels in Inkscape, and exportsannotated/<name>.pdf(andannotated/<name>.pngfor notebooks/docs).\teamfig{name}(LaTeX) andteamplot.figure_path(name)(Python) automatically prefer the annotated version.If a figure is regenerated after it was annotated (its PNG is more than an hour newer than the annotated SVG), LaTeX logs a warning and prints a red “Annotation may be stale” note under the figure;
python scripts/check_figures.pyreports the same. It also flags an annotated SVG that was edited but not re-exported.
Agents: never create, edit, or delete anything in figures/annotated/. If
regenerating a figure makes an annotation stale, say so in TASK.md → Handoff and
let a human update it. Don’t regenerate an annotated figure unless the task needs it.
Style (Tufte: maximize data ink)¶
Style comes from
standards/teamplot/matplotlibrc. Don’t set rcParams or callplt.style.useyourself.No top or right spines; left/bottom spines offset outward; no grid.
Consider
teamplot.rangeframe(ax)so axes span only the data range.No titles inside the figure; the caption carries the message.
Label lines directly (
teamplot.direct_labels) rather than with a legend whenever there are ≤ 4 series.Use the color cycle in order: near-black first, then muted accents. Avoid ad-hoc colors, 3-D effects, shadows, and decorative fills.
x/y/z data always uses
tab:redfor x,tab:greenfor y,tab:bluefor z (teamplot.XYZ_COLORS, orteamplot.xyz_color("x")). This applies to any vector components: position, velocity, acceleration, angular rate, magnetic field, axes of a coordinate frame. It overrides the color cycle so components read the same in every figure.Every axis has a label with units in brackets,
Time [s](teamplot.label).Show uncertainty (error bars or light shaded bands) whenever it’s known.
Filenames: lowercase snake_case describing the content (
bias_vs_temperature).
Typography¶
Element |
Font |
Size |
|---|---|---|
Body text (LaTeX) |
Pagella (Palatino) + newpxmath |
10 pt (tufte-latex native) |
Sidenotes, margin notes |
Pagella |
8 pt (tufte default) |
Captions |
Nimbus Sans |
10 pt |
All text inside plots, incl. math |
Nimbus Sans |
10 pt |
Nimbus Sans must be installed for matplotlib to use it (see README → Fonts);
teamplot warns if it’s missing.
Writing standards¶
Applies to notebook markdown, docs, and papers. Replace with your team’s conventions.
Lead with the answer or finding, then the supporting detail.
Active voice; define every acronym on first use.
Numbers carry units and a sensible number of significant figures.
Every figure is referenced in the text and has a caption that states what to notice and lists the settings that produced it (see
plotting.md).In LaTeX, use sidenotes (
\sidenote{}) for asides and citations, and margin notes (\marginnote{}) for unnumbered remarks. Keep the main text column for the argument.Citations render as margin sidenotes, so put
\cite{}after the punctuation that ends the clause (…prior work.\cite{key}), never as a noun in the sentence (“see~\cite{key}”).Don’t claim more than the data shows; state assumptions and limitations explicitly.
Cite sources (Confluence page titles, papers, ticket keys); never invent a citation.
Mark anything unresolved as an open question rather than guessing.