【问题标题】:Robust algorithm for detection of peak widths用于检测峰宽的稳健算法
【发布时间】:2012-06-04 11:08:31
【问题描述】:

我问how to programmatically judge spectrum bands@detly 建议使用 FWHM(半峰全宽)来确定峰的宽度。我四处搜索,发现 FWHM 可用于拟合模型(我对此几乎是门外汉!),尤其是高斯模型。具体来说,2.354 * sigma 是高斯模型的 the width

我正在寻找一个高斯拟合因为坏峰的存在。这张图片中有 4 个形状良好的峰。然后是“双”峰(虽然两者都可能很重要)和两个展开的峰。对于天真的 FWHM,它们将被证明是不可能的挑战。

鉴于它的 x 坐标的近似位置,您能否帮助生成 Scip/Numpy 中峰值的高斯拟合(用于 FWHM 计算)?如果高斯是一个糟糕的选择,那么其他一些方案。

【问题讨论】:

  • 如果您有大量此类数据并希望以更快的方式获得结果,请尝试使用 root (root.cern.ch)。它是一个专门为数据分析而设计的 C++ 框架(在您的情况下:适合例程)。

标签: python scipy


【解决方案1】:

拟合高斯是一个好方法。如果您对初始参数值有正确的猜测,您可以尝试一次全部猜测。一个大问题是噪声,实际上您可能希望单独拟合每个峰(即一次只考虑给定峰所在的范围),或者在数据中获取基线噪声曲线并将其减去。

这是一些尝试拟合多个高斯的代码。我为我认为是 8 个最突出的峰输入了一些非常宽松的参数,加上一个额外的非常宽的 Guassian 来尝试捕捉背景噪声。在处理之前,我稍微清理了您发布的图像,以帮助从中获取数据(移除鼠标光标和轴边缘,并反转图像)。

代码:

import Image
from scipy import *
from scipy.optimize import leastsq
import numpy as np

im = Image.open("proc.png")
im = im.convert('L')
h, w = im.size
#Extract data from the processed image:
im = np.asarray(im)
y_vals, junk  = np.mgrid[w:0:-1, h:0:-1]
y_vals[im < 255] = 0
y_vals = np.amax(y_vals,axis=0)

def gaussian(x, A, x0, sig):
    return A*exp(-(x-x0)**2/(2.0*sig**2))

def fit(p,x):
    return np.sum([gaussian(x, p[i*3],p[i*3+1],p[i*3+2]) 
                   for i in xrange(len(p)/3)],axis=0)

err = lambda p, x, y: fit(p,x)-y

#params are our intitial guesses for fitting gaussians, 
#(Amplitude, x value, sigma):
params = [[50,40,5],[50,110,5],[100,160,5],[100,220,5],
          [50,250,5],[100,260,5],[100,320,5], [100,400,5],   
          [30,300,150]]  # this last one is our noise estimate
params = np.asarray(params).flatten()

x  = xrange(len(y_vals))
results, value = leastsq(err, params, args=(x, y_vals))

for res in results.reshape(-1,3):
    print "amplitude, position, sigma", res

import pylab
pylab.subplot(211, title='original data')
pylab.plot(y_vals)
pylab.subplot(212, title='guassians fit')
y = fit(results, x)
pylab.plot(x, y)
pylab.savefig('fig2.png')
pylab.show()

这些是拟合的输出高斯参数:

#Output:
amplitude, position, sigma [ 23.47418352  41.27086097   5.91012897]
amplitude, position, sigma [  16.26370263  106.39664543    3.67827824]
amplitude, position, sigma [  59.74500239  163.11210316    2.89866545]
amplitude, position, sigma [  57.91752456  220.24444939    2.91145375]
amplitude, position, sigma [  39.78579841  251.25955921    2.74646334]
amplitude, position, sigma [  86.50061756  260.62004831    3.08367483]
amplitude, position, sigma [  79.26849867  319.64343319    3.57224402]
amplitude, position, sigma [ 127.97009966  399.27833126    3.14331212]
amplitude, position, sigma [  20.21224956  379.41066063  195.47122312]

【讨论】:

  • 您是如何“从 [图片] 中获取数据”的?它比阅读更高级吗? :)
  • @BandGap - 首先我用 Gimp 编辑图像以移除鼠标光标和轴边缘,然后我反转并阈值化图像以使其成为二进制。然后代码中#Extract data from the processed image: 之后的 4 行提取数据:通过创建行值网格,如果图像中的相应位置为零,则将所有这些值设置为零,然后取一列中的最大行索引,产生与发布的图像相对应的第一个图“原始数据”。
  • 你能做到吗,只给 x 值(没有幅度或 SD)?
  • @aitchnyu - 是的。但是,我真的需要更多的样本数据集,和/或更好地理解数据的外观(尤其是极端情况)。 IE。职权范围需要更清晰一些 - 对于您的数据,您需要绝对知道什么构成峰值,什么不构成。在接下来的几天里,我可能不会有太多时间了,所以在提供赏金时可能值得你鼓励某人尝试一下。..
  • 我将其修改为单个峰值、近似峰值位置以及假定的幅度和 SD。但有些峰往往显示出极值。所以它不如天真的 FWHM(@detly 在stackoverflow.com/a/10764997/604511 上回答了我)那么健壮。以下是一些示例数据:pastebin.com/b3VVZ24w
猜你喜欢
  • 2013-10-19
  • 2021-01-04
  • 1970-01-01
  • 1970-01-01
  • 2012-01-25
  • 2017-10-06
  • 2016-12-27
  • 2022-06-10
  • 2022-11-02
相关资源
最近更新 更多