π‘ Problem Formulation: When working with signal processing in Python, you may need to visualize the phase spectrum of a signal to analyze its frequency characteristics. This article explains how to plot a phase spectrum using Matplotlib, starting with the signal’s Fast Fourier Transform (FFT). The input is a time-domain signal, and the desired output is a plot showing the phase angle versus frequency.
Method 1: Basic Phase Spectrum Plot
This method involves computing the phase spectrum of a signal using the numpy.fft
module and then plotting it with Matplotlib. The numpy.angle
function is used to extract phase information from the FFT of the signal.
Here’s an example:
import numpy as np import matplotlib.pyplot as plt # Time-domain signal example t = np.linspace(0, 1, 500, endpoint=False) signal = np.sin(2 * np.pi * 5 * t) # FFT of the signal fft_signal = np.fft.fft(signal) freqs = np.fft.fftfreq(len(signal)) # Compute phase spectrum phase_spectrum = np.angle(fft_signal) # Plot phase spectrum plt.figure() plt.plot(freqs, phase_spectrum, label="Phase Spectrum") plt.xlabel('Frequency [Hz]') plt.ylabel('Phase [Radians]') plt.title('Phase Spectrum') plt.legend() plt.show()
The above code snippet generates an FFT of a sine wave signal, calculates the corresponding phase angles, and plots them as a function of frequency. The phase spectrum helps to identify the phase of each frequency component present in the signal.
Method 2: Unwrapping Phase Angles
To avoid discontinuities in the phase spectrum plot, phase angles can be unwrapped using the np.unwrap
function. This method changes abrupt jumps by 2Ο to their 2Ο complement.
Here’s an example:
# Same initial steps from Method 1 are assumed here # Unwrap the phase angles to avoid discontinuities unwrapped_phase_spectrum = np.unwrap(phase_spectrum) # Plot unwrapped phase spectrum plt.figure() plt.plot(freqs, unwrapped_phase_spectrum, label="Unwrapped Phase Spectrum") plt.xlabel('Frequency [Hz]') plt.ylabel('Phase [Radians]') plt.title('Unwrapped Phase Spectrum') plt.legend() plt.show()
In this code snippet, the np.unwrap
function is used after computing the phase spectrum to create a continuous plot, which is easier to interpret, especially for signals with complex phase behavior.
Method 3: Handling Negative Frequencies
Since FFTs produce symmetric results for negative and positive frequencies, it’s often useful to plot only the positive half of the frequency spectrum. This method uses conditional array slicing to select only the positive frequencies.
Here’s an example:
# Same initial steps from Method 1 are assumed here # Select half the spectrum, positive frequencies only half_n = len(signal) // 2 positive_freqs = freqs[:half_n] positive_phase_spectrum = phase_spectrum[:half_n] # Plot phase spectrum for positive frequencies plt.figure() plt.plot(positive_freqs, positive_phase_spectrum, label="Positive Frequencies Phase Spectrum") plt.xlabel('Frequency [Hz]') plt.ylabel('Phase [Radians]') plt.title('Phase Spectrum for Positive Frequencies') plt.legend() plt.show()
This snippet fine-tunes the frequency spectrum visualization by plotting only the phase associated with positive frequencies. It simplifies the plot and makes it more relevant for most practical applications, where negative frequencies are often redundant.
Method 4: Phase Spectrum with Magnitude Threshold
When plotting the phase spectrum, it might be useful to consider only those frequencies that have a magnitude above a certain threshold, which allows for a more focused analysis of significant frequency components.
Here’s an example:
# Same initial steps from Method 1 are assumed here # Magnitude threshold magnitude_threshold = 0.1 magnitudes = np.abs(fft_signal) # Mask elements below threshold significant_phases = phase_spectrum[magnitudes > magnitude_threshold] # Plot phase spectrum with magnitude threshold plt.figure() plt.plot(freqs[magnitudes > magnitude_threshold], significant_phases, label="Significant Phases") plt.xlabel('Frequency [Hz]') plt.ylabel('Phase [Radians]') plt.title('Phase Spectrum with Magnitude Threshold') plt.legend() plt.show()
The code here filters out the phase information for frequency components with magnitudes below the defined threshold. This results in a phase spectrum that highlights only the significant frequency components, hence potentially revealing the true characteristics of the signal.
Bonus One-Liner Method 5: Phase Spectrum with Log Scale
For signals with a wide range of frequencies, it might be beneficial to plot the phase spectrum on a logarithmic scale which can potentially reveal details in lower frequency components that might be missed in a linear scale.
Here’s an example:
# Same initial steps from Method 1 are assumed here # Plotting with log scale for frequency plt.figure() plt.semilogx(freqs, phase_spectrum, basex=10, label="Phase Spectrum") plt.xlabel('Frequency [Hz]') plt.ylabel('Phase [Radians]') plt.title('Log Scale Phase Spectrum') plt.legend() plt.show()
In this one-liner method, the Matplotlib’s semilogx
function is used to generate a phase spectrum plot where the x-axis (frequency) is scaled logarithmically, providing a detailed view across a broad range of frequencies.
Summary/Discussion
- Method 1: Basic Phase Spectrum Plot. This method is straightforward and suitable for simple signals. However, it might not handle phase discontinuities well.
- Method 2: Unwrapping Phase Angles. Unwrapping provides a continuous phase plot, which eases interpretation. It may introduce artificial trends if not used judiciously.
- Method 3: Handling Negative Frequencies. Removing negative frequencies simplifies the plot. Care should be taken with complex signals where negative frequencies are informative.
- Method 4: Phase Spectrum with Magnitude Threshold. This approach focuses on significant components, but small but potentially important details might be missed.
- Method 5: Phase Spectrum with Log Scale. Useful for a broad spectrum, though it can be less intuitive for those unfamiliar with log scale interpretation.