Skip to content

Commit

Permalink
manual: Improve plot documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
johannes-wolf committed Nov 22, 2023
1 parent 2a24265 commit 5141069
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 99 deletions.
24 changes: 9 additions & 15 deletions manual.typ
Original file line number Diff line number Diff line change
Expand Up @@ -486,15 +486,6 @@ current node, all following items are direct children of that node.
The node itselfes can be of type `content` or `dictionary` with a key `content`.

== Plot
#let plot-module = tidy.parse-module(read("src/lib/plot.typ"), name: "Plot")
#let plot-module-line = tidy.parse-module(read("src/lib/plot/line.typ"),
name: "Plot - Line")
#let plot-module-contour = tidy.parse-module(read("src/lib/plot/contour.typ"),
name: "Plot - Contour")
#let plot-module-boxwhisker = tidy.parse-module(read("src/lib/plot/boxwhisker.typ"),
name: "Plot - Boxwhisker")
#let plot-module-sample = tidy.parse-module(read("src/lib/plot/sample.typ"),
name: "Plot - Sample")

The library `plot` of CeTZ allows plotting 2D data.

Expand All @@ -504,12 +495,15 @@ Types commonly used by function of the `plot` library:
/ `domain`: Tuple representing a functions domain as closed interval.
Example domains are: `(0, 1)` for $[0, 1]$ or
`(-calc.pi, calc.pi)` for $[-pi, pi]$.

#tidy.show-module(plot-module, show-module-name: false)
#tidy.show-module(plot-module-line, show-module-name: false)
#tidy.show-module(plot-module-contour, show-module-name: false)
#tidy.show-module(plot-module-boxwhisker, show-module-name: false)
#tidy.show-module(plot-module-sample, show-module-name: false)
/ `axes`: Tuple of axis names. Plotting functions taking an `axes` tuple
will use those axes as their `x` and `y` axis for plotting.
To rotate a plot, you can simply swap its axes, for example `("y", "x")`.

#doc-style.parse-show-module("/src/lib/plot.typ")
#doc-style.parse-show-module("/src/lib/plot/line.typ")
#doc-style.parse-show-module("/src/lib/plot/contour.typ")
#doc-style.parse-show-module("/src/lib/plot/boxwhisker.typ")
#doc-style.parse-show-module("/src/lib/plot/sample.typ")

=== Examples

Expand Down
217 changes: 135 additions & 82 deletions src/lib/plot.typ
Original file line number Diff line number Diff line change
Expand Up @@ -27,102 +27,122 @@
return default-plot-style(i)
}

/// Add an anchor to a plot environment
///
/// - name (string): Anchor name
/// - position (array): Tuple of x and y values.
/// Both values can have the special values "min" and
/// "max", which resolve to the axis min/max value.
/// Position is in axis space!
/// - axes (array): Name of the axes to use ("x", "y"), note that both
/// axes must exist!
#let add-anchor(name, position, axes: ("x", "y")) = {
((
type: "anchor",
name: name,
position: position,
axes: axes,
),)
}

/// Create a plot environment
///
/// Note: Data for plotting must be passed via `plot.add(..)`
/// Note: Data for plotting must be passed via `plot.add(..)` or other
/// plotting functions.
///
/// #example(```
/// import cetz.plot
/// plot.plot(x-tick-step: none, y-tick-step: none, {
/// plot.add(((0,0), (1,1), (2,.5), (4,3)))
/// })
/// ```)
///
/// Note that different axis-styles can show different axes.
/// Different axis-styles can show different axes.
/// The `"school-book"` and `"left"` style shows only axis "x" and "y",
/// while the `"scientific"` style can show "x2" and "y2", if set
/// (if unset, "x2" mirrors "x" and "y2" mirrors "y"). Other
/// axes (e.G. "my-axis") work, but no ticks or labels will be shown.
/// (if unset, "x2" mirrors "x" and "y2" mirrors "y"). You can use
/// any axis name and as many axes as you want for plotting data, but only
/// the predefined axes (`x`, `y`, `x2`, `y2`) are displayd with ticks.
///
/// *Options*
/// *Options* <plot-axis-options>
///
/// The following options are supported per axis
/// and must be prefixed by `<axis-name>-`, e.G.
/// `x-min: 0` or `y-label: [y]`.
/// #box[
/// - label (content): Axis label
/// - min (int): Axis minimum value
/// - max (int): Axis maximum value
/// - tick-step (none, float): Distance between major ticks (or no ticks if none)
/// - minor-tick-step (none, float): Distance between minor ticks (or no ticks if none)
/// - ticks (array): List of ticks values or value/label
/// tuples. Example `(1,2,3)` or `((1, [A]), (2, [B]),)`
/// - format (string): Tick label format, `"float"`, `"sci"` (scientific)
/// or a custom function that receives a value and
/// returns a content (`value => content`).
/// - grid (bool,string): Enable grid-lines at tick values:
/// - `"major"`: Enable major tick grid
/// - `"minor"`: Enable minor tick grid
/// - `"both"`: Enable major & minor tick grid
/// - `false`: Disable grid
/// - unit (none, content): Tick label suffix
/// - decimals (int): Number of decimals digits to display for tick labels
/// ]
/// The following options are supported per axis and must be prefixed
/// by an axis name: `<<axis-name>-<option>>`, e.G. `x-min: 0` or `y-label: [y]`.
/// #show-parameter-block("label", ("none", "content"), default: "none", [
/// The axis' label. If and where the label is drawn depends on the `axis-style`.])
/// #show-parameter-block("min", ("auto", "float"), default: "auto", [
/// Axis lower domain value. If this is set > than `max`, the axis' direction is swapped])
/// #show-parameter-block("max", ("auto", "float"), default: "auto", [
/// Axis upper domain value. If this is set < than `min`, the axis' direction is swapped])
/// #show-parameter-block("tick-step", ("none", "auto", "float"), default: "auto", [
/// Increment between tick marks on the axis, starting at $0$. If set to `auto`,
/// a matching increment is calculated. When set to `none`, tick marks are disabled.])
/// #show-parameter-block("minor-tick-step", ("none", "auto", "float"), default: "none", [
/// Like `tick-step`, but for minor tick marks.])
/// #show-parameter-block("ticks", ("none", "array"), default: "none", [
/// List o custom tick marks in addition to those generated by `tick-step` and `minor-tick-step`.
/// This argument supports an array of `float` on where to place marks, or an
/// array of `(<float>, <content>)` tuples, for setting custom tick mark labels per mark.
/// Examples: `(1, 2, 3)` or `((1, [One]), (2, [Two]), (3, [Three]))`])
/// #show-parameter-block("format", ("none", "string", "function"), default: "float", [
/// Specifies the tick label formatting or a custom formatter function. The following
/// predefined formats are supported:
/// / `"float"`: Floating point formatting rounded to two digits after the point (see `decimals`)
/// / `"sci"`: Scientific formatting with $times 10^n$ used as expoent syntax
/// / `number => content`: A function that takes a number and returns content that gets uesd
/// as tick label
/// ])
/// #show-parameter-block("decimals", ("int"), default: "2", [
/// Number of decimals digits to display for tick labels, if the format is set
/// to `"float"`.
/// ])
/// #show-parameter-block("unit", ("none", "content"), default: "none", [
/// Suffix to append to all tick labels.
/// ])
/// #show-parameter-block("grid", ("bool", "string"), default: "false", [
/// If `true` or `"major"`, show grid lines for all major ticks. If set
/// to `"minor"`, show grid lines for minor ticks only.
/// The value `"both"` enables grid lines for both, major- and minor ticks.
/// ])
/// #show-parameter-block("equal", ("string"), default: "none", [
/// Set the axis aspect ratio to be fixed to the aspect ratio of the given axis.
/// This can be useful to force one axis to grow or shrink with another one.
/// You can only "lock" two axes of different orientation (`horizontal`).
/// ])
/// #show-parameter-block("horizontal", ("bool"), default: "auto", [
/// If true, values on this axis are drawn horizontally, otherwise vaules
/// get drawn vertically.
/// ])
///
/// - body (body): Calls of `plot.add` or `plot.add-*` commands
/// - size (array): Plot canvas size tuple of width and height in canvas units
/// - body (body): Calls of `plot.add` or `plot.add-*` commands. Note that normal drawing
/// commands like `line` or `rect` are not allowed insides the plots body!
/// - size (array): Plot size tuple of `(<width>, <height>)` in canvas units.
/// This is the plots inner plotting size without axes and labels.
/// - axis-style (none, string): Axis style "scientific", "left", "school-book"
/// - `"scientific"`: Frame plot area and draw axes y, x, y2, and x2 around it
/// - `"school-book"`: Draw axes x and y as arrows with both crossing at $(0, 0)$
/// - `"left"`: Draw axes x and y as arrows, the y axis stays on the left (at `x.min`)
/// / `"scientific"`: Frame plot area using a rect and draw axes `x` (bottom), `y` (left), `x2` (top), and `y2` (right) around it.
/// If `x2` or `y2` are unset, they mirror their opposing axis.
/// / `"scientific-auto"`: Draw set (used) axes `x` (bottom), `y` (left), `x2` (top) and `y2` (right) around
/// the plotting area, forming a rect.
/// / `"school-book"`: Draw axes `x` (horizontal) and `y` (vertical) as arrows pointing to the right/top with both crossing at $(0, 0)$
/// / `"left"`: Draw axes `x` and `y` as arrows, while the y axis stays on the left (at `x.min`)
/// and the x axis at the bottom (at `y.min`)
/// - `none`: Draw no axes (and no ticks).
/// / `none`: Draw no axes (and no ticks).
/// - plot-style (style,function): Style used for drawing plot graphs
/// This style gets inherited by all plots.
/// This style gets inherited by all plots and supports `palette` functions.
/// - mark-style (style,function): Style used for drawing plot marks.
/// This style gets inherited by all plots.
/// - fill-below (bool): Fill functions below the axes (draw axes above fills)
/// - name (string): Element name
/// This style gets inherited by all plots and supports `palette` functions.
/// - fill-below (bool): If true, fill functions below the axes (draw axes above filled plots), if false
/// filled areas get drawn above the plots axes.
/// - name (string): The plots element name to be used when refering to anchors
/// - legend (none, auto, coordinate): Position to place the legend at.
/// The following anchors are considered optimal
/// for legend placement:
/// - `legend.north`, `legend.south`, `legend.east`, `legend.west`
/// - `legend.north-east`, `legend.north-west`, `legend.south-east`, `legend.south-west`
/// - `legend.inner-north`, `legend.inner-south`, `legend.inner-east`, `legend.inner-west`
/// - `legend.inner-north-east`, `legend.inner-north-west`, `legend.inner-south-east`, `legend.inner-south-west`
/// The following anchors are considered optimal for legend placement:
/// - `legend.north`:
/// - `legend.south`:
/// - `legend.east`:
/// - `legend.west`:
/// - `legend.north-east`
/// - `legend.north-west`
/// - `legend.south-east`
/// - `legend.south-west`
/// - `legend.inner-north`
/// - `legend.inner-south`
/// - `legend.inner-east`
/// - `legend.inner-west`
/// - `legend.inner-north-east`
/// - `legend.inner-north-west`
/// - `legend.inner-south-east`
/// - `legend.inner-south-west`
///
/// If set to `auto`, the placement is read from the legend style (root `legend`).
/// - legend-anchor (auto, string): Anchor of the legend group to use as origin of the
/// legend group.
/// - legend-style (style): Legend style orverwrites.
/// - ..options (any): The following options are supported per axis
/// and must be prefixed by `<axis-name>-`, e.G.
/// `x-min: 0`.
/// - min (int): Axis minimum
/// - max (int): Axis maximum
/// - horizontal (bool): Axis orientation; note that each
/// plot must use one vertical and one horizontal axis!
/// The default value for this parameter is guessed: Axes
/// starting with "x" are considered horizontal by default.
/// This does not affect the side the ticks of the axis are
/// drawn, but only the drawing direction.
/// - tick-step (float): Major tick step
/// - minor-tick-step (float): Major tick step
/// - ticks (array): List of ticks values or value/label
/// tuples
/// - unit (content): Tick label suffix
/// - decimals (int): Number of decimals digits to display
/// If set to `auto`, the placement of the legend style (*Style Root* `legend`) gets used.
/// If set to a coordinate, that coordinate, relative to the plots origin is used for
/// placing the legend group.
/// - legend-anchor (auto, string): Anchor of the legend group to use as its origin.
/// If set to `auto` and `lengend` is one of the predefined legend anchors, the
/// opposite anchor to `legend` gets used.
/// - legend-style (style): Style key-value overwrites for the legend style with style root `legend`.
/// - ..options (any): Axis options, see _options_ above.
#let plot(body,
size: (1, 1),
axis-style: "scientific",
Expand Down Expand Up @@ -340,3 +360,36 @@

draw.copy-anchors("plot")
})

/// Add an anchor to a plot environment
///
/// This function is simillar to `draw.anchor` but it takes an additional
/// axis tuple to specify which axis coordinate system to use.
///
/// #example(```
/// import cetz.plot
/// import cetz.draw: *
/// plot.plot(x-tick-step: none, y-tick-step: none, name: "plot", {
/// plot.add(((0,0), (1,1), (2,.5), (4,3)))
/// plot.add-anchor("pt", (1,1))
/// })
///
/// line("plot.pt", ((), "|-", (0,1.5)), mark: (start: ">"), name: "line")
/// content("line.end", [Here], anchor: "south", padding: .1)
/// ```)
///
/// - name (string): Anchor name
/// - position (tuple): Tuple of x and y values.
/// Both values can have the special values "min" and
/// "max", which resolve to the axis min/max value.
/// Position is in axis space defined by the axes passed to `axes`.
/// - axes (tuple): Name of the axes to use `("x", "y")`, note that both
/// axes must exist, as `add-anchors` does not create axes on demand.
#let add-anchor(name, position, axes: ("x", "y")) = {
((
type: "anchor",
name: name,
position: position,
axes: axes,
),)
}
5 changes: 3 additions & 2 deletions src/lib/plot/sample.typ
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
/// Sample the given one parameter function with `samples` values
/// Sample the given single parameter function `samples` times, with values
/// evenly spaced within the range given by `domain` and return each
/// sampled `y` value in an array as `(x, y)` tuple.
///
/// If the functions first return value is a tuple `(x, y)`, then all return values
/// must be a tuple.
///
/// - fn (function): Function to sample of the form `(x) => y` or `(x) => (x, y)`.
/// - fn (function): Function to sample of the form `(x) => y` or `(t) => (x, y)`, where
/// `x` or `t` are `float` values within the domain specified by `domain`.
/// - domain (domain): Domain of `fn` used as bounding interval for the sampling points.
/// - samples (int): Number of samples in domain.
/// - sample-at (array): List of x values the function gets sampled at in addition
Expand Down

0 comments on commit 5141069

Please sign in to comment.