The axis (key) column's name — e.g. 'cumDist'.
Number of rows.
The axis value at row i. Throws if out of range.
The axis values (the x of every row), in axis order. Zero-copy — the
returned Float64Array is the live key buffer; treat it as read-only.
A value column by name, for direct columnar reads (.read(i), .values()).
Index of the row whose axis value is closest to value — the
value-axis cursor primitive. The axis is non-decreasing, so this is a
binary search. Returns -1 for an empty series; clamps to the first / last
row when value is outside the axis extent.
The contiguous sub-series whose axis value lies in [lo, hi) — the
value-axis cull (pan / zoom on a value x). Binary-searches the bounds and
zero-copy slices the store. lo >= hi (or a range outside the extent)
yields an empty series.
StaticfromExample: ValueSeries.fromColumns({ name, schema, columns }).
The direct columnar door into value-land — for data that is natively
value-keyed and never had a meaningful per-row time key: an options chain
keyed by strike, a spectrum keyed by frequency, a profile keyed by depth.
(Data that starts life time-keyed projects in via TimeSeries.byValue
instead; before this door existed, cross-sectional callers had to launder
their axis through a fake time column just to reach
TimeSeries.fromColumns + byValue.)
The exact TimeSeries.fromColumns contract, with the axis in place of
time — the two doors share one ingest engine. schema[0] is the
'value'-kind axis column; each columns entry is one column's
values, keyed by schema column name and aligned by index. Values may be a
plain number[] or a Float64Array; a value cell is a gap (missing)
iff it's null/undefined or non-finite — identical rule for both input
types.
Float64Array inputs are adopted, not copied (zero-copy): the
resulting series' columns alias the caller's buffers; pass a fresh buffer
if that matters. (sort disables the adoption — a reorder needs its
own buffers.)
Ordering. The axis must be defined, finite, and non-decreasing —
it becomes the index (the same contract byValue enforces with
assertMonotonicAxis), so an out-of-order axis throws by default. Pass
sort: true to sort the rows by axis value before construction — the
stable sort every unordered snapshot wants (e.g. a keyed live feed that
delivers rows in update order, not axis order).
v1 scope: number value columns, matching TimeSeries.fromColumns.
Optionalsort?: booleanSort the rows by axis value before construction (off by default), for a
payload whose rows aren't guaranteed ordered. Stable; disables the
Float64Array zero-copy adoption (columns are reordered into fresh
buffers).
ValidationError on a non-'value' axis kind, a missing column, a
length mismatch, a non-'number' value column, or an out-of-order axis
when sort is not set. Throws RangeError on a non-finite
(null/NaN/±Infinity) axis cell — sorting can't make it valid — or
a duplicate column name (the axis name repeated among the value columns).
A value-keyed series — the closed value-axis counterpart of
TimeSeries. Its key is a monotonic non-time axis (distance, cumulative work, …). Two doors in: project aTimeSeriesonto one of its monotonic columns (TimeSeries.byValue(axis)— a track re-keyed by cumulative distance), or construct directly from columnar arrays (ValueSeries.fromColumns) when the data is natively value-keyed and never had a meaningful time key per row — cross-sectional data such as an options chain keyed by strike or a spectrum keyed by frequency.ValueSeriescarries the ordering-based operators (read the axis, read value columns, nearest-by-value, slice-by-value) — the part of the series algebra that was never really about time (RFCvalue-axis.md§5). The calendar/clock operators (Sequence.every, tz formatting) are deliberately absent: a value axis has no wall-clock semantics, and the disjointValueSeriesSchemamakes them type-impossible here.Minimal by design (RFC §7: adopt the type early, grow the algebra as a second value-axis consumer earns it). Wraps the columnar store directly — a value row is an
(axis, …values)tuple, not aTime-keyedEvent, so it does not go through the time-onlySeriesStore/ EventKey layer.