<EOL>finind = np.isfinite(times) & np.isfinite(mags) & np.isfinite(errs)<EOL>ftimes, fmags, ferrs = times[::][finind], mags[::][finind], errs[::][finind]<EOL>finalparam_arrs = []<EOL>for ep in externalparam_arrs:<EOL><INDENT>finalparam_arrs.append(ep[::][finind])<EOL><DEDENT>stimes, smags, serrs, eparams = sigclip_magseries_with_extparams(<EOL>times.copy(), mags.copy(), errs.copy(),<EOL>[x.copy() for x in externalparam_arrs],<EOL>sigclip=epdsmooth_sigclip,<EOL>magsarefluxes=magsarefluxes<EOL>)<EOL>if isinstance(epdsmooth_extraparams, dict):<EOL><INDENT>smoothedmags = epdsmooth_func(smags,<EOL>epdsmooth_windowsize,<EOL>**epdsmooth_extraparams)<EOL><DEDENT>else:<EOL><INDENT>smoothedmags = epdsmooth_func(smags,<EOL>epdsmooth_windowsize)<EOL><DEDENT>initial_coeffs = initial_coeff_guess<EOL>if objective_kwargs is not None:<EOL><INDENT>obj_func = partial(objective_func, **objective_kwargs)<EOL><DEDENT>else:<EOL><INDENT>obj_func = objective_func<EOL><DEDENT>if not optimizer_kwargs:<EOL><INDENT>optimizer_kwargs = {}<EOL><DEDENT>fit_info = optimizer_func(<EOL>obj_func,<EOL>initial_coeffs,<EOL>args=(stimes, smoothedmags, serrs, *eparams),<EOL>**optimizer_kwargs<EOL>)<EOL>if fit_info.success:<EOL><INDENT>fit_coeffs = fit_info.x<EOL>epd_mags = np.median(fmags) + obj_func(fit_coeffs,<EOL>ftimes,<EOL>fmags,<EOL>ferrs,<EOL>*finalparam_arrs)<EOL>retdict = {'<STR_LIT>':ftimes,<EOL>'<STR_LIT>':epd_mags,<EOL>'<STR_LIT>':ferrs,<EOL>'<STR_LIT>':fit_coeffs,<EOL>'<STR_LIT>':fit_info,<EOL>'<STR_LIT>':npmedian(epd_mags),<EOL>'<STR_LIT>':npmedian(npabs(epd_mags - npmedian(epd_mags)))}<EOL>return retdict<EOL><DEDENT>else:<EOL><INDENT>LOGERROR('<STR_LIT>')<EOL>return None<EOL><DEDENT>

This does EPD on a mag-series with arbitrary external parameters.

    Parameters
    ----------

    times,mags,errs : np.array
        The input mag/flux time-series to run EPD on.

    externalparam_arrs : list of np.arrays
        This is a list of ndarrays of external parameters to decorrelate
        against. These should all be the same size as `times`, `mags`, `errs`.

    initial_coeff_guess : np.array
        An array of initial fit coefficients to pass into the objective
        function.

    epdsmooth_sigclip : float or int or sequence of two floats/ints or None
        This specifies how to sigma-clip the input LC before smoothing it and
        fitting the EPD function to it. The actual LC will not be sigma-clipped.

        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.

    epdsmooth_windowsize : int
        This is the number of LC points to smooth over to generate a smoothed
        light curve that will be used to fit the EPD function.

    epdsmooth_func : Python function
        This sets the smoothing filter function to use. A Savitsky-Golay filter
        is used to smooth the light curve by default. The functions that can be
        used with this kwarg are listed in `varbase.trends`. If you want to use
        your own function, it MUST have the following signature::

                def smoothfunc(mags_array, window_size, **extraparams)

        and return a numpy array of the same size as `mags_array` with the
        smoothed time-series. Any extra params can be provided using the
        `extraparams` dict.

    epdsmooth_extraparams : dict
        This is a dict of any extra filter params to supply to the smoothing
        function.

    objective_func : Python function
        The function that calculates residuals between the model and the
        smoothed mag-series. This must have the following signature::

            def objective_func(fit_coeffs,
                               times,
                               mags,
                               errs,
                               *external_params,
                               **objective_kwargs)

        where `times`, `mags`, `errs` are arrays of the sigma-clipped and
        smoothed time-series, `fit_coeffs` is an array of EPD fit coefficients,
        `external_params` is a tuple of the passed in external parameter arrays,
        and `objective_kwargs` is a dict of any optional kwargs to pass into the
        objective function.

        This should return the value of the residual based on evaluating the
        model function (and any weights based on errs or times).

    objective_kwargs : dict or None
        A dict of kwargs to pass into the `objective_func` function.

    optimizer_func : Python function
        The function that minimizes the residual between the model and the
        smoothed mag-series using the `objective_func`. This should have a
        signature similar to one of the optimizer functions in `scipy.optimize
        <https://docs.scipy.org/doc/scipy/reference/optimize.html>`_, i.e.::

            def optimizer_func(objective_func, initial_coeffs, args=(), ...)

        and return a `scipy.optimize.OptimizeResult
        <https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.OptimizeResult.html>`_. We'll
        rely on the ``.success`` attribute to determine if the EPD fit was
        successful, and the ``.x`` attribute to get the values of the fit
        coefficients.

    optimizer_kwargs : dict or None
        A dict of kwargs to pass into the `optimizer_func` function.

    Returns
    -------

    dict
        Returns a dict of the following form::

            {'times':the input times after non-finite elems removed,
             'mags':the EPD detrended mag values (the EPD mags),
             'errs':the errs after non-finite elems removed,
             'fitcoeffs':EPD fit coefficient values,
             'fitinfo':the result returned by the optimizer function,
             'mags_median': this is the median of the EPD mags,
             'mags_mad': this is the MAD of EPD mags}


<EOL>finind = np.isfinite(times) & np.isfinite(mags) & np.isfinite(errs)<EOL>ftimes, fmags, ferrs = times[::][finind], mags[::][finind], errs[::][finind]<EOL>finalparam_arrs = []<EOL>for ep in externalparam_arrs:<EOL><INDENT>finalparam_arrs.append(ep[::][finind])<EOL><DEDENT>stimes, smags, serrs, eparams = sigclip_magseries_with_extparams(<EOL>times, mags, errs,<EOL>externalparam_arrs,<EOL>sigclip=epdsmooth_sigclip,<EOL>magsarefluxes=magsarefluxes<EOL>)<EOL>if epdsmooth:<EOL><INDENT>if isinstance(epdsmooth_extraparams, dict):<EOL><INDENT>smoothedmags = epdsmooth_func(smags,<EOL>epdsmooth_windowsize,<EOL>**epdsmooth_extraparams)<EOL><DEDENT>else:<EOL><INDENT>smoothedmags = epdsmooth_func(smags,<EOL>epdsmooth_windowsize)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>smoothedmags = smags<EOL><DEDENT>if isinstance(rf_extraparams, dict):<EOL><INDENT>RFR = RandomForestRegressor(n_estimators=rf_ntrees,<EOL>**rf_extraparams)<EOL><DEDENT>else:<EOL><INDENT>RFR = RandomForestRegressor(n_estimators=rf_ntrees)<EOL><DEDENT>features = np.column_stack(eparams)<EOL>if rf_subsample < <NUM_LIT:1.0>:<EOL><INDENT>featureindices = np.arange(smoothedmags.size)<EOL>training_indices = np.sort(<EOL>npr.choice(featureindices,<EOL>size=int(rf_subsample*smoothedmags.size),<EOL>replace=False)<EOL>)<EOL><DEDENT>else:<EOL><INDENT>training_indices = np.arange(smoothedmags.size)<EOL><DEDENT>RFR.fit(features[training_indices,:], smoothedmags[training_indices])<EOL>flux_corrections = RFR.predict(np.column_stack(finalparam_arrs))<EOL>corrected_fmags = npmedian(fmags) + fmags - flux_corrections<EOL>retdict = {'<STR_LIT>':ftimes,<EOL>'<STR_LIT>':corrected_fmags,<EOL>'<STR_LIT>':ferrs,<EOL>'<STR_LIT>':RFR.feature_importances_,<EOL>'<STR_LIT>':RFR,<EOL>'<STR_LIT>':npmedian(corrected_fmags),<EOL>'<STR_LIT>':npmedian(npabs(corrected_fmags -<EOL>npmedian(corrected_fmags)))}<EOL>return retdict<EOL>

This uses a `RandomForestRegressor` to de-correlate the given magseries.

    Parameters
    ----------

    times,mags,errs : np.array
        The input mag/flux time-series to run EPD on.

    externalparam_arrs : list of np.arrays
        This is a list of ndarrays of external parameters to decorrelate
        against. These should all be the same size as `times`, `mags`, `errs`.

    epdsmooth : bool
        If True, sets the training LC for the RandomForestRegress to be a
        smoothed version of the sigma-clipped light curve provided in `times`,
        `mags`, `errs`.

    epdsmooth_sigclip : float or int or sequence of two floats/ints or None
        This specifies how to sigma-clip the input LC before smoothing it and
        fitting the EPD function to it. The actual LC will not be sigma-clipped.

        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.

    epdsmooth_windowsize : int
        This is the number of LC points to smooth over to generate a smoothed
        light curve that will be used to fit the EPD function.

    epdsmooth_func : Python function
        This sets the smoothing filter function to use. A Savitsky-Golay filter
        is used to smooth the light curve by default. The functions that can be
        used with this kwarg are listed in `varbase.trends`. If you want to use
        your own function, it MUST have the following signature::

                def smoothfunc(mags_array, window_size, **extraparams)

        and return a numpy array of the same size as `mags_array` with the
        smoothed time-series. Any extra params can be provided using the
        `extraparams` dict.

    epdsmooth_extraparams : dict
        This is a dict of any extra filter params to supply to the smoothing
        function.

    rf_subsample : float
        Defines the fraction of the size of the `mags` array to use for
        training the random forest regressor.

    rf_ntrees : int
        This is the number of trees to use for the `RandomForestRegressor`.

    rf_extraprams : dict
        This is a dict of any extra kwargs to provide to the
        `RandomForestRegressor` instance used.

    Returns
    -------

    dict
        Returns a dict with decorrelated mags and the usual info from the
        `RandomForestRegressor`: variable importances, etc.


def _autocorr_func1(mags, lag, maglen, magmed, magstd):

lagindex = nparange(<NUM_LIT:1>,maglen-lag)<EOL>products = (mags[lagindex] - magmed) * (mags[lagindex+lag] - magmed)<EOL>acorr = (<NUM_LIT:1.0>/((maglen - lag)*magstd)) * npsum(products)<EOL>return acorr<EOL>

Calculates the autocorr of mag series for specific lag.

    This version of the function is taken from: Kim et al. (`2011
    <https://dx.doi.org/10.1088/0004-637X/735/2/68>`_)

    Parameters
    ----------

    mags : np.array
        This is the magnitudes array. MUST NOT have any nans.

    lag : float
        The specific lag value to calculate the auto-correlation for. This MUST
        be less than total number of observations in `mags`.

    maglen : int
        The number of elements in the `mags` array.

    magmed : float
        The median of the `mags` array.

    magstd : float
        The standard deviation of the `mags` array.

    Returns
    -------

    float
        The auto-correlation at this specific `lag` value.


def _autocorr_func2(mags, lag, maglen, magmed, magstd):

lagindex = nparange(<NUM_LIT:0>,maglen-lag)<EOL>products = (mags[lagindex] - magmed) * (mags[lagindex+lag] - magmed)<EOL>autocovarfunc = npsum(products)/lagindex.size<EOL>varfunc = npsum(<EOL>(mags[lagindex] - magmed)*(mags[lagindex] - magmed)<EOL>)/mags.size<EOL>acorr = autocovarfunc/varfunc<EOL>return acorr<EOL>

This is an alternative function to calculate the autocorrelation.

This version is from (first definition):

https://en.wikipedia.org/wiki/Correlogram#Estimation_of_autocorrelations

Parameters
----------

mags : np.array
    This is the magnitudes array. MUST NOT have any nans.

lag : float
    The specific lag value to calculate the auto-correlation for. This MUST
    be less than total number of observations in `mags`.

maglen : int
    The number of elements in the `mags` array.

magmed : float
    The median of the `mags` array.

magstd : float
    The standard deviation of the `mags` array.

Returns
-------

float
    The auto-correlation at this specific `lag` value.


def _autocorr_func3(mags, lag, maglen, magmed, magstd):

<EOL>result = npcorrelate(mags, mags, mode='<STR_LIT>')<EOL>result = result / npmax(result)<EOL>return result[int(result.size / <NUM_LIT:2>):]<EOL>

This is yet another alternative to calculate the autocorrelation.

Taken from: `Bayesian Methods for Hackers by Cameron Pilon <http://nbviewer.jupyter.org/github/CamDavidsonPilon/Probabilistic-Programming-and-Bayesian-Methods-for-Hackers/blob/master/Chapter3_MCMC/Chapter3.ipynb#Autocorrelation>`_

(This should be the fastest method to calculate ACFs.)

Parameters
----------

mags : np.array
    This is the magnitudes array. MUST NOT have any nans.

lag : float
    The specific lag value to calculate the auto-correlation for. This MUST
    be less than total number of observations in `mags`.

maglen : int
    The number of elements in the `mags` array.

magmed : float
    The median of the `mags` array.

magstd : float
    The standard deviation of the `mags` array.

Returns
-------

float
    The auto-correlation at this specific `lag` value.


<EOL>interpolated = fill_magseries_gaps(times, mags, errs,<EOL>fillgaps=fillgaps,<EOL>forcetimebin=forcetimebin,<EOL>sigclip=sigclip,<EOL>magsarefluxes=magsarefluxes,<EOL>filterwindow=filterwindow,<EOL>verbose=verbose)<EOL>if not interpolated:<EOL><INDENT>print('<STR_LIT>')<EOL>return None<EOL><DEDENT>itimes, imags = interpolated['<STR_LIT>'], interpolated['<STR_LIT>'],<EOL>if maxlags:<EOL><INDENT>lags = nparange(<NUM_LIT:0>, maxlags)<EOL><DEDENT>else:<EOL><INDENT>lags = nparange(itimes.size)<EOL><DEDENT>series_stdev = <NUM_LIT>*npmedian(npabs(imags))<EOL>if func != _autocorr_func3:<EOL><INDENT>autocorr = nparray([func(imags, x, imags.size, <NUM_LIT:0.0>, series_stdev)<EOL>for x in lags])<EOL><DEDENT>else:<EOL><INDENT>autocorr = _autocorr_func3(imags, lags[<NUM_LIT:0>], imags.size,<EOL><NUM_LIT:0.0>, series_stdev)<EOL>if maxlags is not None:<EOL><INDENT>autocorr = autocorr[:maxlags]<EOL><DEDENT><DEDENT>interpolated.update({'<STR_LIT>':itimes.min(),<EOL>'<STR_LIT>':lags,<EOL>'<STR_LIT>':autocorr})<EOL>return interpolated<EOL>

This calculates the ACF of a light curve.

    This will pre-process the light curve to fill in all the gaps and normalize
    everything to zero. If `fillgaps = 'noiselevel'`, fills the gaps with the
    noise level obtained via the procedure above. If `fillgaps = 'nan'`, fills
    the gaps with `np.nan`.

    Parameters
    ----------

    times,mags,errs : np.array
        The measurement time-series and associated errors.

    maxlags : int
        The maximum number of lags to calculate.

    func : Python function
        This is a function to calculate the lags.

    fillgaps : 'noiselevel' or float
        This sets what to use to fill in gaps in the time series. If this is
        'noiselevel', will smooth the light curve using a point window size of
        `filterwindow` (this should be an odd integer), subtract the smoothed LC
        from the actual LC and estimate the RMS. This RMS will be used to fill
        in the gaps. Other useful values here are 0.0, and npnan.

    filterwindow : int
        The light curve's smoothing filter window size to use if
        `fillgaps='noiselevel`'.

    forcetimebin : None or float
        This is used to force a particular cadence in the light curve other than
        the automatically determined cadence. This effectively rebins the light
        curve to this cadence. This should be in the same time units as `times`.

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

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

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

    magsarefluxes : bool
        If your input measurements in `mags` are actually fluxes instead of
        mags, set this is True.

    verbose : bool
        If True, will indicate progress and report errors.

    Returns
    -------

    dict
        A dict of the following form is returned::

            {'itimes': the interpolated time values after gap-filling,
             'imags': the interpolated mag/flux values after gap-filling,
             'ierrs': the interpolated mag/flux values after gap-filling,
             'cadence': the cadence of the output mag/flux time-series,
             'minitime': the minimum value of the interpolated times array,
             'lags': the lags used to calculate the auto-correlation function,
             'acf': the value of the ACF at each lag used}


stimes, smags, serrs = sigclip_magseries(times, mags, errs,<EOL>sigclip=sigclip,<EOL>magsarefluxes=magsarefluxes)<EOL>median_mag = np.median(smags)<EOL>mintime = np.min(stimes)<EOL>iphase = (<EOL>(stimes - mintime)/whitenperiod -<EOL>np.floor((stimes - mintime)/whitenperiod)<EOL>)<EOL>phasesortind = np.argsort(iphase)<EOL>phase = iphase[phasesortind]<EOL>pmags = smags[phasesortind]<EOL>perrs = serrs[phasesortind]<EOL>ptimes = stimes[phasesortind]<EOL>wmags = pmags - _fourier_func(whitenparams, phase, pmags)<EOL>wtimeorder = np.argsort(ptimes)<EOL>wtimes = ptimes[wtimeorder]<EOL>wphase = phase[wtimeorder]<EOL>wmags = wmags[wtimeorder]<EOL>werrs = perrs[wtimeorder]<EOL>if rescaletomedian:<EOL><INDENT>wmags = wmags + median_mag<EOL><DEDENT>returndict = {'<STR_LIT>':wtimes,  <EOL>'<STR_LIT>':wphase,<EOL>'<STR_LIT>':wmags,<EOL>'<STR_LIT>':werrs,<EOL>'<STR_LIT>':whitenparams,<EOL>'<STR_LIT>':whitenperiod}<EOL>if plotfit and (isinstance(plotfit, str) or isinstance(plotfit, Strio)):<EOL><INDENT>if plotfitphasedlconly:<EOL><INDENT>plt.figure(figsize=(<NUM_LIT:10>,<NUM_LIT>))<EOL><DEDENT>else:<EOL><INDENT>plt.figure(figsize=(<NUM_LIT:16>,<NUM_LIT>))<EOL><DEDENT>if plotfitphasedlconly:<EOL><INDENT>plt.subplot(<NUM_LIT>)<EOL>plt.plot(phase,pmags,<EOL>marker='<STR_LIT:.>',<EOL>color='<STR_LIT:k>',<EOL>linestyle='<STR_LIT:None>',<EOL>markersize=<NUM_LIT>,<EOL>markeredgewidth=<NUM_LIT:0>)<EOL>if not magsarefluxes:<EOL><INDENT>plt.gca().invert_yaxis()<EOL>plt.ylabel('<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>plt.ylabel('<STR_LIT>')<EOL><DEDENT>plt.xlabel('<STR_LIT>')<EOL>plt.title('<STR_LIT>')<EOL>plt.subplot(<NUM_LIT>)<EOL>plt.plot(wphase,wmags,<EOL>marker='<STR_LIT:.>',<EOL>color='<STR_LIT:g>',<EOL>linestyle='<STR_LIT:None>',<EOL>markersize=<NUM_LIT>,<EOL>markeredgewidth=<NUM_LIT:0>)<EOL>if not magsarefluxes:<EOL><INDENT>plt.gca().invert_yaxis()<EOL>plt.ylabel('<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>plt.ylabel('<STR_LIT>')<EOL><DEDENT>plt.xlabel('<STR_LIT>')<EOL>plt.title('<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>plt.subplot(<NUM_LIT>)<EOL>plt.plot(stimes,smags,<EOL>marker='<STR_LIT:.>',<EOL>color='<STR_LIT:k>',<EOL>linestyle='<STR_LIT:None>',<EOL>markersize=<NUM_LIT>,<EOL>markeredgewidth=<NUM_LIT:0>)<EOL>if not magsarefluxes:<EOL><INDENT>plt.gca().invert_yaxis()<EOL>plt.ylabel('<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>plt.ylabel('<STR_LIT>')<EOL><DEDENT>plt.xlabel('<STR_LIT>')<EOL>plt.title('<STR_LIT>')<EOL>plt.subplot(<NUM_LIT>)<EOL>plt.plot(wtimes,wmags,<EOL>marker='<STR_LIT:.>',<EOL>color='<STR_LIT:g>',<EOL>linestyle='<STR_LIT:None>',<EOL>markersize=<NUM_LIT>,<EOL>markeredgewidth=<NUM_LIT:0>)<EOL>if not magsarefluxes:<EOL><INDENT>plt.gca().invert_yaxis()<EOL>plt.ylabel('<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>plt.ylabel('<STR_LIT>')<EOL><DEDENT>plt.xlabel('<STR_LIT>')<EOL>plt.title('<STR_LIT>' % whitenperiod)<EOL>plt.subplot(<NUM_LIT>)<EOL>plt.plot(phase,pmags,<EOL>marker='<STR_LIT:.>',<EOL>color='<STR_LIT:k>',<EOL>linestyle='<STR_LIT:None>',<EOL>markersize=<NUM_LIT>,<EOL>markeredgewidth=<NUM_LIT:0>)<EOL>if not magsarefluxes:<EOL><INDENT>plt.gca().invert_yaxis()<EOL>plt.ylabel('<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>plt.ylabel('<STR_LIT>')<EOL><DEDENT>plt.xlabel('<STR_LIT>')<EOL>plt.title('<STR_LIT>')<EOL>plt.subplot(<NUM_LIT>)<EOL>plt.plot(wphase,wmags,<EOL>marker='<STR_LIT:.>',<EOL>color='<STR_LIT:g>',<EOL>linestyle='<STR_LIT:None>',<EOL>markersize=<NUM_LIT>,<EOL>markeredgewidth=<NUM_LIT:0>)<EOL>if not magsarefluxes:<EOL><INDENT>plt.gca().invert_yaxis()<EOL>plt.ylabel('<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>plt.ylabel('<STR_LIT>')<EOL><DEDENT>plt.xlabel('<STR_LIT>')<EOL>plt.title('<STR_LIT>')<EOL><DEDENT>plt.tight_layout()<EOL>plt.savefig(plotfit, format='<STR_LIT>', pad_inches=<NUM_LIT:0.0>)<EOL>plt.close()<EOL>if isinstance(plotfit, str) or isinstance(plotfit, Strio):<EOL><INDENT>returndict['<STR_LIT>'] = plotfit<EOL><DEDENT><DEDENT>return returndict<EOL>

Removes a periodic sinusoidal signal generated using whitenparams from
    the input magnitude time series.

    Parameters
    ----------

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

    whitenperiod : float
        The period of the sinusoidal signal to remove.

    whitenparams : list of floats
        This contains the Fourier amplitude and phase coefficients of the
        sinusoidal signal to remove::

            [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
        :py:func:`astrobase.lcfit.sinusoidal.fourier_fit_magseries` for
        example).

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

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

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

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

    plotfit : str or False
        If this is a string, this function will make a plot showing the effect
        of the pre-whitening on the mag/flux time-series and write the plot to
        the path specified here.

    plotfitphasedlconly : bool
        If True, will plot only the phased LC for showing the effect of
        pre-whitening, and skip plotting the unphased LC.

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

    Returns
    -------

    dict
        Returns a dict of the form::

            {'wtimes':times array after pre-whitening,
             'wphase':phase array after pre-whitening,
             'wmags':mags array after pre-whitening,
             'werrs':errs array after pre-whitening,
             'whitenparams':the input pre-whitening params used,
             'whitenperiod':the input pre-whitening period used,
             'fitplotfile':the output plot file if plotfit was set}


stimes, smags, serrs = sigclip_magseries(times, mags, errs,<EOL>sigclip=sigclip,<EOL>magsarefluxes=magsarefluxes)<EOL>gls = pgen_lsp(stimes, smags, serrs,<EOL>magsarefluxes=magsarefluxes,<EOL>startp=startp_gls,<EOL>endp=endp_gls,<EOL>autofreq=autofreq,<EOL>sigclip=sigclip,<EOL>stepsize=stepsize,<EOL>nworkers=nworkers)<EOL>LOGINFO('<STR_LIT>' % (<NUM_LIT:0>, gls['<STR_LIT>']))<EOL>if plotfits and isinstance(plotfits, str):<EOL><INDENT>plt.figure(figsize=(<NUM_LIT:20>,<NUM_LIT:6>*nbestpeaks))<EOL>nplots = nbestpeaks + <NUM_LIT:1><EOL>plt.subplot(nplots,<NUM_LIT:3>,<NUM_LIT:1>)<EOL>plt.plot(gls['<STR_LIT>'],gls['<STR_LIT>'])<EOL>plt.xlabel('<STR_LIT>')<EOL>plt.ylabel('<STR_LIT>')<EOL>plt.xscale('<STR_LIT>')<EOL>plt.title('<STR_LIT>' % gls['<STR_LIT>'])<EOL>plt.subplot(nplots,<NUM_LIT:3>,<NUM_LIT:2>)<EOL>plt.plot(stimes, smags,<EOL>linestyle='<STR_LIT:none>', marker='<STR_LIT:o>',ms=<NUM_LIT:1.0>,rasterized=True)<EOL>if not magsarefluxes:<EOL><INDENT>plt.gca().invert_yaxis()<EOL>plt.ylabel('<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>plt.ylabel('<STR_LIT>')<EOL><DEDENT>plt.xlabel('<STR_LIT>')<EOL>plt.title('<STR_LIT>')<EOL>plt.subplot(nplots,<NUM_LIT:3>,<NUM_LIT:3>)<EOL>phased = phase_magseries(stimes, smags,<EOL>gls['<STR_LIT>'], stimes.min())<EOL>plt.plot(phased['<STR_LIT>'], phased['<STR_LIT>'],<EOL>linestyle='<STR_LIT:none>', marker='<STR_LIT:o>',ms=<NUM_LIT:1.0>,rasterized=True)<EOL>if not magsarefluxes:<EOL><INDENT>plt.ylabel('<STR_LIT>')<EOL>plt.gca().invert_yaxis()<EOL><DEDENT>else:<EOL><INDENT>plt.ylabel('<STR_LIT>')<EOL><DEDENT>plt.xlabel('<STR_LIT>')<EOL>plt.title('<STR_LIT>' % gls['<STR_LIT>'])<EOL><DEDENT>wtimes, wmags, werrs = stimes, smags, serrs<EOL>wperiod = gls['<STR_LIT>']<EOL>bestperiods = []<EOL>for fitind in range(nbestpeaks):<EOL><INDENT>wfseries = fourier_fit_magseries(wtimes, wmags, werrs, wperiod,<EOL>fourierorder=fourierorder,<EOL>fourierparams=initfparams,<EOL>magsarefluxes=magsarefluxes,<EOL>sigclip=sigclip)<EOL>wffitparams = wfseries['<STR_LIT>']['<STR_LIT>']<EOL>wseries = prewhiten_magseries(wtimes, wmags, werrs,<EOL>wperiod,<EOL>wffitparams,<EOL>magsarefluxes=magsarefluxes,<EOL>sigclip=sigclip)<EOL>LOGINFO('<STR_LIT>' % (fitind+<NUM_LIT:1>, wperiod))<EOL>bestperiods.append(wperiod)<EOL>wtimes, wmags, werrs = (<EOL>wseries['<STR_LIT>'], wseries['<STR_LIT>'], wseries['<STR_LIT>']<EOL>)<EOL>wgls = pgen_lsp(wtimes, wmags, werrs,<EOL>magsarefluxes=magsarefluxes,<EOL>startp=startp_gls,<EOL>endp=endp_gls,<EOL>autofreq=autofreq,<EOL>sigclip=sigclip,<EOL>stepsize=stepsize,<EOL>nworkers=nworkers)<EOL>wperiod = wgls['<STR_LIT>']<EOL>bestperiods.append(wperiod)<EOL>if plotfits and isinstance(plotfits, str):<EOL><INDENT>plt.subplot(nplots,<NUM_LIT:3>,<NUM_LIT:4>+fitind*<NUM_LIT:3>)<EOL>plt.plot(wgls['<STR_LIT>'],wgls['<STR_LIT>'])<EOL>plt.xlabel('<STR_LIT>')<EOL>plt.ylabel('<STR_LIT>')<EOL>plt.xscale('<STR_LIT>')<EOL>plt.title('<STR_LIT>' % (fitind+<NUM_LIT:1>,<EOL>wgls['<STR_LIT>']))<EOL>plt.subplot(nplots,<NUM_LIT:3>,<NUM_LIT:5>+fitind*<NUM_LIT:3>)<EOL>plt.plot(wtimes, wmags,<EOL>linestyle='<STR_LIT:none>', marker='<STR_LIT:o>',ms=<NUM_LIT:1.0>,rasterized=True)<EOL>if not magsarefluxes:<EOL><INDENT>plt.gca().invert_yaxis()<EOL>plt.ylabel('<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>plt.ylabel('<STR_LIT>')<EOL><DEDENT>plt.xlabel('<STR_LIT>')<EOL>plt.title('<STR_LIT>')<EOL>plt.subplot(nplots,<NUM_LIT:3>,<NUM_LIT:6>+fitind*<NUM_LIT:3>)<EOL>wphased = phase_magseries(wtimes, wmags,<EOL>wperiod, stimes.min())<EOL>plt.plot(wphased['<STR_LIT>'], wphased['<STR_LIT>'],<EOL>linestyle='<STR_LIT:none>', marker='<STR_LIT:o>',ms=<NUM_LIT:1.0>,rasterized=True)<EOL>if not magsarefluxes:<EOL><INDENT>plt.ylabel('<STR_LIT>')<EOL>plt.gca().invert_yaxis()<EOL><DEDENT>else:<EOL><INDENT>plt.ylabel('<STR_LIT>')<EOL><DEDENT>plt.xlabel('<STR_LIT>')<EOL>plt.title('<STR_LIT>' % wperiod)<EOL><DEDENT><DEDENT>if plotfits and isinstance(plotfits, str):<EOL><INDENT>plt.subplots_adjust(hspace=<NUM_LIT>,wspace=<NUM_LIT>)<EOL>plt.savefig(plotfits, bbox_inches='<STR_LIT>')<EOL>plt.close('<STR_LIT:all>')<EOL>return bestperiods, os.path.abspath(plotfits)<EOL><DEDENT>else:<EOL><INDENT>return bestperiods<EOL><DEDENT>

Iterative pre-whitening of a magnitude series using the L-S periodogram.

    This finds the best period, fits a fourier series with the best period, then
    whitens the time series with the best period, and repeats until `nbestpeaks`
    are done.

    Parameters
    ----------

    times,mags,errs : np.array
        The input mag/flux time-series to iteratively pre-whiten.

    fourierorder : int
        The Fourier order of the sinusoidal signal to fit to the time-series and
        iteratively remove.

    initfparams : list or None
        If this is provided, should be a list of Fourier amplitudes and phases
        in the following format::

            [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
        :py:func:`astrobase.lcfit.sinusoidal.fourier_fit_magseries` for
        example). You MUST provide ONE of `fourierorder` and `initfparams`, but
        not both. If both are provided or both are None, a sinusoidal signal of
        Fourier order 3 will be used by default.

    startp_gls, endp_gls : float or None
        If these are provided, will serve as input to the Generalized
        Lomb-Scargle function that will attempt to find the best `nbestpeaks`
        periods in the time-series. These set the minimum and maximum period to
        search for in the time-series.

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

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

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

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

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

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

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

    plotfits : None or str
        If this is a str, should indicate the file to which a plot of the
        successive iterations of pre-whitening will be written to. This will
        contain a row of plots indicating the before/after states of the light
        curves for each round of pre-whitening.

    Returns
    -------

    (bestperiods, plotfile) : tuple
        This returns a list of the best periods (with the "highest" peak in the
        periodogram) after each round of pre-whitening is done. If plotfit is a
        str, will also return the path to the generated plot file.


stimes, smags, serrs = sigclip_magseries(times, mags, errs,<EOL>sigclip=sigclip,<EOL>magsarefluxes=magsarefluxes)<EOL>phases = (<EOL>(stimes - signalepoch)/signalperiod -<EOL>np.floor((stimes - signalepoch)/signalperiod)<EOL>)<EOL>masks = np.array([(np.abs(phases - x) > maskphaselength)<EOL>for x in maskphases])<EOL>masks = np.all(masks,axis=<NUM_LIT:0>)<EOL>mphases = phases[masks]<EOL>mtimes = stimes[masks]<EOL>mmags = smags[masks]<EOL>merrs = serrs[masks]<EOL>returndict = {'<STR_LIT>':mphases,<EOL>'<STR_LIT>':mtimes,<EOL>'<STR_LIT>':mmags,<EOL>'<STR_LIT>':merrs}<EOL>if plotfit and isinstance(plotfit, str) or isinstance(plotfit, Strio):<EOL><INDENT>if plotfitphasedlconly:<EOL><INDENT>plt.figure(figsize=(<NUM_LIT:10>,<NUM_LIT>))<EOL><DEDENT>else:<EOL><INDENT>plt.figure(figsize=(<NUM_LIT:16>,<NUM_LIT>))<EOL><DEDENT>if plotfitphasedlconly:<EOL><INDENT>plt.subplot(<NUM_LIT>)<EOL>plt.plot(phases,smags,<EOL>marker='<STR_LIT:.>',<EOL>color='<STR_LIT:k>',<EOL>linestyle='<STR_LIT:None>',<EOL>markersize=<NUM_LIT>,<EOL>markeredgewidth=<NUM_LIT:0>)<EOL>if not magsarefluxes:<EOL><INDENT>plt.gca().invert_yaxis()<EOL>plt.ylabel('<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>plt.ylabel('<STR_LIT>')<EOL><DEDENT>plt.xlabel('<STR_LIT>')<EOL>plt.title('<STR_LIT>')<EOL>plt.subplot(<NUM_LIT>)<EOL>plt.plot(mphases,mmags,<EOL>marker='<STR_LIT:.>',<EOL>color='<STR_LIT:g>',<EOL>linestyle='<STR_LIT:None>',<EOL>markersize=<NUM_LIT>,<EOL>markeredgewidth=<NUM_LIT:0>)<EOL>if not magsarefluxes:<EOL><INDENT>plt.gca().invert_yaxis()<EOL>plt.ylabel('<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>plt.ylabel('<STR_LIT>')<EOL><DEDENT>plt.xlabel('<STR_LIT>')<EOL>plt.title('<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>plt.subplot(<NUM_LIT>)<EOL>plt.plot(stimes,smags,<EOL>marker='<STR_LIT:.>',<EOL>color='<STR_LIT:k>',<EOL>linestyle='<STR_LIT:None>',<EOL>markersize=<NUM_LIT>,<EOL>markeredgewidth=<NUM_LIT:0>)<EOL>if not magsarefluxes:<EOL><INDENT>plt.gca().invert_yaxis()<EOL>plt.ylabel('<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>plt.ylabel('<STR_LIT>')<EOL><DEDENT>plt.xlabel('<STR_LIT>')<EOL>plt.title('<STR_LIT>')<EOL>plt.subplot(<NUM_LIT>)<EOL>plt.plot(mtimes,mmags,<EOL>marker='<STR_LIT:.>',<EOL>color='<STR_LIT:g>',<EOL>linestyle='<STR_LIT:None>',<EOL>markersize=<NUM_LIT>,<EOL>markeredgewidth=<NUM_LIT:0>)<EOL>if not magsarefluxes:<EOL><INDENT>plt.gca().invert_yaxis()<EOL>plt.ylabel('<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>plt.ylabel('<STR_LIT>')<EOL><DEDENT>plt.xlabel('<STR_LIT>')<EOL>plt.title('<STR_LIT>')<EOL>plt.subplot(<NUM_LIT>)<EOL>plt.plot(phases,smags,<EOL>marker='<STR_LIT:.>',<EOL>color='<STR_LIT:k>',<EOL>linestyle='<STR_LIT:None>',<EOL>markersize=<NUM_LIT>,<EOL>markeredgewidth=<NUM_LIT:0>)<EOL>if not magsarefluxes:<EOL><INDENT>plt.gca().invert_yaxis()<EOL>plt.ylabel('<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>plt.ylabel('<STR_LIT>')<EOL><DEDENT>plt.xlabel('<STR_LIT>')<EOL>plt.title('<STR_LIT>')<EOL>plt.subplot(<NUM_LIT>)<EOL>plt.plot(mphases,mmags,<EOL>marker='<STR_LIT:.>',<EOL>color='<STR_LIT:g>',<EOL>linestyle='<STR_LIT:None>',<EOL>markersize=<NUM_LIT>,<EOL>markeredgewidth=<NUM_LIT:0>)<EOL>if not magsarefluxes:<EOL><INDENT>plt.gca().invert_yaxis()<EOL>plt.ylabel('<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>plt.ylabel('<STR_LIT>')<EOL><DEDENT>plt.xlabel('<STR_LIT>')<EOL>plt.title('<STR_LIT>')<EOL><DEDENT>plt.tight_layout()<EOL>plt.savefig(plotfit, format='<STR_LIT>', pad_inches=<NUM_LIT:0.0>)<EOL>plt.close()<EOL>if isinstance(plotfit, str) or isinstance(plotfit, Strio):<EOL><INDENT>returndict['<STR_LIT>'] = plotfit<EOL><DEDENT><DEDENT>return returndict<EOL>

This removes repeating signals in the magnitude time series.

    Useful for masking planetary transit signals in light curves to search for
    other variability.

    A small worked example of using this and `prewhiten_magseries` above:

    https://github.com/waqasbhatti/astrobase/issues/77#issuecomment-463803558

    Parameters
    ----------

    times,mags,errs : np.array
        The input mag/flux time-series to run the masking on.

    signalperiod : float
        The period of the signal to mask.

    signalepoch : float
        The epoch of the signal to mask.

    magsarefluxes : bool
        Set to True if `mags` is actually an array of fluxes.

    maskphases : sequence of floats
        This defines which phase values will be masked. For each item in this
        sequence, this function will mask a length of phase given by
        `maskphaselength` centered on each `maskphases` value, and remove all LC
        points in these regions from the light curve.

    maskphaselength : float
        The length in phase to mask for each phase value provided in
        `maskphases`.

    plotfit : str or None
        If provided as a str, indicates the output plot file.

    plotfitphasedlconly : bool
        If True, will only plot the effect of masking the signal as requested on
        the phased LC. If False, will also plot the unphased LC.

    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.


modelmags, ftimes, fmags, ferrs = flares.flare_model(<EOL>flareparams,<EOL>times,<EOL>mags,<EOL>errs<EOL>)<EOL>return {'<STR_LIT>':times,<EOL>'<STR_LIT>':mags + modelmags,<EOL>'<STR_LIT>':errs,<EOL>'<STR_LIT>':flareparams}<EOL>

This adds a flare model function to the input magnitude/flux time-series.

    Parameters
    ----------

    flareparams : list of float
        This defines the flare model::

            [amplitude,
             flare_peak_time,
             rise_gaussian_stdev,
             decay_time_constant]

        where:

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

        `flare_peak_time`: time at which the flare maximum happens.

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

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

    times,mags,errs : np.array
        The input time-series of measurements and associated errors for which
        the model will be generated. The times will be used to generate
        model mags.

    magsarefluxes : bool
        Sets the correct direction of the flare amplitude (+ve) for fluxes if
        True and for mags (-ve) if False.

    Returns
    -------

    dict
        A dict of the form below is returned::

        {'times': the original times array
         'mags': the original mags + the flare model mags evaluated at times,
         'errs': the original errs array,
         'flareparams': the input list of flare params}


<EOL>if errs is None:<EOL><INDENT>errs = <NUM_LIT>*mags<EOL><DEDENT>finiteind = np.isfinite(times) & np.isfinite(mags) & np.isfinite(errs)<EOL>ftimes = times[finiteind]<EOL>fmags = mags[finiteind]<EOL>ferrs = errs[finiteind]<EOL>smoothed = savgol_filter(fmags,<EOL>smoothbinsize,<EOL>savgol_polyorder,<EOL>**savgol_kwargs)<EOL>subtracted = fmags - smoothed<EOL>series_mad = np.median(np.abs(subtracted))<EOL>series_stdev = <NUM_LIT>*series_mad<EOL>if magsarefluxes:<EOL><INDENT>extind = np.where(subtracted > (flare_minsigma*series_stdev))<EOL><DEDENT>else:<EOL><INDENT>extind = np.where(subtracted < (-flare_minsigma*series_stdev))<EOL><DEDENT>if extind and extind[<NUM_LIT:0>]:<EOL><INDENT>extrema_indices = extind[<NUM_LIT:0>]<EOL>flaregroups = []<EOL>for ind, extrema_index in enumerate(extrema_indices):<EOL><INDENT>pass<EOL><DEDENT><DEDENT>

This finds flares in time series using the method in Walkowicz+ 2011.

    FIXME: finish this.

    Parameters
    ----------

    times,mags,errs : np.array
        The input time-series to find flares in.

    smoothbinsize : int
        The number of consecutive light curve points to smooth over in the time
        series using a Savitsky-Golay filter. The smoothed light curve is then
        subtracted from the actual light curve to remove trends that potentially
        last `smoothbinsize` light curve points. The default value is chosen as
        ~6.5 hours (97 x 4 minute cadence for HATNet/HATSouth).

    flare_minsigma : float
        The minimum sigma above the median LC level to designate points as
        belonging to possible flares.

    flare_maxcadencediff : int
        The maximum number of light curve points apart each possible flare event
        measurement is allowed to be. If this is 1, then we'll look for
        consecutive measurements.

    flare_mincadencepoints : int
        The minimum number of light curve points (each `flare_maxcadencediff`
        points apart) required that are at least `flare_minsigma` above the
        median light curve level to call an event a flare.

    magsarefluxes: bool
        If True, indicates that mags is actually an array of fluxes.

    savgol_polyorder: int
        The polynomial order of the function used by the Savitsky-Golay filter.

    savgol_kwargs : extra kwargs
        Any remaining keyword arguments are passed directly to the
        `savgol_filter` function from `scipy.signal`.

    Returns
    -------

    (nflares, flare_indices) : tuple
        Returns the total number of flares found and their time-indices (start,
        end) as tuples.


def trapezoid_transit_func(transitparams, times, mags, errs,<EOL>get_ntransitpoints=False):

(transitperiod,<EOL>transitepoch,<EOL>transitdepth,<EOL>transitduration,<EOL>ingressduration) = transitparams<EOL>iphase = (times - transitepoch)/transitperiod<EOL>iphase = iphase - np.floor(iphase)<EOL>phasesortind = np.argsort(iphase)<EOL>phase = iphase[phasesortind]<EOL>ptimes = times[phasesortind]<EOL>pmags = mags[phasesortind]<EOL>perrs = errs[phasesortind]<EOL>zerolevel = np.median(pmags)<EOL>modelmags = np.full_like(phase, zerolevel)<EOL>halftransitduration = transitduration/<NUM_LIT><EOL>bottomlevel = zerolevel - transitdepth<EOL>slope = transitdepth/ingressduration<EOL>firstcontact = <NUM_LIT:1.0> - halftransitduration<EOL>secondcontact = firstcontact + ingressduration<EOL>thirdcontact = halftransitduration - ingressduration<EOL>fourthcontact = halftransitduration<EOL>ingressind = (phase > firstcontact) & (phase < secondcontact)<EOL>bottomind = (phase > secondcontact) | (phase < thirdcontact)<EOL>egressind = (phase > thirdcontact) & (phase < fourthcontact)<EOL>in_transit_points = ingressind | bottomind | egressind<EOL>n_transit_points = np.sum(in_transit_points)<EOL>modelmags[ingressind] = zerolevel - slope*(phase[ingressind] - firstcontact)<EOL>modelmags[bottomind] = bottomlevel<EOL>modelmags[egressind] = bottomlevel + slope*(phase[egressind] - thirdcontact)<EOL>if get_ntransitpoints:<EOL><INDENT>return modelmags, phase, ptimes, pmags, perrs, n_transit_points<EOL><DEDENT>else:<EOL><INDENT>return modelmags, phase, ptimes, pmags, perrs<EOL><DEDENT>

This returns a trapezoid transit-shaped function.

    Suitable for first order modeling of transit signals.

    Parameters
    ----------

    transitparams : list of float
        This contains the transiting planet trapezoid model::

            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

    times,mags,errs : np.array
        The input time-series of measurements and associated errors for which
        the transit model will be generated. The times will be used to generate
        model mags, and the input `times`, `mags`, and `errs` will be resorted
        by model phase and returned.

    Returns
    -------

    (modelmags, phase, ptimes, pmags, perrs) : tuple
        Returns the model mags and phase values. Also returns the input `times`,
        `mags`, and `errs` sorted by the model's phase.


def trapezoid_transit_residual(transitparams, times, mags, errs):

modelmags, phase, ptimes, pmags, perrs = (<EOL>trapezoid_transit_func(transitparams, times, mags, errs)<EOL>)<EOL>return (pmags - modelmags)/perrs<EOL>

This returns the residual between the modelmags and the actual mags.

Parameters
----------

transitparams : list of float
    This contains the transiting planet trapezoid model::

        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

times,mags,errs : np.array
    The input time-series of measurements and associated errors for which
    the transit model will be generated. The times will be used to generate
    model mags, and the input `times`, `mags`, and `errs` will be resorted
    by model phase and returned.

Returns
-------

np.array
    The residuals between the input `mags` and generated `modelmags`,
    weighted by the measurement errors in `errs`.


def fourier_sinusoidal_func(fourierparams, times, mags, errs):

period, epoch, famps, fphases = fourierparams<EOL>forder = len(famps)<EOL>iphase = (times - epoch)/period<EOL>iphase = iphase - np.floor(iphase)<EOL>phasesortind = np.argsort(iphase)<EOL>phase = iphase[phasesortind]<EOL>ptimes = times[phasesortind]<EOL>pmags = mags[phasesortind]<EOL>perrs = errs[phasesortind]<EOL>fseries = [famps[x]*np.cos(<NUM_LIT>*np.pi*x*phase + fphases[x])<EOL>for x in range(forder)]<EOL>modelmags = np.median(mags)<EOL>for fo in fseries:<EOL><INDENT>modelmags += fo<EOL><DEDENT>return modelmags, phase, ptimes, pmags, perrs<EOL>

This generates a sinusoidal light curve using a Fourier cosine series.

    Parameters
    ----------

    fourierparams : list
        This MUST be a list of the following form like so::

            [period,
             epoch,
             [amplitude_1, amplitude_2, amplitude_3, ..., amplitude_X],
             [phase_1, phase_2, phase_3, ..., phase_X]]

        where X is the Fourier order.

    times,mags,errs : np.array
        The input time-series of measurements and associated errors for which
        the model will be generated. The times will be used to generate model
        mags, and the input `times`, `mags`, and `errs` will be resorted by
        model phase and returned.

    Returns
    -------

    (modelmags, phase, ptimes, pmags, perrs) : tuple
        Returns the model mags and phase values. Also returns the input `times`,
        `mags`, and `errs` sorted by the model's phase.


def fourier_sinusoidal_residual(fourierparams, times, mags, errs):

modelmags, phase, ptimes, pmags, perrs = (<EOL>fourier_sinusoidal_func(fourierparams, times, mags, errs)<EOL>)<EOL>return (pmags - modelmags)/perrs<EOL>

This returns the residual between the model mags and the actual mags.

Parameters
----------

fourierparams : list
    This MUST be a list of the following form like so::

        [period,
         epoch,
         [amplitude_1, amplitude_2, amplitude_3, ..., amplitude_X],
         [phase_1, phase_2, phase_3, ..., phase_X]]

    where X is the Fourier order.

times,mags,errs : np.array
    The input time-series of measurements and associated errors for which
    the model will be generated. The times will be used to generate model
    mags, and the input `times`, `mags`, and `errs` will be resorted by
    model phase and returned.

Returns
-------

np.array
    The residuals between the input `mags` and generated `modelmags`,
    weighted by the measurement errors in `errs`.


def sine_series_sum(fourierparams, times, mags, errs):

period, epoch, famps, fphases = fourierparams<EOL>forder = len(famps)<EOL>iphase = (times - epoch)/period<EOL>iphase = iphase - np.floor(iphase)<EOL>phasesortind = np.argsort(iphase)<EOL>phase = iphase[phasesortind]<EOL>ptimes = times[phasesortind]<EOL>pmags = mags[phasesortind]<EOL>perrs = errs[phasesortind]<EOL>fseries = [famps[x]*np.sin(<NUM_LIT>*np.pi*x*phase + fphases[x])<EOL>for x in range(forder)]<EOL>modelmags = np.median(mags)<EOL>for fo in fseries:<EOL><INDENT>modelmags += fo<EOL><DEDENT>return modelmags, phase, ptimes, pmags, perrs<EOL>

This generates a sinusoidal light curve using a Fourier sine series.

    Parameters
    ----------

    fourierparams : list
        This MUST be a list of the following form like so::

            [period,
             epoch,
             [amplitude_1, amplitude_2, amplitude_3, ..., amplitude_X],
             [phase_1, phase_2, phase_3, ..., phase_X]]

        where X is the Fourier order.

    times,mags,errs : np.array
        The input time-series of measurements and associated errors for which
        the model will be generated. The times will be used to generate model
        mags, and the input `times`, `mags`, and `errs` will be resorted by
        model phase and returned.

    Returns
    -------

    (modelmags, phase, ptimes, pmags, perrs) : tuple
        Returns the model mags and phase values. Also returns the input `times`,
        `mags`, and `errs` sorted by the model's phase.


return amp * np.exp(-((x - loc)*(x - loc))/(<NUM_LIT>*std*std))<EOL>

This is a simple gaussian.

    Parameters
    ----------

    x : np.array
        The items at which the Gaussian is evaluated.

    amp : float
        The amplitude of the Gaussian.

    loc : float
        The central value of the Gaussian.

    std : float
        The standard deviation of the Gaussian.

    Returns
    -------

    np.array
        Returns the Gaussian evaluated at the items in `x`, using the provided
        parameters of `amp`, `loc`, and `std`.


def _double_inverted_gaussian(x,<EOL>amp1, loc1, std1,<EOL>amp2, loc2, std2):

gaussian1 = -_gaussian(x,amp1,loc1,std1)<EOL>gaussian2 = -_gaussian(x,amp2,loc2,std2)<EOL>return gaussian1 + gaussian2<EOL>

This is a double inverted gaussian.

    Parameters
    ----------

    x : np.array
        The items at which the Gaussian is evaluated.

    amp1,amp2 : float
        The amplitude of Gaussian 1 and Gaussian 2.

    loc1,loc2 : float
        The central value of Gaussian 1 and Gaussian 2.

    std1,std2 : float
        The standard deviation of Gaussian 1 and Gaussian 2.

    Returns
    -------

    np.array
        Returns a double inverted Gaussian function evaluated at the items in
        `x`, using the provided parameters of `amp`, `loc`, and `std` for two
        component Gaussians 1 and 2.


def invgauss_eclipses_func(ebparams, times, mags, errs):

(period, epoch, pdepth, pduration, depthratio, secondaryphase) = ebparams<EOL>iphase = (times - epoch)/period<EOL>iphase = iphase - np.floor(iphase)<EOL>phasesortind = np.argsort(iphase)<EOL>phase = iphase[phasesortind]<EOL>ptimes = times[phasesortind]<EOL>pmags = mags[phasesortind]<EOL>perrs = errs[phasesortind]<EOL>zerolevel = np.median(pmags)<EOL>modelmags = np.full_like(phase, zerolevel)<EOL>primaryecl_amp = -pdepth<EOL>secondaryecl_amp = -pdepth * depthratio<EOL>primaryecl_std = pduration/<NUM_LIT>    <EOL>secondaryecl_std = pduration/<NUM_LIT>  <EOL>halfduration = pduration/<NUM_LIT><EOL>primary_eclipse_ingress = (<EOL>(phase >= (<NUM_LIT:1.0> - halfduration)) & (phase <= <NUM_LIT:1.0>)<EOL>)<EOL>primary_eclipse_egress = (<EOL>(phase >= <NUM_LIT:0.0>) & (phase <= halfduration)<EOL>)<EOL>secondary_eclipse_phase = (<EOL>(phase >= (secondaryphase - halfduration)) &<EOL>(phase <= (secondaryphase + halfduration))<EOL>)<EOL>modelmags[primary_eclipse_ingress] = (<EOL>zerolevel + _gaussian(phase[primary_eclipse_ingress],<EOL>primaryecl_amp,<EOL><NUM_LIT:1.0>,<EOL>primaryecl_std)<EOL>)<EOL>modelmags[primary_eclipse_egress] = (<EOL>zerolevel + _gaussian(phase[primary_eclipse_egress],<EOL>primaryecl_amp,<EOL><NUM_LIT:0.0>,<EOL>primaryecl_std)<EOL>)<EOL>modelmags[secondary_eclipse_phase] = (<EOL>zerolevel + _gaussian(phase[secondary_eclipse_phase],<EOL>secondaryecl_amp,<EOL>secondaryphase,<EOL>secondaryecl_std)<EOL>)<EOL>return modelmags, phase, ptimes, pmags, perrs<EOL>

This returns a double eclipse shaped function.

    Suitable for first order modeling of eclipsing binaries.

    Parameters
    ----------

    ebparams : list of float
        This contains the parameters for the eclipsing binary::

            ebparams = [period (time),
                        epoch (time),
                        pdepth: primary eclipse depth (mags),
                        pduration: primary eclipse duration (phase),
                        psdepthratio: primary-secondary eclipse depth ratio,
                        secondaryphase: center phase of the secondary eclipse]

        `period` is the period in days.

        `epoch` is the time of minimum in JD.

        `pdepth` is the depth of the primary eclipse.

        - for magnitudes -> pdepth should be < 0
        - for fluxes     -> pdepth 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 `T_effs` 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.

    times,mags,errs : np.array
        The input time-series of measurements and associated errors for which
        the eclipse model will be generated. The times will be used to generate
        model mags, and the input `times`, `mags`, and `errs` will be resorted
        by model phase and returned.

    Returns
    -------

    (modelmags, phase, ptimes, pmags, perrs) : tuple
        Returns the model mags and phase values. Also returns the input `times`,
        `mags`, and `errs` sorted by the model's phase.


def invgauss_eclipses_residual(ebparams, times, mags, errs):

modelmags, phase, ptimes, pmags, perrs = (<EOL>invgauss_eclipses_func(ebparams, times, mags, errs)<EOL>)<EOL>return (pmags - modelmags)/perrs<EOL>

This returns the residual between the modelmags and the actual mags.

    Parameters
    ----------

    ebparams : list of float
        This contains the parameters for the eclipsing binary::

            ebparams = [period (time),
                        epoch (time),
                        pdepth: primary eclipse depth (mags),
                        pduration: primary eclipse duration (phase),
                        psdepthratio: primary-secondary eclipse depth ratio,
                        secondaryphase: center phase of the secondary eclipse]

        `period` is the period in days.

        `epoch` is the time of minimum in JD.

        `pdepth` is the depth of the primary eclipse.

        - for magnitudes -> `pdepth` should be < 0
        - for fluxes     -> `pdepth` 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 `T_effs` 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.

    times,mags,errs : np.array
        The input time-series of measurements and associated errors for which
        the eclipse model will be generated. The times will be used to generate
        model mags, and the input `times`, `mags`, and `errs` will be resorted
        by model phase and returned.

    Returns
    -------

    np.array
        The residuals between the input `mags` and generated `modelmags`,
        weighted by the measurement errors in `errs`.


def flare_model(flareparams, times, mags, errs):

(amplitude, flare_peak_time,<EOL>rise_gaussian_stdev, decay_time_constant) = flareparams<EOL>zerolevel = np.median(mags)<EOL>modelmags = np.full_like(times, zerolevel)<EOL>modelmags[times < flare_peak_time] = (<EOL>mags[times < flare_peak_time] +<EOL>amplitude * np.exp(<EOL>-((times[times < flare_peak_time] -<EOL>flare_peak_time) *<EOL>(times[times < flare_peak_time] -<EOL>flare_peak_time)) /<EOL>(<NUM_LIT>*rise_gaussian_stdev*rise_gaussian_stdev)<EOL>)<EOL>)<EOL>modelmags[times > flare_peak_time] = (<EOL>mags[times > flare_peak_time] +<EOL>amplitude * np.exp(<EOL>-((times[times > flare_peak_time] -<EOL>flare_peak_time)) /<EOL>(decay_time_constant)<EOL>)<EOL>)<EOL>return modelmags, times, mags, errs<EOL>

This is a flare model function, similar to Kowalski+ 2011.

    From the paper by Pitkin+ 2014:
    http://adsabs.harvard.edu/abs/2014MNRAS.445.2268P

    Parameters
    ----------

    flareparams : list of float
        This defines the flare model::

            [amplitude,
             flare_peak_time,
             rise_gaussian_stdev,
             decay_time_constant]

        where:

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

        `flare_peak_time`: time at which the flare maximum happens.

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

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

    times,mags,errs : np.array
        The input time-series of measurements and associated errors for which
        the model will be generated. The times will be used to generate
        model mags.

    Returns
    -------

    (modelmags, times, mags, errs) : tuple
        Returns the model mags evaluated at the input time values. Also returns
        the input `times`, `mags`, and `errs`.


def flare_model_residual(flareparams, times, mags, errs):

modelmags, _, _, _ = flare_model(flareparams, times, mags, errs)<EOL>return (mags - modelmags)/errs<EOL>

This returns the residual between model mags and the actual mags.

Parameters
----------

flareparams : list of float
    This defines the flare model::

        [amplitude,
         flare_peak_time,
         rise_gaussian_stdev,
         decay_time_constant]

    where:

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

    `flare_peak_time`: time at which the flare maximum happens.

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

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

times,mags,errs : np.array
    The input time-series of measurements and associated errors for which
    the model will be generated. The times will be used to generate
    model mags.

Returns
-------

np.array
    The residuals between the input `mags` and generated `modelmags`,
    weighted by the measurement errors in `errs`.


lc_time_diffs = np.diff(lctimes)<EOL>group_start_indices = np.where(lc_time_diffs > mingap)[<NUM_LIT:0>]<EOL>if len(group_start_indices) > <NUM_LIT:0>:<EOL><INDENT>group_indices = []<EOL>for i, gindex in enumerate(group_start_indices):<EOL><INDENT>if i == <NUM_LIT:0>:<EOL><INDENT>group_indices.append(slice(<NUM_LIT:0>,gindex+<NUM_LIT:1>))<EOL><DEDENT>else:<EOL><INDENT>group_indices.append(slice(group_start_indices[i-<NUM_LIT:1>]+<NUM_LIT:1>,gindex+<NUM_LIT:1>))<EOL><DEDENT><DEDENT>group_indices.append(slice(group_start_indices[-<NUM_LIT:1>]+<NUM_LIT:1>,len(lctimes)))<EOL><DEDENT>else:<EOL><INDENT>group_indices = [slice(<NUM_LIT:0>,len(lctimes))]<EOL><DEDENT>return len(group_indices), group_indices<EOL>

Finds gaps in the provided time-series and indexes them into groups.

    This finds the gaps in the provided `lctimes` array, so we can figure out
    which times are for consecutive observations and which represent gaps
    between seasons or observing eras.

    Parameters
    ----------

    lctimes : array-like
        This contains the times to analyze for gaps; assumed to be some form of
        Julian date.

    mingap : float
        This defines how much the difference between consecutive measurements is
        allowed to be to consider them as parts of different timegroups. By
        default it is set to 4.0 days.

    Returns
    -------

    tuple
        A tuple of the form: `(ngroups, [slice(start_ind_1, end_ind_1), ...])`
        is returned.  This contains the number of groups as the first element,
        and a list of Python `slice` objects for each time-group found. These
        can be used directly to index into the array of times to quickly get
        measurements associated with each group.


ngroups, timegroups = find_lc_timegroups(times,<EOL>mingap=mingap)<EOL>finite_ind = np.isfinite(mags)<EOL>if any(finite_ind):<EOL><INDENT>global_mag_median = np.median(mags[finite_ind])<EOL>for tgind, tg in enumerate(timegroups):<EOL><INDENT>finite_ind = np.isfinite(mags[tg])<EOL>group_median = np.median((mags[tg])[finite_ind])<EOL>if magsarefluxes:<EOL><INDENT>mags[tg] = mags[tg]/group_median<EOL><DEDENT>else:<EOL><INDENT>mags[tg] = mags[tg] - group_median<EOL><DEDENT>if debugmode:<EOL><INDENT>LOGDEBUG('<STR_LIT>'<EOL>'<STR_LIT>' %<EOL>(tgind,<EOL>len(mags[tg]),<EOL>len(finite_ind),<EOL>group_median))<EOL><DEDENT><DEDENT>if isinstance(normto, str) and normto == '<STR_LIT>':<EOL><INDENT>if magsarefluxes:<EOL><INDENT>mags = mags * global_mag_median<EOL><DEDENT>else:<EOL><INDENT>mags = mags + global_mag_median<EOL><DEDENT><DEDENT>elif isinstance(normto, float):<EOL><INDENT>if magsarefluxes:<EOL><INDENT>mags = mags * normto<EOL><DEDENT>else:<EOL><INDENT>mags = mags + normto<EOL><DEDENT><DEDENT>return times, mags<EOL><DEDENT>else:<EOL><INDENT>LOGERROR('<STR_LIT>')<EOL>return None, None<EOL><DEDENT>

This normalizes the magnitude time-series to a specified value.

    This is used to normalize time series measurements that may have large time
    gaps and vertical offsets in mag/flux measurement between these
    'timegroups', either due to instrument changes or different filters.

    NOTE: this works in-place! The mags array will be replaced with normalized
    mags when this function finishes.

    Parameters
    ----------

    times,mags : array-like
        The times (assumed to be some form of JD) and mags (or flux)
        measurements to be normalized.

    mingap : float
        This defines how much the difference between consecutive measurements is
        allowed to be to consider them as parts of different timegroups. By
        default it is set to 4.0 days.

    normto : {'globalmedian', 'zero'} or a float
        Specifies the normalization type::

          'globalmedian' -> norms each mag to the global median of the LC column
          'zero'         -> norms each mag to zero
          a float        -> norms each mag to this specified float value.

    magsarefluxes : bool
        Indicates if the input `mags` array is actually an array of flux
        measurements instead of magnitude measurements. If this is set to True,
        then:

        - if `normto` is 'zero', then the median flux is divided from each
          observation's flux value to yield normalized fluxes with 1.0 as the
          global median.

        - if `normto` is 'globalmedian', then the global median flux value
          across the entire time series is multiplied with each measurement.

        - if `norm` is set to a `float`, then this number is multiplied with the
          flux value for each measurement.

    debugmode : bool
        If this is True, will print out verbose info on each timegroup found.

    Returns
    -------

    times,normalized_mags : np.arrays
        Normalized magnitude values after normalization. If normalization fails
        for some reason, `times` and `normalized_mags` will both be None.


returnerrs = True<EOL>if errs is None:<EOL><INDENT>errs = <NUM_LIT>*mags<EOL>returnerrs = False<EOL><DEDENT>find = npisfinite(times) & npisfinite(mags) & npisfinite(errs)<EOL>ftimes, fmags, ferrs = times[find], mags[find], errs[find]<EOL>if meanormedian == '<STR_LIT>':  <EOL><INDENT>center_mag = npmedian(fmags)<EOL>stddev_mag = (npmedian(npabs(fmags - center_mag))) * <NUM_LIT><EOL><DEDENT>elif meanormedian == '<STR_LIT>':<EOL><INDENT>center_mag = npmean(fmags)<EOL>stddev_mag = npstddev(fmags)<EOL><DEDENT>else:<EOL><INDENT>LOGWARNING("<STR_LIT>"<EOL>"<STR_LIT>" %<EOL>meanormedian)<EOL>meanormedian = '<STR_LIT>'<EOL>center_mag = npmedian(fmags)<EOL>stddev_mag = (npmedian(npabs(fmags - center_mag))) * <NUM_LIT><EOL><DEDENT>if sigclip and isinstance(sigclip, (float, int)):<EOL><INDENT>if not iterative and niterations is None:<EOL><INDENT>sigind = (npabs(fmags - center_mag)) < (sigclip * stddev_mag)<EOL>stimes = ftimes[sigind]<EOL>smags = fmags[sigind]<EOL>serrs = ferrs[sigind]<EOL><DEDENT>else:<EOL><INDENT>if niterations is None:<EOL><INDENT>delta = <NUM_LIT:1><EOL>this_times = ftimes<EOL>this_mags = fmags<EOL>this_errs = ferrs<EOL>while delta:<EOL><INDENT>if meanormedian == '<STR_LIT>':<EOL><INDENT>this_center = npmean(this_mags)<EOL>this_stdev = npstddev(this_mags)<EOL><DEDENT>elif meanormedian == '<STR_LIT>':<EOL><INDENT>this_center = npmedian(this_mags)<EOL>this_stdev = (<EOL>npmedian(npabs(this_mags - this_center))<EOL>) * <NUM_LIT><EOL><DEDENT>this_size = this_mags.size<EOL>tsi = (<EOL>(npabs(this_mags - this_center)) <<EOL>(sigclip * this_stdev)<EOL>)<EOL>this_times = this_times[tsi]<EOL>this_mags = this_mags[tsi]<EOL>this_errs = this_errs[tsi]<EOL>delta = this_size - this_mags.size<EOL><DEDENT><DEDENT>else:  <EOL><INDENT>this_times = ftimes<EOL>this_mags = fmags<EOL>this_errs = ferrs<EOL>iter_num = <NUM_LIT:0><EOL>delta = <NUM_LIT:1><EOL>while iter_num < niterations and delta:<EOL><INDENT>if meanormedian == '<STR_LIT>':<EOL><INDENT>this_center = npmean(this_mags)<EOL>this_stdev = npstddev(this_mags)<EOL><DEDENT>elif meanormedian == '<STR_LIT>':<EOL><INDENT>this_center = npmedian(this_mags)<EOL>this_stdev = (npmedian(npabs(this_mags -<EOL>this_center))) * <NUM_LIT><EOL><DEDENT>this_size = this_mags.size<EOL>tsi = (<EOL>(npabs(this_mags - this_center)) <<EOL>(sigclip * this_stdev)<EOL>)<EOL>this_times = this_times[tsi]<EOL>this_mags = this_mags[tsi]<EOL>this_errs = this_errs[tsi]<EOL>delta = this_size - this_mags.size<EOL>iter_num += <NUM_LIT:1><EOL><DEDENT><DEDENT>stimes, smags, serrs = this_times, this_mags, this_errs<EOL><DEDENT><DEDENT>elif sigclip and isinstance(sigclip, (list,tuple)) and len(sigclip) == <NUM_LIT:2>:<EOL><INDENT>dimmingclip = sigclip[<NUM_LIT:0>]<EOL>brighteningclip = sigclip[<NUM_LIT:1>]<EOL>if not iterative and niterations is None:<EOL><INDENT>if magsarefluxes:<EOL><INDENT>nottoodimind = (<EOL>(fmags - center_mag) > (-dimmingclip*stddev_mag)<EOL>)<EOL>nottoobrightind = (<EOL>(fmags - center_mag) < (brighteningclip*stddev_mag)<EOL>)<EOL><DEDENT>else:<EOL><INDENT>nottoodimind = (<EOL>(fmags - center_mag) < (dimmingclip*stddev_mag)<EOL>)<EOL>nottoobrightind = (<EOL>(fmags - center_mag) > (-brighteningclip*stddev_mag)<EOL>)<EOL><DEDENT>sigind = nottoodimind & nottoobrightind<EOL>stimes = ftimes[sigind]<EOL>smags = fmags[sigind]<EOL>serrs = ferrs[sigind]<EOL><DEDENT>else:<EOL><INDENT>if niterations is None:<EOL><INDENT>delta = <NUM_LIT:1><EOL>this_times = ftimes<EOL>this_mags = fmags<EOL>this_errs = ferrs<EOL>while delta:<EOL><INDENT>if meanormedian == '<STR_LIT>':<EOL><INDENT>this_center = npmean(this_mags)<EOL>this_stdev = npstddev(this_mags)<EOL><DEDENT>elif meanormedian == '<STR_LIT>':<EOL><INDENT>this_center = npmedian(this_mags)<EOL>this_stdev = (npmedian(npabs(this_mags -<EOL>this_center))) * <NUM_LIT><EOL><DEDENT>this_size = this_mags.size<EOL>if magsarefluxes:<EOL><INDENT>nottoodimind = (<EOL>(this_mags - this_center) ><EOL>(-dimmingclip*this_stdev)<EOL>)<EOL>nottoobrightind = (<EOL>(this_mags - this_center) <<EOL>(brighteningclip*this_stdev)<EOL>)<EOL><DEDENT>else:<EOL><INDENT>nottoodimind = (<EOL>(this_mags - this_center) <<EOL>(dimmingclip*this_stdev)<EOL>)<EOL>nottoobrightind = (<EOL>(this_mags - this_center) ><EOL>(-brighteningclip*this_stdev)<EOL>)<EOL><DEDENT>tsi = nottoodimind & nottoobrightind<EOL>this_times = this_times[tsi]<EOL>this_mags = this_mags[tsi]<EOL>this_errs = this_errs[tsi]<EOL>delta = this_size - this_mags.size<EOL><DEDENT><DEDENT>else:  <EOL><INDENT>this_times = ftimes<EOL>this_mags = fmags<EOL>this_errs = ferrs<EOL>iter_num = <NUM_LIT:0><EOL>delta = <NUM_LIT:1><EOL>while iter_num < niterations and delta:<EOL><INDENT>if meanormedian == '<STR_LIT>':<EOL><INDENT>this_center = npmean(this_mags)<EOL>this_stdev = npstddev(this_mags)<EOL><DEDENT>elif meanormedian == '<STR_LIT>':<EOL><INDENT>this_center = npmedian(this_mags)<EOL>this_stdev = (npmedian(npabs(this_mags -<EOL>this_center))) * <NUM_LIT><EOL><DEDENT>this_size = this_mags.size<EOL>if magsarefluxes:<EOL><INDENT>nottoodimind = (<EOL>(this_mags - this_center) ><EOL>(-dimmingclip*this_stdev)<EOL>)<EOL>nottoobrightind = (<EOL>(this_mags - this_center) <<EOL>(brighteningclip*this_stdev)<EOL>)<EOL><DEDENT>else:<EOL><INDENT>nottoodimind = (<EOL>(this_mags - this_center) < (dimmingclip*this_stdev)<EOL>)<EOL>nottoobrightind = (<EOL>(this_mags - this_center) ><EOL>(-brighteningclip*this_stdev)<EOL>)<EOL><DEDENT>tsi = nottoodimind & nottoobrightind<EOL>this_times = this_times[tsi]<EOL>this_mags = this_mags[tsi]<EOL>this_errs = this_errs[tsi]<EOL>delta = this_size - this_mags.size<EOL>iter_num += <NUM_LIT:1><EOL><DEDENT><DEDENT>stimes, smags, serrs = this_times, this_mags, this_errs<EOL><DEDENT><DEDENT>else:<EOL><INDENT>stimes = ftimes<EOL>smags = fmags<EOL>serrs = ferrs<EOL><DEDENT>if returnerrs:<EOL><INDENT>return stimes, smags, serrs<EOL><DEDENT>else:<EOL><INDENT>return stimes, smags, None<EOL><DEDENT>

Sigma-clips a magnitude or flux time-series.

    Selects the finite times, magnitudes (or fluxes), and errors from the passed
    values, and apply symmetric or asymmetric sigma clipping to them.

    Parameters
    ----------

    times,mags,errs : np.array
        The magnitude or flux time-series arrays to sigma-clip. This doesn't
        assume all values are finite or if they're positive/negative. All of
        these arrays will have their non-finite elements removed, and then will
        be sigma-clipped based on the arguments to this function.

        `errs` is optional. Set it to None if you don't have values for these. A
        'faked' `errs` array will be generated if necessary, which can be
        ignored in the output as well.

    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.

    iterative : bool
        If this is set to True, will perform iterative sigma-clipping. If
        `niterations` is not set and this is True, sigma-clipping is iterated
        until no more points are removed.

    niterations : int
        The maximum number of iterations to perform for sigma-clipping. If None,
        the `iterative` arg takes precedence, and `iterative=True` will
        sigma-clip until no more points are removed.  If `niterations` is not
        None and `iterative` is False, `niterations` takes precedence and
        iteration will occur for the specified number of iterations.

    meanormedian : {'mean', 'median'}
        Use 'mean' for sigma-clipping based on the mean value, or 'median' for
        sigma-clipping based on the median value.  Default is 'median'.

    magsareflux : bool
        True if your "mags" are in fact fluxes, i.e. if "fainter" corresponds to
        `mags` getting smaller.

    Returns
    -------

    (stimes, smags, serrs) : tuple
        The sigma-clipped and nan-stripped time-series.


def sigclip_magseries_with_extparams(times, mags, errs, extparams,<EOL>sigclip=None,<EOL>iterative=False,<EOL>magsarefluxes=False):

returnerrs = True<EOL>if errs is None:<EOL><INDENT>errs = <NUM_LIT>*mags<EOL>returnerrs = False<EOL><DEDENT>find = npisfinite(times) & npisfinite(mags) & npisfinite(errs)<EOL>ftimes, fmags, ferrs = times[find], mags[find], errs[find]<EOL>for epi, eparr in enumerate(extparams):<EOL><INDENT>extparams[epi] = eparr[find]<EOL><DEDENT>median_mag = npmedian(fmags)<EOL>stddev_mag = (npmedian(npabs(fmags - median_mag))) * <NUM_LIT><EOL>if sigclip and isinstance(sigclip, (float, int)):<EOL><INDENT>if not iterative:<EOL><INDENT>sigind = (npabs(fmags - median_mag)) < (sigclip * stddev_mag)<EOL>stimes = ftimes[sigind]<EOL>smags = fmags[sigind]<EOL>serrs = ferrs[sigind]<EOL>for epi, eparr in enumerate(extparams):<EOL><INDENT>extparams[epi] = eparr[sigind]<EOL><DEDENT><DEDENT>else:<EOL><INDENT>delta = <NUM_LIT:1><EOL>this_times = ftimes<EOL>this_mags = fmags<EOL>this_errs = ferrs<EOL>while delta:<EOL><INDENT>this_median = npmedian(this_mags)<EOL>this_stdev = (npmedian(npabs(this_mags - this_median))) * <NUM_LIT><EOL>this_size = this_mags.size<EOL>tsi = (npabs(this_mags - this_median)) < (sigclip * this_stdev)<EOL>this_times = this_times[tsi]<EOL>this_mags = this_mags[tsi]<EOL>this_errs = this_errs[tsi]<EOL>for epi, eparr in enumerate(extparams):<EOL><INDENT>extparams[epi] = eparr[tsi]<EOL><DEDENT>delta = this_size - this_mags.size<EOL><DEDENT>stimes, smags, serrs = this_times, this_mags, this_errs<EOL><DEDENT><DEDENT>elif sigclip and isinstance(sigclip, (list, tuple)) and len(sigclip) == <NUM_LIT:2>:<EOL><INDENT>dimmingclip = sigclip[<NUM_LIT:0>]<EOL>brighteningclip = sigclip[<NUM_LIT:1>]<EOL>if not iterative:<EOL><INDENT>if magsarefluxes:<EOL><INDENT>nottoodimind = (<EOL>(fmags - median_mag) > (-dimmingclip*stddev_mag)<EOL>)<EOL>nottoobrightind = (<EOL>(fmags - median_mag) < (brighteningclip*stddev_mag)<EOL>)<EOL><DEDENT>else:<EOL><INDENT>nottoodimind = (<EOL>(fmags - median_mag) < (dimmingclip*stddev_mag)<EOL>)<EOL>nottoobrightind = (<EOL>(fmags - median_mag) > (-brighteningclip*stddev_mag)<EOL>)<EOL><DEDENT>sigind = nottoodimind & nottoobrightind<EOL>stimes = ftimes[sigind]<EOL>smags = fmags[sigind]<EOL>serrs = ferrs[sigind]<EOL>for epi, eparr in enumerate(extparams):<EOL><INDENT>extparams[epi] = eparr[sigind]<EOL><DEDENT><DEDENT>else:<EOL><INDENT>delta = <NUM_LIT:1><EOL>this_times = ftimes<EOL>this_mags = fmags<EOL>this_errs = ferrs<EOL>while delta:<EOL><INDENT>this_median = npmedian(this_mags)<EOL>this_stdev = (npmedian(npabs(this_mags - this_median))) * <NUM_LIT><EOL>this_size = this_mags.size<EOL>if magsarefluxes:<EOL><INDENT>nottoodimind = (<EOL>(this_mags - this_median) > (-dimmingclip*this_stdev)<EOL>)<EOL>nottoobrightind = (<EOL>(this_mags - this_median) < (brighteningclip*this_stdev)<EOL>)<EOL><DEDENT>else:<EOL><INDENT>nottoodimind = (<EOL>(this_mags - this_median) < (dimmingclip*this_stdev)<EOL>)<EOL>nottoobrightind = (<EOL>(this_mags - this_median) ><EOL>(-brighteningclip*this_stdev)<EOL>)<EOL><DEDENT>tsi = nottoodimind & nottoobrightind<EOL>this_times = this_times[tsi]<EOL>this_mags = this_mags[tsi]<EOL>this_errs = this_errs[tsi]<EOL>for epi, eparr in enumerate(extparams):<EOL><INDENT>extparams[epi] = eparr[tsi]<EOL><DEDENT>delta = this_size - this_mags.size<EOL><DEDENT>stimes, smags, serrs = this_times, this_mags, this_errs<EOL><DEDENT><DEDENT>else:<EOL><INDENT>stimes = ftimes<EOL>smags = fmags<EOL>serrs = ferrs<EOL><DEDENT>if returnerrs:<EOL><INDENT>return stimes, smags, serrs, extparams<EOL><DEDENT>else:<EOL><INDENT>return stimes, smags, None, extparams<EOL><DEDENT>

Sigma-clips a magnitude or flux time-series and associated measurement
    arrays.

    Selects the finite times, magnitudes (or fluxes), and errors from the passed
    values, and apply symmetric or asymmetric sigma clipping to them.  Uses the
    same array indices as these values to filter out the values of all arrays in
    the `extparams` list. This can be useful for simultaneously sigma-clipping a
    magnitude/flux time-series along with their associated values of external
    parameters, such as telescope hour angle, zenith distance, temperature, moon
    phase, etc.

    Parameters
    ----------

    times,mags,errs : np.array
        The magnitude or flux time-series arrays to sigma-clip. This doesn't
        assume all values are finite or if they're positive/negative. All of
        these arrays will have their non-finite elements removed, and then will
        be sigma-clipped based on the arguments to this function.

        `errs` is optional. Set it to None if you don't have values for these. A
        'faked' `errs` array will be generated if necessary, which can be
        ignored in the output as well.

    extparams : list of np.array
        This is a list of all external parameter arrays to simultaneously filter
        along with the magnitude/flux time-series. All of these arrays should
        have the same length as the `times`, `mags`, and `errs` arrays.

    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.

    iterative : bool
        If this is set to True, will perform iterative sigma-clipping. If
        `niterations` is not set and this is True, sigma-clipping is iterated
        until no more points are removed.

    magsareflux : bool
        True if your "mags" are in fact fluxes, i.e. if "fainter" corresponds to
        `mags` getting smaller.

    Returns
    -------

    (stimes, smags, serrs) : tuple
        The sigma-clipped and nan-stripped time-series in `stimes`, `smags`,
        `serrs` and the associated values of the `extparams` in `sextparams`.


def phase_magseries(times, mags, period, epoch, wrap=True, sort=True):

<EOL>finiteind = np.isfinite(mags) & np.isfinite(times)<EOL>finite_times = times[finiteind]<EOL>finite_mags = mags[finiteind]<EOL>magseries_phase = (<EOL>(finite_times - epoch)/period -<EOL>np.floor(((finite_times - epoch)/period))<EOL>)<EOL>outdict = {'<STR_LIT>':magseries_phase,<EOL>'<STR_LIT>':finite_mags,<EOL>'<STR_LIT>':period,<EOL>'<STR_LIT>':epoch}<EOL>if sort:<EOL><INDENT>sortorder = np.argsort(outdict['<STR_LIT>'])<EOL>outdict['<STR_LIT>'] = outdict['<STR_LIT>'][sortorder]<EOL>outdict['<STR_LIT>'] = outdict['<STR_LIT>'][sortorder]<EOL><DEDENT>if wrap:<EOL><INDENT>outdict['<STR_LIT>'] = np.concatenate((outdict['<STR_LIT>']-<NUM_LIT:1.0>,<EOL>outdict['<STR_LIT>']))<EOL>outdict['<STR_LIT>'] = np.concatenate((outdict['<STR_LIT>'],<EOL>outdict['<STR_LIT>']))<EOL><DEDENT>return outdict<EOL>

Phases a magnitude/flux time-series using a given period and epoch.

    The equation used is::

        phase = (times - epoch)/period - floor((times - epoch)/period)

    This phases the given magnitude timeseries using the given period and
    epoch. If wrap is True, wraps the result around 0.0 (and returns an array
    that has twice the number of the original elements). If sort is True,
    returns the magnitude timeseries in phase sorted order.

    Parameters
    ----------

    times,mags : np.array
        The magnitude/flux time-series values to phase using the provided
        `period` and `epoch`. Non-fiinite values will be removed.

    period : float
        The period to use to phase the time-series.

    epoch : float
        The epoch to phase the time-series. This is usually the time-of-minimum
        or time-of-maximum of some periodic light curve
        phenomenon. Alternatively, one can use the minimum time value in
        `times`.

    wrap : bool
        If this is True, the returned phased time-series will be wrapped around
        phase 0.0, which is useful for plotting purposes. The arrays returned
        will have twice the number of input elements because of this wrapping.

    sort : bool
        If this is True, the returned phased time-series will be sorted in
        increasing phase order.

    Returns
    -------

    dict
        A dict of the following form is returned::

            {'phase': the phase values,
             'mags': the mags/flux values at each phase,
             'period': the input `period` used to phase the time-series,
             'epoch': the input `epoch` used to phase the time-series}


def phase_magseries_with_errs(times, mags, errs, period, epoch,<EOL>wrap=True, sort=True):

<EOL>finiteind = np.isfinite(mags)<EOL>finite_times = times[finiteind]<EOL>finite_mags = mags[finiteind]<EOL>finite_errs = errs[finiteind]<EOL>magseries_phase = (<EOL>(finite_times - epoch)/period -<EOL>np.floor(((finite_times - epoch)/period))<EOL>)<EOL>outdict = {'<STR_LIT>':magseries_phase,<EOL>'<STR_LIT>':finite_mags,<EOL>'<STR_LIT>':finite_errs,<EOL>'<STR_LIT>':period,<EOL>'<STR_LIT>':epoch}<EOL>if sort:<EOL><INDENT>sortorder = np.argsort(outdict['<STR_LIT>'])<EOL>outdict['<STR_LIT>'] = outdict['<STR_LIT>'][sortorder]<EOL>outdict['<STR_LIT>'] = outdict['<STR_LIT>'][sortorder]<EOL>outdict['<STR_LIT>'] = outdict['<STR_LIT>'][sortorder]<EOL><DEDENT>if wrap:<EOL><INDENT>outdict['<STR_LIT>'] = np.concatenate((outdict['<STR_LIT>']-<NUM_LIT:1.0>,<EOL>outdict['<STR_LIT>']))<EOL>outdict['<STR_LIT>'] = np.concatenate((outdict['<STR_LIT>'],<EOL>outdict['<STR_LIT>']))<EOL>outdict['<STR_LIT>'] = np.concatenate((outdict['<STR_LIT>'],<EOL>outdict['<STR_LIT>']))<EOL><DEDENT>return outdict<EOL>

Phases a magnitude/flux time-series using a given period and epoch.

    The equation used is::

        phase = (times - epoch)/period - floor((times - epoch)/period)

    This phases the given magnitude timeseries using the given period and
    epoch. If wrap is True, wraps the result around 0.0 (and returns an array
    that has twice the number of the original elements). If sort is True,
    returns the magnitude timeseries in phase sorted order.

    Parameters
    ----------

    times,mags,errs : np.array
        The magnitude/flux time-series values and associated measurement errors
        to phase using the provided `period` and `epoch`. Non-fiinite values
        will be removed.

    period : float
        The period to use to phase the time-series.

    epoch : float
        The epoch to phase the time-series. This is usually the time-of-minimum
        or time-of-maximum of some periodic light curve
        phenomenon. Alternatively, one can use the minimum time value in
        `times`.

    wrap : bool
        If this is True, the returned phased time-series will be wrapped around
        phase 0.0, which is useful for plotting purposes. The arrays returned
        will have twice the number of input elements because of this wrapping.

    sort : bool
        If this is True, the returned phased time-series will be sorted in
        increasing phase order.

    Returns
    -------

    dict
        A dict of the following form is returned::

            {'phase': the phase values,
             'mags': the mags/flux values at each phase,
             'errs': the err values at each phase,
             'period': the input `period` used to phase the time-series,
             'epoch': the input `epoch` used to phase the time-series}


<EOL>if not(times.shape and mags.shape and len(times) > <NUM_LIT:9> and len(mags) > <NUM_LIT:9>):<EOL><INDENT>LOGERROR("<STR_LIT>")<EOL>return<EOL><DEDENT>finiteind = np.isfinite(mags) & np.isfinite(times)<EOL>finite_times = times[finiteind]<EOL>finite_mags = mags[finiteind]<EOL>binsizejd = binsize/(<NUM_LIT>)<EOL>nbins = int(np.ceil((np.nanmax(finite_times) -<EOL>np.nanmin(finite_times))/binsizejd) + <NUM_LIT:1>)<EOL>minjd = np.nanmin(finite_times)<EOL>jdbins = [(minjd + x*binsizejd) for x in range(nbins)]<EOL>time_coords = np.array([[x,<NUM_LIT:1.0>] for x in finite_times])<EOL>jdtree = cKDTree(time_coords)<EOL>binned_finite_timeseries_indices = []<EOL>collected_binned_mags = {}<EOL>for jd in jdbins:<EOL><INDENT>bin_indices = jdtree.query_ball_point(np.array([jd,<NUM_LIT:1.0>]),<EOL>binsizejd/<NUM_LIT>, p=<NUM_LIT:1.0>)<EOL>if (bin_indices not in binned_finite_timeseries_indices and<EOL>len(bin_indices) >= minbinelems):<EOL><INDENT>binned_finite_timeseries_indices.append(bin_indices)<EOL><DEDENT><DEDENT>binned_finite_timeseries_indices = [np.array(x) for x in<EOL>binned_finite_timeseries_indices]<EOL>collected_binned_mags['<STR_LIT>'] = binned_finite_timeseries_indices<EOL>collected_binned_mags['<STR_LIT>'] = jdbins<EOL>collected_binned_mags['<STR_LIT>'] = len(binned_finite_timeseries_indices)<EOL>binned_jd = np.array([np.median(finite_times[x])<EOL>for x in binned_finite_timeseries_indices])<EOL>collected_binned_mags['<STR_LIT>'] = binned_jd<EOL>collected_binned_mags['<STR_LIT>'] = binsize<EOL>collected_binned_mags['<STR_LIT>'] = (<EOL>np.array([np.median(finite_mags[x])<EOL>for x in binned_finite_timeseries_indices])<EOL>)<EOL>return collected_binned_mags<EOL>

Bins the given mag/flux time-series in time using the bin size given.

    Parameters
    ----------

    times,mags : np.array
        The magnitude/flux time-series to bin in time. Non-finite elements will
        be removed from these arrays. At least 10 elements in each array are
        required for this function to operate.

    binsize : float
        The bin size to use to group together measurements closer than this
        amount in time. This is in seconds.

    minbinelems : int
        The minimum number of elements required per bin to include it in the
        output.

    Returns
    -------

    dict
        A dict of the following form is returned::

            {'jdbin_indices': a list of the index arrays into the nan-filtered
                              input arrays per each bin,
             'jdbins': list of bin boundaries for each bin,
             'nbins': the number of bins generated,
             'binnedtimes': the time values associated with each time bin;
                            this is the median of the times in each bin,
             'binnedmags': the mag/flux values associated with each time bin;
                           this is the median of the mags/fluxes in each bin}


def time_bin_magseries_with_errs(times, mags, errs,<EOL>binsize=<NUM_LIT>,<EOL>minbinelems=<NUM_LIT:7>):

<EOL>if not(times.shape and mags.shape and errs.shape and<EOL>len(times) > <NUM_LIT:9> and len(mags) > <NUM_LIT:9>):<EOL><INDENT>LOGERROR("<STR_LIT>")<EOL>return<EOL><DEDENT>finiteind = np.isfinite(mags) & np.isfinite(times) & np.isfinite(errs)<EOL>finite_times = times[finiteind]<EOL>finite_mags = mags[finiteind]<EOL>finite_errs = errs[finiteind]<EOL>binsizejd = binsize/(<NUM_LIT>)<EOL>nbins = int(np.ceil((np.nanmax(finite_times) -<EOL>np.nanmin(finite_times))/binsizejd) + <NUM_LIT:1>)<EOL>minjd = np.nanmin(finite_times)<EOL>jdbins = [(minjd + x*binsizejd) for x in range(nbins)]<EOL>time_coords = np.array([[x,<NUM_LIT:1.0>] for x in finite_times])<EOL>jdtree = cKDTree(time_coords)<EOL>binned_finite_timeseries_indices = []<EOL>collected_binned_mags = {}<EOL>for jd in jdbins:<EOL><INDENT>bin_indices = jdtree.query_ball_point(np.array([jd,<NUM_LIT:1.0>]),<EOL>binsizejd/<NUM_LIT>, p=<NUM_LIT:1.0>)<EOL>if (bin_indices not in binned_finite_timeseries_indices and<EOL>len(bin_indices) >= minbinelems):<EOL><INDENT>binned_finite_timeseries_indices.append(bin_indices)<EOL><DEDENT><DEDENT>binned_finite_timeseries_indices = [np.array(x) for x in<EOL>binned_finite_timeseries_indices]<EOL>collected_binned_mags['<STR_LIT>'] = binned_finite_timeseries_indices<EOL>collected_binned_mags['<STR_LIT>'] = np.array(jdbins)<EOL>collected_binned_mags['<STR_LIT>'] = len(binned_finite_timeseries_indices)<EOL>binned_jd = np.array([np.median(finite_times[x])<EOL>for x in binned_finite_timeseries_indices])<EOL>collected_binned_mags['<STR_LIT>'] = binned_jd<EOL>collected_binned_mags['<STR_LIT>'] = binsize<EOL>collected_binned_mags['<STR_LIT>'] = (<EOL>np.array([np.median(finite_mags[x])<EOL>for x in binned_finite_timeseries_indices])<EOL>)<EOL>collected_binned_mags['<STR_LIT>'] = (<EOL>np.array([np.median(finite_errs[x])<EOL>for x in binned_finite_timeseries_indices])<EOL>)<EOL>return collected_binned_mags<EOL>

Bins the given mag/flux time-series in time using the bin size given.

    Parameters
    ----------

    times,mags,errs : np.array
        The magnitude/flux time-series and associated measurement errors to bin
        in time. Non-finite elements will be removed from these arrays. At least
        10 elements in each array are required for this function to operate.

    binsize : float
        The bin size to use to group together measurements closer than this
        amount in time. This is in seconds.

    minbinelems : int
        The minimum number of elements required per bin to include it in the
        output.

    Returns
    -------

    dict
        A dict of the following form is returned::

            {'jdbin_indices': a list of the index arrays into the nan-filtered
                              input arrays per each bin,
             'jdbins': list of bin boundaries for each bin,
             'nbins': the number of bins generated,
             'binnedtimes': the time values associated with each time bin;
                            this is the median of the times in each bin,
             'binnedmags': the mag/flux values associated with each time bin;
                           this is the median of the mags/fluxes in each bin,
             'binnederrs': the err values associated with each time bin;
                           this is the median of the errs in each bin}


<EOL>if not(phases.shape and mags.shape and len(phases) > <NUM_LIT:10> and len(mags) > <NUM_LIT:10>):<EOL><INDENT>LOGERROR("<STR_LIT>")<EOL>return<EOL><DEDENT>finiteind = np.isfinite(mags) & np.isfinite(phases)<EOL>finite_phases = phases[finiteind]<EOL>finite_mags = mags[finiteind]<EOL>nbins = int(np.ceil((np.nanmax(finite_phases) -<EOL>np.nanmin(finite_phases))/binsize) + <NUM_LIT:1>)<EOL>minphase = np.nanmin(finite_phases)<EOL>phasebins = [(minphase + x*binsize) for x in range(nbins)]<EOL>time_coords = np.array([[x,<NUM_LIT:1.0>] for x in finite_phases])<EOL>phasetree = cKDTree(time_coords)<EOL>binned_finite_phaseseries_indices = []<EOL>collected_binned_mags = {}<EOL>for phase in phasebins:<EOL><INDENT>bin_indices = phasetree.query_ball_point(np.array([phase,<NUM_LIT:1.0>]),<EOL>binsize/<NUM_LIT>, p=<NUM_LIT:1.0>)<EOL>if (bin_indices not in binned_finite_phaseseries_indices and<EOL>len(bin_indices) >= minbinelems):<EOL><INDENT>binned_finite_phaseseries_indices.append(bin_indices)<EOL><DEDENT><DEDENT>binned_finite_phaseseries_indices = [np.array(x) for x in<EOL>binned_finite_phaseseries_indices]<EOL>collected_binned_mags['<STR_LIT>'] = (<EOL>binned_finite_phaseseries_indices<EOL>)<EOL>collected_binned_mags['<STR_LIT>'] = phasebins<EOL>collected_binned_mags['<STR_LIT>'] = len(binned_finite_phaseseries_indices)<EOL>binned_phase = np.array([np.median(finite_phases[x])<EOL>for x in binned_finite_phaseseries_indices])<EOL>collected_binned_mags['<STR_LIT>'] = binned_phase<EOL>collected_binned_mags['<STR_LIT>'] = binsize<EOL>collected_binned_mags['<STR_LIT>'] = (<EOL>np.array([np.median(finite_mags[x])<EOL>for x in binned_finite_phaseseries_indices])<EOL>)<EOL>return collected_binned_mags<EOL>

Bins a phased magnitude/flux time-series using the bin size provided.

    Parameters
    ----------

    phases,mags : np.array
        The phased magnitude/flux time-series to bin in phase. Non-finite
        elements will be removed from these arrays. At least 10 elements in each
        array are required for this function to operate.

    binsize : float
        The bin size to use to group together measurements closer than this
        amount in phase. This is in units of phase.

    minbinelems : int
        The minimum number of elements required per bin to include it in the
        output.

    Returns
    -------

    dict
        A dict of the following form is returned::

            {'phasebin_indices': a list of the index arrays into the
                                 nan-filtered input arrays per each bin,
             'phasebins': list of bin boundaries for each bin,
             'nbins': the number of bins generated,
             'binnedphases': the phase values associated with each phase bin;
                            this is the median of the phase value in each bin,
             'binnedmags': the mag/flux values associated with each phase bin;
                           this is the median of the mags/fluxes in each bin}