plot directive#
The plot directive creates mathematical figures directly in MyST / Jupyter Book using a compact key-value syntax. It is designed for textbook-style figures and supports functions, points, labels, polygons, vectors, parametric curves, and a macro system for building repeated structures.
Basic usage#
To plot a function, we can write the following:
:::{plot}
width: 70%
function: (x - 1)**2 - 4, f
:::
which yields the following output:
Syntax overview#
The directive is usually written in MyST form:
:::{plot}
key: value
key: value
Optional caption text.
:::
You can also use classic reStructuredText syntax:
```{eval-rst}
.. plot::
width: 70%
function: sin(x), f
Optional caption text.
```
How front matter works#
Each non-empty line before the first blank line is interpreted as
key: valuefront matter.Repeated keys are allowed for drawing several objects of the same type.
Lines after the first blank line become the figure caption.
Supported keys#
The directive supports repeated drawing keys:
functionpointannotatetextvlinehlinelinetangentpolygonfill-polygonfill-betweenbarvectorline-segmentangle-arccircleellipsecurveaxis
It also supports scalar options such as figure size, axis limits, labels, fonts, caching, and macro definitions.
Global options#
Option |
Meaning |
|---|---|
|
CSS width such as |
|
Matplotlib figure size, e.g. |
|
|
|
Extra CSS classes |
|
Stable output name / figure anchor |
|
Alt text for accessibility |
|
Force regeneration |
|
Keep extra debug output |
|
Force LaTeX text rendering on or off |
|
Use Matplotlib’s XKCD-style rendering |
|
Base font size |
|
Default line width |
|
Default line alpha |
|
Axis limits |
|
Tick spacing |
|
Turn ticks on or off |
|
Turn one axis’ ticks off with |
|
Turn grid on or off |
|
Axis labels, optionally with padding |
|
Draw endpoint markers for functions |
|
Legacy alias for |
Expression support#
Most numeric fields support SymPy expressions. This includes:
arithmetic like
1/3,2*sqrt(5),3*pi/4constants such as
piandEfunctions such as
sqrt,exp,log,sin,cos,tan,asin,acos,atan
For example:
:::{plot}
function: sin(x)
point: (pi/2, 1)
circle: (0, 0), sqrt(2)
line-segment: (0, 0), (2*cos(pi/6), 2*sin(pi/6))
:::
Functions#
Basic function syntax#
You can plot a function with or without a label:
:::{plot}
function: x**2 - 1
function: -x + 2, g
width: 70%
:::
which yields:
Domains and exclusions#
Domains can be open, closed, or mixed, and you can exclude points inside the interval.
:::{plot}
function: 1 / x, f, (-4, 4) \ {0}
xmin: -5
xmax: 5
ymin: -5
ymax: 5
:::
which yields:
Endpoint markers#
Endpoint markers can be enabled with function-endpoints: true.
:::{plot}
function-endpoints: true
function: sqrt(x), f, [0, 4]
function: -sqrt(x), g, (0, 4]
xmin: -1
xmax: 5
ymin: -3
ymax: 3
:::
Tangents#
Tangents can be drawn to labeled functions. The simplest form is:
:::{plot}
function: -x**2 + 4, f
tangent: 1, f, solid, red
point: (1, f(1))
:::
Points, labels, and annotations#
Points#
Points can be given directly, and their coordinates may use function labels such as f(2).
:::{plot}
function: x**2 - 1, f
point: (2, f(2))
point: (-1, 0)
:::
Text labels#
Text labels support positions such as top-left, bottom-center, and center-center. You can also add a bounding box.
:::{plot}
function: (x - 1)**2 - 2
text: 1, -2, "Toppunkt", top-center, bbox
width: 70%
:::
which yields:
Annotations#
Annotations draw an arrow from a text position to a target point.
:::{plot}
function: sin(x)/x, f, (-10, 10) \ {0}
annotate: (4, 2), (pi, f(pi)), "Interessant punkt", 0.2
xmin: -10
xmax: 10
ymin: -1
ymax: 3
:::
Vertical lines, horizontal lines, and straight lines#
Vertical and horizontal lines#
:::{plot}
function: (x - 1) / (x + 2), f
vline: -2, dashed, red
hline: 1, dotted, blue
xmin: -6
xmax: 6
ymin: -6
ymax: 6
:::
General lines#
The line key supports several forms:
line: a, bfory = ax + bline: a, (x0, y0)for a line with slopeathrough(x0, y0)line: (x1, y1), (x2, y2)for a line through two points
:::{plot}
line: 1, -1, dashed, red
line: -1/2, (2, 1), dotted, blue
line: (-2, -1), (3, 2), solid, green
xmin: -4
xmax: 4
ymin: -4
ymax: 4
:::
Line segments#
line-segment draws only the finite segment between two points.
:::{plot}
line-segment: (0, 0), (3, 2), solid, blue
line-segment: (3, 2), (4, 0), dashed, orange
point: (0, 0)
point: (3, 2)
point: (4, 0)
xmin: -1
xmax: 5
ymin: -1
ymax: 3
:::
which yields:
Polygons and filled regions#
Polygons#
polygon draws a polygon outline and can optionally fill it if a color is provided.
:::{plot}
polygon: (0, 0), (2, 0), (1, 1.5), show_vertices, purple, 0.2
xmin: -1
xmax: 3
ymin: -1
ymax: 2
:::
Filled polygons#
fill-polygon fills the polygon interior.
:::{plot}
fill-polygon: (0, 0), (2, 0), (1, 1.5), orange, 0.3
polygon: (0, 0), (2, 0), (1, 1.5), black
xmin: -1
xmax: 3
ymin: -1
ymax: 2
:::
Fill between curves#
fill-between fills the region between two function expressions.
:::{plot}
function: x**2 / 4, f
function: x + 2, g
fill-between: x + 2, x**2 / 4, (-2, 4), blue, 0.2, where=above
xmin: -3
xmax: 5
ymin: -1
ymax: 7
:::
which yields:
Bars, vectors, angle arcs, circles, ellipses, and curves#
Bars#
:::{plot}
bar: (0, 0), 3, horizontal
bar: (4, 0), 2, vertical
xmin: -1
xmax: 6
ymin: -1
ymax: 3
:::
Vectors#
vector supports start-plus-components or start-and-end-point forms.
:::{plot}
vector: 0, 0, 2, 1, teal
vector: (0, 0), (1, 2), orange
xmin: -1
xmax: 3
ymin: -1
ymax: 3
:::
Angle arcs#
:::{plot}
line-segment: (0, 0), (3, 0), solid, black
line-segment: (0, 0), (2, 2), solid, black
angle-arc: (0, 0), 1.2, 0, 45, dashed, red
xmin: -1
xmax: 4
ymin: -1
ymax: 3
:::
Circles, ellipses, and parametric curves#
:::{plot}
circle: (0, 0), 1, fill, blue
ellipse: (3, 0), 1.5, 0.8, dashed, purple
curve: 5 + cos(t), sin(2*t), (0, 2*pi), solid, green
xmin: -2
xmax: 7
ymin: -2
ymax: 2
axis: equal
:::
which yields:
Axes, labels, and layout#
Axis control#
Use axis: off to hide the coordinate system and axis: equal to force equal scaling.
:::{plot}
circle: (0, 0), 1, solid, blue
axis: off
axis: equal
xmin: -2
xmax: 2
ymin: -2
ymax: 2
:::
Ticks and grid#
:::{plot}
function: sin(x)
xmin: -2*pi
xmax: 2*pi
ymin: -2
ymax: 2
xstep: pi/2
grid: true
ticks: true
:::
Axis labels#
You can provide a label alone or a label together with padding.
:::{plot}
function: x**2
xlabel: $x$, 8
ylabel: $y$, 8
width: 70%
:::
Macros and reusable constructions#
The macro system is useful when a figure contains repeated structure.
let#
let defines a constant expression.
:::{plot}
let: a = 2
let: b = 3
point: (a, b)
:::
def#
def defines a helper function. Multi-argument definitions are supported.
:::{plot}
def: px(i, j) = i + j/2
def: py(i, j) = j / 3
point: (px(1, 2), py(1, 2))
xmin: -1
xmax: 3
ymin: -1
ymax: 2
:::
repeat#
repeat expands one line many times, and repeats can be nested.
:::{plot}
def: px(i, j) = i + j/3
def: py(i, j) = j / 4
repeat: i=0..1; repeat: j=0..2; point: (px(i, j), py(i, j))
xmin: -1
xmax: 3
ymin: -1
ymax: 2
:::
macro and use#
Macros let you package several plot lines into one reusable block.
:::{plot}
macro: shortseg(x0, y0, color)
line-segment: (x0, y0), (x0 + 1, y0), solid, color
point: (x0, y0)
endmacro
use: shortseg(0, 0, blue)
use: shortseg(0, 1, red)
xmin: -1
xmax: 2
ymin: -1
ymax: 2
:::
which yields:
Local scope inside macros#
let and def written inside a macro body are local to that macro invocation. They do not leak into the outer scope and do not collide across separate use: calls.
:::{plot}
let: d = 0
macro: scopedseg(i, color)
let: d = i / 10
def: px(x) = x + d
line-segment: (px(0), i / 5), (px(1/5), i / 5), solid, color
endmacro
use: scopedseg(1, #aa0000)
use: scopedseg(2, #00aa00)
line-segment: (d, 0), (d + 0.08, 0), solid, black
xmin: -0.1
xmax: 0.5
ymin: -0.1
ymax: 0.6
axis: off
:::
Complete example#
The following example combines several features in one figure.
:::{plot}
width: 100%
fontsize: 22
function: sin(x)/x, f, (-6*pi, 6*pi) \ {0}
point: (pi, f(pi))
text: pi, f(pi), "$P$", top-right, bbox
annotate: (5, 1.5), (pi, f(pi)), "Merket punkt", 0.15
vline: 0, dotted, gray
hline: 0, dotted, gray
circle: (0, 0), 1, dashed, teal
curve: 3 + cos(t), sin(2*t), (0, 2*pi), solid, orange
xlabel: $x$
ylabel: $y$
xmin: -8
xmax: 8
ymin: -2
ymax: 3
:::
which yields:
Tips#
Prefer labels on important functions if you want to reference them later with
f(2)or use tangents.Use
axis: equalfor circles, ellipses, geometric constructions, and fractal-like figures.Use
nocache:while authoring a figure that changes often.Use
function-endpoints: truewhen the exact endpoint behavior matters pedagogically.Use macros when a figure is structurally repetitive.
Source#
The implementation lives in src/munchboka_edutools/directives/plot.py.