Miter

At the moment, this package is work in progress. The syntax may change without notice, and a lot of the functionality is undocumented. More importantly, an explanation of the key concepts that help in using this package is yet to be written.

Introduction

TBW

String-like arguments

Strings (for axis labels, annotations, plot titles) can be provided three ways:

  1. using any ::AbstractString (except for the types below), eg "100%" or "$5". This will be automatically emitted to the \LaTeX engine in an escaped form, such as 100\%or \$5. Use this for plain text (including Unicode). This is always valid.
  2. using the [LaTeXEscapes.LaTeX]@ref) wrapper that emits strunchanged, or one of the convenience string literals lx"..."or lx"..."m, where the only difference is that the latter wraps the content in $s (for math). Be careful: some basic sanity checks are performed, but using incorrect raw LaTeX can lead to errors that are hard to trace.
  3. using LaTeXString.LaTeXString, especially if you want interpolation, but note that L"..." automatically wraps its input in $s and you may not want that.

If you concatenate strings of the types above with the * operator, make sure you put a LaTeX first (you can always insert an empty one, eg LaTeX() or lx"". That way, the output is a LaTeX and everything will be correctly escaped. Other combinations are deliberately unsupported.

What you see below is a gallery of plots. These serve as examples, and are also useful for visual inspection of plots.

All should be preceded by

using Miter, Colors
using LaTeXEscapes
using Unitful: mm

to load the relevant packages.

Simple plots

Plot([Lines((x, abs2(x)) for x in -1:0.02:1; color = colorant"red"),
      Scatter(MarkSymbol(; color = colorant"darkgreen"), (x, (x + 1) / 2) for x in -1:0.1:1)];
      x_axis = Axis.Linear(; label = math"x"),
      y_axis = Axis.Linear(; label = math"y"),
      title = "line and scatter")

Horizontal and vertical lines, and phantom objects (rendered, but ignored for boundary calculations).

Plot(Scatter((x, sin(x) + (rand() - 0.5) / 10) for x in range(-π, π; length = 100)),
     Phantom(Hline(12.0)),      # does not show, it is outside the boundaries
     Hline(0.0), Vline(0.0))
Example block output

Bar plots with bars directly specified.

let c = [(0, 1, 2), (1, 2, 1), (2, 4, -0.5)]
    Tableau([Plot(RelativeBars(:vertical, c)),
             Plot(RelativeBars(:horizontal, c))])
end
Example block output

Bar plots from a histogram.

using StatsBase
Plot(RelativeBars(:vertical, fit(Histogram, randn(100))))
Example block output

Annotations.

let c = colorant"teal",
    xy = collect((x,  0.5 * x + 0.1 * randn()) for x in range(-1, 1; length = 30))
    Plot(Scatter(MarkSymbol(; color = c), xy),
         Annotation((0, 0.3), textcolor(c, latex"random dots $y = 0.5\cdot x + N(0, 0.1)$");
                    rotate = 30))
end

Various kinds of marks.

let x = range(0, 1; length = 21)
    Plot(Scatter(MarkSymbol(:+; color = colorant"firebrick"), (x, 0.2 * x) for x in x),
         Scatter(MarkSymbol(:*, color = colorant"olive"), (x, 0.1 + abs2(x)) for x in x),
         Scatter(MarkSymbol(:o; color = colorant"teal"), (x, -x + abs2(x) - 0.1) for x in x))
end
Example block output

Guidelines, adding plot elements (with push! & friends).

let plot = Plot(Scatter(MarkSymbol(:o; color = colorant"chocolate4"),
                        (sin(α), cos(α)) for α in range(-π, π, length = 61)))
    for θ in 0:30:150
        pushfirst!(plot.contents, LineThrough((0, 0), tand(θ)))
    end
    plot
end
Example block output

Grids.

Plot(Hgrid(), Vgrid(), # specified first; renders first
     Scatter((x, expm1(x) + randn() / 10)
             for x in range(0, 1; length = 100)))
Example block output

Sync x and y bounds in a tableau.

using Accessors # for @modify

function wobbler(x, y, r, rotate)
    Plot(Lines([sincos(θ) .* (r * (sin(θ  * 3 + rotate)/4 + 1))
                for θ in range(0, 2*π; length = 200)]))
end

m = Tableau(balanced_matrix([wobbler(0, 0, 2, 0),
                                wobbler(1, 0, 1, π/2),
                                wobbler(-1, 0, 3, -π/2),
                                wobbler(1, 3, 1, π)]));
@modify(sync_bounds(:xy), m.contents) # sync columns and rows
Example block output

Add an invisible object to extend the y axis.

Plot([Lines((x, x^2) for x in range(0, 1; length = 20)),
      Invisible(nothing, Interval(-1, 1))])
Example block output

Q5 (five quantiles) plots.

Plot(Scatter(MarkQ5(),
             (x, Q5(randn(10) ./ 4 .+ (x / 3)))
             for x in range(0, 5; length = 8)),
     Scatter(MarkQ5(; color = colorant"deepskyblue1"),
             (Q5(randn(10) ./ 4 .+ (abs2(y) / 5)), y)
             for y in range(0, 5; length = 8)))
Example block output

Circles.

x_y_w = [(x, y, 6 - hypot(x, y)) for x in -5:5 for y in -5:5 if hypot(x, y) ≤ 5]
# make the largest point have 3mm radius
Plot(Circles(x_y_w, 3mm / √maximum(last, x_y_w)))

Color matrix (a building block for heatmaps etc).

Plot(ColorMatrix([0, 1, 3], [2, 4, 5],
                 [nothing colorant"green";
                  colorant"blue" colorant"red"]))
Example block output

Color matrix built from a histogram.

using StatsBase, ColorSchemes
h = fit(Histogram, (randn(1000), randn(1000)); nbins = (15, 17))
Plot(hpd_heatmap(h, range(0.2, 0.8; step = 0.2), ColorSchemes.OrRd_5))
Example block output

Tableaus

Tableau(balanced_matrix(
        [Plot(Lines([(x, exp(-0.5 * abs2(x)) / √(2π))
                     for x in range(-2, 2; length = 101)]);
              y_axis = Axis.Linear(; label = "pdf of normal distribution")),
         Plot(Lines([(x, exp(-abs(x)) / 2)
                     for x in range(-2, 2; length = 101)]);
              y_axis = Axis.Linear(; label = "pdf of Laplace distribution")),
         Plot(Lines([(x, exp(-x))
                     for x in range(0.1, 2; length = 50)]);
              y_axis = Axis.Linear(; label = "pdf of exponential distribution"))]))
Example block output

Visual debugging

Canvas(Tableau([Miter.dummy("$(x), $(y)") for x in 1:3, y in 1:4]),
       width = 100mm, height = 100mm)

Corner cases

Handle collapsing axes gracefully

Plot(Scatter([(0.49999,0.49999)]))