Spectral & Measurement API Map¶
How doppler's spectral surface fits together after the
time -> one PSD core -> measurements/display re-architecture: a single
averaging-PSD core (spectral.PSD) produces every spectrum, and the dBFS
reference is defined exactly once, in that core.
Core data flow¶
%%{init: {'themeVariables': {'fontSize': '24px'}, 'flowchart': {'subGraphTitleMargin': {'top': 8, 'bottom': 16}}}%%
flowchart TD
T["time-domain capture<br/>(cf32 / f32)"] --> W
subgraph CORE["doppler.spectral.PSD — THE averaging-PSD core"]
W["window → zero-pad FFT → |X|²/cg² → average<br/><b>bits / full_scale = 0-dBFS reference</b>"]
end
W -->|linear power<br/>power_twosided / power_onesided| TM
W --> IMD
W --> NPR
W --> SA
TM["measure.ToneMeasure<br/>bits / full_scale<br/>spectrum_dbfs()"]
IMD["measure.IMDMeasure<br/>bits / full_scale<br/>spectrum_dbfs()"]
NPR["measure.NPRMeasure<br/>bits / full_scale<br/>spectrum_dbfs()"]
SA["analyzer.Specan (streaming display)<br/>DDC tune+decimate → PSD → dBFS<br/>bits / full_scale + additive offset_db"]
classDef ok stroke:#16a34a,stroke-width:3px;
class TM,IMD,NPR,SA ok;
The dBFS reference — one source of truth¶
bits is the ergonomic ADC knob: bits>0 sets full_scale = 2**(bits-1) in
psd_create, the only place that conversion lives. full_scale remains the
analog/general alternative. Every consumer forwards bits/full_scale into its
PSD and reads the resolved reference back as psd->full_scale — none of them
re-derive it.
| API | dBFS knob | display-spectrum method | notes |
|---|---|---|---|
spectral.PSD |
bits / full_scale |
psd_db / psd_dbhz |
the core; bits resolves to full_scale here, once |
measure.ToneMeasure |
bits / full_scale |
spectrum_dbfs(x) |
reads psd->full_scale in the metric kernels |
measure.IMDMeasure |
bits / full_scale |
spectrum_dbfs(x) |
same |
measure.NPRMeasure |
bits / full_scale |
spectrum_dbfs(x) |
same |
analyzer.Specan |
bits / full_scale |
execute() -> dBFS |
offset_db is an additive offset on top of dBFS (e.g. dBm) |
bits=B is byte-identical to full_scale=2**(B-1) everywhere.
Demos are doppler-native¶
The measure_demo.py / measure_imd_npr_demo.py gallery demos drive the
analyzers with bits=, draw their spectrum backdrop from the analyzer's own
spectrum_dbfs() (no hand-rolled periodogram), generate tones with source.LO,
noise with source.AWGN, transform with spectral.FFT, and quantise with
cvt.ADC. Only the device-under-test models that have no doppler primitive stay
explicit numpy — the two-tone polynomial nonlinearity, the notch band-mask
geometry, and the analytic Gray-Zeoli / MT-005 NPR reference curve — and they are
labelled as such.