Model and data contracts#

Radar models and typed data contracts.

class pyradar.base.ADCFrame(data, dims, radar=None, timestamp=None, frameId=None, metadata=<factory>)[source]#

Bases: object

Raw ADC frame with explicit dimension names.

Raw ndarrays are never assigned dimensions by guesswork. A singleton loop or emission dimension may be inserted only when the radar model proves that its size is one.

Parameters:
  • data (NDArray[Any])

  • dims (AxisOrder)

  • radar (Radar | None)

  • timestamp (float | None)

  • frameId (int | str | None)

  • metadata (Mapping[str, Any])

data: NDArray[Any]#
dims: AxisOrder#
radar: Radar | None#
timestamp: float | None#
frameId: int | str | None#
metadata: Mapping[str, Any]#
classmethod from_array(data, *, dims, radar=None, timestamp=None, frameId=None, metadata=None)[source]#
Parameters:
  • data (ArrayLike)

  • dims (Sequence[str] | None)

  • radar (Radar | None)

  • timestamp (float | None)

  • frameId (int | str | None)

  • metadata (Mapping[str, Any] | None)

Return type:

ADCFrame

canonical(radar=None)[source]#

Return a view ordered as loop/emission/rx/sample.

Parameters:

radar (Radar | None)

Return type:

ADCFrame

class pyradar.base.AWR1843Radar(waveform, sampler, transceivers, mimo, calibration=<factory>, processing=<factory>, name='radar', hardware='TI AWR1843', profileName='custom')[source]#

Bases: Radar

TI AWR1843 capture profile used by RAMPCNN/CRUW.

Parameters:
hardware: str = 'TI AWR1843'#
profileName: str = 'custom'#
classmethod rampcnn()[source]#
Return type:

AWR1843Radar

class pyradar.base.BPM(numRx, codeMatrix=((1.0, 1.0), (1.0, -1.0)))[source]#

Bases: MIMOScheme

Two-transmitter binary phase modulation with Hadamard decoding.

Parameters:
numRx: int#
codeMatrix: tuple[tuple[float, float], tuple[float, float]]#
numTx: int#
scheme: ClassVar[str] = 'bpm'#
property numEmissions: int#

Number of captured emissions in each raw loop.

decode(adc)[source]#

Decode canonical ADC or range data into virtual channels.

Parameters:

adc (NDArray[Any])

Return type:

NDArray[Any]

slow_time_interval(chirpInterval)[source]#

Time between adjacent decoded slow-time samples.

Parameters:

chirpInterval (float)

Return type:

float

class pyradar.base.CFARConfig(method='ca', trainingCells=(8, 4), guardCells=(2, 1), pfa=0.0001, rankFraction=0.75, minSnrDb=0.0, peakGrouping=True, maxDetections=512)[source]#

Bases: object

Range-Doppler CFAR and peak-grouping configuration.

Parameters:
method: Literal['ca', 'goca', 'soca', 'os']#
trainingCells: tuple[int, int]#
guardCells: tuple[int, int]#
pfa: float#
rankFraction: float#
minSnrDb: float#
peakGrouping: bool#
maxDetections: int | None#
class pyradar.base.Calibration(adcGain=None, adcPhase=None, frequencySlope=None, rangeCoupling=None, arrayPhase=None, overlapPairs=None)[source]#

Bases: object

Calibration terms grouped by the signal-processing stage.

adcGain, adcPhase, and frequencySlope are indexed by (emission, rx) (or by rx for SIMO). rangeCoupling is indexed by (virtual, range). arrayPhase has one complex coefficient per virtual channel. Any supplied shape is checked at the point of use.

Parameters:
  • adcGain (NDArray[Any] | None)

  • adcPhase (NDArray[Any] | None)

  • frequencySlope (NDArray[Any] | None)

  • rangeCoupling (NDArray[Any] | None)

  • arrayPhase (NDArray[Any] | None)

  • overlapPairs (NDArray[int64] | None)

adcGain: NDArray[Any] | None#
adcPhase: NDArray[Any] | None#
frequencySlope: NDArray[Any] | None#
rangeCoupling: NDArray[Any] | None#
arrayPhase: NDArray[Any] | None#
overlapPairs: NDArray[int64] | None#
apply_adc(data)[source]#

Apply gain, phase, and frequency calibration to canonical ADC data.

Parameters:

data (NDArray[Any])

Return type:

NDArray[Any]

apply_range(data)[source]#

Subtract range-domain coupling from (loop, virtual, range) data.

Parameters:

data (NDArray[Any])

Return type:

NDArray[Any]

apply_array(data, channelAxis=-1)[source]#

Apply calibrated complex phase coefficients along a virtual axis.

Parameters:
  • data (NDArray[Any])

  • channelAxis (int)

Return type:

NDArray[Any]

class pyradar.base.ClusterSet(labels, clusterId, centroid, size, covariance, radialVelocity, power)[source]#

Bases: object

Per-point labels and aggregate cluster statistics.

Parameters:
  • labels (NDArray[int64])

  • clusterId (NDArray[int64])

  • centroid (NDArray[float64])

  • size (NDArray[float64])

  • covariance (NDArray[float64])

  • radialVelocity (NDArray[float64])

  • power (NDArray[float64])

labels: NDArray[int64]#
clusterId: NDArray[int64]#
centroid: NDArray[float64]#
size: NDArray[float64]#
covariance: NDArray[float64]#
radialVelocity: NDArray[float64]#
power: NDArray[float64]#
class pyradar.base.ClusteringConfig(enabled=False, eps=1.0, minSamples=3, velocityScale=1.0, dimensions=3)[source]#

Bases: object

Velocity-aware deterministic DBSCAN defaults.

Parameters:
enabled: bool#
eps: float#
minSamples: int#
velocityScale: float#
dimensions: Literal[2, 3]#
class pyradar.base.DDM(numTx, numRx, dopplerOffsets, codeLength)[source]#

Bases: MIMOScheme

Doppler-division MIMO using orthogonal linear slow-time phase codes.

dopplerOffsets are normalized cycles per raw chirp. Decoding correlates one complete code period, so the input loop count must be divisible by codeLength. The target is assumed stationary over one code period.

Parameters:
numTx: int#
numRx: int#
dopplerOffsets: tuple[float, ...]#
codeLength: int#
scheme: ClassVar[str] = 'ddm'#
property numEmissions: int#

Number of captured emissions in each raw loop.

property codes: NDArray[complex128]#
decode(adc)[source]#

Decode canonical ADC or range data into virtual channels.

Parameters:

adc (NDArray[Any])

Return type:

NDArray[Any]

slow_time_interval(chirpInterval)[source]#

Time between adjacent decoded slow-time samples.

Parameters:

chirpInterval (float)

Return type:

float

class pyradar.base.DetectionSet(rangeBin, dopplerBin, power, noise, threshold, snr, azimuthBin=None, elevationBin=None)[source]#

Bases: object

CFAR detections and their source bins.

Parameters:
  • rangeBin (NDArray[int64])

  • dopplerBin (NDArray[int64])

  • power (NDArray[float64])

  • noise (NDArray[float64])

  • threshold (NDArray[float64])

  • snr (NDArray[float64])

  • azimuthBin (NDArray[int64] | None)

  • elevationBin (NDArray[int64] | None)

rangeBin: NDArray[int64]#
dopplerBin: NDArray[int64]#
power: NDArray[float64]#
noise: NDArray[float64]#
threshold: NDArray[float64]#
snr: NDArray[float64]#
azimuthBin: NDArray[int64] | None#
elevationBin: NDArray[int64] | None#
classmethod empty()[source]#
Return type:

DetectionSet

class pyradar.base.DoAConfig(method='auto', azimuthFov=(-1.5707963267948966, 1.5707963267948966), elevationFov=(-0.7853981633974483, 0.7853981633974483), azimuthBins=181, elevationBins=61, numSources=1, diagonalLoading=0.001, duplicatePolicy='coherent')[source]#

Bases: object

Direction-of-arrival defaults in radians.

Parameters:
method: Literal['auto', 'fft', 'bartlett', 'capon', 'music', 'esprit']#
azimuthFov: tuple[float, float]#
elevationFov: tuple[float, float]#
azimuthBins: int#
elevationBins: int#
numSources: int#
diagonalLoading: float#
duplicatePolicy: Literal['first', 'noncoherent', 'coherent']#
class pyradar.base.FFTConfig(rangeFftSize=None, dopplerFftSize=None, azimuthFftSize=256, elevationFftSize=128, rangeWindow='hann', dopplerWindow='hann', angleWindow='hann', removeRangeMean=False, removeDopplerMean=True, rangeCrop=None, azimuthCrop=None, elevationCrop=None)[source]#

Bases: object

FFT sizes, windows, and optional output cropping.

Parameters:
  • rangeFftSize (int | None)

  • dopplerFftSize (int | None)

  • azimuthFftSize (int)

  • elevationFftSize (int)

  • rangeWindow (Literal['rectangular', 'hann', 'hamming', 'blackman', 'blackmanharris'])

  • dopplerWindow (Literal['rectangular', 'hann', 'hamming', 'blackman', 'blackmanharris'])

  • angleWindow (Literal['rectangular', 'hann', 'hamming', 'blackman', 'blackmanharris'])

  • removeRangeMean (bool)

  • removeDopplerMean (bool)

  • rangeCrop (tuple[int, int | None] | None)

  • azimuthCrop (tuple[int, int | None] | None)

  • elevationCrop (tuple[int, int | None] | None)

rangeFftSize: int | None#
dopplerFftSize: int | None#
azimuthFftSize: int#
elevationFftSize: int#
rangeWindow: Literal['rectangular', 'hann', 'hamming', 'blackman', 'blackmanharris']#
dopplerWindow: Literal['rectangular', 'hann', 'hamming', 'blackman', 'blackmanharris']#
angleWindow: Literal['rectangular', 'hann', 'hamming', 'blackman', 'blackmanharris']#
removeRangeMean: bool#
removeDopplerMean: bool#
rangeCrop: tuple[int, int | None] | None#
azimuthCrop: tuple[int, int | None] | None#
elevationCrop: tuple[int, int | None] | None#
crop(dimension)[source]#
Parameters:

dimension (str)

Return type:

slice

class pyradar.base.FMCW(startFrequency, slope, adcStartTime, rampEndTime, idleTime=0.0, shape='sawtooth')[source]#

Bases: object

Sawtooth FMCW chirp definition.

Parameters:
startFrequency:

Frequency at the beginning of the ramp, in Hz.

slope:

Ramp slope, in Hz/s. v1 supports positive-slope sawtooth chirps.

adcStartTime:

Delay from ramp start to the first ADC sample, in seconds.

rampEndTime:

Ramp duration measured from ramp start, in seconds.

idleTime:

Idle time after each ramp, in seconds.

Parameters:
startFrequency: float#
slope: float#
adcStartTime: float#
rampEndTime: float#
idleTime: float#
shape: Literal['sawtooth']#
property chirpInterval: float#

Time between starts of adjacent chirps.

property rampBandwidth: float#

Bandwidth swept during the complete ramp.

property centerFrequency: float#

Carrier frequency at the center of the complete ramp.

property wavelength: float#

Wavelength at centerFrequency.

class pyradar.base.FrameResult(adcFrame, detections, pointCloud, rangeCube=None, rangeDopplerCube=None, rangeAngleCube=None, rangeDopplerAngleCube=None, clusters=None, tracks=None, metadata=<factory>)[source]#

Bases: object

Products generated while processing one ADC frame.

Parameters:
adcFrame: ADCFrame#
detections: DetectionSet#
pointCloud: PointCloud#
rangeCube: RadarCube | None#
rangeDopplerCube: RadarCube | None#
rangeAngleCube: RadarCube | None#
rangeDopplerAngleCube: RadarCube | None#
clusters: ClusterSet | None#
tracks: TrackSet | None#
metadata: Mapping[str, Any]#
class pyradar.base.MIMOScheme[source]#

Bases: ABC

Interface implemented by all MIMO strategies.

scheme: ClassVar[str]#
numTx: int#
numRx: int#
abstract property numEmissions: int#

Number of captured emissions in each raw loop.

property channelMap: tuple[tuple[int, int], ...]#

TX/RX id for each decoded virtual channel.

abstractmethod decode(adc)[source]#

Decode canonical ADC or range data into virtual channels.

Parameters:

adc (NDArray[Any])

Return type:

NDArray[Any]

abstractmethod slow_time_interval(chirpInterval)[source]#

Time between adjacent decoded slow-time samples.

Parameters:

chirpInterval (float)

Return type:

float

phase_correction(dopplerSize, chirpInterval)[source]#

Doppler phase correction indexed by Doppler bin and channel.

Parameters:
  • dopplerSize (int)

  • chirpInterval (float)

Return type:

NDArray[complex128]

class pyradar.base.PointCloud(xyz, power, snr, radialVelocity, sourceBins, timestamp=None, frameId=None)[source]#

Bases: object

Radar point cloud in FLU coordinates with velocity and provenance.

Parameters:
  • xyz (NDArray[float64])

  • power (NDArray[float64])

  • snr (NDArray[float64])

  • radialVelocity (NDArray[float64])

  • sourceBins (NDArray[int64])

  • timestamp (float | None)

  • frameId (int | str | None)

xyz: NDArray[float64]#
power: NDArray[float64]#
snr: NDArray[float64]#
radialVelocity: NDArray[float64]#
sourceBins: NDArray[int64]#
timestamp: float | None#
frameId: int | str | None#
property range: NDArray[float64]#
property azimuth: NDArray[float64]#
property elevation: NDArray[float64]#
to_numpy()[source]#

Return columns x, y, z, power, snr, radialVelocity.

Return type:

NDArray[float64]

classmethod empty(*, timestamp=None, frameId=None)[source]#
Parameters:
Return type:

PointCloud

class pyradar.base.PointCloudConfig(minRange=0.0, maxRange=None, unwrapTdmVelocity=True)[source]#

Bases: object

Point-cloud filtering defaults.

Parameters:
minRange: float#
maxRange: float | None#
unwrapTdmVelocity: bool#
class pyradar.base.ProcessingConfig(fft=<factory>, cfar=<factory>, doa=<factory>, pointCloud=<factory>, clustering=<factory>, tracking=<factory>, retainRangeDoppler=True, retainRangeAngle=False, retainRangeDopplerAngle=False)[source]#

Bases: object

Layered algorithm defaults used by Radar.

Parameters:
fft: FFTConfig#
cfar: CFARConfig#
doa: DoAConfig#
pointCloud: PointCloudConfig#
clustering: ClusteringConfig#
tracking: TrackingConfig#
retainRangeDoppler: bool#
retainRangeAngle: bool#
retainRangeDopplerAngle: bool#
class pyradar.base.Radar(waveform, sampler, transceivers, mimo, calibration=<factory>, processing=<factory>, name='radar')[source]#

Bases: object

Validated radar aggregate used as the context for all algorithms.

Parameters:
waveform: FMCW#
sampler: Sampler#
transceivers: Transceivers#
mimo: MIMOScheme#
calibration: Calibration#
processing: ProcessingConfig#
name: str = 'radar'#
classmethod from_config(path)[source]#

Build a radar from a v1 YAML or JSON configuration file.

Parameters:

path (str | Path)

Return type:

Radar

classmethod radelft_cascade()[source]#
Return type:

TI2243CascadeRadar

classmethod coloradar_cascade()[source]#
Return type:

TI2243CascadeRadar

classmethod coloradar_plus_cascade()[source]#
Return type:

TI2243CascadeRadar

classmethod awr1843_rampcnn()[source]#
Return type:

AWR1843Radar

property sampleDuration: float#
property sampledBandwidth: float#
property centerFrequency: float#
property wavelength: float#
property rangeResolution: float#
property rangeBinSize: float#
property maxUnambiguousRange: float#
property numSlowTimeSamples: int#
property slowTimeInterval: float#
property velocityResolution: float#
property velocityBinSize: float#
property maxUnambiguousVelocity: float#
property virtualArray: NDArray[float64]#
property duplicatePhaseCenters: tuple[tuple[int, ...], ...]#
property arrayGeometry: str#
property unambiguousFov: dict[str, tuple[float, float]]#
property rangeBinIndices: NDArray[int64]#
property rangeAxis: NDArray[float64]#
property velocityAxis: NDArray[float64]#
property azimuthAxis: NDArray[float64]#
property elevationAxis: NDArray[float64]#
build_pipeline()[source]#

Create a stateful ADC-to-track processing pipeline.

process_adc(adc, *, dims=None, **kwargs)[source]#

Process one frame with a fresh pipeline.

Parameters:
simulate(targets, **kwargs)[source]#

Synthesize canonical ADC samples using this radar model.

The import is intentionally local so the physical model remains usable without loading optional simulation backends.

Parameters:
Return type:

ADCFrame

class pyradar.base.RadarCube(data, dims, stage, radar=None, coords=<factory>, metadata=<factory>)[source]#

Bases: object

An ndarray with named dimensions, coordinates, and processing stage.

Parameters:
  • data (NDArray[Any])

  • dims (AxisOrder)

  • stage (str)

  • radar (Radar | None)

  • coords (Mapping[str, NDArray[Any]])

  • metadata (Mapping[str, Any])

data: NDArray[Any]#
dims: AxisOrder#
stage: str#
radar: Radar | None#
coords: Mapping[str, NDArray[Any]]#
metadata: Mapping[str, Any]#
property shape: tuple[int, ...]#
property magnitude: NDArray[Any]#
property power: NDArray[Any]#
dim_index(name)[source]#
Parameters:

name (str)

Return type:

int

transpose(*dims)[source]#

Transpose by dimension name.

Parameters:

dims (str)

Return type:

RadarCube

with_data(data, *, dims=None, stage=None, coords=None, metadata=None)[source]#
Parameters:
Return type:

RadarCube

class pyradar.base.SIMO(numRx)[source]#

Bases: MIMOScheme

Single-transmitter acquisition.

Parameters:

numRx (int)

numRx: int#
numTx: int#
scheme: ClassVar[str] = 'simo'#
property numEmissions: int#

Number of captured emissions in each raw loop.

decode(adc)[source]#

Decode canonical ADC or range data into virtual channels.

Parameters:

adc (NDArray[Any])

Return type:

NDArray[Any]

slow_time_interval(chirpInterval)[source]#

Time between adjacent decoded slow-time samples.

Parameters:

chirpInterval (float)

Return type:

float

class pyradar.base.Sampler(numSamples, numLoops, sampleRate, bitDepth=16, complexSampling=True, framePeriod=None)[source]#

Bases: object

ADC sampling and frame configuration.

Parameters are the samples captured per emission and the number of MIMO loops in one frame. Complex IQ sampling is the default for mmWave radars.

Parameters:
  • numSamples (int)

  • numLoops (int)

  • sampleRate (float)

  • bitDepth (int)

  • complexSampling (bool)

  • framePeriod (float | None)

numSamples: int#
numLoops: int#
sampleRate: float#
bitDepth: int#
complexSampling: bool#
framePeriod: float | None#
property samplePeriod: float#

ADC sampling period in seconds.

property captureDuration: float#

Duration covered by the ADC samples of one emission.

class pyradar.base.TDM(numTx, numRx, txOrder=(), emissionTimeOffsets=(), cyclePeriod=None)[source]#

Bases: MIMOScheme

Time-division MIMO with arbitrary TX order and emission timing.

Parameters:
numTx: int#
numRx: int#
txOrder: tuple[int, ...]#
emissionTimeOffsets: tuple[float, ...]#
cyclePeriod: float | None#
scheme: ClassVar[str] = 'tdm'#
property numEmissions: int#

Number of captured emissions in each raw loop.

decode(adc)[source]#

Decode canonical ADC or range data into virtual channels.

Parameters:

adc (NDArray[Any])

Return type:

NDArray[Any]

slow_time_interval(chirpInterval)[source]#

Time between adjacent decoded slow-time samples.

Parameters:

chirpInterval (float)

Return type:

float

tx_time_offsets(chirpInterval)[source]#
Parameters:

chirpInterval (float)

Return type:

NDArray[float64]

phase_correction(dopplerSize, chirpInterval)[source]#

Doppler phase correction indexed by Doppler bin and channel.

Parameters:
  • dopplerSize (int)

  • chirpInterval (float)

Return type:

NDArray[complex128]

class pyradar.base.TI2243CascadeRadar(waveform, sampler, transceivers, mimo, calibration=<factory>, processing=<factory>, name='radar', hardware='TI AWR2243 4-chip cascade', profileName='custom')[source]#

Bases: Radar

A TI AWR2243 four-chip cascade with a concrete capture profile.

Parameters:
hardware: str = 'TI AWR2243 4-chip cascade'#
profileName: str = 'custom'#
classmethod radelft()[source]#

RaDelft capture profile using its physical chirp parameters.

Return type:

TI2243CascadeRadar

classmethod coloradar()[source]#

Original ColoRadar cascade capture profile.

Return type:

TI2243CascadeRadar

classmethod coloradar_plus()[source]#

ColoRadar+ fallback profile; dataset readers replace exact metadata.

Return type:

TI2243CascadeRadar

class pyradar.base.TrackSet(trackId, status, position, velocity, covariance, age, hits, misses)[source]#

Bases: object

Public snapshot of multi-target tracker state.

Parameters:
  • trackId (NDArray[int64])

  • status (tuple[str, ...])

  • position (NDArray[float64])

  • velocity (NDArray[float64])

  • covariance (NDArray[float64])

  • age (NDArray[int64])

  • hits (NDArray[int64])

  • misses (NDArray[int64])

trackId: NDArray[int64]#
status: tuple[str, ...]#
position: NDArray[float64]#
velocity: NDArray[float64]#
covariance: NDArray[float64]#
age: NDArray[int64]#
hits: NDArray[int64]#
misses: NDArray[int64]#
class pyradar.base.TrackingConfig(enabled=False, dimensions=3, processNoise=2.0, measurementNoise=0.5, radialVelocityNoise=1.0, gatingThreshold=11.34, confirmationHits=3, deletionMisses=5)[source]#

Bases: object

Constant-velocity multi-target tracking defaults.

Parameters:
  • enabled (bool)

  • dimensions (Literal[2, 3])

  • processNoise (float)

  • measurementNoise (float)

  • radialVelocityNoise (float)

  • gatingThreshold (float)

  • confirmationHits (int)

  • deletionMisses (int)

enabled: bool#
dimensions: Literal[2, 3]#
processNoise: float#
measurementNoise: float#
radialVelocityNoise: float#
gatingThreshold: float#
confirmationHits: int#
deletionMisses: int#
class pyradar.base.Transceivers(txPositions, rxPositions, azimuthOnlyChannels=())[source]#

Bases: object

TX/RX coordinates in the radar FLU frame, in meters.

FLU is right handed: x points forward, y left, and z up. Antenna arrays normally lie in the y-z plane. Virtual phase centers are formed from the TX/RX channel map supplied by a MIMO strategy.

Parameters:
  • txPositions (NDArray[float64])

  • rxPositions (NDArray[float64])

  • azimuthOnlyChannels (tuple[int, ...])

txPositions: NDArray[float64]#
rxPositions: NDArray[float64]#
azimuthOnlyChannels: tuple[int, ...]#
property numTx: int#
property numRx: int#
virtual_positions(channelMap)[source]#

Return monostatic virtual phase-center coordinates.

The phase of a far-field return is proportional to (txPosition + rxPosition) dot direction; therefore no arbitrary array offset or dataset-specific topology is required.

Parameters:

channelMap (Sequence[tuple[int, int]])

Return type:

NDArray[float64]

static phase_center_groups(positions, tolerance=1e-09)[source]#

Group channels that share a virtual phase center.

Parameters:
  • positions (NDArray[float64])

  • tolerance (float)

Return type:

tuple[tuple[int, …], …]