Resampling and Interpolation
Why Resampling Matters
Real-world signals often arrive at different sampling rates that must be harmonized for processing. Audio might be at 44.1 kHz, while a control system runs at 1 kHz. Wireless baseband signals may need to be upsampled for digital-to-analog conversion or downsampled after the ADC. SciPy provides both FFT-based and polyphase resampling methods, each with distinct trade-offs.
Definition: FFT-Based Resampling
FFT-Based Resampling
scipy.signal.resample changes the number of samples by:
- Computing the FFT of the input
- Truncating or zero-padding the spectrum to the target length
- Computing the inverse FFT
from scipy.signal import resample
y = resample(x, num=2*len(x)) # upsample by 2
y = resample(x, num=len(x)//3) # downsample by 3
This is exact for bandlimited signals (no aliasing) but assumes periodicity, which can cause artifacts at the signal boundaries.
Definition: Polyphase Resampling
Polyphase Resampling
scipy.signal.resample_poly resamples by a rational factor
using a polyphase FIR filter:
- Upsample by (insert zeros between samples)
- Apply an anti-aliasing FIR lowpass filter
- Downsample by (keep every -th sample)
from scipy.signal import resample_poly
y = resample_poly(x, up=3, down=2) # resample by 3/2
This method does not assume periodicity and handles arbitrary rational resampling factors efficiently.
resample_poly is generally preferred over resample for
non-periodic signals. It uses a Kaiser-windowed sinc filter
whose length can be controlled via the window parameter.
Definition: 1D Interpolation with interp1d
1D Interpolation with interp1d
scipy.interpolate.interp1d constructs an interpolating function
from discrete data points:
from scipy.interpolate import interp1d
f_linear = interp1d(x_data, y_data, kind='linear')
f_cubic = interp1d(x_data, y_data, kind='cubic')
y_new = f_cubic(x_new)
Available methods: 'linear', 'nearest', 'quadratic', 'cubic'.
For new code, prefer make_interp_spline over interp1d (which
is considered legacy in SciPy >= 1.12).
Definition: Cubic Spline Interpolation
Cubic Spline Interpolation
A cubic spline fits piecewise cubic polynomials between data points, ensuring continuity of the function and its first two derivatives at each knot:
from scipy.interpolate import CubicSpline
cs = CubicSpline(t_data, y_data)
y_new = cs(t_new)
y_deriv = cs(t_new, 1) # first derivative
y_integral = cs.integrate(a, b) # definite integral
Cubic splines avoid the Runge phenomenon (oscillation at boundaries) that plagues high-degree polynomial interpolation.
Definition: Multi-Dimensional Interpolation on Regular Grids
Multi-Dimensional Interpolation on Regular Grids
RegularGridInterpolator interpolates data defined on a regular
(rectilinear) grid in dimensions:
from scipy.interpolate import RegularGridInterpolator
interp = RegularGridInterpolator(
(x_grid, y_grid, z_grid), data_3d, method='linear'
)
values = interp(np.array([[x, y, z]]))
Supported methods: 'linear', 'nearest', 'slinear',
'cubic', 'quintic'.
Theorem: Ideal Reconstruction (Whittaker-Shannon)
A bandlimited signal sampled above the Nyquist rate can be perfectly reconstructed using sinc interpolation:
where and .
Each sample contributes a sinc function centered at its position.
The sinc functions are orthogonal at the sample points, so the
sum passes exactly through each sample while interpolating smoothly
between them. This is what scipy.signal.resample approximates.
Example: Resampling a Signal from 44.1 kHz to 48 kHz
Resample a signal from 44100 Hz to 48000 Hz using both
resample and resample_poly. Compare the results.
Apply both methods
from scipy.signal import resample, resample_poly
import numpy as np
fs_in = 44100
fs_out = 48000
duration = 0.1
t_in = np.arange(0, duration, 1/fs_in)
x = np.sin(2*np.pi*1000*t_in)
# FFT-based
n_out = int(len(x) * fs_out / fs_in)
y_fft = resample(x, n_out)
# Polyphase (simplify ratio: 48000/44100 = 160/147)
from math import gcd
g = gcd(fs_out, fs_in)
y_poly = resample_poly(x, fs_out // g, fs_in // g)
Both produce a 48 kHz signal. resample_poly is preferred
because it does not assume signal periodicity.
Example: Smooth Interpolation with Cubic Splines
Given 10 irregularly-spaced data points, create a smooth interpolant
using CubicSpline and evaluate it on a fine grid.
Fit and evaluate the spline
from scipy.interpolate import CubicSpline
import numpy as np
np.random.seed(42)
t_data = np.sort(np.random.rand(10)) * 10
y_data = np.sin(t_data) + 0.1 * np.random.randn(10)
cs = CubicSpline(t_data, y_data)
t_fine = np.linspace(t_data[0], t_data[-1], 500)
y_fine = cs(t_fine)
# Derivative and integral
dy = cs(t_fine, 1) # first derivative
integral = cs.integrate(t_data[0], t_data[-1])
Example: 2D Interpolation on a Regular Grid
Interpolate a coarsely-sampled 2D function onto a finer grid using
RegularGridInterpolator with both linear and cubic methods.
Setup and interpolate
from scipy.interpolate import RegularGridInterpolator
import numpy as np
# Coarse grid
x = np.linspace(0, 4, 10)
y = np.linspace(0, 4, 10)
X, Y = np.meshgrid(x, y, indexing='ij')
Z = np.sin(X) * np.cos(Y)
interp_linear = RegularGridInterpolator((x, y), Z, method='linear')
interp_cubic = RegularGridInterpolator((x, y), Z, method='cubic')
# Fine grid
x_fine = np.linspace(0, 4, 100)
y_fine = np.linspace(0, 4, 100)
pts = np.array(np.meshgrid(x_fine, y_fine, indexing='ij')).reshape(2, -1).T
Z_cubic = interp_cubic(pts).reshape(100, 100)
Resampling Explorer
Visualize the effect of upsampling and downsampling on a signal. Compare FFT-based and polyphase resampling methods.
Parameters
Resampling and Interpolation Recipes
# Code from: ch07/python/resampling.py
# Load from backend supplements endpointQuick Check
What advantage does resample_poly have over resample?
It is always faster
It does not assume the signal is periodic
It can handle complex-valued signals
It uses less memory
resample uses the FFT, which implicitly assumes periodicity. resample_poly uses a polyphase FIR filter that handles signal boundaries correctly.
Common Mistake: Using resample on Non-Periodic Signals
Mistake:
Applying scipy.signal.resample to a signal that is not periodic.
The FFT-based method assumes periodicity, causing ringing artifacts
at the signal boundaries.
Correction:
Use resample_poly for non-periodic signals:
y = resample_poly(x, up=3, down=2) # no periodicity assumption
Key Takeaway
Use resample_poly for general-purpose resampling (no periodicity
assumption). Use CubicSpline for smooth interpolation of
irregularly-spaced data. For multi-dimensional data on regular
grids, use RegularGridInterpolator. Always ensure anti-aliasing
when downsampling.
Interpolation
The process of estimating values between known data points. Common methods include linear, cubic spline, and sinc interpolation.
Related: Why Resampling Matters, cubic spline
Resampling Methods Compared
| Method | Assumes Periodic? | Rational Factor? | Anti-Alias? | Best For |
|---|---|---|---|---|
| resample (FFT) | Yes | Any factor | Implicit (truncation) | Periodic signals, exact integer ratios |
| resample_poly | No | Rational p/q | FIR lowpass | General signals, large ratios |
| interp1d / CubicSpline | No | Arbitrary | No (must pre-filter) | Irregular grids, derivative access |