Exemple #1
0
def fitgaussian2d(data):
    """Returns (height, y, x, sig_y, sig_x, offset)
    the gaussian parameters of a 2D distribution found by a fit"""
    #    data = np.transpose(data)
    params = moments2d(data)
    errorfunction = lambda p: np.ravel(
        gaussian2d(*p)(*np.indices(data.shape)) - data)
    p, success = spleastsq(errorfunction, params, xtol=1e-16, ftol=1e-16)
    return p
Exemple #2
0
def fit_decay_logistic(t,data):
    params = moments_decay_logistic(t,data)
    if (np.any(np.isnan(x))):
        errorfunction = lambda p: decay_logistic(*p)(*np.indices(data.shape)) - data
    else:
        errorfunction = lambda p: decay_logistic(*p)(t) - data
    p = spleastsq(func=errorfunction, x0=params,
                  full_output=1)
    return p
Exemple #3
0
def fit_tof(x,data):
    """Returns the sigma0 and Temp for a time-of-flight measurements"""
    params = moments_tof(x,data)
    if (np.any(np.isnan(x))):
        errorfunction = lambda p: kinetic_expansion(*p)(*np.indices(data.shape)) - data
    else:
        errorfunction = lambda p: kinetic_expansion(*p)(x) - data
    p, success = spleastsq(func=errorfunction, x0=params)#, xtol=1e-16,ftol=1e-16)
    return p
Exemple #4
0
def fitgaussian2d(data):
    """Returns (height, y, x, sig_y, sig_x, offset)
    the gaussian parameters of a 2D distribution found by a fit"""
#    data = np.transpose(data)    
    params = moments2d(data)
    errorfunction = lambda p: np.ravel(gaussian2d(*p)(*np.indices(data.shape)) -
                                 data)
    p, success = spleastsq(errorfunction, params, xtol=1e-16,ftol=1e-16)
    return p
Exemple #5
0
def fit_tof(x, data):
    """Returns the sigma0 and Temp for a time-of-flight measurements"""
    params = moments_tof(x, data)
    if (x == None):
        errorfunction = lambda p: kinetic_expansion(*p)(*np.indices(data.shape)
                                                        ) - data
    else:
        errorfunction = lambda p: kinetic_expansion(*p)(x) - data
    p, success = spleastsq(func=errorfunction,
                           x0=params)  #, xtol=1e-16,ftol=1e-16)
    return p
Exemple #6
0
def fit_poly2_zero_cross(x, data):
    """Returns (height, centre, sigma, offset)
    the gaussian parameters of a 1D distribution found by a fit"""
    params = np.array([-1, 100])
    if (x == None):
        errorfunction = lambda p: poly2_zero_cross(*p)(*np.indices(data.shape))\
                                - data
    else:
        errorfunction = lambda p: poly2_zero_cross(*p)(x)\
                                - data
    p, success = spleastsq(errorfunction, params, full_output=0)
    return p
Exemple #7
0
def fitlorentz1d(x, data):
    """Returns (height, centre, fwhm, offset)
    the lorentzian parameters of a 1D distribution found by a fit"""
    params = moments1d(x, data)
    if (x == None):
        errorfunction = lambda p: lorentz1d(*p)(*np.indices(data.shape))\
                                - data
    else:
        errorfunction = lambda p: lorentz1d(*p)(x)\
                                - data
    p, success = spleastsq(errorfunction, params, full_output=0)
    return p
Exemple #8
0
def fit_poly2_zero_cross(x,data):
    """Returns (height, centre, sigma, offset)
    the gaussian parameters of a 1D distribution found by a fit"""
    params = np.array([-1,100])
    if (np.isnan(x)):
        errorfunction = lambda p: poly2_zero_cross(*p)(*np.indices(data.shape))\
                                - data
    else:
        errorfunction = lambda p: poly2_zero_cross(*p)(x)\
                                - data
    p, success = spleastsq(errorfunction, params, full_output=0)
    return p
Exemple #9
0
def fitlorentz1d(x,data):
    """Returns (height, centre, fwhm, offset)
    the lorentzian parameters of a 1D distribution found by a fit"""
    params = moments1d(x,data)
    if (np.any(np.isnan(x))):
        errorfunction = lambda p: lorentz1d(*p)(*np.indices(data.shape))\
                                - data
    else:
        errorfunction = lambda p: lorentz1d(*p)(x)\
                                - data        
    p, success = spleastsq(errorfunction, params, full_output=0)
    return p
Exemple #10
0
def fit_extinction_lorentz(x,data):
    """Returns the (b0, nu0, offset) exponential decay with a lorentzian
    argument (b(nu)) parameters of a distribution found by a fit"""
    params = moments_extinction_lorentz(x,data)
#    params = np.array([8,0])
    if (np.any(np.isnan(x))):
        errorfunction = lambda p: extinction_lorentz(*p)(*np.indices(data.shape))\
                                - data
    else:
        errorfunction = lambda p: extinction_lorentz(*p)(x)\
                                - data        
    p, success = spleastsq(func=errorfunction, x0=params)#, xtol=1e-16,ftol=1e-16)
    return p
Exemple #11
0
def fit_extinction_lorentz(x, data):
    """Returns the (b0, nu0, offset) exponential decay with a lorentzian
    argument (b(nu)) parameters of a distribution found by a fit"""
    params = moments_extinction_lorentz(x, data)
    #    params = np.array([8,0])
    if (x == None):
        errorfunction = lambda p: extinction_lorentz(*p)(*np.indices(data.shape))\
                                - data
    else:
        errorfunction = lambda p: extinction_lorentz(*p)(x)\
                                - data
    p, success = spleastsq(func=errorfunction,
                           x0=params)  #, xtol=1e-16,ftol=1e-16)
    return p
Exemple #12
0
def fit_decay_logistic(t, data):
    params = moments_decay_logistic(t, data)
    errorfunction = lambda p: decay_logistic(*p)(t) - data
    p = spleastsq(func=errorfunction, x0=params, full_output=1)
    return p
Exemple #13
0
def traptransit_fit_magseries(times,
                              mags,
                              errs,
                              transitparams,
                              sigclip=10.0,
                              plotfit=False,
                              magsarefluxes=False,
                              verbose=True):
    '''This fits a trapezoid transit model to a magnitude time series.

    transitparams = [transitperiod (time),
                     transitepoch (time),
                     transitdepth (flux or mags),
                     transitduration (phase),
                     ingressduration (phase)]

    for magnitudes -> transitdepth should be < 0
    for fluxes     -> transitdepth should be > 0

    if transitepoch is None, this function will do an initial spline fit to find
    an approximate minimum of the phased light curve using the given period.

    the transitdepth provided is checked against the value of magsarefluxes. if
    magsarefluxes = True, the transitdepth is forced to be > 0; if magsarefluxes
    = False, the transitdepth is forced to be < 0.

    '''

    stimes, smags, serrs = sigclip_magseries(times,
                                             mags,
                                             errs,
                                             sigclip=sigclip,
                                             magsarefluxes=magsarefluxes)

    # get rid of zero errs
    nzind = npnonzero(serrs)
    stimes, smags, serrs = stimes[nzind], smags[nzind], serrs[nzind]

    # check the transitparams
    transitperiod, transitepoch, transitdepth = transitparams[0:3]

    # check if we have a transitepoch to use
    if transitepoch is None:

        if verbose:
            LOGWARNING('no transitepoch given in transitparams, '
                       'trying to figure it out automatically...')
        # do a spline fit to figure out the approximate min of the LC
        try:
            spfit = spline_fit_magseries(times,
                                         mags,
                                         errs,
                                         transitperiod,
                                         sigclip=sigclip,
                                         magsarefluxes=magsarefluxes,
                                         verbose=verbose)
            transitepoch = spfit['fitinfo']['fitepoch']

        # if the spline-fit fails, try a savgol fit instead
        except:
            sgfit = savgol_fit_magseries(times,
                                         mags,
                                         errs,
                                         transitperiod,
                                         sigclip=sigclip,
                                         magsarefluxes=magsarefluxes,
                                         verbose=verbose)
            transitepoch = sgfit['fitinfo']['fitepoch']

        # if everything failed, then bail out and ask for the transitepoch
        finally:

            if transitepoch is None:
                LOGERROR(
                    "couldn't automatically figure out the transit epoch, "
                    "can't continue. please provide it in transitparams.")

                # assemble the returndict
                returndict = {
                    'fittype': 'traptransit',
                    'fitinfo': {
                        'initialparams': transitparams,
                        'finalparams': None,
                        'leastsqfit': None,
                        'fitmags': None,
                        'fitepoch': None,
                    },
                    'fitchisq': npnan,
                    'fitredchisq': npnan,
                    'fitplotfile': None,
                    'magseries': {
                        'phase': None,
                        'times': None,
                        'mags': None,
                        'errs': None,
                        'magsarefluxes': magsarefluxes,
                    },
                }

                return returndict

            else:

                # check the case when there are more than one transitepochs returned
                if transitepoch.size > 0:
                    if verbose:
                        LOGWARNING(
                            "could not auto-find a single minimum in LC for "
                            "transitepoch, using the first one returned")
                    transitparams[1] = transitepoch[0]

                else:

                    if verbose:
                        LOGWARNING(
                            'using automatically determined transitepoch = %.5f'
                            % transitepoch)
                    transitparams[1] = transitepoch

    # next, check the transitdepth and fix it to the form required
    if magsarefluxes:
        if transitdepth < 0.0:
            transitparams[2] = -transitdepth[2]

    else:
        if transitdepth > 0.0:
            transitparams[2] = -transitdepth[2]

    # finally, do the fit
    try:
        leastsqfit = spleastsq(transits.trapezoid_transit_residual,
                               transitparams,
                               args=(stimes, smags, serrs),
                               full_output=True)
    except Exception as e:
        leastsqfit = None

    # if the fit succeeded, then we can return the final parameters
    if leastsqfit and leastsqfit[-1] in (1, 2, 3, 4):

        finalparams = leastsqfit[0]
        covxmatrix = leastsqfit[1]

        # calculate the chisq and reduced chisq
        fitmags, phase, ptimes, pmags, perrs = transits.trapezoid_transit_func(
            finalparams, stimes, smags, serrs)
        fitchisq = npsum(
            ((fitmags - pmags) * (fitmags - pmags)) / (perrs * perrs))
        fitredchisq = fitchisq / (len(pmags) - len(finalparams) - 1)

        # get the residual variance and calculate the formal 1-sigma errs on the
        # final parameters
        residuals = leastsqfit[2]['fvec']
        residualvariance = (npsum(residuals * residuals) /
                            (pmags.size - finalparams.size))
        if covxmatrix is not None:
            covmatrix = residualvariance * covxmatrix
            stderrs = npsqrt(npdiag(covmatrix))
        else:
            LOGERROR('covxmatrix not available, fit probably failed!')
            stderrs = None

        if verbose:
            LOGINFO('final fit done. chisq = %.5f, reduced chisq = %.5f' %
                    (fitchisq, fitredchisq))

        # get the fit epoch
        fperiod, fepoch = finalparams[:2]

        # assemble the returndict
        returndict = {
            'fittype': 'traptransit',
            'fitinfo': {
                'initialparams': transitparams,
                'finalparams': finalparams,
                'finalparamerrs': stderrs,
                'leastsqfit': leastsqfit,
                'fitmags': fitmags,
                'fitepoch': fepoch,
            },
            'fitchisq': fitchisq,
            'fitredchisq': fitredchisq,
            'fitplotfile': None,
            'magseries': {
                'phase': phase,
                'times': ptimes,
                'mags': pmags,
                'errs': perrs,
                'magsarefluxes': magsarefluxes,
            },
        }

        # make the fit plot if required
        if plotfit and isinstance(plotfit, str):

            _make_fit_plot(phase,
                           pmags,
                           perrs,
                           fitmags,
                           fperiod,
                           ptimes.min(),
                           fepoch,
                           plotfit,
                           magsarefluxes=magsarefluxes)

            returndict['fitplotfile'] = plotfit

        return returndict

    # if the leastsq fit failed, return nothing
    else:

        LOGERROR('trapezoid-fit: least-squared fit to the light curve failed!')

        # assemble the returndict
        returndict = {
            'fittype': 'traptransit',
            'fitinfo': {
                'initialparams': transitparams,
                'finalparams': None,
                'finalparamerrs': None,
                'leastsqfit': leastsqfit,
                'fitmags': None,
                'fitepoch': None,
            },
            'fitchisq': npnan,
            'fitredchisq': npnan,
            'fitplotfile': None,
            'magseries': {
                'phase': None,
                'times': None,
                'mags': None,
                'errs': None,
                'magsarefluxes': magsarefluxes,
            },
        }

        return returndict
Exemple #14
0
def fourier_fit_magseries(times,
                          mags,
                          errs,
                          period,
                          fourierorder=None,
                          fourierparams=None,
                          sigclip=3.0,
                          magsarefluxes=False,
                          plotfit=False,
                          ignoreinitfail=True,
                          verbose=True):
    '''This fits a Fourier series to a magnitude time series.

    This uses an 8th-order Fourier series by default. This is good for light
    curves with many thousands of observations (HAT light curves have ~10k
    observations). Lower the order accordingly if you have fewer observations in
    your light curves to avoid over-fitting.

    Set the Fourier order by using either the fourierorder kwarg OR the
    fourierparams kwarg. If fourierorder is None, then fourierparams is a
    list of the form for fourier order = N:

    [fourier_amp1, fourier_amp2, fourier_amp3,...,fourier_ampN,
     fourier_phase1, fourier_phase2, fourier_phase3,...,fourier_phaseN]

    If both/neither are specified, the default Fourier order of 3 will be used.

    Returns the Fourier fit parameters, the minimum chisq and reduced
    chisq. Makes a plot for the fit to the mag series if plotfit is a string
    containing a filename to write the plot to.

    This folds the time series using the given period and at the first
    observation. Can optionally sigma-clip observations.

    if ignoreinitfail is True, ignores the initial failure to find a set of
    optimized Fourier parameters and proceeds to do a least-squares fit anyway.

    magsarefluxes is a boolean value for setting the ylabel and ylimits of
    plots for either magnitudes (False) or flux units (i.e. normalized to 1, in
    which case magsarefluxes should be set to True).

    '''

    stimes, smags, serrs = sigclip_magseries(times,
                                             mags,
                                             errs,
                                             sigclip=sigclip,
                                             magsarefluxes=magsarefluxes)

    # get rid of zero errs
    nzind = npnonzero(serrs)
    stimes, smags, serrs = stimes[nzind], smags[nzind], serrs[nzind]

    phase, pmags, perrs, ptimes, mintime = (_get_phased_quantities(
        stimes, smags, serrs, period))

    # get the fourier order either from the scalar order kwarg...
    if fourierorder and fourierorder > 0 and not fourierparams:

        fourieramps = [0.6] + [0.2] * (fourierorder - 1)
        fourierphas = [0.1] + [0.1] * (fourierorder - 1)
        fourierparams = fourieramps + fourierphas

    # or from the fully specified coeffs vector
    elif not fourierorder and fourierparams:

        fourierorder = int(len(fourierparams) / 2)

    else:
        LOGWARNING('specified both/neither Fourier order AND Fourier coeffs, '
                   'using default Fourier order of 3')
        fourierorder = 3
        fourieramps = [0.6] + [0.2] * (fourierorder - 1)
        fourierphas = [0.1] + [0.1] * (fourierorder - 1)
        fourierparams = fourieramps + fourierphas

    if verbose:
        LOGINFO('fitting Fourier series of order %s to '
                'mag series with %s observations, '
                'using period %.6f, folded at %.6f' %
                (fourierorder, len(phase), period, mintime))

    # initial minimize call to find global minimum in chi-sq
    initialfit = spminimize(_fourier_chisq,
                            fourierparams,
                            method='BFGS',
                            args=(phase, pmags, perrs))

    # make sure this initial fit succeeds before proceeding
    if initialfit.success or ignoreinitfail:

        if verbose:
            LOGINFO('initial fit done, refining...')

        leastsqparams = initialfit.x

        try:
            leastsqfit = spleastsq(_fourier_residual,
                                   leastsqparams,
                                   args=(phase, pmags))
        except Exception as e:
            leastsqfit = None

        # if the fit succeeded, then we can return the final parameters
        if leastsqfit and leastsqfit[-1] in (1, 2, 3, 4):

            finalparams = leastsqfit[0]

            # calculate the chisq and reduced chisq
            fitmags = _fourier_func(finalparams, phase, pmags)

            fitchisq = npsum(
                ((fitmags - pmags) * (fitmags - pmags)) / (perrs * perrs))

            fitredchisq = fitchisq / (len(pmags) - len(finalparams) - 1)

            if verbose:
                LOGINFO('final fit done. chisq = %.5f, reduced chisq = %.5f' %
                        (fitchisq, fitredchisq))

            # figure out the time of light curve minimum (i.e. the fit epoch)
            # this is when the fit mag is maximum (i.e. the faintest)
            # or if magsarefluxes = True, then this is when fit flux is minimum
            if not magsarefluxes:
                fitmagminind = npwhere(fitmags == npmax(fitmags))
            else:
                fitmagminind = npwhere(fitmags == npmin(fitmags))
            magseriesepoch = ptimes[fitmagminind]

            # assemble the returndict
            returndict = {
                'fittype': 'fourier',
                'fitinfo': {
                    'fourierorder': fourierorder,
                    'finalparams': finalparams,
                    'initialfit': initialfit,
                    'leastsqfit': leastsqfit,
                    'fitmags': fitmags,
                    'fitepoch': magseriesepoch
                },
                'fitchisq': fitchisq,
                'fitredchisq': fitredchisq,
                'fitplotfile': None,
                'magseries': {
                    'times': ptimes,
                    'phase': phase,
                    'mags': pmags,
                    'errs': perrs,
                    'magsarefluxes': magsarefluxes
                },
            }

            # make the fit plot if required
            if plotfit and isinstance(plotfit, str):

                _make_fit_plot(phase,
                               pmags,
                               perrs,
                               fitmags,
                               period,
                               mintime,
                               magseriesepoch,
                               plotfit,
                               magsarefluxes=magsarefluxes)

                returndict['fitplotfile'] = plotfit

            return returndict

        # if the leastsq fit did not succeed, return Nothing
        else:
            LOGERROR(
                'fourier-fit: least-squared fit to the light curve failed')
            return {
                'fittype': 'fourier',
                'fitinfo': {
                    'fourierorder': fourierorder,
                    'finalparams': None,
                    'initialfit': initialfit,
                    'leastsqfit': None,
                    'fitmags': None,
                    'fitepoch': None
                },
                'fitchisq': npnan,
                'fitredchisq': npnan,
                'fitplotfile': None,
                'magseries': {
                    'times': ptimes,
                    'phase': phase,
                    'mags': pmags,
                    'errs': perrs,
                    'magsarefluxes': magsarefluxes
                }
            }

    # if the fit didn't succeed, we can't proceed
    else:

        LOGERROR('initial Fourier fit did not succeed, '
                 'reason: %s, returning scipy OptimizeResult' %
                 initialfit.message)

        return {
            'fittype': 'fourier',
            'fitinfo': {
                'fourierorder': fourierorder,
                'finalparams': None,
                'initialfit': initialfit,
                'leastsqfit': None,
                'fitmags': None,
                'fitepoch': None
            },
            'fitchisq': npnan,
            'fitredchisq': npnan,
            'fitplotfile': None,
            'magseries': {
                'times': ptimes,
                'phase': phase,
                'mags': pmags,
                'errs': perrs,
                'magsarefluxes': magsarefluxes
            }
        }
Exemple #15
0
def gaussianeb_fit_magseries(times,
                             mags,
                             errs,
                             ebparams,
                             sigclip=10.0,
                             plotfit=False,
                             magsarefluxes=False,
                             verbose=True):
    '''This fits a double inverted gaussian EB model to a magnitude time series.

    ebparams = [period (time),
                epoch (time),
                pdepth (mags),
                pduration (phase),
                psdepthratio,
                secondaryphase]

    period is the period in days

    epoch is the time of minimum in JD

    pdepth is the depth of the primary eclipse
    - for magnitudes -> ebdepth should be < 0
    - for fluxes     -> ebdepth should be > 0

    pduration is the length of the primary eclipse in phase

    psdepthratio is the ratio of the secondary eclipse depth to that of the
    primary eclipse.

    secondaryphase is the phase at which the minimum of the secondary eclipse is
    located. This effectively parameterizes eccentricity.

    if epoch is None, this function will do an initial spline fit to find an
    approximate minimum of the phased light curve using the given period.

    the pdepth provided is checked against the value of magsarefluxes. if
    magsarefluxes = True, the ebdepth is forced to be > 0; if magsarefluxes
    = False, the ebdepth is forced to be < 0.

    '''

    stimes, smags, serrs = sigclip_magseries(times,
                                             mags,
                                             errs,
                                             sigclip=sigclip,
                                             magsarefluxes=magsarefluxes)

    # get rid of zero errs
    nzind = npnonzero(serrs)
    stimes, smags, serrs = stimes[nzind], smags[nzind], serrs[nzind]

    # check the ebparams
    ebperiod, ebepoch, ebdepth = ebparams[0:3]

    # check if we have a ebepoch to use
    if ebepoch is None:

        if verbose:
            LOGWARNING('no ebepoch given in ebparams, '
                       'trying to figure it out automatically...')
        # do a spline fit to figure out the approximate min of the LC
        try:
            spfit = spline_fit_magseries(times,
                                         mags,
                                         errs,
                                         ebperiod,
                                         sigclip=sigclip,
                                         magsarefluxes=magsarefluxes,
                                         verbose=verbose)
            ebepoch = spfit['fitinfo']['fitepoch']

        # if the spline-fit fails, try a savgol fit instead
        except:
            sgfit = savgol_fit_magseries(times,
                                         mags,
                                         errs,
                                         ebperiod,
                                         sigclip=sigclip,
                                         magsarefluxes=magsarefluxes,
                                         verbose=verbose)
            ebepoch = sgfit['fitinfo']['fitepoch']

        # if everything failed, then bail out and ask for the ebepoch
        finally:

            if ebepoch is None:
                LOGERROR("couldn't automatically figure out the eb epoch, "
                         "can't continue. please provide it in ebparams.")

                # assemble the returndict
                returndict = {
                    'fittype': 'gaussianeb',
                    'fitinfo': {
                        'initialparams': ebparams,
                        'finalparams': None,
                        'leastsqfit': None,
                        'fitmags': None,
                        'fitepoch': None,
                    },
                    'fitchisq': npnan,
                    'fitredchisq': npnan,
                    'fitplotfile': None,
                    'magseries': {
                        'phase': None,
                        'times': None,
                        'mags': None,
                        'errs': None,
                        'magsarefluxes': magsarefluxes,
                    },
                }

                return returndict

            else:

                if ebepoch.size > 1:
                    if verbose:
                        LOGWARNING('could not auto-find a single minimum '
                                   'for ebepoch, using the first one returned')
                    ebparams[1] = ebepoch[0]

                else:

                    if verbose:
                        LOGWARNING(
                            'using automatically determined ebepoch = %.5f' %
                            ebepoch)
                    ebparams[1] = ebepoch

    # next, check the ebdepth and fix it to the form required
    if magsarefluxes:
        if ebdepth < 0.0:
            ebparams[2] = -ebdepth[2]

    else:
        if ebdepth > 0.0:
            ebparams[2] = -ebdepth[2]

    # finally, do the fit
    try:
        leastsqfit = spleastsq(eclipses.invgauss_eclipses_residual,
                               ebparams,
                               args=(stimes, smags, serrs),
                               full_output=True)
    except Exception as e:
        leastsqfit = None

    # if the fit succeeded, then we can return the final parameters
    if leastsqfit and leastsqfit[-1] in (1, 2, 3, 4):

        finalparams = leastsqfit[0]
        covxmatrix = leastsqfit[1]

        # calculate the chisq and reduced chisq
        fitmags, phase, ptimes, pmags, perrs = eclipses.invgauss_eclipses_func(
            finalparams, stimes, smags, serrs)
        fitchisq = npsum(
            ((fitmags - pmags) * (fitmags - pmags)) / (perrs * perrs))
        fitredchisq = fitchisq / (len(pmags) - len(finalparams) - 1)

        # get the residual variance and calculate the formal 1-sigma errs on the
        # final parameters
        residuals = leastsqfit[2]['fvec']
        residualvariance = (npsum(residuals * residuals) /
                            (pmags.size - finalparams.size))
        if covxmatrix is not None:
            covmatrix = residualvariance * covxmatrix
            stderrs = npsqrt(npdiag(covmatrix))
        else:
            LOGERROR('covxmatrix not available, fit probably failed!')
            stderrs = None

        if verbose:
            LOGINFO('final fit done. chisq = %.5f, reduced chisq = %.5f' %
                    (fitchisq, fitredchisq))

        # get the fit epoch
        fperiod, fepoch = finalparams[:2]

        # assemble the returndict
        returndict = {
            'fittype': 'gaussianeb',
            'fitinfo': {
                'initialparams': ebparams,
                'finalparams': finalparams,
                'finalparamerrs': stderrs,
                'leastsqfit': leastsqfit,
                'fitmags': fitmags,
                'fitepoch': fepoch,
            },
            'fitchisq': fitchisq,
            'fitredchisq': fitredchisq,
            'fitplotfile': None,
            'magseries': {
                'phase': phase,
                'times': ptimes,
                'mags': pmags,
                'errs': perrs,
                'magsarefluxes': magsarefluxes,
            },
        }

        # make the fit plot if required
        if plotfit and isinstance(plotfit, str):

            _make_fit_plot(phase,
                           pmags,
                           perrs,
                           fitmags,
                           fperiod,
                           ptimes.min(),
                           fepoch,
                           plotfit,
                           magsarefluxes=magsarefluxes)

            returndict['fitplotfile'] = plotfit

        return returndict

    # if the leastsq fit failed, return nothing
    else:

        LOGERROR('eb-fit: least-squared fit to the light curve failed!')

        # assemble the returndict
        returndict = {
            'fittype': 'gaussianeb',
            'fitinfo': {
                'initialparams': ebparams,
                'finalparams': None,
                'finalparamerrs': None,
                'leastsqfit': leastsqfit,
                'fitmags': None,
                'fitepoch': None,
            },
            'fitchisq': npnan,
            'fitredchisq': npnan,
            'fitplotfile': None,
            'magseries': {
                'phase': None,
                'times': None,
                'mags': None,
                'errs': None,
                'magsarefluxes': magsarefluxes,
            },
        }

        return returndict