[英]Plotting and extracting fft phase
Here is a code that compares fft phase plotting with 2 different methods :这是一个将 fft 相位绘图与 2 种不同方法进行比较的代码:
import numpy as np
import matplotlib.pyplot as plt
import scipy.fftpack
phase = np.pi / 4
f = 1
fs = f*20
dur=10
t = np.linspace(0, dur, num=fs*dur, endpoint=False)
y = np.cos(2 * np.pi * t + phase)
Y = scipy.fftpack.fftshift(scipy.fftpack.fft(y))
f = scipy.fftpack.fftshift(scipy.fftpack.fftfreq(len(t)))
p = np.angle(Y)
p[np.abs(Y) < 1] = 0
fig, ax = plt.subplots(2, 1)
ax[0].plot(t, y)
ax[1].plot(f*fs, p, label='from fft')
ax[1].phase_spectrum(y, fs, window=None, label='from phase_spectrum')
plt.legend()
plt.show()
here is the result :结果如下:
Here is result when signal number of period is not an integer :这是当周期的信号数不是整数时的结果:
I have several questions :我有几个问题:
Before the answer, just a small note:在回答之前,只是一个小说明:
Remove the p[np.abs(Y) < 1] = 0
line.删除
p[np.abs(Y) < 1] = 0
行。 Most of your spectrum has magnitude below 1, which is why, with this line, your spectrum looks mostly like a flat line at zero.您的大部分频谱的幅度都低于 1,这就是为什么使用这条线,您的频谱看起来最像一条位于 0 处的平线。
Now to the answer:现在回答:
phase_spectrum
does three things different than you: phase_spectrum
做了三件与你不同的事情:
np.unwrap(np.angle(Y))
.np.unwrap(np.angle(Y))
。angle_spectrum
instead.angle_spectrum
。window=None
, but, for some reason, matplotlib decided that window=None
means "use a hanning window, please" (see the docs ).window=None
,但是,出于某种原因,matplotlib 决定window=None
表示“请使用汉宁窗口”(请参阅文档)。window=lambda x: x
.window=lambda x: x
。
sides='twosided'
to the phase_spectrum
call.sides='twosided'
版本, phase_spectrum
sides='twosided'
phase_spectrum
sides='twosided'
传递给phase_spectrum
调用。 Now, about getting the phase at a frequency f
:现在,关于以频率
f
获取相位:
To do this, you must use the phase without unwrapping .为此,您必须使用相位而不展开.
You are right that you can't directly extract the phase of the single tone signal if you do not have an integer number of cycles.如果您没有整数个周期,您就不能直接提取单音信号的相位,这是对的。 That is because the singal's frequency does not fall exactly on top of any frequency bin in the FFT.
那是因为信号的频率并不完全落在 FFT 中任何频率仓的顶部。 You can get an approximation with the phase of the nearest bin, though.
不过,您可以获得最近 bin 相位的近似值。 You could also do a sinc interpolation of the spectrum to get its value at the frequency you want.
您还可以对频谱进行正弦插值,以在您想要的频率下获得其值。
If you only care about the phase of a single frequency f
, then you shouldn't use FFT at all.如果您只关心单个频率
f
的相位,那么您根本不应该使用 FFT。 The FFT computes the phase and amplitue at all frequencies. FFT 计算所有频率的相位和幅度。 If you only care about a single frequency, just do
Y_at_f = y @ np.exp(2j * np.pi * f * t)
and get that phase by np.angle(Y_at_f)
.如果您只关心单个频率,只需执行
Y_at_f = y @ np.exp(2j * np.pi * f * t)
并通过np.angle(Y_at_f)
获得该相位。
You can extract the phase referenced to the center of your data window by doing an fftshift (circular rotate by N/2) before the FFT.您可以通过在 FFT 之前执行 fftshift(圆形旋转 N/2)来提取参考数据窗口中心的相位。 This is because, after an fftshift, atan2() always is related to the ratio of oddness to eveness of the data around its center (as decomposed to an odd function plus an even function).
这是因为,在 fftshift 之后,atan2() 始终与围绕其中心的数据的奇数与偶数之比有关(分解为奇函数加偶函数)。
So calculate the phase of the signal in the middle of your window during its generation, and use that instead of the phase at the beginning.因此,在生成过程中计算窗口中间信号的相位,并使用它而不是开始时的相位。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.