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.

Updated on: 2026-03-26T15:17:32+05:30

3K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements