简体   繁体   English

如何使用 np.fft.fft() 正确识别“峰值能量”并获得相关的绕组频率?

[英]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问题

  1. How do I do something similar with np.fft我如何用np.fft做类似的事情
  2. How do I recover whatever winding frequencies numpy chose under the hood?如何恢复 numpy 在引擎盖下选择的任何绕组频率?
  3. How do I recover the amplitude of component waves that I find using the transform?如何恢复使用变换找到的分量波的幅度?

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.fftnp.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. fftfftfreqs为您提供反映在零赫兹附近的变换的两侧。 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()

结果图


  • If there is a dc component and you want to see it your filter would be freqs >= 0 .如果有一个 dc 组件并且您想查看它,您的过滤器将是freqs >= 0
  • Your example has 200 data points so you get 100 (n/2) positive frequencies and the graph ranges from zero to one hundred Hz with peaks at three and five.您的示例有 200 个数据点,因此您得到 100 (n/2) 个正频率,图表范围从零到一百赫兹,峰值在三和五。
  • numpy.fft.rfft only computes the positive frequencies. numpy.fft.rfft只计算正频率。 Using numpy.fft.rfftfreq to get the frequencies.使用 numpy.fft.rfftfreq 获取频率。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM