如何在python中制作一个合适的环高斯模型?

时间:2017-12-13 15:02:47

标签: python gaussian ring astropy model-fitting

我的实验目的是将环高斯模型拟合到图像数据中,并找出图像中椭圆或环高斯物体的参数。

为了简单和试用,我尝试使用Astropy制作环高斯模型。不幸的是,它与我的人工数据完全不同。

from astropy.modeling import Fittable2DModel, Parameter, fitting
import matplotlib.pyplot as plt
import numpy as np

class ringGaussian(Fittable2DModel):

    background = Parameter(default=5.)
    amplitude = Parameter(default=1500.)
    x0 = Parameter(default=15.)
    y0 = Parameter(default=15.)
    radius = Parameter(default=2.)
    width = Parameter(default=1.)

    @staticmethod
    def evaluate(x, y, background, amplitude, x0, y0, radius, width):
        z = background + amplitude * np.exp( -((np.sqrt((x-x0)**2. + (y-y0)**2.) - radius) / width)**2 )
        return z

然后我做了一些人工数据(初始参数)来测试环高斯类的拟合函数。

back = 10 # background
amp = 2000 # highest value of the Gaussian
x0 = 10 # x coordinate of center
y0 = 10 # y coordinate of center
radius = 3
width = 1
xx, yy = np.mgrid[:30, :30]
z = back + amp * np.exp( -((np.sqrt((xx-x0)**2. + (yy-y0)**2.) - radius) / width)**2 )

我使用contourf:

绘制了xx,yy和z
fig = plt.subplots(figsize=(7,7))
plt.contourf(xx,yy,z)
plt.show()

这是我得到的: enter image description here

然后我尝试使用我的fittable类来拟合z:

p_init = ringGaussian() #bounds={"x0":[0., 20.], "y0":[0., 20.]}
fit_p = fitting.LevMarLSQFitter()
p = fit_p(p_init, xx, yy, z)
# It is the parameter I got:
<ringGaussian(background=133.0085329497139, amplitude=-155.53652181827655, x0=25.573499373946227, y0=25.25813520725603, radius=8.184302497405568, width=-7.273935403490675)>

我绘制了模型:

fig = plt.subplots(figsize=(7,7))
plt.contourf(xx,yy,p(xx,yy))
plt.show()

这是我得到的: enter image description here

最初,我也试图在我的班级中加入衍生物:

@staticmethod
def fit_deriv(x, y, background, amplitude, x0, y0, radius, width):
    g = (np.sqrt((x-x0)**2. + (y-y0)**2.) - radius) / width
    z = amplitude * np.exp( -g**2 )

    dg_dx0 = - (x-x0)/np.sqrt((x-x0)**2. + (y-y0)**2.)
    dg_dy0 = - (y-y0)/np.sqrt((x-x0)**2. + (y-y0)**2.)
    dg_dr0 = - 1/width
    dg_dw0 = g * -1/width

    dz_dB = 1.
    dz_dA = z / amplitude
    dz_dx0 = -2 * z * g**3 * dg_dx0
    dz_dy0 = -2 * z * g**3 * dg_dy0
    dz_dr0 = -2 * z * g**3 * dg_dr0
    dz_dw0 = -2 * z * g**3 * dg_dw0

    return [dz_dB, dz_dA, dz_dx0, dz_dy0, dz_dr0, dz_dw0]

但它返回“ValueError:用序列设置数组元素。”

我现在非常绝望。有谁能提出一些可能的解决方案或者在python中实现环高斯拟合的替代方法?

非常感谢~~~

1 个答案:

答案 0 :(得分:2)

您的实施正常(我没有尝试或检查您的fit_deriv实施)。

问题在于您的拟合不会收敛,因为初始模型参数与真值相差太远,因此优化器失败。当我运行你的代码时,我收到了这个警告:

WARNING: The fit may be unsuccessful; check fit_info['message'] for more information. [astropy.modeling.fitting]

如果更改模型参数以使模型与数据大致匹配,则拟合成功:

p_init = ringGaussian(x0=11, y0=11)

要检查模型与数据的比较方式,您可以使用imshow显示数据和模型图像(或者还有残差图像):

plt.imshow(z)
plt.imshow(p_init(xx,yy))
plt.imshow(p(xx,yy))