예제 #1
0
 def fit(self):
     r"""actually run the fit"""
     # we can ignore set_what, since I think there's a mechanism in
     # lmfit to take care of that (it's for fixing parameters)
     # but the rest of what it's doing is to pull apart the
     # error, axis, etc, to be fed to minimize.
     #
     # It also automatically converts complex data to real data, and
     # does other things for error handling -- let's not just throw this out
     #
     # I think that a lot of this could be copied with little modification
     #
     # But you  should read through and see what the previous fit method is doing
     # and then copy over what you can
     x = self.getaxis(self.fit_axis)
     if np.iscomplex(self.data.flatten()[0]):
         logging.debug(strm("Warning, taking only real part of fitting data!"))
     y = np.real(self.data)
     sigma = self.get_error()
     out = minimize(
         self.residual,
         self.pars,
         args=(x, y, sigma),
     )
     # can you capture the following as a string? maybe return it?
     report_fit(out, show_correl=True)
     # {{{ capture the result for ouput, etc
     self.fit_coeff = [out.params[j].value for j in self.symbol_list]
     assert out.success
     self.covariance = out.covar
     # }}}
     return
예제 #2
0
def normal_skewed(x, y, parameters=None, dfunc='pdf', check=False, *args, **kwargs):
    # verbous.INFO('FITTING SKEWED-GAUSSIAN')

    if parameters == None:
        parameters = Parameters()
        parameters = Parameters()
        parameters.add('amp', value=max(y))
        max_idx = np.argmin(abs(y - max(y)))
        parameters.add('mu', value=x[max_idx])
        parameters.add('sig', value=15.)
        parameters.add('skew', value=-5.)

    if y[0] > y[-1]:
        reverse = True
    else:
        reverse = False

    errfunc = lambda p, x, y: distributions.normal_skew(x, parameters, reverse=reverse, dfunc=dfunc) - y
    fitout = minimize(errfunc, parameters, args=(x, y))

    # verbous.INFO('FITTED PARAMETERS:')

    if check:
        printfuncs.report_fit(fitout.params)
        x_fit = np.linspace(0, 600, 1000)
        y_fit = distributions.normal_skew(x_fit, parameters, reverse=reverse, dfunc=dfunc)
        plt.plot(x, y)

        plt.plot(x_fit, y_fit)
        plt.show()

    return parameters
예제 #3
0
def test_constraints1():
    def residual(pars, x, sigma=None, data=None):
        yg = gaussian(x, pars['amp_g'], pars['cen_g'], pars['wid_g'])
        yl = lorentzian(x, pars['amp_l'], pars['cen_l'], pars['wid_l'])

        model = yg + yl + pars['line_off'] + x * pars['line_slope']
        if data is None:
            return model
        if sigma is None:
            return (model - data)
        return (model - data) / sigma

    n = 601
    xmin = 0.
    xmax = 20.0
    x = linspace(xmin, xmax, n)

    data = (gaussian(x, 21, 8.1, 1.2) + lorentzian(x, 10, 9.6, 2.4) +
            random.normal(scale=0.23, size=n) + x * 0.5)

    pfit = Parameters()
    pfit.add(name='amp_g', value=10)
    pfit.add(name='cen_g', value=9)
    pfit.add(name='wid_g', value=1)

    pfit.add(name='amp_tot', value=20)
    pfit.add(name='amp_l', expr='amp_tot - amp_g')
    pfit.add(name='cen_l', expr='1.5+cen_g')
    pfit.add(name='wid_l', expr='2*wid_g')

    pfit.add(name='line_slope', value=0.0)
    pfit.add(name='line_off', value=0.0)

    sigma = 0.021  # estimate of data error (for all data points)

    myfit = Minimizer(residual,
                      pfit,
                      fcn_args=(x, ),
                      fcn_kws={
                          'sigma': sigma,
                          'data': data
                      },
                      scale_covar=True)

    myfit.prepare_fit()
    init = residual(myfit.params, x)

    result = myfit.leastsq()

    print(' Nfev = ', result.nfev)
    print(result.chisqr, result.redchi, result.nfree)

    report_fit(result.params)
    pfit = result.params
    fit = residual(result.params, x)
    assert (pfit['cen_l'].value == 1.5 + pfit['cen_g'].value)
    assert (pfit['amp_l'].value == pfit['amp_tot'].value - pfit['amp_g'].value)
    assert (pfit['wid_l'].value == 2 * pfit['wid_g'].value)
def test_constraints1():
    def residual(pars, x, sigma=None, data=None):
        yg = gaussian(x, pars['amp_g'], pars['cen_g'], pars['wid_g'])
        yl = lorentzian(x, pars['amp_l'], pars['cen_l'], pars['wid_l'])

        model =  yg +  yl + pars['line_off'] + x * pars['line_slope']
        if data is None:
            return model
        if sigma is None:
            return (model - data)
        return (model - data)/sigma


    n = 601
    xmin = 0.
    xmax = 20.0
    x = linspace(xmin, xmax, n)

    data = (gaussian(x, 21, 8.1, 1.2) +
            lorentzian(x, 10, 9.6, 2.4) +
            random.normal(scale=0.23,  size=n) +
            x*0.5)


    pfit = Parameters()
    pfit.add(name='amp_g',  value=10)
    pfit.add(name='cen_g',  value=9)
    pfit.add(name='wid_g',  value=1)

    pfit.add(name='amp_tot',  value=20)
    pfit.add(name='amp_l',  expr='amp_tot - amp_g')
    pfit.add(name='cen_l',  expr='1.5+cen_g')
    pfit.add(name='wid_l',  expr='2*wid_g')

    pfit.add(name='line_slope', value=0.0)
    pfit.add(name='line_off', value=0.0)

    sigma = 0.021  # estimate of data error (for all data points)

    myfit = Minimizer(residual, pfit,
                      fcn_args=(x,), fcn_kws={'sigma':sigma, 'data':data},
                      scale_covar=True)

    myfit.prepare_fit()
    init = residual(myfit.params, x)

    result = myfit.leastsq()

    print(' Nfev = ', result.nfev)
    print( result.chisqr, result.redchi, result.nfree)

    report_fit(result.params)
    pfit= result.params
    fit = residual(result.params, x)
    assert(pfit['cen_l'].value == 1.5 + pfit['cen_g'].value)
    assert(pfit['amp_l'].value == pfit['amp_tot'].value - pfit['amp_g'].value)
    assert(pfit['wid_l'].value == 2 * pfit['wid_g'].value)
예제 #5
0
    def fit_spready(self, ):
        params = Parameters()
        c1 = self.refx[np.argmax(self.refy)] - self.x[np.argmax(self.y)]
        params.add('c1', value=c1, min=c1 - 50, max=c1 + 50)
        params.add('c2', value=0.5e-2, min=1e-3, max=1e-2)

        mini = Minimizer(self.lmfit_residuals, params, nan_policy='propagate')
        self.lmfit_minimize_result = mini.minimize(
            method='differential_evolution')

        printfuncs.report_fit(self.lmfit_minimize_result, min_correl=0.5)
예제 #6
0
def align_with_O2(spectra, O2_spectra, R=5000):
    # Convert to ispec structures
    spectra = ispec.create_spectrum_structure(spectra.T[0], spectra.T[1],
                                              spectra.T[2])
    O2_spectra = ispec.create_spectrum_structure(O2_spectra.T[0],
                                                 O2_spectra.T[1],
                                                 O2_spectra.T[2])

    # Now normalise
    normed_spectra, spectra_continuum_model = normalize_whole_spectrum(spectra)
    #wfilter = ispec.create_wavelength_filter(normed_spectra, wave_base=np.min(O2_spectra['waveobs']) - 3, wave_top=np.max(O2_spectra['waveobs']) + 3)
    wfilter = ispec.create_wavelength_filter(normed_spectra,
                                             wave_base=684,
                                             wave_top=690)
    normed_spectra = normed_spectra[wfilter]

    params = Parameters()
    params.add('rv', value=0, min=-100, max=100)
    params.add('strength', value=1, min=0.7, max=1.3)
    params.add('zp', value=1., min=0.9, max=1.1, vary=False)
    mini = Minimizer(lmfit_func,
                     params,
                     fcn_args=(np.copy(normed_spectra), np.copy(O2_spectra),
                               False))
    lmfit_minimize_result = mini.minimize()
    printfuncs.report_fit(lmfit_minimize_result, min_correl=0.5)

    corrected_spectra, o2_model = lmfit_func(lmfit_minimize_result.params,
                                             normed_spectra,
                                             O2_spectra,
                                             return_model=True)

    f = plt.figure()
    plt.plot(normed_spectra['waveobs'], normed_spectra['flux'], 'k', alpha=0.3)
    plt.plot(corrected_spectra['waveobs'],
             corrected_spectra['flux'],
             'k',
             label='Corrected solution')
    plt.plot(O2_spectra['waveobs'], O2_spectra['flux'], 'r', alpha=0.3)
    plt.plot(O2_spectra['waveobs'], o2_model, 'r', label='O2 model')
    plt.gca().set(title='RV = {:.3f} +- {:.3f}'.format(
        lmfit_minimize_result.params['rv'].value,
        lmfit_minimize_result.params['rv'].stderr),
                  xlabel='Wavelength [nm]',
                  ylabel='Normalized flux')
    plt.legend()
    plt.xlim(685, 690)
    corrected = ispec.correct_velocity(
        np.copy(spectra), lmfit_minimize_result.params['rv'].value)
    return f, np.array(
        [corrected['waveobs'], corrected['flux'],
         corrected['err']]).T, lmfit_minimize_result.params[
             'rv'].value, lmfit_minimize_result.params['rv'].stderr
예제 #7
0
    def do_fit(self, verbosity=False):
        PeakFitter.ith_fit += 1

        myfit = Minimizer(self.residual,
                          self.params,
                          fcn_args=(self.data_x, ),
                          fcn_kws={'data_y': self.data_y},
                          scale_covar=True)

        self.result = myfit.leastsq()
        self.init = self.residual(self.params, self.data_x)
        self.fit = self.residual(self.result.params, self.data_x)

        if verbosity:
            # print fit details out
            report_fit(self.result)
예제 #8
0
def main():
    tmpname = 'data/templates/F0_+0.5_Dwarf.fits'
    model = Model(tmpname)

    # ftargetname = 'data/spec-4961-55719-0378.fits'
    ftargetname = '/home/zzx/workspace/data/xiamen/P200-Hale_spec/blue/reduce_second/specdir/fawftbblue0073.fits'
    # new_wo, new_fo, new_eo = specio.read_sdss(ftargetname, lw=3660, rw=10170)
    new_wo, new_fo, new_eo = specio.read_iraf(ftargetname)
    unit = func.get_unit(new_fo)
    new_fo = new_fo / unit
    new_eo = new_eo / unit
    # new_wo, new_fo, new_eo = specio.read_iraf(targetname)
    result = fit(model, new_wo, new_fo, new_eo, show=True, isprint=True)

    residual = model.residual

    out_parms = result.params
    # spec_fit = model.get_spectrum(out_parms, new_wo)
    scalepar = model.get_scale_par(out_parms)
    parshift = model.get_shift_par(out_parms)
    print(parshift[1])
    velocity = str(parshift[1] * c.to('km/s'))
    print('shift = ' + velocity)
    myscale = model.get_scale(new_wo, scalepar)

    plt.figure()
    plt.plot(new_wo, myscale)
    plt.show()

    emcee_params = result.params.copy()
    # emcee_params.add('__lnsigma', value=np.log(0.1), min=np.log(1.0e-20),
    #                  max=np.log(1.0e20))
    result_emcee = minimize(residual,
                            params=emcee_params,
                            args=(new_wo, new_fo, new_eo),
                            method='emcee',
                            nan_policy='omit',
                            steps=1000)
    report_fit(result_emcee)
    plt.plot(new_wo, new_fo)
    # plt.plot(new_wo, spec_fit)
    spec_emcee = model.get_spectrum(result_emcee.params, new_wo)
    plt.plot(new_wo, spec_emcee)
    corner.corner(result_emcee.flatchain,
                  labels=result_emcee.var_names,
                  truths=list(result_emcee.params.valuesdict().values()))
    plt.show()
예제 #9
0
def perform_fit(exp_volumes,
                exp_pressures,
                starting_params,
                interval,
                fix_vo=False,
                bm2=False):

    volumes = exp_volumes[:, 0]
    sigV = exp_volumes[:, 1]
    p = exp_pressures[:, 0]
    sigP = exp_pressures[:, 1]

    uncert = np.column_stack((sigV, sigP))

    #initial starting parameters
    fit_params = Parameters()
    fit_params.add('vo', value=starting_params['vo'], min=0.0)
    fit_params.add('ko', value=starting_params['ko'], min=0.0)
    fit_params.add('kp', value=starting_params['kp'])

    if fix_vo:
        fit_params['vo'].vary = False
    if bm2:
        fit_params['kp'].vary = False

    mini = Minimizer(bm3, fit_params, fcn_args=(volumes,), fcn_kws={'data': p,\
                                                          'uncert': uncert})
    out1 = mini.minimize(method='Nedler')

    out2 = mini.minimize(method='leastsq', params=out1.params)

    results = out2.params.valuesdict()

    plot_volumes = np.linspace((np.min(volumes) - 10), results['vo'], 1000)
    fit = bm3(out2.params, plot_volumes)

    report_fit(out2, show_correl=True, min_correl=0.001)

    PVs = np.column_stack((fit, plot_volumes))

    ci = conf_interval(mini, out2)
    report_ci(ci)

    return ci, mini, out2, PVs
예제 #10
0
def align_distorted_spectra(ref_spectra, traced_flux, verbose=False):
    # First, sort out the two data sets
    refx = np.arange(ref_spectra.shape[0])
    refy = ref_spectra

    datax = np.arange(traced_flux.shape[0])
    datay = traced_flux

    #plt.close()
    #plt.plot(datax,datay, 'r')
    #plt.plot(refx,refy, 'b')
    #plt.show()

    spreader = wavespreader(datax, datay, refx, refy)

    dw = np.argmax(datay) - np.argmax(refy)

    theta0 = np.array([dw, 3000, 0., 0.])

    params = Parameters()
    params.add('c0', value=theta0[0], min=theta0[0] - 50, max=theta0[0] + 50)
    params.add('c1', value=theta0[1], min=theta0[1] - 10, max=theta0[1] + 10)
    params.add('c2',
               value=theta0[2],
               min=theta0[2] - 1e-1,
               max=theta0[2] + 1e-1)
    params.add('c3',
               value=theta0[3],
               min=theta0[3] - 1e-5,
               max=theta0[3] + 1e-5)

    mini = Minimizer(spreader.residuals_lmfit, params, nan_policy='propagate')
    lmfit_minimize_result = mini.minimize(method='differential_evolution')

    if verbose:
        print('Align distorted spectr fit report')
        printfuncs.report_fit(lmfit_minimize_result, min_correl=0.5)

    return spreader, lmfit_minimize_result
예제 #11
0
def test_constraints2():
    """add a user-defined function to symbol table"""
    def residual(pars, x, sigma=None, data=None):
        yg = gaussian(x, pars['amp_g'].value,
                      pars['cen_g'].value, pars['wid_g'].value)
        yl = lorentzian(x, pars['amp_l'].value,
                   pars['cen_l'].value, pars['wid_l'].value)

        slope = pars['line_slope'].value
        offset = pars['line_off'].value
        model =  yg +  yl + offset + x * slope
        if data is None:
            return model
        if sigma is None:
            return (model - data)
        return (model - data)/sigma


    n = 601
    xmin = 0.
    xmax = 20.0
    x = linspace(xmin, xmax, n)

    data = (gaussian(x, 21, 8.1, 1.2) +
            lorentzian(x, 10, 9.6, 2.4) +
            random.normal(scale=0.23,  size=n) +
            x*0.5)

    pfit = Parameters()
    pfit.add(name='amp_g',  value=10)
    pfit.add(name='cen_g',  value=9)
    pfit.add(name='wid_g',  value=1)

    pfit.add(name='amp_tot',  value=20)
    pfit.add(name='amp_l',  expr='amp_tot - amp_g')
    pfit.add(name='cen_l',  expr='1.5+cen_g')
    pfit.add(name='line_slope', value=0.0)
    pfit.add(name='line_off', value=0.0)

    sigma = 0.021  # estimate of data error (for all data points)

    myfit = Minimizer(residual, pfit,
                      fcn_args=(x,), fcn_kws={'sigma':sigma, 'data':data},
                      scale_covar=True)

    def width_func(wpar):
        """ """
        return 2*wpar

    myfit.params._asteval.symtable['wfun'] = width_func

    try:
        myfit.params.add(name='wid_l', expr='wfun(wid_g)')
    except:
        assert(False)

    result = myfit.leastsq()

    print(' Nfev = ', result.nfev)
    print( result.chisqr, result.redchi, result.nfree)
    report_fit(result.params)
    pfit= result.params
    fit = residual(result.params, x)
    assert(pfit['cen_l'].value == 1.5 + pfit['cen_g'].value)
    assert(pfit['amp_l'].value == pfit['amp_tot'].value - pfit['amp_g'].value)
    assert(pfit['wid_l'].value == 2 * pfit['wid_g'].value)
예제 #12
0
    return model - data


n = 1500
xmin = 0.
xmax = 250.0
random.seed(0)
noise = random.normal(scale=2.80, size=n)
x = linspace(xmin, xmax, n)
data = residual(p_true, x) + noise

fit_params = Parameters()
fit_params.add('amp', value=13.0, max=20, min=0.0)
fit_params.add('period', value=2, max=10)
fit_params.add('shift', value=0.0, max=pi / 2., min=-pi / 2.)
fit_params.add('decay', value=0.02, max=0.10, min=0.00)

out = minimize(residual, fit_params, args=(x, ), kws={'data': data})

fit = residual(out.params, x)

report_fit(out, show_correl=True, modelpars=p_true)

print('\n\nRaw (unordered, unscaled) Covariance Matrix:')
print(out.covar)

if HASPYLAB:
    plt.plot(x, data, 'ro')
    plt.plot(x, fit, 'b')
    plt.show()
def test_constraints(with_plot=True):
    with_plot = with_plot and WITHPLOT

    def residual(pars, x, sigma=None, data=None):
        yg = gaussian(x, pars['amp_g'], pars['cen_g'], pars['wid_g'])
        yl = lorentzian(x, pars['amp_l'], pars['cen_l'], pars['wid_l'])

        model =  yg +  yl + pars['line_off'] + x * pars['line_slope']
        if data is None:
            return model
        if sigma is None:
            return (model - data)
        return (model - data) / sigma


    n = 201
    xmin = 0.
    xmax = 20.0
    x = linspace(xmin, xmax, n)

    data = (gaussian(x, 21, 8.1, 1.2) +
            lorentzian(x, 10, 9.6, 2.4) +
            random.normal(scale=0.23,  size=n) +
            x*0.5)

    if with_plot:
        pylab.plot(x, data, 'r+')

    pfit = Parameters()
    pfit.add(name='amp_g',  value=10)
    pfit.add(name='cen_g',  value=9)
    pfit.add(name='wid_g',  value=1)

    pfit.add(name='amp_tot',  value=20)
    pfit.add(name='amp_l',  expr='amp_tot - amp_g')
    pfit.add(name='cen_l',  expr='1.5+cen_g')
    pfit.add(name='wid_l',  expr='2*wid_g')

    pfit.add(name='line_slope', value=0.0)
    pfit.add(name='line_off', value=0.0)

    sigma = 0.021  # estimate of data error (for all data points)

    myfit = Minimizer(residual, pfit,
                      fcn_args=(x,), fcn_kws={'sigma':sigma, 'data':data},
                      scale_covar=True)

    myfit.prepare_fit()
    init = residual(myfit.params, x)

    result = myfit.leastsq()

    print(' Nfev = ', result.nfev)
    print( result.chisqr, result.redchi, result.nfree)

    report_fit(result.params, min_correl=0.3)

    fit = residual(result.params, x)
    if with_plot:
        pylab.plot(x, fit, 'b-')
    assert(result.params['cen_l'].value == 1.5 + result.params['cen_g'].value)
    assert(result.params['amp_l'].value == result.params['amp_tot'].value - result.params['amp_g'].value)
    assert(result.params['wid_l'].value == 2 * result.params['wid_g'].value)

    # now, change fit slightly and re-run
    myfit.params['wid_l'].expr = '1.25*wid_g'
    result = myfit.leastsq()
    report_fit(result.params, min_correl=0.4)
    fit2 = residual(result.params, x)
    if with_plot:
        pylab.plot(x, fit2, 'k')
        pylab.show()

    assert(result.params['cen_l'].value == 1.5 + result.params['cen_g'].value)
    assert(result.params['amp_l'].value == result.params['amp_tot'].value - result.params['amp_g'].value)
    assert(result.params['wid_l'].value == 1.25 * result.params['wid_g'].value)
pfit.add(name='cen_g', value=9)
pfit.add(name='wid_g', value=1)
pfit.add(name='amp_tot', value=20)
pfit.add(name='amp_l', expr='amp_tot - amp_g')
pfit.add(name='cen_l', expr='1.5+cen_g')
pfit.add(name='wid_l', expr='2*wid_g')
pfit.add(name='line_slope', value=0.0)
pfit.add(name='line_off', value=0.0)

sigma = 0.021  # estimate of data error (for all data points)

myfit = Minimizer(residual, pfit,
                  fcn_args=(x,), fcn_kws={'sigma': sigma, 'data': data},
                  scale_covar=True)

myfit.prepare_fit()
init = residual(myfit.params, x)

if HASPYLAB:
    pylab.plot(x, init, 'b--')

result = myfit.leastsq()

report_fit(result)

fit = residual(result.params, x)

if HASPYLAB:
    pylab.plot(x, fit, 'k-')
    pylab.show()
pfit.add(name='wid_l', expr='2*wid_g')
pfit.add(name='line_slope', value=0.0)
pfit.add(name='line_off', value=0.0)

sigma = 0.021  # estimate of data error (for all data points)

myfit = Minimizer(residual,
                  pfit,
                  fcn_args=(x, ),
                  fcn_kws={
                      'sigma': sigma,
                      'data': data
                  },
                  scale_covar=True)

myfit.prepare_fit()
init = residual(myfit.params, x)

if HASPYLAB:
    pylab.plot(x, init, 'b--')

result = myfit.leastsq()

report_fit(result)

fit = residual(result.params, x)

if HASPYLAB:
    pylab.plot(x, fit, 'k-')
    pylab.show()
예제 #16
0
xmin = 0.
xmax = 250.0
random.seed(0)
noise = random.normal(scale=2.80, size=n)
x     = linspace(xmin, xmax, n)
data  = residual(p_true, x) + noise

fit_params = Parameters()
fit_params.add('amp', value=13.0, max=20, min=0.0)
fit_params.add('period', value=2, max=10)
fit_params.add('shift', value=0.0, max=pi/2., min=-pi/2.)
fit_params.add('decay', value=0.02, max=0.10, min=0.00)

out = minimize(residual, fit_params, args=(x,), kws={'data':data})

fit = residual(fit_params, x)

print '# N_func_evals, N_free = ', out.nfev, out.nfree
print '# chi-square, reduced chi-square = % .7g, % .7g' % (out.chisqr, out.redchi)

report_fit(fit_params, show_correl=True, modelpars=p_true)

print 'Raw (unordered, unscaled) Covariance Matrix:'
print out.covar

if HASPYLAB:
    pylab.plot(x, data, 'ro')
    pylab.plot(x, fit, 'b')
    pylab.show()

예제 #17
0
def slit_fit(nu,
             spec,
             init_params=None,
             lineshape='sGaussian',
             power_factor=1.,
             eval_only=False,
             save_fit=False,
             dir_save=None,
             file_name=None,
             **kwargs):
    r"""fitting the experimental slit function with a chosen lineshape

    .. attention::
        It is recommended to always look for initial parameters by using the
        `eval_only` option to roughly match the shape of the experimental slit
        function. The built-in initial parameters may not work for all the
        cases.

    Parameters
    ----------
    nu : 1d array of floats
        Spectral positions in [:math:`\mathrm{cm}^{-1}`].
    spec : 1d array of floats
        Experimentally obtained slit function, usually an isolated atomic line
        from a calibration lamp.
    init_params : dict, optional
        Initial fitting parameters for the lineshape. Refer to
        :mod:`carspy.convol_fcn.asym_Voigt` and
        :mod:`carspy.convol_fcn.asym_Gaussian` for the required arguments.
    lineshape : str, optional
        Type of the lineshape, by default 'sGaussian'. Choose between
        'sGaussian' and 'sVoigt'.
    eval_only : bool, optional
        If true, returns the evaluation with given initial parameters.
    save_fit : bool, optional
        If true, fit results will be saved in a pickle file.
    dir_save : str, optional
        If `save_fit` is true, a string to the desired directory for saving.
    file_name : str, optional
        If `save_fit` is true, specify the file name without file extension.

    Other Parameters
    ----------------
    **kwargs:
        Keyword arguments of the `Model.fit()` method from the module `lmfit`.

    Returns
    -------
    1d array
        If `eval_only` is true, the evaluation result is returned.

    """
    if lineshape == 'sGaussian':
        slit_func = partial(asym_Gaussian, power_factor=power_factor)
    elif lineshape == 'sVoigt':
        slit_func = partial(asym_Voigt, power_factor=power_factor)
    else:
        raise ValueError("Please choose between 'sGaussian' and 'sVoigt'")
    slit_func.__name__ = 'slit_func'

    fit_model = Model(
        slit_func,
        independent_vars='w',
    )

    if init_params is None:
        init_params = (('w0', 0, True), ('sigma', 2, True, 0.01, 10),
                       ('k', 2, True, 0, 10), ('a_sigma', -0.8, True, -5, 5),
                       ('a_k', 1, True, -5, 5), ('sigma_L_l', 0.1, True, 0.01,
                                                 5), ('sigma_L_h', 0.1, True,
                                                      0.01, 5), ('offset', 0,
                                                                 True, 0, 1))

    params = fit_model.make_params()
    params.add_many(*init_params)
    if eval_only:
        return fit_model.eval(params, w=nu)
    else:
        fit_result = fit_model.fit((spec / spec.max())**power_factor,
                                   params,
                                   w=nu,
                                   **kwargs)
        report_fit(fit_result, show_correl=True, modelpars=params)
        fit_result.plot()

        if save_fit and dir_save and file_name:
            path_write = Path(dir_save) / (file_name + '.pkl')
            pkl_dump(path_write, fit_result)
    params_kinetic_seasonal.add("mu_partition",
                                value=0.5,
                                min=math.pow(10.0, -6.0),
                                max=1.0,
                                vary=True)
    params_kinetic_seasonal.add("tau_mu",
                                value=100.0,
                                min=1.0,
                                max=365.0,
                                vary=True)

    kinetic_seasonal_model = Model(SIRD_kinetic_seasonal,
                                   independent_vars=['t', 'x0'])
    optimization_method = "differential_evolution"  # change to another method if desired

    out_kinetic_seasonal = minimize(loss_function,
                                    params_kinetic_seasonal,
                                    args=(
                                        T,
                                        X0,
                                    ),
                                    kws={
                                        "model": kinetic_seasonal_model,
                                        "data": data_array
                                    },
                                    method=optimization_method)
    report_fit(out_kinetic_seasonal, show_correl=False)
    params_json = out_kinetic_seasonal.params.dumps()
    with open(optimization_method + "_params.json", mode='w') as fname:
        json.dump(params_json, fname)
sigma = 0.021  # estimate of data error (for all data points)

myfit = Minimizer(residual,
                  pfit,
                  fcn_args=(x, ),
                  fcn_kws={
                      'sigma': sigma,
                      'data': data
                  },
                  scale_covar=True)

myfit.prepare_fit()
init = residual(myfit.params, x)

if HASPYLAB:
    pylab.plot(x, init, 'b--')

myfit.leastsq()

print(' Nfev = ', myfit.nfev)
print(myfit.chisqr, myfit.redchi, myfit.nfree)

report_fit(myfit.params)

fit = residual(myfit.params, x)

if HASPYLAB:
    pylab.plot(x, fit, 'k-')
    pylab.show()
예제 #20
0
def test_constraints2():
    """add a user-defined function to symbol table"""
    def residual(pars, x, sigma=None, data=None):
        yg = gaussian(x, pars['amp_g'].value, pars['cen_g'].value,
                      pars['wid_g'].value)
        yl = loren(x, pars['amp_l'].value, pars['cen_l'].value,
                   pars['wid_l'].value)

        slope = pars['line_slope'].value
        offset = pars['line_off'].value
        model = yg + yl + offset + x * slope
        if data is None:
            return model
        if sigma is None:
            return (model - data)
        return (model - data) / sigma

    n = 601
    xmin = 0.
    xmax = 20.0
    x = linspace(xmin, xmax, n)

    data = (gaussian(x, 21, 8.1, 1.2) + loren(x, 10, 9.6, 2.4) +
            random.normal(scale=0.23, size=n) + x * 0.5)

    pfit = [
        Parameter(name='amp_g', value=10),
        Parameter(name='cen_g', value=9),
        Parameter(name='wid_g', value=1),
        Parameter(name='amp_tot', value=20),
        Parameter(name='amp_l', expr='amp_tot - amp_g'),
        Parameter(name='cen_l', expr='1.5+cen_g'),
        Parameter(name='line_slope', value=0.0),
        Parameter(name='line_off', value=0.0)
    ]

    sigma = 0.021  # estimate of data error (for all data points)

    myfit = Minimizer(residual,
                      pfit,
                      fcn_args=(x, ),
                      fcn_kws={
                          'sigma': sigma,
                          'data': data
                      },
                      scale_covar=True)

    def width_func(wpar):
        """ """
        return 2 * wpar

    myfit.asteval.symtable['wfun'] = width_func
    myfit.params.add(name='wid_l', expr='wfun(wid_g)')

    myfit.leastsq()

    print(' Nfev = ', myfit.nfev)
    print(myfit.chisqr, myfit.redchi, myfit.nfree)

    report_fit(myfit.params)
    pfit = myfit.params
    fit = residual(myfit.params, x)
    assert (pfit['cen_l'].value == 1.5 + pfit['cen_g'].value)
    assert (pfit['amp_l'].value == pfit['amp_tot'].value - pfit['amp_g'].value)
    assert (pfit['wid_l'].value == 2 * pfit['wid_g'].value)
xmin = 0.
xmax = 250.0
random.seed(0)
noise = random.normal(scale=2.80, size=n)
x     = linspace(xmin, xmax, n)
data  = residual(p_true, x) + noise

fit_params = Parameters()
fit_params.add('amp', value=13.0, max=20, min=0.0)
fit_params.add('period', value=2, max=10)
fit_params.add('shift', value=0.0, max=pi/2., min=-pi/2.)
fit_params.add('decay', value=0.02, max=0.10, min=0.00)

out = minimize(residual, fit_params, args=(x,), kws={'data':data})

fit = residual(out.params, x)

print '# N_func_evals, N_free = ', out.nfev, out.nfree
print '# chi-square, reduced chi-square = % .7g, % .7g' % (out.chisqr, out.redchi)

report_fit(out.params, show_correl=True, modelpars=p_true)

print 'Raw (unordered, unscaled) Covariance Matrix:'
print out.covar

if HASPYLAB:
    pylab.plot(x, data, 'ro')
    pylab.plot(x, fit, 'b')
    pylab.show()

예제 #22
0
def fit(template,
        wave,
        flux,
        err,
        params=None,
        show=False,
        isprint=False,
        mask=None):
    print('run fit')
    if params is None:
        params = Parameters()
        # set_pars(params, 'shift', [0, 1], valuelst=[1.16, -0.00076])
        shiftparname = set_pars(params, 'shift', [1], valuelst=[0.0])
        # sigmaparname = set_pars(params, 'sigma', [1], valuelst=[0.00001],
        #                         minlst=[1.0e-8], maxlst=[5.0e-4])
        scalevalst = [1.0, -1.0, -1.0, 0.22, -0.1, -0.13]
        scaleparname = set_pars(params, 'scale', 5, valuelst=scalevalst)
        # template.set_lmpar_name(scaleparname, sigmaparname, shiftparname)
        template.set_lmpar_name(scaleparname, None, shiftparname)
    # start = time.process_time()
    # print(start)
    if mask is not None:
        argsel = func.mask(wave, mask)
    # print('len wave, flux, err')
    # print(len(wave))
    # print(len(flux))
    # print(len(err))

    def residual(pars, x, data, eps):
        # print('flag')
        # print(pars)
        # print(x)
        # print('length of template is ')
        # print(len(template.wave))
        flux_fit1 = template.get_spectrum(pars, x)
        # print(len(flux_fit1))
        # arrpar = read_lmpar(pars, sigmaparname)
        # flux_fit2 = np.array(convol.gauss_filter(x, data, arrpar))
        if mask is not None:
            return ((flux_fit1 - data) / eps)[argsel]
        return (flux_fit1 - flux_fit2) / eps

    # out = minimize(template.residual, params, args=(wave, flux, err),
    #                method='leastsq')
    # end = time.process_time()
    # print("Time used:", end-start)
    out = minimize(residual, params, args=(wave, flux, err), method='leastsq')
    if isprint:
        report_fit(out)
    # shift = out.params['shift1'].value * c
    # shifterr = out.params['shift1'].stderr * c
    # print('-'*20+' velocity '+'-'*20)
    # print(shift.to('km/s'))
    # print(shifterr.to('km/s'))
    if show:

        plt.figure()

        # arrpar = read_lmpar(out.params, sigmaparname)
        # print('gaussian filter par = ')
        # print(arrpar)
        plt.plot(wave, flux)

        spec_fit = template.get_spectrum(out.params, wave)
        # lower = spec_fit - err
        # upper = spec_fit + err
        #
        # plt.fill_between(wave, lower, upper, alpha=0.3, color='grey')

        plt.plot(wave, spec_fit)
        plt.show()
    return out
예제 #23
0
    if data is None:
        return model
    return model - data


###############################################################################
# Generate synthetic data and initialize fitting Parameters:
random.seed(0)
x = linspace(0, 250, 1500)
noise = random.normal(scale=2.8, size=x.size)
data = residual(p_true, x) + noise

fit_params = Parameters()
fit_params.add('amp', value=13, max=20, min=0)
fit_params.add('period', value=2, max=10)
fit_params.add('shift', value=0, max=pi/2., min=-pi/2.)
fit_params.add('decay', value=0.02, max=0.1, min=0)

###############################################################################
# Perform the fit and show the results:
out = minimize(residual, fit_params, args=(x,), kws={'data': data})
fit = residual(out.params, x)

###############################################################################
report_fit(out, modelpars=p_true)

###############################################################################
plt.plot(x, data, 'o', label='data')
plt.plot(x, fit, label='best fit')
plt.legend()
예제 #24
0
        Parameter(name='line_off', value=0.0)]

sigma = 0.021  # estimate of data error (for all data points)

myfit = Minimizer(residual, pfit, 
                  fcn_args=(x,), fcn_kws={'sigma':sigma, 'data':data},
                  scale_covar=True)

myfit.prepare_fit()
init = residual(myfit.params, x)

if HASPYLAB:
    pylab.plot(x, init, 'b--')

myfit.leastsq()

print(' Nfev = ', myfit.nfev)
print( myfit.chisqr, myfit.redchi, myfit.nfree)

report_fit(myfit.params)

fit = residual(myfit.params, x)

if HASPYLAB:
    pylab.plot(x, fit, 'k-')
    pylab.show()




예제 #25
0
def test_constraints(with_plot=True):
    with_plot = with_plot and WITHPLOT

    def residual(pars, x, sigma=None, data=None):
        yg = gaussian(x, pars['amp_g'].value, pars['cen_g'].value,
                      pars['wid_g'].value)
        yl = lorentzian(x, pars['amp_l'].value, pars['cen_l'].value,
                        pars['wid_l'].value)

        slope = pars['line_slope'].value
        offset = pars['line_off'].value
        model = yg + yl + offset + x * slope
        if data is None:
            return model
        if sigma is None:
            return (model - data)
        return (model - data) / sigma

    n = 201
    xmin = 0.
    xmax = 20.0
    x = linspace(xmin, xmax, n)

    data = (gaussian(x, 21, 8.1, 1.2) + lorentzian(x, 10, 9.6, 2.4) +
            random.normal(scale=0.23, size=n) + x * 0.5)

    if with_plot:
        pylab.plot(x, data, 'r+')

    pfit = Parameters()
    pfit.add(name='amp_g', value=10)
    pfit.add(name='cen_g', value=9)
    pfit.add(name='wid_g', value=1)

    pfit.add(name='amp_tot', value=20)
    pfit.add(name='amp_l', expr='amp_tot - amp_g')
    pfit.add(name='cen_l', expr='1.5+cen_g')
    pfit.add(name='wid_l', expr='2*wid_g')

    pfit.add(name='line_slope', value=0.0)
    pfit.add(name='line_off', value=0.0)

    sigma = 0.021  # estimate of data error (for all data points)

    myfit = Minimizer(residual,
                      pfit,
                      fcn_args=(x, ),
                      fcn_kws={
                          'sigma': sigma,
                          'data': data
                      },
                      scale_covar=True)

    myfit.prepare_fit()
    init = residual(myfit.params, x)

    myfit.leastsq()

    print(' Nfev = ', myfit.nfev)
    print(myfit.chisqr, myfit.redchi, myfit.nfree)

    report_fit(myfit.params, min_correl=0.3)

    fit = residual(myfit.params, x)
    if with_plot:
        pylab.plot(x, fit, 'b-')
    assert (myfit.params['cen_l'].value == 1.5 + myfit.params['cen_g'].value)
    assert (myfit.params['amp_l'].value == myfit.params['amp_tot'].value -
            myfit.params['amp_g'].value)
    assert (myfit.params['wid_l'].value == 2 * myfit.params['wid_g'].value)

    # now, change fit slightly and re-run
    myfit.params['wid_l'].expr = '1.25*wid_g'
    myfit.leastsq()
    report_fit(myfit.params, min_correl=0.4)
    fit2 = residual(myfit.params, x)
    if with_plot:
        pylab.plot(x, fit2, 'k')
        pylab.show()

    assert (myfit.params['cen_l'].value == 1.5 + myfit.params['cen_g'].value)
    assert (myfit.params['amp_l'].value == myfit.params['amp_tot'].value -
            myfit.params['amp_g'].value)
    assert (myfit.params['wid_l'].value == 1.25 * myfit.params['wid_g'].value)
예제 #26
0
    def ls_fit(self, add_params=None, path_fit=None, show_fit=False,
               eval_only=False, **kwargs):
        """
        Fitting the experimental CARS spectrum.

        .. attention::
            The least-quare fit module ``lmfit`` is necessary for this method.
            Please be aware that certain Python versions may not be supported
            by ``lmfit``. For displaying the fit results ``matplotlib`` will be
            needed as well.

        Parameters
        ----------
        add_params : nested tuple, optional
            List of parameters controlling the fitting process. This option can
            be used to modify these initial parameters:

            .. code-block:: python

                (('temperature', 2000, True, 250, 3000),
                 ('del_Tv', 0, False),
                 ('x_mol', 0.6, x_mol_var, 0.2, 1.5),
                 ('nu_shift', fit_params['nu_shift'], False),
                 ('nu_stretch', fit_params['nu_stretch'], False),
                 ('pump_lw', fit_params['pump_lw'], False),
                 ('param1', fit_params['param1'], False),
                 ('param2', fit_params['param2'], False),
                 ('param3', fit_params['param3'], False),
                 ('param4', fit_params['param4'], False),
                 ('param5', fit_params['param5'], False),
                 ('param6', fit_params['param6'], False))
            Each element of the nested tuple has the following element in
            order:
                variable_name : str
                    All the arguments of
                    :mod:`carspy.cars_fit.CarsFit.cars_expt_synth`
                    are admissible variables except for the independent
                    variable `nu_expt`.
                initial_guess : float
                    Initial guess or fixed value set for this variable.
                variable : bool
                    Determine if the variable is fixed (False) or not (True)
                    during the fit.
                lower_bound : float
                    Lower boundary for the fitting variable. If not provided,
                    negative infinity will be assumed.
                upper_bound : float
                    Upper boundary for the fitting variable. If not provide,
                    positive infinity will be assumed.
            For more details refer to the documentation of ``lmfit.Model``.
        path_fit : str
            Path to the `.pkl` file of fitting result created by
            :mod:`carspy.cars_fit.CarsFit.save_fit`. This allows importing
            the fitting result of an existing spectrum, such that the inferred
            values of certain parameters (such as those related to the
            spectrometer) could be re-used in the next fit. A standard use case
            for this would be the fitting result of a room-temperature
            spectrum. This is needed if the `fit` in `fit_mode` of
            :mod:`carspy.cars_fit.CarsFit` is set to `T_x`.
        show_fit : bool, optional
            If True, the fitting results will be reported and plotted. This is
            done via built-in functions in ``lmfit``.
        """
        # general setup
        fit_model = Model(self.cars_expt_synth, independent_vars=['nu_expt'])
        initi_params = []
        # different fitting modes
        if self.fit_mode['fit'] == 'T_x':
            if path_fit is None:
                raise ValueError("Please provide path to a .pkl file "
                                 "containing the fitting result of a spectrum")
            if self.fit_mode['chem_eq']:
                x_mol_var = False
            else:
                x_mol_var = True
            fit_params = pkl_load(path_fit).params
            initi_params = (('temperature', 2000, True, 250, 3000),
                            ('del_Tv', 0, False),
                            ('x_mol', 0.6, x_mol_var, 0.2, 1.5),
                            ('nu_shift', fit_params['nu_shift'], False),
                            ('nu_stretch', fit_params['nu_stretch'], False),
                            ('pump_lw', fit_params['pump_lw'], False),
                            ('param1', fit_params['param1'], False),
                            ('param2', fit_params['param2'], False),
                            ('param3', fit_params['param3'], False),
                            ('param4', fit_params['param4'], False),
                            ('param5', fit_params['param5'], False),
                            ('param6', fit_params['param6'], False))

        if self.fit_mode['fit'] == 'custom':
            if add_params is None:
                raise ValueError("Please specify fitting parameters first "
                                 "using add_params")
        params = fit_model.make_params()
        params.add_many(*initi_params)
        if add_params is not None:
            params.add_many(*add_params)

        if eval_only:
            return fit_model.eval(params, nu_expt=self.nu)
        else:
            self.fit_result = fit_model.fit(np.nan_to_num(self.spec_cars),
                                            params,
                                            nu_expt=self.nu, **kwargs)

            if show_fit:
                report_fit(self.fit_result, show_correl=True, modelpars=params)
                self.fit_result.plot()
예제 #27
0
def fit_lamost():
    bluelst, redlst = [], []
    namelst = glob.glob('/home/zzx/workspace/data/stellar_X/*.fits')
    namelst = [
        '/home/zzx/workspace/data/stellar_X/med-58409-TD045606N223435B01_sp16-102.fits'
    ]
    for name in namelst:
        # fig1 = plt.figure()
        # fig2 = plt.figure()
        # ax1 = fig1.add_subplot(111)
        # ax2 = fig2.add_subplot(111)
        print(name)
        size = len(fits.open(name))
        for ind in range(3, size):
            spec = specio.Spectrum(name, ind)
            spec.clean_cosmic_ray()
            if 'B' in spec.header['EXTNAME']:
                bluelst.append(spec)
            else:
                redlst.append(spec)
    name = namelst[0]
    model_blue = Model(name, 3)
    model_blue.clean_cosmic_ray()
    model_red = Model(name, 11)
    model_red.clean_cosmic_ray()
    params = Parameters()
    shiftparname = set_pars(params, 'shift', [1], valuelst=[0.0])
    scalevalst = [
        0.99608100, -0.00931768, 0.00319284, 5.5658e-04, -4.4060e-04, 0.0
    ]
    bscaleparname = set_pars(params, 'b_scale', 5, valuelst=scalevalst)
    rscaleparname = set_pars(params, 'r_scale', 5, valuelst=scalevalst)
    bsimgapar = set_pars(params, 'b_sigma', [1], valuelst=[0.0004])
    rsigmapar = set_pars(params, 'r_sigma', [1], valuelst=[0.0004])
    model_blue.set_lmpar_name(bscaleparname, bsimgapar, shiftparname)
    model_red.set_lmpar_name(rscaleparname, rsigmapar, shiftparname)
    shiftlst, shifterrlst = [], []

    def residual(pars, x1, data1, eps1, x2, data2, eps2):
        res1 = model_blue.residual(pars, x1, data1, eps1)
        res2 = model_red.residual(pars, x2, data2, eps2)
        return np.append(res2, res1)
        return res2

    for ind in range(len(redlst)):
        bspec = bluelst[ind]
        # bspec = redlst[ind]
        rspec = redlst[ind]
        arg1 = func.select(bspec.wave, [[4920, 5300]])
        bnw = bspec.wave[arg1]
        bnf = bspec.flux[arg1]
        bne = bspec.err[arg1]
        arg2 = func.select(rspec.wave, [[6320, 6860]])
        rnw = rspec.wave[arg2]
        rnf = rspec.flux[arg2]
        rne = rspec.err[arg2]
        bfakeerr = np.ones(len(bnw), dtype=np.float64) * 0.01
        rfakeerr = np.ones(len(rnw), dtype=np.float64) * 0.01
        bne = bfakeerr
        rne = rfakeerr
        # out = minimize(model_blue.residual, params, args=(nw, nf))
        # out = minimize(model_red.residual, params, args=(nw, nf))
        out = minimize(residual, params, args=(bnw, bnf, bne, rnw, rnf, rne))
        report_fit(out)
        shiftlst.append(out.params['shift1'].value * c)
        shifterrlst.append(out.params['shift1'].stderr * c)

        plt.figure()

        spec_fit_blue = model_blue.get_spectrum(out.params, model_blue.wave)
        spec_fit_red = model_red.get_spectrum(out.params, model_red.wave)

        plt.plot(bnw, bnf)
        plt.plot(model_blue.wave, spec_fit_blue)

        plt.figure()
        plt.plot(rnw, rnf)
        plt.plot(model_red.wave, spec_fit_red)
        plt.show()

    for ind, value in enumerate(shiftlst):
        # print(value.to('km/s'))
        print(value.to('km/s'), shifterrlst[ind].to('km/s'))