signature:
def epd_magseries ( times , mags , errs , fsv , fdv , fkv , xcc , ycc , bgv , bge , iha , izd , magsarefluxes = False , epdsmooth_sigclip = 3.0 , epdsmooth_windowsize = 21 , epdsmooth_func = smooth_magseries_savgol , epdsmooth_extraparams = None ) :
    '''Detrends a magnitude series using External Parameter Decorrelation .
 Requires a set of external parameters similar to those present in HAT light
 curves . At the moment , the HAT light - curve - specific external parameters are :
 - S : the ' fsv ' column in light curves ,
 - D : the ' fdv ' column in light curves ,
 - K : the ' fkv ' column in light curves ,
 - x coords : the ' xcc ' column in light curves ,
 - y coords : the ' ycc ' column in light curves ,
 - background value : the ' bgv ' column in light curves ,
 - background error : the ' bge ' column in light curves ,
 - hour angle : the ' iha ' column in light curves ,
 - zenith distance : the ' izd ' column in light curves
 S , D , and K are defined as follows :
 - S - > measure of PSF sharpness ( ~ 1 / sigma ^ 2 sosmaller S = wider PSF )
 - D - > measure of PSF ellipticity in xy direction
 - K - > measure of PSF ellipticity in cross direction
 S , D , K are related to the PSF ' s variance and covariance , see eqn 30-33 in
 A . Pal ' s thesis : https : / / arxiv . org / abs / 0906.3486
 NOTE : The errs are completely ignored and returned unchanged ( except for
 sigclip and finite filtering ) .
 Parameters
 times , mags , errs : np . array
 The input mag / flux time - series to detrend .
 fsv : np . array
 Array containing the external parameter ` S ` of the same length as times .
 fdv : np . array
 Array containing the external parameter ` D ` of the same length as times .
 fkv : np . array
 Array containing the external parameter ` K ` of the same length as times .
 xcc : np . array
 Array containing the external parameter ` x - coords ` of the same length as
 times .
 ycc : np . array
 Array containing the external parameter ` y - coords ` of the same length as
 times .
 bgv : np . array
 Array containing the external parameter ` background value ` of the same
 length as times .
 bge : np . array
 Array containing the external parameter ` background error ` of the same
 length as times .
 iha : np . array
 Array containing the external parameter ` hour angle ` of the same length
 as times .
 izd : np . array
 Array containing the external parameter ` zenith distance ` of the same
 length as times .
 magsarefluxes : bool
 Set this to True if ` mags ` actually contains fluxes .
 epdsmooth _ sigclip : float or int or sequence of two floats / ints or None
 This specifies how to sigma - clip the input LC before fitting the EPD
 function to it .
 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 .
 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 full tuple returned by scipy . leastsq ,
 ' fitmags ' : the EPD fit function evaluated at times ,
 ' mags _ median ' : this is median of the EPD mags ,
 ' mags _ mad ' : this is the MAD of EPD mags }'''

implementation:
finind = np . isfinite ( times ) & np . isfinite ( mags ) & np . isfinite ( errs )
ftimes , fmags , ferrs = times [ : : ] [ finind ] , mags [ : : ] [ finind ] , errs [ : : ] [ finind ]
ffsv , ffdv , ffkv , fxcc , fycc , fbgv , fbge , fiha , fizd = ( fsv [ : : ] [ finind ] , fdv [ : : ] [ finind ] , fkv [ : : ] [ finind ] , xcc [ : : ] [ finind ] , ycc [ : : ] [ finind ] , bgv [ : : ] [ finind ] , bge [ : : ] [ finind ] , iha [ : : ] [ finind ] , izd [ : : ] [ finind ] , )
stimes , smags , serrs , separams = sigclip_magseries_with_extparams ( times , mags , errs , [ fsv , fdv , fkv , xcc , ycc , bgv , bge , iha , izd ] , sigclip = epdsmooth_sigclip , magsarefluxes = magsarefluxes )
sfsv , sfdv , sfkv , sxcc , sycc , sbgv , sbge , siha , sizd = separams
# smooth the signal
if isinstance ( epdsmooth_extraparams , dict ) :
    smoothedmags = epdsmooth_func ( smags , epdsmooth_windowsize , ** epdsmooth_extraparams )
else :
    smoothedmags = epdsmooth_func ( smags , epdsmooth_windowsize )
# initial fit coeffs
initcoeffs = np . zeros ( 22 )
# fit the smoothed mags and find the EPD function coefficients
leastsqfit = leastsq ( _epd_residual , initcoeffs , args = ( smoothedmags , sfsv , sfdv , sfkv , sxcc , sycc , sbgv , sbge , siha , sizd ) , full_output = True )
# if the fit succeeds , then get the EPD mags
if leastsqfit [ - 1 ] in ( 1 , 2 , 3 , 4 ) :
    fitcoeffs = leastsqfit [ 0 ]
    epdfit = _epd_function ( fitcoeffs , ffsv , ffdv , ffkv , fxcc , fycc , fbgv , fbge , fiha , fizd )
    epdmags = npmedian ( fmags ) + fmags - epdfit
    retdict = { 'times' : ftimes , 'mags' : epdmags , 'errs' : ferrs , 'fitcoeffs' : fitcoeffs , 'fitinfo' : leastsqfit , 'fitmags' : epdfit , 'mags_median' : npmedian ( epdmags ) , 'mags_mad' : npmedian ( npabs ( epdmags - npmedian ( epdmags ) ) ) }
    return retdict
# if the solution fails , return nothing
else :
    LOGERROR ( 'EPD fit did not converge' )
    return None


signature:
def epd_magseries_extparams ( times , mags , errs , externalparam_arrs , initial_coeff_guess , magsarefluxes = False , epdsmooth_sigclip = 3.0 , epdsmooth_windowsize = 21 , epdsmooth_func = smooth_magseries_savgol , epdsmooth_extraparams = None , objective_func = _epd_residual2 , objective_kwargs = None , optimizer_func = least_squares , optimizer_kwargs = None , ) :
    '''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 }'''

implementation:
# get finite times , mags , errs
finind = np . isfinite ( times ) & np . isfinite ( mags ) & np . isfinite ( errs )
ftimes , fmags , ferrs = times [ : : ] [ finind ] , mags [ : : ] [ finind ] , errs [ : : ] [ finind ]
finalparam_arrs = [ ]
for ep in externalparam_arrs :
    finalparam_arrs . append ( ep [ : : ] [ finind ] )
# sigclip the LC to pass into the smoothing for EPD fit
stimes , smags , serrs , eparams = sigclip_magseries_with_extparams ( times . copy ( ) , mags . copy ( ) , errs . copy ( ) , [ x . copy ( ) for x in externalparam_arrs ] , sigclip = epdsmooth_sigclip , magsarefluxes = magsarefluxes )
# smooth the signal before fitting the function to it
if isinstance ( epdsmooth_extraparams , dict ) :
    smoothedmags = epdsmooth_func ( smags , epdsmooth_windowsize , ** epdsmooth_extraparams )
else :
    smoothedmags = epdsmooth_func ( smags , epdsmooth_windowsize )
# the initial coeffs are passed in here
initial_coeffs = initial_coeff_guess
# reform the objective function with any optional kwargs
if objective_kwargs is not None :
    obj_func = partial ( objective_func , ** objective_kwargs )
else :
    obj_func = objective_func
# run the optimizer function by passing in the objective function , the
# coeffs , and the smoothed mags and external params as part of the ` args `
# tuple
if not optimizer_kwargs :
    optimizer_kwargs = { }
fit_info = optimizer_func ( obj_func , initial_coeffs , args = ( stimes , smoothedmags , serrs , * eparams ) , ** optimizer_kwargs )
if fit_info . success :
    fit_coeffs = fit_info . x
    epd_mags = np . median ( fmags ) + obj_func ( fit_coeffs , ftimes , fmags , ferrs , * finalparam_arrs )
    retdict = { 'times' : ftimes , 'mags' : epd_mags , 'errs' : ferrs , 'fitcoeffs' : fit_coeffs , 'fitinfo' : fit_info , 'mags_median' : npmedian ( epd_mags ) , 'mags_mad' : npmedian ( npabs ( epd_mags - npmedian ( epd_mags ) ) ) }
    return retdict
# if the solution fails , return nothing
else :
    LOGERROR ( 'EPD fit did not converge' )
    return None


signature:
def rfepd_magseries ( times , mags , errs , externalparam_arrs , magsarefluxes = False , epdsmooth = True , epdsmooth_sigclip = 3.0 , epdsmooth_windowsize = 21 , epdsmooth_func = smooth_magseries_savgol , epdsmooth_extraparams = None , rf_subsample = 1.0 , rf_ntrees = 300 , rf_extraparams = { 'criterion' : 'mse' , 'oob_score' : False , 'n_jobs' : - 1 } ) :
    '''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 .'''

implementation:
# get finite times , mags , errs
finind = np . isfinite ( times ) & np . isfinite ( mags ) & np . isfinite ( errs )
ftimes , fmags , ferrs = times [ : : ] [ finind ] , mags [ : : ] [ finind ] , errs [ : : ] [ finind ]
finalparam_arrs = [ ]
for ep in externalparam_arrs :
    finalparam_arrs . append ( ep [ : : ] [ finind ] )
stimes , smags , serrs , eparams = sigclip_magseries_with_extparams ( times , mags , errs , externalparam_arrs , sigclip = epdsmooth_sigclip , magsarefluxes = magsarefluxes )
# smoothing is optional for RFR because we train on a fraction of the mag
# series and so should not require a smoothed input to fit a function to
if epdsmooth : # smooth the signal
    if isinstance ( epdsmooth_extraparams , dict ) :
        smoothedmags = epdsmooth_func ( smags , epdsmooth_windowsize , ** epdsmooth_extraparams )
    else :
        smoothedmags = epdsmooth_func ( smags , epdsmooth_windowsize )
else :
    smoothedmags = smags
# set up the regressor
if isinstance ( rf_extraparams , dict ) :
    RFR = RandomForestRegressor ( n_estimators = rf_ntrees , ** rf_extraparams )
else :
    RFR = RandomForestRegressor ( n_estimators = rf_ntrees )
# collect the features
features = np . column_stack ( eparams )
# fit , then generate the predicted values , then get corrected values
# we fit on a randomly selected subsample of all the mags
if rf_subsample < 1.0 :
    featureindices = np . arange ( smoothedmags . size )
    # these are sorted because time - order should be important
    training_indices = np . sort ( npr . choice ( featureindices , size = int ( rf_subsample * smoothedmags . size ) , replace = False ) )
else :
    training_indices = np . arange ( smoothedmags . size )
RFR . fit ( features [ training_indices , : ] , smoothedmags [ training_indices ] )
# predict on the full feature set
flux_corrections = RFR . predict ( np . column_stack ( finalparam_arrs ) )
corrected_fmags = npmedian ( fmags ) + fmags - flux_corrections
retdict = { 'times' : ftimes , 'mags' : corrected_fmags , 'errs' : ferrs , 'feature_importances' : RFR . feature_importances_ , 'regressor' : RFR , 'mags_median' : npmedian ( corrected_fmags ) , 'mags_mad' : npmedian ( npabs ( corrected_fmags - npmedian ( corrected_fmags ) ) ) }
return retdict


signature:
def lcfit_features ( times , mags , errs , period , fourierorder = 5 , # these are depth , duration , ingress duration
transitparams = ( - 0.01 , 0.1 , 0.1 ) , # these are depth , duration , depth ratio , secphase
ebparams = ( - 0.2 , 0.3 , 0.7 , 0.5 ) , sigclip = 10.0 , magsarefluxes = False , fitfailure_means_featurenan = False , verbose = True ) :
    '''This calculates various features related to fitting models to light
 curves .
 This function :
 - calculates ` R _ ij ` and ` phi _ ij ` ratios for Fourier fit amplitudes and
 phases .
 - calculates the reduced chi - sq for fourier , EB , and planet transit fits .
 - calculates the reduced chi - sq for fourier , EB , planet transit fits w / 2 x
 period .
 Parameters
 times , mags , errs : np . array
 The input mag / flux time - series to calculate periodic features for .
 period : float
 The period of variabiity to use to phase the light curve .
 fourierorder : int
 The Fourier order to use to generate sinusoidal function and fit that to
 the phased light curve .
 transitparams : list of floats
 The transit depth , duration , and ingress duration to use to generate a
 trapezoid planet transit model fit to the phased light curve . The period
 used is the one provided in ` period ` , while the epoch is automatically
 obtained from a spline fit to the phased light curve .
 ebparams : list of floats
 The primary eclipse depth , eclipse duration , the primary - secondary depth
 ratio , and the phase of the secondary eclipse to use to generate an
 eclipsing binary model fit to the phased light curve . The period used is
 the one provided in ` period ` , while the epoch is automatically obtained
 from a spline fit to the phased light curve .
 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
 Set this to True if the input measurements in ` mags ` are actually
 fluxes .
 fitfailure _ means _ featurenan : bool
 If the planet , EB and EBx2 fits don ' t return standard errors because the
 covariance matrix could not be generated , then the fit is suspicious and
 the features calculated can ' t be trusted . If
 ` fitfailure _ means _ featurenan ` is True , then the output features for
 these fits will be set to nan .
 verbose : bool
 If True , will indicate progress while working .
 Returns
 dict
 A dict of all the features calculated is returned .'''

implementation:
# get the finite values
finind = np . isfinite ( times ) & np . isfinite ( mags ) & np . isfinite ( errs )
ftimes , fmags , ferrs = times [ finind ] , mags [ finind ] , errs [ finind ]
# get nonzero errors
nzind = np . nonzero ( ferrs )
ftimes , fmags , ferrs = ftimes [ nzind ] , fmags [ nzind ] , ferrs [ nzind ]
# get the MAD of the unphased light curve
lightcurve_median = np . median ( fmags )
lightcurve_mad = np . median ( np . abs ( fmags - lightcurve_median ) )
# fourier fit
# we fit a Fourier series to the light curve using the best period and
# extract the amplitudes and phases up to the 8th order to fit the LC . the
# various ratios of the amplitudes A _ ij and the differences in the phases
# phi _ ij are also used as periodic variability features
# do the fit
ffit = lcfit . fourier_fit_magseries ( ftimes , fmags , ferrs , period , fourierorder = fourierorder , sigclip = sigclip , magsarefluxes = magsarefluxes , verbose = verbose )
# get the coeffs and redchisq
fourier_fitcoeffs = ffit [ 'fitinfo' ] [ 'finalparams' ]
fourier_chisq = ffit [ 'fitchisq' ]
fourier_redchisq = ffit [ 'fitredchisq' ]
if fourier_fitcoeffs is not None :
    fourier_modelmags , _ , _ , fpmags , _ = sinusoidal . fourier_sinusoidal_func ( [ period , ffit [ 'fitinfo' ] [ 'fitepoch' ] , ffit [ 'fitinfo' ] [ 'finalparams' ] [ : fourierorder ] , ffit [ 'fitinfo' ] [ 'finalparams' ] [ fourierorder : ] ] , ftimes , fmags , ferrs )
    fourier_residuals = fourier_modelmags - fpmags
    fourier_residual_median = np . median ( fourier_residuals )
    fourier_residual_mad = np . median ( np . abs ( fourier_residuals - fourier_residual_median ) )
    # break them out into amps and phases
    famplitudes = fourier_fitcoeffs [ : fourierorder ]
    fphases = fourier_fitcoeffs [ fourierorder : ]
    famp_combos = combinations ( famplitudes , 2 )
    famp_cinds = combinations ( range ( len ( famplitudes ) ) , 2 )
    fpha_combos = combinations ( fphases , 2 )
    fpha_cinds = combinations ( range ( len ( fphases ) ) , 2 )
else :
    LOGERROR ( 'LC fit to sinusoidal series model failed, ' 'using initial params' )
    initfourieramps = [ 0.6 ] + [ 0.2 ] * ( fourierorder - 1 )
    initfourierphas = [ 0.1 ] + [ 0.1 ] * ( fourierorder - 1 )
    fourier_modelmags , _ , _ , fpmags , _ = sinusoidal . fourier_sinusoidal_func ( [ period , ffit [ 'fitinfo' ] [ 'fitepoch' ] , initfourieramps , initfourierphas ] , ftimes , fmags , ferrs )
    fourier_residuals = fourier_modelmags - fpmags
    fourier_residual_median = np . median ( fourier_residuals )
    fourier_residual_mad = np . median ( np . abs ( fourier_residuals - fourier_residual_median ) )
    # break them out into amps and phases
    famplitudes = initfourieramps
    fphases = initfourierphas
    famp_combos = combinations ( famplitudes , 2 )
    famp_cinds = combinations ( range ( len ( famplitudes ) ) , 2 )
    fpha_combos = combinations ( fphases , 2 )
    fpha_cinds = combinations ( range ( len ( fphases ) ) , 2 )
fampratios = { }
fphadiffs = { }
# get the ratios for all fourier coeff combinations
for ampi , ampc , phai , phac in zip ( famp_cinds , famp_combos , fpha_cinds , fpha_combos ) :
    ampratind = 'R_%s%s' % ( ampi [ 1 ] + 1 , ampi [ 0 ] + 1 )
    # this is R _ ij
    amprat = ampc [ 1 ] / ampc [ 0 ]
    phadiffind = 'phi_%s%s' % ( phai [ 1 ] + 1 , phai [ 0 ] + 1 )
    # this is phi _ ij
    phadiff = phac [ 1 ] - phai [ 0 ] * phac [ 0 ]
    fampratios [ ampratind ] = amprat
    fphadiffs [ phadiffind ] = phadiff
# update the outdict for the Fourier fit results
outdict = { 'fourier_ampratios' : fampratios , 'fourier_phadiffs' : fphadiffs , 'fourier_fitparams' : fourier_fitcoeffs , 'fourier_redchisq' : fourier_redchisq , 'fourier_chisq' : fourier_chisq , 'fourier_residual_median' : fourier_residual_median , 'fourier_residual_mad' : fourier_residual_mad , 'fourier_residual_mad_over_lcmad' : fourier_residual_mad / lightcurve_mad }
# EB and planet fits will find the epoch automatically
planetfitparams = [ period , None , transitparams [ 0 ] , transitparams [ 1 ] , transitparams [ 2 ] ]
ebfitparams = [ period , None , ebparams [ 0 ] , ebparams [ 1 ] , ebparams [ 2 ] , ebparams [ 3 ] ]
# do the planet and EB fit with this period
planet_fit = lcfit . traptransit_fit_magseries ( ftimes , fmags , ferrs , planetfitparams , sigclip = sigclip , magsarefluxes = magsarefluxes , verbose = verbose )
planetfit_finalparams = planet_fit [ 'fitinfo' ] [ 'finalparams' ]
planetfit_finalparamerrs = planet_fit [ 'fitinfo' ] [ 'finalparamerrs' ]
if planetfit_finalparamerrs is None and fitfailure_means_featurenan :
    LOGWARNING ( 'planet fit: no standard errors available ' 'for fit parameters, fit is bad, ' 'setting fit chisq and red-chisq to np.nan' )
    planetfit_chisq = np . nan
    planetfit_redchisq = np . nan
    planet_residual_median = np . nan
    planet_residual_mad = np . nan
    planet_residual_mad_over_lcmad = np . nan
else :
    planetfit_chisq = planet_fit [ 'fitchisq' ]
    planetfit_redchisq = planet_fit [ 'fitredchisq' ]
    if planetfit_finalparams is not None :
        planet_modelmags , _ , _ , ppmags , _ = transits . trapezoid_transit_func ( planetfit_finalparams , ftimes , fmags , ferrs )
    else :
        LOGERROR ( 'LC fit to transit planet model ' 'failed, using initial params' )
        planet_modelmags , _ , _ , ppmags , _ = transits . trapezoid_transit_func ( planetfitparams , ftimes , fmags , ferrs )
    planet_residuals = planet_modelmags - ppmags
    planet_residual_median = np . median ( planet_residuals )
    planet_residual_mad = np . median ( np . abs ( planet_residuals - planet_residual_median ) )
    planet_residual_mad_over_lcmad = planet_residual_mad / lightcurve_mad
eb_fit = lcfit . gaussianeb_fit_magseries ( ftimes , fmags , ferrs , ebfitparams , sigclip = sigclip , magsarefluxes = magsarefluxes , verbose = verbose )
ebfit_finalparams = eb_fit [ 'fitinfo' ] [ 'finalparams' ]
ebfit_finalparamerrs = eb_fit [ 'fitinfo' ] [ 'finalparamerrs' ]
if ebfit_finalparamerrs is None and fitfailure_means_featurenan :
    LOGWARNING ( 'EB fit: no standard errors available ' 'for fit parameters, fit is bad, ' 'setting fit chisq and red-chisq to np.nan' )
    ebfit_chisq = np . nan
    ebfit_redchisq = np . nan
    eb_residual_median = np . nan
    eb_residual_mad = np . nan
    eb_residual_mad_over_lcmad = np . nan
else :
    ebfit_chisq = eb_fit [ 'fitchisq' ]
    ebfit_redchisq = eb_fit [ 'fitredchisq' ]
    if ebfit_finalparams is not None :
        eb_modelmags , _ , _ , ebpmags , _ = eclipses . invgauss_eclipses_func ( ebfit_finalparams , ftimes , fmags , ferrs )
    else :
        LOGERROR ( 'LC fit to EB model failed, using initial params' )
        eb_modelmags , _ , _ , ebpmags , _ = eclipses . invgauss_eclipses_func ( ebfitparams , ftimes , fmags , ferrs )
    eb_residuals = eb_modelmags - ebpmags
    eb_residual_median = np . median ( eb_residuals )
    eb_residual_mad = np . median ( np . abs ( eb_residuals - eb_residual_median ) )
    eb_residual_mad_over_lcmad = eb_residual_mad / lightcurve_mad
# do the EB fit with 2 x period
ebfitparams [ 0 ] = ebfitparams [ 0 ] * 2.0
eb_fitx2 = lcfit . gaussianeb_fit_magseries ( ftimes , fmags , ferrs , ebfitparams , sigclip = sigclip , magsarefluxes = magsarefluxes , verbose = verbose )
ebfitx2_finalparams = eb_fitx2 [ 'fitinfo' ] [ 'finalparams' ]
ebfitx2_finalparamerrs = eb_fitx2 [ 'fitinfo' ] [ 'finalparamerrs' ]
if ebfitx2_finalparamerrs is None and fitfailure_means_featurenan :
    LOGWARNING ( 'EB x2 period fit: no standard errors available ' 'for fit parameters, fit is bad, ' 'setting fit chisq and red-chisq to np.nan' )
    ebfitx2_chisq = np . nan
    ebfitx2_redchisq = np . nan
    ebx2_residual_median = np . nan
    ebx2_residual_mad = np . nan
    ebx2_residual_mad_over_lcmad = np . nan
else :
    ebfitx2_chisq = eb_fitx2 [ 'fitchisq' ]
    ebfitx2_redchisq = eb_fitx2 [ 'fitredchisq' ]
    if ebfitx2_finalparams is not None :
        ebx2_modelmags , _ , _ , ebx2pmags , _ = ( eclipses . invgauss_eclipses_func ( ebfitx2_finalparams , ftimes , fmags , ferrs ) )
    else :
        LOGERROR ( 'LC fit to EB model with 2xP failed, using initial params' )
        ebx2_modelmags , _ , _ , ebx2pmags , _ = ( eclipses . invgauss_eclipses_func ( ebfitparams , ftimes , fmags , ferrs ) )
    ebx2_residuals = ebx2_modelmags - ebx2pmags
    ebx2_residual_median = np . median ( ebx2_residuals )
    ebx2_residual_mad = np . median ( np . abs ( ebx2_residuals - ebx2_residual_median ) )
    ebx2_residual_mad_over_lcmad = ebx2_residual_mad / lightcurve_mad
# update the outdict
outdict . update ( { 'planet_fitparams' : planetfit_finalparams , 'planet_chisq' : planetfit_chisq , 'planet_redchisq' : planetfit_redchisq , 'planet_residual_median' : planet_residual_median , 'planet_residual_mad' : planet_residual_mad , 'planet_residual_mad_over_lcmad' : ( planet_residual_mad_over_lcmad , ) , 'eb_fitparams' : ebfit_finalparams , 'eb_chisq' : ebfit_chisq , 'eb_redchisq' : ebfit_redchisq , 'eb_residual_median' : eb_residual_median , 'eb_residual_mad' : eb_residual_mad , 'eb_residual_mad_over_lcmad' : ( eb_residual_mad_over_lcmad , ) , 'ebx2_fitparams' : ebfitx2_finalparams , 'ebx2_chisq' : ebfitx2_chisq , 'ebx2_redchisq' : ebfitx2_redchisq , 'ebx2_residual_median' : ebx2_residual_median , 'ebx2_residual_mad' : ebx2_residual_mad , 'ebx2_residual_mad_over_lcmad' : ( ebx2_residual_mad_over_lcmad , ) , } )
return outdict


signature:
def periodogram_features ( pgramlist , times , mags , errs , sigclip = 10.0 , pdiff_threshold = 1.0e-4 , sidereal_threshold = 1.0e-4 , sampling_peak_multiplier = 5.0 , sampling_startp = None , sampling_endp = None , verbose = True ) :
    '''This calculates various periodogram features ( for each periodogram ) .
 The following features are obtained :
 - For all best periods from all periodogram methods in ` pgramlist ` ,
 calculates the number of these with peaks that are at least
 ` sampling _ peak _ multiplier ` x time - sampling periodogram peak at the same
 period . This indicates how likely the ` pgramlist ` periodogram peaks are to
 being real as opposed to just being caused by time - sampling
 window - function of the observations .
 - For all best periods from all periodogram methods in ` pgramlist ` ,
 calculates the number of best periods which are consistent with a sidereal
 day ( 1.0027379 and 0.9972696 ) , likely indicating that they ' re not real .
 - For all best periods from all periodogram methods in ` pgramlist ` ,
 calculates the number of cross - wise period differences for all of these
 that fall below the ` pdiff _ threshold ` value . If this is high , most of the
 period - finders in ` pgramlist ` agree on their best period results , so it ' s
 likely the periods found are real .
 Parameters
 pgramlist : list of dicts
 This is a list of dicts returned by any of the periodfinding methods in
 : py : mod : ` astrobase . periodbase ` . This can also be obtained from the
 resulting pickle from the : py : func : astrobase . lcproc . periodsearch . run _ pf `
 function . It ' s a good idea to make ` pgramlist ` a list of periodogram
 lists from all magnitude columns in the input light curve to test
 periodic variability across all magnitude columns ( e . g . period diffs
 between EPD and TFA mags )
 times , mags , errs : np . array
 The input flux / mag time - series to use to calculate features . These are
 used to recalculate the time - sampling L - S periodogram ( using
 : py : func : ` astrobase . periodbase . zgls . specwindow _ lsp ` ) if one is not
 present in pgramlist . If it ' s present , these can all be set to None .
 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 .
 pdiff _ threshold : float
 This is the max difference between periods to consider them the same .
 sidereal _ threshold : float
 This is the max difference between any of the ' best ' periods and the
 sidereal day periods to consider them the same .
 sampling _ peak _ multiplier : float
 This is the minimum multiplicative factor of a ' best ' period ' s
 normalized periodogram peak over the sampling periodogram peak at the
 same period required to accept the ' best ' period as possibly real .
 sampling _ startp , sampling _ endp : float
 If the ` pgramlist ` doesn ' t have a time - sampling Lomb - Scargle
 periodogram , it will be obtained automatically . Use these kwargs to
 control the minimum and maximum period interval to be searched when
 generating this periodogram .
 verbose : bool
 If True , will indicate progress and report errors .
 Returns
 dict
 Returns a dict with all of the periodogram features calculated .'''

implementation:
# run the sampling peak periodogram if necessary
pfmethodlist = [ pgram [ 'method' ] for pgram in pgramlist ]
if 'win' not in pfmethodlist : # get the finite values
    finind = np . isfinite ( times ) & np . isfinite ( mags ) & np . isfinite ( errs )
    ftimes , fmags , ferrs = times [ finind ] , mags [ finind ] , errs [ finind ]
    # get nonzero errors
    nzind = np . nonzero ( ferrs )
    ftimes , fmags , ferrs = ftimes [ nzind ] , fmags [ nzind ] , ferrs [ nzind ]
    sampling_lsp = specwindow_lsp ( times , mags , errs , startp = sampling_startp , endp = sampling_endp , sigclip = sigclip , verbose = verbose )
else :
    sampling_lsp = pgramlist [ pfmethodlist . index ( 'win' ) ]
# get the normalized sampling periodogram peaks
normalized_sampling_lspvals = ( sampling_lsp [ 'lspvals' ] / ( np . nanmax ( sampling_lsp [ 'lspvals' ] ) - np . nanmin ( sampling_lsp [ 'lspvals' ] ) ) )
normalized_sampling_periods = sampling_lsp [ 'periods' ]
# go through the periodograms and calculate normalized peak height of best
# periods over the normalized peak height of the sampling periodogram at the
# same periods
for pfm , pgram in zip ( pfmethodlist , pgramlist ) :
    if pfm == 'pdm' :
        best_peak_sampling_ratios = [ ]
        close_to_sidereal_flag = [ ]
        periods = pgram [ 'periods' ]
        peaks = pgram [ 'lspvals' ]
        normalized_peaks = ( 1.0 - peaks ) / ( np . nanmax ( 1.0 - peaks ) - np . nanmin ( 1.0 - peaks ) )
        # get the best period normalized peaks
        if pgram [ 'nbestperiods' ] is None :
            LOGERROR ( 'no period results for method: %s' % pfm )
            continue
        for bp in pgram [ 'nbestperiods' ] :
            if np . isfinite ( bp ) : # first , get the normalized peak ratio
                thisp_norm_pgrampeak = normalized_peaks [ periods == bp ]
                thisp_sampling_pgramind = ( np . abs ( normalized_sampling_periods - bp ) < pdiff_threshold )
                thisp_sampling_peaks = normalized_sampling_lspvals [ thisp_sampling_pgramind ]
                if thisp_sampling_peaks . size > 1 :
                    thisp_sampling_ratio = ( thisp_norm_pgrampeak / np . mean ( thisp_sampling_peaks ) )
                elif thisp_sampling_peaks . size == 1 :
                    thisp_sampling_ratio = ( thisp_norm_pgrampeak / thisp_sampling_peaks )
                else :
                    LOGERROR ( 'sampling periodogram is not defined ' 'at period %.5f, ' 'skipping calculation of ratio' % bp )
                    thisp_sampling_ratio = np . nan
                best_peak_sampling_ratios . append ( thisp_sampling_ratio )
                # next , see if the best periods are close to a sidereal day
                # or any multiples of thus
                sidereal_a_ratio = ( bp - 1.0027379 ) / bp
                sidereal_b_ratio = ( bp - 0.9972696 ) / bp
                if ( ( sidereal_a_ratio < sidereal_threshold ) or ( sidereal_b_ratio < sidereal_threshold ) ) :
                    close_to_sidereal_flag . append ( True )
                else :
                    close_to_sidereal_flag . append ( False )
            else :
                LOGERROR ( 'period is nan' )
                best_peak_sampling_ratios . append ( np . nan )
                close_to_sidereal_flag . append ( False )
        # update the pgram with these
        pgram [ 'nbestpeakratios' ] = best_peak_sampling_ratios
        pgram [ 'siderealflags' ] = close_to_sidereal_flag
    elif pfm != 'win' :
        best_peak_sampling_ratios = [ ]
        close_to_sidereal_flag = [ ]
        periods = pgram [ 'periods' ]
        peaks = pgram [ 'lspvals' ]
        normalized_peaks = peaks / ( np . nanmax ( peaks ) - np . nanmin ( peaks ) )
        # get the best period normalized peaks
        if pgram [ 'nbestperiods' ] is None :
            LOGERROR ( 'no period results for method: %s' % pfm )
            continue
        # first , get the best period normalized peaks
        for bp in pgram [ 'nbestperiods' ] :
            if np . isfinite ( bp ) :
                thisp_norm_pgrampeak = normalized_peaks [ periods == bp ]
                thisp_sampling_pgramind = ( np . abs ( normalized_sampling_periods - bp ) < pdiff_threshold )
                thisp_sampling_peaks = normalized_sampling_lspvals [ thisp_sampling_pgramind ]
                if thisp_sampling_peaks . size > 1 :
                    thisp_sampling_ratio = ( thisp_norm_pgrampeak / np . mean ( thisp_sampling_peaks ) )
                elif thisp_sampling_peaks . size == 1 :
                    thisp_sampling_ratio = ( thisp_norm_pgrampeak / thisp_sampling_peaks )
                else :
                    LOGERROR ( 'sampling periodogram is not defined ' 'at period %.5f, ' 'skipping calculation of ratio' % bp )
                    thisp_sampling_ratio = np . nan
                best_peak_sampling_ratios . append ( thisp_sampling_ratio )
                # next , see if the best periods are close to a sidereal day
                # or any multiples of thus
                sidereal_a_ratio = ( bp - 1.0027379 ) / bp
                sidereal_b_ratio = ( bp - 0.9972696 ) / bp
                if ( ( sidereal_a_ratio < sidereal_threshold ) or ( sidereal_b_ratio < sidereal_threshold ) ) :
                    close_to_sidereal_flag . append ( True )
                else :
                    close_to_sidereal_flag . append ( False )
            else :
                LOGERROR ( 'period is nan' )
                best_peak_sampling_ratios . append ( np . nan )
                close_to_sidereal_flag . append ( False )
        # update the pgram with these
        pgram [ 'nbestpeakratios' ] = best_peak_sampling_ratios
        pgram [ 'siderealflags' ] = close_to_sidereal_flag
# done with calculations , get the features we need
# get the best periods across all the period finding methods
all_bestperiods = np . concatenate ( [ x [ 'nbestperiods' ] for x in pgramlist if ( x [ 'method' ] != 'win' and x [ 'nbestperiods' ] is not None ) ] )
all_bestperiod_diffs = np . array ( [ abs ( a - b ) for a , b in combinations ( all_bestperiods , 2 ) ] )
all_sampling_ratios = np . concatenate ( [ x [ 'nbestpeakratios' ] for x in pgramlist if ( x [ 'method' ] != 'win' and x [ 'nbestperiods' ] is not None ) ] )
all_sidereal_flags = np . concatenate ( [ x [ 'siderealflags' ] for x in pgramlist if ( x [ 'method' ] != 'win' and x [ 'nbestperiods' ] is not None ) ] )
# bestperiods _ n _ abovesampling - number of top period estimates with peaks
# that are at least sampling _ peak _ multiplier x
# sampling peak height at the same period
bestperiods_n_abovesampling = ( all_sampling_ratios [ all_sampling_ratios > sampling_peak_multiplier ] ) . size
# bestperiods _ n _ sidereal - number of top period estimates that are
# consistent with a 1 day period ( 1.0027379 and
# 0.9972696 actually , for sidereal day period )
bestperiods_n_sidereal = all_sidereal_flags . sum ( )
# bestperiods _ diffn _ threshold - the number of cross - wise period diffs from
# all period finders that fall below the
# pdiff _ threshold
bestperiods_diffn_threshold = ( all_bestperiod_diffs < pdiff_threshold ) . size
resdict = { 'bestperiods_n_abovesampling' : bestperiods_n_abovesampling , 'bestperiods_n_sidereal' : bestperiods_n_sidereal , 'bestperiods_diffn_threshold' : bestperiods_diffn_threshold }
return resdict


signature:
def phasedlc_features ( times , mags , errs , period , nbrtimes = None , nbrmags = None , nbrerrs = None ) :
    '''This calculates various phased LC features for the object .
 Some of the features calculated here come from :
 Kim , D . - W . , Protopapas , P . , Bailer - Jones , C . A . L . , et al . 2014 , Astronomy
 and Astrophysics , 566 , A43 , and references therein ( especially Richards , et
 al . 2011 ) .
 Parameters
 times , mags , errs : np . array
 The input mag / flux time - series to calculate the phased LC features for .
 period : float
 The period used to phase the input mag / flux time - series .
 nbrtimes , nbrmags , nbrerrs : np . array or None
 If ` nbrtimes ` , ` nbrmags ` , and ` nbrerrs ` are all provided , they should be
 ndarrays with ` times ` , ` mags ` , ` errs ` of this object ' s closest neighbor
 ( close within some small number x FWHM of telescope to check for
 blending ) . This function will then also calculate extra features based
 on the neighbor ' s phased LC using the ` period ` provided for the target
 object .
 Returns
 dict
 Returns a dict with phased LC features .'''

implementation:
# get the finite values
finind = np . isfinite ( times ) & np . isfinite ( mags ) & np . isfinite ( errs )
ftimes , fmags , ferrs = times [ finind ] , mags [ finind ] , errs [ finind ]
# get nonzero errors
nzind = np . nonzero ( ferrs )
ftimes , fmags , ferrs = ftimes [ nzind ] , fmags [ nzind ] , ferrs [ nzind ]
# only operate on LC if enough points
if ftimes . size > 49 : # get the MAD of the unphased light curve
    lightcurve_median = np . median ( fmags )
    lightcurve_mad = np . median ( np . abs ( fmags - lightcurve_median ) )
    # get p2p for raw lightcurve
    p2p_unphasedlc = lightcurve_ptp_measures ( ftimes , fmags , ferrs )
    inveta_unphasedlc = 1.0 / p2p_unphasedlc [ 'eta_normal' ]
    # phase the light curve with the given period , assume epoch is
    # times . min ( )
    phasedlc = lcmath . phase_magseries_with_errs ( ftimes , fmags , ferrs , period , ftimes . min ( ) , wrap = False )
    phase = phasedlc [ 'phase' ]
    pmags = phasedlc [ 'mags' ]
    perrs = phasedlc [ 'errs' ]
    # get ptp measures for best period
    ptp_bestperiod = lightcurve_ptp_measures ( phase , pmags , perrs )
    # phase the light curve with the given periodx2 , assume epoch is
    # times . min ( )
    phasedlc = lcmath . phase_magseries_with_errs ( ftimes , fmags , ferrs , period * 2.0 , ftimes . min ( ) , wrap = False )
    phasex2 = phasedlc [ 'phase' ]
    pmagsx2 = phasedlc [ 'mags' ]
    perrsx2 = phasedlc [ 'errs' ]
    # get ptp measures for best periodx2
    ptp_bestperiodx2 = lightcurve_ptp_measures ( phasex2 , pmagsx2 , perrsx2 )
    # eta _ phasedlc _ bestperiod - calculate eta for the phased LC with best
    # period
    inveta_bestperiod = 1.0 / ptp_bestperiod [ 'eta_normal' ]
    # eta _ phasedlc _ bestperiodx2 - calculate eta for the phased LC with best
    # period x 2
    inveta_bestperiodx2 = 1.0 / ptp_bestperiodx2 [ 'eta_normal' ]
    # eta _ phased _ ratio _ eta _ raw - eta for best period phased LC / eta for raw
    # LC
    inveta_ratio_phased_unphased = inveta_bestperiod / inveta_unphasedlc
    # eta _ phasedx2 _ ratio _ eta _ raw - eta for best periodx2 phased LC / eta for
    # raw LC
    inveta_ratio_phasedx2_unphased = inveta_bestperiodx2 / inveta_unphasedlc
    # freq _ model _ max _ delta _ mags - absval of magdiff btw model phased LC
    # maxima using period x 2 . look at points
    # more than 10 points away for maxima
    phasedx2_maxval_ind = argrelmax ( pmagsx2 , order = 10 )
    if phasedx2_maxval_ind [ 0 ] . size > 1 :
        phasedx2_magdiff_maxval = ( np . max ( np . abs ( np . diff ( pmagsx2 [ phasedx2_maxval_ind [ 0 ] ] ) ) ) )
    else :
        phasedx2_magdiff_maxval = np . nan
    # freq _ model _ min _ delta _ mags - absval of magdiff btw model phased LC
    # minima using period x 2 . look at points
    # more than 10 points away for minima
    phasedx2_minval_ind = argrelmin ( pmagsx2 , order = 10 )
    if phasedx2_minval_ind [ 0 ] . size > 1 :
        phasedx2_magdiff_minval = ( np . max ( np . abs ( np . diff ( pmagsx2 [ phasedx2_minval_ind [ 0 ] ] ) ) ) )
    else :
        phasedx2_magdiff_minval = np . nan
    # p2p _ scatter _ pfold _ over _ mad - MAD of successive absolute mag diffs of
    # the phased LC using best period divided
    # by the MAD of the unphased LC
    phased_magdiff = np . diff ( pmags )
    phased_magdiff_median = np . median ( phased_magdiff )
    phased_magdiff_mad = np . median ( np . abs ( phased_magdiff - phased_magdiff_median ) )
    phasedx2_magdiff = np . diff ( pmagsx2 )
    phasedx2_magdiff_median = np . median ( phasedx2_magdiff )
    phasedx2_magdiff_mad = np . median ( np . abs ( phasedx2_magdiff - phasedx2_magdiff_median ) )
    phased_magdiffmad_unphased_mad_ratio = phased_magdiff_mad / lightcurve_mad
    phasedx2_magdiffmad_unphased_mad_ratio = ( phasedx2_magdiff_mad / lightcurve_mad )
    # get the percentiles of the slopes of the adjacent mags for phasedx2
    phasedx2_slopes = np . diff ( pmagsx2 ) / np . diff ( phasex2 )
    phasedx2_slope_percentiles = np . ravel ( np . nanpercentile ( phasedx2_slopes , [ 10.0 , 90.0 ] ) )
    phasedx2_slope_10percentile = phasedx2_slope_percentiles [ 0 ]
    phasedx2_slope_90percentile = phasedx2_slope_percentiles [ 1 ]
    # check if nbrtimes , _ mags , _ errs are available
    if ( ( nbrtimes is not None ) and ( nbrmags is not None ) and ( nbrerrs is not None ) ) : # get the finite values
        nfinind = ( np . isfinite ( nbrtimes ) & np . isfinite ( nbrmags ) & np . isfinite ( nbrerrs ) )
        nftimes , nfmags , nferrs = ( nbrtimes [ nfinind ] , nbrmags [ nfinind ] , nbrerrs [ nfinind ] )
        # get nonzero errors
        nnzind = np . nonzero ( nferrs )
        nftimes , nfmags , nferrs = ( nftimes [ nnzind ] , nfmags [ nnzind ] , nferrs [ nnzind ] )
        # only operate on LC if enough points
        if nftimes . size > 49 : # get the phased light curve using the same period and epoch as
        # the actual object
            nphasedlc = lcmath . phase_magseries_with_errs ( nftimes , nfmags , nferrs , period , ftimes . min ( ) , wrap = False )
            # normalize the object and neighbor phased mags
            norm_pmags = pmags - np . median ( pmags )
            norm_npmags = nphasedlc [ 'mags' ] - np . median ( nphasedlc [ 'mags' ] )
            # phase bin them both so we can compare LCs easily
            phabinned_objectlc = lcmath . phase_bin_magseries ( phase , norm_pmags , minbinelems = 1 )
            phabinned_nbrlc = lcmath . phase_bin_magseries ( nphasedlc [ 'phase' ] , norm_npmags , minbinelems = 1 )
            absdiffs = [ ]
            for pha , phamag in zip ( phabinned_objectlc [ 'binnedphases' ] , phabinned_objectlc [ 'binnedmags' ] ) :
                try : # get the matching phase from the neighbor phased LC
                    phadiffs = np . abs ( pha - phabinned_nbrlc [ 'binnedphases' ] )
                    minphadiffind = np . where ( ( phadiffs < 1.0e-4 ) & ( phadiffs == np . min ( phadiffs ) ) )
                    absmagdiff = np . abs ( phamag - phabinned_nbrlc [ 'binnedmags' ] [ minphadiffind ] )
                    if absmagdiff . size > 0 :
                        absdiffs . append ( absmagdiff . min ( ) )
                except Exception as e :
                    continue
            # sum of absdiff between the normalized to 0.0 phased LC of this
            # object and that of the closest neighbor phased with the same
            # period and epoch
            if len ( absdiffs ) > 0 :
                sum_nbr_phasedlc_magdiff = sum ( absdiffs )
            else :
                sum_nbr_phasedlc_magdiff = np . nan
        else :
            sum_nbr_phasedlc_magdiff = np . nan
    else :
        sum_nbr_phasedlc_magdiff = np . nan
    return { 'inveta_unphasedlc' : inveta_unphasedlc , 'inveta_bestperiod' : inveta_bestperiod , 'inveta_bestperiodx2' : inveta_bestperiodx2 , 'inveta_ratio_phased_unphased' : inveta_ratio_phased_unphased , 'inveta_ratio_phasedx2_unphased' : inveta_ratio_phasedx2_unphased , 'phasedx2_magdiff_maxima' : phasedx2_magdiff_maxval , 'phasedx2_magdiff_minina' : phasedx2_magdiff_minval , 'phased_unphased_magdiff_mad_ratio' : ( phased_magdiffmad_unphased_mad_ratio ) , 'phasedx2_unphased_magdiff_mad_ratio' : ( phasedx2_magdiffmad_unphased_mad_ratio ) , 'phasedx2_slope_10percentile' : phasedx2_slope_10percentile , 'phasedx2_slope_90percentile' : phasedx2_slope_90percentile , 'sum_nbr_phasedlc_magdiff' : sum_nbr_phasedlc_magdiff , }
else :
    return { 'inveta_unphasedlc' : np . nan , 'inveta_bestperiod' : np . nan , 'inveta_bestperiodx2' : np . nan , 'inveta_ratio_phased_unphased' : np . nan , 'inveta_ratio_phasedx2_unphased' : np . nan , 'phasedx2_magdiff_maxima' : np . nan , 'phasedx2_magdiff_minina' : np . nan , 'phased_unphased_magdiff_mad_ratio' : np . nan , 'phasedx2_unphased_magdiff_mad_ratio' : np . nan , 'phasedx2_slope_10percentile' : np . nan , 'phasedx2_slope_90percentile' : np . nan , 'sum_nbr_phasedlc_magdiff' : np . nan , }


signature:
def stellingwerf_pdm_theta ( times , mags , errs , frequency , binsize = 0.05 , minbin = 9 ) :
    '''This calculates the Stellingwerf PDM theta value at a test frequency .
 Parameters
 times , mags , errs : np . array
 The input time - series and associated errors .
 frequency : float
 The test frequency to calculate the theta statistic at .
 binsize : float
 The phase bin size to use .
 minbin : int
 The minimum number of items in a phase bin to consider in the
 calculation of the statistic .
 Returns
 theta _ pdm : float
 The value of the theta statistic at the specified ` frequency ` .'''

implementation:
period = 1.0 / frequency
fold_time = times [ 0 ]
phased = phase_magseries ( times , mags , period , fold_time , wrap = False , sort = True )
phases = phased [ 'phase' ]
pmags = phased [ 'mags' ]
bins = nparange ( 0.0 , 1.0 , binsize )
binnedphaseinds = npdigitize ( phases , bins )
binvariances = [ ]
binndets = [ ]
goodbins = 0
for x in npunique ( binnedphaseinds ) :
    thisbin_inds = binnedphaseinds == x
    thisbin_mags = pmags [ thisbin_inds ]
    if thisbin_mags . size > minbin :
        thisbin_variance = npvar ( thisbin_mags , ddof = 1 )
        binvariances . append ( thisbin_variance )
        binndets . append ( thisbin_mags . size )
        goodbins = goodbins + 1
# now calculate theta
binvariances = nparray ( binvariances )
binndets = nparray ( binndets )
theta_top = npsum ( binvariances * ( binndets - 1 ) ) / ( npsum ( binndets ) - goodbins )
theta_bot = npvar ( pmags , ddof = 1 )
theta = theta_top / theta_bot
return theta


signature:
def _stellingwerf_pdm_worker ( task ) :
    '''This is a parallel worker for the function below .
 Parameters
 task : tuple
 This is of the form below : :
 task [ 0 ] = times
 task [ 1 ] = mags
 task [ 2 ] = errs
 task [ 3 ] = frequency
 task [ 4 ] = binsize
 task [ 5 ] = minbin
 Returns
 theta _ pdm : float
 The theta value at the specified frequency . nan if the calculation
 fails .'''

implementation:
times , mags , errs , frequency , binsize , minbin = task
try :
    theta = stellingwerf_pdm_theta ( times , mags , errs , frequency , binsize = binsize , minbin = minbin )
    return theta
except Exception as e :
    return npnan


signature:
def stellingwerf_pdm ( times , mags , errs , magsarefluxes = False , startp = None , endp = None , stepsize = 1.0e-4 , autofreq = True , normalize = False , phasebinsize = 0.05 , mindetperbin = 9 , nbestpeaks = 5 , periodepsilon = 0.1 , sigclip = 10.0 , nworkers = None , verbose = True ) :
    '''This runs a parallelized Stellingwerf phase - dispersion minimization ( PDM )
 period search .
 Parameters
 times , mags , errs : np . array
 The mag / flux time - series with associated measurement errors to run the
 period - finding on .
 magsarefluxes : bool
 If the input measurement values in ` mags ` and ` errs ` are in fluxes , set
 this to True .
 startp , endp : float or None
 The minimum and maximum periods to consider for the transit search .
 stepsize : float
 The step - size in frequency to use when constructing a frequency grid for
 the period search .
 autofreq : bool
 If this is True , the value of ` stepsize ` will be ignored and the
 : py : func : ` astrobase . periodbase . get _ frequency _ grid ` function will be used
 to generate a frequency grid based on ` startp ` , and ` endp ` . If these are
 None as well , ` startp ` will be set to 0.1 and ` endp ` will be set to
 ` times . max ( ) - times . min ( ) ` .
 normalize : bool
 This sets if the input time - series is normalized to 0.0 and rescaled
 such that its variance = 1.0 . This is the recommended procedure by
 Schwarzenberg - Czerny 1996.
 phasebinsize : float
 The bin size in phase to use when calculating the PDM theta statistic at
 a test frequency .
 mindetperbin : int
 The minimum number of elements in a phase bin to consider it valid when
 calculating the PDM theta statistic at a test frequency .
 nbestpeaks : int
 The number of ' best ' peaks to return from the periodogram results ,
 starting from the global maximum of the periodogram peak values .
 periodepsilon : float
 The fractional difference between successive values of ' best ' periods
 when sorting by periodogram power to consider them as separate periods
 ( as opposed to part of the same periodogram peak ) . This is used to avoid
 broad peaks in the periodogram and make sure the ' best ' periods returned
 are all actually independent .
 sigclip : float or int or sequence of two floats / ints or None
 If a single float or int , a symmetric sigma - clip will be performed using
 the number provided as the sigma - multiplier to cut out from the input
 time - series .
 If a list of two ints / floats is provided , the function will perform an
 ' asymmetric ' sigma - clip . The first element in this list is the sigma
 value to use for fainter flux / mag values ; the second element in this
 list is the sigma value to use for brighter flux / mag values . For
 example , ` sigclip = [ 10 . , 3 . ] ` , will sigclip out greater than 10 - sigma
 dimmings and greater than 3 - sigma brightenings . Here the meaning of
 " dimming " and " brightening " is set by * physics * ( not the magnitude
 system ) , which is why the ` magsarefluxes ` kwarg must be correctly set .
 If ` sigclip ` is None , no sigma - clipping will be performed , and the
 time - series ( with non - finite elems removed ) will be passed through to
 the output .
 nworkers : int
 The number of parallel workers to use when calculating the periodogram .
 verbose : bool
 If this is True , will indicate progress and details about the frequency
 grid used for the period search .
 Returns
 dict
 This function returns a dict , referred to as an ` lspinfo ` dict in other
 astrobase functions that operate on periodogram results . This is a
 standardized format across all astrobase period - finders , and is of the
 form below : :
 { ' bestperiod ' : the best period value in the periodogram ,
 ' bestlspval ' : the periodogram peak associated with the best period ,
 ' nbestpeaks ' : the input value of nbestpeaks ,
 ' nbestlspvals ' : nbestpeaks - size list of best period peak values ,
 ' nbestperiods ' : nbestpeaks - size list of best periods ,
 ' lspvals ' : the full array of periodogram powers ,
 ' periods ' : the full array of periods considered ,
 ' method ' : ' pdm ' - > the name of the period - finder method ,
 ' kwargs ' : { dict of all of the input kwargs for record - keeping } }'''

implementation:
# get rid of nans first and sigclip
stimes , smags , serrs = sigclip_magseries ( times , mags , errs , magsarefluxes = magsarefluxes , sigclip = sigclip )
# make sure there are enough points to calculate a spectrum
if len ( stimes ) > 9 and len ( smags ) > 9 and len ( serrs ) > 9 : # get the frequencies to use
    if startp :
        endf = 1.0 / startp
    else : # default start period is 0.1 day
        endf = 1.0 / 0.1
    if endp :
        startf = 1.0 / endp
    else : # default end period is length of time series
        startf = 1.0 / ( stimes . max ( ) - stimes . min ( ) )
    # if we ' re not using autofreq , then use the provided frequencies
    if not autofreq :
        frequencies = nparange ( startf , endf , stepsize )
        if verbose :
            LOGINFO ( 'using %s frequency points, start P = %.3f, end P = %.3f' % ( frequencies . size , 1.0 / endf , 1.0 / startf ) )
    else : # this gets an automatic grid of frequencies to use
        frequencies = get_frequency_grid ( stimes , minfreq = startf , maxfreq = endf )
        if verbose :
            LOGINFO ( 'using autofreq with %s frequency points, ' 'start P = %.3f, end P = %.3f' % ( frequencies . size , 1.0 / frequencies . max ( ) , 1.0 / frequencies . min ( ) ) )
    # map to parallel workers
    if ( not nworkers ) or ( nworkers > NCPUS ) :
        nworkers = NCPUS
        if verbose :
            LOGINFO ( 'using %s workers...' % nworkers )
    pool = Pool ( nworkers )
    # renormalize the working mags to zero and scale them so that the
    # variance = 1 for use with our LSP functions
    if normalize :
        nmags = ( smags - npmedian ( smags ) ) / npstd ( smags )
    else :
        nmags = smags
    tasks = [ ( stimes , nmags , serrs , x , phasebinsize , mindetperbin ) for x in frequencies ]
    lsp = pool . map ( _stellingwerf_pdm_worker , tasks )
    pool . close ( )
    pool . join ( )
    del pool
    lsp = nparray ( lsp )
    periods = 1.0 / frequencies
    # find the nbestpeaks for the periodogram : 1 . sort the lsp array by
    # lowest value first 2 . go down the values until we find five values
    # that are separated by at least periodepsilon in period
    # make sure to filter out the non - finite values of lsp
    finitepeakind = npisfinite ( lsp )
    finlsp = lsp [ finitepeakind ]
    finperiods = periods [ finitepeakind ]
    # finlsp might not have any finite values if the period finding
    # failed . if so , argmin will return a ValueError .
    try :
        bestperiodind = npargmin ( finlsp )
    except ValueError :
        LOGERROR ( 'no finite periodogram values for ' 'this mag series, skipping...' )
        return { 'bestperiod' : npnan , 'bestlspval' : npnan , 'nbestpeaks' : nbestpeaks , 'nbestlspvals' : None , 'nbestperiods' : None , 'lspvals' : None , 'periods' : None , 'method' : 'pdm' , 'kwargs' : { 'startp' : startp , 'endp' : endp , 'stepsize' : stepsize , 'normalize' : normalize , 'phasebinsize' : phasebinsize , 'mindetperbin' : mindetperbin , 'autofreq' : autofreq , 'periodepsilon' : periodepsilon , 'nbestpeaks' : nbestpeaks , 'sigclip' : sigclip } }
    sortedlspind = npargsort ( finlsp )
    sortedlspperiods = finperiods [ sortedlspind ]
    sortedlspvals = finlsp [ sortedlspind ]
    # now get the nbestpeaks
    nbestperiods , nbestlspvals , peakcount = ( [ finperiods [ bestperiodind ] ] , [ finlsp [ bestperiodind ] ] , 1 )
    prevperiod = sortedlspperiods [ 0 ]
    # find the best nbestpeaks in the lsp and their periods
    for period , lspval in zip ( sortedlspperiods , sortedlspvals ) :
        if peakcount == nbestpeaks :
            break
        perioddiff = abs ( period - prevperiod )
        bestperiodsdiff = [ abs ( period - x ) for x in nbestperiods ]
        # print ( ' prevperiod = % s , thisperiod = % s , '
        # ' perioddiff = % s , peakcount = % s ' %
        # ( prevperiod , period , perioddiff , peakcount ) )
        # this ensures that this period is different from the last
        # period and from all the other existing best periods by
        # periodepsilon to make sure we jump to an entire different peak
        # in the periodogram
        if ( perioddiff > ( periodepsilon * prevperiod ) and all ( x > ( periodepsilon * period ) for x in bestperiodsdiff ) ) :
            nbestperiods . append ( period )
            nbestlspvals . append ( lspval )
            peakcount = peakcount + 1
        prevperiod = period
    return { 'bestperiod' : finperiods [ bestperiodind ] , 'bestlspval' : finlsp [ bestperiodind ] , 'nbestpeaks' : nbestpeaks , 'nbestlspvals' : nbestlspvals , 'nbestperiods' : nbestperiods , 'lspvals' : lsp , 'periods' : periods , 'method' : 'pdm' , 'kwargs' : { 'startp' : startp , 'endp' : endp , 'stepsize' : stepsize , 'normalize' : normalize , 'phasebinsize' : phasebinsize , 'mindetperbin' : mindetperbin , 'autofreq' : autofreq , 'periodepsilon' : periodepsilon , 'nbestpeaks' : nbestpeaks , 'sigclip' : sigclip } }
else :
    LOGERROR ( 'no good detections for these times and mags, skipping...' )
    return { 'bestperiod' : npnan , 'bestlspval' : npnan , 'nbestpeaks' : nbestpeaks , 'nbestlspvals' : None , 'nbestperiods' : None , 'lspvals' : None , 'periods' : None , 'method' : 'pdm' , 'kwargs' : { 'startp' : startp , 'endp' : endp , 'stepsize' : stepsize , 'normalize' : normalize , 'phasebinsize' : phasebinsize , 'mindetperbin' : mindetperbin , 'autofreq' : autofreq , 'periodepsilon' : periodepsilon , 'nbestpeaks' : nbestpeaks , 'sigclip' : sigclip } }


signature:
def analytic_false_alarm_probability ( lspinfo , times , conservative_nfreq_eff = True , peakvals = None , inplace = True ) :
    '''This returns the analytic false alarm probabilities for periodogram
 peak values .
 FIXME : this doesn ' t actually work . Fix later .
 The calculation follows that on page 3 of Zechmeister & Kurster ( 2009 ) : :
 FAP = 1 − [ 1 − Prob ( z > z0 ) ] * * M
 where : :
 M is the number of independent frequencies
 Prob ( z > z0 ) is the probability of peak with value > z0
 z0 is the peak value we ' re evaluating
 For PDM , the Prob ( z > z0 ) is described by the beta distribution , according
 to :
 - Schwarzenberg - Czerny ( 1997;
 https : / / ui . adsabs . harvard . edu / # abs / 1997ApJ . . . 489 . . 941S )
 - Zalian , Chadid , and Stellingwerf ( 2013;
 http : / / adsabs . harvard . edu / abs / 2014MNRAS . 440 . . . 68Z )
 This is given by : :
 beta ( ( N - B ) / 2 , ( B - 1 ) / 2 ; ( ( N - B ) / ( B - 1 ) ) * theta _ pdm )
 Where : :
 N = number of observations
 B = number of phase bins
 This translates to a scipy . stats call to the beta distribution CDF : :
 x = ( ( N - B ) / ( B - 1 ) ) * theta _ pdm _ best
 prob _ exceeds _ val = scipy . stats . beta . cdf ( x , ( N - B ) / 2.0 , ( B - 1.0 ) / 2.0)
 Which we can then plug into the false alarm prob eqn above with the
 calculation of M .
 Parameters
 lspinfo : dict
 The dict returned by the
 : py : func : ` ~ astrobase . periodbase . spdm . stellingwerf _ pdm ` function .
 times : np . array
 The times for which the periodogram result in ` ` lspinfo ` ` was
 calculated .
 conservative _ nfreq _ eff : bool
 If True , will follow the prescription given in Schwarzenberg - Czerny
 (2003 ) :
 http : / / adsabs . harvard . edu / abs / 2003ASPC . . 292 . . 383S
 and estimate the effective number of independent frequences M _ eff as : :
 min ( N _ obs , N _ freq , DELTA _ f / delta _ f )
 peakvals : sequence or None
 The peak values for which to evaluate the false - alarm probability . If
 None , will calculate this for each of the peak values in the
 ` ` nbestpeaks ` ` key of the ` ` lspinfo ` ` dict .
 inplace : bool
 If True , puts the results of the FAP calculation into the ` ` lspinfo ` `
 dict as a list available as ` ` lspinfo [ ' falsealarmprob ' ] ` ` .
 Returns
 list
 The calculated false alarm probabilities for each of the peak values in
 ` ` peakvals ` ` .'''

implementation:
from scipy . stats import beta
frequencies = 1.0 / lspinfo [ 'periods' ]
M = independent_freq_count ( frequencies , times , conservative = conservative_nfreq_eff )
if peakvals is None :
    peakvals = lspinfo [ 'nbestlspvals' ]
nphasebins = nparange ( 0.0 , 1.0 , lspinfo [ 'kwargs' ] [ 'phasebinsize' ] ) . size
ndet = times . size
false_alarm_probs = [ ]
for peakval in peakvals :
    prob_xval = ( ( ndet - nphasebins ) / ( nphasebins - 1.0 ) ) * peakval
    prob_exceeds_val = beta . cdf ( prob_xval , ( ndet - nphasebins ) / 2.0 , ( nphasebins - 1.0 ) / 2.0 )
    import ipdb ;
    ipdb . set_trace ( )
    false_alarm_probs . append ( 1.0 - ( 1.0 - prob_exceeds_val ) ** M )
if inplace :
    lspinfo [ 'falsealarmprob' ] = false_alarm_probs
return false_alarm_probs


signature:
def keplermag_to_sdssr ( keplermag , kic_sdssg , kic_sdssr ) :
    '''Converts magnitude measurements in Kepler band to SDSS r band .
 Parameters
 keplermag : float or array - like
 The Kepler magnitude value ( s ) to convert to fluxes .
 kic _ sdssg , kic _ sdssr : float or array - like
 The SDSS g and r magnitudes of the object ( s ) from the Kepler Input
 Catalog . The . llc . fits MAST light curve file for a Kepler object
 contains these values in the FITS extension 0 header .
 Returns
 float or array - like
 SDSS r band magnitude ( s ) converted from the Kepler band magnitude .'''

implementation:
kic_sdssgr = kic_sdssg - kic_sdssr
if kic_sdssgr < 0.8 :
    kepsdssr = ( keplermag - 0.2 * kic_sdssg ) / 0.8
else :
    kepsdssr = ( keplermag - 0.1 * kic_sdssg ) / 0.9
return kepsdssr


signature:
def read_kepler_fitslc ( lcfits , headerkeys = LCHEADERKEYS , datakeys = LCDATAKEYS , sapkeys = LCSAPKEYS , pdckeys = LCPDCKEYS , topkeys = LCTOPKEYS , apkeys = LCAPERTUREKEYS , appendto = None , normalize = False , ) :
    '''This extracts the light curve from a single Kepler or K2 LC FITS file .
 This works on the light curves available at MAST :
 - ` kplr { kepid } - { somedatething } _ llc . fits ` files from the Kepler mission
 - ` ktwo { epicid } - c { campaign } _ llc . fits ` files from the K2 mission
 Parameters
 lcfits : str
 The filename of a MAST Kepler / K2 light curve FITS file .
 headerkeys : list
 A list of FITS header keys that will be extracted from the FITS light
 curve file . These describe the observations . The default value for this
 is given in ` LCHEADERKEYS ` above .
 datakeys : list
 A list of FITS column names that correspond to the auxiliary
 measurements in the light curve . The default is ` LCDATAKEYS ` above .
 sapkeys : list
 A list of FITS column names that correspond to the SAP flux
 measurements in the light curve . The default is ` LCSAPKEYS ` above .
 pdckeys : list
 A list of FITS column names that correspond to the PDC flux
 measurements in the light curve . The default is ` LCPDCKEYS ` above .
 topkeys : list
 A list of FITS header keys that describe the object in the light
 curve . The default is ` LCTOPKEYS ` above .
 apkeys : list
 A list of FITS header keys that describe the flux measurement apertures
 used by the Kepler / K2 pipeline . The default is ` LCAPERTUREKEYS ` above .
 appendto : lcdict or None
 If appendto is an ` lcdict ` , will append measurements of this ` lcdict ` to
 that ` lcdict ` . This is used for consolidating light curves for the same
 object across different files ( quarters ) . The appending does not care
 about the time order . To consolidate light curves in time order , use
 ` consolidate _ kepler _ fitslc ` below .
 normalize : bool
 If True , then each component light curve ' s SAP _ FLUX and PDCSAP _ FLUX
 measurements will be normalized to 1.0 by dividing out the median flux
 for the component light curve .
 Returns
 lcdict
 Returns an ` lcdict ` ( this is useable by most astrobase functions for LC
 processing ) .'''

implementation:
# read the fits file
hdulist = pyfits . open ( lcfits )
lchdr , lcdata = hdulist [ 1 ] . header , hdulist [ 1 ] . data
lctophdr , lcaperturehdr , lcaperturedata = ( hdulist [ 0 ] . header , hdulist [ 2 ] . header , hdulist [ 2 ] . data )
hdulist . close ( )
hdrinfo = { }
# now get the values we want from the header
for key in headerkeys :
    if key in lchdr and lchdr [ key ] is not None :
        hdrinfo [ key . lower ( ) ] = lchdr [ key ]
    else :
        hdrinfo [ key . lower ( ) ] = None
# get the number of detections
ndet = lchdr [ 'NAXIS2' ]
# get the info from the topheader
for key in topkeys :
    if key in lctophdr and lctophdr [ key ] is not None :
        hdrinfo [ key . lower ( ) ] = lctophdr [ key ]
    else :
        hdrinfo [ key . lower ( ) ] = None
# get the info from the lcaperturehdr
for key in lcaperturehdr :
    if key in lcaperturehdr and lcaperturehdr [ key ] is not None :
        hdrinfo [ key . lower ( ) ] = lcaperturehdr [ key ]
    else :
        hdrinfo [ key . lower ( ) ] = None
# if we ' re appending to another lcdict
if appendto and isinstance ( appendto , dict ) :
    lcdict = appendto
    lcdict [ 'quarter' ] . append ( hdrinfo [ 'quarter' ] )
    lcdict [ 'season' ] . append ( hdrinfo [ 'season' ] )
    lcdict [ 'datarelease' ] . append ( hdrinfo [ 'data_rel' ] )
    lcdict [ 'obsmode' ] . append ( hdrinfo [ 'obsmode' ] )
    lcdict [ 'campaign' ] . append ( hdrinfo [ 'campaign' ] )
    # we don ' t update the objectid
    # update lcinfo
    lcdict [ 'lcinfo' ] [ 'timesys' ] . append ( hdrinfo [ 'timesys' ] )
    lcdict [ 'lcinfo' ] [ 'bjdoffset' ] . append ( hdrinfo [ 'bjdrefi' ] + hdrinfo [ 'bjdreff' ] )
    lcdict [ 'lcinfo' ] [ 'exptime' ] . append ( hdrinfo [ 'exposure' ] )
    lcdict [ 'lcinfo' ] [ 'lcaperture' ] . append ( lcaperturedata )
    lcdict [ 'lcinfo' ] [ 'aperpixused' ] . append ( hdrinfo [ 'npixsap' ] )
    lcdict [ 'lcinfo' ] [ 'aperpixunused' ] . append ( hdrinfo [ 'npixmiss' ] )
    lcdict [ 'lcinfo' ] [ 'pixarcsec' ] . append ( ( npabs ( hdrinfo [ 'cdelt1' ] ) + npabs ( hdrinfo [ 'cdelt2' ] ) ) * 3600.0 / 2.0 )
    lcdict [ 'lcinfo' ] [ 'channel' ] . append ( hdrinfo [ 'channel' ] )
    lcdict [ 'lcinfo' ] [ 'skygroup' ] . append ( hdrinfo [ 'skygroup' ] )
    lcdict [ 'lcinfo' ] [ 'module' ] . append ( hdrinfo [ 'module' ] )
    lcdict [ 'lcinfo' ] [ 'output' ] . append ( hdrinfo [ 'output' ] )
    lcdict [ 'lcinfo' ] [ 'ndet' ] . append ( ndet )
    # the objectinfo is not updated for the same object when appending to a
    # light curve . FIXME : maybe it should be ?
    # update the varinfo for this light curve
    lcdict [ 'varinfo' ] [ 'cdpp3_0' ] . append ( hdrinfo [ 'cdpp3_0' ] )
    lcdict [ 'varinfo' ] [ 'cdpp6_0' ] . append ( hdrinfo [ 'cdpp6_0' ] )
    lcdict [ 'varinfo' ] [ 'cdpp12_0' ] . append ( hdrinfo [ 'cdpp12_0' ] )
    lcdict [ 'varinfo' ] [ 'pdcvar' ] . append ( hdrinfo [ 'pdcvar' ] )
    lcdict [ 'varinfo' ] [ 'pdcmethod' ] . append ( hdrinfo [ 'pdcmethd' ] )
    lcdict [ 'varinfo' ] [ 'aper_target_total_ratio' ] . append ( hdrinfo [ 'crowdsap' ] )
    lcdict [ 'varinfo' ] [ 'aper_target_frac' ] . append ( hdrinfo [ 'flfrcsap' ] )
    # update the light curve columns now
    for key in datakeys :
        if key . lower ( ) in lcdict :
            lcdict [ key . lower ( ) ] = ( npconcatenate ( ( lcdict [ key . lower ( ) ] , lcdata [ key ] ) ) )
    for key in sapkeys :
        if key . lower ( ) in lcdict [ 'sap' ] :
            sapflux_median = np . nanmedian ( lcdata [ 'SAP_FLUX' ] )
            # normalize the current flux measurements if needed
            if normalize and key == 'SAP_FLUX' :
                thislcdata = lcdata [ key ] / sapflux_median
            elif normalize and key == 'SAP_FLUX_ERR' :
                thislcdata = lcdata [ key ] / sapflux_median
            elif normalize and key == 'SAP_BKG' :
                thislcdata = lcdata [ key ] / sapflux_median
            elif normalize and key == 'SAP_BKG_ERR' :
                thislcdata = lcdata [ key ] / sapflux_median
            else :
                thislcdata = lcdata [ key ]
            lcdict [ 'sap' ] [ key . lower ( ) ] = ( np . concatenate ( ( lcdict [ 'sap' ] [ key . lower ( ) ] , thislcdata ) ) )
    for key in pdckeys :
        if key . lower ( ) in lcdict [ 'pdc' ] :
            pdcsap_flux_median = np . nanmedian ( lcdata [ 'PDCSAP_FLUX' ] )
            # normalize the current flux measurements if needed
            if normalize and key == 'PDCSAP_FLUX' :
                thislcdata = lcdata [ key ] / pdcsap_flux_median
            elif normalize and key == 'PDCSAP_FLUX_ERR' :
                thislcdata = lcdata [ key ] / pdcsap_flux_median
            else :
                thislcdata = lcdata [ key ]
            lcdict [ 'pdc' ] [ key . lower ( ) ] = ( np . concatenate ( ( lcdict [ 'pdc' ] [ key . lower ( ) ] , thislcdata ) ) )
    # append some of the light curve information into existing numpy arrays
    # so we can sort on them later
    lcdict [ 'lc_channel' ] = npconcatenate ( ( lcdict [ 'lc_channel' ] , npfull_like ( lcdata [ 'TIME' ] , hdrinfo [ 'channel' ] ) ) )
    lcdict [ 'lc_skygroup' ] = npconcatenate ( ( lcdict [ 'lc_skygroup' ] , npfull_like ( lcdata [ 'TIME' ] , hdrinfo [ 'skygroup' ] ) ) )
    lcdict [ 'lc_module' ] = npconcatenate ( ( lcdict [ 'lc_module' ] , npfull_like ( lcdata [ 'TIME' ] , hdrinfo [ 'module' ] ) ) )
    lcdict [ 'lc_output' ] = npconcatenate ( ( lcdict [ 'lc_output' ] , npfull_like ( lcdata [ 'TIME' ] , hdrinfo [ 'output' ] ) ) )
    lcdict [ 'lc_quarter' ] = npconcatenate ( ( lcdict [ 'lc_quarter' ] , npfull_like ( lcdata [ 'TIME' ] , hdrinfo [ 'quarter' ] ) ) )
    lcdict [ 'lc_season' ] = npconcatenate ( ( lcdict [ 'lc_season' ] , npfull_like ( lcdata [ 'TIME' ] , hdrinfo [ 'season' ] ) ) )
    lcdict [ 'lc_campaign' ] = npconcatenate ( ( lcdict [ 'lc_campaign' ] , npfull_like ( lcdata [ 'TIME' ] , hdrinfo [ 'campaign' ] ) ) )
# otherwise , this is a new lcdict
else : # form the lcdict
# the metadata is one - elem arrays because we might add on to them later
    lcdict = { 'quarter' : [ hdrinfo [ 'quarter' ] ] , 'season' : [ hdrinfo [ 'season' ] ] , 'datarelease' : [ hdrinfo [ 'data_rel' ] ] , 'campaign' : [ hdrinfo [ 'campaign' ] ] , # this is None for KepPrime
    'obsmode' : [ hdrinfo [ 'obsmode' ] ] , 'objectid' : hdrinfo [ 'object' ] , 'lcinfo' : { 'timesys' : [ hdrinfo [ 'timesys' ] ] , 'bjdoffset' : [ hdrinfo [ 'bjdrefi' ] + hdrinfo [ 'bjdreff' ] ] , 'exptime' : [ hdrinfo [ 'exposure' ] ] , 'lcaperture' : [ lcaperturedata ] , 'aperpixused' : [ hdrinfo [ 'npixsap' ] ] , 'aperpixunused' : [ hdrinfo [ 'npixmiss' ] ] , 'pixarcsec' : [ ( npabs ( hdrinfo [ 'cdelt1' ] ) + npabs ( hdrinfo [ 'cdelt2' ] ) ) * 3600.0 / 2.0 ] , 'channel' : [ hdrinfo [ 'channel' ] ] , 'skygroup' : [ hdrinfo [ 'skygroup' ] ] , 'module' : [ hdrinfo [ 'module' ] ] , 'output' : [ hdrinfo [ 'output' ] ] , 'ndet' : [ ndet ] , } , 'objectinfo' : { 'objectid' : hdrinfo [ 'object' ] , # repeated here for checkplot use
    'keplerid' : hdrinfo [ 'keplerid' ] , 'ra' : hdrinfo [ 'ra_obj' ] , 'decl' : hdrinfo [ 'dec_obj' ] , 'pmra' : hdrinfo [ 'pmra' ] , 'pmdecl' : hdrinfo [ 'pmdec' ] , 'pmtotal' : hdrinfo [ 'pmtotal' ] , 'sdssg' : hdrinfo [ 'gmag' ] , 'sdssr' : hdrinfo [ 'rmag' ] , 'sdssi' : hdrinfo [ 'imag' ] , 'sdssz' : hdrinfo [ 'zmag' ] , 'kepmag' : hdrinfo [ 'kepmag' ] , 'teff' : hdrinfo [ 'teff' ] , 'logg' : hdrinfo [ 'logg' ] , 'feh' : hdrinfo [ 'feh' ] , 'ebminusv' : hdrinfo [ 'ebminusv' ] , 'extinction' : hdrinfo [ 'av' ] , 'starradius' : hdrinfo [ 'radius' ] , 'twomassuid' : hdrinfo [ 'tmindex' ] , } , 'varinfo' : { 'cdpp3_0' : [ hdrinfo [ 'cdpp3_0' ] ] , 'cdpp6_0' : [ hdrinfo [ 'cdpp6_0' ] ] , 'cdpp12_0' : [ hdrinfo [ 'cdpp12_0' ] ] , 'pdcvar' : [ hdrinfo [ 'pdcvar' ] ] , 'pdcmethod' : [ hdrinfo [ 'pdcmethd' ] ] , 'aper_target_total_ratio' : [ hdrinfo [ 'crowdsap' ] ] , 'aper_target_frac' : [ hdrinfo [ 'flfrcsap' ] ] , } , 'sap' : { } , 'pdc' : { } , }
    # get the LC columns
    for key in datakeys :
        lcdict [ key . lower ( ) ] = lcdata [ key ]
    for key in sapkeys :
        lcdict [ 'sap' ] [ key . lower ( ) ] = lcdata [ key ]
    for key in pdckeys :
        lcdict [ 'pdc' ] [ key . lower ( ) ] = lcdata [ key ]
    # turn some of the light curve information into numpy arrays so we can
    # sort on them later
    lcdict [ 'lc_channel' ] = npfull_like ( lcdict [ 'time' ] , lcdict [ 'lcinfo' ] [ 'channel' ] [ 0 ] )
    lcdict [ 'lc_skygroup' ] = npfull_like ( lcdict [ 'time' ] , lcdict [ 'lcinfo' ] [ 'skygroup' ] [ 0 ] )
    lcdict [ 'lc_module' ] = npfull_like ( lcdict [ 'time' ] , lcdict [ 'lcinfo' ] [ 'module' ] [ 0 ] )
    lcdict [ 'lc_output' ] = npfull_like ( lcdict [ 'time' ] , lcdict [ 'lcinfo' ] [ 'output' ] [ 0 ] )
    lcdict [ 'lc_quarter' ] = npfull_like ( lcdict [ 'time' ] , lcdict [ 'quarter' ] [ 0 ] )
    lcdict [ 'lc_season' ] = npfull_like ( lcdict [ 'time' ] , lcdict [ 'season' ] [ 0 ] )
    lcdict [ 'lc_campaign' ] = npfull_like ( lcdict [ 'time' ] , lcdict [ 'campaign' ] [ 0 ] )
    # normalize the SAP and PDCSAP fluxes if needed
    if normalize :
        sapflux_median = np . nanmedian ( lcdict [ 'sap' ] [ 'sap_flux' ] )
        pdcsap_flux_median = np . nanmedian ( lcdict [ 'pdc' ] [ 'pdcsap_flux' ] )
        lcdict [ 'sap' ] [ 'sap_flux' ] = ( lcdict [ 'sap' ] [ 'sap_flux' ] / sapflux_median )
        lcdict [ 'sap' ] [ 'sap_flux_err' ] = ( lcdict [ 'sap' ] [ 'sap_flux_err' ] / sapflux_median )
        lcdict [ 'sap' ] [ 'sap_bkg' ] = ( lcdict [ 'sap' ] [ 'sap_bkg' ] / sapflux_median )
        lcdict [ 'sap' ] [ 'sap_bkg_err' ] = ( lcdict [ 'sap' ] [ 'sap_bkg_err' ] / sapflux_median )
        lcdict [ 'pdc' ] [ 'pdcsap_flux' ] = ( lcdict [ 'pdc' ] [ 'pdcsap_flux' ] / pdcsap_flux_median )
        lcdict [ 'pdc' ] [ 'pdcsap_flux_err' ] = ( lcdict [ 'pdc' ] [ 'pdcsap_flux_err' ] / pdcsap_flux_median )
# # END OF LIGHT CURVE CONSTRUCTION # #
# update the lcdict columns with the actual columns
lcdict [ 'columns' ] = ( [ x . lower ( ) for x in datakeys ] + [ 'sap.%s' % x . lower ( ) for x in sapkeys ] + [ 'pdc.%s' % x . lower ( ) for x in pdckeys ] + [ 'lc_channel' , 'lc_skygroup' , 'lc_module' , 'lc_output' , 'lc_quarter' , 'lc_season' ] )
# return the lcdict at the end
return lcdict


signature:
def consolidate_kepler_fitslc ( keplerid , lcfitsdir , normalize = True , headerkeys = LCHEADERKEYS , datakeys = LCDATAKEYS , sapkeys = LCSAPKEYS , pdckeys = LCPDCKEYS , topkeys = LCTOPKEYS , apkeys = LCAPERTUREKEYS ) :
    '''This gets all Kepler / K2 light curves for the given ` keplerid `
 in ` lcfitsdir ` .
 Searches recursively in ` lcfitsdir ` for all of the files belonging to the
 specified ` keplerid ` . Sorts the light curves by time . Returns an
 ` lcdict ` . This is meant to be used to consolidate light curves for a single
 object across Kepler quarters .
 NOTE : ` keplerid ` is an integer ( without the leading zeros ) . This is usually
 the KIC ID .
 NOTE : if light curve time arrays contain ` nans ` , these and their associated
 measurements will be sorted to the end of the final combined arrays .
 Parameters
 keplerid : int
 The Kepler ID of the object to consolidate LCs for , as an integer
 without any leading zeros . This is usually the KIC or EPIC ID .
 lcfitsdir : str
 The directory to look in for LCs of the specified object .
 normalize : bool
 If True , then each component light curve ' s SAP _ FLUX and PDCSAP _ FLUX
 measurements will be normalized to 1.0 by dividing out the median flux
 for the component light curve .
 headerkeys : list
 A list of FITS header keys that will be extracted from the FITS light
 curve file . These describe the observations . The default value for this
 is given in ` LCHEADERKEYS ` above .
 datakeys : list
 A list of FITS column names that correspond to the auxiliary
 measurements in the light curve . The default is ` LCDATAKEYS ` above .
 sapkeys : list
 A list of FITS column names that correspond to the SAP flux
 measurements in the light curve . The default is ` LCSAPKEYS ` above .
 pdckeys : list
 A list of FITS column names that correspond to the PDC flux
 measurements in the light curve . The default is ` LCPDCKEYS ` above .
 topkeys : list
 A list of FITS header keys that describe the object in the light
 curve . The default is ` LCTOPKEYS ` above .
 apkeys : list
 A list of FITS header keys that describe the flux measurement apertures
 used by the Kepler / K2 pipeline . The default is ` LCAPERTUREKEYS ` above .
 Returns
 lcdict
 Returns an ` lcdict ` ( this is useable by most astrobase functions for LC
 processing ) .'''

implementation:
LOGINFO ( 'looking for Kepler light curve FITS in %s for %s...' % ( lcfitsdir , keplerid ) )
# for Python 3.5 and up , use recursive glob , it appears to be absurdly
# faster than os . walk
if sys . version_info [ : 2 ] > ( 3 , 4 ) :
    matching = glob . glob ( os . path . join ( lcfitsdir , '**' , 'kplr%09i-*_llc.fits' % keplerid ) , recursive = True )
    LOGINFO ( 'found %s files: %s' % ( len ( matching ) , repr ( matching ) ) )
# for Python < 3.5 , use os . walk and glob
else : # use the os . walk function to start looking for files in lcfitsdir
    walker = os . walk ( lcfitsdir )
    matching = [ ]
    for root , dirs , _files in walker :
        for sdir in dirs :
            searchpath = os . path . join ( root , sdir , 'kplr%09i-*_llc.fits' % keplerid )
            foundfiles = glob . glob ( searchpath )
            if foundfiles :
                matching . extend ( foundfiles )
                LOGINFO ( 'found %s in dir: %s' % ( repr ( foundfiles ) , os . path . join ( root , sdir ) ) )
# now that we ' ve found everything , read them all in
if len ( matching ) > 0 :
    LOGINFO ( 'consolidating...' )
    # the first file
    consolidated = read_kepler_fitslc ( matching [ 0 ] , headerkeys = headerkeys , datakeys = datakeys , sapkeys = sapkeys , pdckeys = pdckeys , topkeys = topkeys , apkeys = apkeys , normalize = normalize )
    # get the rest of the files
    for lcf in matching :
        consolidated = read_kepler_fitslc ( lcf , appendto = consolidated , headerkeys = headerkeys , datakeys = datakeys , sapkeys = sapkeys , pdckeys = pdckeys , topkeys = topkeys , apkeys = apkeys , normalize = normalize )
    # get the sort indices
    # we use time for the columns and quarters for the headers
    LOGINFO ( 'sorting by time...' )
    # NOTE : nans in time will be sorted to the end of the array
    finiteind = npisfinite ( consolidated [ 'time' ] )
    if npsum ( finiteind ) < consolidated [ 'time' ] . size :
        LOGWARNING ( 'some time values are nan! ' 'measurements at these times will be ' 'sorted to the end of the column arrays.' )
    # get the sort index
    column_sort_ind = npargsort ( consolidated [ 'time' ] )
    # sort the columns by time
    for col in consolidated [ 'columns' ] :
        if '.' in col :
            key , subkey = col . split ( '.' )
            consolidated [ key ] [ subkey ] = ( consolidated [ key ] [ subkey ] [ column_sort_ind ] )
        else :
            consolidated [ col ] = consolidated [ col ] [ column_sort_ind ]
    # now sort the headers by quarters
    header_sort_ind = npargsort ( consolidated [ 'quarter' ] ) . tolist ( )
    # this is a bit convoluted , but whatever : list - > array - > list
    for key in ( 'quarter' , 'season' , 'datarelease' , 'obsmode' ) :
        consolidated [ key ] = ( nparray ( consolidated [ key ] ) [ header_sort_ind ] . tolist ( ) )
    for key in ( 'timesys' , 'bjdoffset' , 'exptime' , 'lcaperture' , 'aperpixused' , 'aperpixunused' , 'pixarcsec' , 'channel' , 'skygroup' , 'module' , 'output' , 'ndet' ) :
        consolidated [ 'lcinfo' ] [ key ] = ( nparray ( consolidated [ 'lcinfo' ] [ key ] ) [ header_sort_ind ] . tolist ( ) )
    for key in ( 'cdpp3_0' , 'cdpp6_0' , 'cdpp12_0' , 'pdcvar' , 'pdcmethod' , 'aper_target_total_ratio' , 'aper_target_frac' ) :
        consolidated [ 'varinfo' ] [ key ] = ( nparray ( consolidated [ 'varinfo' ] [ key ] ) [ header_sort_ind ] . tolist ( ) )
    # finally , return the consolidated lcdict
    return consolidated
# if we didn ' t find anything , complain
else :
    LOGERROR ( 'could not find any light curves ' 'for %s in %s or its subdirectories' % ( keplerid , lcfitsdir ) )
    return None


signature:
def read_k2sff_lightcurve ( lcfits ) :
    '''This reads a K2 SFF ( Vandenberg + 2014 ) light curve into an ` lcdict ` .
 Use this with the light curves from the K2 SFF project at MAST .
 Parameters
 lcfits : str
 The filename of the FITS light curve file downloaded from MAST .
 Returns
 lcdict
 Returns an ` lcdict ` ( this is useable by most astrobase functions for LC
 processing ) .'''

implementation:
# read the fits file
hdulist = pyfits . open ( lcfits )
lchdr , lcdata = hdulist [ 1 ] . header , hdulist [ 1 ] . data
lctophdr = hdulist [ 0 ] . header
hdulist . close ( )
hdrinfo = { }
# get the number of detections
ndet = lchdr [ 'NAXIS2' ]
# get the info from the topheader
for key in SFFTOPKEYS :
    if key in lctophdr and lctophdr [ key ] is not None :
        hdrinfo [ key . lower ( ) ] = lctophdr [ key ]
    else :
        hdrinfo [ key . lower ( ) ] = None
# now get the values we want from the header
for key in SFFHEADERKEYS :
    if key in lchdr and lchdr [ key ] is not None :
        hdrinfo [ key . lower ( ) ] = lchdr [ key ]
    else :
        hdrinfo [ key . lower ( ) ] = None
# form the lcdict
# the metadata is one - elem arrays because we might add on to them later
lcdict = { 'quarter' : [ hdrinfo [ 'quarter' ] ] , 'season' : [ hdrinfo [ 'season' ] ] , 'datarelease' : [ hdrinfo [ 'data_rel' ] ] , 'obsmode' : [ hdrinfo [ 'obsmode' ] ] , 'objectid' : hdrinfo [ 'object' ] , 'campaign' : [ hdrinfo [ 'campaign' ] ] , 'lcinfo' : { 'timesys' : [ hdrinfo [ 'timesys' ] ] , 'bjdoffset' : [ hdrinfo [ 'bjdrefi' ] + hdrinfo [ 'bjdreff' ] ] , 'exptime' : [ hdrinfo [ 'exposure' ] ] , 'lcapermaskidx' : [ hdrinfo [ 'maskinde' ] ] , 'lcapermasktype' : [ hdrinfo [ 'masktype' ] ] , 'aperpixused' : [ hdrinfo [ 'npixsap' ] ] , 'aperpixunused' : [ None ] , 'pixarcsec' : [ None ] , 'channel' : [ hdrinfo [ 'channel' ] ] , 'skygroup' : [ hdrinfo [ 'skygroup' ] ] , 'module' : [ hdrinfo [ 'module' ] ] , 'output' : [ hdrinfo [ 'output' ] ] , 'ndet' : [ ndet ] , } , 'objectinfo' : { 'keplerid' : hdrinfo [ 'keplerid' ] , 'ra' : hdrinfo [ 'ra_obj' ] , 'decl' : hdrinfo [ 'dec_obj' ] , 'pmra' : hdrinfo [ 'pmra' ] , 'pmdecl' : hdrinfo [ 'pmdec' ] , 'pmtotal' : hdrinfo [ 'pmtotal' ] , 'sdssg' : hdrinfo [ 'gmag' ] , 'sdssr' : hdrinfo [ 'rmag' ] , 'sdssi' : hdrinfo [ 'imag' ] , 'sdssz' : hdrinfo [ 'zmag' ] , 'kepmag' : hdrinfo [ 'kepmag' ] , 'teff' : hdrinfo [ 'teff' ] , 'logg' : hdrinfo [ 'logg' ] , 'feh' : hdrinfo [ 'feh' ] , 'ebminusv' : hdrinfo [ 'ebminusv' ] , 'extinction' : hdrinfo [ 'av' ] , 'starradius' : hdrinfo [ 'radius' ] , 'twomassuid' : hdrinfo [ 'tmindex' ] , } , 'varinfo' : { 'cdpp3_0' : [ hdrinfo [ 'cdpp3_0' ] ] , 'cdpp6_0' : [ hdrinfo [ 'cdpp6_0' ] ] , 'cdpp12_0' : [ hdrinfo [ 'cdpp12_0' ] ] , 'pdcvar' : [ hdrinfo [ 'pdcvar' ] ] , 'pdcmethod' : [ hdrinfo [ 'pdcmethd' ] ] , 'aptgttotrat' : [ hdrinfo [ 'crowdsap' ] ] , 'aptgtfrac' : [ hdrinfo [ 'flfrcsap' ] ] , } , }
# get the LC columns
for key in SFFDATAKEYS :
    lcdict [ key . lower ( ) ] = lcdata [ key ]
# add some of the light curve information to the data arrays so we can sort
# on them later
lcdict [ 'channel' ] = npfull_like ( lcdict [ 't' ] , lcdict [ 'lcinfo' ] [ 'channel' ] [ 0 ] )
lcdict [ 'skygroup' ] = npfull_like ( lcdict [ 't' ] , lcdict [ 'lcinfo' ] [ 'skygroup' ] [ 0 ] )
lcdict [ 'module' ] = npfull_like ( lcdict [ 't' ] , lcdict [ 'lcinfo' ] [ 'module' ] [ 0 ] )
lcdict [ 'output' ] = npfull_like ( lcdict [ 't' ] , lcdict [ 'lcinfo' ] [ 'output' ] [ 0 ] )
lcdict [ 'quarter' ] = npfull_like ( lcdict [ 't' ] , lcdict [ 'quarter' ] [ 0 ] )
lcdict [ 'season' ] = npfull_like ( lcdict [ 't' ] , lcdict [ 'season' ] [ 0 ] )
lcdict [ 'campaign' ] = npfull_like ( lcdict [ 't' ] , lcdict [ 'campaign' ] [ 0 ] )
# update the lcdict columns with the actual columns
lcdict [ 'columns' ] = ( [ x . lower ( ) for x in SFFDATAKEYS ] + [ 'channel' , 'skygroup' , 'module' , 'output' , 'quarter' , 'season' , 'campaign' ] )
# return the lcdict at the end
return lcdict


signature:
def kepler_lcdict_to_pkl ( lcdict , outfile = None ) :
    '''This writes the ` lcdict ` to a Python pickle .
 Parameters
 lcdict : lcdict
 This is the input ` lcdict ` to write to a pickle .
 outfile : str or None
 If this is None , the object ' s Kepler ID / EPIC ID will determined from the
 ` lcdict ` and used to form the filename of the output pickle file . If
 this is a ` str ` , the provided filename will be used .
 Returns
 str
 The absolute path to the written pickle file .'''

implementation:
if not outfile :
    outfile = '%s-keplc.pkl' % lcdict [ 'objectid' ] . replace ( ' ' , '-' )
# we ' re using pickle . HIGHEST _ PROTOCOL here , this will make Py3 pickles
# unreadable for Python 2.7
with open ( outfile , 'wb' ) as outfd :
    pickle . dump ( lcdict , outfd , protocol = pickle . HIGHEST_PROTOCOL )
return os . path . abspath ( outfile )


signature:
def read_kepler_pklc ( picklefile ) :
    '''This turns the pickled lightcurve file back into an ` lcdict ` .
 Parameters
 picklefile : str
 The path to a previously written Kepler LC picklefile generated by
 ` kepler _ lcdict _ to _ pkl ` above .
 Returns
 lcdict
 Returns an ` lcdict ` ( this is useable by most astrobase functions for LC
 processing ) .'''

implementation:
if picklefile . endswith ( '.gz' ) :
    infd = gzip . open ( picklefile , 'rb' )
else :
    infd = open ( picklefile , 'rb' )
try :
    with infd :
        lcdict = pickle . load ( infd )
except UnicodeDecodeError :
    with open ( picklefile , 'rb' ) as infd :
        lcdict = pickle . load ( infd , encoding = 'latin1' )
    LOGWARNING ( 'pickle %s was probably from Python 2 ' 'and failed to load without using "latin1" encoding. ' 'This is probably a numpy issue: ' 'http://stackoverflow.com/q/11305790' % picklefile )
return lcdict


signature:
def filter_kepler_lcdict ( lcdict , filterflags = True , nanfilter = 'sap,pdc' , timestoignore = None ) :
    '''This filters the Kepler ` lcdict ` , removing nans and bad
 observations .
 By default , this function removes points in the Kepler LC that have ANY
 quality flags set .
 Parameters
 lcdict : lcdict
 An ` lcdict ` produced by ` consolidate _ kepler _ fitslc ` or
 ` read _ kepler _ fitslc ` .
 filterflags : bool
 If True , will remove any measurements that have non - zero quality flags
 present . This usually indicates an issue with the instrument or
 spacecraft .
 nanfilter : { ' sap ' , ' pdc ' , ' sap , pdc ' }
 Indicates the flux measurement type ( s ) to apply the filtering to .
 timestoignore : list of tuples or None
 This is of the form : :
 [ ( time1 _ start , time1 _ end ) , ( time2 _ start , time2 _ end ) , . . . ]
 and indicates the start and end times to mask out of the final
 lcdict . Use this to remove anything that wasn ' t caught by the quality
 flags .
 Returns
 lcdict
 Returns an ` lcdict ` ( this is useable by most astrobase functions for LC
 processing ) . The ` lcdict ` is filtered IN PLACE !'''

implementation:
cols = lcdict [ 'columns' ]
# filter all bad LC points as noted by quality flags
if filterflags :
    nbefore = lcdict [ 'time' ] . size
    filterind = lcdict [ 'sap_quality' ] == 0
    for col in cols :
        if '.' in col :
            key , subkey = col . split ( '.' )
            lcdict [ key ] [ subkey ] = lcdict [ key ] [ subkey ] [ filterind ]
        else :
            lcdict [ col ] = lcdict [ col ] [ filterind ]
    nafter = lcdict [ 'time' ] . size
    LOGINFO ( 'applied quality flag filter, ndet before = %s, ndet after = %s' % ( nbefore , nafter ) )
if nanfilter and nanfilter == 'sap,pdc' :
    notnanind = ( npisfinite ( lcdict [ 'sap' ] [ 'sap_flux' ] ) & npisfinite ( lcdict [ 'pdc' ] [ 'pdcsap_flux' ] ) & npisfinite ( lcdict [ 'time' ] ) )
elif nanfilter and nanfilter == 'sap' :
    notnanind = ( npisfinite ( lcdict [ 'sap' ] [ 'sap_flux' ] ) & npisfinite ( lcdict [ 'time' ] ) )
elif nanfilter and nanfilter == 'pdc' :
    notnanind = ( npisfinite ( lcdict [ 'pdc' ] [ 'pdcsap_flux' ] ) & npisfinite ( lcdict [ 'time' ] ) )
# remove nans from all columns
if nanfilter :
    nbefore = lcdict [ 'time' ] . size
    for col in cols :
        if '.' in col :
            key , subkey = col . split ( '.' )
            lcdict [ key ] [ subkey ] = lcdict [ key ] [ subkey ] [ notnanind ]
        else :
            lcdict [ col ] = lcdict [ col ] [ notnanind ]
    nafter = lcdict [ 'time' ] . size
    LOGINFO ( 'removed nans, ndet before = %s, ndet after = %s' % ( nbefore , nafter ) )
# exclude all times in timestoignore
if ( timestoignore and isinstance ( timestoignore , list ) and len ( timestoignore ) > 0 ) :
    exclind = npfull_like ( lcdict [ 'time' ] , True , dtype = np . bool_ )
    nbefore = exclind . size
    # get all the masks
    for ignoretime in timestoignore :
        time0 , time1 = ignoretime [ 0 ] , ignoretime [ 1 ]
        thismask = ~ ( ( lcdict [ 'time' ] >= time0 ) & ( lcdict [ 'time' ] <= time1 ) )
        exclind = exclind & thismask
    # apply the masks
    for col in cols :
        if '.' in col :
            key , subkey = col . split ( '.' )
            lcdict [ key ] [ subkey ] = lcdict [ key ] [ subkey ] [ exclind ]
        else :
            lcdict [ col ] = lcdict [ col ] [ exclind ]
    nafter = lcdict [ 'time' ] . size
    LOGINFO ( 'removed timestoignore, ndet before = %s, ndet after = %s' % ( nbefore , nafter ) )
return lcdict


signature:
def _epd_function ( coeffs , fluxes , xcc , ycc , bgv , bge ) :
    '''This is the EPD function to fit .
 Parameters
 coeffs : array - like of floats
 Contains the EPD coefficients that will be used to generate the EPD fit
 function .
 fluxes : array - like
 The flux measurement array being used .
 xcc , ycc : array - like
 Arrays of the x and y coordinates associated with each measurement in
 ` fluxes ` .
 bgv , bge : array - like
 Arrays of the flux background value and the flux background error
 associated with each measurement in ` fluxes ` .
 Returns
 np . array
 Contains the fit function evaluated at each flux measurement value .'''

implementation:
epdf = ( coeffs [ 0 ] + coeffs [ 1 ] * npsin ( 2 * MPI * xcc ) + coeffs [ 2 ] * npcos ( 2 * MPI * xcc ) + coeffs [ 3 ] * npsin ( 2 * MPI * ycc ) + coeffs [ 4 ] * npcos ( 2 * MPI * ycc ) + coeffs [ 5 ] * npsin ( 4 * MPI * xcc ) + coeffs [ 6 ] * npcos ( 4 * MPI * xcc ) + coeffs [ 7 ] * npsin ( 4 * MPI * ycc ) + coeffs [ 8 ] * npcos ( 4 * MPI * ycc ) + coeffs [ 9 ] * bgv + coeffs [ 10 ] * bge )
return epdf


signature:
def _epd_residual ( coeffs , fluxes , xcc , ycc , bgv , bge ) :
    '''This is the residual function to minimize using scipy . optimize . leastsq .
 Parameters
 coeffs : array - like of floats
 Contains the EPD coefficients that will be used to generate the EPD fit
 function .
 fluxes : array - like
 The flux measurement array being used .
 xcc , ycc : array - like
 Arrays of the x and y coordinates associated with each measurement in
 ` fluxes ` .
 bgv , bge : array - like
 Arrays of the flux background value and the flux background error
 associated with each measurement in ` fluxes ` .
 Returns
 np . array
 Contains the fit function residual evaluated at each flux measurement
 value .'''

implementation:
f = _epd_function ( coeffs , fluxes , xcc , ycc , bgv , bge )
residual = fluxes - f
return residual