Field Guide · technology

Also known as: NumPy, SciPy, numpy scipy dsp, scipy.signal

NumPy and SciPy are the pair of Python libraries that make the language a practical workbench for signal processing: NumPy supplies fast vectorized N-dimensional arrays (including complex types), and SciPy’s scipy.signal and scipy.fft modules add ready-made DSP routines — filter design, convolution, FFTs, resampling, and spectral estimation.12 Together they are the default tools for offline software-defined-radio work: loading a recorded IQ file, inspecting it, prototyping an algorithm, and checking the result — all in a few lines of Python.

IQ file(complex64) np.fromfile→ ndarray scipy.signalfilter / FFT spectrum /plot whole arrays processed at once — no per-sample Python loop
A typical offline SDR session: NumPy reads an IQ recording into a complex array, scipy.signal filters and transforms it, and the spectrum is plotted — all on whole arrays, avoiding slow per-sample loops.

How it works

The foundation is NumPy’s ndarray: a contiguous, typed buffer that operations run over as a whole. Crucially for SDR it has native complex types — complex64 (two 32-bit floats) matches the interleaved float IQ that most SDR tools write, so np.fromfile(path, dtype=np.complex64) loads an entire recording into a baseband array in one call. Arithmetic, mixing (multiplying by a complex exponential to shift frequency), and magnitude/phase all become vectorized expressions, and the interpreter overhead of Python’s per-element loops is avoided because the work happens in compiled C and BLAS underneath.

SciPy layers the DSP algorithms on top. scipy.signal designs and applies filters (firwin, butter, lfilter, sosfilt, filtfilt — see FIR filters), resamples (resample, resample_poly, decimate), correlates, and estimates spectra (welch, spectrogram); scipy.fft (and numpy.fft) provide the FFT for turning a block of samples into a spectrum. A handful of these calls reproduces the core of a receive chain — decimate, shift, filter, demodulate — well enough to validate an idea before it is reimplemented in a fast language.

In practice

The everyday use is analysis and prototyping, not real-time reception. Paired with Matplotlib for plotting (and often Jupyter notebooks), NumPy/SciPy let you open a capture, plot its spectrum and spectrogram, measure SNR, design a filter and see its response, try a demodulator on a slice of samples, and generate reference test signals. The main caveats are speed and streaming: pure-Python/NumPy is fine for megabyte-scale files but not for sustained real-time multi-megasample throughput, and the array model wants the whole signal in memory rather than an endless stream — which is exactly why production receivers are written in C, C++, Rust, or Go.

Relevance to SDR

NumPy and SciPy are the lingua franca for reasoning about SDR signals: nearly every tutorial, research paper, and algorithm prototype in the field is expressed in them, and they are the standard way to generate the golden reference vectors against which a fast implementation is checked. Their role is upstream of the receiver — design and verify here, then port to a real-time language.

That upstream/downstream split is exactly GopherTrunk’s relationship to them. GT is the real-time receiver written in Go for a single dependency-free binary, so it does not run NumPy or SciPy in its decode path. But the analysis around GT lives comfortably in this world: a recorded IQ file that GT replays can be loaded with np.fromfile and examined with scipy.signal to measure SNR and EVM, confirm a channel’s center offset, or independently resample a capture — the kind of cross-check GT’s own DSP notes rely on when deciding whether a decode failure lives in the samples or in the code.

Sources

  1. NumPy documentation — the ndarray, complex dtypes, and FFT routines used for array-based signal processing. 

  2. scipy.signal reference — SciPy, the filter-design, resampling, correlation, and spectral-estimation routines for DSP. 

See also