使用astropy拟合椭圆[Ellipse2d模型]

时间:2017-02-09 12:34:59

标签: python astropy

我试图在Ellipse2D库中使用astropy模型拟合椭圆。适合不起作用。建模参数与初始参数相同(可能除幅度参数外)。请参阅以下代码:

import numpy as np
from astropy.modeling import models, fitting
import matplotlib.pyplot as pl

# fake data
num = 100
x, y = np.meshgrid(np.linspace(-5., 5., num), np.linspace(-5, 5, num))
e0 = models.Ellipse2D(amplitude=1., x_0=0., y_0=0., a=2, b=1, theta=0.)
z0 = e0(x, y)
print 'DATA:\n', e0, '\n\n'

# initial model
ei = models.Ellipse2D(amplitude=1., x_0=0.0, y_0=0.0, a=2, b=2, theta=0.2)

fi = fitting.LevMarLSQFitter()

#fitted model?
e1 = fi(ei, x, y, z0)
z1 = e1(x, y)
print 'MODEL:\n', e1, '\n\n'

pl.imshow(z0, extent=[-5, 5, -5, 5], alpha=0.5)
pl.imshow(z1, extent=[-5, 5, -5, 5], alpha=0.2)
pl.show()

3 个答案:

答案 0 :(得分:2)

我在这里或Astropy邮件列表中等待这个问题的答案,因为那时我遇到了完全相同的问题。

由于我找不到答案,我决定不使用Ellipse2D,直到我弄清楚你/我的代码的问题,而是使用Gaussian2D获取theta参数。

您可以尝试以下代码。我只更改了一小部分代码。

import numpy as np
from astropy.modeling import models, fitting
import matplotlib.pyplot as pl

#%%
# data
num = 100
x, y = np.meshgrid(np.linspace(-5., 5., num), np.linspace(-5, 5, num))
e0 = models.Ellipse2D(amplitude=1., x_0=0., y_0=0., a=2, b=1, theta=0.)
z0 = e0(x, y)
print ('DATA:\n', e0, '\n\n')

#%%
# initial model
ei = models.Ellipse2D(amplitude=1., x_0=0.1, y_0=0.1, a=3, b=2, theta=0.2)
gi = models.Gaussian2D(amplitude=1., x_mean=0.1, y_mean=0.1,
                       x_stddev=3, y_stddev=2, theta=0.2)
fi = fitting.LevMarLSQFitter()

#%% 
# fitted model?
e1 = fi(ei, x, y, z0)
g1 = fi(gi, x, y, z0)
z1 = e1(x, y)
z2 = g1(x, y)
print('MODEL:\n', e1, '\n\n')
print('MODEL:\n', g1, '\n\n')

pl.imshow(z0, extent=[-5, 5, -5, 5], alpha=0.5)
pl.imshow(z1, extent=[-5, 5, -5, 5], alpha=0.2)
pl.imshow(z2, extent=[-5, 5, -5, 5], alpha=0.5)
pl.colorbar()
pl.show()
print(g1.theta.value)

虽然它不适合给定的具有恒定幅度的椭圆形平台,但它仍然给出了正确的theta1.23386185422e-10,它实际上为零。当我将theta的{​​{1}}更改为某些不同的值时,它会给出正确的值。

希望它有所帮助!

答案 1 :(得分:0)

如前所述,另一个钳工可能更适合此任务,例如SimplexLSQFitter

这并不完全符合椭圆,但至少b参数几乎可以很好地匹配:

...
fi = fitting.SimplexLSQFitter()
e1 = fi(ei, x, y, z0)
z1 = e1(x, y)
print(repr(e1))
# <Ellipse2D(amplitude=0.8765330382805181, 
#            x_0=0.00027076793418705464, 
#            y_0=0.0008061856852329963, 
#            a=2.0019138872185174, 
#            b=1.0985760645823452, 
#            theta=0.22591442574477916)>

但我认为Ellipse2D并不是一个很好的模型,特别是如果模型之间的theta不同。

答案 2 :(得分:0)

感谢@ yoonsoo-p-bach的建议,这是一个有效的例子:

import numpy as np
from astropy.modeling import models, fitting
import matplotlib.pyplot as pl

# data
num = 100
x, y = np.meshgrid(np.linspace(-5., 5., num), np.linspace(-5, 5, num))
e0 = models.Ellipse2D(amplitude=1., x_0=0.2, y_0=0.3, a=2, b=1, theta=0.4)
z0 = e0(x, y)
print 'DATA:\n', e0, '\n\n'

# fitting procedure
fi = fitting.SimplexLSQFitter() 
#fi = fitting.LevMarLSQFitter()

# gaussian fit (to estimate x_0, y_0 and theta)
gi = models.Gaussian2D(amplitude=1., x_mean=0.1, y_mean=0.2, x_stddev=1, y_stddev=1, theta=0.0)
g1 = fi(gi, x, y, z0, maxiter=1000)
print 'Gaussian:\n', g1, '\n\n'

# initial model
ei = models.Ellipse2D(amplitude=1., x_0=g1.x_mean, y_0=g1.y_mean, a=g1.x_stddev, b=g1.y_stddev, theta=g1.theta, fixed={'x_0': True, 'y_0':True, 'theta':True})

#fitted model
e1 = fi(ei, x, y, z0, maxiter=1000)
z1 = e1(x, y)
print 'MODEL:\n', e1, '\n\n'

pl.imshow(z0-z1, extent=[-5, 5, -5, 5])
pl.show()