在带有噪声的数据中寻找峰值,使用find_peaks_cwt函数。

3
我正在尝试找到一些非常嘈杂的数据中的峰值,如下图所示: 在不太理解术语的情况下,我将峰值定义为狭窄的(宽度<30),并且比附近区域高出100000以上。
我试图使用scipy的find_peaks_cwt,但文档对我来说不太清楚。我尝试了find_peaks_cwt(my_data, np.arange(1,30)),但返回了大量峰值。然后我尝试添加了noise_perc=60参数,但这并没有真正解决问题。我还尝试调整其他参数,但我不太理解'ridge line'是什么意思。
我应该做些什么不同的事情?像我想象的那样,widths=np.arange(1,30)是否设置了我的宽度要求?如何指定高度要求?

一个对我来说效果更好的替代方法是先使用高斯窗口卷积手动过滤信号,然后搜索极大值(参见此答案)。 - Puco4
1个回答

4
很多事情取决于你的数据实际意义是什么(或者你认为它们应该代表什么)。这里有一个使用合成数据的例子:
from scipy.signal import find_peaks_cwt
from matplotlib.pyplot import plot, ylim
from numpy import *
N = 2000
x = arange(N)
pwid = 200.
zideal = sinc(x/pwid - 2)**2 # Vaguely similar to yours
z = zideal * random.randn(N)**2 # adding noise
plot(x, zideal, lw=4)
ylim(0, 1)
zf = find_peaks_cwt(z, pwid/4+zeros(N))
plot(x[zf], zideal[zf], '*', ms=20, color='green')
# Create averaging zones around peaks
xlow = maximum(array(zf) - pwid/2, 0)
xhigh = minimum(array(zf) + pwid/2, x.max())
zguess = 0*xlow # allocate space
for ii in range(len(zf)):
   zguess[ii] = z[xlow[ii]:xhigh[ii]].mean()
plot(x[zf], zguess, 'o', ms=10, color='red')

pwidth参数用于调整 sinc() 函数中峰值的宽度。在调用 find_peaks_cwt() 函数时,使用较大的 widths 值会产生较少的峰值(峰值密度更低)。最佳结果似乎是将 widths 中的缩放值设置为峰值的半高全宽(HWHM)的约一半。

find_peaks_cwt() 函数在找到理想数据的峰值方面表现得相当不错。在峰值周围进行求和是猜测峰值值的一种方式。如果您正在对谱功率进行求和,则应该将所有值之间的值相加,而不是像我为这个快速而简单的演示所做的那样使用固定间隔。

ploted as in example

我发现这个函数特别擅长在存在大量峰值的情况下找到较小的峰值。


1
似乎区分您的峰值搜索的主要特征是pwid/4+zeros(N)。您能解释一下您是如何选择它的吗?我也不明白您是如何选择幅度以及为什么它应该是与点数相同长度的数组。 - ericksonla
从文档中可以得知,widths是:“用于计算CWT矩阵的宽度的一维数组。通常,此范围应涵盖感兴趣峰值的预期宽度。” 在这种情况下,我将sinc()中的间隔缩放为pwid。 “widths”数组是单侧宽度,因此我将其缩放以近似峰值的HWHM。 - Frank M

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接