簡體   English   中英

如何使用 Astropy 擬合高斯

[英]How to fit a Gaussian using Astropy

我正在嘗試使用 astropy.modeling package 將高斯擬合到一組數據點,但我得到的只是一條平線。 見下文:

https://i.stack.imgur.com/H37VC.png

https://i.stack.imgur.com/DOKSd.png

這是我的代碼:

%pylab inline
from astropy.modeling import models,fitting
from astropy import modeling

#Fitting a gaussian for the absorption lines
wavelength= linspace(galaxy1_wavelength_extracted_1.min(),galaxy1_wavelength_extracted_1.max(),200)
g_init = models.Gaussian1D(amplitude=1., mean=5000, stddev=1.)
fit_g = fitting.LevMarLSQFitter()
g = fit_g(g_init, galaxy1_wavelength_extracted_1, galaxy1_flux_extracted_1)

#Plotting 
plot(galaxy1_wavelength_extracted_1,galaxy1_flux_extracted_1,".k")
plot(wavelength, g(wavelength))
xlabel("Wavelength ($\\AA$)")
ylabel("Flux (counts)")

我做錯了什么或錯過了什么?

我制作了一些與您的相似的假數據,並嘗試在其上運行您的代碼並獲得了類似的結果。 我認為問題在於,如果您不將模型的初始參數調整到至少類似於原始的 model,否則無論執行多少輪擬合,擬合器都無法收斂。

如果我要擬合高斯,我想給初始 model 一些初始參數,這些參數基於計算上的“目測”它們(這里我將你的真實數據的通量和波長分別命名為orig_fluxorig_wavelength ):

>>> an_amplitude = orig_flux.min()
>>> an_mean = orig_wavelength[orig_flux.argmin()]
>>> an_stddev = np.sqrt(np.sum((orig_wavelength - an_mean)**2) / (len(orig_wavelength) - 1))
>>> print(f'mean: {an_mean}, stddev: {an_stddev}, amplitude: {an_amplitude}')
mean: 5737.979797979798, stddev: 42.768052162734605, amplitude: 84.73925092448636

對於標准偏差,我使用了無偏標准偏差估計

將其繪制在我的假數據上表明,如果我也手動觀察數據,我可能會選擇這些合理的值:

>>> plt.plot(orig_wavelength, orig_flux, '.k', zorder=1)
>>> plt.scatter(an_mean, an_amplitude, color='red', s=100, zorder=2)
>>> plt.vlines([an_mean - an_stddev, an_mean + an_stddev], orig_flux.min(), orig_flux.max(),
...            linestyles='dashed', colors='gg', zorder=2)

在此處輸入圖像描述

過去我想添加到astropy.modeling的一個功能是可選方法,這些方法可以附加到某些模型上,以根據某些數據對其參數進行合理的估計。 所以對於高斯人來說,這樣的方法會像我上面計算的那樣返回。 我不知道這是否曾經實施過。

還值得注意的是,您的高斯將被反轉(具有負幅度)並且它在通量軸上偏移了大約 120 個點,所以我在 model 中添加了一個Const1D來解決這個問題,並從幅度中減去位移:

>>> an_disp = orig_flux.max()
>>> g_init = (
...     models.Const1D(an_disp) +
...     models.Gaussian1D(amplitude=(an_amplitude - an_disp), mean=an_mean, stddev=an_stddev)
... )
>>> fit_g = fitting.LevMarLSQFitter()
>>> g = fit_g(g_init, orig_wavelength, orig_flux)

這導致以下擬合看起來已經好多了:

>>> plt.plot(orig_wavelength, orig_flux, '.k')
>>> plt.plot(orig_wavelength, g(orig_wavelength), 'r-')

在此處輸入圖像描述

我不是建模或統計方面的專家,因此具有更深入知識的人可能會對此有所改進。 我添加了一個筆記本,其中包含我對問題的完整分析,包括我如何在此處生成示例數據。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM