コード例 #1
0
def ed(mpo, left=False):
    # Convert mpo into a matrix
    H = mpo2mat(mpo)
    H = to_nparray(H)
    (nx, ny) = H.shape
    if False:
        for y in range(ny):
            string = ''
            for x in range(nx):
                string += '{} '.format(H[x, y])
            print(string)
    # Solve eigenproblem
    if left:
        e, vl, vr = sla.eig(H, left=True)
        inds = npargsort(npreal(e))[::-1]
        e = e[inds]
        vl = vl[:, inds]
        vr = vr[:, inds]
        e = from_nparray(e)
        vl = from_nparray(vl)
        vr = from_nparray(vr)
        return e, vl, vr
    else:
        e, vr = sla.eig(H, left=False)
        inds = npargsort(npreal(e))[::-1]
        e = e[inds]
        vr = vr[:, inds]
        e = from_nparray(e)
        vr = from_nparray(vr)
        return e, vr
コード例 #2
0
ファイル: lcfit.py プロジェクト: joshuawallace/astrobase
def _get_phased_quantities(stimes, smags, serrs, period):
    '''
    Given finite and sigma-clipped times, magnitudes, and errors (i.e. the
    output of lcfit.get_finite_and_sigclipped_data), along with the period at
    which to phase-fold the data, perform the phase-folding and return:
        1) phase: phase-sorted values of phase at each of stimes
        2) pmags: phase-sorted magnitudes at each phase
        3) perrs: phase-sorted errors
        4) ptimes: phase-sorted times
        5) mintime: earliest time in stimes.
    '''

    # phase the mag series using the given period and faintest mag time
    # mintime = stimes[npwhere(smags == npmax(smags))]

    # phase the mag series using the given period and epoch = min(stimes)
    mintime = npmin(stimes)

    # calculate the unsorted phase, then sort it
    iphase = (stimes - mintime) / period - npfloor((stimes - mintime) / period)
    phasesortind = npargsort(iphase)

    # these are the final quantities to use for the Fourier fits
    phase = iphase[phasesortind]
    pmags = smags[phasesortind]
    perrs = serrs[phasesortind]

    # get the times sorted in phase order (useful to get the fit mag minimum
    # with respect to phase -- the light curve minimum)
    ptimes = stimes[phasesortind]

    return phase, pmags, perrs, ptimes, mintime
コード例 #3
0
def exact1(mps, mpo, envl, envr):
    """ 
    Calculate the eigenvalues and eigenvectors by explicitly computing the Hamiltonian

    Args:
        mps : 1d array of np or ctf tensors
            a list containing the mps tensor for each desired 
            state at the optimization site
        mpo : 1d array of np or ctf tensors
            a list containing the mpo tensor for each 
            operator at the optimization site
        envl : 1d array of np or ctf tensors
            a list containing the left env tensor for each
            operator at the optimization site
        envr : 1d array of np or ctf tensors
            a list containing the right env tensor for each
            operator at the optimization site

    Returns:
        E : 1d array
            a 1d array of the energy associated with each state 
            of the system
        mps : 1d array of np or ctf tensors
            a list containing the resulting mps tensor for each
            state from the optimization
        ovlp : float
            the overlap between the input guess and output state
    """
    mpiprint(6, 'Doing Exact optimization routine')

    # Figure out number of states required
    nState = len(mps)

    # Compute the full Hamiltonian
    H = calc_ham1(mps, mpo, envl, envr)

    # Diagonalize and sort
    if USE_CTF: H = to_nparray(H)
    E, vecs = sla.eig(H)
    inds = npargsort(E)[::-1]
    E = E[inds[:nState]]
    vecs = vecs[:, inds[:nState]]

    # Convert vecs back to ctf if needed
    if USE_CTF: vecs = from_nparray(vecs)

    # Convert vecs into original mps shape
    _mps = mps
    mps = vec2mps(vecs, mps)

    # Check the overlap
    # PH - Need to implement
    ovlp = calc_ovlp(_mps, mps)

    return E, mps, ovlp
コード例 #4
0
ファイル: sinusoidal.py プロジェクト: sakshambassi/astrobase
def sine_series_sum(fourierparams, times, mags, errs):
    '''This generates a sinusoidal light curve using a sine series.

    The series is generated using the coefficients provided in
    fourierparams. This is a sequence like so:

    [period,
     epoch,
     [ampl_1, ampl_2, ampl_3, ..., ampl_X],
     [pha_1, pha_2, pha_3, ..., pha_X]]

    where X is the Fourier order.

    '''

    period, epoch, famps, fphases = fourierparams

    # figure out the order from the length of the Fourier param list
    forder = len(famps)

    # phase the times with this period
    iphase = (times - epoch) / period
    iphase = iphase - npfloor(iphase)

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

    # calculate all the individual terms of the series
    fseries = [
        famps[x] * npsin(2.0 * MPI * x * phase + fphases[x])
        for x in range(forder)
    ]

    # this is the zeroth order coefficient - a constant equal to median mag
    modelmags = npmedian(mags)

    # sum the series
    for fo in fseries:
        modelmags += fo

    return modelmags, phase, ptimes, pmags, perrs
コード例 #5
0
def sortedKeys(d):
    """
    Return keys of the dictionary d sorted based on their values.
    """
    values = d.values()
    sortedIndices = npargsort(values)
    sortedKeys = [d.keys()[i] for i in sortedIndices]
    minVal = min(values)
    countMin = values.count(minVal)
    if countMin > 1:
        minIndices = sortedKeys[0:countMin]
        nInd = len(minIndices)
        idx = range(nInd)
        nprandom.shuffle(idx)
        permMins = idx
        c = 0
        for i in range(nInd):
            place = permMins[c]
            sortedKeys[c] = minIndices[place]
            c += 1
    return sortedKeys
コード例 #6
0
def sortedKeys(d):
    """
    Return keys of the dictionary d sorted based on their values.
    """
    values = d.values()
    sortedIndices = npargsort(values)
    sortedKeys = [d.keys()[i] for i in sortedIndices]
    minVal = min(values)
    countMin = values.count(minVal)
    if countMin > 1:
        minIndices = sortedKeys[0: countMin]
        nInd = len(minIndices)
        idx = range(nInd)
        nprandom.shuffle(idx)
        permMins = idx
        c = 0
        for i in range(nInd):
            place = permMins[c]
            sortedKeys[c] = minIndices[place]
            c += 1
    return sortedKeys
コード例 #7
0
ファイル: abls.py プロジェクト: JinbiaoJi/astrobase
def bls_serial_pfind(
        times,
        mags,
        errs,
        magsarefluxes=False,
        startp=0.1,  # search from 0.1 d to...
        endp=100.0,  # ... 100.0 d -- don't search full timebase
        stepsize=5.0e-4,
        mintransitduration=0.01,  # minimum transit length in phase
        maxtransitduration=0.4,  # maximum transit length in phase
        ndurations=100,
        autofreq=True,  # figure out f0, nf, and df automatically
        blsobjective='likelihood',
        blsmethod='fast',
        blsoversample=10,
        blsmintransits=3,
        blsfreqfactor=10.0,
        periodepsilon=0.1,
        nbestpeaks=5,
        sigclip=10.0,
        endp_timebase_check=True,
        verbose=True,
        raiseonfail=False):
    '''Runs the Box Least Squares Fitting Search for transit-shaped signals.

    Based on the version of BLS in Astropy 3.1:
    `astropy.stats.BoxLeastSquares`. If you don't have Astropy 3.1, this module
    will fail to import. Note that by default, this implementation of
    `bls_serial_pfind` doesn't use the `.autoperiod()` function from
    `BoxLeastSquares` but uses the same auto frequency-grid generation as the
    functions in `periodbase.kbls`. If you want to use Astropy's implementation,
    set the value of `autofreq` kwarg to 'astropy'.

    The dict returned from this function contains a `blsmodel` key, which is the
    generated model from Astropy's BLS. Use the `.compute_stats()` method to
    calculate the required stats like SNR, depth, duration, etc.

    Parameters
    ----------

    times,mags,errs : np.array
        The magnitude/flux time-series to search for transits.

    magsarefluxes : bool
        If the input measurement values in `mags` and `errs` are in fluxes, set
        this to True.

    startp,endp : float
        The minimum and maximum periods to consider for the transit search.

    stepsize : float
        The step-size in frequency to use when constructing a frequency grid for
        the period search.

    mintransitduration,maxtransitduration : float
        The minimum and maximum transitdurations (in units of phase) to consider
        for the transit search.

    ndurations : int
        The number of transit durations to use in the period-search.

    autofreq : bool or str
        If this is True, the values of `stepsize` and `nphasebins` will be
        ignored, and these, along with a frequency-grid, will be determined
        based on the following relations::

            nphasebins = int(ceil(2.0/mintransitduration))
            if nphasebins > 3000:
                nphasebins = 3000

            stepsize = 0.25*mintransitduration/(times.max()-times.min())

            minfreq = 1.0/endp
            maxfreq = 1.0/startp
            nfreq = int(ceil((maxfreq - minfreq)/stepsize))

        If this is False, you must set `startp`, `endp`, and `stepsize` as
        appropriate.

        If this is str == 'astropy', will use the
        `astropy.stats.BoxLeastSquares.autoperiod()` function to calculate the
        frequency grid instead of the kbls method.

    blsobjective : {'likelihood','snr'}
        Sets the type of objective to optimize in the `BoxLeastSquares.power()`
        function.

    blsmethod : {'fast','slow'}
        Sets the type of method to use in the `BoxLeastSquares.power()`
        function.

    blsoversample : {'likelihood','snr'}
        Sets the `oversample` kwarg for the `BoxLeastSquares.power()` function.

    blsmintransits : int
        Sets the `min_n_transits` kwarg for the `BoxLeastSquares.autoperiod()`
        function.

    blsfreqfactor : float
        Sets the `frequency_factor` kwarg for the `BoxLeastSquares.autperiod()`
        function.

    periodepsilon : float
        The fractional difference between successive values of 'best' periods
        when sorting by periodogram power to consider them as separate periods
        (as opposed to part of the same periodogram peak). This is used to avoid
        broad peaks in the periodogram and make sure the 'best' periods returned
        are all actually independent.

    nbestpeaks : int
        The number of 'best' peaks to return from the periodogram results,
        starting from the global maximum of the periodogram peak values.

    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.

    endp_timebase_check : bool
        If True, will check if the ``endp`` value is larger than the time-base
        of the observations. If it is, will change the ``endp`` value such that
        it is half of the time-base. If False, will allow an ``endp`` larger
        than the time-base of the observations.

    verbose : bool
        If this is True, will indicate progress and details about the frequency
        grid used for the period search.

    raiseonfail : bool
        If True, raises an exception if something goes wrong. Otherwise, returns
        None.

    Returns
    -------

    dict
        This function returns a dict, referred to as an `lspinfo` dict in other
        astrobase functions that operate on periodogram results. This is a
        standardized format across all astrobase period-finders, and is of the
        form below::

            {'bestperiod': the best period value in the periodogram,
             'bestlspval': the periodogram peak associated with the best period,
             'nbestpeaks': the input value of nbestpeaks,
             'nbestlspvals': nbestpeaks-size list of best period peak values,
             'nbestperiods': nbestpeaks-size list of best periods,
             'lspvals': the full array of periodogram powers,
             'frequencies': the full array of frequencies considered,
             'periods': the full array of periods considered,
             'durations': the array of durations used to run BLS,
             'blsresult': Astropy BLS result object (BoxLeastSquaresResult),
             'blsmodel': Astropy BLS BoxLeastSquares object used for work,
             'stepsize': the actual stepsize used,
             'nfreq': the actual nfreq used,
             'durations': the durations array used,
             'mintransitduration': the input mintransitduration,
             'maxtransitduration': the input maxtransitdurations,
             'method':'bls' -> the name of the period-finder method,
             'kwargs':{ dict of all of the input kwargs for record-keeping}}

    '''

    # 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:

        # if we're setting up everything automatically
        if isinstance(autofreq, bool) and autofreq:

            # use heuristic to figure out best timestep
            stepsize = 0.25 * mintransitduration / (stimes.max() -
                                                    stimes.min())

            # now figure out the frequencies to use
            minfreq = 1.0 / endp
            maxfreq = 1.0 / startp
            nfreq = int(npceil((maxfreq - minfreq) / stepsize))

            # say what we're using
            if verbose:
                LOGINFO('min P: %s, max P: %s, nfreq: %s, '
                        'minfreq: %s, maxfreq: %s' %
                        (startp, endp, nfreq, minfreq, maxfreq))
                LOGINFO('autofreq = True: using AUTOMATIC values for '
                        'freq stepsize: %s, ndurations: %s, '
                        'min transit duration: %s, max transit duration: %s' %
                        (stepsize, ndurations, mintransitduration,
                         maxtransitduration))

            use_autoperiod = False

        elif isinstance(autofreq, bool) and not autofreq:

            minfreq = 1.0 / endp
            maxfreq = 1.0 / startp
            nfreq = int(npceil((maxfreq - minfreq) / stepsize))

            # say what we're using
            if verbose:
                LOGINFO('min P: %s, max P: %s, nfreq: %s, '
                        'minfreq: %s, maxfreq: %s' %
                        (startp, endp, nfreq, minfreq, maxfreq))
                LOGINFO('autofreq = False: using PROVIDED values for '
                        'freq stepsize: %s, ndurations: %s, '
                        'min transit duration: %s, max transit duration: %s' %
                        (stepsize, ndurations, mintransitduration,
                         maxtransitduration))

            use_autoperiod = False

        elif isinstance(autofreq, str) and autofreq == 'astropy':

            use_autoperiod = True
            minfreq = 1.0 / endp
            maxfreq = 1.0 / startp

        else:

            LOGERROR("unknown autofreq kwarg encountered. can't continue...")
            return None

        # check the minimum frequency
        if ((minfreq < (1.0 / (stimes.max() - stimes.min())))
                and endp_timebase_check):

            LOGWARNING('the requested max P = %.3f is larger than '
                       'the time base of the observations = %.3f, '
                       ' will make minfreq = 2 x 1/timebase' %
                       (endp, stimes.max() - stimes.min()))
            minfreq = 2.0 / (stimes.max() - stimes.min())
            LOGWARNING('new minfreq: %s, maxfreq: %s' % (minfreq, maxfreq))

        # run BLS
        try:

            # astropy's BLS requires durations in units of time
            durations = nplinspace(mintransitduration * startp,
                                   maxtransitduration * startp, ndurations)

            # set up the correct units for the BLS model
            if magsarefluxes:

                blsmodel = BoxLeastSquares(stimes * u.day,
                                           smags * u.dimensionless_unscaled,
                                           dy=serrs * u.dimensionless_unscaled)

            else:

                blsmodel = BoxLeastSquares(stimes * u.day,
                                           smags * u.mag,
                                           dy=serrs * u.mag)

            # use autoperiod if requested
            if use_autoperiod:
                periods = nparray(
                    blsmodel.autoperiod(durations,
                                        minimum_period=startp,
                                        maximum_period=endp,
                                        minimum_n_transit=blsmintransits,
                                        frequency_factor=blsfreqfactor))
                nfreq = periods.size

                if verbose:
                    LOGINFO("autofreq = 'astropy', used .autoperiod() with "
                            "minimum_n_transit = %s, freq_factor = %s "
                            "to generate the frequency grid" %
                            (blsmintransits, blsfreqfactor))
                    LOGINFO(
                        'stepsize = %.5f, nfreq = %s, minfreq = %.5f, '
                        'maxfreq = %.5f, ndurations = %s' %
                        (abs(1.0 / periods[1] - 1.0 / periods[0]), nfreq, 1.0 /
                         periods.max(), 1.0 / periods.min(), durations.size))

            # otherwise, use kbls method
            else:
                frequencies = minfreq + nparange(nfreq) * stepsize
                periods = 1.0 / frequencies

            if nfreq > 5.0e5:
                if verbose:
                    LOGWARNING('more than 5.0e5 frequencies to go through; '
                               'this will take a while. '
                               'you might want to use the '
                               'abls.bls_parallel_pfind function instead')

            # run the periodogram
            blsresult = blsmodel.power(periods * u.day,
                                       durations * u.day,
                                       objective=blsobjective,
                                       method=blsmethod,
                                       oversample=blsoversample)

            # get the peak values
            lsp = nparray(blsresult.power)

            # find the nbestpeaks for the periodogram: 1. sort the lsp array
            # by highest value first 2. go down the values until we find
            # five values that are separated by at least periodepsilon in
            # period
            # make sure to get only the finite peaks in the periodogram
            # this is needed because BLS may produce infs for some peaks
            finitepeakind = npisfinite(lsp)
            finlsp = lsp[finitepeakind]
            finperiods = periods[finitepeakind]

            # make sure that finlsp has finite values before we work on it
            try:

                bestperiodind = npargmax(finlsp)

            except ValueError:

                LOGERROR('no finite periodogram values '
                         'for this mag series, skipping...')

                return {
                    'bestperiod': npnan,
                    'bestlspval': npnan,
                    'nbestpeaks': nbestpeaks,
                    'nbestinds': None,
                    'nbestlspvals': None,
                    'nbestperiods': None,
                    'lspvals': None,
                    'periods': None,
                    'durations': None,
                    'method': 'bls',
                    'blsresult': None,
                    'blsmodel': None,
                    'kwargs': {
                        'startp': startp,
                        'endp': endp,
                        'stepsize': stepsize,
                        'mintransitduration': mintransitduration,
                        'maxtransitduration': maxtransitduration,
                        'ndurations': ndurations,
                        'blsobjective': blsobjective,
                        'blsmethod': blsmethod,
                        'blsoversample': blsoversample,
                        'blsntransits': blsmintransits,
                        'blsfreqfactor': blsfreqfactor,
                        'autofreq': autofreq,
                        'periodepsilon': periodepsilon,
                        'nbestpeaks': nbestpeaks,
                        'sigclip': sigclip,
                        'magsarefluxes': magsarefluxes
                    }
                }

            sortedlspind = npargsort(finlsp)[::-1]
            sortedlspperiods = finperiods[sortedlspind]
            sortedlspvals = finlsp[sortedlspind]

            # now get the nbestpeaks
            nbestperiods, nbestlspvals, nbestinds, peakcount = ([
                finperiods[bestperiodind]
            ], [finlsp[bestperiodind]], [bestperiodind], 1)
            prevperiod = sortedlspperiods[0]

            # find the best nbestpeaks in the lsp and their periods
            for period, lspval, ind in zip(sortedlspperiods, sortedlspvals,
                                           sortedlspind):

                if peakcount == nbestpeaks:
                    break
                perioddiff = abs(period - prevperiod)
                bestperiodsdiff = [abs(period - x) for x in nbestperiods]

                # print('prevperiod = %s, thisperiod = %s, '
                #       'perioddiff = %s, peakcount = %s' %
                #       (prevperiod, period, perioddiff, peakcount))

                # this ensures that this period is different from the last
                # period and from all the other existing best periods by
                # periodepsilon to make sure we jump to an entire different
                # peak in the periodogram
                if (perioddiff > (periodepsilon * prevperiod)
                        and all(x > (periodepsilon * period)
                                for x in bestperiodsdiff)):
                    nbestperiods.append(period)
                    nbestlspvals.append(lspval)
                    nbestinds.append(ind)
                    peakcount = peakcount + 1

                prevperiod = period

            # generate the return dict
            resultdict = {
                'bestperiod': finperiods[bestperiodind],
                'bestlspval': finlsp[bestperiodind],
                'nbestpeaks': nbestpeaks,
                'nbestinds': nbestinds,
                'nbestlspvals': nbestlspvals,
                'nbestperiods': nbestperiods,
                'lspvals': lsp,
                'frequencies': frequencies,
                'periods': periods,
                'durations': durations,
                'blsresult': blsresult,
                'blsmodel': blsmodel,
                'stepsize': stepsize,
                'nfreq': nfreq,
                'mintransitduration': mintransitduration,
                'maxtransitduration': maxtransitduration,
                'method': 'bls',
                'kwargs': {
                    'startp': startp,
                    'endp': endp,
                    'stepsize': stepsize,
                    'mintransitduration': mintransitduration,
                    'maxtransitduration': maxtransitduration,
                    'ndurations': ndurations,
                    'blsobjective': blsobjective,
                    'blsmethod': blsmethod,
                    'blsoversample': blsoversample,
                    'blsntransits': blsmintransits,
                    'blsfreqfactor': blsfreqfactor,
                    'autofreq': autofreq,
                    'periodepsilon': periodepsilon,
                    'nbestpeaks': nbestpeaks,
                    'sigclip': sigclip,
                    'magsarefluxes': magsarefluxes
                }
            }

            return resultdict

        except Exception as e:

            LOGEXCEPTION('BLS failed!')

            if raiseonfail:
                raise

            return {
                'bestperiod': npnan,
                'bestlspval': npnan,
                'nbestinds': None,
                'nbestpeaks': nbestpeaks,
                'nbestlspvals': None,
                'nbestperiods': None,
                'lspvals': None,
                'periods': None,
                'durations': None,
                'blsresult': None,
                'blsmodel': None,
                'stepsize': stepsize,
                'nfreq': nfreq,
                'mintransitduration': mintransitduration,
                'maxtransitduration': maxtransitduration,
                'method': 'bls',
                'kwargs': {
                    'startp': startp,
                    'endp': endp,
                    'stepsize': stepsize,
                    'mintransitduration': mintransitduration,
                    'maxtransitduration': maxtransitduration,
                    'ndurations': ndurations,
                    'blsobjective': blsobjective,
                    'blsmethod': blsmethod,
                    'blsoversample': blsoversample,
                    'blsntransits': blsmintransits,
                    'blsfreqfactor': blsfreqfactor,
                    'autofreq': autofreq,
                    'periodepsilon': periodepsilon,
                    'nbestpeaks': nbestpeaks,
                    'sigclip': sigclip,
                    'magsarefluxes': magsarefluxes
                }
            }

    else:

        LOGERROR('no good detections for these times and mags, skipping...')
        return {
            'bestperiod': npnan,
            'bestlspval': npnan,
            'nbestinds': None,
            'nbestpeaks': nbestpeaks,
            'nbestlspvals': None,
            'nbestperiods': None,
            'lspvals': None,
            'periods': None,
            'durations': None,
            'blsresult': None,
            'blsmodel': None,
            'stepsize': stepsize,
            'nfreq': None,
            'nphasebins': None,
            'mintransitduration': mintransitduration,
            'maxtransitduration': maxtransitduration,
            'method': 'bls',
            'kwargs': {
                'startp': startp,
                'endp': endp,
                'stepsize': stepsize,
                'mintransitduration': mintransitduration,
                'maxtransitduration': maxtransitduration,
                'ndurations': ndurations,
                'blsobjective': blsobjective,
                'blsmethod': blsmethod,
                'blsoversample': blsoversample,
                'blsntransits': blsmintransits,
                'blsfreqfactor': blsfreqfactor,
                'autofreq': autofreq,
                'periodepsilon': periodepsilon,
                'nbestpeaks': nbestpeaks,
                'sigclip': sigclip,
                'magsarefluxes': magsarefluxes
            }
        }
コード例 #8
0
ファイル: abls.py プロジェクト: JinbiaoJi/astrobase
def bls_parallel_pfind(
    times,
    mags,
    errs,
    magsarefluxes=False,
    startp=0.1,  # by default, search from 0.1 d to...
    endp=100.0,  # ... 100.0 d -- don't search full timebase
    stepsize=1.0e-4,
    mintransitduration=0.01,  # minimum transit length in phase
    maxtransitduration=0.4,  # maximum transit length in phase
    ndurations=100,
    autofreq=True,  # figure out f0, nf, and df automatically
    blsobjective='likelihood',
    blsmethod='fast',
    blsoversample=5,
    blsmintransits=3,
    blsfreqfactor=10.0,
    nbestpeaks=5,
    periodepsilon=0.1,  # 0.1
    sigclip=10.0,
    endp_timebase_check=True,
    verbose=True,
    nworkers=None,
):
    '''Runs the Box Least Squares Fitting Search for transit-shaped signals.

    Breaks up the full frequency space into chunks and passes them to parallel
    BLS workers.

    Based on the version of BLS in Astropy 3.1:
    `astropy.stats.BoxLeastSquares`. If you don't have Astropy 3.1, this module
    will fail to import. Note that by default, this implementation of
    `bls_parallel_pfind` doesn't use the `.autoperiod()` function from
    `BoxLeastSquares` but uses the same auto frequency-grid generation as the
    functions in `periodbase.kbls`. If you want to use Astropy's implementation,
    set the value of `autofreq` kwarg to 'astropy'. The generated period array
    will then be broken up into chunks and sent to the individual workers.

    NOTE: the combined BLS spectrum produced by this function is not identical
    to that produced by running BLS in one shot for the entire frequency
    space. There are differences on the order of 1.0e-3 or so in the respective
    peak values, but peaks appear at the same frequencies for both methods. This
    is likely due to different aliasing caused by smaller chunks of the
    frequency space used by the parallel workers in this function. When in
    doubt, confirm results for this parallel implementation by comparing to
    those from the serial implementation above.

    In particular, when you want to get reliable estimates of the SNR, transit
    depth, duration, etc. that Astropy's BLS gives you, rerun `bls_serial_pfind`
    with `startp`, and `endp` close to the best period you want to characterize
    the transit at. The dict returned from that function contains a `blsmodel`
    key, which is the generated model from Astropy's BLS. Use the
    `.compute_stats()` method to calculate the required stats.

    Parameters
    ----------

    times,mags,errs : np.array
        The magnitude/flux time-series to search for transits.

    magsarefluxes : bool
        If the input measurement values in `mags` and `errs` are in fluxes, set
        this to True.

    startp,endp : float
        The minimum and maximum periods to consider for the transit search.

    stepsize : float
        The step-size in frequency to use when constructing a frequency grid for
        the period search.

    mintransitduration,maxtransitduration : float
        The minimum and maximum transitdurations (in units of phase) to consider
        for the transit search.

    ndurations : int
        The number of transit durations to use in the period-search.

    autofreq : bool or str
        If this is True, the values of `stepsize` and `nphasebins` will be
        ignored, and these, along with a frequency-grid, will be determined
        based on the following relations::

            nphasebins = int(ceil(2.0/mintransitduration))
            if nphasebins > 3000:
                nphasebins = 3000

            stepsize = 0.25*mintransitduration/(times.max()-times.min())

            minfreq = 1.0/endp
            maxfreq = 1.0/startp
            nfreq = int(ceil((maxfreq - minfreq)/stepsize))

        If this is False, you must set `startp`, `endp`, and `stepsize` as
        appropriate.

        If this is str == 'astropy', will use the
        `astropy.stats.BoxLeastSquares.autoperiod()` function to calculate the
        frequency grid instead of the kbls method.

    blsobjective : {'likelihood','snr'}
        Sets the type of objective to optimize in the `BoxLeastSquares.power()`
        function.

    blsmethod : {'fast','slow'}
        Sets the type of method to use in the `BoxLeastSquares.power()`
        function.

    blsoversample : {'likelihood','snr'}
        Sets the `oversample` kwarg for the `BoxLeastSquares.power()` function.

    blsmintransits : int
        Sets the `min_n_transits` kwarg for the `BoxLeastSquares.autoperiod()`
        function.

    blsfreqfactor : float
        Sets the `frequency_factor` kwarg for the `BoxLeastSquares.autoperiod()`
        function.

    periodepsilon : float
        The fractional difference between successive values of 'best' periods
        when sorting by periodogram power to consider them as separate periods
        (as opposed to part of the same periodogram peak). This is used to avoid
        broad peaks in the periodogram and make sure the 'best' periods returned
        are all actually independent.

    nbestpeaks : int
        The number of 'best' peaks to return from the periodogram results,
        starting from the global maximum of the periodogram peak values.

    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.

    endp_timebase_check : bool
        If True, will check if the ``endp`` value is larger than the time-base
        of the observations. If it is, will change the ``endp`` value such that
        it is half of the time-base. If False, will allow an ``endp`` larger
        than the time-base of the observations.

    verbose : bool
        If this is True, will indicate progress and details about the frequency
        grid used for the period search.

    nworkers : int or None
        The number of parallel workers to launch for period-search. If None,
        nworkers = NCPUS.

    Returns
    -------

    dict
        This function returns a dict, referred to as an `lspinfo` dict in other
        astrobase functions that operate on periodogram results. This is a
        standardized format across all astrobase period-finders, and is of the
        form below::

            {'bestperiod': the best period value in the periodogram,
             'bestlspval': the periodogram peak associated with the best period,
             'nbestpeaks': the input value of nbestpeaks,
             'nbestlspvals': nbestpeaks-size list of best period peak values,
             'nbestperiods': nbestpeaks-size list of best periods,
             'lspvals': the full array of periodogram powers,
             'frequencies': the full array of frequencies considered,
             'periods': the full array of periods considered,
             'durations': the array of durations used to run BLS,
             'blsresult': Astropy BLS result object (BoxLeastSquaresResult),
             'blsmodel': Astropy BLS BoxLeastSquares object used for work,
             'stepsize': the actual stepsize used,
             'nfreq': the actual nfreq used,
             'durations': the durations array used,
             'mintransitduration': the input mintransitduration,
             'maxtransitduration': the input maxtransitdurations,
             'method':'bls' -> the name of the period-finder method,
             'kwargs':{ dict of all of the input kwargs for record-keeping}}

    '''

    # 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:

        # if we're setting up everything automatically
        if isinstance(autofreq, bool) and autofreq:

            # use heuristic to figure out best timestep
            stepsize = 0.25 * mintransitduration / (stimes.max() -
                                                    stimes.min())

            # now figure out the frequencies to use
            minfreq = 1.0 / endp
            maxfreq = 1.0 / startp
            nfreq = int(npceil((maxfreq - minfreq) / stepsize))

            # say what we're using
            if verbose:
                LOGINFO('min P: %s, max P: %s, nfreq: %s, '
                        'minfreq: %s, maxfreq: %s' %
                        (startp, endp, nfreq, minfreq, maxfreq))
                LOGINFO('autofreq = True: using AUTOMATIC values for '
                        'freq stepsize: %s, ndurations: %s, '
                        'min transit duration: %s, max transit duration: %s' %
                        (stepsize, ndurations, mintransitduration,
                         maxtransitduration))

            use_autoperiod = False

        elif isinstance(autofreq, bool) and not autofreq:

            minfreq = 1.0 / endp
            maxfreq = 1.0 / startp
            nfreq = int(npceil((maxfreq - minfreq) / stepsize))

            # say what we're using
            if verbose:
                LOGINFO('min P: %s, max P: %s, nfreq: %s, '
                        'minfreq: %s, maxfreq: %s' %
                        (startp, endp, nfreq, minfreq, maxfreq))
                LOGINFO('autofreq = False: using PROVIDED values for '
                        'freq stepsize: %s, ndurations: %s, '
                        'min transit duration: %s, max transit duration: %s' %
                        (stepsize, ndurations, mintransitduration,
                         maxtransitduration))

            use_autoperiod = False

        elif isinstance(autofreq, str) and autofreq == 'astropy':

            use_autoperiod = True
            minfreq = 1.0 / endp
            maxfreq = 1.0 / startp

        else:

            LOGERROR("unknown autofreq kwarg encountered. can't continue...")
            return None

        # check the minimum frequency
        if ((minfreq < (1.0 / (stimes.max() - stimes.min())))
                and endp_timebase_check):

            LOGWARNING('the requested max P = %.3f is larger than '
                       'the time base of the observations = %.3f, '
                       ' will make minfreq = 2 x 1/timebase' %
                       (endp, stimes.max() - stimes.min()))
            minfreq = 2.0 / (stimes.max() - stimes.min())
            LOGWARNING('new minfreq: %s, maxfreq: %s' % (minfreq, maxfreq))

        #############################
        ## NOW RUN BLS IN PARALLEL ##
        #############################

        # fix number of CPUs if needed
        if not nworkers or nworkers > NCPUS:
            nworkers = NCPUS
            if verbose:
                LOGINFO('using %s workers...' % nworkers)

        # check if autoperiod is True and get the correct period-grid
        if use_autoperiod:

            # astropy's BLS requires durations in units of time
            durations = nplinspace(mintransitduration * startp,
                                   maxtransitduration * startp, ndurations)

            # set up the correct units for the BLS model
            if magsarefluxes:

                blsmodel = BoxLeastSquares(stimes * u.day,
                                           smags * u.dimensionless_unscaled,
                                           dy=serrs * u.dimensionless_unscaled)

            else:

                blsmodel = BoxLeastSquares(stimes * u.day,
                                           smags * u.mag,
                                           dy=serrs * u.mag)

            periods = nparray(
                blsmodel.autoperiod(durations * u.day,
                                    minimum_period=startp,
                                    maximum_period=endp,
                                    minimum_n_transit=blsmintransits,
                                    frequency_factor=blsfreqfactor))

            frequencies = 1.0 / periods
            nfreq = frequencies.size

            if verbose:
                LOGINFO("autofreq = 'astropy', used .autoperiod() with "
                        "minimum_n_transit = %s, freq_factor = %s "
                        "to generate the frequency grid" %
                        (blsmintransits, blsfreqfactor))
                LOGINFO('stepsize = %s, nfreq = %s, minfreq = %.5f, '
                        'maxfreq = %.5f, ndurations = %s' %
                        (abs(frequencies[1] - frequencies[0]), nfreq, 1.0 /
                         periods.max(), 1.0 / periods.min(), durations.size))

            del blsmodel
            del durations

        # otherwise, use kbls method
        else:

            frequencies = minfreq + nparange(nfreq) * stepsize

        # break up the tasks into chunks
        csrem = int(fmod(nfreq, nworkers))
        csint = int(float(nfreq / nworkers))
        chunk_minfreqs, chunk_nfreqs = [], []

        for x in range(nworkers):

            this_minfreqs = frequencies[x * csint]

            # handle usual nfreqs
            if x < (nworkers - 1):
                this_nfreqs = frequencies[x * csint:x * csint + csint].size
            else:
                this_nfreqs = frequencies[x * csint:x * csint + csint +
                                          csrem].size

            chunk_minfreqs.append(this_minfreqs)
            chunk_nfreqs.append(this_nfreqs)

        # populate the tasks list
        #
        # task[0] = times
        # task[1] = mags
        # task[2] = errs
        # task[3] = magsarefluxes

        # task[4] = minfreq
        # task[5] = nfreq
        # task[6] = stepsize

        # task[7] = nphasebins
        # task[8] = mintransitduration
        # task[9] = maxtransitduration

        # task[10] = blsobjective
        # task[11] = blsmethod
        # task[12] = blsoversample

        # populate the tasks list
        tasks = [(stimes, smags, serrs, magsarefluxes, chunk_minf, chunk_nf,
                  stepsize, ndurations, mintransitduration, maxtransitduration,
                  blsobjective, blsmethod, blsoversample)
                 for (chunk_minf,
                      chunk_nf) in zip(chunk_minfreqs, chunk_nfreqs)]

        if verbose:
            for ind, task in enumerate(tasks):
                LOGINFO('worker %s: minfreq = %.6f, nfreqs = %s' %
                        (ind + 1, task[4], task[5]))
            LOGINFO('running...')

        # return tasks

        # start the pool
        pool = Pool(nworkers)
        results = pool.map(_parallel_bls_worker, tasks)

        pool.close()
        pool.join()
        del pool

        # now concatenate the output lsp arrays
        lsp = npconcatenate([x['power'] for x in results])
        periods = 1.0 / frequencies

        # find the nbestpeaks for the periodogram: 1. sort the lsp array
        # by highest value first 2. go down the values until we find
        # five values that are separated by at least periodepsilon in
        # period
        # make sure to get only the finite peaks in the periodogram
        # this is needed because BLS may produce infs for some peaks
        finitepeakind = npisfinite(lsp)
        finlsp = lsp[finitepeakind]
        finperiods = periods[finitepeakind]

        # make sure that finlsp has finite values before we work on it
        try:

            bestperiodind = npargmax(finlsp)

        except ValueError:

            LOGERROR('no finite periodogram values '
                     'for this mag series, skipping...')

            return {
                'bestperiod': npnan,
                'bestlspval': npnan,
                'nbestpeaks': nbestpeaks,
                'nbestinds': None,
                'nbestlspvals': None,
                'nbestperiods': None,
                'lspvals': None,
                'periods': None,
                'durations': None,
                'method': 'bls',
                'blsresult': None,
                'blsmodel': None,
                'kwargs': {
                    'startp': startp,
                    'endp': endp,
                    'stepsize': stepsize,
                    'mintransitduration': mintransitduration,
                    'maxtransitduration': maxtransitduration,
                    'ndurations': ndurations,
                    'blsobjective': blsobjective,
                    'blsmethod': blsmethod,
                    'blsoversample': blsoversample,
                    'autofreq': autofreq,
                    'periodepsilon': periodepsilon,
                    'nbestpeaks': nbestpeaks,
                    'sigclip': sigclip,
                    'magsarefluxes': magsarefluxes
                }
            }

        sortedlspind = npargsort(finlsp)[::-1]
        sortedlspperiods = finperiods[sortedlspind]
        sortedlspvals = finlsp[sortedlspind]

        # now get the nbestpeaks
        nbestperiods, nbestlspvals, nbestinds, peakcount = ([
            finperiods[bestperiodind]
        ], [finlsp[bestperiodind]], [bestperiodind], 1)
        prevperiod = sortedlspperiods[0]

        # find the best nbestpeaks in the lsp and their periods
        for period, lspval, ind in zip(sortedlspperiods, sortedlspvals,
                                       sortedlspind):

            if peakcount == nbestpeaks:
                break
            perioddiff = abs(period - prevperiod)
            bestperiodsdiff = [abs(period - x) for x in nbestperiods]

            # this ensures that this period is different from the last
            # period and from all the other existing best periods by
            # periodepsilon to make sure we jump to an entire different
            # peak in the periodogram
            if (perioddiff > (periodepsilon * prevperiod)
                    and all(x > (periodepsilon * period)
                            for x in bestperiodsdiff)):
                nbestperiods.append(period)
                nbestlspvals.append(lspval)
                nbestinds.append(ind)
                peakcount = peakcount + 1

            prevperiod = period

        # generate the return dict
        resultdict = {
            'bestperiod': finperiods[bestperiodind],
            'bestlspval': finlsp[bestperiodind],
            'nbestpeaks': nbestpeaks,
            'nbestinds': nbestinds,
            'nbestlspvals': nbestlspvals,
            'nbestperiods': nbestperiods,
            'lspvals': lsp,
            'frequencies': frequencies,
            'periods': periods,
            'durations': [x['durations'] for x in results],
            'blsresult': [x['blsresult'] for x in results],
            'blsmodel': [x['blsmodel'] for x in results],
            'stepsize': stepsize,
            'nfreq': nfreq,
            'mintransitduration': mintransitduration,
            'maxtransitduration': maxtransitduration,
            'method': 'bls',
            'kwargs': {
                'startp': startp,
                'endp': endp,
                'stepsize': stepsize,
                'mintransitduration': mintransitduration,
                'maxtransitduration': maxtransitduration,
                'ndurations': ndurations,
                'blsobjective': blsobjective,
                'blsmethod': blsmethod,
                'blsoversample': blsoversample,
                'autofreq': autofreq,
                'periodepsilon': periodepsilon,
                'nbestpeaks': nbestpeaks,
                'sigclip': sigclip,
                'magsarefluxes': magsarefluxes
            }
        }

        return resultdict

    else:

        LOGERROR('no good detections for these times and mags, skipping...')
        return {
            'bestperiod': npnan,
            'bestlspval': npnan,
            'nbestinds': None,
            'nbestpeaks': nbestpeaks,
            'nbestlspvals': None,
            'nbestperiods': None,
            'lspvals': None,
            'periods': None,
            'durations': None,
            'blsresult': None,
            'blsmodel': None,
            'stepsize': stepsize,
            'nfreq': None,
            'nphasebins': None,
            'mintransitduration': mintransitduration,
            'maxtransitduration': maxtransitduration,
            'method': 'bls',
            'kwargs': {
                'startp': startp,
                'endp': endp,
                'stepsize': stepsize,
                'mintransitduration': mintransitduration,
                'maxtransitduration': maxtransitduration,
                'ndurations': ndurations,
                'blsobjective': blsobjective,
                'blsmethod': blsmethod,
                'blsoversample': blsoversample,
                'autofreq': autofreq,
                'periodepsilon': periodepsilon,
                'nbestpeaks': nbestpeaks,
                'sigclip': sigclip,
                'magsarefluxes': magsarefluxes
            }
        }
コード例 #9
0
ファイル: task_sdstatold.py プロジェクト: sjyu1988/casa
 def __sort_stats_order(self, order):
     if len(self.returnstats[self.returnstats.keys()[0]]) != len(order):
         raise ValueError, "Length of sort order list != statistics list."
     idx = npargsort(order)
     for key, val in self.returnstats.items():
         self.returnstats[key] = [val[i] for i in idx]
コード例 #10
0
ファイル: task_sdstat.py プロジェクト: keflavich/casa
 def __sort_stats_order(self, order):
     if len(self.returnstats[self.returnstats.keys()[0]]) != len(order):
         raise ValueError, "Length of sort order list != statistics list."
     idx = npargsort(order)
     for key, val in self.returnstats.items():
         self.returnstats[key] = [val[i] for i in idx ]
コード例 #11
0
def dworetsky_period_find(time,
                          mag,
                          err,
                          init_p,
                          end_p,
                          f_step,
                          verbose=False):
    '''

    This is the super-slow naive version taken from my thesis work.

    Uses the string length method in Dworetsky 1983 to calculate the period of a
    time-series of magnitude measurements and associated magnitude
    errors. Searches in linear frequency space (which obviously doesn't
    correspond to a linear period space).

    PARAMETERS:

    time: series of times at which mags were measured (usually some form of JD)
    mag: timeseries of magnitudes (np.array)
    err: associated errs per magnitude measurement (np.array)
    init_p, end_p: interval to search for periods between (both ends inclusive)
    f_step: step in frequency [days^-1] to use

    RETURNS:

    tuple of the following form:

    (periods (np.array),
     string_lengths (np.array),
     good_period_mask (boolean array))

    '''

    mod_mag = (mag - npmin(mag)) / (2.0 * (npmax(mag) - npmin(mag))) - 0.25
    fold_time = npmin(time)  # fold at the first time element

    init_f = 1.0 / end_p
    end_f = 1.0 / init_p

    n_freqs = npceil((end_f - init_f) / f_step)

    if verbose:
        print('searching %s frequencies between %s and %s days^-1...' %
              (n_freqs, init_f, end_f))

    out_periods = npempty(n_freqs, dtype=np.float64)
    out_strlens = npempty(n_freqs, dtype=np.float64)
    p_goodflags = npempty(n_freqs, dtype=bool)

    j_range = len(mag) - 1

    for i in range(int(n_freqs)):

        period = 1.0 / init_f

        # print('P: %s, f: %s, i: %s, n_freqs: %s, maxf: %s' %
        #       (period, init_f, i, n_freqs, end_f))

        phase = (time - fold_time) / period - npfloor(
            (time - fold_time) / period)
        phase_sort_ind = npargsort(phase)

        phase_sorted = phase[phase_sort_ind]
        mod_mag_sorted = mod_mag[phase_sort_ind]

        strlen = 0.0

        epsilon = 2.0 * npmean(err)
        delta_l = 0.34 * (epsilon - 0.5 *
                          (epsilon**2)) * (len(time) - npsqrt(10.0 / epsilon))
        keep_threshold_1 = 1.6 + 1.2 * delta_l

        l = 0.212 * len(time)
        sig_l = len(time) / 37.5
        keep_threshold_2 = l + 4.0 * sig_l

        # now calculate the string length
        for j in range(j_range):
            strlen += npsqrt((mod_mag_sorted[j + 1] - mod_mag_sorted[j])**2 +
                             (phase_sorted[j + 1] - phase_sorted[j])**2)

        strlen += npsqrt((mod_mag_sorted[0] - mod_mag_sorted[-1])**2 +
                         (phase_sorted[0] - phase_sorted[-1] + 1)**2)

        if ((strlen < keep_threshold_1) or (strlen < keep_threshold_2)):
            p_goodflags[i] = True

        out_periods[i] = period
        out_strlens[i] = strlen

        init_f += f_step

    return (out_periods, out_strlens, p_goodflags)
コード例 #12
0
 def sort_metadata_by_bpm(self, metadata):
     return metadata[npargsort(metadata[:, 2])]
コード例 #13
0
def arnoldi1(mps, mpo, envl, envr):
    """ 
    Calculate the eigenvalues and eigenvectors with the arnoldi algorithm
    
    Args:
        mps : 1d array of np or ctf tensors
            a list containing the mps tensor for each desired 
            state at the optimization site
        mpo : 1d array of np or ctf tensors
            a list containing the mpo tensor for each 
            operator at the optimization site
        envl : 1d array of np or ctf tensors
            a list containing the left env tensor for each
            operator at the optimization site
        envr : 1d array of np or ctf tensors
            a list containing the right env tensor for each
            operator at the optimization site

    Returns:
        E : 1d array
            a 1d array of the energy associated with each state 
            of the system
        mps : 1d array of np or ctf tensors
            a list containing the resulting mps tensor for each
            state from the optimization
        ovlp : float
            the overlap between the input guess and output state
    """
    print('ARNOLDI NOT WORKING')
    import sys
    sys.exit()
    mpiprint(6, 'Doing Arnoldi optimization routine')

    # Compute the number of states
    nStates = len(mps)
    (n1, n2, n3) = mps[0].shape

    # Make the hamiltonian function
    hop, _ = make_ham_func1(mps, mpo, envl, envr)
    hop = LinearOperator((n1 * n2 * n3, n1 * n2 * n3), matvec=hop)

    # Determine initial guess
    if USE_CTF:
        guess = to_nparray(ravel(mps[0]))
    else:
        guess = ravel(mps[0])
    #guess = np.zeros((n1*n2*n3,nStates),dtype=type(mps[0][0,0,0]))
    #for state in range(nStates):
    #    if USE_CTF:
    #        guess[:,state] = to_nparray(ravel(mps[state]))
    #    else:
    #        guess[:,state] = ravel(mps[state])

    # Send to davidson algorithm
    try:
        E, vecs = arnoldi(hop,
                          k=nStates,
                          which='SR',
                          v0=guess,
                          tol=ARNOLDI_TOL,
                          maxiter=ARNOLDI_MAX_ITER)
    except Exception as exc:
        E = exc.eigenvalues
        vecs = exc.eigenvectors
    E = -E

    # Sort results
    inds = npargsort(E)[::-1]
    E = E[inds[:nStates]]
    vecs = vecs[:, inds[:nStates]]

    # Convert vecs back to ctf if needed
    if USE_CTF: vecs = from_nparray(vecs)

    # convert vecs into original mps shape
    _mps = mps
    mps = vec2mps(vecs, mps)

    # check the overlap
    ovlp = calc_ovlp(mps, _mps)

    return E, mps, ovlp
コード例 #14
0
ファイル: transits.py プロジェクト: sakshambassi/astrobase
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
コード例 #15
0
ファイル: htls.py プロジェクト: waqasbhatti/astrobase
def tls_parallel_pfind(
        times,
        mags,
        errs,
        magsarefluxes=None,
        startp=0.1,  # search from 0.1 d to...
        endp=None,  # determine automatically from times
        tls_oversample=5,
        tls_mintransits=3,
        tls_transit_template='default',
        tls_rstar_min=0.13,
        tls_rstar_max=3.5,
        tls_mstar_min=0.1,
        tls_mstar_max=2.0,
        periodepsilon=0.1,
        nbestpeaks=5,
        sigclip=10.0,
        verbose=True,
        nworkers=None):
    """Wrapper to Hippke & Heller (2019)'s "transit least squares", which is BLS,
    but with a slightly better template (and niceties in the implementation).

    A few comments:

    * The time series must be in units of days.

    * The frequency sampling Hippke & Heller (2019) advocate for is cubic in
      frequencies, instead of linear. Ofir (2014) found that the
      linear-in-frequency sampling (which is correct for sinusoidal signal
      detection) isn't optimal for a Keplerian box signal. He gave an equation
      for "optimal" sampling. `tlsoversample` is the factor by which to
      oversample over that. The grid can be imported independently via::

        from transitleastsquares import period_grid

      The spacing equations are given here:
      https://transitleastsquares.readthedocs.io/en/latest/Python%20interface.html#period-grid

    * The boundaries of the period search are by default 0.1 day to 99% the
      baseline of times.

    Parameters
    ----------

    times,mags,errs : np.array
        The magnitude/flux time-series to search for transits.

    magsarefluxes : bool
        `transitleastsquares` requires fluxes. Therefore if magsarefluxes is
        set to false, the passed mags are converted to fluxes. All output
        dictionary vectors include fluxes, not mags.

    startp,endp : float
        The minimum and maximum periods to consider for the transit search.

    tls_oversample : int
        Factor by which to oversample the frequency grid.

    tls_mintransits : int
        Sets the `min_n_transits` kwarg for the `BoxLeastSquares.autoperiod()`
        function.

    tls_transit_template: str
        `default`, `grazing`, or `box`.

    tls_rstar_min,tls_rstar_max : float
        The range of stellar radii to consider when generating a frequency
        grid. In uniits of Rsun.

    tls_mstar_min,tls_mstar_max : float
        The range of stellar masses to consider when generating a frequency
        grid. In units of Msun.

    periodepsilon : float
        The fractional difference between successive values of 'best' periods
        when sorting by periodogram power to consider them as separate periods
        (as opposed to part of the same periodogram peak). This is used to avoid
        broad peaks in the periodogram and make sure the 'best' periods returned
        are all actually independent.

    nbestpeaks : int
        The number of 'best' peaks to return from the periodogram results,
        starting from the global maximum of the periodogram peak values.

    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.

    verbose : bool
        Kept for consistency with `periodbase` functions.

    nworkers : int or None
        The number of parallel workers to launch for period-search. If None,
        nworkers = NCPUS.

    Returns
    -------

    dict
        This function returns a dict, referred to as an `lspinfo` dict in other
        astrobase functions that operate on periodogram results. The format is
        similar to the other astrobase period-finders -- it contains the
        nbestpeaks, which is the most important thing. (But isn't entirely
        standardized.)

        Crucially, it also contains "tlsresult", which is a dictionary with
        transitleastsquares spectra (used to get the SDE as defined in the TLS
        paper), statistics, transit period, mid-time, duration, depth, SNR, and
        the "odd_even_mismatch" statistic. The full key list is::

            dict_keys(['SDE', 'SDE_raw', 'chi2_min', 'chi2red_min', 'period',
            'period_uncertainty', 'T0', 'duration', 'depth', 'depth_mean',
            'depth_mean_even', 'depth_mean_odd', 'transit_depths',
            'transit_depths_uncertainties', 'rp_rs', 'snr', 'snr_per_transit',
            'snr_pink_per_transit', 'odd_even_mismatch', 'transit_times',
            'per_transit_count', 'transit_count', 'distinct_transit_count',
            'empty_transit_count', 'FAP', 'in_transit_count',
            'after_transit_count', 'before_transit_count', 'periods',
            'power', 'power_raw', 'SR', 'chi2',
            'chi2red', 'model_lightcurve_time', 'model_lightcurve_model',
            'model_folded_phase', 'folded_y', 'folded_dy', 'folded_phase',
            'model_folded_model'])

        The descriptions are here:

        https://transitleastsquares.readthedocs.io/en/latest/Python%20interface.html#return-values

        The remaining resultdict is::

            resultdict = {
                'tlsresult':tlsresult,
                'bestperiod': the best period value in the periodogram,
                'bestlspval': the peak associated with the best period,
                'nbestpeaks': the input value of nbestpeaks,
                'nbestlspvals': nbestpeaks-size list of best period peak values,
                'nbestperiods': nbestpeaks-size list of best periods,
                'lspvals': the full array of periodogram powers,
                'periods': the full array of periods considered,
                'tlsresult': Astropy tls result object (BoxLeastSquaresResult),
                'tlsmodel': Astropy tls BoxLeastSquares object used for work,
                'method':'tls' -> the name of the period-finder method,
                'kwargs':{ dict of all of the input kwargs for record-keeping}
            }
    """

    # set NCPUS for HTLS
    if nworkers is None:
        nworkers = NCPUS

    # convert mags to fluxes because this method requires them
    if not magsarefluxes:

        LOGWARNING('transitleastsquares requires relative flux...')
        LOGWARNING('converting input mags to relative flux...')
        LOGWARNING('and forcing magsarefluxes=True...')

        mag_0, f_0 = 12.0, 1.0e4
        flux = f_0 * 10.0**(-0.4 * (mags - mag_0))
        flux /= np.nanmedian(flux)

        # if the errors are provided as mag errors, convert them to flux
        if errs is not None:
            flux_errs = flux * (errs / mags)
        else:
            flux_errs = None

        mags = flux
        errs = flux_errs

        magsarefluxes = True

    # uniform weights for errors if none given
    if errs is None:
        errs = np.ones_like(mags) * 1.0e-4

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

    stimes, smags, serrs = resort_by_time(stimes, smags, serrs)

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

        LOGERROR('no good detections for these times and mags, skipping...')
        resultdict = {
            'tlsresult': npnan,
            'bestperiod': npnan,
            'bestlspval': npnan,
            'nbestpeaks': nbestpeaks,
            'nbestinds': None,
            'nbestlspvals': None,
            'nbestperiods': None,
            'lspvals': None,
            'periods': None,
            'method': 'tls',
            'kwargs': {
                'startp': startp,
                'endp': endp,
                'tls_oversample': tls_oversample,
                'tls_ntransits': tls_mintransits,
                'tls_transit_template': tls_transit_template,
                'tls_rstar_min': tls_rstar_min,
                'tls_rstar_max': tls_rstar_max,
                'tls_mstar_min': tls_mstar_min,
                'tls_mstar_max': tls_mstar_max,
                'periodepsilon': periodepsilon,
                'nbestpeaks': nbestpeaks,
                'sigclip': sigclip,
                'magsarefluxes': magsarefluxes
            }
        }
        return resultdict

    # if the end period is not provided, set it to
    # 99% of the time baseline. (for two transits).
    if endp is None:
        endp = 0.99 * (np.nanmax(stimes) - np.nanmin(stimes))

    # run periodogram
    model = transitleastsquares(stimes, smags, serrs)
    tlsresult = model.power(use_threads=nworkers,
                            show_progress_bar=False,
                            R_star_min=tls_rstar_min,
                            R_star_max=tls_rstar_max,
                            M_star_min=tls_mstar_min,
                            M_star_max=tls_mstar_max,
                            period_min=startp,
                            period_max=endp,
                            n_transits_min=tls_mintransits,
                            transit_template=tls_transit_template,
                            oversampling_factor=tls_oversample)

    # get the peak values
    lsp = nparray(tlsresult.power)
    periods = nparray(tlsresult.periods)

    # find the nbestpeaks for the periodogram: 1. sort the lsp array by highest
    # value first 2. go down the values until we find five values that are
    # separated by at least periodepsilon in period make sure to get only the
    # finite peaks in the periodogram this is needed because tls may produce
    # infs for some peaks
    finitepeakind = npisfinite(lsp)
    finlsp = lsp[finitepeakind]
    finperiods = periods[finitepeakind]

    # make sure that finlsp has finite values before we work on it
    try:

        bestperiodind = npargmax(finlsp)

    except ValueError:

        LOGERROR('no finite periodogram values '
                 'for this mag series, skipping...')
        resultdict = {
            'tlsresult': npnan,
            'bestperiod': npnan,
            'bestlspval': npnan,
            'nbestpeaks': nbestpeaks,
            'nbestinds': None,
            'nbestlspvals': None,
            'nbestperiods': None,
            'lspvals': None,
            'periods': None,
            'method': 'tls',
            'kwargs': {
                'startp': startp,
                'endp': endp,
                'tls_oversample': tls_oversample,
                'tls_ntransits': tls_mintransits,
                'tls_transit_template': tls_transit_template,
                'tls_rstar_min': tls_rstar_min,
                'tls_rstar_max': tls_rstar_max,
                'tls_mstar_min': tls_mstar_min,
                'tls_mstar_max': tls_mstar_max,
                'periodepsilon': periodepsilon,
                'nbestpeaks': nbestpeaks,
                'sigclip': sigclip,
                'magsarefluxes': magsarefluxes
            }
        }
        return resultdict

    sortedlspind = npargsort(finlsp)[::-1]
    sortedlspperiods = finperiods[sortedlspind]
    sortedlspvals = finlsp[sortedlspind]

    # now get the nbestpeaks
    nbestperiods, nbestlspvals, nbestinds, peakcount = ([
        finperiods[bestperiodind]
    ], [finlsp[bestperiodind]], [bestperiodind], 1)
    prevperiod = sortedlspperiods[0]

    # find the best nbestpeaks in the lsp and their periods
    for period, lspval, ind in zip(sortedlspperiods, sortedlspvals,
                                   sortedlspind):

        if peakcount == nbestpeaks:
            break
        perioddiff = abs(period - prevperiod)
        bestperiodsdiff = [abs(period - x) for x in nbestperiods]

        # this ensures that this period is different from the last
        # period and from all the other existing best periods by
        # periodepsilon to make sure we jump to an entire different
        # peak in the periodogram
        if (perioddiff > (periodepsilon * prevperiod)
                and all(x > (periodepsilon * period)
                        for x in bestperiodsdiff)):
            nbestperiods.append(period)
            nbestlspvals.append(lspval)
            nbestinds.append(ind)
            peakcount = peakcount + 1

        prevperiod = period

    # generate the return dict
    resultdict = {
        'tlsresult': tlsresult,
        'bestperiod': finperiods[bestperiodind],
        'bestlspval': finlsp[bestperiodind],
        'nbestpeaks': nbestpeaks,
        'nbestinds': nbestinds,
        'nbestlspvals': nbestlspvals,
        'nbestperiods': nbestperiods,
        'lspvals': lsp,
        'periods': periods,
        'method': 'tls',
        'kwargs': {
            'startp': startp,
            'endp': endp,
            'tls_oversample': tls_oversample,
            'tls_ntransits': tls_mintransits,
            'tls_transit_template': tls_transit_template,
            'tls_rstar_min': tls_rstar_min,
            'tls_rstar_max': tls_rstar_max,
            'tls_mstar_min': tls_mstar_min,
            'tls_mstar_max': tls_mstar_max,
            'periodepsilon': periodepsilon,
            'nbestpeaks': nbestpeaks,
            'sigclip': sigclip,
            'magsarefluxes': magsarefluxes
        }
    }

    return resultdict
コード例 #16
0
def aov_periodfind(times,
                   mags,
                   errs,
                   magsarefluxes=False,
                   startp=None,
                   endp=None,
                   stepsize=1.0e-4,
                   autofreq=True,
                   normalize=True,
                   phasebinsize=0.05,
                   mindetperbin=9,
                   nbestpeaks=5,
                   periodepsilon=0.1,
                   sigclip=10.0,
                   nworkers=None,
                   verbose=True):
    '''This runs a parallelized Analysis-of-Variance (AoV) period search.

    NOTE: `normalize = True` here as recommended by Schwarzenberg-Czerny 1996,
    i.e. mags will be normalized to zero and rescaled so their variance = 1.0.

    Parameters
    ----------

    times,mags,errs : np.array
        The mag/flux time-series with associated measurement errors to run the
        period-finding on.

    magsarefluxes : bool
        If the input measurement values in `mags` and `errs` are in fluxes, set
        this to True.

    startp,endp : float or None
        The minimum and maximum periods to consider for the transit search.

    stepsize : float
        The step-size in frequency to use when constructing a frequency grid for
        the period search.

    autofreq : bool
        If this is True, the value of `stepsize` will be ignored and the
        :py:func:`astrobase.periodbase.get_frequency_grid` function will be used
        to generate a frequency grid based on `startp`, and `endp`. If these are
        None as well, `startp` will be set to 0.1 and `endp` will be set to
        `times.max() - times.min()`.

    normalize : bool
        This sets if the input time-series is normalized to 0.0 and rescaled
        such that its variance = 1.0. This is the recommended procedure by
        Schwarzenberg-Czerny 1996.

    phasebinsize : float
        The bin size in phase to use when calculating the AoV theta statistic at
        a test frequency.

    mindetperbin : int
        The minimum number of elements in a phase bin to consider it valid when
        calculating the AoV theta statistic at a test frequency.

    nbestpeaks : int
        The number of 'best' peaks to return from the periodogram results,
        starting from the global maximum of the periodogram peak values.

    periodepsilon : float
        The fractional difference between successive values of 'best' periods
        when sorting by periodogram power to consider them as separate periods
        (as opposed to part of the same periodogram peak). This is used to avoid
        broad peaks in the periodogram and make sure the 'best' periods returned
        are all actually independent.

    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.

    nworkers : int
        The number of parallel workers to use when calculating the periodogram.

    verbose : bool
        If this is True, will indicate progress and details about the frequency
        grid used for the period search.

    Returns
    -------

    dict
        This function returns a dict, referred to as an `lspinfo` dict in other
        astrobase functions that operate on periodogram results. This is a
        standardized format across all astrobase period-finders, and is of the
        form below::

            {'bestperiod': the best period value in the periodogram,
             'bestlspval': the periodogram peak associated with the best period,
             'nbestpeaks': the input value of nbestpeaks,
             'nbestlspvals': nbestpeaks-size list of best period peak values,
             'nbestperiods': nbestpeaks-size list of best periods,
             'lspvals': the full array of periodogram powers,
             'periods': the full array of periods considered,
             'method':'aov' -> the name of the period-finder method,
             'kwargs':{ dict of all of the input kwargs for record-keeping}}

    '''

    # 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:

        # get the frequencies to use
        if startp:
            endf = 1.0/startp
        else:
            # default start period is 0.1 day
            endf = 1.0/0.1

        if endp:
            startf = 1.0/endp
        else:
            # default end period is length of time series
            startf = 1.0/(stimes.max() - stimes.min())

        # if we're not using autofreq, then use the provided frequencies
        if not autofreq:
            frequencies = nparange(startf, endf, stepsize)
            if verbose:
                LOGINFO(
                    'using %s frequency points, start P = %.3f, end P = %.3f' %
                    (frequencies.size, 1.0/endf, 1.0/startf)
                )
        else:
            # this gets an automatic grid of frequencies to use
            frequencies = get_frequency_grid(stimes,
                                             minfreq=startf,
                                             maxfreq=endf)
            if verbose:
                LOGINFO(
                    'using autofreq with %s frequency points, '
                    'start P = %.3f, end P = %.3f' %
                    (frequencies.size,
                     1.0/frequencies.max(),
                     1.0/frequencies.min())
                )

        # map to parallel workers
        if (not nworkers) or (nworkers > NCPUS):
            nworkers = NCPUS
            if verbose:
                LOGINFO('using %s workers...' % nworkers)

        pool = Pool(nworkers)

        # renormalize the working mags to zero and scale them so that the
        # variance = 1 for use with our LSP functions
        if normalize:
            nmags = (smags - npmedian(smags))/npstd(smags)
        else:
            nmags = smags

        tasks = [(stimes, nmags, serrs, x, phasebinsize, mindetperbin)
                 for x in frequencies]

        lsp = pool.map(_aov_worker, tasks)

        pool.close()
        pool.join()
        del pool

        lsp = nparray(lsp)
        periods = 1.0/frequencies

        # find the nbestpeaks for the periodogram: 1. sort the lsp array by
        # highest value first 2. go down the values until we find five
        # values that are separated by at least periodepsilon in period

        # make sure to filter out non-finite values
        finitepeakind = npisfinite(lsp)
        finlsp = lsp[finitepeakind]
        finperiods = periods[finitepeakind]

        # make sure that finlsp has finite values before we work on it
        try:

            bestperiodind = npargmax(finlsp)

        except ValueError:

            LOGERROR('no finite periodogram values '
                     'for this mag series, skipping...')
            return {'bestperiod':npnan,
                    'bestlspval':npnan,
                    'nbestpeaks':nbestpeaks,
                    'nbestlspvals':None,
                    'nbestperiods':None,
                    'lspvals':None,
                    'periods':None,
                    'method':'aov',
                    'kwargs':{'startp':startp,
                              'endp':endp,
                              'stepsize':stepsize,
                              'normalize':normalize,
                              'phasebinsize':phasebinsize,
                              'mindetperbin':mindetperbin,
                              'autofreq':autofreq,
                              'periodepsilon':periodepsilon,
                              'nbestpeaks':nbestpeaks,
                              'sigclip':sigclip}}

        sortedlspind = npargsort(finlsp)[::-1]
        sortedlspperiods = finperiods[sortedlspind]
        sortedlspvals = finlsp[sortedlspind]

        # now get the nbestpeaks
        nbestperiods, nbestlspvals, peakcount = (
            [finperiods[bestperiodind]],
            [finlsp[bestperiodind]],
            1
        )
        prevperiod = sortedlspperiods[0]

        # find the best nbestpeaks in the lsp and their periods
        for period, lspval in zip(sortedlspperiods, sortedlspvals):

            if peakcount == nbestpeaks:
                break
            perioddiff = abs(period - prevperiod)
            bestperiodsdiff = [abs(period - x) for x in nbestperiods]

            # print('prevperiod = %s, thisperiod = %s, '
            #       'perioddiff = %s, peakcount = %s' %
            #       (prevperiod, period, perioddiff, peakcount))

            # this ensures that this period is different from the last
            # period and from all the other existing best periods by
            # periodepsilon to make sure we jump to an entire different peak
            # in the periodogram
            if (perioddiff > (periodepsilon*prevperiod) and
                all(x > (periodepsilon*period) for x in bestperiodsdiff)):
                nbestperiods.append(period)
                nbestlspvals.append(lspval)
                peakcount = peakcount + 1

            prevperiod = period


        return {'bestperiod':finperiods[bestperiodind],
                'bestlspval':finlsp[bestperiodind],
                'nbestpeaks':nbestpeaks,
                'nbestlspvals':nbestlspvals,
                'nbestperiods':nbestperiods,
                'lspvals':lsp,
                'periods':periods,
                'method':'aov',
                'kwargs':{'startp':startp,
                          'endp':endp,
                          'stepsize':stepsize,
                          'normalize':normalize,
                          'phasebinsize':phasebinsize,
                          'mindetperbin':mindetperbin,
                          'autofreq':autofreq,
                          'periodepsilon':periodepsilon,
                          'nbestpeaks':nbestpeaks,
                          'sigclip':sigclip}}

    else:

        LOGERROR('no good detections for these times and mags, skipping...')
        return {'bestperiod':npnan,
                'bestlspval':npnan,
                'nbestpeaks':nbestpeaks,
                'nbestlspvals':None,
                'nbestperiods':None,
                'lspvals':None,
                'periods':None,
                'method':'aov',
                'kwargs':{'startp':startp,
                          'endp':endp,
                          'stepsize':stepsize,
                          'normalize':normalize,
                          'phasebinsize':phasebinsize,
                          'mindetperbin':mindetperbin,
                          'autofreq':autofreq,
                          'periodepsilon':periodepsilon,
                          'nbestpeaks':nbestpeaks,
                          'sigclip':sigclip}}
コード例 #17
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
コード例 #18
0
 def sort_metadata_by_filename(self, metadata):
     print(npargsort(metadata[:, 0]))
     return metadata[npargsort(metadata[:, 0])]
コード例 #19
0
def pdw_period_find(times,
                    mags,
                    errs,
                    autofreq=True,
                    init_p=None,
                    end_p=None,
                    f_step=1.0e-4,
                    phasebinsize=None,
                    sigclip=10.0,
                    nworkers=None,
                    verbose=False):
    '''This is the parallel version of the function above.

    Uses the string length method in Dworetsky 1983 to calculate the period of a
    time-series of magnitude measurements and associated magnitude errors. This
    can optionally bin in phase to try to speed up the calculation.

    PARAMETERS:

    time: series of times at which mags were measured (usually some form of JD)
    mag: timeseries of magnitudes (np.array)
    err: associated errs per magnitude measurement (np.array)
    init_p, end_p: interval to search for periods between (both ends inclusive)
    f_step: step in frequency [days^-1] to use

    RETURNS:

    tuple of the following form:

    (periods (np.array),
     string_lengths (np.array),
     good_period_mask (boolean array))

    '''

    # remove nans
    find = npisfinite(times) & npisfinite(mags) & npisfinite(errs)
    ftimes, fmags, ferrs = times[find], mags[find], errs[find]

    mod_mags = (fmags - npmin(fmags)) / (2.0 *
                                         (npmax(fmags) - npmin(fmags))) - 0.25

    if len(ftimes) > 9 and len(fmags) > 9 and len(ferrs) > 9:

        # get the median and stdev = 1.483 x MAD
        median_mag = np.median(fmags)
        stddev_mag = (np.median(np.abs(fmags - median_mag))) * 1.483

        # sigclip next
        if sigclip:

            sigind = (np.abs(fmags - median_mag)) < (sigclip * stddev_mag)

            stimes = ftimes[sigind]
            smags = fmags[sigind]
            serrs = ferrs[sigind]

            LOGINFO('sigclip = %s: before = %s observations, '
                    'after = %s observations' %
                    (sigclip, len(times), len(stimes)))

        else:

            stimes = ftimes
            smags = fmags
            serrs = ferrs

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

            # get the frequencies to use
            if init_p:
                endf = 1.0 / init_p
            else:
                # default start period is 0.1 day
                endf = 1.0 / 0.1

            if end_p:
                startf = 1.0 / end_p
            else:
                # default end period is length of time series
                startf = 1.0 / (stimes.max() - stimes.min())

            # if we're not using autofreq, then use the provided frequencies
            if not autofreq:
                frequencies = np.arange(startf, endf, stepsize)
                LOGINFO(
                    'using %s frequency points, start P = %.3f, end P = %.3f' %
                    (frequencies.size, 1.0 / endf, 1.0 / startf))
            else:
                # this gets an automatic grid of frequencies to use
                frequencies = get_frequency_grid(stimes,
                                                 minfreq=startf,
                                                 maxfreq=endf)
                LOGINFO('using autofreq with %s frequency points, '
                        'start P = %.3f, end P = %.3f' %
                        (frequencies.size, 1.0 / frequencies.max(),
                         1.0 / frequencies.min()))

            # set up some internal stuff
            fold_time = npmin(ftimes)  # fold at the first time element
            j_range = len(fmags) - 1
            epsilon = 2.0 * npmean(ferrs)
            delta_l = 0.34 * (epsilon - 0.5 *
                              (epsilon**2)) * (len(ftimes) -
                                               npsqrt(10.0 / epsilon))
            keep_threshold_1 = 1.6 + 1.2 * delta_l
            l = 0.212 * len(ftimes)
            sig_l = len(ftimes) / 37.5
            keep_threshold_2 = l + 4.0 * sig_l

            # generate the tasks
            tasks = [(x, ftimes, mod_mags, fold_time, j_range,
                      keep_threshold_1, keep_threshold_2, phasebinsize)
                     for x in frequencies]

            # fire up the pool and farm out the tasks
            if (not nworkers) or (nworkers > NCPUS):
                nworkers = NCPUS
                LOGINFO('using %s workers...' % nworkers)

            pool = Pool(nworkers)
            strlen_results = pool.map(pdw_worker, tasks)
            pool.close()
            pool.join()
            del pool

            periods, strlens, goodflags = zip(*strlen_results)
            periods, strlens, goodflags = (np.array(periods),
                                           np.array(strlens),
                                           np.array(goodflags))

            strlensort = npargsort(strlens)
            nbeststrlens = strlens[strlensort[:5]]
            nbestperiods = periods[strlensort[:5]]
            nbestflags = goodflags[strlensort[:5]]
            bestperiod = nbestperiods[0]
            beststrlen = nbeststrlens[0]
            bestflag = nbestflags[0]

            return {
                'bestperiod': bestperiod,
                'beststrlen': beststrlen,
                'bestflag': bestflag,
                'nbeststrlens': nbeststrlens,
                'nbestperiods': nbestperiods,
                'nbestflags': nbestflags,
                'strlens': strlens,
                'periods': periods,
                'goodflags': goodflags
            }

        else:

            LOGERROR(
                'no good detections for these times and mags, skipping...')
            return {
                'bestperiod': npnan,
                'beststrlen': npnan,
                'bestflag': npnan,
                'nbeststrlens': None,
                'nbestperiods': None,
                'nbestflags': None,
                'strlens': None,
                'periods': None,
                'goodflags': None
            }
    else:

        LOGERROR('no good detections for these times and mags, skipping...')
        return {
            'bestperiod': npnan,
            'beststrlen': npnan,
            'bestflag': npnan,
            'nbeststrlens': None,
            'nbestperiods': None,
            'nbestflags': None,
            'strlens': None,
            'periods': None,
            'goodflags': None
        }
コード例 #20
0
def prewhiten_magseries(times,
                        mags,
                        errs,
                        whitenperiod,
                        whitenparams,
                        sigclip=3.0,
                        magsarefluxes=False,
                        plotfit=None,
                        plotfitphasedlconly=True,
                        rescaletomedian=True):
    '''Removes a periodic sinusoidal signal generated using whitenparams from
    the input magnitude time series.

    whitenparams are the Fourier amplitude and phase coefficients:

    [ampl_1, ampl_2, ampl_3, ..., ampl_X,
     pha_1, pha_2, pha_3, ..., pha_X]

    where X is the Fourier order. These are usually the output of a previous
    Fourier fit to the light curve (from varbase.lcfit.fourier_fit_magseries for
    example).

    if rescaletomedian is True, then we add back the constant median term of the
    magnitudes to the final pre-whitened mag series.

    '''

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

    median_mag = npmedian(smags)

    # phase the mag series using the given period and epoch = min(stimes)
    mintime = npmin(stimes)

    # calculate the unsorted phase, then sort it
    iphase = ((stimes - mintime) / whitenperiod - npfloor(
        (stimes - mintime) / whitenperiod))
    phasesortind = npargsort(iphase)

    # these are the final quantities to use for the Fourier fits
    phase = iphase[phasesortind]
    pmags = smags[phasesortind]
    perrs = serrs[phasesortind]

    # get the times sorted in phase order (useful to get the fit mag minimum
    # with respect to phase -- the light curve minimum)
    ptimes = stimes[phasesortind]

    # get the Fourier order
    fourierorder = int(len(whitenparams) / 2)

    # now subtract the harmonic series from the phased LC
    # these are still in phase order
    wmags = pmags - _fourier_func(whitenparams, phase, pmags)

    # resort everything by time order
    wtimeorder = npargsort(ptimes)
    wtimes = ptimes[wtimeorder]
    wphase = phase[wtimeorder]
    wmags = wmags[wtimeorder]
    werrs = perrs[wtimeorder]

    if rescaletomedian:
        wmags = wmags + median_mag

    # prepare the returndict
    returndict = {
        'wtimes': wtimes,  # these are in the new time order
        'wphase': wphase,
        'wmags': wmags,
        'werrs': werrs,
        'whitenparams': whitenparams,
        'whitenperiod': whitenperiod
    }

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

        if plotfitphasedlconly:
            plt.figure(figsize=(10, 4.8))
        else:
            plt.figure(figsize=(16, 9.6))

        if plotfitphasedlconly:

            # phased series before whitening
            plt.subplot(121)
            plt.plot(phase,
                     pmags,
                     marker='.',
                     color='k',
                     linestyle='None',
                     markersize=2.0,
                     markeredgewidth=0)

            if not magsarefluxes:
                plt.gca().invert_yaxis()
                plt.ylabel('magnitude')
            else:
                plt.ylabel('fluxes')

            plt.xlabel('phase')
            plt.title('phased LC before pre-whitening')

            # phased series after whitening
            plt.subplot(122)
            plt.plot(wphase,
                     wmags,
                     marker='.',
                     color='g',
                     linestyle='None',
                     markersize=2.0,
                     markeredgewidth=0)

            if not magsarefluxes:
                plt.gca().invert_yaxis()
                plt.ylabel('magnitude')
            else:
                plt.ylabel('fluxes')

            plt.xlabel('phase')
            plt.title('phased LC after pre-whitening')

        else:

            # time series before whitening
            plt.subplot(221)
            plt.plot(stimes,
                     smags,
                     marker='.',
                     color='k',
                     linestyle='None',
                     markersize=2.0,
                     markeredgewidth=0)

            if not magsarefluxes:
                plt.gca().invert_yaxis()
                plt.ylabel('magnitude')
            else:
                plt.ylabel('fluxes')

            plt.xlabel('JD')
            plt.title('LC before pre-whitening')

            # time series after whitening
            plt.subplot(222)
            plt.plot(wtimes,
                     wmags,
                     marker='.',
                     color='g',
                     linestyle='None',
                     markersize=2.0,
                     markeredgewidth=0)

            if not magsarefluxes:
                plt.gca().invert_yaxis()
                plt.ylabel('magnitude')
            else:
                plt.ylabel('fluxes')

            plt.xlabel('JD')
            plt.title('LC after pre-whitening with period: %.6f' %
                      whitenperiod)

            # phased series before whitening
            plt.subplot(223)
            plt.plot(phase,
                     pmags,
                     marker='.',
                     color='k',
                     linestyle='None',
                     markersize=2.0,
                     markeredgewidth=0)

            if not magsarefluxes:
                plt.gca().invert_yaxis()
                plt.ylabel('magnitude')
            else:
                plt.ylabel('fluxes')

            plt.xlabel('phase')
            plt.title('phased LC before pre-whitening')

            # phased series after whitening
            plt.subplot(224)
            plt.plot(wphase,
                     wmags,
                     marker='.',
                     color='g',
                     linestyle='None',
                     markersize=2.0,
                     markeredgewidth=0)

            if not magsarefluxes:
                plt.gca().invert_yaxis()
                plt.ylabel('magnitude')
            else:
                plt.ylabel('fluxes')

            plt.xlabel('phase')
            plt.title('phased LC after pre-whitening')

        plt.tight_layout()
        plt.savefig(plotfit, format='png', pad_inches=0.0)
        plt.close()

        if isinstance(plotfit, str) or isinstance(plotfit, strio):
            returndict['fitplotfile'] = plotfit

    return returndict