Python Measurement API¶
doppler.measure.ToneMeasure analyses one time-domain capture (real or complex)
into the full single-tone ADC / spectral metric bag — SNR, SINAD, THD, THD+N,
SFDR, ENOB, noise floor and the worst spur — plus the accuracy/resolution
metadata. Each component's power is integrated over its window main lobe
(IEEE Std 1241); see the design guide for the
equations and conventions, and the
Spectral & Measurement API Map for how this
module composes with the shared PSD core.
Source:
src/doppler/measure/__init__.py
Examples¶
Single-tone metrics¶
import numpy as np
from doppler.measure import ToneMeasure
fs, n = 100e6, 1 << 14
x = np.cos(2 * np.pi * 10.017e6 * np.arange(n) / fs).astype(np.float32)
m = ToneMeasure(n=n, fs=fs) # auto Kaiser window, sized from bits/DR
r = m.analyze(x) # named ToneMetrics result
r.enob, r.sfdr_dbc, r.fund_dbfs # attribute access
snr, sinad, *_ = r # ...and tuple unpacking
ENOB of an ADC¶
from doppler.cvt import ADC
codes = ADC(12, 0.0, 0).steps(x).astype(np.float32)
m = ToneMeasure(n=n, fs=fs, bits=12) # bits sets the dBFS reference
print(round(m.analyze(codes).enob, 2)) # ≈ 12.0 for an ideal 12-bit ADC
All three analyzers take the bits (ADC depth → 2**(bits-1)) or
full_scale dBFS knob and read it back from the shared PSD
core, so bits=B is identical to full_scale=2**(B-1) — one source of truth.
Each also exposes spectrum_dbfs(x): the same averaged-PSD dBFS trace its
metrics use, for a display backdrop (no hand-rolled periodogram needed).
Complex baseband, accuracy metadata, and the spectrum¶
iq = np.exp(2j * np.pi * 13e6 * np.arange(n) / fs).astype(np.complex64)
r = m.analyze_complex(iq) # two-sided analysis
m.rbw, m.bin_hz, r.lobe_bins # resolution vs interpolation grid
spec = m.spectrum_dbfs(x) # DC-centred dBFS trace (length nfft) for plots
ts = m.time_stats(x) # crest_db / papr_db / dc_offset / fs_util_pct
Resolution vs bin spacing
m.rbw (resolution bandwidth) is derived from the un-padded length n;
m.bin_hz is the zero-padded interpolation grid. Padding sharpens the
frequency estimate and the plot, but does not improve resolution.
Two-tone IMD and notched-noise NPR¶
from doppler.measure import IMDMeasure, NPRMeasure
# Two equal tones -> IMD2/IMD3 and the third-order intercept
t = np.arange(n)
two_tone_capture = (
0.5 * np.cos(2 * np.pi * 10.0e6 * t / fs)
+ 0.5 * np.cos(2 * np.pi * 11.0e6 * t / fs)
).astype(np.float32)
imd = IMDMeasure(n=n, fs=fs)
r = imd.analyze(two_tone_capture) # r.imd3_dbc, r.toi_dbfs, ...
# Notched-noise loading -> NPR (band/notch geometry are analyze() args)
noise = np.random.randn(n).astype(np.float32)
active_lo, active_hi = 1.0e6, 40.0e6 # loaded band edges (Hz)
notch_lo, notch_hi = 19.0e6, 21.0e6 # the cleared notch (Hz)
guard_hz = 1.0e6
npr = NPRMeasure(n=n, fs=fs, bits=10)
g = npr.analyze(noise, active_lo, active_hi, notch_lo, notch_hi, guard_hz)
print(g.npr_db)
# both expose the same display-spectrum method as ToneMeasure
imd_spec = imd.spectrum_dbfs(two_tone_capture) # DC-centred dBFS, length nfft
npr_spec = npr.spectrum_dbfs(noise)
Capture planning¶
from doppler.measure import (
dp_coherent_freq,
measure_min_samples,
measure_proc_gain,
measure_rec_nfft,
)
n = measure_min_samples(
fs, target_rbw=1e3, bits=12, dynamic_range_db=0.0, complex_input=0
)
nfft = measure_rec_nfft(n, pad=2)
pg = measure_proc_gain(nfft)
f0 = dp_coherent_freq(fs, 10e6, n) # leakage-free coherent test tone
ToneMeasure
¶
Create a ToneMeasure analyser (auto Kaiser window).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n
|
int
|
Capture/frame length (>= 2). |
8192
|
fs
|
float
|
Sample rate (Hz, > 0). |
1.0
|
n_harmonics
|
int
|
Harmonics to track (k = 2..n_harmonics). |
8
|
full_scale
|
float
|
Amplitude that equals 0 dBFS (> 0). Ignored if bits > 0. |
1.0
|
bits
|
int
|
ADC depth: bits>0 sets the 0-dBFS reference to 2^(bits-1) and, unless overridden, the dynamic-range target (6.02*bits + 1.76 + headroom). |
0
|
dynamic_range_db
|
float
|
Explicit sidelobe/dynamic-range target (dB); used when > 0, else derived from bits (or a deep default when both are 0). |
0.0
|
dc_guard
|
int
|
Extra bins excluded beyond L around DC. |
0
|
Examples:
Create with defaults:
>>> from doppler.measure import ToneMeasure
>>> obj = ToneMeasure(
... n=8192,
... fs=1.0,
... n_harmonics=8,
... full_scale=1.0,
... bits=0,
... dynamic_range_db=0.0,
... dc_guard=0,
... )
reset
¶
Reset the analyser (a no-op: it holds no state between calls).
Every analyze() / analyze_complex() / time_stats() / spectrum_dbfs() call re-windows and re-transforms its own capture from scratch, so there is nothing carried between calls to clear. The method exists only so ToneMeasure honours the same reset() contract as every other doppler object, letting a generic pipeline reset each stage uniformly.
Examples:
analyze
¶
Analyze a real time-domain capture; returns a ToneMetrics result.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
float
|
Input. |
required |
Returns:
| Type | Description |
|---|---|
ToneMetrics
|
the metric record (by value). |
Examples:
>>> from doppler.measure import ToneMeasure
>>> import numpy as np
>>> n, t = 4096, np.arange(4096)
>>> # full-scale tone at 300 cycles + a 2nd harmonic 40 dB down
>>> x = (np.cos(2*np.pi*300*t/n)
... + 0.01*np.cos(2*np.pi*600*t/n)).astype(np.float32)
>>> r = ToneMeasure(n=n, fs=1.0).analyze(x)
>>> type(r).__name__
'ToneMetrics'
>>> abs(r.fund_dbfs) < 0.1, round(r.thd, 1) # 0 dBFS tone, THD -40
(True, -40.0)
analyze_complex
¶
Analyze a complex baseband capture (two-sided spectrum).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
complex
|
Input. |
required |
Returns:
| Type | Description |
|---|---|
ToneMetrics
|
Output. |
Examples:
time_stats
¶
Time-domain stats: RMS, peak, crest/PAPR, DC offset, FS utilisation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
float
|
Input. |
required |
Returns:
| Type | Description |
|---|---|
TimeStats
|
Output. |
Examples:
spectrum_dbfs
¶
DC-centred dBFS magnitude spectrum of a capture (length nfft, for plots).
The windowed, zero-padded magnitude spectrum behind the metrics, laid out DC-centred (fftshifted) and normalised to dBFS so it drops straight under an analyzer trace. Use it to eyeball where the fundamental, harmonics and spurs that analyze() quantifies actually sit.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
NDArray[float32]
|
Real time-domain capture (length x_len). |
required |
out
|
NDArray[float32] | None
|
Destination buffer (length >= max_out). |
None
|
Returns:
| Type | Description |
|---|---|
NDArray[float32]
|
DC-centred dBFS magnitude spectrum, one value per FFT bin (nfft). |
Examples:
>>> from doppler.measure import ToneMeasure
>>> import numpy as np
>>> t = np.arange(4096)
>>> x = np.cos(2*np.pi*300*t/4096).astype(np.float32) # full-scale
>>> s = ToneMeasure(n=4096, fs=1.0).spectrum_dbfs(x) # DC-centred dBFS
>>> s.shape # zero-padded to next power of two
(8192,)
>>> round(float(s.max()), 1) # two real images, ~6 dB each
-6.0
spectrum_dbfs_max_out
¶
Capacity (== nfft) of the spectrum_dbfs output buffer.
Returns:
| Type | Description |
|---|---|
int
|
Output. |
destroy
¶
Release the underlying C resources immediately.
Ordinarily unnecessary: the resources are freed when the object is garbage-collected. Call this to release them at a definite point instead, or use the object as a context manager, which calls it on exit.
Idempotent: calling it again on an already-released object does
nothing. Every other method raises RuntimeError once it has run.
__enter__
¶
Enter a context manager, returning this object.
Lets a ToneMeasure be used in a with statement so its C resources are
released deterministically on exit rather than at collection time.
Returns:
| Type | Description |
|---|---|
ToneMeasure
|
This same object, not a copy. |
__exit__
¶
__exit__(
exc_type: object | None = ...,
exc: object | None = ...,
tb: object | None = ...,
) -> None
Exit a context manager, releasing the ToneMeasure.
Equivalent to calling destroy(). Returns None, so an exception
raised inside the with body propagates normally; this never
suppresses one.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
exc_type
|
object | None
|
Exception class, or None. Ignored. |
...
|
exc
|
object | None
|
Exception instance, or None. Ignored. |
...
|
tb
|
object | None
|
Traceback object, or None. Ignored. |
...
|
TimeStats
¶
Bases: tuple[float, float, float, float, float, float]
AC-coupled time-domain capture statistics (crest factor / PAPR).
Attributes:
| Name | Type | Description |
|---|---|---|
rms |
float
|
Root-mean-square amplitude (DC included). |
peak |
float
|
Peak deviation, max|x - DC|. |
crest_db |
float
|
Crest factor, 20log10(peak_ac / rms_ac) (dB). |
papr_db |
float
|
Peak-to-average power ratio (= crest) (dB). |
dc_offset |
float
|
DC offset, mean(x). |
fs_util_pct |
float
|
Full-scale use, 100*max|x|/full_scale (%). |
IMDMeasure
¶
Create an IMDMeasure analyser (auto Kaiser window).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n
|
int
|
Capture/frame length (>= 2). |
8192
|
fs
|
float
|
Sample rate (Hz, > 0). |
1.0
|
full_scale
|
float
|
Amplitude that equals 0 dBFS (> 0). Ignored if bits > 0. |
1.0
|
bits
|
int
|
ADC depth: bits>0 sets the 0-dBFS reference to 2^(bits-1) and, unless overridden, the dynamic-range target. |
0
|
dynamic_range_db
|
float
|
Explicit sidelobe/dynamic-range target (dB); used when > 0, else derived from bits. |
0.0
|
Examples:
Create with defaults:
>>> from doppler.measure import IMDMeasure
>>> obj = IMDMeasure(
... n=8192,
... fs=1.0,
... full_scale=1.0,
... bits=0,
... dynamic_range_db=0.0,
... )
reset
¶
Reset the analyser (a no-op: each analyze() call is independent).
Every analyze() / spectrum_dbfs() call re-windows and re-transforms its own capture from scratch, so nothing is carried between calls to clear. The method exists only so IMDMeasure honours the same reset() contract as every other doppler object, letting a generic pipeline reset each stage uniformly.
Examples:
analyze
¶
Two-tone IMD/TOI of a real capture (finds the two strongest tones).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
float
|
Input. |
required |
Returns:
| Type | Description |
|---|---|
IMDMetrics
|
the IMD metric record (by value; zeroed if no two tones are found). |
Examples:
>>> from doppler.measure import IMDMeasure
>>> import numpy as np
>>> t = np.arange(4096)
>>> # two equal tones at 200 & 250 cycles, plus 3rd-order
>>> # products 40 dB down
>>> x = (np.cos(2*np.pi*200*t/4096) + np.cos(2*np.pi*250*t/4096)
... + 0.01*np.cos(2*np.pi*150*t/4096)
... + 0.01*np.cos(2*np.pi*300*t/4096)).astype(np.float32)
>>> r = IMDMeasure(n=4096, fs=1.0).analyze(x)
>>> round(r.f1, 4), round(r.f2, 4), round(r.imd3_dbc, 0)
(0.0488, 0.061, -40.0)
spectrum_dbfs
¶
DC-centred dBFS magnitude spectrum of a capture (length nfft, for plots).
The same windowed, zero-padded PSD the IMD metrics are read off, laid out DC-centred (fftshifted) and normalised to dBFS for an analyzer-display backdrop. Use it to see the two fundamentals and the intermodulation products that analyze() integrates.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
NDArray[float32]
|
Real time-domain capture (length x_len). |
required |
out
|
NDArray[float32] | None
|
Destination buffer (length >= max_out). |
None
|
Returns:
| Type | Description |
|---|---|
NDArray[float32]
|
DC-centred dBFS magnitude spectrum, one value per FFT bin (nfft). |
Examples:
>>> from doppler.measure import IMDMeasure
>>> import numpy as np
>>> t = np.arange(4096)
>>> x = (0.5*np.cos(2*np.pi*200*t/4096)
... + 0.5*np.cos(2*np.pi*250*t/4096)).astype(np.float32)
>>> s = IMDMeasure(n=4096, fs=1.0).spectrum_dbfs(x) # DC-centred dBFS
>>> s.shape
(8192,)
>>> round(float(s.max()), 1) # each tone splits into two images
-12.0
spectrum_dbfs_max_out
¶
Capacity (== nfft) of the spectrum_dbfs output buffer.
Returns:
| Type | Description |
|---|---|
int
|
Output. |
destroy
¶
Release the underlying C resources immediately.
Ordinarily unnecessary: the resources are freed when the object is garbage-collected. Call this to release them at a definite point instead, or use the object as a context manager, which calls it on exit.
Idempotent: calling it again on an already-released object does
nothing. Every other method raises RuntimeError once it has run.
__enter__
¶
Enter a context manager, returning this object.
Lets a IMDMeasure be used in a with statement so its C resources are
released deterministically on exit rather than at collection time.
Returns:
| Type | Description |
|---|---|
IMDMeasure
|
This same object, not a copy. |
__exit__
¶
__exit__(
exc_type: object | None = ...,
exc: object | None = ...,
tb: object | None = ...,
) -> None
Exit a context manager, releasing the IMDMeasure.
Equivalent to calling destroy(). Returns None, so an exception
raised inside the with body propagates normally; this never
suppresses one.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
exc_type
|
object | None
|
Exception class, or None. Ignored. |
...
|
exc
|
object | None
|
Exception instance, or None. Ignored. |
...
|
tb
|
object | None
|
Traceback object, or None. Ignored. |
...
|
IMDMetrics
¶
Bases: tuple[float, float, float, float, float, float, float, float, float, float, float, float]
Two-tone intermodulation metrics (IMD2, IMD3, second/third-order intercepts).
Attributes:
| Name | Type | Description |
|---|---|---|
f1 |
float
|
Lower tone frequency (Hz). |
f2 |
float
|
Upper tone frequency (Hz). |
p1_dbfs |
float
|
Lower tone level (dBFS). |
p2_dbfs |
float
|
Upper tone level (dBFS). |
imd2_dbc |
float
|
2nd-order product (f2-f1) vs mean tone (dBc). |
imd3_dbc |
float
|
Worst 3rd-order product vs mean tone (dBc). |
imd2_freq |
float
|
2nd-order product frequency (Hz). |
imd3_lo_freq |
float
|
3rd-order (2f1-f2) product frequency (Hz). |
imd3_hi_freq |
float
|
3rd-order (2f2-f1) product frequency (Hz). |
toi_dbfs |
float
|
Third-order intercept (dBFS). |
soi_dbfs |
float
|
Second-order intercept (dBFS). |
rbw_hz |
float
|
Resolution bandwidth = enbw*fs/n (Hz). |
NPRMeasure
¶
Create an NPRMeasure analyser (auto Kaiser window).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n
|
int
|
Capture/frame length (>= 2). |
8192
|
fs
|
float
|
Sample rate (Hz, > 0). |
1.0
|
full_scale
|
float
|
Amplitude that equals 0 dBFS (> 0). Ignored if bits > 0. |
1.0
|
bits
|
int
|
ADC depth: bits>0 sets the 0-dBFS reference to 2^(bits-1) and, unless overridden, the dynamic-range target. |
0
|
dynamic_range_db
|
float
|
Explicit sidelobe/dynamic-range target (dB); used when > 0, else derived from bits. |
0.0
|
Examples:
Create with defaults:
>>> from doppler.measure import NPRMeasure
>>> obj = NPRMeasure(
... n=8192,
... fs=1.0,
... full_scale=1.0,
... bits=0,
... dynamic_range_db=0.0,
... )
reset
¶
Reset the analyser (a no-op: each analyze() call is independent).
Every analyze() / spectrum_dbfs() call re-windows and re-transforms its own capture from scratch, so nothing is carried between calls to clear. The method exists only so NPRMeasure honours the same reset() contract as every other doppler object, letting a generic pipeline reset each stage uniformly.
Examples:
analyze
¶
analyze(
x: float,
active_lo: float,
active_hi: float,
notch_lo: float,
notch_hi: float,
guard_hz: float = 0.0,
) -> NPRMetrics
NPR of a notched-noise capture over [active_lo,active_hi] with a notch [notch_lo,notch_hi] (Hz) and guard keep-out.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
float
|
Real time-domain capture. |
required |
active_lo
|
float
|
Active noise band lower edge (Hz). |
required |
active_hi
|
float
|
Active noise band upper edge (Hz). |
required |
notch_lo
|
float
|
Notch lower edge (Hz). |
required |
notch_hi
|
float
|
Notch upper edge (Hz). |
required |
guard_hz
|
float
|
Keep-out around the notch edges (Hz). |
0.0
|
Returns:
| Type | Description |
|---|---|
NPRMetrics
|
the NPR metric record (by value). |
Examples:
>>> from doppler.measure import NPRMeasure
>>> import numpy as np
>>> rng = np.random.default_rng(0)
>>> n = 1 << 15
>>> F = np.fft.rfft(rng.standard_normal(n))
>>> f = np.fft.rfftfreq(n)
>>> F[(f < 0.05) | (f > 0.45)] = 0 # band-limit to [0.05,0.45]
>>> F[(f >= 0.20) & (f <= 0.25)] *= 10**(-50/20) # notch 50 dB deep
>>> x = np.fft.irfft(F, n)
>>> x = (0.3*x/np.std(x)).astype(np.float32)
>>> r = NPRMeasure(n=n, fs=1.0).analyze(
... x, 0.05, 0.45, 0.20, 0.25, 0.01)
>>> 45 < r.npr_db < 55, r.notch_psd_dbfs < r.inband_psd_dbfs
(True, True)
spectrum_dbfs
¶
DC-centred dBFS magnitude spectrum of a capture (length nfft, for plots).
The same windowed, zero-padded PSD the NPR metrics are read off, laid out DC-centred (fftshifted) and normalised to dBFS for an analyzer-display backdrop. Use it to see the notch and the active band that analyze() integrates over.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
NDArray[float32]
|
Real time-domain capture (length x_len). |
required |
out
|
NDArray[float32] | None
|
Destination buffer (length >= max_out). |
None
|
Returns:
| Type | Description |
|---|---|
NDArray[float32]
|
DC-centred dBFS magnitude spectrum, one value per FFT bin (nfft). |
Examples:
>>> from doppler.measure import NPRMeasure
>>> import numpy as np
>>> rng = np.random.default_rng(0)
>>> x = (0.3*rng.standard_normal(8192)).astype(np.float32) # noise
>>> s = NPRMeasure(n=8192, fs=1.0).spectrum_dbfs(x) # DC-centred dBFS
>>> s.shape # zero-padded nfft
(16384,)
>>> round(float(np.median(s)), 0) # broadband floor, below 0 dBFS
-48.0
spectrum_dbfs_max_out
¶
Capacity (== nfft) of the spectrum_dbfs output buffer.
Returns:
| Type | Description |
|---|---|
int
|
Output. |
destroy
¶
Release the underlying C resources immediately.
Ordinarily unnecessary: the resources are freed when the object is garbage-collected. Call this to release them at a definite point instead, or use the object as a context manager, which calls it on exit.
Idempotent: calling it again on an already-released object does
nothing. Every other method raises RuntimeError once it has run.
__enter__
¶
Enter a context manager, returning this object.
Lets a NPRMeasure be used in a with statement so its C resources are
released deterministically on exit rather than at collection time.
Returns:
| Type | Description |
|---|---|
NPRMeasure
|
This same object, not a copy. |
__exit__
¶
__exit__(
exc_type: object | None = ...,
exc: object | None = ...,
tb: object | None = ...,
) -> None
Exit a context manager, releasing the NPRMeasure.
Equivalent to calling destroy(). Returns None, so an exception
raised inside the with body propagates normally; this never
suppresses one.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
exc_type
|
object | None
|
Exception class, or None. Ignored. |
...
|
exc
|
object | None
|
Exception instance, or None. Ignored. |
...
|
tb
|
object | None
|
Traceback object, or None. Ignored. |
...
|
NPRMetrics
¶
Bases: tuple[float, float, float, int, int, float]
Noise-power-ratio metrics from a notched-noise-loading test.
Attributes:
| Name | Type | Description |
|---|---|---|
npr_db |
float
|
NPR = 10log10(in-band PSD / notch PSD) (dB). |
inband_psd_dbfs |
float
|
Mean in-band noise power per bin (dBFS). |
notch_psd_dbfs |
float
|
Mean power folded into the notch (dBFS). |
n_inband_bins |
int
|
Bins averaged in the active band. |
n_notch_bins |
int
|
Bins averaged inside the notch. |
rbw_hz |
float
|
Resolution bandwidth = enbw*fs/n (Hz). |
measure_min_samples
¶
measure_min_samples(
fs: float,
target_rbw: float,
bits: int,
dynamic_range_db: float,
complex_input: int,
) -> int
Samples for a target RBW (auto Kaiser from bits/dynamic_range_db; target_rbw<=0 -> span/1000).
Plans a capture for the same auto-Kaiser window the measurement objects use: the dynamic-range target (from dynamic_range_db, else bits) selects the Kaiser beta, whose ENBW (measured via kaiser_enbw) sets the bins-per-RBW. RBW = ENBW * fs / n, so n = ceil(ENBW * fs / target_rbw).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fs
|
float
|
Sample rate (Hz, > 0). |
required |
target_rbw
|
float
|
Desired resolution bandwidth (Hz). When <= 0 it defaults to span/1000, where span = fs/2 for real captures and fs for complex (complex_input). |
required |
bits
|
int
|
ADC depth: sets the dynamic-range target when no explicit override is given. |
required |
dynamic_range_db
|
float
|
Explicit dynamic-range target (dB); used when > 0. |
required |
complex_input
|
int
|
Non-zero if the capture is complex (span = fs). |
required |
Returns:
| Type | Description |
|---|---|
int
|
Required capture length, or 0 on bad args. |
measure_rec_nfft
¶
Recommended zero-padded transform length: next_pow2(n * pad).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n
|
int
|
Input. |
required |
pad
|
int
|
Input. |
required |
Returns:
| Type | Description |
|---|---|
int
|
Output. |
measure_proc_gain
¶
FFT processing gain in dB: 10*log10(nfft / 2).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
nfft
|
int
|
Input. |
required |
Returns:
| Type | Description |
|---|---|
float
|
Output. |
dp_coherent_freq
¶
Nearest leakage-free coherent test frequency (J cycles, J coprime N).
Snaps f_target to J * fs / N where J is the nearest integer cycle
count that is coprime with N — an integer number of cycles in the
capture (no leakage) with J coprime to N (so quantisation-noise
correlation is minimised).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fs
|
float
|
Input. |
required |
f_target
|
float
|
Input. |
required |
N
|
int
|
Input. |
required |
Returns:
| Type | Description |
|---|---|
float
|
The coherent frequency (Hz), or 0 on bad args. |
Related pages¶
Gallery — Gallery, Measurement Suite — two-tone IMD/TOI & notched-noise NPR, Measurement Suite — ADC characterisation Guides — Power Spectra & Measurements Design — API taxonomy: the DSP building-block hierarchy and its naming axis, Measurement Suite — single-tone ADC / spectral metrics, Spectral & Measurement API Map