Receiver chain

The Noise, Agc, Iq and Adc records that model thermal and phase noise, automatic gain control, IQ imbalance and quantization in witwin.radar.

The receiver chain is set by four fields on Radar: noise, lna_gain, agc and adc, plus iq. Each stage is a frozen dataclass. All configuration values must be Python numbers; a tensor is refused.

from witwin.radar import Adc, Agc, Iq, Noise

The stages run in this order on the synthesized cube: conversion from sqrt(W) to volts at Radar.impedance, then noise and the LNA gain in one fused stage, then IQ imbalance, then AGC, then the ADC. A chain exists only when at least one of noise, lna_gain, agc or adc is set. With none of them set, the cube stays in sqrt(W) and iq has no effect. See Model the receiver chain.

Noise#

class Noise(figure=0.0, antenna_temperature=290.0, bandwidth=None, phase_density=None,
            phase_offset=None, phase_sample_rate=None)

Thermal noise from a noise figure, and optional oscillator phase noise. The noise is circular complex Gaussian with total power k · T_sys · B, where T_sys = antenna_temperature + 290 · (F - 1) and F = 10^(figure / 10). Noise is drawn from Radar.seed, so the same seed gives the same noise.

figurefloatdefault 0.0

Receiver noise figure, dB. 0.0 still adds thermal noise at the antenna temperature.

antenna_temperaturefloatdefault 290.0

Antenna noise temperature, K. Must be non-negative.

bandwidthfloat | Nonedefault None

Thermal noise bandwidth, Hz. None takes the waveform's bandwidth: the sample rate for FMCW, num_subcarriers · subcarrier_spacing for OFDM, and the declared bandwidth for pulsed. Must be positive when given.

phase_densityfloat | Nonedefault None

Single-sideband oscillator phase-noise density, dBc/Hz, at phase_offset. None means no phase noise.

phase_offsetfloat | Nonedefault None

Offset frequency phase_density was measured at, Hz. Required when phase_density is set.

phase_sample_ratefloat | Nonedefault None

Step rate of the oscillator random walk, Hz. None takes the waveform's sample rate.

The phase noise is a free-running oscillator with a -20 dB/decade spectrum. It does not model the close-in 1/f^3 region or a far-out floor. Phase noise needs FMCW and ADC-time observations, so Motion.auto() resamples every ADC instant when it is set.

Raises ValueError for a negative antenna temperature, a non-positive bandwidth, phase_offset or phase_sample_rate, or phase_density without phase_offset.

MemberReturns
noise_factor10^(figure / 10), linear.
system_noise_temperature_kantenna_temperature + 290 · (noise_factor - 1), K.
noise_power_wattsk · T_sys · bandwidth, W. Raises ValueError while bandwidth is None.
thermal_sigma_volts(impedance)sqrt(k · T_sys · B · R / 2), the standard deviation of each real component, V.
phase_innovation_sigma_radStandard deviation of one random-walk step, rad. 0.0 without phase noise.
resolved(*, bandwidth, sample_rate)A copy with bandwidth and phase_sample_rate filled in where they were None.
noise = Noise(figure=10.0, phase_density=-90.0, phase_offset=1e6)
radar = radar.replace(noise=noise, seed=3)

LNA gain#

Radar.lna_gain is a plain float in dB, not a record. It scales the signal and the noise together in the fused noise stage, so it changes the level but not the signal-to-noise ratio.

Agc#

class Agc(target_rms, mode='per_rx', min_gain=-60.0, max_gain=60.0)

Automatic gain control: scale each group of samples to a target RMS voltage, within gain limits. The gain depends on the signal itself, so a chain with AGC is not linear in the signal.

target_rmsfloatrequired

Target output RMS, V. Must be positive.

modestrdefault 'per_rx'

"per_rx" computes one gain per receive channel. "global" computes one gain for the whole frame.

min_gainfloatdefault -60.0

Lowest allowed gain, dB.

max_gainfloatdefault 60.0

Highest allowed gain, dB. Must not be below min_gain.

Raises ValueError for a non-positive target_rms, an unknown mode, or min_gain > max_gain.

PropertyReturns
min_voltage_gain10^(min_gain / 20).
max_voltage_gain10^(max_gain / 20).

Iq#

class Iq(gain_db=0.0, phase_deg=0.0)

Quadrature demodulator imbalance. The output is y = alpha · x + beta · conj(x), so a mirror image of every target appears at the opposite Doppler, image_rejection_db below it. Both values zero is a perfect demodulator.

gain_dbfloatdefault 0.0

Gain ratio between the I and Q branches, dB.

phase_degfloatdefault 0.0

Phase error between the branches, degrees.

PropertyReturns
alphaDirect coefficient (1 + g · exp(-j · phi)) / 2, complex.
betaImage coefficient (1 - g · exp(+j · phi)) / 2, complex.
image_rejection_db-20 · log10(abs(beta) / abs(alpha)), dB. inf for a perfect demodulator.

Iq needs a receiver chain

Radar(iq=...) alone does not change the cube. Set at least one of noise, lna_gain, agc or adc as well.

Adc#

class Adc(bits, full_scale)

Uniform mid-tread quantizer with clipping at ±full_scale, applied to each real component.

bitsintrequired

Resolution, bits. Must be between 1 and 30.

full_scalefloatrequired

Clipping level, V. Must be positive.

Raises ValueError for bits outside [1, 30] or a non-positive full_scale. Quantization is not differentiable: a chain with an Adc refuses an input that carries a gradient or a forward tangent.

PropertyReturns
stepQuantization step 2 · full_scale / (2^bits - 1), V.
radar = radar.replace(noise=Noise(figure=8.0), lna_gain=20.0, agc=Agc(target_rms=0.1),
                      adc=Adc(bits=12, full_scale=1.0))