Validation: rx_frontend/phase_noise_iq¶
Validated with documented limitations.
1. The component¶
rx_frontend/phase_noise_iq contains three independent hardware-impairment surfaces for the receiver side of a software-defined radio (SDR: a radio whose signal processing is done in software after digitization):
LeesonRXPhaseNoise: multiplies the downconverted complex baseband byexp(j * phi[n]), wherephi[n]is a random phase trajectory whose power spectrum (how signal energy is distributed across frequency) follows the three-region Leeson model (a standard oscillator noise model).TorchSigRXIQImbalance: applies a static differential gain and phase mismatch between the I and Q channels (the two 90-degree-separated components of a complex baseband signal) of a quadrature demodulator.TorchSigImpairments: an opt-in compatibility adapter that invokes explicitly configured public TorchSig 2.1.1 transforms on a single-receiver IQ buffer. Itslevelvalue probes the public bundled-constructor signature only and is nonsemantic.
Class signatures¶
class LeesonRXPhaseNoise(BaseRXPhaseNoise):
def __init__(
self,
*,
psd_floor_dbc_hz: float = -100.0,
fc_hz: float = 1e4,
flicker_corner_hz: float = 1e3,
) -> None: ...
def apply(self, signal: Signal, ctx: ChannelContext) -> Signal: ...
class TorchSigRXIQImbalance(BaseRXIQImbalance):
def __init__(
self,
*,
amplitude_imbalance_db: float = 0.0,
phase_imbalance_rad: float = 0.0,
) -> None: ...
def apply(self, signal: Signal, ctx: ChannelContext) -> Signal: ...
class TorchSigImpairments(BaseChannel):
def __init__(self, config: TorchSigImpairmentsConfig) -> None: ...
def apply(self, signal: Signal, ctx: ChannelContext) -> Signal: ...
Parameter table¶
Parameter |
Type |
Units |
Default |
Purpose |
|---|---|---|---|---|
|
|
dBc/Hz |
-100.0 |
Far-from-carrier phase-noise floor; dBc/Hz means decibels below the carrier per unit bandwidth |
|
|
Hz |
1e4 |
Leeson resonator corner: offset frequency below which noise rises as 1/f² |
|
|
Hz |
1e3 |
Flicker (1/f) corner: offset frequency below which noise rises as 1/f³ |
|
|
dB |
0.0 |
Gain difference between I and Q ADC channels |
|
|
rad |
0.0 |
Phase difference between I and Q demodulator paths |
Worked example¶
import torch
from rfgen.core_types import Signal, SignalMetadata
from rfgen.channels.protocols import ChannelContext, ChannelRxParams
from rfgen.rx_frontend import LeesonRXPhaseNoise, TorchSigRXIQImbalance
# Build a 1024-sample unit-amplitude signal
n = 1024
iq = torch.stack([torch.ones(n), torch.zeros(n)])
md = SignalMetadata(
family="comms", class_name="cw", class_taxonomy=("comms", "cw"),
generator_name="demo", device_id="dev0",
sample_rate_hz=1e6, bandwidth_hz=1e3, realized_carrier_hz=2.4e9,
start_sample=0, duration_samples=n, snr_db=float("inf"), extras={},
)
sig = Signal(iq=iq, metadata=md)
rng = torch.Generator(); rng.manual_seed(42)
ctx = ChannelContext(
emitter_meta=md,
rx_params=ChannelRxParams(center_freq_hz=2.4e9, bandwidth_hz=1e6,
sample_rate_hz=1e6, noise_figure_db=6.0),
scene_id="demo", sample_idx=0, rng=rng,
)
# Apply phase noise then IQ imbalance
pn_out = LeesonRXPhaseNoise(psd_floor_dbc_hz=-110.0, fc_hz=1e4).apply(sig, ctx)
# pn_out.iq.shape == (2, 1024), dtype float32
rng2 = torch.Generator(); rng2.manual_seed(0)
ctx2 = ChannelContext(emitter_meta=md,
rx_params=ChannelRxParams(center_freq_hz=2.4e9, bandwidth_hz=1e6,
sample_rate_hz=1e6, noise_figure_db=6.0),
scene_id="demo", sample_idx=0, rng=rng2)
iq_out = TorchSigRXIQImbalance(amplitude_imbalance_db=1.0,
phase_imbalance_rad=0.05).apply(sig, ctx2)
# iq_out.iq.shape == (2, 1024), dtype float32
Taxonomy and scope¶
LeesonRXPhaseNoise sits in Group.RX_HARDWARE and models a stationary, spectrally-shaped phase perturbation from a local oscillator (LO: the reference frequency source used to downconvert the received signal to baseband). It reuses rfgen._leeson.synthesize_leeson_phase_noise, the same synthesizer used by LeesonTXPhaseNoise, so TX-side and RX-side phase noise are bit-identical at matched seed and parameters.
TorchSigRXIQImbalance models static, per-call gain and phase mismatch between the I and Q paths of a quadrature demodulator. The transform is linear and deterministic given (amplitude_imbalance_db, phase_imbalance_rad).
TorchSigImpairments requires an explicit nonempty TorchSigImpairmentsConfig and exactly TorchSig 2.1.1. It constructs Impairments(level, seed) only as a constructor-compatibility probe, then executes the configured public transform classes AdditiveNoise, TimeVaryingNoise, CarrierPhaseNoise, IQImbalance, Quantize, and RandomDropSamples in the documented canonical order. It preserves tuple-versus-list constructor semantics in validated parameters, records pre- and post-IQ SHA-256 values and the unexecuted probe in the transformation log, and has no rfgen substitute DSP path. Its NumPy bridge accepts CPU tensors only and fails closed before any implicit device transfer.
2. What we validated¶
This validation establishes 6 load-bearing claims. Each is restated and supported by evidence in §3.
Leeson PSD shape (§3.1): the synthesised phase trajectory matches the analytical three-region Leeson form within Welch single-realisation tolerance.
Band-integrated variance (§3.2): integrated phase-noise power over a measurement band agrees with the analytical band integral.
Three asymptotic regions (§3.3): the Leeson PSD reproduces its documented floor, resonator, and flicker slope regions analytically.
TX-RX shared synthesizer (§3.4): LeesonTXPhaseNoise and LeesonRXPhaseNoise produce bit-identical output at matched seed and parameters.
IQ imbalance closed form (§3.5): TorchSigRXIQImbalance matches the Razavi differential model to float32 precision.
Pinned TorchSig adapter contract (§3.6): TorchSigImpairments matches direct TorchSig 2.1.1 public-transform application, rejects unavailable or unsupported configurations, and records its compatibility probe without claiming that the bundled chain ran.
Limits and scope-bounded items appear in §4; full citations are in §5.
3. Evidence per claim¶
3.1 Leeson PSD shape¶
Claim. The Welch-estimated PSD (power spectral density: how signal energy is distributed across frequency) of the synthesised phase trajectory phi[n] matches the analytical Leeson SSB (single-sideband: measuring noise on one side of the carrier frequency) PSD L(f) within 3 dB at mid-band offsets.
Formula. The analytical Leeson three-region PSD is:
L(Δf) = L_0 + 10·log10(1 + (fc/Δf)²) + 10·log10(1 + (f_flicker/Δf)) [dBc/Hz]
where L_0 is the floor, fc is the resonator corner, and f_flicker is the flicker (1/f) corner. The synthesizer generates phi[n] in the frequency domain by scaling complex Gaussian noise by sqrt(var_per_bin), where var_per_bin = 10^(L/10) · df / 2 (the /2 factor converts the SSB PSD to a two-sided density). Hermitian symmetry ensures a real-valued time-domain output.
Citation. Leeson, D. B. (1966), DOI 10.1109/PROC.1966.4682. Rohde, U. L. (1997), ISBN 978-0-471-52019-8, ch. 5.
Measurement. Four parameter cells (2 floors × 2 resonator corners: psd_floor ∈ {-90, -110} dBc/Hz, fc ∈ {1 kHz, 10 kHz}) each produce maximum mid-band deviation < 0.5 dB against the analytical L(f). The comparison band runs from 10 × flicker corner (10 kHz) to fs/8 (125 kHz) to avoid DC and Nyquist bias. The 3 dB tolerance is the standard Welch single-realisation bound (Welch 1967, DOI 10.1109/TAU.1967.1161901) with 8192-sample Hann windows (a smooth window that reduces spectral leakage) at 50% overlap.
Test. tests/validation/rx_frontend/phase_noise_iq/test_mathematical_fidelity.py::test_leeson_realised_psd_matches_analytical_within_3db (4 parametrised cells).
Figure 1 shows the Welch-estimated PSD overlaid on the analytical Leeson curve for one representative parameter set, confirming the close agreement across the mid-band region.

3.2 Band-integrated variance¶
Claim. The variance of phi[n] integrated over the measurement band (5 kHz to fs/4) agrees with the analytical integral ∫ L(f) df over the same band within 15%.
Formula. The analytical variance is ∫_{f_lo}^{f_hi} 10^(L(f)/10) df, computed via the trapezoidal rule on a dense log-spaced frequency grid. The empirical variance is the Welch-estimated PSD integrated over the same band. Both are one-sided, so no factor-of-2 correction is required.
Citation. Welch (1967), DOI 10.1109/TAU.1967.1161901.
Measurement. Two floor values (-100, -120 dBc/Hz), each averaged over 8 independent realisations, produce relative errors of 2–5% against the analytical integral. The 15% tolerance is the standard single-realisation Welch bound, tightened by the 8-realisation average.
Test. test_mathematical_fidelity.py::test_leeson_integrated_variance_matches_analytical_band_integral (2 parametrised cells × 8 realisations each).
3.3 Three asymptotic regions¶
Claim. The analytical Leeson PSD produces the documented asymptotic slopes: flat floor far from the carrier, -20 dB/decade (resonator-only region between f_flicker and fc), and -30 dB/decade (combined flicker-plus-resonator region below f_flicker).
Citation. Leeson (1966), DOI 10.1109/PROC.1966.4682.
Measurement. Sampling L(f) at 100 Hz (below both corners), 30 kHz (mid-resonator region), and 300 kHz (flat floor): the far-region value is within 0.5 dB of L_0, and the near-carrier excess is in the expected 40–60 dB range above the floor.
Test. test_mathematical_fidelity.py::test_leeson_psd_three_regions_have_correct_slopes.
Figure 2 shows the analytical Leeson PSD for three parameter sets, annotating the three slope regions.

3.5 IQ imbalance closed form¶
Claim. TorchSigRXIQImbalance implements the Razavi differential I/Q-imbalance model exactly:
I' = I · (1 + a/2)
Q' = I · sin(φ) + Q · cos(φ) · (1 - a/2), a = 10^(amp_db/20) - 1
where φ = phase_imbalance_rad. Output matches the algebraic closed form within atol=rtol=1e-6 (float32-tight tolerance).
Citation. Razavi, B. (2011), RF Microelectronics, 2nd ed., Prentice Hall, §4.2.4 and §7.4. ISBN 978-0-13-713473-1.
Measurement. Five (amp_db, phase_rad) cells covering identity (0, 0), mild (0.5, 0.01), moderate (1.0, 0.05), severe (2.0, 0.1), and negative-amplitude (-1.0, -0.05) all pass torch.allclose with atol=rtol=1e-6. Identity cell additionally confirms the output equals the input bit-for-bit.
Test. test_iq_imbalance_and_stub.py::test_rx_iq_imbalance_matches_differential_closed_form (5 cells) and test_rx_iq_imbalance_zero_imbalance_is_identity_on_signal.
Figure 4 shows the QPSK (quadrature phase-shift keying: a 4-symbol digital modulation scheme) constellation before and after applying the differential IQ-imbalance model, confirming the textbook asymmetric skew.

3.6 Pinned TorchSig adapter contract¶
Claim. Each admitted public transform produces a finite complex64 result with the same shape as direct TorchSig 2.1.1 application at the CPU IQ bridge, with max_abs <= 1e-6. Construction without TorchSig raises BackendUnavailableError; omitted configuration raises TypeError; a package version other than 2.1.1 or an unadmitted transform raises UnsupportedCapabilityError; malformed public-transform parameters raise ValueError; non-CPU input raises ChannelError before any implicit device transfer.
Measurement. Direct-oracle tests cover all six admitted transform classes with non-no-op parameters, verify the transformation-log version, ordered class parameters, seed, pre/post SHA-256 values, and impairments_probe.executed is false, and exercise the installed rfgen.channels entry point through a built wheel.
Test. tests/unit/test_layer26_torchsig_compat.py::test_every_admitted_transform_matches_direct_torchsig_211_non_noop_oracle, test_config_rejects_unknown_or_out_of_order_transform_contracts, and test_torchsig_impairments_entry_point_constructs_configured_adapter_and_applies.
4. Limits and what’s not validated¶
Operating envelope. The following input ranges were probed and produce finite, well-formed output:
Surface |
Parameter |
Validated range |
Observed behaviour |
|---|---|---|---|
Phase noise |
|
2 to 2^18 |
Finite real output at every length |
Phase noise |
|
-200 to 0 dBc/Hz |
Finite output across full range |
Phase noise |
|
1 kHz to 100 kHz |
Finite output |
Phase noise |
|
1 Hz to 1 THz |
Carrier-agnostic (metadata only) |
IQ imbalance |
|
-20 to +20 dB |
Finite output; zero input stays zero |
IQ imbalance |
|
-π/4 to +π/4 rad |
Finite output |
Bad inputs are rejected with informative ValueErrors: n_samples <= 0 and sample_rate_hz <= 0 both raise at the synthesizer entry point.
Not validated.
Signals longer than 2^18 samples are not exercised. Per-window Welch statistics are not expected to change, but the asymptotic slope-region match for very long records is not directly verified.
Non-stationary phase noise (time-varying floor, per-burst phase reset, oscillator warm-up transients) is not modelled. The Leeson synthesizer is statistically stationary by construction.
Time-varying IQ imbalance (gain or phase drift over the record length) is not modelled. The transform is applied once per
apply()call with constant parameters.The upstream bundled
Impairments(level, seed)chain is not executed. TorchSig 2.1.1 does not expose selection of the explicit transform list through that bundle, so rfgen uses it only as a public-constructor compatibility probe. The configured public classes, not the bundle, define the executed DSP path.The Leeson model’s
f0_hzparameter is metadata-only and is not used in the PSD formula. The carrier frequency does not affect the phase-noise shape in this implementation, which is consistent with the baseband representation used throughout rfgen but departs from formulations that include the oscillator’s loaded Q-factor term.
Deferred items.
A multi-window Welch cross-check (tightening the slope-region asymptotic bounds) is not required for the documented contract and is deferred.
Admission of a later TorchSig minor is deferred until a new compatibility row verifies its public constructors and direct-oracle behavior.
5. References¶
Published works¶
Reference |
DOI / ISBN |
|---|---|
Leeson, D. B. (1966). “A Simple Model of Feedback Oscillator Noise Spectrum.” Proceedings of the IEEE 54(2):329–330. |
|
Rohde, U. L. (1997). Microwave and Wireless Synthesizers: Theory and Design. Wiley, ch. 5. |
ISBN: 978-0-471-52019-8 |
Razavi, B. (2011). RF Microelectronics, 2nd ed. Prentice Hall, §4.2.4 and §7.4. |
ISBN: 978-0-13-713473-1 |
Welch, P. D. (1967). “The Use of Fast Fourier Transform for the Estimation of Power Spectra.” IEEE Transactions on Audio and Electroacoustics 15(2):70–73. |
Libraries¶
PyPI distribution |
Installed version |
Documentation URL |
Role in this validation |
|---|---|---|---|
|
2.12.1 |
IQ tensor arithmetic, |
|
|
1.18.0 |
|
|
|
2.4.6 |
Array construction, |
|
|
3.11.0 |
Figure generation (all four PNGs in the figures directory) |
