Skip to content

`harmos-signal`

This crate is the shared mathematics of measurement: the transform between a signal's two domains, the readings taken off each, the reductions that fit a long capture into a short display, and one mergeable fold of a run of samples.

It is kernels rather than containers. Every function takes the slices a caller already has and answers a value, a Vec, or the indices it selected, so two applications with two different series types share one implementation. Nothing here owns, shares, locks, or caches anything.

It depends on rustfft and std. It does not depend on harmos, and it must not: the runtime's read path stays algorithm-free, and this crate stays liftable into a repository of its own unchanged.

Thirty-eight names, counted by crates/harmos-signal/tests/census.rs.

The frequency domain:

The time domain:

A caller hands transform its samples and a sampling rate and receives a Spectrum: a bin step and two columns, normalized so a tone landing on a bin reads its own amplitude whichever taper measured it. reconstruct undoes exactly that normalization, so a transform and its reconstruction return the samples — and scaling the bins by a Band on the way through is how a band-limited copy is produced without designing a filter. Welch runs the same transform over overlapping segments and averages their power, which buys a quieter estimate and spends the phase.

Every reading takes slices. A reducer answers the indices it selected, so the caller gathers whichever of its own columns it keeps and reducers compose by mapping one answer through the next. Summary is the only accumulator, and it merges: the summary of two runs is a function of their two summaries, never of their samples.

  • Kernels take slices and never a container; a caller's own series type is never converted to call one.
  • Spectrum is a transparent record — public fields, no identity, no cache — and exists because a transform must answer something, not to own data.
  • A reduction answers indices. Values would pick which columns matter, and the caller is the one that knows.
  • An averaged estimate carries no phase. Welch's method discards it, and a spectrum with an invented zero imaginary part would reconstruct to something that was never measured.
  • Degenerate input answers an empty or absent result. The crate has no error type, and therefore no error dependency.
  • Statistics merge or they are not here: Summary carries the accumulators harmos's Bucket carries, and its variance is Welford's rather than the difference of two large sums.

This crate is measurement math, not a data engine. The test for anything proposed for it: does it compute a property of a signal — a spectrum, an envelope, a crossing, a reduction, a calibrated conversion — or does it arrange data? Tables, joins, group-by, lazy pipelines, generic aggregation frameworks, and columnar containers are a DataFrame's work, which meti left behind to arrive at exactly this content; an application needing relational row manipulation reaches for a DataFrame of its own, above the runtime's algorithm-free reads.

Interpolation is linear and clamps outside the sampled span. Statistics that cannot merge — medians and percentiles — are deliberately absent, as they are from the accumulators of harmos's served tier. There is no filter design, no resampling that band-limits, and no window overlap-add.

Stokker Technologies markDesigned and built by Stokker Technologies