elbow_helper.plotting module
Diagnostic figure for a robust_knee() run.
Renders a self-contained SVG — no matplotlib, no Vega, no runtime image
library — so this stays a core feature (no [plot] extra to install)
rather than a lazy opt-in. The SVG-writing code below (the Catmull-Rom
spline helper, the responsive <svg> header, the additive dark-mode
block) is adapted from this project’s sibling sprezzature-figures
package (scripts/make_elbow.py / _svg.py / _style.py) and
copy-pasted in rather than taken as a dependency, then cut down and
re-specialised for this module’s own data shapes (normalized x/y
arrays and the ClearKnee /
NoClearKnee result types) — elbow-helper’s
only runtime dependencies stay numpy and os-helper.
The figure never shows a bare point estimate: the knee is paired with its 90% bootstrap interval and the supporting evidence (detection probability, null-model p-value, slope contrast, a BIC-derived posterior model probability, and a worst-case-normalized fit-quality score) in a compact legend. When the evidence is too weak, the figure says so plainly — a greyed, dashed curve and a reason — instead of drawing a marker that implies more confidence than the data supports.
- elbow_helper.plotting.plot_diagnostics(x, y=None, *, curve=None, direction=None, config=None, out=None, language='en', raw_axis=False, log_y=False, x_label=None, y_label=None)[source]
Render the robust-knee diagnostic SVG and optionally save it.
- Parameters:
x (array-like) – The curve.
ymay be omitted, as inelbow_helper.robust_knee().y (array-like) – The curve.
ymay be omitted, as inelbow_helper.robust_knee().curve (str, optional) – Orientation; inferred from the data when omitted.
direction (str, optional) – Orientation; inferred from the data when omitted.
config (RobustKneeConfig, optional) – Thresholds and replicate counts forwarded to the pipeline.
out (str, optional) – If given, save the SVG to this path (parent directories are created).
language (str, optional) – Chrome-text language,
"en"(default) or"fr".raw_axis (bool, optional) – Display in original data units instead of the pipeline’s internal normalized
[0, 1]square; seerender_svg().log_y (bool, optional) – Log-scale the y-axis (only meaningful with
raw_axis=True).x_label (str, optional) – Axis captions to use with
raw_axis=True.y_label (str, optional) – Axis captions to use with
raw_axis=True.
- Returns:
The complete SVG document (also written to
outwhen given).- Return type:
Examples
>>> import numpy as np >>> x = np.linspace(0, 1, 50) >>> y = np.where(x <= 0.3, 3 * x, 0.9 + 0.1 * (x - 0.3)) >>> svg = plot_diagnostics(x, y) >>> svg.startswith("<svg") True
- elbow_helper.plotting.plot_diagnostics_panels(svgs, *, out=None, gap=24.0)[source]
Render
render_svg_panels()and optionally save it.- Parameters:
svgs (sequence of str) – One complete, standalone SVG document string per panel; see
render_svg_panels().out (str, optional) – If given, save the SVG to this path (parent directories are created).
gap (float, optional) – Horizontal gap, in pixels, between panels.
- Returns:
The complete SVG document (also written to
outwhen given).- Return type:
- elbow_helper.plotting.plot_multi_diagnostics(x, y=None, *, config=None, out=None, language='en', x_label=None, y_label=None)[source]
Render the robust-knees (plural) diagnostic SVG and optionally save it.
- Parameters:
x (array-like) – The curve.
ymay be omitted, as inelbow_helper.robust_knees().y (array-like) – The curve.
ymay be omitted, as inelbow_helper.robust_knees().config (RobustKneesConfig, optional) – Search size and false-positive-control settings.
out (str, optional) – If given, save the SVG to this path (parent directories are created).
language (str, optional) – Chrome-text language,
"en"(default) or"fr".x_label (str, optional) – Axis captions; default to the generic normalized-style captions when omitted.
y_label (str, optional) – Axis captions; default to the generic normalized-style captions when omitted.
- Returns:
The complete SVG document (also written to
outwhen given).- Return type:
Examples
>>> import numpy as np >>> x = np.linspace(0, 1, 150) >>> y = np.piecewise( ... x, [x < 0.4, x >= 0.4], [lambda t: 2 * t, lambda t: 0.8 + 0.1 * (t - 0.4)] ... ) >>> svg = plot_multi_diagnostics(x, y) >>> svg.startswith("<svg") True
- elbow_helper.plotting.render_svg(x, y=None, *, curve=None, direction=None, config=None, language='en', raw_axis=False, log_y=False, x_label=None, y_label=None)[source]
Build the robust-knee diagnostic as a complete, standalone SVG string.
- Parameters:
x (array-like) – The curve.
ymay be omitted, as inelbow_helper.robust_knee().y (array-like) – The curve.
ymay be omitted, as inelbow_helper.robust_knee().curve (str, optional) – Orientation; inferred from the data when omitted.
direction (str, optional) – Orientation; inferred from the data when omitted.
config (RobustKneeConfig, optional) – Thresholds and replicate counts forwarded to the pipeline.
language (str, optional) – Chrome-text language,
"en"(default) or"fr".raw_axis (bool, optional) – Display the curve in its original data units instead of the pipeline’s internal normalized
[0, 1]square. The knee marker and confidence band still come straight fromresult.knee_x/result.ci90, already in data units; only the displayed points and smoothed curve are mapped back throughprepared’s storedx_lo/x_hi/y_lo/y_hibounds. DefaultFalse(the package’s own normalized diagnostic view, unchanged).log_y (bool, optional) – Log-scale the y-axis. Only meaningful with
raw_axis=Trueand a strictly positivey; ignored otherwise.x_label (str, optional) – Axis captions to use with
raw_axis=True, where the default “x (normalized)” / “y (scaled)” captions no longer apply. Ignored whenraw_axisisFalse.y_label (str, optional) – Axis captions to use with
raw_axis=True, where the default “x (normalized)” / “y (scaled)” captions no longer apply. Ignored whenraw_axisisFalse.
- Returns:
A complete SVG document: the curve with its knee (or an honest abstention state) and the evidence that backs it.
- Return type:
- elbow_helper.plotting.render_svg_multi(x, y=None, *, config=None, language='en', x_label=None, y_label=None)[source]
Build the robust-knees (plural) diagnostic as a standalone SVG string.
Unlike
render_svg(), this wrapselbow_helper.robust_knees()and marks zero or more breakpoints with dashed lines rather than a single knee with a confidence band: there is no continuous broken-line fit or BIC-derived evidence legend here, only the breakpoint locationselbow_helper.robust_knees()itself reports, each an independent (discontinuous) segment boundary rather thanClearKnee’s continuous broken-line model.- Parameters:
x (array-like) – The curve.
ymay be omitted, as inelbow_helper.robust_knees().y (array-like) – The curve.
ymay be omitted, as inelbow_helper.robust_knees().config (RobustKneesConfig, optional) – Search size and false-positive-control settings.
language (str, optional) – Chrome-text language,
"en"(default) or"fr".x_label (str, optional) – Axis captions; default to the generic normalized-style captions when omitted.
y_label (str, optional) – Axis captions; default to the generic normalized-style captions when omitted.
- Returns:
A complete SVG document: the curve with every detected breakpoint marked by a dashed line (or an honest abstention state).
- Return type:
- elbow_helper.plotting.render_svg_panels(svgs, *, gap=24.0)[source]
Lay out several already-rendered diagnostic SVGs side by side.
Each panel is whatever complete, standalone SVG the caller already produced, typically one
render_svg()call per noise level or scenario (or a mix ofrender_svg()/render_svg_multi()outputs), run and rendered independently: its own pipeline call, its own title/subtitle, its own legend or abstention card. This only nests those SVGs into one shared canvas via SVG’s native nested-viewport element, left to right. Useful for a controlled side-by-side comparison, such as the same shape at two noise levels.- Parameters:
- Returns:
A complete SVG document containing one nested panel per input SVG.
- Return type:
Examples
>>> import numpy as np >>> x = np.linspace(0, 1, 60) >>> y = np.where(x < 0.5, 0.8 * x, 0.4 + 0.2 * (x - 0.5)) >>> left = render_svg(x, y + 0.01) >>> right = render_svg(x, y + 0.2) >>> svg = render_svg_panels([left, right]) >>> svg.count("<svg") == 3 True