Bland.Uncertainty (Elixir Technical Drawing v0.6.0)

Copy Markdown View Source

Uncertainty and error — how every series reports it.

Any series where error is meaningful — Bland.line/4, Bland.step/4, Bland.scatter/4, Bland.bar/4, Bland.histogram/3 and the dedicated Bland.errorbar/4 — accepts the same :yerr / :xerr input and the same display controls, so changing plot type never means re-learning how to report error.

xs = [1.0, 2.0, 3.0]
ys = [1.0, 4.0, 9.0]
sd = [0.1, 0.3, 0.6]

Bland.figure()
# per-point ±SD, drawn as a hatched band behind the line
|> Bland.line(xs, ys, yerr: sd, label: "model")
# one half-width for every point, drawn as capped I-bars
|> Bland.scatter(xs, ys, yerr: 0.25, label: "measured")
# ±5% of each value
|> Bland.line(xs, ys, yerr: {:relative, 0.05})

Specs

SpecMeaning
0.25the same half-width above and below every point
[0.1, 0.3, 0.6]per-point symmetric half-width
[{0.1, 0.2}, ...]per-point {lower, upper} half-widths
{:bounds, los, his}absolute lower and upper bounds per point
{:relative, 0.05}±5% of each value's magnitude
:poisson√N counting error, for series whose values are raw counts

A spec shorter than the series leaves the remaining points with no error bar at all, which is different from an error bar of width zero.

Display

:error_style picks between :band (a hatched envelope, the default for line and step) and :bars (capped I-bars, the default for scatter, bar and histogram). :error_hatch overrides the band fill and :cap_width the I-bar cap.

Summary

Types

A resolved per-point error span: {lower, upper} half-widths, both non-negative, or nil where the series carries no error at that point.

How a caller supplies error for a series.

Functions

Absolute {lower, upper} positions of a span around center.

Default half-width of an I-bar cap, in px.

Every value a resolved error series reaches, for folding into an axis domain. Points with no error contribute their centre only.

Resolves a spec against the series' centre values.

Reduces replicate samples to a centre and a symmetric half-width.

Types

span()

@type span() :: {float(), float()} | nil

A resolved per-point error span: {lower, upper} half-widths, both non-negative, or nil where the series carries no error at that point.

spec()

@type spec() ::
  number()
  | [number() | {number(), number()}]
  | {:bounds, [number()], [number()]}
  | {:relative, number()}
  | :poisson
  | nil

How a caller supplies error for a series.

Functions

bounds(arg1, center)

@spec bounds(span(), number()) :: {float(), float()} | nil

Absolute {lower, upper} positions of a span around center.

iex> Bland.Uncertainty.bounds({0.5, 1.5}, 10.0)
{9.5, 11.5}

default_cap_width()

Default half-width of an I-bar cap, in px.

extent(spans, centers)

@spec extent([span()], [number()]) :: [float()]

Every value a resolved error series reaches, for folding into an axis domain. Points with no error contribute their centre only.

iex> Bland.Uncertainty.extent([{1.0, 2.0}, nil], [10.0, 50.0])
[9.0, 12.0, 50.0]

resolve(half, centers)

@spec resolve(spec(), [number()]) :: [span()]

Resolves a spec against the series' centre values.

The result is indexed positionally and is exactly as long as centers. Entries are nil where the spec says nothing about that point.

iex> Bland.Uncertainty.resolve(0.5, [1.0, 2.0])
[{0.5, 0.5}, {0.5, 0.5}]

iex> Bland.Uncertainty.resolve({:relative, 0.1}, [10.0, -20.0])
[{1.0, 1.0}, {2.0, 2.0}]

iex> Bland.Uncertainty.resolve(:poisson, [4.0, 9.0])
[{2.0, 2.0}, {3.0, 3.0}]

summarize(groups, rule \\ :sd)

@spec summarize([[number()]], :sd | :sem | {:ci, number()}) :: {[float()], [float()]}

Reduces replicate samples to a centre and a symmetric half-width.

rule picks the interval:

  • :sd — one sample standard deviation
  • :sem — one standard error of the mean
  • {:ci, level} — a Student-t confidence interval at level (0.95 for the conventional 95%)

Returns {centers, half_widths} ready to hand straight to a series as its values and its :yerr.

iex> {c, e} = Bland.Uncertainty.summarize([[1.0, 2.0, 3.0]], :sd)
iex> {c, Enum.map(e, &Float.round(&1, 4))}
{[2.0], [1.0]}