spine_plot¶

Show where a partition came from: the measure, and the profile behind it.

Two panels. The left is where multiplicative scale separation is visible, or visibly absent. The right says whether a single stratum means no structure at all, or structure that is not entropic.

Syntax and options¶

from entropy_spine import spine_plot
help(spine_plot)
Help on function spine_plot in module entropy_spine.interface.plots:

spine_plot(result_or_info, *, title: 'str' = '', scale: 'str' = 'auto')
    Show where a partition came from: the measure, and the profile.

    Two panels: the sorted measure against rank with strata shaded and each
    cut marked with its value, and the incremental nested entropy with
    candidate transitions as open circles and retained cuts filled. Accepts the
    Result from ``spine`` or a bare info record from ``spine_core``. Returns
    the figure.

A partition with clear separation¶

%matplotlib inline
import numpy as np
from entropy_spine import spine, spine_plot

rng = np.random.default_rng(20260810)
X = np.vstack([rng.standard_normal((240, 8)),
               rng.standard_normal((45, 8)) + 6,
               rng.standard_normal((15, 8)) + 30])
_, result = spine(X, "robustrownorm", "upper")
spine_plot(result, title="three planted scales");
No description has been provided for this image

Reading it¶

The left panel shades alternate strata and marks each cut with its value. The right panel plots the incremental nested entropy against rank, with candidate boundaries as open circles and retained boundaries filled.

When nothing is found¶

The profile panel is the one to look at. A profile that simply rises has no transition to cut on, which is a different statement from "the data has no groups".

rng = np.random.default_rng(3)
_, flat = spine(rng.standard_normal((300, 4)), "dist2median", "upper")
spine_plot(flat, title="no separation");
No description has been provided for this image

It also accepts a bare info record¶

Useful when the objects are not rows and there is no data to draw, as with the singular measure.

rng = np.random.default_rng(77)
M = rng.standard_normal((60, 25)) @ np.diag([40, 26, 15] + [0.6] * 22)
_, rsv = spine(M, "singular", "upper")
spine_plot(rsv.info, title="singular values, with the cut");
No description has been provided for this image

See also¶

spine_data_plot for the data itself, spine_summary to read the same partition in words.