For anyone working with signals, time series, or periodic data in Python, the Fourier Transform is the core tool for frequency analysis. Use numpy.fft or scipy.fft when you need to decompose a signal into its constituent frequencies, analyze spectra, filter noise, or transform between time and frequency domains.
This guide gives you the fastest way to get useful results, covering what matters for students and engineers.
P.S. scroll to the bottom for a complete SciPy beginner’s learning path.
When to Use FFT in Python
Use FFT (Fast Fourier Transform) when you want to:
- Identify periodicities in data (e.g., frequencies in audio, vibration, financial series).
- Filter signals (remove noise, isolate components).
- Analyze spectral properties for engineering, science, or machine learning.
- Move between time and frequency domains for any 1D or multi-dimensional signal.
Choose numpy.fft for small to moderate signals and learning. Use scipy.fft for more features, speed, and compatibility with real-world (multi-dimensional, real-valued, or large) signals.
Getting Started: FFT Basics
Suppose you have a sampled signal and want to find out what frequencies are present.
import numpy as np
import matplotlib.pyplot as plt
# Create a sample signal: sum of two sine waves
fs = 500 # Sampling rate, Hz
t = np.arange(0, 1, 1/fs)
x = 2*np.sin(2*np.pi*50*t) + 0.5*np.sin(2*np.pi*120*t)
# Compute FFT
X = np.fft.fft(x)
freqs = np.fft.fftfreq(len(x), 1/fs)
# Plot spectrum
plt.plot(freqs[:len(x)//2], np.abs(X[:len(x)//2]) * 2 / len(x))
plt.xlabel('Frequency (Hz)')
plt.ylabel('Amplitude')
plt.title('FFT Spectrum')
plt.show()
This gives you the basic recipe: build your signal, run fft, plot the magnitude spectrum. You see sharp peaks at 50 Hz and 120 Hz.
Key points:
- Always scale the amplitude by 2/N for one-sided spectrum.
- Only plot positive frequencies for real signals (first half of freqs and X).
- Use np.fft.fft for simple cases; switch to scipy.fft.fft for better real/complex handling.
Using scipy.fft for Advanced Features
scipy.fft provides the same interface as numpy.fft, but supports multi-dimensional signals, real FFTs, and better performance on large arrays.
from scipy.fft import fft, fftfreq
X = fft(x)
freqs = fftfreq(len(x), 1/fs)
You can also use rfft and rfftfreq for real-valued input, which is faster and avoids redundant output:
from scipy.fft import rfft, rfftfreq
X = rfft(x)
freqs = rfftfreq(len(x), 1/fs)
plt.plot(freqs, np.abs(X) * 2 / len(x))
plt.show()
Filtering and Signal Processing with FFT
FFT enables quick frequency filtering. For example, to remove high-frequency noise, zero out unwanted frequencies and invert the FFT.
# Simple low-pass filter
X_filtered = X.copy()
X_filtered[freqs > 60] = 0
x_filtered = np.fft.ifft(X_filtered).real
plt.plot(t, x, label='Original')
plt.plot(t, x_filtered, label='Filtered')
plt.legend()
plt.show()
The high-frequency (120 Hz) component disappears, leaving only the 50 Hz wave.
Practical Tips and Troubleshooting
- Signal length: Pad your signal to the next power of two for speed, if required.
- Sampling rate: Always keep track of your fs (sampling frequency) for correct frequency axis.
- Windowing: If your signal is not periodic or is windowed, apply a window function (like np.hanning) before FFT to reduce spectral leakage.
- DC component: The zero-frequency term in the FFT output is the mean (average) of the signal.
- Real vs complex: For real signals, prefer rfft; for general use, fft handles any input.
Table: Essential FFT Functions in numpy.fft and scipy.fft
Function | Purpose | Notes |
---|---|---|
fft | FFT for any signal | Use with fftfreq |
ifft | Inverse FFT | Reconstructs time signal from spectrum |
rfft | FFT for real input | Faster, output is positive freq only |
irfft | Inverse real FFT | For reconstructing real time-domain signal |
fftfreq | Frequency bins for fft | Use with length N, sample spacing 1/fs |
rfftfreq | Freq bins for real FFT | Positive freq bins only |
When to Use Which FFT
- Use np.fft for basic teaching and compatibility.
- Use scipy.fft for large signals, higher speed, and advanced real/complex support.
- Use rfft and irfft when input data is known to be real-valued (audio, sensor, etc).
- Use multi-dimensional fft2, fftn, etc., for images and multidimensional arrays.
Skimmable Example: FFT of a Real Signal
from scipy.fft import rfft, rfftfreq, irfft
fs = 1000
t = np.linspace(0, 1, fs, endpoint=False)
signal = np.sin(2*np.pi*100*t) + 0.2*np.random.randn(fs)
# FFT
freqs = rfftfreq(len(signal), 1/fs)
spectrum = rfft(signal)
# Zero out frequencies above 150 Hz
spectrum[freqs > 150] = 0
# Inverse FFT
filtered = irfft(spectrum)
plt.plot(t, signal, alpha=0.7, label='Original')
plt.plot(t, filtered, label='Filtered')
plt.legend()
plt.show()
Summary
Use numpy.fft or scipy.fft for frequency analysis, filtering, and spectrum computation in Python. Start with rfft and rfftfreq for most real-world signals, and remember to scale and interpret your spectrum correctly. For multidimensional or large-scale problems, scipy.fft is the tool of choice.
SciPy Beginner’s Learning Path
- What is SciPy?
- Python SciPy tutorial
- How to install SciPy (Windows, MacOS, Linux)
- SciPy subpackages and library structure
- SciPy constants
- SciPy special functions
- SciPy linear algebra module
- SciPy integrate
- SciPy minimize
- SciPy interpolate
- SciPy integrate quad
- SciPy integrate solve_ivp
- SciPy fft
- SciPy signal
- Applying Filters with scipy.signal
- SciPy signal find_peaks
- SciPy ndimage