[英]How do I use np.fft.fft() to correctly identify “peak energy” and also get the associated winding frequencies?
I conceptually understand Fourier transforms.我从概念上理解傅里叶变换。 I wrote a naive algorithm to compute the transform, decompose a wave and plot it's individual components.
我写了一个简单的算法来计算变换,分解波和 plot 它是单独的组件。 I know it's not 'fast', and it also doesn't reconstruct the right amplitude.
我知道它不是“快”,它也不能重建正确的幅度。 It was just meant to code the math behind the machinery, and it gives me this nice output:
它只是为了编写机器背后的数学代码,它给了我这个不错的 output:
Questions问题
np.fft
np.fft
做类似的事情 I've tried a few things.我已经尝试了几件事。 However, when I use
p = np.fft.fft(signal)
on the same exact wave as the above, I get really wacky plots, like this one:但是,当我在与上述相同的波形上使用
p = np.fft.fft(signal)
时,我会得到非常古怪的图,比如这个:
f1 = 3
f2 = 5
start = 0
stop = 1
sample_rate = 0.005
x = np.arange(start, stop, sample_rate)
y = np.cos(f1 * 2 * np.pi * x) + np.sin(f2 * 2 * np.pi *x)
p = np.fft.fft(y)
plt.plot(np.real(p))
Or if I try to use np.fft.freq()
to get the right frequencies for the horizontal axis:或者,如果我尝试使用
np.fft.freq()
来获得水平轴的正确频率:
p = np.fft.fft(y)
f = np.fft.fftfreq(y.shape[-1], d=sampling_rate)
plt.plot(f, np.real(p))
And as a recent addition, my attempt to implement @wwii's suggestions resulted in an improvement, but the frequency powers are still off in the transform:作为最近的补充,我尝试实施@wwii 的建议导致了改进,但转换中的频率功率仍然关闭:
f1 = 3
f2 = 5
start = 0
stop = 4.5
sample_rate = 0.01
x = np.arange(start, stop, sample_rate)
y = np.cos(f1 * 2 * np.pi * x) + np.sin(f2 * 2 * np.pi *x)
p = np.fft.fft(y)
freqs= np.fft.fftfreq(y.shape[-1], d=sampling_rate)
q = np.abs(p)
q = q[freqs > 0]
f = freqs[freqs > 0]
peaks, _ = find_peaks(q)
peaks
plt.plot(f, q)
plt.plot(freqs[peaks], q[peaks], 'ro')
plt.show()
So again, my question is, how do I use np.fft.fft
and np.fft.fftfreqs
to get the same information as my naive method does?再说一次,我的问题是,我如何使用
np.fft.fft
和np.fft.fftfreqs
来获得与我的幼稚方法相同的信息? And secondly, how do I recover amplitude information from the fft (amplitude of the component waves that add up to the composite).其次,我如何从 fft(叠加到复合波的分量波的幅度)中恢复幅度信息。
I've read the documentation, but it is far from helpful.我已经阅读了文档,但它远没有帮助。
For context here is my my naive method:对于上下文,这是我天真的方法:
def wind(timescale, data, w_freq):
"""
wrap time-series data around complex plain at given winding frequency
"""
return data * np.exp(2 * np.pi * w_freq * timescale * 1.j)
def transform(x, y, freqs):
"""
Returns center of mass of each winding frequency
"""
ft = []
for f in freqs:
mapped = wind(x, y, f)
re, im = np.real(mapped).mean(), np.imag(mapped).mean()
mag = np.sqrt(re ** 2 + im ** 2)
ft.append(mag)
return np.array(ft)
def get_waves(parts, time):
"""
Generate sine waves based on frequency parts.
"""
num_waves = len(parts)
steps = len(time)
waves = np.zeros((num_waves, steps))
for i in range(num_waves):
waves[i] = np.sin(parts[i] * 2 * np.pi * time)
return waves
def decompose(time, data, freqs, threshold=None):
"""
Decompose and return the individual components of a composite wave form.
Plot each component wave.
"""
powers = transform(time, data, freqs)
peaks, _ = find_peaks(powers, threshold=threshold)
plt.plot(freqs, powers, 'b.--', label='Center of Mass')
plt.plot(freqs[peaks], powers[peaks], 'ro', label='Peaks')
plt.xlabel('Frequency')
plt.legend(), plt.grid()
plt.show()
return get_waves(freqs[peaks], time)
And the signal set-up I used to generate the plots:我用来生成图的信号设置:
# sample data plot: sin with frequencey of 3 hz.
f1 = 3
f2 = 5
start = 0
stop = 1
sample_rate = 0.005
x = np.arange(start, stop, sample_rate)
y = np.cos(f1 * 2 * np.pi * x) + np.sin(f2 * 2 * np.pi *x)
plt.plot(x, y, '.')
plt.xlabel('time')
plt.ylabel('amplitude')
plt.show()
freqs = np.arange(0, 20, .5)
waves = decompose(x, y, freqs, threshold=0.12)
for w in waves:
plt.plot(x, w)
plt.show()
f1 = 3
f2 = 5
start = 0
stop = 1
sample_rate = 0.005
x = np.arange(start, stop, sample_rate)
y = np.cos(f1 * 2 * np.pi * x) + np.sin(f2 * 2 * np.pi *x)
p = np.fft.fft(y)
freqs = np.fft.fftfreq(y.shape[0],sample_rate)
The fft returns the complex values so you need the sqrt of the sum of the squares like you did for mag
in transform
. fft 返回复数值,因此您需要平方和的 sqrt ,就像您在
transform
中对mag
所做的那样。
>>> p[:2] array([-1.42663659e-14+0.00000000e+00j, -1.77635684e-15+1.38777878e-17j])
q = np.absolute(p)
>>> q[:2] array([1.77641105e-15, 2.70861628e-14])
fft
and fftfreqs
give you both sides of the transform reflected around zero hz. fft
和fftfreqs
为您提供反映在零赫兹附近的变换的两侧。 You can see the negative frequencies at the end.你可以在最后看到负频率。
>>> freqs[-10:]
array([-10., -9., -8., -7., -6., -5., -4., -3., -2., -1.])
You only care about the positive frequencies so you can filter for them and plot.您只关心正频率,因此您可以过滤它们和 plot。
q = q[freqs > 0]
freqs = freqs[freqs > 0]
plt.bar(freqs,q)
plt.show()
plt.close()
freqs >= 0
.freqs >= 0
。 For me, this was/is an awesome resource - The Scientist and Engineer's Guide to Digital Signal Processing - it's on my desk at work.对我来说,这是/现在是一个很棒的资源—— 《科学家和工程师数字信号处理指南》 ——它在我的办公桌上。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.