π‘ Problem Formulation: When working with signal processing in Python, you might be interested in visualizing the frequency content of a signal. This article explains how to plot a longitudinal magnitude spectrum using the matplotlib library. An example of input could be a time-series data, and the desired output is the corresponding spectrum showing magnitude vs frequency.
Method 1: Using the matplotlib and numpy libraries
This method utilizes the power of numpy for numerical operations combined with matplotlib for plotting. The function numpy.fft.fft()
computes the one-dimensional discrete Fourier Transform, while matplotlib.pyplot.plot()
is used to plot the magnitude spectrum.
Here’s an example:
import numpy as np import matplotlib.pyplot as plt # Time-domain signal t = np.linspace(0, 1, 1000, False) sine_wave = np.sin(2*np.pi*10*t) # Compute the frequency spectrum fft_vals = np.fft.fft(sine_wave) fft_freq = np.fft.fftfreq(len(fft_vals)) # Plot the magnitude spectrum plt.plot(fft_freq, np.abs(fft_vals)) plt.show()
The output is a figure showing the frequency content of the sine wave signal.
This code generates a sine wave and computes its Fourier Transform to convert it from the time domain to the frequency domain. The absolute value of the Fourier Transform (magnitude) is then plotted using matplotlib, which reveals the signal’s frequency components.
Method 2: Applying a window function before FFT
Applying a window function can reduce spectral leakage. This is done by multiplying the signal with a window function before performing the FFT. The numpy.hanning()
function is an example of a window function.
Here’s an example:
import numpy as np import matplotlib.pyplot as plt # Time-domain signal t = np.linspace(0, 1, 1000, False) sine_wave = np.sin(2*np.pi*10*t) # Apply a window function window = np.hanning(len(sine_wave)) sine_wave = sine_wave * window # Compute the frequency spectrum fft_vals = np.fft.fft(sine_wave) fft_freq = np.fft.fftfreq(len(fft_vals)) # Plot the magnitude spectrum plt.plot(fft_freq, np.abs(fft_vals)) plt.show()
The output is a magnitude spectrum plot that benefits from reduced spectral leakage due to the windowing process.
By windowing the signal before applying the FFT, we can minimize the effects of spectral leakage, which happens due to the discontinuities at the edges of a signal that is not periodic within the FFT frame. This method provides a cleaner spectrum, showcasing more accurate frequency components.
Method 3: Using scipy’s signal.periodogram
The scipy library offers the signal.periodogram
function, which estimates the power spectral density using a fast Fourier transform. This can be a quick and efficient approach to obtain the magnitude spectrum without dealing with FFT explicitly.
Here’s an example:
from scipy import signal import matplotlib.pyplot as plt import numpy as np # Generate a test signal t = np.linspace(0, 1, 1000, False) signal = np.sin(2*np.pi*10*t) # Compute the power spectral density frequencies, spectrum = signal.periodogram(signal) # Plot the magnitude spectrum plt.semilogy(frequencies, spectrum) plt.show()
The output is a power spectral density plot on a log scale, showing the magnitude of different frequencies in the signal.
The signal.periodogram
function abstracts away the need to manually compute and plot the magnitude spectrum. It provides a straightforward way to analyze signals and is particularly useful for quick analyses.
Method 4: Logarithmic plotting for better clarity
Plotting the magnitude spectrum on a logarithmic scale can provide better clarity, especially when dealing with signals with a wide range of magnitudes. Matplotlib’s pyplot.semilogy()
function helps to plot data on a logarithmic scale.
Here’s an example:
import numpy as np import matplotlib.pyplot as plt # Generate a test signal t = np.linspace(0, 1, 1000, False) signal = np.sin(2*np.pi*10*t) # Compute the frequency spectrum fft_vals = np.fft.fft(signal) fft_freq = np.fft.fftfreq(len(fft_vals)) # Plot the magnitude spectrum on a logarithmic scale plt.semilogy(fft_freq, np.abs(fft_vals)) plt.show()
The output is a logarithmic plot of the magnitude spectrum, highlighting the frequency components more clearly.
This method emphasizes the strength of different components of the signal by scaling the magnitude to a logarithmic scale. It can be useful for observing subtle features in the signal that might not be clearly visible on a linear scale.
Bonus One-Liner Method 5: Using mlab’s specgram function
Matplotlib’s mlab module provides a one-liner function called specgram()
to plot the spectrogram which includes the magnitude spectrum over time.
Here’s an example:
import matplotlib.pyplot as plt import numpy as np # Generate a test signal t = np.linspace(0, 1, 1000, False) signal = np.sin(2*np.pi*10*t) # Plot the spectrogram plt.specgram(signal, Fs=1/dt) plt.show()
The output is a spectrogram which displays the signal’s magnitude spectrum over time.
plt.specgram()
function is a quick and potent tool, it can be used for a comprehensive overview when both frequency content and its evolution over time are of interest. This one-liner can be incredibly useful for initial explorations of the signal characteristics.
Summary/Discussion
- Method 1: Matplotlib and Numpy. Simple and direct. Less sophisticated, may lead to spectral leakage.
- Method 2: Windowed FFT. Improved spectral accuracy. Adds complexity by requiring a window function.
- Method 3: Scipy’s Periodogram. Abstract and powerful. Might not offer as much flexibility for advanced applications.
- Method 4: Logarithmic Scale. Enhances clarity. Can distort the perception of relative differences in lower magnitudes.
- Method 5: Mlab’s Specgram. Comprehensive one-liner. More suitable for signal dynamics over time rather than just a static spectrum.