Fourier Transforms — Core Concepts
What a Fourier transform does
Every signal — audio, image, sensor data — can be represented as a sum of sine and cosine waves at different frequencies, amplitudes, and phases. The Fourier transform converts a signal from its original domain (usually time or space) into the frequency domain, revealing which frequencies are present and how strong they are.
The Discrete Fourier Transform (DFT) operates on sampled data: N equally spaced samples go in, N complex numbers come out. Each complex number encodes the amplitude and phase of one frequency component.
The FFT algorithm
Computing the DFT directly requires O(N²) operations. The Fast Fourier Transform (FFT), discovered by Cooley and Tukey in 1965, reduces this to O(N log N) by recursively splitting the problem. For N = 1,000,000, that is the difference between 10¹² and 2×10⁷ operations — the reason real-time audio processing is possible.
import numpy as np
# Generate a signal: 50 Hz + 120 Hz sine waves
sample_rate = 1000 # Hz
t = np.arange(0, 1.0, 1 / sample_rate)
signal = np.sin(2 * np.pi * 50 * t) + 0.5 * np.sin(2 * np.pi * 120 * t)
# Compute FFT
fft_result = np.fft.fft(signal)
frequencies = np.fft.fftfreq(len(signal), d=1/sample_rate)
# Only positive frequencies matter (signal is real)
positive_mask = frequencies >= 0
magnitudes = np.abs(fft_result[positive_mask]) / len(signal)
The magnitudes array peaks at 50 Hz and 120 Hz — exactly the frequencies we put in.
Reading FFT output
The output of np.fft.fft is an array of complex numbers:
- Magnitude (
np.abs) — how strong each frequency is - Phase (
np.angle) — the timing offset of each wave - Frequencies — mapped by
np.fft.fftfreq, ranging from 0 to ±sample_rate/2
For real-valued signals, the FFT output is symmetric. The first half contains the useful information; the second half is a mirror. Use np.fft.rfft to compute only the positive-frequency half, saving half the computation.
The Nyquist limit
You can only detect frequencies up to half the sampling rate — this is the Nyquist frequency. A signal sampled at 44,100 Hz (CD quality) can represent frequencies up to 22,050 Hz, which conveniently covers human hearing.
Frequencies above the Nyquist limit “fold back” and appear as lower frequencies — a phenomenon called aliasing. This is why audio recording always includes a low-pass filter before digitization.
Inverse FFT
The inverse transform reconstructs the original signal from its frequency components:
reconstructed = np.fft.ifft(fft_result)
np.allclose(signal, reconstructed.real) # True
This round-trip property is fundamental: you can transform to the frequency domain, modify specific frequencies (filtering), and transform back.
2D FFT for images
Images are 2D signals. The 2D FFT reveals spatial frequency patterns — edges, textures, and periodic noise:
image_fft = np.fft.fft2(grayscale_image)
magnitude_spectrum = np.log(1 + np.abs(np.fft.fftshift(image_fft)))
Low frequencies (center of the shifted spectrum) represent smooth regions. High frequencies (edges) represent sharp transitions. JPEG compression works by discarding high-frequency components that human eyes barely notice.
Windowing
Real signals have finite length, which causes spectral leakage — energy smearing into adjacent frequency bins. Windowing functions taper the signal edges to reduce this:
from scipy.signal import windows
window = windows.hann(len(signal))
windowed_signal = signal * window
fft_windowed = np.fft.fft(windowed_signal)
Common windows: Hann (general purpose), Hamming (similar to Hann), Blackman (better sidelobe suppression), and Kaiser (tunable).
Common misconception
People often think the FFT tells you when different frequencies occur. It does not — the standard FFT gives you frequency content averaged over the entire signal. To know when frequencies appear, you need the Short-Time Fourier Transform (STFT), which applies the FFT to overlapping windows of the signal.
One thing to remember: The FFT converts a signal from time to frequency, revealing what the signal is made of — but for “when,” you need windowed approaches like the STFT.
See Also
- Python Bayesian Inference How updating your beliefs with new evidence works — and why it helps computers make smarter guesses.
- Python Convolution Operations The sliding-window trick that lets computers sharpen photos, recognize faces, and hear words in noisy audio.
- Python Genetic Algorithms How computers borrow evolution's playbook — survival of the fittest, mutation, and reproduction — to solve problems too complicated for brute force.
- Python Linear Algebra Numpy Why solving puzzles with rows and columns of numbers is the secret engine behind search engines, video games, and AI.
- Python Markov Chains Why the next thing that happens often depends only on what is happening right now — and how that one rule generates text, predicts weather, and powers board games.