Radar signal processing#

Radar signal-processing algorithms.

class pyradar.rsp.ADCToPointCloudPipeline(radar)[source]#

Bases: object

Stateful detection-first processing pipeline built from one Radar.

Processing order is ADC calibration, range FFT, MIMO decode, range-domain calibration, Doppler FFT, RD CFAR, MIMO phase correction, DoA, point cloud, clustering, and tracking. Dense RA/RDA products are optional.

Parameters:

radar (Radar)

reset()[source]#

Reset stateful downstream algorithms such as tracking.

Return type:

None

process(adc, *, dims=None, timestamp=None, frameId=None)[source]#

Process one ADC frame using the attached Radar model.

Parameters:
Return type:

FrameResult

class pyradar.rsp.CFARResult(detections, noise, threshold, snr)[source]#

Bases: object

Full-size CFAR products.

Parameters:
  • detections (NDArray[bool])

  • noise (NDArray[float64])

  • threshold (NDArray[float64])

  • snr (NDArray[float64])

detections: NDArray[bool]#
noise: NDArray[float64]#
threshold: NDArray[float64]#
snr: NDArray[float64]#
class pyradar.rsp.DoAResult(azimuth, elevation, power, spectrum, azimuthAxis, elevationAxis, method)[source]#

Bases: object

Estimated directions and the search spectrum.

Parameters:
  • azimuth (NDArray[float64])

  • elevation (NDArray[float64])

  • power (NDArray[float64])

  • spectrum (NDArray[float64])

  • azimuthAxis (NDArray[float64])

  • elevationAxis (NDArray[float64])

  • method (str)

azimuth: NDArray[float64]#
elevation: NDArray[float64]#
power: NDArray[float64]#
spectrum: NDArray[float64]#
azimuthAxis: NDArray[float64]#
elevationAxis: NDArray[float64]#
method: str#
class pyradar.rsp.DopplerUnwrapResult(frequency, velocity, ambiguityOrder, score, phaseCorrection)[source]#

Bases: object

One TDM Doppler ambiguity decision.

frequency is two-way Doppler frequency in hertz, velocity is radial velocity in metres per second, and ambiguityOrder is the integer alias multiple relative to the decoded slow-time interval.

Parameters:
  • frequency (float)

  • velocity (float)

  • ambiguityOrder (int)

  • score (float)

  • phaseCorrection (NDArray[complex128])

frequency: float#
velocity: float#
ambiguityOrder: int#
score: float#
phaseCorrection: NDArray[complex128]#
class pyradar.rsp.MultiTargetTracker(config=None)[source]#

Bases: object

GNN tracker with Hungarian assignment and radial-velocity EKF updates.

Parameters:

config (TrackingConfig | None)

reset()[source]#

Delete all tracker state and restart track ids.

Return type:

None

update(pointCloud, *, clusters=None, timestamp=None, deltaTime=None)[source]#

Predict, globally associate, and update tracks for one frame.

Parameters:
Return type:

TrackSet

class pyradar.rsp.TimeFrequencyResult(spectrum, frequency, time, velocity=None)[source]#

Bases: object

Complex STFT with frequency and segment-center coordinates.

Parameters:
  • spectrum (NDArray[complex128])

  • frequency (NDArray[float64])

  • time (NDArray[float64])

  • velocity (NDArray[float64] | None)

spectrum: NDArray[complex128]#
frequency: NDArray[float64]#
time: NDArray[float64]#
velocity: NDArray[float64] | None#
property power: NDArray[float64]#

Linear spectrogram power.

class pyradar.rsp.ZoomFFTResult(spectrum, frequency, axis)[source]#

Bases: object

Spectrum evaluated on a requested uniform frequency interval.

Parameters:
  • spectrum (NDArray[complex128])

  • frequency (NDArray[float64])

  • axis (int)

spectrum: NDArray[complex128]#
frequency: NDArray[float64]#
axis: int#
pyradar.rsp.angle_fft(signal, *, radar=None, fftSize=None, antennaAxis=-1, window=None, dimension='azimuth')[source]#

Apply a centered FFT over an already ordered uniform aperture.

Parameters:
Return type:

RadarCube | NDArray[Any]

pyradar.rsp.ca_cfar_1d(power, **kwargs)[source]#
Parameters:

power (ArrayLike)

Return type:

CFARResult

pyradar.rsp.ca_cfar_2d(power, **kwargs)[source]#
Parameters:

power (ArrayLike)

Return type:

CFARResult

pyradar.rsp.cfar_1d(power, *, method='ca', trainingCells=8, guardCells=2, pfa=0.0001, rankFraction=0.75, axis=-1, minSnrDb=0.0, peakGrouping=False, wrap=False)[source]#

One-dimensional CA/GOCA/SOCA/OS-CFAR.

Parameters:
Return type:

CFARResult

pyradar.rsp.cfar_2d(power, *, method='ca', trainingCells=(8, 4), guardCells=(2, 1), pfa=0.0001, rankFraction=0.75, minSnrDb=0.0, peakGrouping=True)[source]#

Two-dimensional CFAR over a range-Doppler power map.

Doppler is treated as circular. Range edge cells without a complete training set are marked invalid.

Parameters:
Return type:

CFARResult

pyradar.rsp.combine_duplicate_channels(signal, positions, *, policy='coherent', tolerance=1e-09)[source]#

Combine repeated virtual phase centers according to policy.

Parameters:
  • signal (ArrayLike)

  • positions (ArrayLike)

  • policy (Literal['first', 'noncoherent', 'coherent'])

  • tolerance (float)

Return type:

tuple[NDArray[Any], NDArray[float64]]

pyradar.rsp.coherent_integrate(values, *, axis=0)[source]#

Coherently sum complex samples along one axis.

Parameters:
  • values (ArrayLike)

  • axis (int)

Return type:

NDArray

pyradar.rsp.dbscan(pointCloud, *, eps=1.0, minSamples=3, velocityScale=1.0, dimensions=3)[source]#

Cluster a radar point cloud in position/radial-velocity space.

The feature metric is [position, velocityScale * radialVelocity]. Iteration and neighborhood ordering are fixed, making labels deterministic.

Parameters:
Return type:

ClusterSet

pyradar.rsp.detections_to_pointcloud(detections, *, radar, azimuth, elevation, azimuthBin=None, elevationBin=None, radialVelocity=None, timestamp=None, frameId=None)[source]#

Map typed detections and DoA estimates to a typed point cloud.

Parameters:
  • detections (DetectionSet)

  • radar (Radar)

  • azimuth (ArrayLike)

  • elevation (ArrayLike)

  • azimuthBin (ArrayLike | None)

  • elevationBin (ArrayLike | None)

  • radialVelocity (ArrayLike | None)

  • timestamp (float | None)

  • frameId (int | str | None)

Return type:

PointCloud

pyradar.rsp.doa_bartlett(signal, *, arrayPositions, wavelength, azimuthAxis, elevationAxis=None)[source]#

Conventional (Bartlett) beamforming spectrum.

Parameters:
  • signal (ArrayLike)

  • arrayPositions (ArrayLike)

  • wavelength (float)

  • azimuthAxis (ArrayLike)

  • elevationAxis (ArrayLike | None)

Return type:

NDArray[float64]

pyradar.rsp.doa_capon(signal, *, arrayPositions, wavelength, azimuthAxis, elevationAxis=None, diagonalLoading=0.001)[source]#

MVDR/Capon spatial spectrum.

Parameters:
  • signal (ArrayLike)

  • arrayPositions (ArrayLike)

  • wavelength (float)

  • azimuthAxis (ArrayLike)

  • elevationAxis (ArrayLike | None)

  • diagonalLoading (float)

Return type:

NDArray[float64]

pyradar.rsp.doa_esprit(signal, *, numSources, spacing, wavelength)[source]#

Estimate ULA azimuths with rotational-invariance ESPRIT.

Parameters:
  • signal (ArrayLike)

  • numSources (int)

  • spacing (float)

  • wavelength (float)

Return type:

NDArray[float64]

pyradar.rsp.doa_music(signal, *, arrayPositions, wavelength, azimuthAxis, elevationAxis=None, numSources=1, forwardBackward=False)[source]#

MUSIC pseudospectrum for arbitrary array geometry.

Parameters:
  • signal (ArrayLike)

  • arrayPositions (ArrayLike)

  • wavelength (float)

  • azimuthAxis (ArrayLike)

  • elevationAxis (ArrayLike | None)

  • numSources (int)

  • forwardBackward (bool)

Return type:

NDArray[float64]

pyradar.rsp.doppler_fft(signal, *, radar=None, fftSize=None, loopAxis=-2, window=None, removeMean=None)[source]#

Apply a centered slow-time Doppler FFT.

Parameters:
  • signal (ArrayLike | RadarCube)

  • radar (Any)

  • fftSize (int | None)

  • loopAxis (int)

  • window (str | None)

  • removeMean (bool | None)

Return type:

RadarCube | NDArray[Any]

pyradar.rsp.estimate_doa(signal, *, radar, method=None, numSources=None)[source]#

Select and run a model-aware DoA method for one RD cell or snapshots.

Parameters:
  • signal (ArrayLike)

  • radar (Radar)

  • method (DoAMethod | None)

  • numSources (int | None)

Return type:

DoAResult

pyradar.rsp.goca_cfar_1d(power, **kwargs)[source]#
Parameters:

power (ArrayLike)

Return type:

CFARResult

pyradar.rsp.goca_cfar_2d(power, **kwargs)[source]#
Parameters:

power (ArrayLike)

Return type:

CFARResult

pyradar.rsp.micro_doppler_spectrogram(values, *, radar=None, sampleRate=None, segmentLength=128, overlap=None, fftSize=None, window='hann', axis=-1, detrend=False)[source]#

Compute slow-time micro-Doppler and an optional velocity coordinate.

Parameters:
  • values (ArrayLike)

  • radar (Radar | None)

  • sampleRate (float | None)

  • segmentLength (int)

  • overlap (int | None)

  • fftSize (int | None)

  • window (str)

  • axis (int)

  • detrend (bool)

Return type:

TimeFrequencyResult

pyradar.rsp.noncoherent_integrate(values, *, axis=0, power=True)[source]#

Sum magnitudes or powers along one axis.

Parameters:
  • values (ArrayLike)

  • axis (int)

  • power (bool)

Return type:

NDArray[float64]

pyradar.rsp.os_cfar_1d(power, **kwargs)[source]#
Parameters:

power (ArrayLike)

Return type:

CFARResult

pyradar.rsp.os_cfar_2d(power, **kwargs)[source]#
Parameters:

power (ArrayLike)

Return type:

CFARResult

pyradar.rsp.range_doppler_azimuth_fft(adc, *, radar=None, dims=None, **kwargs)[source]#

Convenience range, Doppler, and azimuth FFT composition.

Parameters:
Return type:

RadarCube | NDArray[Any]

pyradar.rsp.range_doppler_fft(adc, *, radar=None, dims=None, rangeFftSize=None, dopplerFftSize=None, sampleAxis=-1, loopAxis=-2, rangeWindow=None, dopplerWindow=None, removeRangeMean=None, removeDopplerMean=None)[source]#

Apply range and Doppler processing with optional model-aware MIMO decode.

Parameters:
Return type:

RadarCube | NDArray[Any]

pyradar.rsp.range_fft(adc, *, radar=None, fftSize=None, sampleAxis=-1, window=None, removeMean=None)[source]#

Apply the fast-time FFT.

Explicit keyword arguments override the attached Radar defaults. Raw ndarray input without a Radar returns an ndarray; model-aware input returns a RadarCube.

Parameters:
Return type:

RadarCube | NDArray[Any]

pyradar.rsp.remove_static_clutter(values, *, slowTimeAxis=0)[source]#

Suppress zero-Doppler clutter by subtracting the coherent mean.

Parameters:
  • values (ArrayLike)

  • slowTimeAxis (int)

Return type:

NDArray

pyradar.rsp.soca_cfar_1d(power, **kwargs)[source]#
Parameters:

power (ArrayLike)

Return type:

CFARResult

pyradar.rsp.soca_cfar_2d(power, **kwargs)[source]#
Parameters:

power (ArrayLike)

Return type:

CFARResult

pyradar.rsp.spatial_covariance(signal, *, channelAxis=-1, forwardBackward=False)[source]#

Estimate the spatial covariance matrix from one or more snapshots.

Parameters:
  • signal (ArrayLike)

  • channelAxis (int)

  • forwardBackward (bool)

Return type:

NDArray[complex128]

pyradar.rsp.spatial_smoothing(signal, *, subarraySize, forwardBackward=True)[source]#

Spatially smooth ULA snapshots for coherent-source estimation.

Parameters:
  • signal (ArrayLike)

  • subarraySize (int)

  • forwardBackward (bool)

Return type:

NDArray[complex128]

pyradar.rsp.spherical_to_cartesian(range, azimuth, elevation)[source]#

Convert radar spherical coordinates to right-handed FLU Cartesian.

Parameters:
  • range (ArrayLike)

  • azimuth (ArrayLike)

  • elevation (ArrayLike)

Return type:

NDArray[float64]

pyradar.rsp.steering_vector(arrayPositions, wavelength, azimuth, elevation=0.0)[source]#

Return far-field steering vectors for FLU array coordinates.

azimuth and elevation are broadcast together. The returned shape is broadcast_shape + (numChannels,).

Parameters:
  • arrayPositions (ArrayLike)

  • wavelength (float)

  • azimuth (ArrayLike)

  • elevation (ArrayLike | float)

Return type:

NDArray[complex128]

pyradar.rsp.stft(values, *, sampleRate, segmentLength=128, overlap=None, fftSize=None, window='hann', axis=-1, detrend=False, centered=True)[source]#

Compute a two-sided STFT with output shape (..., frequency, time).

Parameters:
  • values (ArrayLike)

  • sampleRate (float)

  • segmentLength (int)

  • overlap (int | None)

  • fftSize (int | None)

  • window (str)

  • axis (int)

  • detrend (bool)

  • centered (bool)

Return type:

TimeFrequencyResult

pyradar.rsp.unwrap_tdm_velocity(signal, *, radar, dopplerBin, ambiguityOrders=None)[source]#

Resolve a TDM Doppler alias from duplicate virtual phase centres.

Parameters:
signal:

Uncompensated decoded virtual-channel samples with channels on the last axis. Leading dimensions are treated as snapshots.

radar:

A TDM radar with calibrated overlapPairs.

dopplerBin:

Index on radar.velocityAxis before ambiguity resolution.

ambiguityOrders:

Optional integer alias candidates. By default candidates are limited to the raw chirp-rate Nyquist interval.

Parameters:
  • signal (ArrayLike)

  • radar (Radar)

  • dopplerBin (int)

  • ambiguityOrders (ArrayLike | None)

Return type:

DopplerUnwrapResult

Notes

Every candidate applies its true emission-time phase correction. The chosen candidate minimizes weighted circular phase error between channels sharing a physical virtual phase centre. If all overlap samples have zero energy, the unaliased candidate (order zero) is retained with an infinite score.

pyradar.rsp.window(length, name='hann')[source]#

Return a periodicity-independent symmetric processing window.

Parameters:
Return type:

NDArray[float64]

pyradar.rsp.zoom_fft(values, *, frequencyRange, sampleRate, fftSize, axis=-1, window='rectangular', endpoint=False)[source]#

Evaluate the DFT only over frequencyRange using Bluestein’s CZT.

Parameters:
Return type:

ZoomFFTResult