2d高斯函数的集成(python)

时间:2016-03-31 12:32:22

标签: python scipy gaussian numerical-integration

我使用Area,sigmax和sigmay参数定义了2D高斯(在自变量之间没有相关性)。 当我在两个变量中进行(-inf,inf)的积分时,我只得到sigmax和sigmay为1时的Area。

import numpy as np
import scipy.integrate as sci

class BeamDistribution(object):
    def __init__(self, Ipeak, sigmax, sigmay):
        print Ipeak, sigmax, sigmay
        self.__Ipeak = Ipeak
        self.__sigmax = sigmax
        self.__sigmay = sigmay

    def value(self, x, y):
        factor = self.__Ipeak/(2.*np.pi*self.__sigmax * self.__sigmay)
        factorx = np.exp(-x**2/(2.*self.__sigmax**2))
        factory = np.exp(-y**2/(2.*self.__sigmay**2))
        return factor*factorx*factory

    def integral(self, a, b, c, d):
        integration = sci.dblquad(self.value, a, b, lambda x: c, lambda x: d,
                                  epsrel = 1e-9, epsabs = 0)
#        sci.quad_explain()
        return integration

    def __call__(self, x, y):
        return self.value(x, y)


if __name__ == "__main__":
    Ipeak = 65.0e-3
    sigmax = 0.2e-3
    sigmay = 0.3e-3
    limit = np.inf
    my_beam_class = BeamDistribution(Ipeak, sigmax, sigmay)
    total = my_beam_class.integral(-limit, limit, -limit, limit)
    print "Integrated total current ",total," of Ipeak ", Ipeak

    my_beam_class = BeamDistribution(Ipeak, 1, 1)
    total = my_beam_class.integral(-limit, limit, -limit, limit)
    print "Integrated total current ",total," of Ipeak ", Ipeak

输出

0.065 0.0002 0.0003
Integrated total current  (7.452488478001055e-32, 6.855160478762106e-41)  of Ipeak  0.065
0.065 1 1
Integrated total current  (0.4084070449667172, 1.0138233535120856e-11)  of Ipeak  0.065

知道为什么会这样吗?我想它应该是一件简单的事情,但是经过几个小时的努力,我看不出任何错误。

2 个答案:

答案 0 :(得分:2)

集成高斯核的正确方法是使用Gauss-Hermite quadratures,参见here

它在Python中实现为SciPy模块http://docs.scipy.org/doc/numpy-1.10.1/reference/generated/numpy.polynomial.hermite.hermgauss.html

代码,高斯核上的积分应为√(π)

import math
import numpy as np

a,w = np.polynomial.hermite.hermgauss(32)

print(a)
print(w)

def f(x):
    return 1.0

s = 0.0
for k in range(0,len(a)):
    s += w[k]*f(a[k])

print(s - math.sqrt(math.pi))

2D案例

Ipeak = 0.065
sigmax = 0.2e-3
sigmay = 0.3e-3
sqrt2 = math.sqrt(2.)

def h(x, y):
    return Ipeak*1.0/math.pi

s = 0.0
for k in range(0, len(a)):
    x = sqrt2 * sigmax * a[k]
    t = 0.0
    for l in range(0, len(a)):
        y = sqrt2 * sigmay * a[l]
        t += w[l] * h(x, y)
    s += w[k]*t

print(s)

答案 1 :(得分:0)

我认为你的高斯与0.002 sigma对于正交来说太高峰了:Scipy忽略了这个非常小的峰值,并且到处都只看到零。你有两个解决方案:

  • 重新规范化函数:∫ a b f x )dx =σ∫ a /σ b /σ f u )du

  • 将积分切成许多块。这是一个计算从-infinity到-4 * sigma,然后从-4 * sigma到4 * sigma,然后从4 * sigma到无穷大的积分的例子:

def integral(self, a, b, c, d):
    integration =0
    nsigmas=4
    for intervalx in [(a,-nsigmas*sigmax),(-nsigmas*sigmax,nsigmas*sigmax),(nsigmas*sigmax,b)]:
        for intervaly in [(c,-nsigmas*sigmay),(-nsigmas*sigmay,nsigmas*sigmay),(nsigmas*sigmay,d)]:
                integration+= sci.dblquad(self.value, intervalx[0], intervalx[1], lambda x: intervaly[0], lambda x: intervaly[1],
                              epsrel = 1e-9, epsabs = 0)[0]
    #        sci.quad_explain()
    return integration

我获得了这个输出:

0.065 0.0002 0.0003
Integrated total current  0.06499999987174367  of Ipeak  0.065
0.065 1 1
Integrated total current  0.06500000000019715  of Ipeak  0.065