RF Datacube
RF datacube creation and processing.
Provides helpers to allocate a pulse-Doppler datacube, compute range and frequency axes, apply a matched filter via fast convolution, and Doppler-process the slow-time dimension with an FFT.
data_cube(fs, prf, N_p)
Creates an empty, complex-valued datacube.
This function initializes a 2D NumPy array (datacube) with zeros, representing the raw data collected over a coherent processing interval (CPI). The dimensions are determined by the number of range bins and the number of pulses.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fs
|
float
|
The sampling frequency in Hertz [Hz]. |
required |
prf
|
float
|
The pulse repetition frequency in Hertz [Hz]. |
required |
N_p
|
int
|
The number of pulses in the coherent processing interval (CPI). |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
np.ndarray: A 2D NumPy array of shape (N_range_bins, N_pulses) initialized with complex zeros. |
Source code in src/rad_lab/rf_datacube.py
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | |
doppler_process(datacube, fs)
Performs Doppler processing on a radar datacube.
This function applies a Fast Fourier Transform (FFT) across the slow-time (pulse) dimension of the datacube to transform the data into the Range-Doppler domain. The operation is performed in-place on the input datacube. It also generates the corresponding Doppler frequency and range axes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
datacube
|
ndarray
|
A 2D NumPy array representing the time-domain datacube, with shape (N_range_bins, N_pulses). This array will be modified in-place. |
required |
fs
|
float
|
The sampling frequency in Hertz [Hz]. |
required |
Returns:
| Type | Description |
|---|---|
tuple[ndarray, ndarray]
|
tuple[np.ndarray, np.ndarray]: A tuple containing:
- f_axis (np.ndarray): The Doppler frequency axis, [-PRF/2, PRF/2) [Hz].
- R_axis (np.ndarray): The range axis |
Source code in src/rad_lab/rf_datacube.py
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | |
matchfilter(datacube, pulse_wvf, pedantic=True, window='none', window_kwargs=None)
Applies a matched filter to a datacube for pulse compression.
Mirrors a real-time hardware matched filter (FIR with coefficients
p*[-n]): output is the raw discrete correlation with no additional
scaling. For a unit-amplitude transmit pulse of N_taps samples the
peak output is V_rx · N_taps where N_taps = T · fs ≈ T · B is
the pulse-compression (TB) gain.
Two implementations are available: - Pedantic (True): Iteratively applies the matched filter to each pulse using a time-domain helper function. This is typically slower but can be clearer to understand. - Non-pedantic (False): Uses a more efficient frequency-domain approach by performing convolution via FFT. This involves a single FFT of the waveform kernel and is generally faster for large datacubes.
Pass window to weight the replica for range-sidelobe control: this
suppresses the ~-13.2 dB LFM sidelobes that a CFAR detector would otherwise
flag as spurious targets around a strong return, at the cost of a broader
mainlobe and a small SNR loss. See range_window and Richards,
FRSP 2nd ed., Ch. 4.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
datacube
|
ndarray
|
2D time-domain datacube with shape (N_range_bins, N_pulses), modified in-place. |
required |
pulse_wvf
|
ndarray
|
1D transmitted pulse template (unit-amplitude convention,
see |
required |
pedantic
|
bool
|
If True, use the iterative time-domain helper; if False, use FFT-based convolution. Defaults to True. |
True
|
window
|
str
|
Range weighting applied to the replica. |
'none'
|
window_kwargs
|
dict | None
|
Optional dict forwarded to the window function. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
None |
None
|
The |
Source code in src/rad_lab/rf_datacube.py
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 | |
number_range_bins(fs, prf)
Calculates the number of range bins.
The number of range bins is determined by the number of samples collected during one pulse repetition interval (PRI). PRI is the reciprocal of the pulse repetition frequency (PRF).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fs
|
float
|
The sampling frequency [Hz]. |
required |
prf
|
float
|
The pulse repetition frequency [Hz]. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
int |
int
|
The total number of range bins. |
Source code in src/rad_lab/rf_datacube.py
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | |
range_axis(fs, N_r)
Generates the range axis for a radar datacube.
This function calculates the range corresponding to each range bin based on the sampling frequency. The range resolution is determined by the speed of light and the sampling rate.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fs
|
float
|
The sampling frequency in Hertz [Hz]. |
required |
N_r
|
int
|
The number of range bins (samples in fast-time). |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
np.ndarray: A 1D NumPy array representing the range axis in meters [m]. |
Source code in src/rad_lab/rf_datacube.py
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | |
range_window(n_taps, window='none', window_kwargs=None)
Unit-mean amplitude taper for weighting a matched-filter replica.
Weighting the replica across its N_taps samples suppresses the range
sidelobes of the compressed pulse:
- An LFM's frequency is linear in time, so a time taper tapers the swept-spectrum edges -- the frequency weighting Richards uses for range-sidelobe control. The unweighted LFM sits at ~-13.2 dB peak sidelobes; weighting drives these down (e.g. Hamming ~-43 dB).
- The cost is a broader mainlobe (coarser range resolution) and a small SNR loss from the now-mismatched filter.
- Normalising to unit mean keeps the coherent peak gain at
N_taps, so the loss shows up as a raised noise floor, not a rescaled peak.
Window vocabulary matches create_window.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_taps
|
int
|
Length of the taper (number of replica samples). |
required |
window
|
str
|
Window type. One of |
'none'
|
window_kwargs
|
dict | None
|
Optional dict forwarded to the underlying
|
None
|
Returns:
| Type | Description |
|---|---|
ndarray
|
1D taper of length |
References
Richards, M. A., Fundamentals of Radar Signal Processing, 2nd ed., McGraw-Hill, 2014, Ch. 4 (Radar Waveforms) — matched filtering, LFM pulse compression, and range-sidelobe reduction by weighting.
Source code in src/rad_lab/rf_datacube.py
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | |