Пример #1
0
def stetson_kindex(fmags, ferrs):
    '''
    This calculates the Stetson K index (robust measure of the kurtosis).

    Requires finite mags and errs.

    '''

    # use a fill in value for the errors if they're none
    if ferrs is None:
        ferrs = npfull_like(mags, 0.005)

    ndet = len(fmags)

    if ndet > 9:

        # get the median and ndet
        medmag = npmedian(fmags)

        # get the stetson index elements
        delta_prefactor = (ndet / (ndet - 1))
        sigma_i = delta_prefactor * (fmags - medmag) / ferrs

        stetsonk = (npsum(npabs(sigma_i)) /
                    (npsqrt(npsum(sigma_i * sigma_i))) * (ndet**(-0.5)))

        return stetsonk

    else:

        LOGERROR('not enough detections in this magseries '
                 'to calculate stetson K index')
        return npnan
Пример #2
0
def stetson_kindex(fmags, ferrs):
    '''This calculates the Stetson K index (a robust measure of the kurtosis).

    Parameters
    ----------

    fmags,ferrs : np.array
        The input mag/flux time-series to process. Must have no non-finite
        elems.

    Returns
    -------

    float
        The Stetson K variability index.

    '''

    # use a fill in value for the errors if they're none
    if ferrs is None:
        ferrs = npfull_like(fmags, 0.005)

    ndet = len(fmags)

    if ndet > 9:

        # get the median and ndet
        medmag = npmedian(fmags)

        # get the stetson index elements
        delta_prefactor = (ndet/(ndet - 1))
        sigma_i = delta_prefactor*(fmags - medmag)/ferrs

        stetsonk = (
            npsum(npabs(sigma_i))/(npsqrt(npsum(sigma_i*sigma_i))) *
            (ndet**(-0.5))
        )

        return stetsonk

    else:

        LOGERROR('not enough detections in this magseries '
                 'to calculate stetson K index')
        return npnan
Пример #3
0
def invgauss_eclipses_func(ebparams, times, mags, errs):
    '''This returns a double eclipse shaped function.

    Suitable for first order modeling of eclipsing binaries.

    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 -> transitdepth should be < 0
    - for fluxes     -> transitdepth should be > 0

    pduration is the length of the primary eclipse in phase

    psdepthratio is the ratio in the eclipse depths:
    depth_secondary/depth_primary. This is generally the same as the ratio of
    the Teffs of the two stars.

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

    All of these will then have fitted values after the fit is done.

    '''

    (period, epoch, pdepth, pduration, depthratio, secondaryphase) = ebparams

    # generate the phases
    iphase = (times - epoch) / period
    iphase = iphase - npfloor(iphase)

    phasesortind = npargsort(iphase)
    phase = iphase[phasesortind]
    ptimes = times[phasesortind]
    pmags = mags[phasesortind]
    perrs = errs[phasesortind]

    zerolevel = npmedian(pmags)
    modelmags = npfull_like(phase, zerolevel)

    primaryecl_amp = -pdepth
    secondaryecl_amp = -pdepth * depthratio

    primaryecl_std = pduration / 5.0  # we use 5-sigma as full-width -> duration
    secondaryecl_std = pduration / 5.0  # secondary eclipse has the same duration

    halfduration = pduration / 2.0

    # phase indices
    primary_eclipse_ingress = ((phase >=
                                (1.0 - halfduration)) & (phase <= 1.0))
    primary_eclipse_egress = ((phase >= 0.0) & (phase <= halfduration))

    secondary_eclipse_phase = ((phase >= (secondaryphase - halfduration)) &
                               (phase <= (secondaryphase + halfduration)))

    # put in the eclipses
    modelmags[primary_eclipse_ingress] = (zerolevel + _gaussian(
        phase[primary_eclipse_ingress], primaryecl_amp, 1.0, primaryecl_std))
    modelmags[primary_eclipse_egress] = (zerolevel + _gaussian(
        phase[primary_eclipse_egress], primaryecl_amp, 0.0, primaryecl_std))
    modelmags[secondary_eclipse_phase] = (
        zerolevel + _gaussian(phase[secondary_eclipse_phase], secondaryecl_amp,
                              secondaryphase, secondaryecl_std))

    return modelmags, phase, ptimes, pmags, perrs
Пример #4
0
def bls_snr(blsdict,
            times,
            mags,
            errs,
            magsarefluxes=False,
            sigclip=10.0,
            perioddeltapercent=10,
            npeaks=None,
            assumeserialbls=False,
            verbose=True):
    '''Calculates the signal to noise ratio for each best peak in the BLS
    periodogram.

    This calculates two values of SNR:

    SNR = transit model depth / RMS of light curve with transit model subtracted
    altSNR = transit model depth / RMS of light curve inside transit

    blsdict is the output of either bls_parallel_pfind or bls_serial_pfind.

    times, mags, errs are ndarrays containing the magnitude series.

    perioddeltapercent controls the period interval used by a bls_serial_pfind
    run around each peak period to figure out the transit depth, duration, and
    ingress/egress bins for eventual calculation of the SNR of the peak.

    npeaks controls how many of the periods in blsdict['nbestperiods'] to find
    the SNR for. If it's None, then this will calculate the SNR for all of
    them. If it's an integer between 1 and len(blsdict['nbestperiods']), will
    calculate for only the specified number of peak periods, starting from the
    best period.

    If assumeserialbls is True, will not rerun bls_serial_pfind to figure out
    the transit depth, duration, and ingress/egress bins for eventual
    calculation of the SNR of the peak. This is normally False because we assume
    that the user will be using bls_parallel_pfind, which works on chunks of
    frequency space so returns multiple values of transit depth, duration,
    ingress/egress bin specific to those chunks. These may not be valid for the
    global best peaks in the periodogram, so we need to rerun bls_serial_pfind
    around each peak in blsdict['nbestperiods'] to get correct values for these.

    FIXME: for now, we're only doing simple RMS. Need to calculate red and
    white-noise RMS as outlined below:

      - calculate the white noise rms and the red noise rms of the residual.

        - the white noise rms is just the rms of the residual
        - the red noise rms = sqrt(binnedrms^2 - expectedbinnedrms^2)

      - calculate the SNR using:

        sqrt(delta^2 / ((sigma_w ^2 / nt) + (sigma_r ^2 / Nt))))

        where:

        delta = transit depth
        sigma_w = white noise rms
        sigma_r = red noise rms
        nt = number of in-transit points
        Nt = number of distinct transits sampled

    '''

    # figure out how many periods to work on
    if (npeaks and (0 < npeaks < len(blsdict['nbestperiods']))):
        nperiods = npeaks
    else:
        if verbose:
            LOGWARNING('npeaks not specified or invalid, '
                       'getting SNR for all %s BLS peaks' %
                       len(blsdict['nbestperiods']))
        nperiods = len(blsdict['nbestperiods'])

    nbestperiods = blsdict['nbestperiods'][:nperiods]

    # get rid of nans first and sigclip
    stimes, smags, serrs = sigclip_magseries(times,
                                             mags,
                                             errs,
                                             magsarefluxes=magsarefluxes,
                                             sigclip=sigclip)

    # make sure there are enough points to calculate a spectrum
    if len(stimes) > 9 and len(smags) > 9 and len(serrs) > 9:

        nbestsnrs = []
        nbestasnrs = []
        transitdepth, transitduration = [], []

        # get these later
        whitenoise, rednoise = [], []
        nphasebins, transingressbin, transegressbin = [], [], []

        # keep these around for diagnostics
        allsubtractedmags = []
        allphasedmags = []
        allphases = []
        allblsmodels = []

        for ind, period in enumerate(nbestperiods):

            # get the period interval
            startp = period - perioddeltapercent * period / 100.0
            endp = period + perioddeltapercent * period / 100.0

            # see if we need to rerun bls_serial_pfind
            if not assumeserialbls:

                # run bls_serial_pfind with the kwargs copied over from the
                # initial run. replace only the startp, endp, and verbose kwarg
                # values
                prevkwargs = blsdict['kwargs'].copy()
                prevkwargs['verbose'] = verbose
                prevkwargs['startp'] = startp
                prevkwargs['endp'] = endp

                blsres = bls_serial_pfind(times, mags, errs, **prevkwargs)

            else:
                blsres = blsdict

            thistransdepth = blsres['blsresult']['transdepth']
            thistransduration = blsres['blsresult']['transduration']
            thisbestperiod = blsres['bestperiod']
            thistransingressbin = blsres['blsresult']['transingressbin']
            thistransegressbin = blsres['blsresult']['transegressbin']
            thisnphasebins = blsdict['kwargs']['nphasebins']

            # get the minimum light epoch using a spline fit
            try:

                spfit = spline_fit_magseries(times,
                                             mags,
                                             errs,
                                             thisbestperiod,
                                             magsarefluxes=magsarefluxes,
                                             verbose=verbose)
                thisminepoch = spfit['fitinfo']['fitepoch']

            except ValueError:

                LOGEXCEPTION('could not fit a spline to find a minimum of '
                             'the phased LC, trying SavGol fit instead...')
                # fit a Savitsky-Golay instead and get its minimum
                savfit = savgol_fit_magseries(times,
                                              mags,
                                              errs,
                                              thisbestperiod,
                                              magsarefluxes=magsarefluxes,
                                              verbose=verbose)
                thisminepoch = savfit['fitinfo']['fitepoch']

            if isinstance(thisminepoch, np.ndarray):
                if verbose:
                    LOGWARNING('minimum epoch is actually an array:\n'
                               '%s\n'
                               'instead of a float, '
                               'are there duplicate time values '
                               'in the original input? '
                               'will use the first value in this array.' %
                               repr(thisminepoch))
                thisminepoch = thisminepoch[0]

            # phase using this epoch
            phased_magseries = phase_magseries_with_errs(stimes,
                                                         smags,
                                                         serrs,
                                                         thisbestperiod,
                                                         thisminepoch,
                                                         wrap=False,
                                                         sort=True)

            tphase = phased_magseries['phase']
            tmags = phased_magseries['mags']
            terrs = phased_magseries['errs']

            # use the transit depth and duration to subtract the BLS transit
            # model from the phased mag series. we're centered about 0.0 as the
            # phase of the transit minimum so we need to look at stuff from
            # [0.0, transitphase] and [1.0-transitphase, 1.0]
            transitphase = thistransduration / 2.0

            transitindices = ((tphase < transitphase) | (tphase >
                                                         (1.0 - transitphase)))

            # this is the BLS model
            # constant = median(tmags) outside transit
            # constant = thistransitdepth inside transit
            blsmodel = npfull_like(tmags, npmedian(tmags))

            if magsarefluxes:
                blsmodel[transitindices] = (blsmodel[transitindices] +
                                            thistransdepth)
            else:
                blsmodel[transitindices] = (blsmodel[transitindices] -
                                            thistransdepth)

            # this is the residual of mags - model
            subtractedmags = tmags - blsmodel

            # calculate the rms of this residual
            subtractedrms = npstd(subtractedmags)

            # the SNR is the transit depth divided by the rms of the residual
            thissnr = npabs(thistransdepth / subtractedrms)

            # alt SNR = expected transit depth / rms of timeseries in transit
            altsnr = npabs(thistransdepth / npstd(tmags[transitindices]))

            # tell user about stuff if verbose = True
            if verbose:

                LOGINFO('peak %s: new best period: %.6f, '
                        'fit center of transit: %.5f' %
                        (ind + 1, thisbestperiod, thisminepoch))

                LOGINFO('transit ingress phase = %.3f to %.3f' %
                        (1.0 - transitphase, 1.0))
                LOGINFO('transit egress phase = %.3f to %.3f' %
                        (0.0, transitphase))
                LOGINFO('npoints in transit: %s' % tmags[transitindices].size)

                LOGINFO('transit depth (delta): %.5f, '
                        'frac transit length (q): %.3f, '
                        ' SNR: %.3f, altSNR: %.3f' %
                        (thistransdepth, thistransduration, thissnr, altsnr))

            # update the lists with results from this peak
            nbestsnrs.append(thissnr)
            nbestasnrs.append(altsnr)
            transitdepth.append(thistransdepth)
            transitduration.append(thistransduration)
            transingressbin.append(thistransingressbin)
            transegressbin.append(thistransegressbin)
            nphasebins.append(thisnphasebins)

            # update the diagnostics
            allsubtractedmags.append(subtractedmags)
            allphasedmags.append(tmags)
            allphases.append(tphase)
            allblsmodels.append(blsmodel)

            # update these when we figure out how to do it
            # nphasebins.append(thisnphasebins)
            # transingressbin.append(thisingressbin)
            # transegressbin.append(thisegressbin)

        # done with working on each peak

    # if there aren't enough points in the mag series, bail out
    else:

        LOGERROR('no good detections for these times and mags, skipping...')
        nbestsnrs, whitenoise, rednoise = None, None, None
        transitdepth, transitduration = None, None
        nphasebins, transingressbin, transegressbin = None, None, None
        allsubtractedmags, allphases, allphasedmags = None, None, None

    return {
        'npeaks': npeaks,
        'period': nbestperiods,
        'snr': nbestsnrs,
        'altsnr': nbestasnrs,
        'whitenoise': whitenoise,
        'rednoise': rednoise,
        'transitdepth': transitdepth,
        'transitduration': transitduration,
        'nphasebins': nphasebins,
        'transingressbin': transingressbin,
        'transegressbin': transegressbin,
        'allblsmodels': allblsmodels,
        'allsubtractedmags': allsubtractedmags,
        'allphasedmags': allphasedmags,
        'allphases': allphases
    }
Пример #5
0
def spline_fit_magseries(times,
                         mags,
                         errs,
                         period,
                         knotfraction=0.01,
                         maxknots=30,
                         sigclip=30.0,
                         plotfit=False,
                         ignoreinitfail=False,
                         magsarefluxes=False,
                         verbose=True):
    '''This fits a univariate cubic spline to the phased light curve.

    This fit may be better than the Fourier fit for sharply variable objects,
    like EBs, so can be used to distinguish them from other types of variables.

    The knot fraction is the number of internal knots to use for the spline. A
    value of 0.01 (or 1%) of the total number of non-nan observations appears to
    work quite well, without over-fitting. maxknots controls the maximum number
    of knots that will be allowed.

    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).

    Returns the chisq of the fit, as well as the reduced chisq. FIXME: check
    this equation below to see if it's right.

    reduced_chisq = fit_chisq/(len(pmags) - len(knots) - 1)

    '''

    # this is required to fit the spline correctly
    if errs is None:
        errs = npfull_like(mags, 0.005)

    # sigclip the magnitude time series
    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 the mag series
    phase, pmags, perrs, ptimes, mintime = (_get_phased_quantities(
        stimes, smags, serrs, period))

    # now figure out the number of knots up to max knots (=100)
    nobs = len(phase)
    nknots = int(npfloor(knotfraction * nobs))
    nknots = maxknots if nknots > maxknots else nknots
    splineknots = nplinspace(phase[0] + 0.01, phase[-1] - 0.01, num=nknots)

    # generate and fit the spline
    spl = LSQUnivariateSpline(phase, pmags, t=splineknots, w=1.0 / perrs)

    # calculate the spline fit to the actual phases, the chisq and red-chisq
    fitmags = spl(phase)

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

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

    if verbose:
        LOGINFO('spline fit done. nknots = %s,  '
                'chisq = %.5f, reduced chisq = %.5f' %
                (nknots, 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': 'spline',
        'fitinfo': {
            'nknots': nknots,
            '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
Пример #6
0
def spline_fit_magseries(times, mags, errs, period,
                         knotfraction=0.01,
                         maxknots=30,
                         sigclip=30.0,
                         plotfit=False,
                         ignoreinitfail=False,
                         magsarefluxes=False,
                         verbose=True):

    '''This fits a univariate cubic spline to the phased light curve.

    This fit may be better than the Fourier fit for sharply variable objects,
    like EBs, so can be used to distinguish them from other types of variables.

    Parameters
    ----------

    times,mags,errs : np.array
        The input mag/flux time-series to fit a spline to.

    period : float
        The period to use for the spline fit.

    knotfraction : float
        The knot fraction is the number of internal knots to use for the
        spline. A value of 0.01 (or 1%) of the total number of non-nan
        observations appears to work quite well, without over-fitting. maxknots
        controls the maximum number of knots that will be allowed.

    maxknots : int
        The maximum number of knots that will be used even if `knotfraction`
        gives a value to use larger than `maxknots`. This helps dealing with
        over-fitting to short time-scale variations.

    sigclip : float or int or sequence of two floats/ints or None
        If a single float or int, a symmetric sigma-clip will be performed using
        the number provided as the sigma-multiplier to cut out from the input
        time-series.

        If a list of two ints/floats is provided, the function will perform an
        'asymmetric' sigma-clip. The first element in this list is the sigma
        value to use for fainter flux/mag values; the second element in this
        list is the sigma value to use for brighter flux/mag values. For
        example, `sigclip=[10., 3.]`, will sigclip out greater than 10-sigma
        dimmings and greater than 3-sigma brightenings. Here the meaning of
        "dimming" and "brightening" is set by *physics* (not the magnitude
        system), which is why the `magsarefluxes` kwarg must be correctly set.

        If `sigclip` is None, no sigma-clipping will be performed, and the
        time-series (with non-finite elems removed) will be passed through to
        the output.

    magsarefluxes : bool
        If True, will treat the input values of `mags` as fluxes for purposes of
        plotting the fit and sig-clipping.

    plotfit : str or False
        If this is a string, this function will make a plot for the fit to the
        mag/flux time-series and writes the plot to the path specified here.

    ignoreinitfail : bool
        If this is True, ignores the initial failure to find a set of optimized
        Fourier parameters using the global optimization function and proceeds
        to do a least-squares fit anyway.

    verbose : bool
        If True, will indicate progress and warn of any problems.

    Returns
    -------

    dict
        This function returns a dict containing the model fit parameters, the
        minimized chi-sq value and the reduced chi-sq value. The form of this
        dict is mostly standardized across all functions in this module::

            {
                'fittype':'spline',
                'fitinfo':{
                    'nknots': the number of knots used for the fit
                    'fitmags': the model fit mags,
                    'fitepoch': the epoch of minimum light for the fit,
                },
                'fitchisq': the minimized value of the fit's chi-sq,
                'fitredchisq':the reduced chi-sq value,
                'fitplotfile': the output fit plot if fitplot is not None,
                'magseries':{
                    'times':input times in phase order of the model,
                    'phase':the phases of the model mags,
                    'mags':input mags/fluxes in the phase order of the model,
                    'errs':errs in the phase order of the model,
                    'magsarefluxes':input value of magsarefluxes kwarg
                }
            }

    '''

    # this is required to fit the spline correctly
    if errs is None:
        errs = npfull_like(mags, 0.005)

    # sigclip the magnitude time series
    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 the mag series
    phase, pmags, perrs, ptimes, mintime = (
        get_phased_quantities(stimes, smags, serrs, period)
    )

    # now figure out the number of knots up to max knots (=100)
    nobs = len(phase)
    nknots = int(npfloor(knotfraction*nobs))
    nknots = maxknots if nknots > maxknots else nknots
    splineknots = nplinspace(phase[0] + 0.01,
                             phase[-1] - 0.01,
                             num=nknots)

    # NOTE: newer scipy needs x to be strictly increasing. this means we should
    # filter out anything that doesn't have np.diff(phase) > 0.0
    # FIXME: this needs to be tested
    phase_diffs_ind = npdiff(phase) > 0.0
    incphase_ind = npconcatenate((nparray([True]), phase_diffs_ind))
    phase, pmags, perrs = (phase[incphase_ind],
                           pmags[incphase_ind],
                           perrs[incphase_ind])

    # generate and fit the spline
    spl = LSQUnivariateSpline(phase, pmags, t=splineknots, w=1.0/perrs)

    # calculate the spline fit to the actual phases, the chisq and red-chisq
    fitmags = spl(phase)

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

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

    if verbose:
        LOGINFO(
            'spline fit done. nknots = %s,  '
            'chisq = %.5f, reduced chisq = %.5f' %
            (nknots, 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))
    if len(fitmagminind[0]) > 1:
        fitmagminind = (fitmagminind[0][0],)
    magseriesepoch = ptimes[fitmagminind]

    # assemble the returndict
    returndict = {
        'fittype':'spline',
        'fitinfo':{
            'nknots':nknots,
            '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
Пример #7
0
def flare_model(flareparams, times, mags, errs):
    '''This is a flare model function, similar to Kowalski+ 2011.

    Model params
    ------------

    flareparams is a list:

    [amplitude, flare_peak_time, rise_gaussian_stdev, decay_time_constant]

    where:

    amplitude: the maximum flare amplitude in mags or flux. If flux, then
    amplitude should be positive. If mags, amplitude should be negative.

    flare_peak_time: time at which the flare maximum happens

    rise_gaussian_stdev: the stdev of the gaussian describing the rise of the
                         flare

    decay_time_constant: the time constant of the exponential fall of the flare


    Other args
    ----------

    times: a numpy array of times

    mags: a numpy array of magnitudes or fluxes. the flare will simply be added
    to mags at the appropriate times

    errs: a numpy array of measurement errors for each mag/flux measurement

    '''

    (amplitude, flare_peak_time,
     rise_gaussian_stdev, decay_time_constant) = flareparams

    zerolevel = npmedian(mags)
    modelmags = npfull_like(times, zerolevel)

    # before peak gaussian rise...
    modelmags[times < flare_peak_time] = (
        mags[times < flare_peak_time] +
        amplitude * np.exp(
            -((times[times < flare_peak_time] -
               flare_peak_time) *
              (times[times < flare_peak_time] -
               flare_peak_time)) /
            (2.0*rise_gaussian_stdev*rise_gaussian_stdev)
            )
    )

    # after peak exponential decay...
    modelmags[times > flare_peak_time] = (
        mags[times > flare_peak_time] +
        amplitude * np.exp(
            -((times[times > flare_peak_time] -
               flare_peak_time)) /
            (decay_time_constant)
            )
    )

    return modelmags, times, mags, errs
Пример #8
0
def trapezoid_transit_func(transitparams, times, mags, errs):
    '''This returns a trapezoid transit-shaped function.

    Suitable for first order modeling of transit signals.

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

    All of these will then have fitted values after the fit is done.

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

    (transitperiod, transitepoch, transitdepth, transitduration,
     ingressduration) = transitparams

    # generate the phases
    iphase = (times - transitepoch) / transitperiod
    iphase = iphase - npfloor(iphase)

    phasesortind = npargsort(iphase)
    phase = iphase[phasesortind]
    ptimes = times[phasesortind]
    pmags = mags[phasesortind]
    perrs = errs[phasesortind]

    zerolevel = npmedian(pmags)
    modelmags = npfull_like(phase, zerolevel)

    halftransitduration = transitduration / 2.0
    bottomlevel = zerolevel - transitdepth
    slope = transitdepth / ingressduration

    # the four contact points of the eclipse
    firstcontact = 1.0 - halftransitduration
    secondcontact = firstcontact + ingressduration
    thirdcontact = halftransitduration - ingressduration
    fourthcontact = halftransitduration

    ## the phase indices ##

    # during ingress
    ingressind = (phase > firstcontact) & (phase < secondcontact)

    # at transit bottom
    bottomind = (phase > secondcontact) | (phase < thirdcontact)

    # during egress
    egressind = (phase > thirdcontact) & (phase < fourthcontact)

    # set the mags
    modelmags[ingressind] = zerolevel - slope * (phase[ingressind] -
                                                 firstcontact)
    modelmags[bottomind] = bottomlevel
    modelmags[egressind] = bottomlevel + slope * (phase[egressind] -
                                                  thirdcontact)

    return modelmags, phase, ptimes, pmags, perrs