Exemplo n.º 1
0
    def T_color_zeta(self, is_quiet=True, is_Fj=False):
        from pystella.fit import mpfit
        """
        Fitting Spectrum by planck function and find the color temperature
        :return:   color temperature adn dilution
        """
        def least_sq(p, fjac):
            T = p[0]
            w = p[1]
            if is_Fj:
                wbb = w * rf.planck(self.Freq, T, inp="Hz", out="freq")
            else:
                wbb = np.pi * w * rf.planck(self.Freq, T, inp="Hz", out="freq")

            # model interpolation
            res = np.abs(self.Flux - wbb)
            return 0, res

        Tinit, W = self.T_wien, 1.
        xtol = 1e-10
        ftol = 1e-10
        gtol = 1e-10
        parinfo = [{
            'value': Tinit,
            'limited': [1, 1],
            'limits': [10., 1e7]
        }, {
            'value': 1.,
            'limited': [1, 1],
            'limits': [0., 1e9]
        }]
        result = mpfit.mpfit(least_sq,
                             parinfo=parinfo,
                             quiet=is_quiet,
                             maxiter=200,
                             ftol=ftol,
                             gtol=gtol,
                             xtol=xtol)
        popt = result.params

        # if is_mpfit:
        #     xtol = 1e-10
        #     ftol = 1e-10
        #     gtol = 1e-10
        #     parinfo = [{'value': Tinit, 'limited': [1, 1], 'limits': [10., 1e6]},
        #                {'value': 1., 'limited': [1, 1], 'limits': [0., 1e9]}]
        #     result = mpfit.mpfit(least_sq, parinfo=parinfo, quiet=is_quiet, maxiter=200,
        #                          ftol=ftol, gtol=gtol, xtol=xtol)
        #     popt = result.params
        # else:
        #     def func(nu, T, w):
        #         return np.pi * w * rf.planck(nu, T, inp="Hz", out="freq")
        #     popt, pcov = curve_fit(func, self.Freq, self.Flux, p0=(Tinit, W))
        return popt
Exemplo n.º 2
0
def popov_fit(lc, R0, M0, Mni0=None, E0=None, dt0=None,
              is_verbose=True, xtol=1e-10, ftol=1e-10, gtol=1e-10):
    if is_verbose:
        quiet = 0
    else:
        quiet = 1

    time = lc.Time

    def leastsq(p, fjac):
        mdl = Popov('test', R=p[0], M=p[1], Mni=p[2], E=p[3])
        l_dt = p[4]
        t = time + l_dt
        m = mdl.MagBol(t)
        res = (lc.Mag - m)
        w = np.exp(-(max(abs(lc.Mag)) - abs(lc.Mag))*2)  # weight
        w = 1.
        # w = w / max(w)
        if lc.MagErr is not None:
            res = res * w / lc.MagErr
        return 0, res

    parinfo = [{'value': R0,   'limited': [1, 1], 'limits': [10., 1500e0]},
               {'value': M0,   'limited': [1, 1], 'limits': [1., 150.]}
               # {'value': Mni0, 'limited': [1, 1], 'limits': [0.0000001, 0.00001]},
               # , {'value': E0,   'limited': [1, 1], 'limits': [0.01, 5.]}
               # , {'value': dt0,  'limited': [1, 1], 'limits': [-200., 250.]}
               ]
    if Mni0 is not None:
        parinfo.append({'value': Mni0, 'limited': [1, 1], 'limits': [0.0000001, 0.00001]})
    else:
        parinfo.append({'value': 0., 'fixed': 1})
    if E0 is not None:
        parinfo.append({'value': E0,   'limited': [1, 1], 'limits': [0.01, 5.]})
    else:
        parinfo.append({'value': 1., 'fixed': 1})
    if dt0 is not None:
        parinfo.append({'value': dt0,  'limited': [1, 1], 'limits': [-200., 250.]})
    else:
        parinfo.append({'value': 0., 'fixed': 1})

    result = mpfit.mpfit(leastsq, parinfo=parinfo, quiet=quiet, maxiter=200,
                         ftol=ftol, gtol=gtol, xtol=xtol)
    if result.status == 5:
        print 'Maximum number of iterations exceeded in mangle_spectrum'

    ppv = Popov('test', R=result.params[0], M=result.params[1], Mni=result.params[2], E=result.params[3])
    tshift = result.params[4]

    if is_verbose:
        print "The final params are: R=%f M=%f Mni=%f E=%f; dt = %f " % (
            result.params[0], result.params[1], result.params[2], result.params[3], tshift)
    return ppv, tshift
Exemplo n.º 3
0
def myfit(mags, lc, is_verbose=True, xtol=1e-10, ftol=1e-10, gtol=1e-10):
    if is_verbose:
        quiet = 0
    else:
        quiet = 1
    t0 = 0.

    mags_interp = interpolate.splrep(lc.Time, mags, s=0)

    def leastsq(p, fjac):
        lc.tshift = p[0]
        m = interpolate.splev(lc.Time, mags_interp)
        return 0, lc.Mag - m

    parinfo = [{'value': t0}]
    result = mpfit.mpfit(leastsq, parinfo=parinfo, quiet=quiet, maxiter=200,
                         ftol=ftol, gtol=gtol, xtol=xtol)
    if result.status == 5:
        print 'Maximum number of iterations exceeded in mangle_spectrum'

    tshift = result.params[0]
    if is_verbose:
        print "The final tshift are: %f" % tshift
    return tshift
Exemplo n.º 4
0
    def best_curves_gp(self,
                       curves_m,
                       curves_o,
                       dt0=None,
                       dm0=None,
                       Npoints=None,
                       At=0.,
                       err_mdl=0.):
        from pystella.fit.fit_gp import FitGP

        dt_init = {lc.Band.Name: lc.tshift for lc in curves_o}
        dm_init = {lc.Band.Name: lc.mshift for lc in curves_o}

        # заменить модель на  сплайны
        curves_m_spline = {}
        for lc_m in curves_m:
            curves_m_spline[lc_m.Band.Name] = InterpolatedUnivariateSpline(
                lc_m.Time, lc_m.Mag, k=1)

        # Вычислить chi
        def least_sq(p, fjac):
            total = []
            for lc_m in curves_m:
                lc_o = curves_o.get(lc_m.Band.Name)
                lc_o.tshift = dt_init[lc_m.Band.Name] + p[0]
                lc_o.mshift = dm_init[lc_m.Band.Name] + p[1]
                N = Npoints if Npoints is not None else lc_o.Length
                # to = lc_o.Time
                # Chick time ranges
                tmin = max(lc_o.TimeMin, lc_m.TimeMin)
                tmax = min(lc_o.TimeMax, lc_m.TimeMax)

                # заменить наблюдения их гауссовым процессом
                if True and lc_o.IsErr:
                    to_gp = np.linspace(tmin, tmax, N)
                    gp_o = FitGP.lc2gp(lc_o)
                    mo, err_o = gp_o.predict(to_gp.reshape(-1, 1),
                                             return_std=True)
                else:
                    to_gp = lc_o.Time
                    mo = lc_o.Mag
                    err_o = lc_o.MagErr

                # model interpolation
                s = curves_m_spline[lc_m.Band.Name]
                m = s(to_gp)
                #                w = np.ones(len(m))
                w = np.abs(1. - At * (to_gp - tmin) / (tmax - tmin))  # weight
                diff = mo - m
                if lc_o.IsErr:
                    deviates = diff * w / (err_mdl + err_o)
                else:
                    deviates = diff * w
                total = np.append(total, deviates)
            return 0, total

        parinfo = []
        if dt0 is not None:
            parinfo.append({
                'value': dt0,
                'limited': [1, 1],
                'limits': [-250. + dt0, 250. + dt0]
            })
        else:
            parinfo.append({'value': 0., 'fixed': 1})

        if dm0 is not None:
            parinfo.append({
                'value': dm0,
                'limited': [1, 1],
                'limits': [-5. + dm0, 5. + dm0]
            })
        else:
            parinfo.append({'value': 0., 'fixed': 1})

        if dt0 is not None or dm0 is not None:
            result = mpfit.mpfit(least_sq,
                                 parinfo=parinfo,
                                 quiet=self.is_quiet,
                                 maxiter=self.maxiter,
                                 ftol=self.ftol,
                                 gtol=self.gtol,
                                 xtol=self.xtol)
        else:
            dum, r = least_sq([x['value'] for x in parinfo],
                              None)  # just return the weight diff
            r = np.array(r)
            chi2 = np.sum(r**2)
            if self.is_info:
                print("No fit: only run least_sq: len(r)={}  chi2={}".format(
                    len(r), chi2))

            res = {
                'dt': None,
                'dtsig': None,
                'dm': None,
                'dmsig': None,
                'chi2': chi2,
                'dof': len(r)
            }
            return res

        # return initial states
        for lc in curves_o:
            lc.tshift = dt_init[lc.Band.Name]
            lc.mshift = dm_init[lc.Band.Name]

        if result.status <= 0:
            print('status = ', result.status)
            print('error message = ', result.errmsg)
            print('parameters = ', result.params)
            raise ValueError(result.errmsg)

        if self.is_info:
            print("status: ", result.status)
            if result.status == 5:
                print(
                    'Maximum number of iterations exceeded in mangle_spectrum')
            else:
                print("Iterations: ", result.niter)
                print("Fitted pars: ", result.params)
                print("Uncertainties: ", result.perror)

        # time and magnitude shifts
        tshift = result.params[0]
        dof = np.sum([lc.Length for lc in curves_o])
        if dt0 is not None:
            dof -= 1
        if dm0 is not None:
            dof -= 1

        # scaled uncertainties
        pcerror = result.perror * np.sqrt(result.fnorm / dof)
        tsigma = pcerror[0]  # todo tsigma check

        dmshift = result.params[1]
        dmsigma = pcerror[1]

        if self.is_info:
            print(
                "The final params are: tshift=%f+-%f mshift=%f+-%f  chi2: %e" %
                (tshift, tsigma, dmshift, dmsigma, result.fnorm))
        res = {
            'dt': tshift,
            'dtsig': tsigma,
            'dm': dmshift,
            'dmsig': dmsigma,
            'chi2': result.fnorm,
            'dof': result.dof
        }
        return res
Exemplo n.º 5
0
    def best_curves(self, curves_m, curves_o, dt0=None, dm0=None, **kwargs):
        # is_spline=True, At=0., **kwargs):
        """
        Find the values of time shift and magnitude shift minimizing the distance between the observational
        and modal light curves
        :param curves_m: modal LCs
        :param curves_o: observational LCs
        :param dt0: initial time shift
        :param dm0: magnitude shift, default: 0.
        :param is_spline:
        :param At:
        :param kwargs:
                dt_limits = kwargs.get("dt_limits", [-250., 250.])
                dm_limits = kwargs.get("dm_limits", [-5., 5])
                band_limits = kwargs.get("band_limits", [0.001, 4.])
                is_fit_sigmas = kwargs.get("is_fit_sigmas", False)
        :return:
        """
        dt_init = {lc.Band.Name: lc.tshift for lc in curves_o}
        dm_init = {lc.Band.Name: lc.mshift for lc in curves_o}
        bnames = curves_o.BandNames

        is_spline = kwargs.get("is_spline", True)
        At = kwargs.get("At", 0.)
        dt_limits = kwargs.get("dt_limits", [-250., 250.])
        dm_limits = kwargs.get("dm_limits", [-5., 5])
        band_limits = kwargs.get("band_limits", [0.001, 4.])
        is_fit_sigmas = kwargs.get("is_fit_sigmas", False)
        magerr_uplim = kwargs.get("magerr_uplim", 0.01)
        magerr_downlim = kwargs.get("magerr_downlim", 0.01)
        magerr_goodlim = kwargs.get("magerr_goodlim", 10.)

        # заменить модели их сплайном
        curves_m_spline = {}
        if is_spline:
            for lc_m in curves_m:
                curves_m_spline[lc_m.Band.Name] = InterpolatedUnivariateSpline(
                    lc_m.Time, lc_m.Mag, k=1)

        def least_sq_simga(p, fjac):
            dt, dm, sigs = FitMPFit.thetaDtDm2arr(p, len(bnames))
            # dt, dm = p
            # dt, dm, sigma = p
            total = []
            for i, bname in enumerate(bnames):
                lc_o = curves_o[bname]
                to, mo, eo = lc_o.Time, lc_o.Mag, lc_o.MagErr
                # lc_o = curves_o.get(lc_m.Band.Name)
                # lc_o.tshift = dt_init[lc_m.Band.Name] + dt
                # lc_o.mshift = dm_init[lc_m.Band.Name] + dm
                # model interpolation
                lc_m = curves_m[bname]
                tm, mm = lc_m.Time, lc_m.Mag
                mm += dm
                tm += dt
                em = sigs[i]
                m = np.interp(to, tm,
                              mm)  # One-dimensional linear interpolation.
                #                w = np.ones(len(m))
                # err_m = abs(min(m)-m) * err_mdl
                # w = np.abs(1. - At * (lc_o.Time - lc_o.TimeMin) / (lc_o.TimeMax - lc_o.TimeMin))  # weight
                diff = lc_o.Mag - m
                sig = np.ones(lc_o.Length) * em
                if lc_o.IsErr:
                    sig = np.sqrt(em**2 + lc_o.MagErr**2)

                    # err_m = np.sqrt(np.sum(diff ** 2) / len(m))
                inv_sigma2 = 1. / sig**2
                chi = np.sqrt(
                    np.abs(diff**2 * inv_sigma2 - np.log(inv_sigma2) +
                           np.log(2 * np.pi)))
                # chi = np.sum(diff**2 * inv_sigma2 - np.log(inv_sigma2)) + np.log(2 * np.pi) * len(diff)
                # chi = np.sum(diff**2 * inv_sigma2 - np.log(inv_sigma2) + np.log(2 * np.pi))
                # chi = diff / sig #+ np.log(sig*np.pi)/lc_o.Length
                # chi += fjac[0]
                # chi = np.ones(lc_o.Length) * chi
                total = np.append(total, chi)
            return 0, total

        def least_sq(p, fjac):
            dt, dm, sigs = FitMPFit.thetaDtDm2arr(p, len(bnames))
            total = []
            for lc_m in curves_m:
                lc_o = curves_o.get(lc_m.Band.Name)
                to, mo = lc_o.Time, lc_o.Mag
                to -= dt
                mo -= dm
                # if to too large
                cut = to <= np.max(lc_m.Time)
                to = to[cut]
                mo = mo[cut]
                # model interpolation
                if is_spline:
                    s = curves_m_spline[lc_m.Band.Name]
                    mm = s(to)
                else:
                    mm = np.interp(
                        to, lc_m.Time,
                        lc_m.Mag)  # One-dimensional linear interpolation.
                #                w = np.ones(len(m))
                # err_m = abs(min(m)-m) * err_mdl
                w = np.ones_like(to)  # weight
                # if max(to) - min(to) > 0:
                #     w = np.abs(1. - At * (to -  min(to)) / (max(to) - min(to)))
                diff = mo - mm
                chi = diff * w
                if lc_o.IsErr:
                    eo = np.copy(lc_o.MagErr)
                    eo = eo[cut]
                    # check
                    if any(eo == 0):
                        # one = np.array(range(len(eo)))
                        one = np.arange(len(eo), dtype=int)
                        check0 = eo == 0
                        one = np.array(one[check0])
                        msg = 'Error in band: {}. err_mag == 0 for lines: {}'.format(
                            lc_m.Band.Name, ', '.join(map(str, one)))
                        # print(msg)
                        raise ValueError(msg)

                    for i, e in enumerate(lc_o.MagErr[cut]):
                        # обработать вверхние и нижние пределы в наблюдениях
                        if e == -1:  # upper lim
                            if diff[i] > 0:
                                eo[i] = magerr_uplim  # сильно увеличить вес моделей превышающих верхний предел
                            else:
                                eo[i] = magerr_goodlim
                        elif e == -2:  # down lim
                            if diff[i] > 0:
                                eo[i] = magerr_downlim  # сильно увеличить вес моделей, проходящих ниже предела
                            else:
                                eo[i] = magerr_goodlim
                    chi /= eo
                #                    res = diff**2 * w
                total = np.append(total, chi)
                # total = np.append(total, chi)
            return 0, total

        parinfo = [
        ]  # [{'value': 0.0, 'limited': [1, 1], 'limits': [0., 3.]}]  # todo changeable parameters
        if dt0 is not None:
            dt_limits = [x + dt0 for x in dt_limits]
            parinfo.append({
                'value': dt0,
                'limited': [1, 1],
                'limits': dt_limits
            })
        else:
            parinfo.append({'value': 0., 'fixed': 1})

        if dm0 is not None:
            dm_limits = [x + dm0 for x in dm_limits]
            parinfo.append({
                'value': dm0,
                'limited': [1, 1],
                'limits': dm_limits
            })
        else:
            parinfo.append({'value': 0., 'fixed': 1})

        for i, bname in enumerate(bnames):
            parinfo.append({
                'value': 0.1,
                'limited': [1, 1],
                'limits': band_limits
            })  # todo changeable parameters

        if dt0 is not None or dm0 is not None:
            func = least_sq
            if is_fit_sigmas:
                func = least_sq_simga
            result = mpfit.mpfit(func,
                                 parinfo=parinfo,
                                 quiet=self.is_quiet,
                                 maxiter=self.maxiter,
                                 ftol=self.ftol,
                                 gtol=self.gtol,
                                 xtol=self.xtol)
        else:
            dum, r = least_sq([x['value'] for x in parinfo],
                              None)  # just return the weight diff
            r = np.array(r)
            chi2 = np.sum(r**2)
            if self.is_info:
                print("No fit: only run least_sq: len(r)={}  chi2={}".format(
                    len(r), chi2))

            res = {
                'dt': None,
                'dtsig': None,
                'dm': None,
                'dmsig': None,
                'chi2': chi2,
                'dof': len(r)
            }
            return res

        # return initial states
        for lc in curves_o:
            lc.tshift = dt_init[lc.Band.Name]
            lc.mshift = dm_init[lc.Band.Name]

        if result.status <= 0:
            print('status = ', result.status)
            print('error message = ', result.errmsg)
            print('parameters = ', result.params)
            raise ValueError(result.errmsg)

        if self.is_info:
            print("status: ", result.status)
            if result.status == 5:
                print(
                    'Maximum number of iterations exceeded in mangle_spectrum')
            else:
                print("Iterations: ", result.niter)
                print("Fitted pars: ", result.params)
                print("Uncertainties: ", result.perror)

        dof = np.sum([lc.Length for lc in curves_o])
        if dt0 is not None:
            dof -= 1
        if dm0 is not None:
            dof -= 1

        # pcerror = result.perror  # * np.sqrt(result.fnorm / dof)

        # time and magnitude shifts

        dt, dtsig = result.params[0], result.perror[0]
        dm, dmsig = result.params[1], result.perror[1]

        if self.is_info:
            print(
                "The final params are: tshift=%f+-%f mshift=%f+-%f  chi2: %e" %
                (dt, dtsig, dm, dmsig, result.fnorm))

        res = {
            'dt': dt,
            'dtsig': dtsig,
            'dm': dm,
            'dmsig': dmsig,
            'chi2': result.fnorm,
            'dof': result.dof
        }
        # scaled uncertainties
        if len(result.params) > 2:
            err, errsig = result.params[2:], result.perror[2:]
            res['err'] = err
            res['errsig'] = errsig
            if self.is_info:
                for i, bname in enumerate(bnames):
                    print("The sigma_{}= {} +- {}".format(
                        bname, err[i], errsig[i]))

        fit_result = FitLcResult()
        fit_result.tshift = res['dt']
        fit_result.tsigma = res['dtsig']
        fit_result.mshift = dm
        fit_result.msigma = res['dmsig']
        fit_result.measure = res['chi2']

        dt, dm, sigs = FitMPFit.thetaDtDm2arr(result.params, len(bnames))
        if is_fit_sigmas:
            fit_result.comm = 'result {}:dof: {} sigmas: {}'. \
                format(self.Name, res['dof'], ' '.join([f'{bn}: {sigs[i]:.3f}' for i, bn in enumerate(bnames)]))
        else:
            fit_result.comm = 'result {}:dof: {}'.format(self.Name, res['dof'])

        return fit_result, res, None  # as Fit_MCMC
Exemplo n.º 6
0
    def best_time_series(tss_m,
                         tss_o,
                         At=0.,
                         is_debug=False,
                         is_info=True,
                         xtol=1e-10,
                         ftol=1e-10,
                         gtol=1e-10):
        # print('Input tss_o:')
        # for ts in tss_o:
        #     print(ts.Name, ts.Time, ts.V)
        # print('Input tss_m:')
        # for ts in tss_m:
        #     print(ts.Name, ts.Time, ts.V)

        def least_sq(p, fjac):
            dt, sigs = p
            # print('dt, sigs = ',dt, sigs)
            E = 0.01
            total = []
            for ts_m in tss_m:
                ts_o = tss_o[ts_m.Name]
                # ts_o.tshift = dt
                sigma = sigs
                # model interpolation
                # check = np.where((ts_o.Time > min(ts_m.Time)) & (ts_o.Time < max(ts_m.Time)))
                # check = range(1, len(ts_o.Time))
                # time_o = ts_o.Time[check]
                # V_o = ts_o.V[check]
                time_o = ts_o.Time
                V_o = ts_o.V

                m = np.interp(time_o, ts_m.Time + dt,
                              ts_m.V)  # One-dimensional linear interpolation.
                # if 'Vel' in ts_m.Name:
                #     print(ts_o.Name, ts_o.tshift, ts_o.Time, ts_o.V)
                #     print(ts_m.Name, ts_m.tshift, ts_m.Time, ts_m.V)
                # print('time_o, m: ', time_o, m)
                # sigma = sigma
                # w = 1.
                # if At > 0:
                #     w = np.abs(1. - At * (time_o - min(time_o)) / (max(time_o) - min(time_o)))  # weight
                # err_m = np.sqrt(np.sum((V_o - m) ** 2) / len(m))
                # # err_m = abs(V_o - m)
                # if ts_o.IsErr:
                #     # err_o = ts_o.Err[check]
                #     # res = np.abs((V_o - m) / (abs(m)*E + err_o)) * w
                #     res = np.abs((V_o - m) / (err_m + ts_o.Err)) * w
                #     # res = np.abs((V_o - m) / (err_m + ts_o.Err+sigma)) * w
                #     # res = np.abs(V_o - m) * w
                # else:
                #     res = np.abs(V_o - m) * w

                em = sigs
                diff = ts_o.V - m
                sig = np.ones(ts_o.Length) * em
                if ts_o.IsErr:
                    sig = np.sqrt(em**2 + ts_o.Err**2)

                    # err_m = np.sqrt(np.sum(diff ** 2) / len(m))
                inv_sigma2 = 1. / sig**2
                chi = np.sqrt(
                    np.abs(diff**2 * inv_sigma2 - np.log(inv_sigma2) +
                           np.log(2 * np.pi)))
                # chi = np.sum(diff**2 * inv_sigma2 - np.log(inv_sigma2)) + np.log(2 * np.pi) * len(diff)
                # chi = np.sum(diff**2 * inv_sigma2 - np.log(inv_sigma2) + np.log(2 * np.pi))
                # chi = diff / sig #+ np.log(sig*np.pi)/lc_o.Length
                # chi += fjac[0]
                # chi = np.ones(lc_o.Length) * chi
                total = np.append(total, chi)

                # total = np.append(total, res)
            return 0, total

        # parinfo = [{'value': 0., 'limited': [1, 1], 'limits': [-250., 250.]}]
        parinfo = [{
            'value': 0.,
            'limited': [1, 1],
            'limits': [-250., 250.]
        }, {
            'value': 0.001,
            'limited': [1, 1],
            'limits': [0.001, 3.]
        }]
        result = mpfit.mpfit(least_sq,
                             parinfo=parinfo,
                             quiet=not is_debug,
                             maxiter=200,
                             ftol=ftol,
                             gtol=gtol,
                             xtol=xtol)

        if is_info:
            print("status: ", result.status)
            if result.status <= 0:
                print('status = ', result.status)
                print('error message = ', result.errmsg)
                print('parameters = ', result.params)
                raise ValueError(result.errmsg)
            elif result.status == 5:
                print(
                    'Maximum number of iterations exceeded in mangle_spectrum')
            else:
                print("Iterations: ", result.niter)
                print("Fitted pars: ", result.params)
                print("Uncertainties: ", result.perror)

        return result
Exemplo n.º 7
0
    def best_lc(self, lc_m, lc_o, dt0=None, dm0=None, At=0., is_spline=True):
        dt_init = lc_o.tshift
        dm_init = lc_o.mshift

        def least_sq(p, fjac):
            lc_o.tshift = dt_init + p[0]
            lc_o.mshift = dm_init + p[1]
            # model interpolation
            if is_spline:
                s = InterpolatedUnivariateSpline(lc_m.Time, lc_m.Mag, k=1)
                m = s(lc_o.Time)
            else:
                m = np.interp(
                    lc_o.Time, lc_m.Time,
                    lc_m.Mag)  # One-dimensional linear interpolation.
            w = np.ones(len(m))
            w = np.abs(1. - At * (lc_o.Time - lc_o.TimeMin) /
                       (lc_o.TimeMax - lc_o.TimeMin))  # weight
            # w = np.abs(lc_o.Time / max(lc_o.Time))  # weight
            diff = lc_o.Mag - m
            if lc_o.IsErr:
                res = diff**2 / lc_o.MagErr**2 * w
                # res = np.abs((lc_o.Mag - m) / lc_o.MagErr) * w
            else:
                res = diff**2 * w
            return 0, res

        parinfo = []
        if dt0 is not None:
            parinfo.append({
                'value': dt0,
                'limited': [1, 1],
                'limits': [-250., 250.]
            })
        else:
            parinfo.append({'value': 0., 'fixed': 1})

        if dm0 is not None:
            parinfo.append({
                'value': dm0,
                'limited': [1, 1],
                'limits': [-5., 5.]
            })
        else:
            parinfo.append({'value': 0., 'fixed': 1})

        #        print(parinfo)
        result = mpfit.mpfit(least_sq,
                             parinfo=parinfo,
                             quiet=self.is_quiet,
                             maxiter=self.maxiter,
                             ftol=self.ftol,
                             gtol=self.gtol,
                             xtol=self.xtol)
        if result.status == 5:
            print('Maximum number of iterations exceeded in mangle_spectrum')
        elif result.status <= 0:
            print('error message = ', result.errmsg)
            print('parameters = ', result.params)
            raise ValueError(result.errmsg)

        tshift = result.params[0]

        #        dof = len(lc_o.Time) - len(result.params)  # deg of freedom
        dof = len(lc_o.Time)
        if dt0 is not None:
            dof -= 1
        if dm0 is not None:
            dof -= 1

        # scaled uncertainties
        pcerror = result.perror * np.sqrt(result.fnorm / dof)
        tsigma = pcerror[0]  # todo tsigma check

        dmshift = result.params[1]
        dmsigma = pcerror[1]

        lc_o.tshift = dt_init
        lc_o.mshift = dm_init

        if self.is_info:
            print(
                "The final params are: tshift=%f+-%f mshift=%f+-%f  chi2: %e" %
                (tshift, tsigma, dmshift, dmsigma, result.fnorm))
        res = {
            'dt': tshift,
            'dtsig': tsigma,
            'dm': dmshift,
            'dmsig': dmsigma,
            'chi2': result.fnorm,
            'dof': result.dof
        }
        return res