analyze_error_by_phase
Overview
analyze_error_by_phase performs AM/PM (Amplitude Modulation / Phase Modulation) decomposition of ADC errors as a function of the input signal phase. This reveals whether errors are signal-dependent and whether they modulate the amplitude (AM) or timing/phase (PM) of the signal.
Syntax
from adctoolbox import analyze_error_by_phase
# Basic usage with auto-detected frequency
result = analyze_error_by_phase(signal, show_plot=True)
# With specified frequency
result = analyze_error_by_phase(signal, norm_freq=0.123, n_bins=100,
show_plot=True)
# Exclude base noise term
result = analyze_error_by_phase(signal, include_base_noise=False,
show_plot=True)
Parameters
signal(array_like) — Input ADC signal (sine wave excitation)norm_freq(float, optional) — Normalized frequency (f/fs), range (0, 0.5)If None: auto-detected via FFT
n_bins(int, default=100) — Number of phase bins for visualizationinclude_base_noise(bool, default=True) — Include base noise term in fittingshow_plot(bool, default=True) — Display error vs. phase plotaxes(tuple, optional) — Tuple of (ax1, ax2) for top and bottom panelsax(matplotlib axis, optional) — Single axis to split into 2 panelstitle(str, optional) — Test setup description for title
Returns
Dictionary containing:
Numerical Results:
am_noise_rms_v— AM noise RMS (amplitude modulation)pm_noise_rms_v— PM noise RMS in voltage unitspm_noise_rms_rad— PM noise RMS in radiansbase_noise_rms_v— Base noise RMS (signal-independent)total_rms_v— Total error RMS
Validation Metrics:
r_squared_raw— R² for raw data fit (energy ratio)r_squared_binned— R² for binned data (model confidence)
Visualization Data:
bin_error_rms_v— RMS error per phase binbin_error_mean_v— Mean error per phase binphase_bin_centers_rad— Phase bin centers (radians)
Metadata:
amplitude,dc_offset,norm_freq— Fitted signal parametersfitted_signal,error,phase— Signal decomposition
Algorithm
AM/PM Model
Error is decomposed as:
error(φ) = AM·sin(φ) + PM·cos(φ) + base_noise
where:
AM: Amplitude modulation error (gain variation with signal level)
PM: Phase modulation error (timing jitter, settling errors)
base_noise: Signal-independent noise
φ: Signal phase
Dual-Track Analysis
Path A (Raw): Fit all N samples → highest precision AM/PM values Path B (Binned): Compute binned statistics → visualization
Cross-validation: Path A coefficients predict Path B trend → R² metric
Examples
Example 1: AM/PM Decomposition
import numpy as np
from adctoolbox import analyze_error_by_phase
# Analyze ADC signal
result = analyze_error_by_phase(adc_signal, show_plot=True)
print(f"AM noise: {result['am_noise_rms_v']*1e6:.2f} µV RMS")
print(f"PM noise: {result['pm_noise_rms_rad']*1e12:.2f} pico-radians RMS")
print(f"Base noise: {result['base_noise_rms_v']*1e6:.2f} µV RMS")
print(f"Total RMS: {result['total_rms_v']*1e6:.2f} µV RMS")
print(f"R² (model fit): {result['r_squared_raw']:.4f}")
Example 2: Identify Dominant Error Mechanism
result = analyze_error_by_phase(signal, show_plot=False)
am = result['am_noise_rms_v']
pm = result['pm_noise_rms_v']
base = result['base_noise_rms_v']
# Determine dominant error source
errors = {'AM': am, 'PM': pm, 'Base': base}
dominant = max(errors, key=errors.get)
print(f"Dominant error: {dominant}")
print(f" AM: {am*1e6:.2f} µV ({am/result['total_rms_v']*100:.1f}%)")
print(f" PM: {pm*1e6:.2f} µV ({pm/result['total_rms_v']*100:.1f}%)")
print(f" Base: {base*1e6:.2f} µV ({base/result['total_rms_v']*100:.1f}%)")
Example 3: Compare Multiple Conditions
import matplotlib.pyplot as plt
conditions = {
'Ideal': signal_ideal,
'With Jitter': signal_jitter,
'With Gain Error': signal_gain_error,
}
fig, axes = plt.subplots(len(conditions), 2, figsize=(12, 4*len(conditions)))
for i, (name, sig) in enumerate(conditions.items()):
result = analyze_error_by_phase(sig, axes=axes[i], title=name,
show_plot=True)
print(f"{name}: AM={result['am_noise_rms_v']*1e6:.1f}µV, "
f"PM={result['pm_noise_rms_rad']*1e12:.1f}pRad")
plt.tight_layout()
plt.show()
Interpretation
Error Type Classification
Dominant Component |
Likely Cause |
|---|---|
AM dominant |
Gain error, amplitude-dependent distortion, residue amplifier gain variation |
PM dominant |
Clock jitter, timing errors, settling time issues |
Base noise dominant |
Thermal noise, quantization noise (signal-independent) |
AM ≈ PM |
Mixed analog impairments |
Phase Pattern Analysis
Error vs. Phase Pattern |
Interpretation |
|---|---|
Sinusoidal (AM-like) |
Amplitude-dependent error |
Cosinusoidal (PM-like) |
Timing/phase-dependent error |
Flat (uniform) |
Signal-independent noise |
Complex shape |
Multiple error mechanisms |
R² Interpretation
R² > 0.9: Model fits well, errors are signal-dependent
0.5 < R² < 0.9: Moderate signal dependence
R² < 0.5: Errors mostly signal-independent (random noise)
Use Cases
Distinguish jitter from amplitude errors
Identify memory effects in pipelined ADCs
Validate settling time in SAR ADCs
Characterize residue amplifier gain variations
Debug clock quality (PM noise indicates jitter)
Common Patterns
Pipelined ADC
High AM → Residue amplifier gain error
High PM → Inadequate settling time
SAR ADC
High AM → DAC mismatch, reference variation
High PM → Comparator metastability
Flash ADC
Low AM, low PM → Good performance
High base noise → Comparator noise
See Also
analyze_error_by_value— Error vs. ADC codeanalyze_error_pdf— Error distributionanalyze_error_autocorr— Temporal correlation
References
IEEE Std 1241-2010, “IEEE Standard for Terminology and Test Methods for ADCs”
M. Soudan et al., “A Novel AM-PM-Jitter Decomposition Method for Characterizing ADC Nonidealities,” IEEE Trans. IM, 2008