Python Spinmob curve_fit работает, но установщик - нет - PullRequest
0 голосов
/ 30 ноября 2018

Я пытаюсь согласовать данные с гауссовским.

Необработанные данные показывают очень очевидный пик.Когда я пытаюсь выполнить подгонку с помощью curve_fit, подгонка идентифицирует пик, но у него нет изогнутой вершины.Сейчас я пытаюсь привести данные в соответствие с установщиком spinmob.Однако эта примерка просто дает прямую линию.

Я пытался изменить несколько параметров установщика, определение функции Гаусса и начальные параметры для подгонки, но, похоже, ничего не работает.

Вот код:

from scipy.optimize import curve_fit
from scipy import asarray as ar,exp
import spinmob as s

x = x30
y = ydata

def gaussian(x, A, mu, sig): # See http://mathworld.wolfram.com/GaussianFunction.html
    return A/(sig * np.sqrt(2*np.pi)) * np.exp(-np.power(x-mu, 2) / (2 * np.power(sig, 2)))

popt,pcov = curve_fit(gaussian,x,y,p0=[1,7.688,0.005])

FWHM = 2*np.sqrt(2*np.log(2))*popt[2]
print("FWHM: {}".format(FWHM))

plt.plot(x,y,'bo',label='data')
plt.plot(x,gaussian(x,*popt),'r+-',label='fit')
plt.legend()

fitter = s.data.fitter()
fitter.set(subtract_bg=True, plot_guess_zoom=True)
fitter.set_functions(f=gaussian, p='A=1,mu=8.688,sig=0.001')
fitter.set_data(x, y, eydata = 0.03)
fitter.fit()

Curve_fit возвращает этот график: График Curve_fit

График установщика spinmob дает это: Spinmob Fitter Plot

1 Ответ

0 голосов
/ 04 декабря 2018

Предполагая, что spinmob фактически использует scipy.curve_fit под капотом, я бы предположил (извините), что проблема в том, что начальные значения, которые вы ему задаете, настолько далеки, что он не может найти решение.

Конечно, A=1 не очень хорошая догадка для scipy.curve_fit() или spinmob.fitter().Пик определенно отрицателен, и вы должны угадать значение, больше похожее на -0.1, чем +1.На самом деле вы, вероятно, могли бы утверждать, что A должно быть <0. </p>

Начальное значение 7,688 для mu, которое вы задаете для curve_fit(), довольно хорошее и позволитрешение.Я не знаю, является ли это опечаткой или нет, но начальное значение 8,688 для mu, которое вы задаете для spinmob.fitter(), очень далеко (то есть выходит за пределы диапазона данных), и подгонка никогда не будетможет уточнить свой путь к правильному решению оттуда.

Начальные значения имеют значение для подбора кривой, и плохие начальные значения могут привести к плохим результатам.

Некоторые могут рассматривать его как бесстыдный плагин, но позвольте мне призвать вас попробовать lmfit (https://lmfit.github.io/lmfit-py/) (я ведущий автор) для решения этой проблемы. Lmfit заменяетмассив значений параметров с именованными объектами Parameter для лучшей организации подгонок. Он также имеет встроенную гауссову модель (которая также рассчитывает FWHM, включая неопределенность). То есть, с Lmfit ваш скрипт может выглядеть так:

import numpy as np
import matplotlib.pyplot as plt

from lmfit.models import GaussianModel
from lmfit.lineshapes import gaussian

# create fake data that looks like yours
xdata = 7.670 + np.arange(41)*0.0010
ydata = gaussian(xdata, amplitude=-0.196, center=7.6881, sigma=0.001)
ydata += np.random.normal(size=41, scale=10.0)

# create gaussian model
gmodel = GaussianModel()

# fit data, giving initial values for amplitude, center, and sigma
result = gmodel.fit(ydata, x=xdata, amplitude=-0.1, center=7.688, sigma=0.005)

# show results
print(result.fit_report())
plt.plot(xdata, ydata, 'bo', label='data')
plt.plot(xdata, result.best_fit, 'r+-', label='fit')
plt.legend()
plt.show()

Это распечатает отчет как

[Model]]
    Model(gaussian)
[[Fit Statistics]]
    # fitting method   = leastsq
    # function evals   = 21
    # data points      = 41
    # variables        = 3
    chi-square         = 5114.87632
    reduced chi-square = 134.602009
    Akaike info crit   = 203.879794
    Bayesian info crit = 209.020510
[[Variables]]
    sigma:      9.7713e-04 +/- 1.5456e-04 (15.82%) (init = 0.005)
    center:     7.68822727 +/- 1.5484e-04 (0.00%) (init = 7.688)
    amplitude: -0.19273945 +/- 0.02643400 (13.71%) (init = -0.1)
    fwhm:       0.00230096 +/- 3.6396e-04 (15.82%) == '2.3548200*sigma'
    height:    -78.6917624 +/- 10.7894236 (13.71%) == '0.3989423*amplitude/max(1.e-15, sigma)'
[[Correlations]] (unreported correlations are < 0.100)
    C(sigma, amplitude) = -0.577

и даст график данных и лучше всего подойдет как enter image description here

, который должен бытьблизко к тому, что вы пытаетесь сделать.

...