仅查找1d数组的“突出”局部最大值

时间:2016-11-10 22:19:41

标签: python numpy scipy signal-processing

我有几个数据集,包含如下所示的峰簇:Data sets with clusters of peaks 你可以看到这里的主要特征是一组峰,每个簇有三个峰。我想找到那些局部峰值的x值,但我遇到了一些问题。我目前的代码如下:

import numpy as np
import matplotlib.pyplot as plt
from scipy import loadtxt, optimize
from scipy.signal import argrelmax

def rounddown(x):
    return int(np.floor(x / 10.0)) * 10

pixel, value = loadtxt('voltage152_4.txt', unpack=True, skiprows=0)

ax = plt.axes()
ax.plot(pixel, value, '-')
ax.axis([0, np.max(pixel), np.min(value), np.max(value) + 1])

maxTemp = argrelmax(value, order=5)
maxes = []
for maxi in maxTemp[0]:
    if value[maxi] > 40:
        maxes.append(maxi)

ax.plot(maxes, value[maxes], 'ro')

plt.yticks(np.arange(rounddown(value.min()), value.max(), 10))
plt.savefig("spectrum1.pdf")
plt.show()

哪个效果相对较好,但仍然不完美。标记为Some peaks labeled的一些峰值这里的主要问题是我的信号不平滑,因此一些实际上不是我相关峰值的东西会被拾取。您可以在群集中间大约一半的杂散最大值中看到这一点,以及具有两个最大值的峰值,实际上它应该是一个。你可以看到附近的中心有一些高频最大值。我正在挑选那些,所以我在循环中添加只考虑高于某一点的值。

我担心平滑曲线实际上会使我松散一些我想要的聚集峰,因为在我的其他一些数据集中,它们更加紧密。也许我的恐惧是没有根据的,我只是误解了平滑的效果。任何帮助将不胜感激。

有没有人能解决如何挑选出“突出”的高峰?也就是说,只有那些与其他峰相比快速变大的峰值?

2 个答案:

答案 0 :(得分:1)

从SciPy 1.1.0版开始,您还可以使用功能scipy.signal.find_peaks,该功能可让您根据其topographic prominence选择检测到的峰。此功能通常比find_peaks_cwt更易于使用。您必须花点时间才能找到最佳下限,并将其作为值传递给prominence,例如find_peaks(..., prominence=5)将忽略示例中不需要的峰。这应该使您合理地接近目标。如果这还不够,您可以根据峰属性(例如可以返回的left_ / right_bases)自行选择峰。

答案 1 :(得分:0)

我还建议您使用scipy.signal.find_peaks。另一个较旧的安全备用find_peaks_cwt的使用非常复杂。

基本上,它会在一行中完成您要查找的内容。除了lagru提到的prominence参数之外,对于您的数据,thresholdheight参数也可能满足您的需求。

height = 40会过滤以获取您喜欢的所有峰。

突出有时很难准确地表现出来。