Skip to main content

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."

Documentation

The wheel ships its documentation inside the package, in gri_signal/docs/, so it is available wherever the package is installed:

  • overview.md -- conventions, the subpackage map, recipes, and gotchas
  • api_summary.md -- every public function and signature (generated)

Print the directory with python -c "import gri_signal, pathlib; print(pathlib.Path(gri_signal.__file__).parent / 'docs')". Every example in those files is run by the test suite.

Installation

pip install gri-signal

For development:

git clone https://gitlab.com/geosol-foss/python/gri-signal.git
cd gri-signal
uv sync

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.

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(eirp_dbw, range_m, freq_hz, noise_temp_k, bandwidth_hz, *, atmo_loss_db=0, collector_gain_dbi=0): Single-pulse SNR, received power minus kTB noise (dB).

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
psd_db, freqs = 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.

Release files for gri-signal 0.2.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for gri-signal 0.2.5
File Size Uploaded
gri_signal-0.2.5.tar.gz 89.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for gri-signal 0.2.5
File Interpreter ABI Platform
gri_signal-0.2.5-py3-none-any.whl Python 3 none any Details

Total release size: 178.5 kB

Release files / gri_signal-0.2.5.tar.gz

Download URL gri_signal-0.2.5.tar.gz
Size 89.9 kB
Tags Source
SHA-256 checksum
How to use checksums
01e24e7f03e10954b621aece5401a5cd98e412dc7498792164a04f202507c946
BLAKE2b-256 checksum
How to use checksums
4d041e441b300c9403aa865959229be12b4500528fdfd38390b07813ef0566df
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.9.30 {"installer":{"name":"uv","version":"0.9.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / gri_signal-0.2.5-py3-none-any.whl

Download URL gri_signal-0.2.5-py3-none-any.whl
Size 88.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4d4e045caf64794b34eccb334dab5d054e5f01b0bdfee84150c44ca25aaff892
BLAKE2b-256 checksum
How to use checksums
7f10c1625b154cbd636d3c77d8753ee17e4b9ca98ec13b41785e846ae69072f3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.9.30 {"installer":{"name":"uv","version":"0.9.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

0.2.5 This release

2 release files

0.2.4

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page