FFT无法检测到实验数据中已知周期性预期频率的原因及解决方法
Hey there! Let's break down why your FFT isn't showing the expected peaks and how to fix it step by step.
First, Why the FFT Isn't Working as Expected
There are two key issues with your current approach:
Incorrect calculation of the angular step
dPhi
You converted your angles to radians first, then tried to convert the difference between two radians values back to radians withnp.deg2rad(angles[2]-angles[1])—that's a double conversion mistake! Sinceanglesis already in radians,angles[2]-angles[1]is already the step size in radians (equal tonp.deg2rad(2)for your 2° step data). Wrapping that in anothernp.deg2rad()completely skews your frequency axis, making the expected peaks show up in the wrong place (or not at all).Misinterpretation of FFT frequency units
Your function's periodicities are defined as cycles per 360°, but your currentfreqscalculation gives you frequencies in cycles per radian. Without converting these to the units you care about (cycles per full 360° rotation), you can't easily spot the 2 and 4 cycle peaks.
Additionally, let's confirm the expected frequencies from your model:
Your fit function uses squared cosines, which expand using the identity cos²θ = (1 + cos2θ)/2. Expanding your full function:
Rxx(Phi) = (A/2 + B/2 + const) + (A/2)cos(2π(Phi-Phi₀)/180) + (B/2)cos(4π(Phi-Phi₀)/180)
This means you should see:
- A large DC (zero-frequency) peak from the constant terms
- A peak at 2 cycles per 360° (from the
cos(2π(Phi-Phi₀)/180)term) - A peak at 4 cycles per 360° (from the
cos(4π(Phi-Phi₀)/180)term)
How to Fix It
Let's correct your code step by step to get the right FFT results:
Step 1: Fix the angular step calculation
Instead of double-converting radians, directly use the step size from your radians array (or even better, work with degrees directly for more intuitive frequency units):
Corrected Code (Working with Degrees)
import numpy as np import pandas as pd import matplotlib.pyplot as plt from scipy.fft import fft, fftfreq # Import data data = pd.read_csv("test") x = data["Phi"].to_numpy() # Phi in degrees (0 to 360, step 2°) Rxx = data["Rxx"].to_numpy() N = len(x) dx = x[1] - x[0] # Step size in degrees (should be 2°) # Compute FFT and frequencies fft_Rxx = fft(Rxx) # freqs here are in cycles per degree freqs = fftfreq(N, d=dx) # Convert to cycles per 360° (what you care about) cycles_per_360 = freqs * 360 # Get amplitude spectrum (normalize by N for better scaling) amplitude_Rxx = np.abs(fft_Rxx) / N # Plot only positive frequencies (FFT is symmetric, so we don't need negative half) positive_mask = cycles_per_360 >= 0 plt.plot(cycles_per_360[positive_mask], amplitude_Rxx[positive_mask]) plt.xlabel("Cycles per 360°") plt.ylabel("Amplitude") plt.title("FFT of Rxx vs. Phi") plt.xlim(0, 10) # Zoom in to see 2 and 4 clearly plt.grid(True) plt.show()
Alternative: Working with Radians (If You Prefer)
If you want to stick with radians, fix the step size and convert frequencies properly:
import numpy as np import pandas as pd import matplotlib.pyplot as plt from scipy.fft import fft, fftfreq data = pd.read_csv("test") x = data["Phi"].to_numpy() Rxx = data["Rxx"].to_numpy() angles = np.deg2rad(x) dPhi = angles[1] - angles[0] # Step size in radians (no extra deg2rad!) N = len(angles) fft_Rxx = fft(Rxx) # freqs here are cycles per radian freqs = fftfreq(N, d=dPhi) # Convert to cycles per 360° (since 360° = 2π radians) cycles_per_360 = freqs * 2 * np.pi amplitude_Rxx = np.abs(fft_Rxx) / N positive_mask = cycles_per_360 >= 0 plt.plot(cycles_per_360[positive_mask], amplitude_Rxx[positive_mask]) plt.xlabel("Cycles per 360°") plt.ylabel("Amplitude") plt.xlim(0,10) plt.grid(True) plt.show()
What You'll See After Fixing
Once you run the corrected code, you should clearly see:
- A large peak at 0 cycles (DC component from the constants in your model)
- A peak at 2 cycles per 360°
- A peak at 4 cycles per 360°
The low-frequency artifact you saw before was likely due to the incorrect frequency axis scaling from the double radian conversion—fixing that step aligns the FFT results with your expected periodicities.
备注:内容来源于stack exchange,提问作者kuba_pol

