Skip to content

Normal distributions and MCMC

Cargo featurefeatures = ["ml"]

Gaussian2D { mean, covariance } is a 2D normal distribution. density(p) is its probability density, principal_axes() the standard deviation along each eigenvector of the covariance (the longer axis first), ring(k) the ellipse k standard deviations from the mean, and samples(seed, n) seeded samples. All of these are empty or None when the covariance is not positive definite.

  • GaussianEllipse. The ellipses of equal density sigmas standard deviations from the mean (1, 2 and 3 by default) on axes, each filled at fill_opacity so the middle is darkest, the mean as a dot and, with show_axes, the principal axes. With stagger the rings appear one after the other from start, the innermost first.
  • McmcChain. A random-walk Metropolis-Hastings chain sampling the equal mixture of the distributions in target. It starts at origin, proposes steps from a normal distribution proposal wide, and takes a step with the probability min(1, p(to) / p(from)), so a step uphill is always taken. chain() gives its steps (McmcStep { from, to, accepted }), the same for the same seed. With run: Some(ChainRun { start, duration }) a dot walks the accepted moves at an even speed over duration, drawing the path in accepted_color. Every proposal it rejects appears as a ring in rejected_color when the dot is where it was proposed. Rejected proposals outside the axes are not drawn.

Draw both before the Axes so the axis lines stay on top. Gallery scenes: GaussianEllipse, McmcChain (a chain finding both modes of a mixture), McmcSwarm (ten chains from the edge finding three modes together).

GaussianEllipse demo, first frame
GaussianEllipse 4 s
McmcChain demo, first frame
McmcChain 5 s
McmcSwarm demo, first frame
McmcSwarm 6 s
use fframes_kit::prelude::*;
fn distribution<'a>(ui: &mut Ui<'a, '_, '_>) -> Svgr<'a> {
let axes = Axes::default();
let gaussian = Gaussian2D { mean: (0.4, -0.2), covariance: [[1.2, 0.5], [0.5, 0.45]] };
let ellipse = ui.show(GaussianEllipse { gaussian, axes: axes.map(ui), ..ui.defaults() });
let chain = ui.show(McmcChain {
target: vec![gaussian], axes: axes.map(ui), steps: 70, seed: 5,
run: Some(ChainRun { start: 0.9, duration: 3.6 }), ..ui.defaults()
});
let axes = ui.show(axes);
svgr!(<g>{ellipse}{chain}{axes}</g>)
}

Components are plain structs. Set the fields you need and fill the rest with ..ui.defaults(): the defaults below come from the current theme (theme. values are fields of Theme).

A 2D normal distribution drawn as its ellipses of equal density (ManimML’s GaussianDistribution): a ring sigmas standard deviations from the mean for each entry, in color, each filled at fill_opacity (the inner rings stack up darker), the mean as a dot and, with show_axes, the principal axes out to the outer ring. On axes; draw the Axes after it. With stagger the rings appear one after the other from start, the innermost first.

Field Type Default Description
gaussian Gaussian2D Gaussian2D::default() The 2D normal distribution (mean and covariance) whose ellipses are drawn.
axes AxesMap AxesMap::default() The axes to draw on, mapping data values to the canvas.
sigmas Vec<f64> vec![1.0, 2.0, 3.0] Standard deviations from the mean at which a ring is drawn, one ring per entry.
color Color theme.colors.accent Colour of the rings, their fill, the mean dot and the principal axes.
fill_opacity f32 0.12 0 transparent to 1 opaque, of each ring’s fill; inner rings stack up darker.
stroke_width f32 2.5 Width in pixels of the ring outlines; the mean dot scales with it.
show_axes bool false Draws the principal axes of the distribution out to the outer ring.
start f32 0.0 Seconds after the container’s start when the first ring begins to appear.
stagger f32 0.0 Seconds between one ring appearing and the next, innermost first; 0 shows all rings from the start.
enter Option<FadeIn> None Fade in at the start; None for none.
exit Option<FadeOut> None Fade out before the end; None for none.

Feature ml · Source

A random-walk Metropolis-Hastings chain sampling the equal mixture of the normal distributions in target (ManimML’s MCMC scenes). It starts at origin and proposes steps drawn from a normal distribution proposal wide; a step is accepted with the probability min(1, p(to) / p(from)). The chain is the same for the same seed. With run it plays one step after another over the run’s duration from its start: accepted moves extend the path in accepted_color, rejected proposals inside the axes stay as hollow marks in rejected_color, and the current state is a dot. On axes.

Field Type Default Description
target Vec<Gaussian2D> vec![Gaussian2D::default()] The normal distributions whose equal mixture the chain samples.
origin (f64, f64) (0.0, 0.0) The state the chain starts at, in data units of axes.
proposal f64 0.6 Standard deviation of the random step proposed each time, in data units.
steps usize 60 Number of steps (proposals) in the whole chain.
seed u64 1 Seed of the chain; the same seed gives the same chain on every frame and machine.
axes AxesMap AxesMap::default() The axes to draw on, mapping data values to the canvas.
run Option<ChainRun> None When the steps play, and over how long; None shows the whole chain at once.
accepted_color Color theme.colors.highlight Colour of the path of accepted moves and of the current state dot.
rejected_color Color Color::hex("#ff6b6b") Colour of the hollow marks for rejected proposals.
stroke_width f32 2.5 Width in pixels of the path and the rejected marks.
point_radius f32 6.0 Radius in pixels of the current state dot.
enter Option<FadeIn> None Fade in at the start; None for none.
exit Option<FadeOut> None Fade out before the end; None for none.

Methods:

  • fn chain(&self) -> Vec<McmcStep>: The steps of the chain.

Feature ml · Source