【发布时间】:2017-03-25 02:19:11
【问题描述】:
我有几个数据集的峰值簇如下所示: 您可以看到这里的主要特征是一个峰簇,每个簇有三个峰。我想找到那些局部峰值的 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()
效果相对较好,但仍不完美。一些峰值标记为: 这里的主要问题是我的信号不平滑,所以一些实际上不是我相关峰值的东西正在被拾取。您可以在集群中大约一半的杂散最大值中看到这一点,以及具有两个最大值的峰,实际上它应该是一个。您可以在图的中心附近看到一些高频最大值。我正在挑选这些,所以我在循环中添加了只考虑高于某个点的值。
我担心平滑曲线实际上会使我失去一些我想要的聚集峰,因为在我的其他一些数据集中,它们之间的距离甚至更近。不过,也许我的担心是没有根据的,我只是误解了平滑的工作原理。任何帮助将不胜感激。
有没有人能解决如何只挑出“突出”的山峰?也就是说,只有那些比其他峰快大的峰?
【问题讨论】:
-
scipy有一个内置的峰值检测器:scipy.signal.find_peaks_cwt,它使用小波分析。 -
噪声数据中的峰值检测并非易事,从你的结果来看,我认为你的算法已经做得很好了。一个简单的解决方案可能是实施一个规则,即两个峰必须由足够深的谷隔开。
-
感谢两位的建议。我最终选择了 Chris 的解决方案,因为它有点“安全”,因为它很少会错过峰值。我没有意识到峰值检测并非易事,所以我对我的解决方案感到满意。
-
比
find_peaks_cwt更适合我的另一种方法是手动过滤信号,首先将其与高斯窗口进行卷积,然后搜索最大值(请参阅this answer)。
标签: python numpy scipy signal-processing