Skip to main content

Signal processing for filtering, spectral analysis, correlation, and beamforming

Project description

GeoSol Research Logo

Signal Processing Library

Signal processing utilities for signal generation, channel simulation, modulation, sampling, filtering, spectral analysis, correlation, beamforming, pulse detection, and link-budget computation. Requires Python 3.12+.

This library provides functional signal processing tools designed to be composable and efficient. All functions support both 1D and multi-channel (row-major: channels x samples) signals where applicable.

Mathematical Background

Filter design tradeoffs. Three filter implementations are provided for each filter type, each with different characteristics:

  • Butterworth (IIR): Maximally flat passband response. Uses zero-phase filtering (sosfiltfilt) for zero phase distortion. Lowest order for a given transition width, but infinite impulse response means feedback.
  • FIR: Linear phase, no feedback (always stable). Hamming window design. Higher order than IIR for equivalent stopband attenuation, but predictable group delay.
  • FFT-domain: Steepest possible cutoff (brick-wall in frequency). Applied via multiplication in the frequency domain with Hann smoothing at transitions. Best rejection but assumes periodic signals.

Power spectral density. PSD estimates the power distribution across frequency, computed via |FFT(x)|^2 / N and reported in dB.

Cross-correlation for delay estimation. The cross-correlation R_xy[k] = sum(x[n] * conj(y[n-k])) peaks at the lag corresponding to the time delay between signals. Quadratic interpolation (qint) refines the peak location to sub-sample precision.

References: Oppenheim & Willsky, "Signals and Systems"; Proakis & Manolakis, "Digital Signal Processing."

Installation

pip install gri-signal

For development:

git clone https://gitlab.com/geosol-foss/python/gri-signal.git
cd gri-signal
. .init_venv.sh

Signal Flow

The library is organized around the standard signal processing pipeline:

sources -> modulation -> channel -> sampling -> [filters/spectral/correlation/beamforming]

Sources

Signal generation functions for creating test signals and waveforms:

  • tone(fs, freq, ...): Complex sinusoidal tone with optional windowing
  • prn(fs, ...): Pseudorandom noise (white or bandlimited)
  • pri(fs, freq, pri_interval, pulse_width, ...): Pulsed signal with constant PRI
  • zeros(fs, ...): Zero-filled signal array
  • ula_steering(aoa_deg, d, wavelength, n_elements): ULA steering vector for multi-channel signal generation
  • generate_complex_signal(...): Multi-component test signal with tones, chirps, AM, PM

Channel

Propagation effects for simulating signal transmission:

  • delay(sig, delay_time, fs): Sub-sample precision time delay via FFT
  • awgn(sig, snr_db): Additive white Gaussian noise
  • attenuation(sig, db): Amplitude scaling (gain or loss)
  • doppler(sig, fs, f_shift, *, f_rate=0.0): Doppler frequency shift with optional linear drift
  • multipath(sig, fs, delays, amplitudes): Tapped delay line multipath channel

Modulation

Analog modulation schemes:

  • mod_am(sig, fs, f_carrier, *, mod_index=1.0): Amplitude modulation
  • demod_am(sig, fs, f_carrier): AM envelope detection
  • mod_fm(sig, fs, f_carrier, *, freq_deviation): Frequency modulation
  • demod_fm(sig, fs, f_carrier, *, freq_deviation): FM frequency discrimination
  • mod_pm(sig, fs, f_carrier, *, phase_deviation): Phase modulation
  • demod_pm(sig, fs, f_carrier, *, phase_deviation): PM phase extraction

Digital modulation schemes (baseband, rectangular pulses):

  • mod_bpsk(bits, fs, symbol_rate): Binary Phase Shift Keying (1 bit/symbol)
  • demod_bpsk(sig, fs, symbol_rate): BPSK hard decision
  • mod_qpsk(bits, fs, symbol_rate): Quadrature PSK (2 bits/symbol, Gray coded)
  • demod_qpsk(sig, fs, symbol_rate): QPSK hard decision
  • mod_qam(bits, fs, symbol_rate, *, order=16): QAM (4/16/64/256, Gray coded)
  • demod_qam(sig, fs, symbol_rate, *, order=16): QAM nearest-neighbor decision

IQ conversion:

  • passband_to_iq(sig, fs, f_center): Real passband to complex baseband
  • iq_to_passband(sig, fs, f_center): Complex baseband to real passband

Sampling

Digitization and quantization:

  • adc(sig, n_bits): Simulate n-bit analog-to-digital converter

Filters

Lowpass Filters

Three implementations with different tradeoffs:

  • lowpass_butter: Butterworth IIR filter (scipy SOS, zero-phase via sosfiltfilt)
  • lowpass_fir: FIR filter (Hamming window design, less phase ringing)
  • lowpass_fft: FFT-domain filter (steepest cutoff, Hann smoothing)

Highpass Filters

  • highpass_butter: Butterworth highpass
  • highpass_fir: FIR highpass
  • highpass_fft: FFT-domain highpass

Bandpass Filters

  • bandpass_butter: Butterworth bandpass
  • bandpass_fir: FIR bandpass
  • bandpass_fft: FFT-domain bandpass

Notch (Bandstop) Filters

Attenuate a frequency band while passing all others (useful for interference rejection):

  • notch_butter: Butterworth notch/bandstop
  • notch_fir: FIR notch/bandstop
  • notch_fft: FFT-domain notch/bandstop

Analytic Bandpass Filters

Complex-valued bandpass filters returning analytic signals for single-sideband processing:

  • analytic_bandpass_butter: Butterworth-based analytic
  • analytic_bandpass_fir: FIR-based analytic
  • analytic_bandpass_fft: FFT-based analytic (handles negative/positive frequencies)

Spectral Analysis

PSD computation and frequency mapping:

  • get_psd(fs, sig): Power Spectral Density (dB-scaled, shifted frequency)
  • get_max_power(fs, sig): Find dominant frequency and power
  • get_psd_power(f, psd, freq): Query PSD at specific frequency
  • get_freq_idx(f, fs, n): Frequency-to-bin mapping

Signal quality metrics:

  • estimate_snr(fs, sig, *, signal_bw, signal_center): Estimate SNR in dB
  • estimate_noise_floor(fs, sig, *, percentile): Estimate noise floor in dB
  • sinad(fs, sig, *, fundamental_freq): Signal-to-Noise and Distortion ratio
  • thd(fs, sig, *, fundamental_freq, num_harmonics): Total Harmonic Distortion

Time-frequency analysis:

  • effective_bandwidth(fs, sig, *, method): RMS or threshold-based bandwidth in Hz
  • effective_duration(fs, sig, *, method): RMS or threshold-based duration in seconds
  • estimate_tbp(fs, sig, *, method): Time-bandwidth product (dimensionless)

Correlation

  • xcorr(sig1, sig2, max_lags=None): MATLAB-style cross-correlation with lags
  • qint(x3p, y3p): Quadratic interpolation for sub-sample peak resolution

Beamforming

Single-section processing:

  • adaptive_beamform(sig): Adaptive beamforming with spatial covariance and eigenvalue decomposition
  • steering_angles(steering_vecs): Compute steering angles from eigenvectors

Batch processing (for multiple sections):

  • batch_adaptive_beamform(sig): Vectorized beamforming for all sections
  • batch_steering_angles(steering_vecs): Batch steering angle computation

Detection

Threshold-based pulse detection on IQ envelopes and scoring against ground-truth labels:

  • detect_pulses(iq, sample_rate_hz, min_pri_s, *, threshold_frac=0.4): Returns sample indices of detected peaks. Uses scipy.signal.find_peaks with PRI-derived minimum separation and zero-padded boundary handling.
  • match_detections(detected_indices, truth_starts, ...): Returns a DetectionResult with matched/missed/false-alarm counts, per-match timing errors, and a .detection_rate accessor.

Link Budget

Standard link-equation primitives in the dB domain:

  • eirp_dbw(peak_power_w, antenna_gain_dbi): Effective isotropic radiated power (dBW).
  • fspl_db(range_m, freq_hz): Free-space path loss (dB).
  • noise_power_dbw(noise_temp_k, bandwidth_hz): Thermal noise power N = k T B (dBW).
  • received_power_dbw(eirp_dbw, range_m, freq_hz, *, atmo_loss_db=0, collector_gain_dbi=0): Received power after FSPL, atmospheric loss, and collector gain.
  • multipath_received_power_dbw(...), multipath_relative_db(...): Multipath reflection variants.
  • snr_db(received_power_dbw, noise_power_dbw): Signal-to-noise ratio.

Constants exported alongside: C (speed of light), K_BOLTZMANN, K_BOLTZMANN_DB.

Example Usage

from gri_signal import (
    # Sources
    tone, prn, pri, ula_steering,
    # Channel
    delay, awgn, attenuation, doppler, multipath,
    # Sampling
    adc,
    # Filters
    lowpass_butter, bandpass_fft,
    # Analysis
    get_psd, xcorr, qint,
)

# Generate a 100 Hz tone
fs = 10e3  # 10 kHz sample rate
sig = tone(fs, 100, duration=1.0)

# Add channel effects
sig = delay(sig, 0.001, fs)  # 1ms delay
sig = doppler(sig, fs, 50.0)  # 50 Hz Doppler shift
sig = awgn(sig, 20.0)  # 20 dB SNR
sig = attenuation(sig, 6.0)  # 6 dB loss

# Digitize
sig = adc(sig, 12)  # 12-bit ADC

# Filter
filtered = lowpass_butter(fs, 200, sig)  # 200 Hz cutoff

# Analyze
freqs, psd_db = get_psd(fs, filtered)

# Generate multi-channel array signal from a source at 30 degrees
wavelength = 3e8 / 915e6  # 915 MHz
steering = ula_steering(30.0, wavelength/2, wavelength, n_elements=4)
array_sig = steering[:, None] * sig  # (4, n_samples)

Design Patterns

All functions follow consistent conventions:

  • Functional: Pure functions, no classes (composable, testable)
  • Signature: func(fs, params, sig, *, optional_params) for processing functions
  • Input/Output: Signal arrays with same shape preserved
  • Safety: Uses sig.copy() where needed to avoid modifying original data
  • Multi-channel: Row-major format (channels as rows)

Dependencies

  • numpy: Array operations
  • scipy: Filter design and signal processing

Other Projects

Current list of other GRI FOSS Projects we are building and maintaining.

License

MIT License. See LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gri_signal-0.2.3.tar.gz (105.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gri_signal-0.2.3-py3-none-any.whl (80.7 kB view details)

Uploaded Python 3

File details

Details for the file gri_signal-0.2.3.tar.gz.

File metadata

  • Download URL: gri_signal-0.2.3.tar.gz
  • Upload date:
  • Size: 105.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for gri_signal-0.2.3.tar.gz
Algorithm Hash digest
SHA256 fbf7b759069818ad1e5ebe9581918152ccce9f9f2599079cc181ec7df801e6cf
MD5 611523900f952788d1c0f83462ef1063
BLAKE2b-256 535fdc5111ab8c1e45d8e9c91cceb056790ccdfc8e3a6f4f8382fac9a8112e7e

See more details on using hashes here.

File details

Details for the file gri_signal-0.2.3-py3-none-any.whl.

File metadata

  • Download URL: gri_signal-0.2.3-py3-none-any.whl
  • Upload date:
  • Size: 80.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for gri_signal-0.2.3-py3-none-any.whl
Algorithm Hash digest
SHA256 28e22cad1704cd43a5a95de922729cba2e1a10bb608a5b79e352e9612b311eee
MD5 a6e5b2156bfd943bf5e7162589ae6000
BLAKE2b-256 491ba96f550f8c37107f881d860bab48b8f81482f7fb0df5a908e1449d0552ed

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page