Plot
Plot module: SVG chart generation.
Generates self-contained SVG strings for line, scatter, bar, and histogram charts. No external dependencies — pure March string building.
Usage: let svg = Plot.new() |> Plot.add_series(Plot.line_series(xs, ys)) |> Plot.set_title("My Chart") |> Plot.to_svg
Types
Functions
Like add_series, but also sets the series label shown by the legend (see with_legend).
Examples
march> let bars = Plot.bar_series(["a", "b", "c"], [3.0, 1.0, 2.0])
march> let lp = Plot.new() |> Plot.add_labeled_series(bars, "sales")
march> List.map(lp.series, fn s -> s.label)
[Some("sales")]Append series s to p (drawn after, i.e. on top of, earlier series). The series is recoloured from the 10-colour palette by its position in the plot, overriding its previous style.
Examples
march> let bars = Plot.bar_series(["a", "b", "c"], [3.0, 1.0, 2.0])
march> let two = Plot.new() |> Plot.add_series(Plot.line_series([0.0], [1.0])) |> Plot.add_series(bars)
march> List.map(two.series, fn s -> s.style.line_color.r)
[31, 255]A bar series with one bar per value, placed at x = 0.0, 1.0, 2.0, ... (one position per element of labels). Bars rise from y = 0 (negative values hang below it). Note: only the number of labels is used; the label strings themselves are not rendered on the axis.
Examples
march> let bars = Plot.bar_series(["a", "b", "c"], [3.0, 1.0, 2.0])
march> bars.xs == [0.0, 1.0, 2.0]
true
march> let bars = Plot.bar_series(["a", "b", "c"], [3.0, 1.0, 2.0])
march> bars.ys == [3.0, 1.0, 2.0]
trueBin values into bins equal-width bins spanning [min, max] and return a bar series of the counts, at x = 0.0 .. bins - 1. The maximum value falls into the last bin. When all values are equal every value lands in bin 0. An empty values list (or bins <= 0) gives a series with no bars. O(n log n + n * bins).
Examples
march> (Plot.histogram_series([1.0, 2.0, 2.5, 4.0], 3)).ys == [1.0, 2.0, 1.0]
true
march> (Plot.histogram_series([5.0, 5.0], 2)).ys == [2.0, 0.0]
true
march> (Plot.histogram_series([], 3)).ys
[]A line series through the points zip(xs, ys), drawn as one SVG polyline in data order (points are not sorted by x). Unpaired trailing values of the longer list are ignored. Its colour is assigned when it is added to a plot.
Examples
march> (Plot.line_series([0.0, 1.0], [2.0, 3.0])).ys == [2.0, 3.0]
trueAn empty 640x480 plot: no title, no series, 60px margin, axes auto-ranged from the data with 5 target ticks, legend and grid off.
Examples
march> let p = Plot.new()
march> p.width
640
march> let p = Plot.new()
march> List.length(p.series)
0Like new() but with the given width and height in pixels.
Examples
march> let big = Plot.new_sized(800, 600)
march> (big.width, big.height)
(800, 600)Shortcut: the SVG of a default plot with one bar series (see bar_series; the labels are not drawn).
Examples
march> String.ends_with(Plot.quick_bar(["a", "b"], [1.0, 2.0]), "</svg>")
trueShortcut: the SVG of a default plot with one histogram_series(values, bins).
Examples
march> String.contains(Plot.quick_histogram([1.0, 2.0, 2.0, 3.0], 2), "<rect")
trueShortcut: the SVG of a default plot with one line series.
Examples
march> String.contains(Plot.quick_line([0.0, 1.0], [0.0, 1.0]), "<polyline")
trueShortcut: the SVG of a default plot with one scatter series.
Examples
march> String.contains(Plot.quick_scatter([1.0, 2.0], [2.0, 3.0]), "<circle")
trueRender p to SVG and write it to path, replacing any existing file. Fails with the File.FileError the write reported (NotFound, Permission, IsDirectory, IoError, ...).
Examples
Plot.new()
|> Plot.add_series(Plot.line_series([0.0, 1.0, 2.0], [1.0, 4.0, 9.0]))
|> Plot.set_title("Squares")
|> Plot.save("squares.svg")A scatter series: one circle (radius 4px) per point of zip(xs, ys). Unpaired trailing values of the longer list are ignored.
Examples
march> (Plot.scatter_series([1.0], [5.0])).xs == [1.0]
trueSet the SVG width and height in pixels.
Examples
march> let p = Plot.new()
march> let sized = Plot.set_size(p, 320, 240)
march> (sized.width, sized.height)
(320, 240)Set the title drawn centred above the plot (escaped for SVG).
Examples
march> let p = Plot.new()
march> (Plot.set_title(p, "Revenue")).title
Some("Revenue")Fix the x-axis data range to [lo, hi] instead of auto-ranging. Auto ranges take the data min/max and pad each side by 5% of the span (0.5 when the span is zero); a fixed range is used as given. Points outside the range are not clipped.
Examples
march> let p = Plot.new()
march> ((Plot.set_x_range(p, 0.0, 10.0)).x_axis.data_max) == Some(10.0)
trueSet the x-axis label, drawn centred under the x-axis tick labels.
Examples
march> let p = Plot.new()
march> (Plot.set_xlabel(p, "time")).x_axis.label
Some("time")Fix the y-axis data range to [lo, hi] instead of auto-ranging (see set_x_range).
Examples
march> let p = Plot.new()
march> ((Plot.set_y_range(p, 0.0, 1.0)).y_axis.data_min) == Some(0.0)
trueSet the y-axis label, drawn rotated to the left of the y-axis.
Examples
march> let p = Plot.new()
march> (Plot.set_ylabel(p, "count")).y_axis.label
Some("count")Render p as a self-contained SVG document string (<svg ...> through </svg>): white background, plot-area border, optional grid, axes with "nice" ticks (steps of 1, 2 or 5 times a power of ten), the series, the title and the optional legend. Coordinates and tick labels are written with two decimals (truncated). Title, axis and legend text is XML-escaped.
Examples
march> let p = Plot.new()
march> String.starts_with(Plot.to_svg(p), "<svg")
true
march> let p = Plot.new()
march> String.contains(Plot.to_svg(Plot.set_title(p, "a<b")), "a<b")
trueTurn on light dashed grid lines at every axis tick.
Examples
march> let p = Plot.new()
march> (Plot.with_grid(p)).show_grid
true