ecdf

package
v0.0.21 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 21, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package ecdf is the imzero2 widget for plotting an empirical CDF together with a finite-sample exact simultaneous confidence band (Berk-Jones by default; DKW / equal-precision / higher-criticism available per the underlying ecdfbands library).

The widget is stateless: construct one Renderer with a fluent builder, then call Render once per frame with the host's open *implot.Plot (between Begin and End — the widget renders through the implot port per ADR-0149 SD7). Each Render declares the shaded band and the ECDF step curve into that plot.

Index

Constants

View Source
const ReadoutLineCount = 5

ReadoutLineCount is the fixed number of text rows WriteStatusLine emits, so the status area keeps a constant height whether or not the cursor is over the curve. A height that jumped on hover would shift the layout and, in the distsummary host, re-enter the plot-width grow guard. Hosts budget vertical space for the readout from this.

Variables

View Source
var PackageProps = packageprops.Props{
	WASMWASI:         packageprops.WASMBlocked,
	WASMJS:           packageprops.WASMBlocked,
	WASMFreestanding: packageprops.WASMBlocked,
}

PackageProps records this package's curated properties (ADR-0080). Seeded by `boxer code analysis golang wasmsurvey props generate`; curate by hand. The same group's `props verify` reconciles it.

Functions

func CancelBandJob

func CancelBandJob(jobKey string)

CancelBandJob aborts the background band warm-up scheduled under jobKey by EnsureBandJob, if one is in flight, and forgets it. Idempotent — a no-op when nothing is registered for jobKey — so it is safe to call every frame an inspector is closed. It is a package function rather than a Renderer method because the job is identified by jobKey alone: the renderer's own (α, method) configuration is irrelevant to which solve to stop. A band that already finished stays in the shared ecdfbands cache, so a reopen still renders instantly.

func WriteStatusLine

func WriteStatusLine(ch Crosshair)

WriteStatusLine emits the verbose, plain-language cursor readout immediately below the c.Plot as a fixed-height stack of weak-styled rows: the description when ch.Valid, a one-line hover hint otherwise, padded with blank rows to ReadoutLineCount so hovering on / off never reflows the host. The text is produced by the pure [formatReadout] so the wording is unit-testable without egui.

func WriteStatusLineTerse added in v0.0.5

func WriteStatusLineTerse(ch Crosshair)

WriteStatusLineTerse emits the compact one-line counterpart to WriteStatusLine: a single weak row in standard ECDF notation, for inline placements (a status bar, a dense table row) where the multi-line readout is too tall. No-op when ch.Valid is false — terse callers that want a placeholder emit their own. The text is built by the pure [formatStatusLineTerse].

Types

type BandJobSnapshot

type BandJobSnapshot struct {
	State    BandJobState
	Fraction float32
	EtaMs    int64
	Note     string
	Err      error
}

BandJobSnapshot is an immutable view of a warm-up's progress, safe to read from the render goroutine. Fraction ∈ [0,1]; EtaMs is -1 until estimable, 0 once finished.

type BandJobState

type BandJobState uint8

BandJobState is the lifecycle of a background confidence-band warm-up.

const (
	// BandJobRunning: the O(n²) critical-value inversion is in flight.
	BandJobRunning BandJobState = iota
	// BandJobDone: the critical value is cached — ecdfbands.BandReady is
	// now true and the band renders cheaply on the next frame.
	BandJobDone
	// BandJobError: the inversion failed or was cancelled; Err carries
	// the reason. Not retried automatically.
	BandJobError
)

type BandKindE added in v0.0.5

type BandKindE uint8

BandKindE classifies which confidence band a Crosshair's [LowerX, UpperX] edges were read from, so the readout can name it honestly.

const (
	// BandNone: no band edges populated. The readout omits the band line.
	BandNone BandKindE = iota
	// BandExact: edges from the configured exact family ([Crosshair.Method])
	// at calibration size [Crosshair.BandN] — the tighter band behind the
	// optional background warm-up.
	BandExact
	// BandPreview: edges from the instant closed-form DKW preview (always at
	// the true sample size); wider / conservative.
	BandPreview
)

type Crosshair

type Crosshair struct {
	Valid      bool
	X          float64
	Y          float64
	FnX        float64
	LowerX     float64
	UpperX     float64
	NearestX   float64
	NearestIdx int
	Alpha      float64

	// BandKind classifies [LowerX, UpperX] (exact vs DKW preview vs none)
	// so the readout can label it; Method names the exact family
	// (immaterial for the DKW preview, which the readout names explicitly).
	BandKind BandKindE
	Method   ecdfbands.BandMethodE

	// BandN is the sample size the band's critical value was calibrated at;
	// SampleN is the true current sample size. They differ when the host
	// caps or buckets the exact-band n (BandN < SampleN) — then the band is
	// a conservative over-cover and the readout says so. The grid entry
	// points set BandN; the host sets SampleN, since only it knows the true
	// count distinct from the bucketed / capped solve size.
	BandN   int
	SampleN int

	// FromGrid is true for the streaming/grid paths (AtGrid / AtGridPreview),
	// where "nearest" is a grid evaluation point rather than an observed
	// order statistic — the readout phrases it honestly instead of
	// mislabelling a grid point as X_(i).
	FromGrid bool
}

Crosshair captures the cursor position over an ECDF plot and the derived statistics most readers want to inspect at that point: the empirical CDF value F_n(x), the simultaneous confidence band [LowerX, UpperX] at x, and the nearest order statistic X_(NearestIdx+1). Valid is false when no hover information is currently available — the cursor is outside the plot, no plot has rendered yet this session, or the cached hover refers to a different plot id.

Alpha echoes Renderer.Alpha so WriteStatusLine can derive the coverage label "(1-α)·100%" without the caller having to plumb it through. The band-provenance fields (BandKind, Method, BandN, SampleN, FromGrid) let WriteStatusLine name the band honestly and surface staleness — see those fields' notes (ADR-0093).

type Renderer

type Renderer struct {
	// contains filtered or unexported fields
}

Renderer is the configured ECDF + confidence band visualiser. Zero value is not usable — construct via New.

func New

func New() (inst Renderer)

New constructs a Renderer with IDS-aligned defaults.

Static defaults:

  • method: BandMethodBerkJones (tail-tight, default)
  • alpha: 0.05 (95% simultaneous coverage)
  • bandFill: AccentDefault with 0x40 alpha overlay
  • bandStroke: AccentDefault at 0px width (no outline)
  • ecdfStroke: NeutralTextPrimary at 1.5 px
  • seriesName: "ECDF" (band's legend label is "<seriesName> band")

func (Renderer) Alpha

func (inst Renderer) Alpha(a float64) (out Renderer)

Alpha sets the complement-of-coverage level. The band realises (1-α)·100% simultaneous coverage. Default 0.05.

func (Renderer) At

func (inst Renderer) At(p *implot.Plot, sorted []float64) (out Crosshair)

At returns the crosshair info for the sample at the cursor position over the given plot (implot's per-plot hover state — one frame behind, like every register read; a pointer over a different plot never surfaces here).

Crosshair.Valid is false when the plot is not hovered or sorted is empty. Cheap to call: BandsForSample is cached by (n, α, method); the per-call cost is two O(log n) binary searches plus a slice copy out of the band cache.

func (Renderer) AtGrid

func (inst Renderer) AtGrid(p *implot.Plot, xs, fnAt []float64, n int) (out Crosshair)

AtGrid mirrors At for the streaming/grid path used by RenderGrid. xs and fnAt are the same grid arrays passed to RenderGrid; n is the total sample size on which the underlying ECDF estimator was built (typically much larger than len(xs)).

func (Renderer) AtGridPreview

func (inst Renderer) AtGridPreview(p *implot.Plot, xs, fnAt []float64, n int) (out Crosshair)

AtGridPreview mirrors AtGrid for the DKW preview band: it reads the band edges at the cursor from the instant closed-form ecdfbands.DkwBandForGrid rather than the warmed exact band, so a hover readout is available before (or without) the exact inversion. Crosshair.Alpha echoes the renderer's alpha as usual.

func (Renderer) BandFill

func (inst Renderer) BandFill(col color.Color) (out Renderer)

BandFill overrides the polygon fill colour applied to the band region. Default AccentDefault at 0x40 alpha.

func (Renderer) BandMethod added in v0.0.5

func (inst Renderer) BandMethod() ecdfbands.BandMethodE

BandMethod returns the configured exact-band family — the getter counterpart to Renderer.Method, so a host widget can name the band (e.g. in an always-visible status line) without re-deriving it.

func (Renderer) BandReady

func (inst Renderer) BandReady(n int) bool

BandReady reports whether this renderer's (n, α, method) confidence band is already cached — i.e. whether RenderGrid/AtGrid will draw without blocking on the O(n²) inversion. Non-blocking probe; pair it with EnsureBandJob to drive the schedule-and-show-progress path.

func (Renderer) BandStroke

func (inst Renderer) BandStroke(col color.Color, widthPx float32) (out Renderer)

BandStroke sets the polygon outline colour and width for the band. Default 0 px (no outline) — the band reads as a fill alone.

func (Renderer) EcdfStroke

func (inst Renderer) EcdfStroke(col color.Color, widthPx float32) (out Renderer)

EcdfStroke sets the colour and width of the ECDF step polyline. Default NeutralTextPrimary at 1.5 px.

func (Renderer) EnsureBandJob

func (inst Renderer) EnsureBandJob(jobKey string, tasks task.TaskApiI, n int) BandJobSnapshot

EnsureBandJob schedules (once, idempotently) a background warm-up of this renderer's (n, α, method) band under jobKey — a stable per-inspector identity the host widget supplies (its per-call scope) — and returns the current progress snapshot. tasks may be nil (the solve still runs; only keelson task integration is skipped). Call on frames where BandReady(n) is false: render RenderGridCurveOnly for the curve and show the returned snapshot via a progress widget below the plot. Pair it with CancelBandJob(jobKey) when the inspector closes so a long solve does not outlive the window that asked for it.

func (Renderer) Method

func (inst Renderer) Method(m ecdfbands.BandMethodE) (out Renderer)

Method sets the confidence-band family. Default BandMethodBerkJones.

func (Renderer) PaintCrosshair

func (inst Renderer) PaintCrosshair(p *implot.Plot, ch Crosshair)

PaintCrosshair declares a vertical reference line at ch.X using the renderer's ECDF stroke colour at half alpha. No-op when ch.Valid is false. Declare it after Render inside the same plot so the line draws on top of the band and curve.

func (Renderer) Render

func (inst Renderer) Render(p *implot.Plot, sorted []float64) (err error)

Render declares the ECDF + confidence band for one sorted iid sample into the host's open plot.

sorted must be non-decreasing; the underlying ecdfbands library rejects unsorted inputs with an error. n must be ≥ 2 for a meaningful band; n = 0 / 1 short-circuit (no emit).

The render order is: the shaded band first (it sits under the curve), then the ECDF step polyline.

func (Renderer) RenderGrid

func (inst Renderer) RenderGrid(p *implot.Plot, xs, fnAt []float64, n int) (err error)

RenderGrid renders the ECDF + confidence band at an explicit (xs, fnAt) grid, mirroring ecdfbands.BandsForGrid. n is the total sample size on which the ECDF estimator was built (typically much larger than len(xs)) — the band's calibration depends on n, not on the grid resolution.

Use this when the sample is too large to sort (a t-digest or Greenwald-Khanna sketch is the typical source) or when the visualisation grid is intentionally coarser than the underlying data. xs and fnAt must satisfy the same validation as BandsForGrid: monotone non-decreasing, fnAt ∈ [0, 1].

Render order matches Render: band rectangles first, then the ECDF step curve from the (xs, fnAt) grid.

func (Renderer) RenderGridCurveOnly

func (inst Renderer) RenderGridCurveOnly(p *implot.Plot, xs, fnAt []float64)

RenderGridCurveOnly emits only the ECDF step polyline for an (xs, fnAt) grid — the band-free counterpart to RenderGrid, drawn while the confidence band is still warming in the background.

func (Renderer) RenderGridPreview

func (inst Renderer) RenderGridPreview(p *implot.Plot, xs, fnAt []float64, n int) (err error)

RenderGridPreview draws the instant closed-form DKW preview band (via ecdfbands.DkwBandForGrid) plus the ECDF grid curve. Unlike RenderGrid it never blocks on the O(n²) inversion, so it is the band to draw every frame while the tighter exact band (the renderer's configured Method) warms in the background or waits behind an explicit compute request. The conservative DKW strip is wider than the exact band — most visibly in the tails — so swapping to the exact band reads as a tightening.

func (Renderer) SeriesName

func (inst Renderer) SeriesName(name string) (out Renderer)

SeriesName sets the legend label for the ECDF series. The band series uses "<seriesName> band".

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL