signature:
def bls_parallel_pfind ( times , mags , errs , magsarefluxes = False , startp = 0.1 , # by default , search from 0.1 d to . . .
endp = 100.0 , # . . . 100.0 d - - don ' t search full timebase
stepsize = 1.0e-4 , mintransitduration = 0.01 , # minimum transit length in phase
maxtransitduration = 0.4 , # maximum transit length in phase
ndurations = 100 , autofreq = True , # figure out f0 , nf , and df automatically
blsobjective = 'likelihood' , blsmethod = 'fast' , blsoversample = 5 , blsmintransits = 3 , blsfreqfactor = 10.0 , nbestpeaks = 5 , periodepsilon = 0.1 , # 0.1
sigclip = 10.0 , verbose = True , nworkers = None , ) :
    '''Runs the Box Least Squares Fitting Search for transit - shaped signals .
 Breaks up the full frequency space into chunks and passes them to parallel
 BLS workers .
 Based on the version of BLS in Astropy 3.1:
 ` astropy . stats . BoxLeastSquares ` . If you don ' t have Astropy 3.1 , this module
 will fail to import . Note that by default , this implementation of
 ` bls _ parallel _ pfind ` doesn ' t use the ` . autoperiod ( ) ` function from
 ` BoxLeastSquares ` but uses the same auto frequency - grid generation as the
 functions in ` periodbase . kbls ` . If you want to use Astropy ' s implementation ,
 set the value of ` autofreq ` kwarg to ' astropy ' . The generated period array
 will then be broken up into chunks and sent to the individual workers .
 NOTE : the combined BLS spectrum produced by this function is not identical
 to that produced by running BLS in one shot for the entire frequency
 space . There are differences on the order of 1.0e - 3 or so in the respective
 peak values , but peaks appear at the same frequencies for both methods . This
 is likely due to different aliasing caused by smaller chunks of the
 frequency space used by the parallel workers in this function . When in
 doubt , confirm results for this parallel implementation by comparing to
 those from the serial implementation above .
 In particular , when you want to get reliable estimates of the SNR , transit
 depth , duration , etc . that Astropy ' s BLS gives you , rerun ` bls _ serial _ pfind `
 with ` startp ` , and ` endp ` close to the best period you want to characterize
 the transit at . The dict returned from that function contains a ` blsmodel `
 key , which is the generated model from Astropy ' s BLS . Use the
 ` . compute _ stats ( ) ` method to calculate the required stats .
 Parameters
 times , mags , errs : np . array
 The magnitude / flux time - series to search for transits .
 magsarefluxes : bool
 If the input measurement values in ` mags ` and ` errs ` are in fluxes , set
 this to True .
 startp , endp : float
 The minimum and maximum periods to consider for the transit search .
 stepsize : float
 The step - size in frequency to use when constructing a frequency grid for
 the period search .
 mintransitduration , maxtransitduration : float
 The minimum and maximum transitdurations ( in units of phase ) to consider
 for the transit search .
 ndurations : int
 The number of transit durations to use in the period - search .
 autofreq : bool or str
 If this is True , the values of ` stepsize ` and ` nphasebins ` will be
 ignored , and these , along with a frequency - grid , will be determined
 based on the following relations : :
 nphasebins = int ( ceil ( 2.0 / mintransitduration ) )
 if nphasebins > 3000:
 nphasebins = 3000
 stepsize = 0.25 * mintransitduration / ( times . max ( ) - times . min ( ) )
 minfreq = 1.0 / endp
 maxfreq = 1.0 / startp
 nfreq = int ( ceil ( ( maxfreq - minfreq ) / stepsize ) )
 If this is False , you must set ` startp ` , ` endp ` , and ` stepsize ` as
 appropriate .
 If this is str = = ' astropy ' , will use the
 ` astropy . stats . BoxLeastSquares . autoperiod ( ) ` function to calculate the
 frequency grid instead of the kbls method .
 blsobjective : { ' likelihood ' , ' snr ' }
 Sets the type of objective to optimize in the ` BoxLeastSquares . power ( ) `
 function .
 blsmethod : { ' fast ' , ' slow ' }
 Sets the type of method to use in the ` BoxLeastSquares . power ( ) `
 function .
 blsoversample : { ' likelihood ' , ' snr ' }
 Sets the ` oversample ` kwarg for the ` BoxLeastSquares . power ( ) ` function .
 blsmintransits : int
 Sets the ` min _ n _ transits ` kwarg for the ` BoxLeastSquares . autoperiod ( ) `
 function .
 blsfreqfactor : float
 Sets the ` frequency _ factor ` kwarg for the ` BoxLeastSquares . autoperiod ( ) `
 function .
 periodepsilon : float
 The fractional difference between successive values of ' best ' periods
 when sorting by periodogram power to consider them as separate periods
 ( as opposed to part of the same periodogram peak ) . This is used to avoid
 broad peaks in the periodogram and make sure the ' best ' periods returned
 are all actually independent .
 nbestpeaks : int
 The number of ' best ' peaks to return from the periodogram results ,
 starting from the global maximum of the periodogram peak values .
 sigclip : float or int or sequence of two floats / ints or None
 If a single float or int , a symmetric sigma - clip will be performed using
 the number provided as the sigma - multiplier to cut out from the input
 time - series .
 If a list of two ints / floats is provided , the function will perform an
 ' asymmetric ' sigma - clip . The first element in this list is the sigma
 value to use for fainter flux / mag values ; the second element in this
 list is the sigma value to use for brighter flux / mag values . For
 example , ` sigclip = [ 10 . , 3 . ] ` , will sigclip out greater than 10 - sigma
 dimmings and greater than 3 - sigma brightenings . Here the meaning of
 " dimming " and " brightening " is set by * physics * ( not the magnitude
 system ) , which is why the ` magsarefluxes ` kwarg must be correctly set .
 If ` sigclip ` is None , no sigma - clipping will be performed , and the
 time - series ( with non - finite elems removed ) will be passed through to
 the output .
 verbose : bool
 If this is True , will indicate progress and details about the frequency
 grid used for the period search .
 nworkers : int or None
 The number of parallel workers to launch for period - search . If None ,
 nworkers = NCPUS .
 Returns
 dict
 This function returns a dict , referred to as an ` lspinfo ` dict in other
 astrobase functions that operate on periodogram results . This is a
 standardized format across all astrobase period - finders , and is of the
 form below : :
 { ' bestperiod ' : the best period value in the periodogram ,
 ' bestlspval ' : the periodogram peak associated with the best period ,
 ' nbestpeaks ' : the input value of nbestpeaks ,
 ' nbestlspvals ' : nbestpeaks - size list of best period peak values ,
 ' nbestperiods ' : nbestpeaks - size list of best periods ,
 ' lspvals ' : the full array of periodogram powers ,
 ' frequencies ' : the full array of frequencies considered ,
 ' periods ' : the full array of periods considered ,
 ' durations ' : the array of durations used to run BLS ,
 ' blsresult ' : Astropy BLS result object ( BoxLeastSquaresResult ) ,
 ' blsmodel ' : Astropy BLS BoxLeastSquares object used for work ,
 ' stepsize ' : the actual stepsize used ,
 ' nfreq ' : the actual nfreq used ,
 ' durations ' : the durations array used ,
 ' mintransitduration ' : the input mintransitduration ,
 ' maxtransitduration ' : the input maxtransitdurations ,
 ' method ' : ' bls ' - > the name of the period - finder method ,
 ' kwargs ' : { dict of all of the input kwargs for record - keeping } }'''

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 : # if we ' re setting up everything automatically
    if isinstance ( autofreq , bool ) and autofreq : # use heuristic to figure out best timestep
        stepsize = 0.25 * mintransitduration / ( stimes . max ( ) - stimes . min ( ) )
        # now figure out the frequencies to use
        minfreq = 1.0 / endp
        maxfreq = 1.0 / startp
        nfreq = int ( npceil ( ( maxfreq - minfreq ) / stepsize ) )
        # say what we ' re using
        if verbose :
            LOGINFO ( 'min P: %s, max P: %s, nfreq: %s, ' 'minfreq: %s, maxfreq: %s' % ( startp , endp , nfreq , minfreq , maxfreq ) )
            LOGINFO ( 'autofreq = True: using AUTOMATIC values for ' 'freq stepsize: %s, ndurations: %s, ' 'min transit duration: %s, max transit duration: %s' % ( stepsize , ndurations , mintransitduration , maxtransitduration ) )
        use_autoperiod = False
    elif isinstance ( autofreq , bool ) and not autofreq :
        minfreq = 1.0 / endp
        maxfreq = 1.0 / startp
        nfreq = int ( npceil ( ( maxfreq - minfreq ) / stepsize ) )
        # say what we ' re using
        if verbose :
            LOGINFO ( 'min P: %s, max P: %s, nfreq: %s, ' 'minfreq: %s, maxfreq: %s' % ( startp , endp , nfreq , minfreq , maxfreq ) )
            LOGINFO ( 'autofreq = False: using PROVIDED values for ' 'freq stepsize: %s, ndurations: %s, ' 'min transit duration: %s, max transit duration: %s' % ( stepsize , ndurations , mintransitduration , maxtransitduration ) )
        use_autoperiod = False
    elif isinstance ( autofreq , str ) and autofreq == 'astropy' :
        use_autoperiod = True
        minfreq = 1.0 / endp
        maxfreq = 1.0 / startp
    else :
        LOGERROR ( "unknown autofreq kwarg encountered. can't continue..." )
        return None
    # check the minimum frequency
    if minfreq < ( 1.0 / ( stimes . max ( ) - stimes . min ( ) ) ) :
        minfreq = 2.0 / ( stimes . max ( ) - stimes . min ( ) )
        if verbose :
            LOGWARNING ( 'the requested max P = %.3f is larger than ' 'the time base of the observations = %.3f, ' ' will make minfreq = 2 x 1/timebase' % ( endp , stimes . max ( ) - stimes . min ( ) ) )
            LOGINFO ( 'new minfreq: %s, maxfreq: %s' % ( minfreq , maxfreq ) )
    # # NOW RUN BLS IN PARALLEL # #
    # fix number of CPUs if needed
    if not nworkers or nworkers > NCPUS :
        nworkers = NCPUS
        if verbose :
            LOGINFO ( 'using %s workers...' % nworkers )
    # check if autoperiod is True and get the correct period - grid
    if use_autoperiod : # astropy ' s BLS requires durations in units of time
        durations = nplinspace ( mintransitduration * startp , maxtransitduration * startp , ndurations )
        # set up the correct units for the BLS model
        if magsarefluxes :
            blsmodel = BoxLeastSquares ( stimes * u . day , smags * u . dimensionless_unscaled , dy = serrs * u . dimensionless_unscaled )
        else :
            blsmodel = BoxLeastSquares ( stimes * u . day , smags * u . mag , dy = serrs * u . mag )
        periods = nparray ( blsmodel . autoperiod ( durations * u . day , minimum_period = startp , maximum_period = endp , minimum_n_transit = blsmintransits , frequency_factor = blsfreqfactor ) )
        frequencies = 1.0 / periods
        nfreq = frequencies . size
        if verbose :
            LOGINFO ( "autofreq = 'astropy', used .autoperiod() with " "minimum_n_transit = %s, freq_factor = %s " "to generate the frequency grid" % ( blsmintransits , blsfreqfactor ) )
            LOGINFO ( 'stepsize = %s, nfreq = %s, minfreq = %.5f, ' 'maxfreq = %.5f, ndurations = %s' % ( abs ( frequencies [ 1 ] - frequencies [ 0 ] ) , nfreq , 1.0 / periods . max ( ) , 1.0 / periods . min ( ) , durations . size ) )
        del blsmodel
        del durations
    # otherwise , use kbls method
    else :
        frequencies = minfreq + nparange ( nfreq ) * stepsize
    # break up the tasks into chunks
    csrem = int ( fmod ( nfreq , nworkers ) )
    csint = int ( float ( nfreq / nworkers ) )
    chunk_minfreqs , chunk_nfreqs = [ ] , [ ]
    for x in range ( nworkers ) :
        this_minfreqs = frequencies [ x * csint ]
        # handle usual nfreqs
        if x < ( nworkers - 1 ) :
            this_nfreqs = frequencies [ x * csint : x * csint + csint ] . size
        else :
            this_nfreqs = frequencies [ x * csint : x * csint + csint + csrem ] . size
        chunk_minfreqs . append ( this_minfreqs )
        chunk_nfreqs . append ( this_nfreqs )
    # populate the tasks list
    # task [ 0 ] = times
    # task [ 1 ] = mags
    # task [ 2 ] = errs
    # task [ 3 ] = magsarefluxes
    # task [ 4 ] = minfreq
    # task [ 5 ] = nfreq
    # task [ 6 ] = stepsize
    # task [ 7 ] = nphasebins
    # task [ 8 ] = mintransitduration
    # task [ 9 ] = maxtransitduration
    # task [ 10 ] = blsobjective
    # task [ 11 ] = blsmethod
    # task [ 12 ] = blsoversample
    # populate the tasks list
    tasks = [ ( stimes , smags , serrs , magsarefluxes , chunk_minf , chunk_nf , stepsize , ndurations , mintransitduration , maxtransitduration , blsobjective , blsmethod , blsoversample ) for ( chunk_minf , chunk_nf ) in zip ( chunk_minfreqs , chunk_nfreqs ) ]
    if verbose :
        for ind , task in enumerate ( tasks ) :
            LOGINFO ( 'worker %s: minfreq = %.6f, nfreqs = %s' % ( ind + 1 , task [ 4 ] , task [ 5 ] ) )
        LOGINFO ( 'running...' )
    # return tasks
    # start the pool
    pool = Pool ( nworkers )
    results = pool . map ( _parallel_bls_worker , tasks )
    pool . close ( )
    pool . join ( )
    del pool
    # now concatenate the output lsp arrays
    lsp = npconcatenate ( [ x [ 'power' ] for x in results ] )
    periods = 1.0 / frequencies
    # find the nbestpeaks for the periodogram : 1 . sort the lsp array
    # by highest value first 2 . go down the values until we find
    # five values that are separated by at least periodepsilon in
    # period
    # make sure to get only the finite peaks in the periodogram
    # this is needed because BLS may produce infs for some peaks
    finitepeakind = npisfinite ( lsp )
    finlsp = lsp [ finitepeakind ]
    finperiods = periods [ finitepeakind ]
    # make sure that finlsp has finite values before we work on it
    try :
        bestperiodind = npargmax ( finlsp )
    except ValueError :
        LOGERROR ( 'no finite periodogram values ' 'for this mag series, skipping...' )
        return { 'bestperiod' : npnan , 'bestlspval' : npnan , 'nbestpeaks' : nbestpeaks , 'nbestinds' : None , 'nbestlspvals' : None , 'nbestperiods' : None , 'lspvals' : None , 'periods' : None , 'durations' : None , 'method' : 'bls' , 'blsresult' : None , 'blsmodel' : None , 'kwargs' : { 'startp' : startp , 'endp' : endp , 'stepsize' : stepsize , 'mintransitduration' : mintransitduration , 'maxtransitduration' : maxtransitduration , 'ndurations' : ndurations , 'blsobjective' : blsobjective , 'blsmethod' : blsmethod , 'blsoversample' : blsoversample , 'autofreq' : autofreq , 'periodepsilon' : periodepsilon , 'nbestpeaks' : nbestpeaks , 'sigclip' : sigclip , 'magsarefluxes' : magsarefluxes } }
    sortedlspind = npargsort ( finlsp ) [ : : - 1 ]
    sortedlspperiods = finperiods [ sortedlspind ]
    sortedlspvals = finlsp [ sortedlspind ]
    # now get the nbestpeaks
    nbestperiods , nbestlspvals , nbestinds , peakcount = ( [ finperiods [ bestperiodind ] ] , [ finlsp [ bestperiodind ] ] , [ bestperiodind ] , 1 )
    prevperiod = sortedlspperiods [ 0 ]
    # find the best nbestpeaks in the lsp and their periods
    for period , lspval , ind in zip ( sortedlspperiods , sortedlspvals , sortedlspind ) :
        if peakcount == nbestpeaks :
            break
        perioddiff = abs ( period - prevperiod )
        bestperiodsdiff = [ abs ( period - x ) for x in nbestperiods ]
        # this ensures that this period is different from the last
        # period and from all the other existing best periods by
        # periodepsilon to make sure we jump to an entire different
        # peak in the periodogram
        if ( perioddiff > ( periodepsilon * prevperiod ) and all ( x > ( periodepsilon * period ) for x in bestperiodsdiff ) ) :
            nbestperiods . append ( period )
            nbestlspvals . append ( lspval )
            nbestinds . append ( ind )
            peakcount = peakcount + 1
        prevperiod = period
    # generate the return dict
    resultdict = { 'bestperiod' : finperiods [ bestperiodind ] , 'bestlspval' : finlsp [ bestperiodind ] , 'nbestpeaks' : nbestpeaks , 'nbestinds' : nbestinds , 'nbestlspvals' : nbestlspvals , 'nbestperiods' : nbestperiods , 'lspvals' : lsp , 'frequencies' : frequencies , 'periods' : periods , 'durations' : [ x [ 'durations' ] for x in results ] , 'blsresult' : [ x [ 'blsresult' ] for x in results ] , 'blsmodel' : [ x [ 'blsmodel' ] for x in results ] , 'stepsize' : stepsize , 'nfreq' : nfreq , 'mintransitduration' : mintransitduration , 'maxtransitduration' : maxtransitduration , 'method' : 'bls' , 'kwargs' : { 'startp' : startp , 'endp' : endp , 'stepsize' : stepsize , 'mintransitduration' : mintransitduration , 'maxtransitduration' : maxtransitduration , 'ndurations' : ndurations , 'blsobjective' : blsobjective , 'blsmethod' : blsmethod , 'blsoversample' : blsoversample , 'autofreq' : autofreq , 'periodepsilon' : periodepsilon , 'nbestpeaks' : nbestpeaks , 'sigclip' : sigclip , 'magsarefluxes' : magsarefluxes } }
    return resultdict
else :
    LOGERROR ( 'no good detections for these times and mags, skipping...' )
    return { 'bestperiod' : npnan , 'bestlspval' : npnan , 'nbestinds' : None , 'nbestpeaks' : nbestpeaks , 'nbestlspvals' : None , 'nbestperiods' : None , 'lspvals' : None , 'periods' : None , 'durations' : None , 'blsresult' : None , 'blsmodel' : None , 'stepsize' : stepsize , 'nfreq' : None , 'nphasebins' : None , 'mintransitduration' : mintransitduration , 'maxtransitduration' : maxtransitduration , 'method' : 'bls' , 'kwargs' : { 'startp' : startp , 'endp' : endp , 'stepsize' : stepsize , 'mintransitduration' : mintransitduration , 'maxtransitduration' : maxtransitduration , 'ndurations' : ndurations , 'blsobjective' : blsobjective , 'blsmethod' : blsmethod , 'blsoversample' : blsoversample , 'autofreq' : autofreq , 'periodepsilon' : periodepsilon , 'nbestpeaks' : nbestpeaks , 'sigclip' : sigclip , 'magsarefluxes' : magsarefluxes } }


signature:
def _parse_csv_header ( header ) :
    '''This parses a CSV header from a K2 CSV LC .
 Returns a dict that can be used to update an existing lcdict with the
 relevant metadata info needed to form a full LC .'''

implementation:
# first , break into lines
headerlines = header . split ( '\n' )
headerlines = [ x . lstrip ( '# ' ) for x in headerlines ]
# next , find the indices of the ' # COLUMNS ' line and ' # LIGHTCURVE ' line
metadatastart = headerlines . index ( 'METADATA' )
columnstart = headerlines . index ( 'COLUMNS' )
lcstart = headerlines . index ( 'LIGHTCURVE' )
# get the lines for the metadata and columndefs
metadata = headerlines [ metadatastart + 1 : columnstart - 1 ]
columndefs = headerlines [ columnstart + 1 : lcstart - 1 ]
# parse the metadata
metainfo = [ x . split ( ',' ) for x in metadata ] [ : - 1 ]
aperpixradius = metadata [ - 1 ]
objectid , kepid , ucac4id , kepmag = metainfo [ 0 ]
objectid , kepid , ucac4id , kepmag = ( objectid . split ( ' = ' ) [ - 1 ] , kepid . split ( ' = ' ) [ - 1 ] , ucac4id . split ( ' = ' ) [ - 1 ] , kepmag . split ( ' = ' ) [ - 1 ] )
kepmag = float ( kepmag ) if kepmag else None
ra , decl , ndet , k2campaign = metainfo [ 1 ]
ra , decl , ndet , k2campaign = ( ra . split ( ' = ' ) [ - 1 ] , decl . split ( ' = ' ) [ - 1 ] , int ( ndet . split ( ' = ' ) [ - 1 ] ) , int ( k2campaign . split ( ' = ' ) [ - 1 ] ) )
fovccd , fovchannel , fovmodule = metainfo [ 2 ]
fovccd , fovchannel , fovmodule = ( int ( fovccd . split ( ' = ' ) [ - 1 ] ) , int ( fovchannel . split ( ' = ' ) [ - 1 ] ) , int ( fovmodule . split ( ' = ' ) [ - 1 ] ) )
try :
    qualflag , bjdoffset , napertures = metainfo [ 3 ]
    qualflag , bjdoffset , napertures = ( int ( qualflag . split ( ' = ' ) [ - 1 ] ) , float ( bjdoffset . split ( ' = ' ) [ - 1 ] ) , int ( napertures . split ( ' = ' ) [ - 1 ] ) )
    kernelspec = None
except Exception as e :
    qualflag , bjdoffset , napertures , kernelspec = metainfo [ 3 ]
    qualflag , bjdoffset , napertures , kernelspec = ( int ( qualflag . split ( ' = ' ) [ - 1 ] ) , float ( bjdoffset . split ( ' = ' ) [ - 1 ] ) , int ( napertures . split ( ' = ' ) [ - 1 ] ) , str ( kernelspec . split ( ' = ' ) [ - 1 ] ) )
aperpixradius = aperpixradius . split ( ' = ' ) [ - 1 ] . split ( ',' )
aperpixradius = [ float ( x ) for x in aperpixradius ]
# parse the columndefs
columns = [ x . split ( ' - ' ) [ 1 ] for x in columndefs ]
metadict = { 'objectid' : objectid , 'objectinfo' : { 'objectid' : objectid , 'kepid' : kepid , 'ucac4id' : ucac4id , 'kepmag' : kepmag , 'ra' : ra , 'decl' : decl , 'ndet' : ndet , 'k2campaign' : k2campaign , 'fovccd' : fovccd , 'fovchannel' : fovchannel , 'fovmodule' : fovmodule , 'qualflag' : qualflag , 'bjdoffset' : bjdoffset , 'napertures' : napertures , 'kernelspec' : kernelspec , 'aperpixradius' : aperpixradius , } , 'columns' : columns }
return metadict


signature:
def read_csv_lightcurve ( lcfile ) :
    '''This reads in a K2 lightcurve in CSV format . Transparently reads gzipped
 files .
 Parameters
 lcfile : str
 The light curve file to read .
 Returns
 dict
 Returns an lcdict .'''

implementation:
# read in the file first
if '.gz' in os . path . basename ( lcfile ) :
    LOGINFO ( 'reading gzipped K2 LC: %s' % lcfile )
    infd = gzip . open ( lcfile , 'rb' )
else :
    LOGINFO ( 'reading K2 LC: %s' % lcfile )
    infd = open ( lcfile , 'rb' )
lctext = infd . read ( ) . decode ( )
infd . close ( )
# figure out the header and get the LC columns
lcstart = lctext . index ( '# LIGHTCURVE\n' )
lcheader = lctext [ : lcstart + 12 ]
lccolumns = lctext [ lcstart + 13 : ] . split ( '\n' )
lccolumns = [ x . split ( ',' ) for x in lccolumns if len ( x ) > 0 ]
# initialize the lcdict and parse the CSV header
lcdict = _parse_csv_header ( lcheader )
# tranpose the LC rows into columns
lccolumns = list ( zip ( * lccolumns ) )
# write the columns to the dict
for colind , col in enumerate ( lcdict [ 'columns' ] ) : # this picks out the caster to use when reading each column using the
# definitions in the lcutils . COLUMNDEFS dictionary
    lcdict [ col . lower ( ) ] = np . array ( [ COLUMNDEFS [ col ] [ 2 ] ( x ) for x in lccolumns [ colind ] ] )
lcdict [ 'columns' ] = [ x . lower ( ) for x in lcdict [ 'columns' ] ]
return lcdict


signature:
def get_starfeatures ( lcfile , outdir , kdtree , objlist , lcflist , neighbor_radius_arcsec , deredden = True , custom_bandpasses = None , lcformat = 'hat-sql' , lcformatdir = None ) :
    '''This runs the functions from : py : func : ` astrobase . varclass . starfeatures `
 on a single light curve file .
 Parameters
 lcfile : str
 This is the LC file to extract star features for .
 outdir : str
 This is the directory to write the output pickle to .
 kdtree : scipy . spatial . cKDTree
 This is a ` scipy . spatial . KDTree ` or ` cKDTree ` used to calculate neighbor
 proximity features . This is for the light curve catalog this object is
 in .
 objlist : np . array
 This is a Numpy array of object IDs in the same order as the
 ` kdtree . data ` np . array . This is for the light curve catalog this object
 is in .
 lcflist : np . array
 This is a Numpy array of light curve filenames in the same order as
 ` kdtree . data ` . This is for the light curve catalog this object is in .
 neighbor _ radius _ arcsec : float
 This indicates the radius in arcsec to search for neighbors for this
 object using the light curve catalog ' s ` kdtree ` , ` objlist ` , ` lcflist ` ,
 and in GAIA .
 deredden : bool
 This controls if the colors and any color classifications will be
 dereddened using 2MASS DUST .
 custom _ bandpasses : dict or None
 This is a dict used to define any custom bandpasses in the
 ` in _ objectinfo ` dict you want to make this function aware of and
 generate colors for . Use the format below for this dict : :
 ' < bandpass _ key _ 1 > ' : { ' dustkey ' : ' < twomass _ dust _ key _ 1 > ' ,
 ' label ' : ' < band _ label _ 1 > '
 ' colors ' : [ [ ' < bandkey1 > - < bandkey2 > ' ,
 ' < BAND1 > - < BAND2 > ' ] ,
 [ ' < bandkey3 > - < bandkey4 > ' ,
 ' < BAND3 > - < BAND4 > ' ] ] } ,
 ' < bandpass _ key _ N > ' : { ' dustkey ' : ' < twomass _ dust _ key _ N > ' ,
 ' label ' : ' < band _ label _ N > '
 ' colors ' : [ [ ' < bandkey1 > - < bandkey2 > ' ,
 ' < BAND1 > - < BAND2 > ' ] ,
 [ ' < bandkey3 > - < bandkey4 > ' ,
 ' < BAND3 > - < BAND4 > ' ] ] } ,
 Where :
 ` bandpass _ key ` is a key to use to refer to this bandpass in the
 ` objectinfo ` dict , e . g . ' sdssg ' for SDSS g band
 ` twomass _ dust _ key ` is the key to use in the 2MASS DUST result table for
 reddening per band - pass . For example , given the following DUST result
 table ( using http : / / irsa . ipac . caltech . edu / applications / DUST / ) : :
 | Filter _ name | LamEff | A _ over _ E _ B _ V _ SandF | A _ SandF | A _ over _ E _ B _ V _ SFD | A _ SFD |
 | char | float | float | float | float | float |
 | | microns | | mags | | mags |
 CTIO U 0.3734 4.107 0.209 4.968 0.253
 CTIO B 0.4309 3.641 0.186 4.325 0.221
 CTIO V 0.5517 2.682 0.137 3.240 0.165
 The ` twomass _ dust _ key ` for ' vmag ' would be ' CTIO V ' . If you want to
 skip DUST lookup and want to pass in a specific reddening magnitude
 for your bandpass , use a float for the value of
 ` twomass _ dust _ key ` . If you want to skip DUST lookup entirely for
 this bandpass , use None for the value of ` twomass _ dust _ key ` .
 ` band _ label ` is the label to use for this bandpass , e . g . ' W1 ' for
 WISE - 1 band , ' u ' for SDSS u , etc .
 The ' colors ' list contains color definitions for all colors you want
 to generate using this bandpass . this list contains elements of the
 form : :
 [ ' < bandkey1 > - < bandkey2 > ' , ' < BAND1 > - < BAND2 > ' ]
 where the the first item is the bandpass keys making up this color ,
 and the second item is the label for this color to be used by the
 frontends . An example : :
 [ ' sdssu - sdssg ' , ' u - g ' ]
 lcformat : str
 This is the ` formatkey ` associated with your light curve format , which
 you previously passed in to the ` lcproc . register _ lcformat `
 function . This will be used to look up how to find and read the light
 curves specified in ` basedir ` or ` use _ list _ of _ filenames ` .
 lcformatdir : str or None
 If this is provided , gives the path to a directory when you ' ve stored
 your lcformat description JSONs , other than the usual directories lcproc
 knows to search for them in . Use this along with ` lcformat ` to specify
 an LC format JSON file that ' s not currently registered with lcproc .
 Returns
 str
 Path to the output pickle containing all of the star features for this
 object .'''

implementation:
try :
    formatinfo = get_lcformat ( lcformat , use_lcformat_dir = lcformatdir )
    if formatinfo :
        ( dfileglob , readerfunc , dtimecols , dmagcols , derrcols , magsarefluxes , normfunc ) = formatinfo
    else :
        LOGERROR ( "can't figure out the light curve format" )
        return None
except Exception as e :
    LOGEXCEPTION ( "can't figure out the light curve format" )
    return None
try : # get the LC into a dict
    lcdict = readerfunc ( lcfile )
    # this should handle lists / tuples being returned by readerfunc
    # we assume that the first element is the actual lcdict
    # FIXME : figure out how to not need this assumption
    if ( ( isinstance ( lcdict , ( list , tuple ) ) ) and ( isinstance ( lcdict [ 0 ] , dict ) ) ) :
        lcdict = lcdict [ 0 ]
    resultdict = { 'objectid' : lcdict [ 'objectid' ] , 'info' : lcdict [ 'objectinfo' ] , 'lcfbasename' : os . path . basename ( lcfile ) }
    # run the coord features first
    coordfeat = starfeatures . coord_features ( lcdict [ 'objectinfo' ] )
    # next , run the color features
    colorfeat = starfeatures . color_features ( lcdict [ 'objectinfo' ] , deredden = deredden , custom_bandpasses = custom_bandpasses )
    # run a rough color classification
    colorclass = starfeatures . color_classification ( colorfeat , coordfeat )
    # finally , run the neighbor features
    nbrfeat = starfeatures . neighbor_gaia_features ( lcdict [ 'objectinfo' ] , kdtree , neighbor_radius_arcsec )
    # get the objectids of the neighbors found if any
    if nbrfeat [ 'nbrindices' ] . size > 0 :
        nbrfeat [ 'nbrobjectids' ] = objlist [ nbrfeat [ 'nbrindices' ] ]
        nbrfeat [ 'closestnbrobjectid' ] = objlist [ nbrfeat [ 'closestdistnbrind' ] ]
        nbrfeat [ 'closestnbrlcfname' ] = lcflist [ nbrfeat [ 'closestdistnbrind' ] ]
    else :
        nbrfeat [ 'nbrobjectids' ] = np . array ( [ ] )
        nbrfeat [ 'closestnbrobjectid' ] = np . array ( [ ] )
        nbrfeat [ 'closestnbrlcfname' ] = np . array ( [ ] )
    # update the result dict
    resultdict . update ( coordfeat )
    resultdict . update ( colorfeat )
    resultdict . update ( colorclass )
    resultdict . update ( nbrfeat )
    outfile = os . path . join ( outdir , 'starfeatures-%s.pkl' % squeeze ( resultdict [ 'objectid' ] ) . replace ( ' ' , '-' ) )
    with open ( outfile , 'wb' ) as outfd :
        pickle . dump ( resultdict , outfd , protocol = 4 )
    return outfile
except Exception as e :
    LOGEXCEPTION ( 'failed to get star features for %s because: %s' % ( os . path . basename ( lcfile ) , e ) )
    return None


signature:
def _starfeatures_worker ( task ) :
    '''This wraps starfeatures .'''

implementation:
try :
    ( lcfile , outdir , kdtree , objlist , lcflist , neighbor_radius_arcsec , deredden , custom_bandpasses , lcformat , lcformatdir ) = task
    return get_starfeatures ( lcfile , outdir , kdtree , objlist , lcflist , neighbor_radius_arcsec , deredden = deredden , custom_bandpasses = custom_bandpasses , lcformat = lcformat , lcformatdir = lcformatdir )
except Exception as e :
    return None


signature:
def serial_starfeatures ( lclist , outdir , lc_catalog_pickle , neighbor_radius_arcsec , maxobjects = None , deredden = True , custom_bandpasses = None , lcformat = 'hat-sql' , lcformatdir = None ) :
    '''This drives the ` get _ starfeatures ` function for a collection of LCs .
 Parameters
 lclist : list of str
 The list of light curve file names to process .
 outdir : str
 The output directory where the results will be placed .
 lc _ catalog _ pickle : str
 The path to a catalog containing at a dict with least :
 - an object ID array accessible with ` dict [ ' objects ' ] [ ' objectid ' ] `
 - an LC filename array accessible with ` dict [ ' objects ' ] [ ' lcfname ' ] `
 - a ` scipy . spatial . KDTree ` or ` cKDTree ` object to use for finding
 neighbors for each object accessible with ` dict [ ' kdtree ' ] `
 A catalog pickle of the form needed can be produced using
 : py : func : ` astrobase . lcproc . catalogs . make _ lclist ` or
 : py : func : ` astrobase . lcproc . catalogs . filter _ lclist ` .
 neighbor _ radius _ arcsec : float
 This indicates the radius in arcsec to search for neighbors for this
 object using the light curve catalog ' s ` kdtree ` , ` objlist ` , ` lcflist ` ,
 and in GAIA .
 maxobjects : int
 The number of objects to process from ` lclist ` .
 deredden : bool
 This controls if the colors and any color classifications will be
 dereddened using 2MASS DUST .
 custom _ bandpasses : dict or None
 This is a dict used to define any custom bandpasses in the
 ` in _ objectinfo ` dict you want to make this function aware of and
 generate colors for . Use the format below for this dict : :
 ' < bandpass _ key _ 1 > ' : { ' dustkey ' : ' < twomass _ dust _ key _ 1 > ' ,
 ' label ' : ' < band _ label _ 1 > '
 ' colors ' : [ [ ' < bandkey1 > - < bandkey2 > ' ,
 ' < BAND1 > - < BAND2 > ' ] ,
 [ ' < bandkey3 > - < bandkey4 > ' ,
 ' < BAND3 > - < BAND4 > ' ] ] } ,
 ' < bandpass _ key _ N > ' : { ' dustkey ' : ' < twomass _ dust _ key _ N > ' ,
 ' label ' : ' < band _ label _ N > '
 ' colors ' : [ [ ' < bandkey1 > - < bandkey2 > ' ,
 ' < BAND1 > - < BAND2 > ' ] ,
 [ ' < bandkey3 > - < bandkey4 > ' ,
 ' < BAND3 > - < BAND4 > ' ] ] } ,
 Where :
 ` bandpass _ key ` is a key to use to refer to this bandpass in the
 ` objectinfo ` dict , e . g . ' sdssg ' for SDSS g band
 ` twomass _ dust _ key ` is the key to use in the 2MASS DUST result table for
 reddening per band - pass . For example , given the following DUST result
 table ( using http : / / irsa . ipac . caltech . edu / applications / DUST / ) : :
 | Filter _ name | LamEff | A _ over _ E _ B _ V _ SandF | A _ SandF | A _ over _ E _ B _ V _ SFD | A _ SFD |
 | char | float | float | float | float | float |
 | | microns | | mags | | mags |
 CTIO U 0.3734 4.107 0.209 4.968 0.253
 CTIO B 0.4309 3.641 0.186 4.325 0.221
 CTIO V 0.5517 2.682 0.137 3.240 0.165
 The ` twomass _ dust _ key ` for ' vmag ' would be ' CTIO V ' . If you want to
 skip DUST lookup and want to pass in a specific reddening magnitude
 for your bandpass , use a float for the value of
 ` twomass _ dust _ key ` . If you want to skip DUST lookup entirely for
 this bandpass , use None for the value of ` twomass _ dust _ key ` .
 ` band _ label ` is the label to use for this bandpass , e . g . ' W1 ' for
 WISE - 1 band , ' u ' for SDSS u , etc .
 The ' colors ' list contains color definitions for all colors you want
 to generate using this bandpass . this list contains elements of the
 form : :
 [ ' < bandkey1 > - < bandkey2 > ' , ' < BAND1 > - < BAND2 > ' ]
 where the the first item is the bandpass keys making up this color ,
 and the second item is the label for this color to be used by the
 frontends . An example : :
 [ ' sdssu - sdssg ' , ' u - g ' ]
 lcformat : str
 This is the ` formatkey ` associated with your light curve format , which
 you previously passed in to the ` lcproc . register _ lcformat `
 function . This will be used to look up how to find and read the light
 curves specified in ` basedir ` or ` use _ list _ of _ filenames ` .
 lcformatdir : str or None
 If this is provided , gives the path to a directory when you ' ve stored
 your lcformat description JSONs , other than the usual directories lcproc
 knows to search for them in . Use this along with ` lcformat ` to specify
 an LC format JSON file that ' s not currently registered with lcproc .
 Returns
 list of str
 A list of all star features pickles produced .'''

implementation:
# make sure to make the output directory if it doesn ' t exist
if not os . path . exists ( outdir ) :
    os . makedirs ( outdir )
if maxobjects :
    lclist = lclist [ : maxobjects ]
# read in the kdtree pickle
with open ( lc_catalog_pickle , 'rb' ) as infd :
    kdt_dict = pickle . load ( infd )
kdt = kdt_dict [ 'kdtree' ]
objlist = kdt_dict [ 'objects' ] [ 'objectid' ]
objlcfl = kdt_dict [ 'objects' ] [ 'lcfname' ]
tasks = [ ( x , outdir , kdt , objlist , objlcfl , neighbor_radius_arcsec , deredden , custom_bandpasses , lcformat , lcformatdir ) for x in lclist ]
for task in tqdm ( tasks ) :
    result = _starfeatures_worker ( task )
return result


signature:
def parallel_starfeatures ( lclist , outdir , lc_catalog_pickle , neighbor_radius_arcsec , maxobjects = None , deredden = True , custom_bandpasses = None , lcformat = 'hat-sql' , lcformatdir = None , nworkers = NCPUS ) :
    '''This runs ` get _ starfeatures ` in parallel for all light curves in ` lclist ` .
 Parameters
 lclist : list of str
 The list of light curve file names to process .
 outdir : str
 The output directory where the results will be placed .
 lc _ catalog _ pickle : str
 The path to a catalog containing at a dict with least :
 - an object ID array accessible with ` dict [ ' objects ' ] [ ' objectid ' ] `
 - an LC filename array accessible with ` dict [ ' objects ' ] [ ' lcfname ' ] `
 - a ` scipy . spatial . KDTree ` or ` cKDTree ` object to use for finding
 neighbors for each object accessible with ` dict [ ' kdtree ' ] `
 A catalog pickle of the form needed can be produced using
 : py : func : ` astrobase . lcproc . catalogs . make _ lclist ` or
 : py : func : ` astrobase . lcproc . catalogs . filter _ lclist ` .
 neighbor _ radius _ arcsec : float
 This indicates the radius in arcsec to search for neighbors for this
 object using the light curve catalog ' s ` kdtree ` , ` objlist ` , ` lcflist ` ,
 and in GAIA .
 maxobjects : int
 The number of objects to process from ` lclist ` .
 deredden : bool
 This controls if the colors and any color classifications will be
 dereddened using 2MASS DUST .
 custom _ bandpasses : dict or None
 This is a dict used to define any custom bandpasses in the
 ` in _ objectinfo ` dict you want to make this function aware of and
 generate colors for . Use the format below for this dict : :
 ' < bandpass _ key _ 1 > ' : { ' dustkey ' : ' < twomass _ dust _ key _ 1 > ' ,
 ' label ' : ' < band _ label _ 1 > '
 ' colors ' : [ [ ' < bandkey1 > - < bandkey2 > ' ,
 ' < BAND1 > - < BAND2 > ' ] ,
 [ ' < bandkey3 > - < bandkey4 > ' ,
 ' < BAND3 > - < BAND4 > ' ] ] } ,
 ' < bandpass _ key _ N > ' : { ' dustkey ' : ' < twomass _ dust _ key _ N > ' ,
 ' label ' : ' < band _ label _ N > '
 ' colors ' : [ [ ' < bandkey1 > - < bandkey2 > ' ,
 ' < BAND1 > - < BAND2 > ' ] ,
 [ ' < bandkey3 > - < bandkey4 > ' ,
 ' < BAND3 > - < BAND4 > ' ] ] } ,
 Where :
 ` bandpass _ key ` is a key to use to refer to this bandpass in the
 ` objectinfo ` dict , e . g . ' sdssg ' for SDSS g band
 ` twomass _ dust _ key ` is the key to use in the 2MASS DUST result table for
 reddening per band - pass . For example , given the following DUST result
 table ( using http : / / irsa . ipac . caltech . edu / applications / DUST / ) : :
 | Filter _ name | LamEff | A _ over _ E _ B _ V _ SandF | A _ SandF | A _ over _ E _ B _ V _ SFD | A _ SFD |
 | char | float | float | float | float | float |
 | | microns | | mags | | mags |
 CTIO U 0.3734 4.107 0.209 4.968 0.253
 CTIO B 0.4309 3.641 0.186 4.325 0.221
 CTIO V 0.5517 2.682 0.137 3.240 0.165
 The ` twomass _ dust _ key ` for ' vmag ' would be ' CTIO V ' . If you want to
 skip DUST lookup and want to pass in a specific reddening magnitude
 for your bandpass , use a float for the value of
 ` twomass _ dust _ key ` . If you want to skip DUST lookup entirely for
 this bandpass , use None for the value of ` twomass _ dust _ key ` .
 ` band _ label ` is the label to use for this bandpass , e . g . ' W1 ' for
 WISE - 1 band , ' u ' for SDSS u , etc .
 The ' colors ' list contains color definitions for all colors you want
 to generate using this bandpass . this list contains elements of the
 form : :
 [ ' < bandkey1 > - < bandkey2 > ' , ' < BAND1 > - < BAND2 > ' ]
 where the the first item is the bandpass keys making up this color ,
 and the second item is the label for this color to be used by the
 frontends . An example : :
 [ ' sdssu - sdssg ' , ' u - g ' ]
 lcformat : str
 This is the ` formatkey ` associated with your light curve format , which
 you previously passed in to the ` lcproc . register _ lcformat `
 function . This will be used to look up how to find and read the light
 curves specified in ` basedir ` or ` use _ list _ of _ filenames ` .
 lcformatdir : str or None
 If this is provided , gives the path to a directory when you ' ve stored
 your lcformat description JSONs , other than the usual directories lcproc
 knows to search for them in . Use this along with ` lcformat ` to specify
 an LC format JSON file that ' s not currently registered with lcproc .
 nworkers : int
 The number of parallel workers to launch .
 Returns
 dict
 A dict with key : val pairs of the input light curve filename and the
 output star features pickle for each LC processed .'''

implementation:
try :
    formatinfo = get_lcformat ( lcformat , use_lcformat_dir = lcformatdir )
    if formatinfo :
        ( dfileglob , readerfunc , dtimecols , dmagcols , derrcols , magsarefluxes , normfunc ) = formatinfo
    else :
        LOGERROR ( "can't figure out the light curve format" )
        return None
except Exception as e :
    LOGEXCEPTION ( "can't figure out the light curve format" )
    return None
# make sure to make the output directory if it doesn ' t exist
if not os . path . exists ( outdir ) :
    os . makedirs ( outdir )
if maxobjects :
    lclist = lclist [ : maxobjects ]
# read in the kdtree pickle
with open ( lc_catalog_pickle , 'rb' ) as infd :
    kdt_dict = pickle . load ( infd )
kdt = kdt_dict [ 'kdtree' ]
objlist = kdt_dict [ 'objects' ] [ 'objectid' ]
objlcfl = kdt_dict [ 'objects' ] [ 'lcfname' ]
tasks = [ ( x , outdir , kdt , objlist , objlcfl , neighbor_radius_arcsec , deredden , custom_bandpasses , lcformat ) for x in lclist ]
with ProcessPoolExecutor ( max_workers = nworkers ) as executor :
    resultfutures = executor . map ( _starfeatures_worker , tasks )
results = [ x for x in resultfutures ]
resdict = { os . path . basename ( x ) : y for ( x , y ) in zip ( lclist , results ) }
return resdict


signature:
def parallel_starfeatures_lcdir ( lcdir , outdir , lc_catalog_pickle , neighbor_radius_arcsec , fileglob = None , maxobjects = None , deredden = True , custom_bandpasses = None , lcformat = 'hat-sql' , lcformatdir = None , nworkers = NCPUS , recursive = True ) :
    '''This runs parallel star feature extraction for a directory of LCs .
 Parameters
 lcdir : list of str
 The directory to search for light curves .
 outdir : str
 The output directory where the results will be placed .
 lc _ catalog _ pickle : str
 The path to a catalog containing at a dict with least :
 - an object ID array accessible with ` dict [ ' objects ' ] [ ' objectid ' ] `
 - an LC filename array accessible with ` dict [ ' objects ' ] [ ' lcfname ' ] `
 - a ` scipy . spatial . KDTree ` or ` cKDTree ` object to use for finding
 neighbors for each object accessible with ` dict [ ' kdtree ' ] `
 A catalog pickle of the form needed can be produced using
 : py : func : ` astrobase . lcproc . catalogs . make _ lclist ` or
 : py : func : ` astrobase . lcproc . catalogs . filter _ lclist ` .
 neighbor _ radius _ arcsec : float
 This indicates the radius in arcsec to search for neighbors for this
 object using the light curve catalog ' s ` kdtree ` , ` objlist ` , ` lcflist ` ,
 and in GAIA .
 fileglob : str
 The UNIX file glob to use to search for the light curves in ` lcdir ` . If
 None , the default value for the light curve format specified will be
 used .
 maxobjects : int
 The number of objects to process from ` lclist ` .
 deredden : bool
 This controls if the colors and any color classifications will be
 dereddened using 2MASS DUST .
 custom _ bandpasses : dict or None
 This is a dict used to define any custom bandpasses in the
 ` in _ objectinfo ` dict you want to make this function aware of and
 generate colors for . Use the format below for this dict : :
 ' < bandpass _ key _ 1 > ' : { ' dustkey ' : ' < twomass _ dust _ key _ 1 > ' ,
 ' label ' : ' < band _ label _ 1 > '
 ' colors ' : [ [ ' < bandkey1 > - < bandkey2 > ' ,
 ' < BAND1 > - < BAND2 > ' ] ,
 [ ' < bandkey3 > - < bandkey4 > ' ,
 ' < BAND3 > - < BAND4 > ' ] ] } ,
 ' < bandpass _ key _ N > ' : { ' dustkey ' : ' < twomass _ dust _ key _ N > ' ,
 ' label ' : ' < band _ label _ N > '
 ' colors ' : [ [ ' < bandkey1 > - < bandkey2 > ' ,
 ' < BAND1 > - < BAND2 > ' ] ,
 [ ' < bandkey3 > - < bandkey4 > ' ,
 ' < BAND3 > - < BAND4 > ' ] ] } ,
 Where :
 ` bandpass _ key ` is a key to use to refer to this bandpass in the
 ` objectinfo ` dict , e . g . ' sdssg ' for SDSS g band
 ` twomass _ dust _ key ` is the key to use in the 2MASS DUST result table for
 reddening per band - pass . For example , given the following DUST result
 table ( using http : / / irsa . ipac . caltech . edu / applications / DUST / ) : :
 | Filter _ name | LamEff | A _ over _ E _ B _ V _ SandF | A _ SandF | A _ over _ E _ B _ V _ SFD | A _ SFD |
 | char | float | float | float | float | float |
 | | microns | | mags | | mags |
 CTIO U 0.3734 4.107 0.209 4.968 0.253
 CTIO B 0.4309 3.641 0.186 4.325 0.221
 CTIO V 0.5517 2.682 0.137 3.240 0.165
 The ` twomass _ dust _ key ` for ' vmag ' would be ' CTIO V ' . If you want to
 skip DUST lookup and want to pass in a specific reddening magnitude
 for your bandpass , use a float for the value of
 ` twomass _ dust _ key ` . If you want to skip DUST lookup entirely for
 this bandpass , use None for the value of ` twomass _ dust _ key ` .
 ` band _ label ` is the label to use for this bandpass , e . g . ' W1 ' for
 WISE - 1 band , ' u ' for SDSS u , etc .
 The ' colors ' list contains color definitions for all colors you want
 to generate using this bandpass . this list contains elements of the
 form : :
 [ ' < bandkey1 > - < bandkey2 > ' , ' < BAND1 > - < BAND2 > ' ]
 where the the first item is the bandpass keys making up this color ,
 and the second item is the label for this color to be used by the
 frontends . An example : :
 [ ' sdssu - sdssg ' , ' u - g ' ]
 lcformat : str
 This is the ` formatkey ` associated with your light curve format , which
 you previously passed in to the ` lcproc . register _ lcformat `
 function . This will be used to look up how to find and read the light
 curves specified in ` basedir ` or ` use _ list _ of _ filenames ` .
 lcformatdir : str or None
 If this is provided , gives the path to a directory when you ' ve stored
 your lcformat description JSONs , other than the usual directories lcproc
 knows to search for them in . Use this along with ` lcformat ` to specify
 an LC format JSON file that ' s not currently registered with lcproc .
 nworkers : int
 The number of parallel workers to launch .
 Returns
 dict
 A dict with key : val pairs of the input light curve filename and the
 output star features pickle for each LC processed .'''

implementation:
try :
    formatinfo = get_lcformat ( lcformat , use_lcformat_dir = lcformatdir )
    if formatinfo :
        ( dfileglob , readerfunc , dtimecols , dmagcols , derrcols , magsarefluxes , normfunc ) = formatinfo
    else :
        LOGERROR ( "can't figure out the light curve format" )
        return None
except Exception as e :
    LOGEXCEPTION ( "can't figure out the light curve format" )
    return None
if not fileglob :
    fileglob = dfileglob
# now find the files
LOGINFO ( 'searching for %s light curves in %s ...' % ( lcformat , lcdir ) )
if recursive is False :
    matching = glob . glob ( os . path . join ( lcdir , fileglob ) )
else : # use recursive glob for Python 3.5 +
    if sys . version_info [ : 2 ] > ( 3 , 4 ) :
        matching = glob . glob ( os . path . join ( lcdir , '**' , fileglob ) , recursive = True )
    # otherwise , use os . walk and glob
    else : # use os . walk to go through the directories
        walker = os . walk ( lcdir )
        matching = [ ]
        for root , dirs , _files in walker :
            for sdir in dirs :
                searchpath = os . path . join ( root , sdir , fileglob )
                foundfiles = glob . glob ( searchpath )
                if foundfiles :
                    matching . extend ( foundfiles )
# now that we have all the files , process them
if matching and len ( matching ) > 0 :
    LOGINFO ( 'found %s light curves, getting starfeatures...' % len ( matching ) )
    return parallel_starfeatures ( matching , outdir , lc_catalog_pickle , neighbor_radius_arcsec , deredden = deredden , custom_bandpasses = custom_bandpasses , maxobjects = maxobjects , lcformat = lcformat , lcformatdir = lcformatdir , nworkers = nworkers )
else :
    LOGERROR ( 'no light curve files in %s format found in %s' % ( lcformat , lcdir ) )
    return None


signature:
def checkplot_dict ( lspinfolist , times , mags , errs , fast_mode = False , magsarefluxes = False , nperiodstouse = 3 , objectinfo = None , deredden_object = True , custom_bandpasses = None , gaia_submit_timeout = 10.0 , gaia_submit_tries = 3 , gaia_max_timeout = 180.0 , gaia_mirror = None , complete_query_later = True , varinfo = None , getvarfeatures = True , lclistpkl = None , nbrradiusarcsec = 60.0 , maxnumneighbors = 5 , xmatchinfo = None , xmatchradiusarcsec = 3.0 , lcfitfunc = None , lcfitparams = None , externalplots = None , findercmap = 'gray_r' , finderconvolve = None , findercachedir = '~/.astrobase/stamp-cache' , normto = 'globalmedian' , normmingap = 4.0 , sigclip = 4.0 , varepoch = 'min' , phasewrap = True , phasesort = True , phasebin = 0.002 , minbinelems = 7 , plotxlim = ( - 0.8 , 0.8 ) , xliminsetmode = False , plotdpi = 100 , bestperiodhighlight = None , xgridlines = None , mindet = 99 , verbose = True ) :
    '''This writes a multiple lspinfo checkplot to a dict .
 This function can take input from multiple lspinfo dicts ( e . g . a list of
 output dicts or gzipped pickles of dicts from independent runs of BLS , PDM ,
 AoV , or GLS period - finders in periodbase ) .
 NOTE : if ` lspinfolist ` contains more than one lspinfo object with the same
 lspmethod ( ' pdm ' , ' gls ' , ' sls ' , ' aov ' , ' bls ' ) , the latest one in the list will
 overwrite the earlier ones .
 The output dict contains all the plots ( magseries and phased magseries ) ,
 periodograms , object information , variability information , light curves , and
 phased light curves . This can be written to :
 - a pickle with ` checkplot _ pickle ` below
 - a PNG with ` checkplot . pkl _ png . checkplot _ pickle _ to _ png `
 Parameters
 lspinfolist : list of dicts
 This is a list of dicts containing period - finder results ( ' lspinfo '
 dicts ) . These can be from any of the period - finder methods in
 astrobase . periodbase . To incorporate external period - finder results into
 checkplots , these dicts must be of the form below , including at least
 the keys indicated here : :
 { ' periods ' : np . array of all periods searched by the period - finder ,
 ' lspvals ' : np . array of periodogram power value for each period ,
 ' bestperiod ' : a float value that is the period with the highest
 peak in the periodogram , i . e . the most - likely actual
 period ,
 ' method ' : a three - letter code naming the period - finder used ; must
 be one of the keys in the
 ` astrobase . periodbase . METHODLABELS ` dict ,
 ' nbestperiods ' : a list of the periods corresponding to periodogram
 peaks ( ` nbestlspvals ` below ) to annotate on the
 periodogram plot so they can be called out
 visually ,
 ' nbestlspvals ' : a list of the power values associated with
 periodogram peaks to annotate on the periodogram
 plot so they can be called out visually ; should be
 the same length as ` nbestperiods ` above }
 ` nbestperiods ` and ` nbestlspvals ` in each lspinfo dict must have at
 least as many elements as the ` nperiodstouse ` kwarg to this function .
 times , mags , errs : np . arrays
 The magnitude / flux time - series to process for this checkplot along with
 their associated measurement errors .
 fast _ mode : bool or float
 This runs the external catalog operations in a " fast " mode , with short
 timeouts and not trying to hit external catalogs that take a long time
 to respond .
 If this is set to True , the default settings for the external requests
 will then become : :
 skyview _ lookup = False
 skyview _ timeout = 10.0
 skyview _ retry _ failed = False
 dust _ timeout = 10.0
 gaia _ submit _ timeout = 7.0
 gaia _ max _ timeout = 10.0
 gaia _ submit _ tries = 2
 complete _ query _ later = False
 search _ simbad = False
 If this is a float , will run in " fast " mode with the provided timeout
 value in seconds and the following settings : :
 skyview _ lookup = True
 skyview _ timeout = fast _ mode
 skyview _ retry _ failed = False
 dust _ timeout = fast _ mode
 gaia _ submit _ timeout = 0.66 * fast _ mode
 gaia _ max _ timeout = fast _ mode
 gaia _ submit _ tries = 2
 complete _ query _ later = False
 search _ simbad = False
 magsarefluxes : bool
 If True , indicates the input time - series is fluxes and not mags so the
 plot y - axis direction and range can be set appropriately .
 nperiodstouse : int
 This controls how many ' best ' periods to make phased LC plots for . By
 default , this is the 3 best . If this is set to None , all ' best ' periods
 present in each lspinfo dict ' s ' nbestperiods ' key will be processed for
 this checkplot .
 objectinfo : dict or None
 This is a dict containing information on the object whose light
 curve is being processed . This function will then be able to
 look up and download a finder chart for this object and write
 that to the output checkplotdict . External services such as
 GAIA , SIMBAD , TIC , etc . will also be used to look up this object
 by its coordinates , and will add in information available from
 those services .
 This dict must be of the form and contain at least the keys described
 below : :
 { ' objectid ' : the name of the object ,
 ' ra ' : the right ascension of the object in decimal degrees ,
 ' decl ' : the declination of the object in decimal degrees ,
 ' ndet ' : the number of observations of this object }
 You can also provide magnitudes and proper motions of the object using
 the following keys and the appropriate values in the ` objectinfo `
 dict . These will be used to calculate colors , total and reduced proper
 motion , etc . and display these in the output checkplot PNG : :
 ' pmra ' - > the proper motion in mas / yr in right ascension ,
 ' pmdecl ' - > the proper motion in mas / yr in declination ,
 ' umag ' - > U mag - > colors : U - B , U - V , U - g
 ' bmag ' - > B mag - > colors : U - B , B - V
 ' vmag ' - > V mag - > colors : U - V , B - V , V - R , V - I , V - K
 ' rmag ' - > R mag - > colors : V - R , R - I
 ' imag ' - > I mag - > colors : g - I , V - I , R - I , B - I
 ' jmag ' - > 2MASS J mag - > colors : J - H , J - K , g - J , i - J
 ' hmag ' - > 2MASS H mag - > colors : J - H , H - K
 ' kmag ' - > 2MASS Ks mag - > colors : g - Ks , H - Ks , J - Ks , V - Ks
 ' sdssu ' - > SDSS u mag - > colors : u - g , u - V
 ' sdssg ' - > SDSS g mag - > colors : g - r , g - i , g - K , u - g , U - g , g - J
 ' sdssr ' - > SDSS r mag - > colors : r - i , g - r
 ' sdssi ' - > SDSS i mag - > colors : r - i , i - z , g - i , i - J , i - W1
 ' sdssz ' - > SDSS z mag - > colors : i - z , z - W2 , g - z
 ' ujmag ' - > UKIRT J mag - > colors : J - H , H - K , J - K , g - J , i - J
 ' uhmag ' - > UKIRT H mag - > colors : J - H , H - K
 ' ukmag ' - > UKIRT K mag - > colors : g - K , H - K , J - K , V - K
 ' irac1 ' - > Spitzer IRAC1 mag - > colors : i - I1 , I1 - I2
 ' irac2 ' - > Spitzer IRAC2 mag - > colors : I1 - I2 , I2 - I3
 ' irac3 ' - > Spitzer IRAC3 mag - > colors : I2 - I3
 ' irac4 ' - > Spitzer IRAC4 mag - > colors : I3 - I4
 ' wise1 ' - > WISE W1 mag - > colors : i - W1 , W1 - W2
 ' wise2 ' - > WISE W2 mag - > colors : W1 - W2 , W2 - W3
 ' wise3 ' - > WISE W3 mag - > colors : W2 - W3
 ' wise4 ' - > WISE W4 mag - > colors : W3 - W4
 If you have magnitude measurements in other bands , use the
 ` custom _ bandpasses ` kwarg to pass these in .
 If this is None , no object information will be incorporated into the
 checkplot ( kind of making it effectively useless for anything other than
 glancing at the phased light curves at various ' best ' periods from the
 period - finder results ) .
 deredden _ object : bool
 If this is True , will use the 2MASS DUST service to get extinction
 coefficients in various bands , and then try to deredden the magnitudes
 and colors of the object already present in the checkplot ' s objectinfo
 dict .
 custom _ bandpasses : dict
 This is a dict used to provide custom bandpass definitions for any
 magnitude measurements in the objectinfo dict that are not automatically
 recognized by : py : func : ` astrobase . varclass . starfeatures . color _ features ` .
 gaia _ submit _ timeout : float
 Sets the timeout in seconds to use when submitting a request to look up
 the object ' s information to the GAIA service . Note that if ` fast _ mode `
 is set , this is ignored .
 gaia _ submit _ tries : int
 Sets the maximum number of times the GAIA services will be contacted to
 obtain this object ' s information . If ` fast _ mode ` is set , this is
 ignored , and the services will be contacted only once ( meaning that a
 failure to respond will be silently ignored and no GAIA data will be
 added to the checkplot ' s objectinfo dict ) .
 gaia _ max _ timeout : float
 Sets the timeout in seconds to use when waiting for the GAIA service to
 respond to our request for the object ' s information . Note that if
 ` fast _ mode ` is set , this is ignored .
 gaia _ mirror : str or None
 This sets the GAIA mirror to use . This is a key in the
 ` services . gaia . GAIA _ URLS ` dict which defines the URLs to hit for each
 mirror .
 complete _ query _ later : bool
 If this is True , saves the state of GAIA queries that are not yet
 complete when ` gaia _ max _ timeout ` is reached while waiting for the GAIA
 service to respond to our request . A later call for GAIA info on the
 same object will attempt to pick up the results from the existing query
 if it ' s completed . If ` fast _ mode ` is True , this is ignored .
 varinfo : dict
 If this is None , a blank dict of the form below will be added to the
 checkplotdict : :
 { ' objectisvar ' : None - > variability flag ( None indicates unset ) ,
 ' vartags ' : CSV str containing variability type tags from review ,
 ' varisperiodic ' : None - > periodic variability flag ( None - > unset ) ,
 ' varperiod ' : the period associated with the periodic variability ,
 ' varepoch ' : the epoch associated with the periodic variability }
 If you provide a dict matching this format in this kwarg , this will be
 passed unchanged to the output checkplotdict produced .
 getvarfeatures : bool
 If this is True , several light curve variability features for this
 object will be calculated and added to the output checkpotdict as
 checkplotdict [ ' varinfo ' ] [ ' features ' ] . This uses the function
 ` varclass . varfeatures . all _ nonperiodic _ features ` so see its docstring for
 the measures that are calculated ( e . g . Stetson J indices , dispersion
 measures , etc . )
 lclistpkl : dict or str
 If this is provided , must be a dict resulting from reading a catalog
 produced by the ` lcproc . catalogs . make _ lclist ` function or a str path
 pointing to the pickle file produced by that function . This catalog is
 used to find neighbors of the current object in the current light curve
 collection . Looking at neighbors of the object within the radius
 specified by ` nbrradiusarcsec ` is useful for light curves produced by
 instruments that have a large pixel scale , so are susceptible to
 blending of variability and potential confusion of neighbor variability
 with that of the actual object being looked at . If this is None , no
 neighbor lookups will be performed .
 nbrradiusarcsec : flaot
 The radius in arcseconds to use for a search conducted around the
 coordinates of this object to look for any potential confusion and
 blending of variability amplitude caused by their proximity .
 maxnumneighbors : int
 The maximum number of neighbors that will have their light curves and
 magnitudes noted in this checkplot as potential blends with the target
 object .
 xmatchinfo : str or dict
 This is either the xmatch dict produced by the function
 ` load _ xmatch _ external _ catalogs ` above , or the path to the xmatch info
 pickle file produced by that function .
 xmatchradiusarcsec : float
 This is the cross - matching radius to use in arcseconds .
 lcfitfunc : Python function or None
 If provided , this should be a Python function that is used to fit a
 model to the light curve . This fit is then overplotted for each phased
 light curve in the checkplot . This function should have the following
 signature :
 ` def lcfitfunc ( times , mags , errs , period , * * lcfitparams ) `
 where ` lcfitparams ` encapsulates all external parameters ( i . e . number of
 knots for a spline function , the degree of a Legendre polynomial fit ,
 etc . , planet transit parameters ) This function should return a Python
 dict with the following structure ( similar to the functions in
 ` astrobase . lcfit ` ) and at least the keys below : :
 { ' fittype ' : < str : name of fit method > ,
 ' fitchisq ' : < float : the chi - squared value of the fit > ,
 ' fitredchisq ' : < float : the reduced chi - squared value of the fit > ,
 ' fitinfo ' : { ' fitmags ' : < ndarray : model mags / fluxes from fit func > } ,
 ' magseries ' : { ' times ' : < ndarray : times where fitmags are evaluated > } }
 Additional keys in the dict returned from this function can include
 ` fitdict [ ' fitinfo ' ] [ ' finalparams ' ] ` for the final model fit parameters
 ( this will be used by the checkplotserver if present ) ,
 ` fitdict [ ' fitinfo ' ] [ ' fitepoch ' ] ` for the minimum light epoch returned by
 the model fit , among others .
 In any case , the output dict of ` lcfitfunc ` will be copied to the output
 checkplotdict as : :
 checkplotdict [ lspmethod ] [ periodind ] [ ' lcfit ' ] [ < fittype > ]
 for each phased light curve .
 lcfitparams : dict
 A dict containing the LC fit parameters to use when calling the function
 provided in ` lcfitfunc ` . This contains key - val pairs corresponding to
 parameter names and their respective initial values to be used by the
 fit function .
 externalplots : list of tuples of str
 If provided , this is a list of 4 - element tuples containing :
 1 . path to PNG of periodogram from an external period - finding method
 2 . path to PNG of best period phased LC from the external period - finder
 3 . path to PNG of 2nd - best phased LC from the external period - finder
 4 . path to PNG of 3rd - best phased LC from the external period - finder
 This can be used to incorporate external period - finding method results
 into the output checkplot pickle or exported PNG to allow for comparison
 with astrobase results .
 Example of externalplots : :
 [ ( ' / path / to / external / bls - periodogram . png ' ,
 ' / path / to / external / bls - phasedlc - plot - bestpeak . png ' ,
 ' / path / to / external / bls - phasedlc - plot - peak2 . png ' ,
 ' / path / to / external / bls - phasedlc - plot - peak3 . png ' ) ,
 ( ' / path / to / external / pdm - periodogram . png ' ,
 ' / path / to / external / pdm - phasedlc - plot - bestpeak . png ' ,
 ' / path / to / external / pdm - phasedlc - plot - peak2 . png ' ,
 ' / path / to / external / pdm - phasedlc - plot - peak3 . png ' ) ,
 If ` externalplots ` is provided here , these paths will be stored in the
 output checkplotdict . The ` checkplot . pkl _ png . checkplot _ pickle _ to _ png `
 function can then automatically retrieve these plot PNGs and put
 them into the exported checkplot PNG .
 findercmap : str or matplotlib . cm . ColorMap object
 The Colormap object to use for the finder chart image .
 finderconvolve : astropy . convolution . Kernel object or None
 If not None , the Kernel object to use for convolving the finder image .
 findercachedir : str
 The path to the astrobase cache directory for finder chart downloads
 from the NASA SkyView service .
 normto : { ' globalmedian ' , ' zero ' } or a float
 These are specified as below :
 - ' globalmedian ' - > norms each mag to the global median of the LC column
 - ' zero ' - > norms each mag to zero
 - a float - > norms each mag to this specified float value .
 normmingap : float
 This defines how much the difference between consecutive measurements is
 allowed to be to consider them as parts of different timegroups . By
 default it is set to 4.0 days .
 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 .
 varepoch : ' min ' or float or list of lists or None
 The epoch to use for this phased light curve plot tile . If this is a
 float , will use the provided value directly . If this is ' min ' , will
 automatically figure out the time - of - minimum of the phased light
 curve . If this is None , will use the mimimum value of ` stimes ` as the
 epoch of the phased light curve plot . If this is a list of lists , will
 use the provided value of ` lspmethodind ` to look up the current
 period - finder method and the provided value of ` periodind ` to look up
 the epoch associated with that method and the current period . This is
 mostly only useful when ` twolspmode ` is True .
 phasewrap : bool
 If this is True , the phased time - series will be wrapped around
 phase 0.0.
 phasesort : bool
 If True , will sort the phased light curve in order of increasing phase .
 phasebin : float
 The bin size to use to group together measurements closer than this
 amount in phase . This is in units of phase . If this is a float , a
 phase - binned version of the phased light curve will be overplotted on
 top of the regular phased light curve .
 minbinelems : int
 The minimum number of elements required per phase bin to include it in
 the phased LC plot .
 plotxlim : sequence of two floats or None
 The x - range ( min , max ) of the phased light curve plot . If None , will be
 determined automatically .
 xliminsetmode : bool
 If this is True , the generated phased light curve plot will use the
 values of ` plotxlim ` as the main plot x - axis limits ( i . e . zoomed - in if
 ` plotxlim ` is a range smaller than the full phase range ) , and will show
 the full phased light curve plot as an smaller inset . Useful for
 planetary transit light curves .
 plotdpi : int
 The resolution of the output plot PNGs in dots per inch .
 bestperiodhighlight : str or None
 If not None , this is a str with a matplotlib color specification to use
 as the background color to highlight the phased light curve plot of the
 ' best ' period and epoch combination . If None , no highlight will be
 applied .
 xgridlines : list of floats or None
 If this is provided , must be a list of floats corresponding to the phase
 values where to draw vertical dashed lines as a means of highlighting
 these .
 mindet : int
 The minimum of observations the input object ' s mag / flux time - series must
 have for this function to plot its light curve and phased light
 curve . If the object has less than this number , no light curves will be
 plotted , but the checkplotdict will still contain all of the other
 information .
 verbose : bool
 If True , will indicate progress and warn about problems .
 Returns
 dict
 Returns a checkplotdict .'''

implementation:
# if an objectinfo dict is absent , we ' ll generate a fake objectid based on
# the second five time and mag array values . this should be OK to ID the
# object across repeated runs of this function with the same times , mags ,
# errs , but should provide enough uniqueness otherwise ( across different
# times / mags array inputs ) . this is all done so we can still save checkplots
# correctly to pickles after reviewing them using checkplotserver
try :
    objuuid = hashlib . sha512 ( times [ 5 : 10 ] . tostring ( ) + mags [ 5 : 10 ] . tostring ( ) ) . hexdigest ( ) [ : 5 ]
except Exception as e :
    if verbose :
        LOGWARNING ( 'times, mags, and errs may have too few items' )
        objuuid = hashlib . sha512 ( times . tostring ( ) + mags . tostring ( ) ) . hexdigest ( ) [ : 5 ]
if ( objectinfo is None ) :
    if verbose :
        LOGWARNING ( 'no objectinfo dict provided as kwarg, ' 'adding a randomly generated objectid' )
    objectinfo = { 'objectid' : objuuid }
# special for HAT stuff , eventually we should add objectid to
# lcd [ ' objectinfo ' ] there as well
elif ( isinstance ( objectinfo , dict ) and 'hatid' in objectinfo ) :
    objectinfo [ 'objectid' ] = objectinfo [ 'hatid' ]
elif ( ( isinstance ( objectinfo , dict ) and 'objectid' not in objectinfo ) or ( isinstance ( objectinfo , dict ) and 'objectid' in objectinfo and ( objectinfo [ 'objectid' ] is None or objectinfo [ 'objectid' ] == '' ) ) ) :
    if verbose :
        LOGWARNING ( 'adding a randomly generated objectid ' 'since none was provided in objectinfo dict' )
    objectinfo [ 'objectid' ] = objuuid
# 0 . get the objectinfo and finder chart and initialize the checkplotdict
checkplotdict = _pkl_finder_objectinfo ( objectinfo , varinfo , findercmap , finderconvolve , sigclip , normto , normmingap , deredden_object = deredden_object , custom_bandpasses = custom_bandpasses , lclistpkl = lclistpkl , nbrradiusarcsec = nbrradiusarcsec , maxnumneighbors = maxnumneighbors , plotdpi = plotdpi , verbose = verbose , findercachedir = findercachedir , gaia_submit_timeout = gaia_submit_timeout , gaia_submit_tries = gaia_submit_tries , gaia_max_timeout = gaia_max_timeout , gaia_mirror = gaia_mirror , complete_query_later = complete_query_later , fast_mode = fast_mode )
# try again to get the right objectid
if ( objectinfo and isinstance ( objectinfo , dict ) and 'objectid' in objectinfo and objectinfo [ 'objectid' ] ) :
    checkplotdict [ 'objectid' ] = objectinfo [ 'objectid' ]
# filter the input times , mags , errs ; do sigclipping and normalization
stimes , smags , serrs = sigclip_magseries ( times , mags , errs , magsarefluxes = magsarefluxes , sigclip = sigclip )
# fail early if not enough light curve points
if ( ( stimes is None ) or ( smags is None ) or ( serrs is None ) or ( stimes . size < 49 ) or ( smags . size < 49 ) or ( serrs . size < 49 ) ) :
    LOGERROR ( "one or more of times, mags, errs appear to be None " "after sig-clipping. are the measurements all nan? " "can't make a checkplot for this objectid: %s" % checkplotdict [ 'objectid' ] )
    checkplotdict [ 'magseries' ] = None
    checkplotdict [ 'status' ] = 'failed: LC points appear to be all nan'
    return checkplotdict
# this may fix some unpickling issues for astropy . table . Column objects
# we convert them back to ndarrays
if isinstance ( stimes , AstColumn ) :
    stimes = stimes . data
    LOGWARNING ( 'times is an astropy.table.Column object, ' 'changing to numpy array because of ' 'potential unpickling issues' )
if isinstance ( smags , AstColumn ) :
    smags = smags . data
    LOGWARNING ( 'mags is an astropy.table.Column object, ' 'changing to numpy array because of ' 'potential unpickling issues' )
if isinstance ( serrs , AstColumn ) :
    serrs = serrs . data
    LOGWARNING ( 'errs is an astropy.table.Column object, ' 'changing to numpy array because of ' 'potential unpickling issues' )
# report on how sigclip went
if verbose :
    LOGINFO ( 'sigclip = %s: before = %s observations, ' 'after = %s observations' % ( sigclip , len ( times ) , len ( stimes ) ) )
# take care of the normalization
if normto is not False :
    stimes , smags = normalize_magseries ( stimes , smags , normto = normto , magsarefluxes = magsarefluxes , mingap = normmingap )
# make sure we have some lightcurve points to plot after sigclip
if len ( stimes ) > mindet : # 1 . get the mag series plot using these filtered stimes , smags , serrs
    magseriesdict = _pkl_magseries_plot ( stimes , smags , serrs , plotdpi = plotdpi , magsarefluxes = magsarefluxes )
    # update the checkplotdict
    checkplotdict . update ( magseriesdict )
    # 2 . for each lspinfo in lspinfolist , read it in ( from pkl or pkl . gz
    # if necessary ) , make the periodogram , make the phased mag series plots
    # for each of the nbestperiods in each lspinfo dict
    checkplot_pfmethods = [ ]
    for lspind , lspinfo in enumerate ( lspinfolist ) : # get the LSP from a pickle file transparently
        if isinstance ( lspinfo , str ) and os . path . exists ( lspinfo ) :
            LOGINFO ( 'loading LSP info from pickle %s' % lspinfo )
            if '.gz' in lspinfo :
                with gzip . open ( lspinfo , 'rb' ) as infd :
                    lspinfo = pickle . load ( infd )
            else :
                with open ( lspinfo , 'rb' ) as infd :
                    lspinfo = pickle . load ( infd )
        # make the periodogram first
        # we ' ll prepend the lspmethod index to allow for multiple same
        # lspmethods
        override_pfmethod = '%s-%s' % ( lspind , lspinfo [ 'method' ] )
        periodogramdict = _pkl_periodogram ( lspinfo , plotdpi = plotdpi , override_pfmethod = override_pfmethod )
        # update the checkplotdict .
        checkplotdict . update ( periodogramdict )
        # now , make the phased light curve plots for each of the
        # nbestperiods from this periodogram
        for nbpind , nbperiod in enumerate ( lspinfo [ 'nbestperiods' ] [ : nperiodstouse ] ) : # if there ' s a function to use for fitting , do the fit
            if lcfitfunc :
                try :
                    if lcfitparams is None :
                        lcfitparams = { }
                    overplotfit = lcfitfunc ( stimes , smags , serrs , nbperiod , ** lcfitparams )
                except Exception as e :
                    LOGEXCEPTION ( 'the light curve fitting function ' 'failed, not plotting a fit over the ' 'phased light curve' )
                    overplotfit = None
            else :
                overplotfit = None
            # get the varepoch from a run of bls _ snr if available . this
            # allows us to use the correct transit center epochs if
            # calculated using bls _ snr and added back to the kbls function
            # result dicts
            if ( lspinfo is not None and 'bls' in lspinfo [ 'method' ] and 'epochs' in lspinfo ) :
                thisvarepoch = lspinfo [ 'epochs' ] [ nbpind ]
                if verbose :
                    LOGINFO ( 'using pre-calculated transit-center epoch value: ' '%.6f from kbls.bls_snr() for period: %.5f' % ( thisvarepoch , nbperiod ) )
            else :
                thisvarepoch = varepoch
            # this updates things as it runs
            checkplotdict = _pkl_phased_magseries_plot ( checkplotdict , lspinfo [ 'method' ] , nbpind , stimes , smags , serrs , nbperiod , thisvarepoch , lspmethodind = lspind , phasewrap = phasewrap , phasesort = phasesort , phasebin = phasebin , minbinelems = minbinelems , plotxlim = plotxlim , overplotfit = overplotfit , plotdpi = plotdpi , bestperiodhighlight = bestperiodhighlight , magsarefluxes = magsarefluxes , xliminsetmode = xliminsetmode , xgridlines = xgridlines , verbose = verbose , override_pfmethod = override_pfmethod , )
        # if there ' s an snr key for this lspmethod , add the info in it to
        # the checkplotdict as well
        if 'snr' in lspinfo :
            if override_pfmethod in checkplotdict :
                checkplotdict [ override_pfmethod ] [ 'snr' ] = ( lspinfo [ 'snr' ] )
        if 'transitdepth' in lspinfo :
            if override_pfmethod in checkplotdict :
                checkplotdict [ override_pfmethod ] [ 'transitdepth' ] = ( lspinfo [ 'transitdepth' ] )
        if 'transitduration' in lspinfo :
            if override_pfmethod in checkplotdict :
                checkplotdict [ override_pfmethod ] [ 'transitduration' ] = ( lspinfo [ 'transitduration' ] )
        checkplot_pfmethods . append ( override_pfmethod )
    # end of processing each pfmethod
    # # update the checkplot dict with some other stuff that ' s needed by
    # # checkplotserver
    # 3 . add a comments key : val
    checkplotdict [ 'comments' ] = None
    # 4 . calculate some variability features
    if getvarfeatures is True :
        checkplotdict [ 'varinfo' ] [ 'features' ] = all_nonperiodic_features ( stimes , smags , serrs , magsarefluxes = magsarefluxes , )
    # 5 . add a signals key : val . this will be used by checkplotserver ' s
    # pre - whitening and masking functions . these will write to
    # checkplotdict [ ' signals ' ] [ ' whiten ' ] and
    # checkplotdict [ ' signals ' ] [ ' mask ' ] respectively .
    checkplotdict [ 'signals' ] = { }
    # 6 . add any externalplots if we have them
    checkplotdict [ 'externalplots' ] = [ ]
    if ( externalplots and isinstance ( externalplots , list ) and len ( externalplots ) > 0 ) :
        for externalrow in externalplots :
            if all ( os . path . exists ( erowfile ) for erowfile in externalrow ) :
                if verbose :
                    LOGINFO ( 'adding external plots: %s to checkplot dict' % repr ( externalrow ) )
                checkplotdict [ 'externalplots' ] . append ( externalrow )
            else :
                LOGWARNING ( 'could not add some external ' 'plots in: %s to checkplot dict' % repr ( externalrow ) )
    # 7 . do any xmatches required
    if xmatchinfo is not None :
        checkplotdict = xmatch_external_catalogs ( checkplotdict , xmatchinfo , xmatchradiusarcsec = xmatchradiusarcsec )
    # the checkplotdict now contains everything we need
    contents = sorted ( list ( checkplotdict . keys ( ) ) )
    checkplotdict [ 'status' ] = 'ok: contents are %s' % contents
    if verbose :
        LOGINFO ( 'checkplot dict complete for %s' % checkplotdict [ 'objectid' ] )
        LOGINFO ( 'checkplot dict contents: %s' % contents )
    # 8 . update the pfmethods key
    checkplotdict [ 'pfmethods' ] = checkplot_pfmethods
# otherwise , we don ' t have enough LC points , return nothing
else :
    LOGERROR ( 'not enough light curve points for %s, have %s, need %s' % ( checkplotdict [ 'objectid' ] , len ( stimes ) , mindet ) )
    checkplotdict [ 'magseries' ] = None
    checkplotdict [ 'status' ] = 'failed: not enough LC points'
# at the end , return the dict
return checkplotdict