Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Matplotlib – How to plot the FFT of signal with correct frequencies on the X-axis?
To plot the FFT (Fast Fourier Transform) of a signal with correct frequencies on the X-axis in matplotlib, we need to properly compute the frequency bins and visualize the power spectrum.
Understanding FFT Frequency Calculation
The key to plotting FFT with correct frequencies is using np.fft.fftfreq() which returns the discrete Fourier Transform sample frequencies. For real signals, we typically plot only the positive frequencies using np.fft.rfftfreq().
Basic FFT Plot with Normalized Frequencies
Here's how to create a basic FFT plot with normalized frequencies ?
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams["figure.figsize"] = [10, 6]
plt.rcParams["figure.autolayout"] = True
# Signal parameters
N = 512 # Number of samples
t = np.arange(N)
m = 8
nu = float(m) / N
# Create a sine wave signal
signal = np.sin(2 * np.pi * nu * t)
# Compute FFT
ft = np.fft.fft(signal)
# Get frequency bins (normalized)
freq = np.fft.fftfreq(N)
# Plot power spectrum
power = ft.real**2 + ft.imag**2
plt.plot(freq, power)
plt.xlabel('Normalized Frequency')
plt.ylabel('Power')
plt.title('FFT with Normalized Frequencies')
plt.grid(True)
plt.show()
FFT Plot with Real Frequencies in Hz
To display actual frequencies in Hz, we need to specify the sampling rate ?
import numpy as np
import matplotlib.pyplot as plt
# Signal parameters
fs = 1000 # Sampling frequency in Hz
T = 1.0 / fs # Sampling period
N = 1024 # Number of samples
t = np.linspace(0.0, N*T, N, endpoint=False)
# Create a composite signal (50Hz + 120Hz + noise)
signal = np.sin(50.0 * 2.0 * np.pi * t) + 0.5 * np.sin(120.0 * 2.0 * np.pi * t)
signal += 0.1 * np.random.randn(N) # Add some noise
# Compute FFT
ft = np.fft.fft(signal)
# Get frequency bins in Hz
freq = np.fft.fftfreq(N, T)
# Plot only positive frequencies
plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
plt.plot(t[:100], signal[:100])
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.title('Original Signal')
plt.grid(True)
plt.subplot(1, 2, 2)
plt.plot(freq[:N//2], np.abs(ft)[:N//2])
plt.xlabel('Frequency (Hz)')
plt.ylabel('Magnitude')
plt.title('FFT - Frequency Domain')
plt.grid(True)
plt.show()
Using rfft for Real Signals
For real-valued signals, np.fft.rfft() is more efficient as it computes only positive frequencies ?
import numpy as np
import matplotlib.pyplot as plt
# Parameters
fs = 500 # Sampling frequency
duration = 2.0 # Signal duration in seconds
N = int(fs * duration)
t = np.linspace(0, duration, N, endpoint=False)
# Create signal with multiple frequency components
f1, f2, f3 = 25, 50, 100 # Frequencies in Hz
signal = (np.sin(2*np.pi*f1*t) +
0.6*np.sin(2*np.pi*f2*t) +
0.3*np.sin(2*np.pi*f3*t))
# Compute FFT for real signal
ft = np.fft.rfft(signal)
freq = np.fft.rfftfreq(N, 1/fs)
# Plot results
plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.plot(t[:200], signal[:200])
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.title('Time Domain Signal')
plt.grid(True)
plt.subplot(1, 2, 2)
plt.plot(freq, np.abs(ft))
plt.xlabel('Frequency (Hz)')
plt.ylabel('Magnitude')
plt.title('FFT Magnitude Spectrum')
plt.grid(True)
plt.xlim(0, 150)
plt.show()
Key Parameters Summary
| Parameter | Description | Usage |
|---|---|---|
N |
Number of samples | Determines frequency resolution |
fs |
Sampling frequency | Sets the frequency range (0 to fs/2) |
np.fft.fftfreq() |
Frequency bins | Returns both positive and negative frequencies |
np.fft.rfftfreq() |
Real FFT frequency bins | Returns only positive frequencies |
Conclusion
To plot FFT with correct frequencies, use np.fft.fftfreq() with the sampling rate to get frequency bins in Hz. For real signals, np.fft.rfft() and np.fft.rfftfreq() provide a more efficient approach by computing only positive frequencies.
