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

scipy.signal.resample changes the number of samples by:

  1. Computing the FFT of the input
  2. Truncating or zero-padding the spectrum to the target length
  3. 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

scipy.signal.resample_poly resamples by a rational factor p/qp/q using a polyphase FIR filter:

  1. Upsample by pp (insert pβˆ’1p-1 zeros between samples)
  2. Apply an anti-aliasing FIR lowpass filter
  3. Downsample by qq (keep every qq-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

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

A cubic spline fits piecewise cubic polynomials between data points, ensuring continuity of the function and its first two derivatives at each knot:

Si(t)=ai+bi(tβˆ’ti)+ci(tβˆ’ti)2+di(tβˆ’ti)3S_i(t) = a_i + b_i(t - t_i) + c_i(t - t_i)^2 + d_i(t - t_i)^3

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

RegularGridInterpolator interpolates data defined on a regular (rectilinear) grid in NN 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:

x(t)=βˆ‘n=βˆ’βˆžβˆžx[n] sinc ⁣(tβˆ’nTsTs)x(t) = \sum_{n=-\infty}^{\infty} x[n]\, \mathrm{sinc}\!\left(\frac{t - nT_s}{T_s}\right)

where sinc(u)=sin⁑(Ο€u)/(Ο€u)\mathrm{sinc}(u) = \sin(\pi u)/(\pi u) and Ts=1/fsT_s = 1/f_s.

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.

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.

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.

Resampling Explorer

Visualize the effect of upsampling and downsampling on a signal. Compare FFT-based and polyphase resampling methods.

Parameters

Resampling and Interpolation Recipes

python
Complete examples: resample, resample_poly, interp1d, CubicSpline, RegularGridInterpolator, and make_interp_spline.
# Code from: ch07/python/resampling.py
# Load from backend supplements endpoint

Quick 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

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

MethodAssumes Periodic?Rational Factor?Anti-Alias?Best For
resample (FFT)YesAny factorImplicit (truncation)Periodic signals, exact integer ratios
resample_polyNoRational p/qFIR lowpassGeneral signals, large ratios
interp1d / CubicSplineNoArbitraryNo (must pre-filter)Irregular grids, derivative access