Signal Tools

Digital signal processing for any numeric series β€” no LLM, no credits, fully deterministic.

Signal tools operate entirely in-process. There are no external calls, no AI generation, and no credit cost. The transforms (fft, ifft, spectral) run in a native Rust NIF (rustfft, O(n log n)); filter and convolve are pure Elixir. Every response includes a deterministic receipt under _meta.datagrout, and outputs carry both values and records so results drop straight into prism.chart / prism.refract. All Signal tools are available at data-grout@1/signal.*@1.

Binary payload input

Alongside JSON arrays, every numeric input X also accepts X_b64 β€” a base64 string of packed little-endian IEEE-754 floats. The dtype argument selects float64 (default, 8 bytes) or float32 (4 bytes). This is a compact, exact alternative for large signals that avoids a giant JSON array. An explicit JSON array under X always wins over X_b64.

The suite covers two areas:

  • Transforms: fft, ifft, spectral β€” move between the time and frequency domains and read off the spectrum.
  • Filtering: filter, convolve β€” isolate or remove frequency bands, smooth, and apply custom kernels.

Signal inputs resolve from explicit arguments (data/real/imag/a/b) or from payload/cache_ref, so you can pipe a series from a Data/Frame tool directly in.

Frequency conventions

Cutoff frequencies for filter are normalized to the sample rate, in the range (0, 0.5], where 0.5 is the Nyquist frequency. If you have a real sample rate fs, pass cutoff = f_hz / fs. spectral and fft accept a sample_rate (Hz) and report each bin’s freq in Hz; with the default sample_rate of 1.0, frequencies are in cycles/sample.


signal.fft@1

Forward Fast Fourier Transform of a real or complex signal (native, rustfft, O(n log n)). Returns the complex spectrum (real, imag), magnitude, phase, and β€” with sample_rate β€” per-bin freq, plus a records list. Set one_sided: true to return only bins 0..n/2 (the non-redundant half for real input). Max 1,048,576 samples.

Parameters

Parameter Type Required Description
data number[] one of Real signal samples
real / imag number[] one of Explicit real/imaginary parts (imag defaults to zeros)
sample_rate number no Sampling rate (Hz) for per-bin frequency
one_sided boolean no Return only bins 0..n/2 (default false)

Example

{
  "name": "data-grout@1/signal.fft@1",
  "arguments": { "data": "$sensor.readings", "sample_rate": 1000, "one_sided": true }
}

Response: { "n": 1024, "real": [...], "imag": [...], "magnitude": [...], "phase": [...], "records": [{ "index": 4, "freq": 3.9, "magnitude": 512.0, ... }] }.


signal.ifft@1

Inverse FFT (native, rustfft). Reconstructs a time/space-domain signal from a complex spectrum, normalized by 1/n so ifft(fft(x)) == x. Returns the complex output (real, imag) and, as values, the real part β€” the recovered signal for spectra that came from real input. Max 1,048,576 bins.

Parameters

Parameter Type Required Description
real number[] yes Real part of the spectrum
imag number[] no Imaginary part (defaults to zeros)

Example

{
  "name": "data-grout@1/signal.ifft@1",
  "arguments": { "real": "$fft.real", "imag": "$fft.imag" }
}

Response: { "n": 8, "values": [3, 1, 4, 1, 5, 9, 2, 6], "real": [...], "imag": [...] }.


signal.spectral@1

One-sided power spectrum of a real signal, computed via the native FFT (O(n log n)). Returns, per frequency bin, the freq, magnitude, power, and phase, plus the top peaks (excluding DC) and the dominant_frequency. An optional window (hann / hamming) reduces spectral leakage. Max 1,048,576 samples.

Parameters

Parameter Type Required Default Description
data number[] yes – Real signal samples (or via payload/cache_ref)
sample_rate number no 1.0 Sampling rate (Hz); default reports cycles/sample
window string no none none | hann | hamming
top_peaks integer no 5 Number of spectral peaks to return

Example

{
  "name": "data-grout@1/signal.spectral@1",
  "arguments": { "data": "$sensor.readings", "sample_rate": 1000, "window": "hann" }
}

Response: { "n": 512, "dominant_frequency": 60.0, "peaks": [{ "freq": 60.0, "power": 812.4, ... }], "records": [...] }.


signal.filter@1

FIR frequency filter built from a windowed-sinc kernel (Hamming window), convolved with the signal to give a same-length, phase-delay-corrected output. Types: lowpass, highpass, bandpass, bandstop. lowpass/highpass take a single cutoff; bandpass/bandstop take low and high. All cutoffs are normalized to (0, 0.5]. Max 100,000 samples, 2,001 taps.

Parameters

Parameter Type Required Default Description
data number[] yes – Input signal samples
type string yes – lowpass | highpass | bandpass | bandstop
cutoff number low/high – Normalized cutoff for lowpass/highpass
low, high number band – Normalized band edges (low < high)
num_taps integer no 51 FIR kernel length (forced odd); higher = sharper transition

Example

{
  "name": "data-grout@1/signal.filter@1",
  "arguments": { "data": "$sensor.readings", "type": "lowpass", "cutoff": 0.05 }
}

Response: { "values": [...], "records": [...], "count": 1000, "type": "lowpass", "num_taps": 51 }.


signal.convolve@1

Discrete convolution of two numeric sequences (a * b). Modes: full (length len(a)+len(b)-1, default), same (length len(a), centered), valid (overlap only). Useful for smoothing, feature detection, and applying custom kernels. Max 50,000 per input (and ≀ 5,000,000 total operations).

Parameters

Parameter Type Required Default Description
a number[] yes – First sequence (the signal)
b number[] yes – Second sequence (the kernel)
mode string no full full | same | valid

Example

{
  "name": "data-grout@1/signal.convolve@1",
  "arguments": { "a": [1, 2, 3], "b": [0, 1, 0.5], "mode": "full" }
}

Response: { "values": [0, 1, 2.5, 4, 1.5], "records": [...], "count": 5, "mode": "full" }.



signal.correlate@1

Cross-correlation of two sequences by lag β€” the DSP sliding dot-product, not the Pearson coefficient (that’s math.correlate). Omit b and it defaults to a, giving the auto-correlation (peaks away from lag 0 mark repeat intervals β€” periodicity detection). Set normalize: true to scale by the signal energies so values fall in [-1, 1] (auto-correlation is then 1.0 at lag 0). Modes: full (default), same, valid. Returns values, {lag, value} records, and the peak_lag. Max 50,000 per input.

Parameters

Parameter Type Required Default Description
a number[] yes – First sequence
b number[] no a Second sequence; omit for auto-correlation
mode string no full full | same | valid
normalize boolean no false Scale to [-1, 1] by signal energies

Example

{
  "name": "data-grout@1/signal.correlate@1",
  "arguments": { "a": "$sensor.readings", "normalize": true }
}

Response: { "values": [...], "records": [{ "lag": -6, "value": 0.12 }, ...], "peak_lag": 0, "count": 13 }.


Composition

Pull a series through Data / Frame tools, transform it here, then chart the spectrum or waveform with Prism Chart β€” the records (frequency, magnitude, phase) and filtered values are chart-ready. Pair with Math for descriptive statistics on the magnitudes, or with Linalg when spectral features feed clustering or similarity. A common pipeline is fft β†’ edit the spectrum β†’ ifft for frequency-domain processing.