Peak detection of measured signal
我们使用一个数据采集卡从一个设备中获取读数,这个设备将信号增加到一个峰值,然后再降低到接近原始值。为了找到峰值,我们目前搜索数组中的最高读数,并使用索引来确定计算中使用的峰值时间。
如果最高值是我们正在寻找的峰值,这就可以很好地工作,但是如果设备工作不正常,我们可以看到第二个峰值,它可以高于初始峰值。我们在90秒内从16台设备上每秒读取10个读数。
我最初的想法是在读数中循环,检查前面和后面的点是否小于电流,以找到一个峰值并构造一组峰值。也许我们应该在当前位置的每一侧平均观察几个点,以考虑系统中的噪声。这是最好的方法还是有更好的技术?
我们确实使用了LabVIEW,我已经查看了Lava论坛,这里有许多有趣的例子。这是我们测试软件的一部分,我们试图避免使用太多的非标准vi库,所以我希望得到有关所涉及的过程/算法的反馈,而不是特定代码。
有很多经典的峰值检测方法,其中任何一种都可以工作。您必须了解数据质量的界限,尤其是。以下是基本说明:
在您的数据中的任意两点之间,
使用匹配的过滤器对标准峰值形状的相似性进行评分(本质上,使用针对某个形状的标准化点积来获得相似性的余弦度量)
对标准峰值形状进行反卷积,并检查是否有高值(尽管对于简单的仪器输出,我经常发现2对噪声不太敏感)。
平滑数据并检查等距点的三联体,如果是
将一个非常简单的2高斯混合模型适合您的数据(例如,数字配方有一个很好的现成代码块)。以较早的高峰为例。这将正确处理重叠的峰值。
在数据中找到与简单高斯、柯西、泊松或你曲线的最佳匹配。在大范围内评估该曲线,并在记录其峰值位置后从数据副本中减去该曲线。重复。以最早的峰值为例,其模型参数(可能是标准偏差,但某些应用可能关心峰度或其他特征)满足某些标准。当心从数据中减去峰值后留下的伪影。最佳匹配可能由上述2中建议的匹配得分类型决定。
我以前做过这样的工作:在DNA序列数据中找到峰值,在根据测量曲线估计的导数中找到峰值,在柱状图中找到峰值。
我鼓励你认真考虑适当的底线。维纳滤波或其他滤波或简单的柱状图分析通常是在有噪声的情况下基线的一种简单方法。
最后,如果您的数据通常是嘈杂的,并且您将数据从卡上取下来作为未引用的单端输出(甚至是引用的,只是不是差分的),并且如果您将许多观测平均到每个数据点,请尝试对这些观测进行排序,并丢弃第一个和最后一个四分位数,然后对剩余的数据进行平均。有很多这样的离群值消除策略是非常有用的。
您可以尝试信号平均,即对每个点,用周围3个或更多点平均值。如果噪声点很大,那么即使这样也没有帮助。
我知道这是语言不可知论者,但是假设你正在使用LabVIEW,LabVIEW附带了许多预打包的信号处理VIS,你可以使用它们来进行平滑和降噪。NI论坛是一个很好的地方,可以在这类事情上获得更专业的帮助。
我想为这个线程贡献一个我自己开发的算法:
它是基于离散原理:如果一个新的数据点是一个给定的x个标准差,远离某个移动平均值,算法信号(也称为z-得分)。该算法具有很强的鲁棒性,因为它构造了一个独立的移动平均值和偏差,这样信号就不会破坏阈值。因此,未来信号的识别精度大致相同,而与先前信号的数量无关。该算法接受3个输入:
其工作原理如下:
伪代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | # Let y be a vector of timeseries data of at least length lag+2 # Let mean() be a function that calculates the mean # Let std() be a function that calculates the standard deviaton # Let absolute() be the absolute value function # Settings (the ones below are examples: choose what is best for your data) set lag to 5; # lag 5 for the smoothing functions set threshold to 3.5; # 3.5 standard deviations for signal set influence to 0.5; # between 0 and 1, where 1 is normal influence, 0.5 is half # Initialise variables set signals to vector 0,...,0 of length of y; # Initialise signal results set filteredY to y(1,...,lag) # Initialise filtered series set avgFilter to null; # Initialise average filter set stdFilter to null; # Initialise std. filter set avgFilter(lag) to mean(y(1,...,lag)); # Initialise first value set stdFilter(lag) to std(y(1,...,lag)); # Initialise first value for i=lag+1,...,t do if absolute(y(i) - avgFilter(i-1)) > threshold*stdFilter(i-1) then if y(i) > avgFilter(i-1) set signals(i) to +1; # Positive signal else set signals(i) to -1; # Negative signal end # Adjust the filters set filteredY(i) to influence*y(i) + (1-influence)*filteredY(i-1); set avgFilter(i) to mean(filteredY(i-lag,i),lag); set stdFilter(i) to std(filteredY(i-lag,i),lag); else set signals(i) to 0; # No signal # Adjust the filters set filteredY(i) to y(i); set avgFilter(i) to mean(filteredY(i-lag,i),lag); set stdFilter(i) to std(filteredY(i-lag,i),lag); end end |
演示
。
>原始答案对这个问题作了一些详细的研究。
根源代码是可用的,因此如果需要,可以获取此实现。
从a href="http://root.cern.ch/root/html/tsspectrum.html"rel="noreferrer">tsspectrum/aa类文档:
此类中使用的算法已在以下参考文献中发布:
[1] M.Morhac et al.: Background
elimination methods for
multidimensional coincidence gamma-ray
spectra. Nuclear Instruments and
Methods in Physics Research A 401
(1997) 113-
132.[2] M.Morhac et al.: Efficient one- and two-dimensional Gold
deconvolution and its application to
gamma-ray spectra decomposition.
Nuclear Instruments and Methods in
Physics Research A 401 (1997) 385-408.[3] M.Morhac et al.: Identification of peaks in
multidimensional coincidence gamma-ray
spectra. Nuclear Instruments and
Methods in Research Physics A
443(2000), 108-125.
号
这些论文是从类文档链接到那些没有NIM在线订阅的人。
所做的工作的简短版本是将直方图展平以消除噪声,然后在展平的直方图中使用蛮力检测局部最大值。
这种方法基本上是从大卫·马尔的《视觉》一书中得出的。
高斯模糊您的信号与预期宽度的峰值。这样可以消除噪声峰值,并且相位数据没有损坏。
然后边缘检测(日志将执行此操作)
然后你的边缘就是特征的边缘(像峰)。在边缘之间寻找峰值,按大小对峰值进行排序,这样就完成了。
我在这个问题上使用了变体,它们工作得很好。
我认为你想把你的信号与一个预期的、典型的信号交叉关联起来。但是,从我学习信号处理到现在已经有很长一段时间了,即使在那时我也没有太多的注意。
所需峰值和不需要的第二峰值之间是否存在质量差异?如果这两个峰值都是"尖峰"——即持续时间短——当你在频域中观察信号时(通过做FFT),你将在大多数波段获得能量。但是,如果"好"峰的能量确实存在于"坏"峰不存在的频率上,或者相反,你可以自动地用这种方式区分它们。
我对仪器不太了解,所以这可能完全不切实际,但这可能是一个有帮助的不同方向。如果你知道读数是如何失效的,并且在给定失效的情况下,峰值之间有一定的间隔,为什么不在每个间隔处进行梯度下降呢?如果下降带你回到你以前搜索过的区域,你可以放弃它。根据采样表面的形状,这也可能有助于比搜索更快地找到峰值。
您可以对逻辑应用一些标准偏差,并注意超过x%的峰值。