Signals

signals

Digital signal processing functions.

Functionality handled includes pulse generation, determination of antenna phases for beamforming, filtering and downsampling of received signals, beamforming of filtered signals, and extraction of lag profiles from beamformed samples.

class src.utils.signals.DSP[source]

Bases: object

Performs the digital signal processing functions of Borealis.

static apply_bandpass_decimate(
input_samples,
bp_filters,
mixing_freqs,
dm_rate,
rx_rate,
)[source]

Apply a Frerking bandpass filter to the input samples.

Several different frequencies can be centered on simultaneously. Downsampling is done in simultaneously to reduce the computational load.

Parameters:
  • input_samples (xp.ndarray [num_channels, num_samples]) – The input IQ samples for each channel.

  • bp_filters (xp.ndarray [num_slices, num_taps]) – The bandpass filter(s).

  • mixing_freqs (list[float]) – The frequencies used to mix the first stage filter for bandpass

  • dm_rate (int) – The decimation rate of this stage

  • rx_rate (float) – The sampling rate

Returns:

Samples after bandpass filter and downsampling operations. Shape [num_slices, num_channels, samples]

Return type:

ndarray

static apply_lowpass_decimate(input_samples, lp_filter, dm_rate)[source]

Apply a lowpass filter to the baseband input samples. Downsampling is done in parallel via a strided window view of the input samples.

Parameters:
  • input_samples (ndarray [num_slices, num_channels, num_samples]) – Baseband input samples

  • lp_filter (xp.ndarray [1, num_taps]) – Lowpass filter taps

  • dm_rate (int) – The decimation rate of this stage

Returns:

Samples after lowpass filter and downsampling operations. Shape [num_slices, num_channels, samples]

Return type:

ndarray

static beamform_samples(filtered_samples, beam_phases)[source]

Beamform the filtered samples for multiple beams simultaneously.

Parameters:
  • filtered_samples (ndarray [num_slices, num_channels, num_samples]) – The filtered input samples.

  • beam_phases (ndarray [num_slices, num_beams, num_channels]) – The beam phases used to phase each channel’s samples before combining.

Returns:

Beamformed samples of shape [num_slices, num_beams, num_samples]

Return type:

np.ndarray

static correlations_from_samples(
beamformed_samples_1,
beamformed_samples_2,
output_sample_rate,
slice_metadata,
)[source]

Correlate two sets of beamformed samples together.

Parameters:
  • beamformed_samples_1 (np.ndarray [num_slices, num_beams, num_samples]) – The first beamformed samples

  • beamformed_samples_2 (np.ndarray [num_slices, num_beams, num_samples]) – The second beamformed samples

  • output_sample_rate (float) – Sampling rate of data

  • slice_metadata (list[dict]) – Details used to extract indices for each slice.

Returns:

Correlations for slices. List of length num_slices, with each entry having shape [num_beams, num_range_gates, num_lags].

Return type:

list[np.ndarray]

static create_filters(filter_taps, mixing_freqs, rx_rate)[source]

Makes bandpass filters and moves taps to the GPU, if available.

The first stage filters are mixed to bandpass and the low pass filters are reshaped. mixing_freqs should be given as offsets from the USRP center frequency. For example, with 12 MHz center frequency and a 10.5 MHz operating frequency, the mixing frequency should be -1.5 MHz.

Parameters:
  • filter_taps (list[np.ndarray]) – The filter taps from the experiment decimation scheme

  • mixing_freqs (list[float]) – The frequencies used to mix the first stage filter to make it a bandpass filter

  • rx_rate (float) – The rf rx rate.

Returns:

List of stages of filter taps. First stage is bandpass with shape [num_freqs, num_taps], subsequent stages are lowpass with shape [1, num_taps]. Filter taps are moved to the GPU if cupy is available.

Return type:

list[xp.ndarray]

__init__(
rx_rate,
filter_taps,
mixing_freqs,
dm_rates,
use_shared_mem=True,
)[source]

Create the filters and initialize parameters for signal processing operations.

Parameters:
  • rx_rate (float) – The sampling rate for the system [Hz]

  • filter_taps (list[np.ndarray]) – The filter taps to use at each stage

  • mixing_freqs (list[float]) – The freqs used to mix to baseband [Hz]

  • dm_rates (list[int]) – The decimation rates at each stage

  • use_shared_mem (bool) – Flag to use shared memory for CPU arrays

apply_filters(input_samples)[source]

Filter and downsample input_samples.

Results are stored in self.filter_outputs, on the same device (CPU/GPU) as input_samples.

Parameters:

input_samples (ndarray) – The samples to operate on, shape [num_channels, num_samples]

beamform(beam_phases)[source]

Applies the beamforming operation to the antennas_iq samples. Different beam directions are formed in parallel, and the results are stored in SharedMemory if so specified for this instance.

Parameters:

beam_phases (np.ndarray) – The complex phases used to beamform the filtered samples. Expects shape [num_slices, num_beams, num_channels].

cfs_freq_analysis(metadata, num_fft_points)[source]

Performs decimation and frequency analysis on clear frequency search data. Data will not be in shared memory.

Parameters:
  • metadata (dict) – Clear frequency search sequence metadata

  • num_fft_points (int) – Number of points used in the FFT. Determines the frequency resolution of where df = (rx_rate / total decimation rate) / num_fft_points

move_filter_results()[source]

Move the final results of filtering (antennas_iq data) to the CPU, optionally in SharedMemory if specified for this instance.

beamformed_samples: ndarray | None

Beamformed IQ data.

This field is populated by DSP.beamform() after DSP.apply_filters() has been called. The shape of the array is [num_slices, num_beams, num_samples].

filter_outputs: list[ndarray]

IQ data for each RX channel, with intermediate results of staged filters.

This field is populated by DSP.apply_filters() and will be a list of either cupy or numpy ndarray’s, depending on the type of input_samples parameter to DSP.apply_filters(). Entries are ordered by the filter stage, and each has shape [num_slices, num_channels, num_samples], where num_samples gets smaller with each successive filter stage.

src.utils.signals.basic_pulse_phase_offset(exp_slice, beam_iter)[source]

Calculate the phase difference of each pulse with respect to the first pulse based on the transmit frequency and the pulse separation.

Parameters:
  • exp_slice (ExperimentSlice) – The experiment slice information

  • beam_iter (int) – beam index

Returns:

Pulse phase offsets [radians]

Return type:

np.ndarray

src.utils.signals.get_phase_shift(beam_angle, freq_khz, antenna_locations)[source]

Find the complex excitation for all antennas to make beams in all given directions.

Parameters:
  • beam_angle (list[float]) – list of azimuthal direction of the beam off boresight, in degrees, positive beamdir being to the right of the boresight (looking along boresight from ground).

  • freq_khz (Union[float, list[float]]) – transmit frequency in kHz. Can be a single frequency or a list

  • antenna_locations (np.ndarray) – x-coordinates of each antenna in the array, in meters. Shape [num_antennas]

Returns:

phase_shift a 3D array of shape [freqs, beams, antennas] giving the complex excitation for each antenna required to form each beam for each frequency.

Return type:

phase_shift ndarray

src.utils.signals.get_samples(
sampling_rate,
mixing_freq,
pulse_len,
ramp_time,
max_amplitude,
)[source]

Get basic (not phase-shifted) samples for a given pulse.

Find the normalized sample array given the rate (Hz), frequency (Hz), pulse length (s).

Parameters:
  • sampling_rate (float) – USRP tx sample rate [Hz].

  • mixing_freq (float) – frequency offset from the centre frequency on the USRP [Hz]. To be mixed with the centre frequency before transmitting, e.g. centre = 12 MHz, wave_freq = + 1.2 MHz, output = 13.2 MHz.

  • pulse_len (float) – length of the pulse [s]

  • ramp_time (float) – ramp up and ramp down time for the pulse [s]. Typical 1.0e-5 s from config.ini

  • max_amplitude (float) – USRP’s max DAC amplitude. N200 = 0.707 max

Returns samples:

a numpy array of complex samples, representing all samples needed for a pulse of length pulse_len sampled at sampling_rate.

Return type:

np.ndarray