signature:
def parallel_cp_pfdir ( pfpickledir , outdir , lcbasedir , pfpickleglob = 'periodfinding-*.pkl*' , lclistpkl = None , cprenorm = False , nbrradiusarcsec = 60.0 , maxnumneighbors = 5 , makeneighborlcs = True , fast_mode = False , gaia_max_timeout = 60.0 , gaia_mirror = None , xmatchinfo = None , xmatchradiusarcsec = 3.0 , minobservations = 99 , sigclip = 10.0 , lcformat = 'hat-sql' , lcformatdir = None , timecols = None , magcols = None , errcols = None , skipdone = False , done_callback = None , done_callback_args = None , done_callback_kwargs = None , maxobjects = None , nworkers = 32 ) :
    '''This drives the parallel execution of ` runcp ` for a directory of
 periodfinding pickles .
 Parameters
 pfpickledir : str
 This is the directory containing all of the period - finding pickles to
 process .
 outdir : str
 The directory the checkplot pickles will be written to .
 lcbasedir : str
 The base directory that this function will look in to find the light
 curves pointed to by the period - finding result files . If you ' re using
 ` lcfnamelist ` to provide a list of light curve filenames directly , this
 arg is ignored .
 pkpickleglob : str
 This is a UNIX file glob to select period - finding result pickles in the
 specified ` pfpickledir ` .
 lclistpkl : str or dict
 This is either the filename of a pickle or the actual dict produced by
 lcproc . make _ lclist . This is used to gather neighbor information .
 cprenorm : bool
 Set this to True if the light curves should be renormalized by
 ` checkplot . checkplot _ pickle ` . This is set to False by default because we
 do our own normalization in this function using the light curve ' s
 registered normalization function and pass the normalized times , mags ,
 errs to the ` checkplot . checkplot _ pickle ` function .
 nbrradiusarcsec : float
 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 .
 makeneighborlcs : bool
 If True , will make light curve and phased light curve plots for all
 neighbors found in the object collection for each input object .
 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
 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 .
 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 .
 minobservations : 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 .
 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 .
 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 .
 timecols : list of str or None
 The timecol keys to use from the lcdict in generating this checkplot .
 magcols : list of str or None
 The magcol keys to use from the lcdict in generating this checkplot .
 errcols : list of str or None
 The errcol keys to use from the lcdict in generating this checkplot .
 skipdone : bool
 This indicates if this function will skip creating checkplots that
 already exist corresponding to the current ` objectid ` and ` magcol ` . If
 ` skipdone ` is set to True , this will be done .
 done _ callback : Python function or None
 This is used to provide a function to execute after the checkplot
 pickles are generated . This is useful if you want to stream the results
 of checkplot making to some other process , e . g . directly running an
 ingestion into an LCC - Server collection . The function will always get
 the list of the generated checkplot pickles as its first arg , and all of
 the kwargs for runcp in the kwargs dict . Additional args and kwargs can
 be provided by giving a list in the ` done _ callbacks _ args ` kwarg and a
 dict in the ` done _ callbacks _ kwargs ` kwarg .
 NOTE : the function you pass in here should be pickleable by normal
 Python if you want to use it with the parallel _ cp and parallel _ cp _ lcdir
 functions below .
 done _ callback _ args : tuple or None
 If not None , contains any args to pass into the ` done _ callback `
 function .
 done _ callback _ kwargs : dict or None
 If not None , contains any kwargs to pass into the ` done _ callback `
 function .
 maxobjects : int
 The maximum number of objects to process in this run .
 nworkers : int
 The number of parallel workers that will work on the checkplot
 generation process .
 Returns
 dict
 This returns a dict with keys = input period - finding pickles and vals =
 list of the corresponding checkplot pickles produced .'''

implementation:
pfpicklelist = sorted ( glob . glob ( os . path . join ( pfpickledir , pfpickleglob ) ) )
LOGINFO ( 'found %s period-finding pickles, running cp...' % len ( pfpicklelist ) )
return parallel_cp ( pfpicklelist , outdir , lcbasedir , fast_mode = fast_mode , lclistpkl = lclistpkl , nbrradiusarcsec = nbrradiusarcsec , gaia_max_timeout = gaia_max_timeout , gaia_mirror = gaia_mirror , maxnumneighbors = maxnumneighbors , makeneighborlcs = makeneighborlcs , xmatchinfo = xmatchinfo , xmatchradiusarcsec = xmatchradiusarcsec , sigclip = sigclip , minobservations = minobservations , cprenorm = cprenorm , maxobjects = maxobjects , lcformat = lcformat , lcformatdir = lcformatdir , timecols = timecols , magcols = magcols , errcols = errcols , skipdone = skipdone , nworkers = nworkers , done_callback = done_callback , done_callback_args = done_callback_args , done_callback_kwargs = done_callback_kwargs )


signature:
def runpf ( lcfile , outdir , timecols = None , magcols = None , errcols = None , lcformat = 'hat-sql' , lcformatdir = None , pfmethods = ( 'gls' , 'pdm' , 'mav' , 'win' ) , pfkwargs = ( { } , { } , { } , { } ) , sigclip = 10.0 , getblssnr = False , nworkers = NCPUS , minobservations = 500 , excludeprocessed = False , raiseonfail = False ) :
    '''This runs the period - finding for a single LC .
 Parameters
 lcfile : str
 The light curve file to run period - finding on .
 outdir : str
 The output directory where the result pickle will go .
 timecols : list of str or None
 The timecol keys to use from the lcdict in calculating the features .
 magcols : list of str or None
 The magcol keys to use from the lcdict in calculating the features .
 errcols : list of str or None
 The errcol keys to use from the lcdict in calculating the features .
 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 .
 pfmethods : list of str
 This is a list of period finding methods to run . Each element is a
 string matching the keys of the ` PFMETHODS ` dict above . By default , this
 runs GLS , PDM , AoVMH , and the spectral window Lomb - Scargle periodogram .
 pfkwargs : list of dicts
 This is used to provide any special kwargs as dicts to each
 period - finding method function specified in ` pfmethods ` .
 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 .
 getblssnr : bool
 If this is True and BLS is one of the methods specified in ` pfmethods ` ,
 will also calculate the stats for each best period in the BLS results :
 transit depth , duration , ingress duration , refit period and epoch , and
 the SNR of the transit .
 nworkers : int
 The number of parallel period - finding workers to launch .
 minobservations : int
 The minimum number of finite LC points required to process a light
 curve .
 excludeprocessed : bool
 If this is True , light curves that have existing period - finding result
 pickles in ` outdir ` will not be processed .
 FIXME : currently , this uses a dumb method of excluding already - processed
 files . A smarter way to do this is to ( i ) generate a SHA512 cachekey
 based on a repr of ` { ' lcfile ' , ' timecols ' , ' magcols ' , ' errcols ' ,
 ' lcformat ' , ' pfmethods ' , ' sigclip ' , ' getblssnr ' , ' pfkwargs ' } ` , ( ii ) make
 sure all list kwargs in the dict are sorted , ( iii ) check if the output
 file has the same cachekey in its filename ( last 8 chars of cachekey
 should work ) , so the result was processed in exactly the same way as
 specifed in the input to this function , and can therefore be
 ignored . Will implement this later .
 raiseonfail : bool
 If something fails and this is True , will raise an Exception instead of
 returning None at the end .
 Returns
 str
 The path to the output period - finding result pickle .'''

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
# override the default timecols , magcols , and errcols
# using the ones provided to the function
if timecols is None :
    timecols = dtimecols
if magcols is None :
    magcols = dmagcols
if errcols is None :
    errcols = derrcols
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 ]
    outfile = os . path . join ( outdir , 'periodfinding-%s.pkl' % squeeze ( lcdict [ 'objectid' ] ) . replace ( ' ' , '-' ) )
    # if excludeprocessed is True , return the output file if it exists and
    # has a size that is at least 100 kilobytes ( this should be enough to
    # contain the minimal results of this function ) .
    if excludeprocessed :
        test_outfile = os . path . exists ( outfile )
        test_outfile_gz = os . path . exists ( outfile + '.gz' )
        if ( test_outfile and os . stat ( outfile ) . st_size > 102400 ) :
            LOGWARNING ( 'periodfinding result for %s already exists at %s, ' 'skipping because excludeprocessed=True' % ( lcfile , outfile ) )
            return outfile
        elif ( test_outfile_gz and os . stat ( outfile + '.gz' ) . st_size > 102400 ) :
            LOGWARNING ( 'gzipped periodfinding result for %s already ' 'exists at %s, skipping because excludeprocessed=True' % ( lcfile , outfile + '.gz' ) )
            return outfile + '.gz'
    # this is the final returndict
    resultdict = { 'objectid' : lcdict [ 'objectid' ] , 'lcfbasename' : os . path . basename ( lcfile ) , 'kwargs' : { 'timecols' : timecols , 'magcols' : magcols , 'errcols' : errcols , 'lcformat' : lcformat , 'lcformatdir' : lcformatdir , 'pfmethods' : pfmethods , 'pfkwargs' : pfkwargs , 'sigclip' : sigclip , 'getblssnr' : getblssnr } }
    # normalize using the special function if specified
    if normfunc is not None :
        lcdict = normfunc ( lcdict )
    for tcol , mcol , ecol in zip ( timecols , magcols , errcols ) : # dereference the columns and get them from the lcdict
        if '.' in tcol :
            tcolget = tcol . split ( '.' )
        else :
            tcolget = [ tcol ]
        times = _dict_get ( lcdict , tcolget )
        if '.' in mcol :
            mcolget = mcol . split ( '.' )
        else :
            mcolget = [ mcol ]
        mags = _dict_get ( lcdict , mcolget )
        if '.' in ecol :
            ecolget = ecol . split ( '.' )
        else :
            ecolget = [ ecol ]
        errs = _dict_get ( lcdict , ecolget )
        # normalize here if not using special normalization
        if normfunc is None :
            ntimes , nmags = normalize_magseries ( times , mags , magsarefluxes = magsarefluxes )
            times , mags , errs = ntimes , nmags , errs
        # run each of the requested period - finder functions
        resultdict [ mcol ] = { }
        # check if we have enough non - nan observations to proceed
        finmags = mags [ np . isfinite ( mags ) ]
        if finmags . size < minobservations :
            LOGERROR ( 'not enough non-nan observations for ' 'this LC. have: %s, required: %s, ' 'magcol: %s, skipping...' % ( finmags . size , minobservations , mcol ) )
            continue
        pfmkeys = [ ]
        for pfmind , pfm , pfkw in zip ( range ( len ( pfmethods ) ) , pfmethods , pfkwargs ) :
            pf_func = PFMETHODS [ pfm ]
            # get any optional kwargs for this function
            pf_kwargs = pfkw
            pf_kwargs . update ( { 'verbose' : False , 'nworkers' : nworkers , 'magsarefluxes' : magsarefluxes , 'sigclip' : sigclip } )
            # we ' ll always prefix things with their index to allow multiple
            # invocations and results from the same period - finder ( for
            # different period ranges , for example ) .
            pfmkey = '%s-%s' % ( pfmind , pfm )
            pfmkeys . append ( pfmkey )
            # run this period - finder and save its results to the output dict
            resultdict [ mcol ] [ pfmkey ] = pf_func ( times , mags , errs , ** pf_kwargs )
        # done with running the period finders
        # append the pfmkeys list to the magcol dict
        resultdict [ mcol ] [ 'pfmethods' ] = pfmkeys
        # check if we need to get the SNR from any BLS pfresults
        if 'bls' in pfmethods and getblssnr : # we need to scan thru the pfmethods to get to any BLS pfresults
            for pfmk in resultdict [ mcol ] [ 'pfmethods' ] :
                if 'bls' in pfmk :
                    try :
                        bls = resultdict [ mcol ] [ pfmk ]
                        # calculate the SNR for the BLS as well
                        blssnr = bls_snr ( bls , times , mags , errs , magsarefluxes = magsarefluxes , verbose = False )
                        # add the SNR results to the BLS result dict
                        resultdict [ mcol ] [ pfmk ] . update ( { 'snr' : blssnr [ 'snr' ] , 'transitdepth' : blssnr [ 'transitdepth' ] , 'transitduration' : blssnr [ 'transitduration' ] , } )
                        # update the BLS result dict with the refit periods
                        # and epochs using the results from bls _ snr
                        resultdict [ mcol ] [ pfmk ] . update ( { 'nbestperiods' : blssnr [ 'period' ] , 'epochs' : blssnr [ 'epoch' ] } )
                    except Exception as e :
                        LOGEXCEPTION ( 'could not calculate BLS SNR for %s' % lcfile )
                        # add the SNR null results to the BLS result dict
                        resultdict [ mcol ] [ pfmk ] . update ( { 'snr' : [ np . nan , np . nan , np . nan , np . nan , np . nan ] , 'transitdepth' : [ np . nan , np . nan , np . nan , np . nan , np . nan ] , 'transitduration' : [ np . nan , np . nan , np . nan , np . nan , np . nan ] , } )
        elif 'bls' in pfmethods : # we need to scan thru the pfmethods to get to any BLS pfresults
            for pfmk in resultdict [ mcol ] [ 'pfmethods' ] :
                if 'bls' in pfmk : # add the SNR null results to the BLS result dict
                    resultdict [ mcol ] [ pfmk ] . update ( { 'snr' : [ np . nan , np . nan , np . nan , np . nan , np . nan ] , 'transitdepth' : [ np . nan , np . nan , np . nan , np . nan , np . nan ] , 'transitduration' : [ np . nan , np . nan , np . nan , np . nan , np . nan ] , } )
    # once all mag cols have been processed , write out the pickle
    with open ( outfile , 'wb' ) as outfd :
        pickle . dump ( resultdict , outfd , protocol = pickle . HIGHEST_PROTOCOL )
    return outfile
except Exception as e :
    LOGEXCEPTION ( 'failed to run for %s, because: %s' % ( lcfile , e ) )
    if raiseonfail :
        raise
    return None


signature:
def _runpf_worker ( task ) :
    '''This runs the runpf function .'''

implementation:
( lcfile , outdir , timecols , magcols , errcols , lcformat , lcformatdir , pfmethods , pfkwargs , getblssnr , sigclip , nworkers , minobservations , excludeprocessed ) = task
if os . path . exists ( lcfile ) :
    pfresult = runpf ( lcfile , outdir , timecols = timecols , magcols = magcols , errcols = errcols , lcformat = lcformat , lcformatdir = lcformatdir , pfmethods = pfmethods , pfkwargs = pfkwargs , getblssnr = getblssnr , sigclip = sigclip , nworkers = nworkers , minobservations = minobservations , excludeprocessed = excludeprocessed )
    return pfresult
else :
    LOGERROR ( 'LC does not exist for requested file %s' % lcfile )
    return None


signature:
def parallel_pf ( lclist , outdir , timecols = None , magcols = None , errcols = None , lcformat = 'hat-sql' , lcformatdir = None , pfmethods = ( 'gls' , 'pdm' , 'mav' , 'win' ) , pfkwargs = ( { } , { } , { } , { } ) , sigclip = 10.0 , getblssnr = False , nperiodworkers = NCPUS , ncontrolworkers = 1 , liststartindex = None , listmaxobjects = None , minobservations = 500 , excludeprocessed = True ) :
    '''This drives the overall parallel period processing for a list of LCs .
 As a rough benchmark , 25000 HATNet light curves with up to 50000 points per
 LC take about 26 days in total for an invocation of this function using
 GLS + PDM + BLS , 10 periodworkers , and 4 controlworkers ( so all 40 ' cores ' ) on a
 2 x Xeon E5-2660v3 machine .
 Parameters
 lclist : list of str
 The list of light curve file to process .
 outdir : str
 The output directory where the period - finding result pickles will go .
 timecols : list of str or None
 The timecol keys to use from the lcdict in calculating the features .
 magcols : list of str or None
 The magcol keys to use from the lcdict in calculating the features .
 errcols : list of str or None
 The errcol keys to use from the lcdict in calculating the features .
 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 .
 pfmethods : list of str
 This is a list of period finding methods to run . Each element is a
 string matching the keys of the ` PFMETHODS ` dict above . By default , this
 runs GLS , PDM , AoVMH , and the spectral window Lomb - Scargle periodogram .
 pfkwargs : list of dicts
 This is used to provide any special kwargs as dicts to each
 period - finding method function specified in ` pfmethods ` .
 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 .
 getblssnr : bool
 If this is True and BLS is one of the methods specified in ` pfmethods ` ,
 will also calculate the stats for each best period in the BLS results :
 transit depth , duration , ingress duration , refit period and epoch , and
 the SNR of the transit .
 nperiodworkers : int
 The number of parallel period - finding workers to launch per object task .
 ncontrolworkers : int
 The number of controlling processes to launch . This effectively sets how
 many objects from ` lclist ` will be processed in parallel .
 liststartindex : int or None
 This sets the index from where to start in ` lclist ` .
 listmaxobjects : int or None
 This sets the maximum number of objects in ` lclist ` to run
 period - finding for in this invocation . Together with ` liststartindex ` ,
 ` listmaxobjects ` can be used to distribute processing over several
 independent machines if the number of light curves is very large .
 minobservations : int
 The minimum number of finite LC points required to process a light
 curve .
 excludeprocessed : bool
 If this is True , light curves that have existing period - finding result
 pickles in ` outdir ` will not be processed .
 FIXME : currently , this uses a dumb method of excluding already - processed
 files . A smarter way to do this is to ( i ) generate a SHA512 cachekey
 based on a repr of ` { ' lcfile ' , ' timecols ' , ' magcols ' , ' errcols ' ,
 ' lcformat ' , ' pfmethods ' , ' sigclip ' , ' getblssnr ' , ' pfkwargs ' } ` , ( ii ) make
 sure all list kwargs in the dict are sorted , ( iii ) check if the output
 file has the same cachekey in its filename ( last 8 chars of cachekey
 should work ) , so the result was processed in exactly the same way as
 specifed in the input to this function , and can therefore be
 ignored . Will implement this later .
 Returns
 list of str
 A list of the period - finding pickles created for all of input LCs
 processed .'''

implementation:
# make the output directory if it doesn ' t exist
if not os . path . exists ( outdir ) :
    os . makedirs ( outdir )
if ( liststartindex is not None ) and ( listmaxobjects is None ) :
    lclist = lclist [ liststartindex : ]
elif ( liststartindex is None ) and ( listmaxobjects is not None ) :
    lclist = lclist [ : listmaxobjects ]
elif ( liststartindex is not None ) and ( listmaxobjects is not None ) :
    lclist = lclist [ liststartindex : liststartindex + listmaxobjects ]
tasklist = [ ( x , outdir , timecols , magcols , errcols , lcformat , lcformatdir , pfmethods , pfkwargs , getblssnr , sigclip , nperiodworkers , minobservations , excludeprocessed ) for x in lclist ]
with ProcessPoolExecutor ( max_workers = ncontrolworkers ) as executor :
    resultfutures = executor . map ( _runpf_worker , tasklist )
results = [ x for x in resultfutures ]
return results


signature:
def parallel_pf_lcdir ( lcdir , outdir , fileglob = None , recursive = True , timecols = None , magcols = None , errcols = None , lcformat = 'hat-sql' , lcformatdir = None , pfmethods = ( 'gls' , 'pdm' , 'mav' , 'win' ) , pfkwargs = ( { } , { } , { } , { } ) , sigclip = 10.0 , getblssnr = False , nperiodworkers = NCPUS , ncontrolworkers = 1 , liststartindex = None , listmaxobjects = None , minobservations = 500 , excludeprocessed = True ) :
    '''This runs parallel light curve period finding for directory of LCs .
 Parameters
 lcdir : str
 The directory containing the LCs to process .
 outdir : str
 The directory where the resulting period - finding pickles will go .
 fileglob : str or None
 The UNIX file glob to use to search for LCs in ` lcdir ` . If None , the
 default file glob associated with the registered LC format will be used
 instead .
 recursive : bool
 If True , will search recursively in ` lcdir ` for light curves to process .
 timecols : list of str or None
 The timecol keys to use from the lcdict in calculating the features .
 magcols : list of str or None
 The magcol keys to use from the lcdict in calculating the features .
 errcols : list of str or None
 The errcol keys to use from the lcdict in calculating the features .
 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 .
 pfmethods : list of str
 This is a list of period finding methods to run . Each element is a
 string matching the keys of the ` PFMETHODS ` dict above . By default , this
 runs GLS , PDM , AoVMH , and the spectral window Lomb - Scargle periodogram .
 pfkwargs : list of dicts
 This is used to provide any special kwargs as dicts to each
 period - finding method function specified in ` pfmethods ` .
 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 .
 getblssnr : bool
 If this is True and BLS is one of the methods specified in ` pfmethods ` ,
 will also calculate the stats for each best period in the BLS results :
 transit depth , duration , ingress duration , refit period and epoch , and
 the SNR of the transit .
 nperiodworkers : int
 The number of parallel period - finding workers to launch per object task .
 ncontrolworkers : int
 The number of controlling processes to launch . This effectively sets how
 many objects from ` lclist ` will be processed in parallel .
 liststartindex : int or None
 This sets the index from where to start in ` lclist ` .
 listmaxobjects : int or None
 This sets the maximum number of objects in ` lclist ` to run
 period - finding for in this invocation . Together with ` liststartindex ` ,
 ` listmaxobjects ` can be used to distribute processing over several
 independent machines if the number of light curves is very large .
 minobservations : int
 The minimum number of finite LC points required to process a light
 curve .
 excludeprocessed : bool
 If this is True , light curves that have existing period - finding result
 pickles in ` outdir ` will not be processed .
 FIXME : currently , this uses a dumb method of excluding already - processed
 files . A smarter way to do this is to ( i ) generate a SHA512 cachekey
 based on a repr of ` { ' lcfile ' , ' timecols ' , ' magcols ' , ' errcols ' ,
 ' lcformat ' , ' pfmethods ' , ' sigclip ' , ' getblssnr ' , ' pfkwargs ' } ` , ( ii ) make
 sure all list kwargs in the dict are sorted , ( iii ) check if the output
 file has the same cachekey in its filename ( last 8 chars of cachekey
 should work ) , so the result was processed in exactly the same way as
 specifed in the input to this function , and can therefore be
 ignored . Will implement this later .
 Returns
 list of str
 A list of the period - finding pickles created for all of input LCs
 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 : # this helps us process things in deterministic order when we distribute
# processing over several machines
    matching = sorted ( matching )
    LOGINFO ( 'found %s light curves, running pf...' % len ( matching ) )
    return parallel_pf ( matching , outdir , timecols = timecols , magcols = magcols , errcols = errcols , lcformat = lcformat , lcformatdir = lcformatdir , pfmethods = pfmethods , pfkwargs = pfkwargs , getblssnr = getblssnr , sigclip = sigclip , nperiodworkers = nperiodworkers , ncontrolworkers = ncontrolworkers , liststartindex = liststartindex , listmaxobjects = listmaxobjects , minobservations = minobservations , excludeprocessed = excludeprocessed )
else :
    LOGERROR ( 'no light curve files in %s format found in %s' % ( lcformat , lcdir ) )
    return None


signature:
def collect_nonperiodic_features ( featuresdir , magcol , outfile , pklglob = 'varfeatures-*.pkl' , featurestouse = NONPERIODIC_FEATURES_TO_COLLECT , maxobjects = None , labeldict = None , labeltype = 'binary' , ) :
    '''This collects variability features into arrays for use with the classifer .
 Parameters
 featuresdir : str
 This is the directory where all the varfeatures pickles are . Use
 ` pklglob ` to specify the glob to search for . The ` varfeatures ` pickles
 contain objectids , a light curve magcol , and features as dict
 key - vals . The : py : mod : ` astrobase . lcproc . lcvfeatures ` module can be used
 to produce these .
 magcol : str
 This is the key in each varfeatures pickle corresponding to the magcol
 of the light curve the variability features were extracted from .
 outfile : str
 This is the filename of the output pickle that will be written
 containing a dict of all the features extracted into np . arrays .
 pklglob : str
 This is the UNIX file glob to use to search for varfeatures pickle files
 in ` featuresdir ` .
 featurestouse : list of str
 Each varfeatures pickle can contain any combination of non - periodic ,
 stellar , and periodic features ; these must have the same names as
 elements in the list of strings provided in ` featurestouse ` . This tries
 to get all the features listed in NONPERIODIC _ FEATURES _ TO _ COLLECT by
 default . If ` featurestouse ` is provided as a list , gets only the
 features listed in this kwarg instead .
 maxobjects : int or None
 The controls how many pickles from the featuresdir to process . If None ,
 will process all varfeatures pickles .
 labeldict : dict or None
 If this is provided , it must be a dict with the following key : val list : :
 ' < objectid > ' : < label value >
 for each objectid collected from the varfeatures pickles . This will turn
 the collected information into a training set for classifiers .
 Example : to carry out non - periodic variable feature collection of fake
 LCS prepared by : py : mod : ` astrobase . fakelcs . generation ` , use the value
 of the ' isvariable ' dict elem from the ` fakelcs - info . pkl ` here , like
 so : :
 labeldict = { x : y for x , y in zip ( fakelcinfo [ ' objectid ' ] ,
 fakelcinfo [ ' isvariable ' ] ) }
 labeltype : { ' binary ' , ' classes ' }
 This is either ' binary ' or ' classes ' for binary / multi - class
 classification respectively .
 Returns
 dict
 This returns a dict with all of the features collected into np . arrays ,
 ready to use as input to a scikit - learn classifier .'''

implementation:
# list of input pickles generated by varfeatures in lcproc . py
pklist = glob . glob ( os . path . join ( featuresdir , pklglob ) )
if maxobjects :
    pklist = pklist [ : maxobjects ]
# fancy progress bar with tqdm if present
if TQDM :
    listiterator = tqdm ( pklist )
else :
    listiterator = pklist
# go through all the varfeatures arrays
feature_dict = { 'objectids' : [ ] , 'magcol' : magcol , 'availablefeatures' : [ ] }
LOGINFO ( 'collecting features for magcol: %s' % magcol )
for pkl in listiterator :
    with open ( pkl , 'rb' ) as infd :
        varf = pickle . load ( infd )
    # update the objectid list
    objectid = varf [ 'objectid' ]
    if objectid not in feature_dict [ 'objectids' ] :
        feature_dict [ 'objectids' ] . append ( objectid )
    thisfeatures = varf [ magcol ]
    if featurestouse and len ( featurestouse ) > 0 :
        featurestoget = featurestouse
    else :
        featurestoget = NONPERIODIC_FEATURES_TO_COLLECT
    # collect all the features for this magcol / objectid combination
    for feature in featurestoget : # update the global feature list if necessary
        if ( ( feature not in feature_dict [ 'availablefeatures' ] ) and ( feature in thisfeatures ) ) :
            feature_dict [ 'availablefeatures' ] . append ( feature )
            feature_dict [ feature ] = [ ]
        if feature in thisfeatures :
            feature_dict [ feature ] . append ( thisfeatures [ feature ] )
# now that we ' ve collected all the objects and their features , turn the list
# into arrays , and then concatenate them
for feat in feature_dict [ 'availablefeatures' ] :
    feature_dict [ feat ] = np . array ( feature_dict [ feat ] )
feature_dict [ 'objectids' ] = np . array ( feature_dict [ 'objectids' ] )
feature_array = np . column_stack ( [ feature_dict [ feat ] for feat in feature_dict [ 'availablefeatures' ] ] )
feature_dict [ 'features_array' ] = feature_array
# if there ' s a labeldict available , use it to generate a label array . this
# feature collection is now a training set .
if isinstance ( labeldict , dict ) :
    labelarray = np . zeros ( feature_dict [ 'objectids' ] . size , dtype = np . int64 )
    # populate the labels for each object in the training set
    for ind , objectid in enumerate ( feature_dict [ 'objectids' ] ) :
        if objectid in labeldict : # if this is a binary classifier training set , convert bools to
        # ones and zeros
            if labeltype == 'binary' :
                if labeldict [ objectid ] :
                    labelarray [ ind ] = 1
            # otherwise , use the actual class label integer
            elif labeltype == 'classes' :
                labelarray [ ind ] = labeldict [ objectid ]
    feature_dict [ 'labels_array' ] = labelarray
feature_dict [ 'kwargs' ] = { 'pklglob' : pklglob , 'featurestouse' : featurestouse , 'maxobjects' : maxobjects , 'labeltype' : labeltype }
# write the info to the output pickle
with open ( outfile , 'wb' ) as outfd :
    pickle . dump ( feature_dict , outfd , pickle . HIGHEST_PROTOCOL )
# return the feature _ dict
return feature_dict


signature:
def train_rf_classifier ( collected_features , test_fraction = 0.25 , n_crossval_iterations = 20 , n_kfolds = 5 , crossval_scoring_metric = 'f1' , classifier_to_pickle = None , nworkers = - 1 , ) :
    '''This gets the best RF classifier after running cross - validation .
 - splits the training set into test / train samples
 - does ` KFold ` stratified cross - validation using ` RandomizedSearchCV `
 - gets the ` RandomForestClassifier ` with the best performance after CV
 - gets the confusion matrix for the test set
 Runs on the output dict from functions that produce dicts similar to that
 produced by ` collect _ nonperiodic _ features ` above .
 Parameters
 collected _ features : dict or str
 This is either the dict produced by a ` collect _ * _ features ` function or
 the pickle produced by the same .
 test _ fraction : float
 This sets the fraction of the input set that will be used as the
 test set after training .
 n _ crossval _ iterations : int
 This sets the number of iterations to use when running the
 cross - validation .
 n _ kfolds : int
 This sets the number of K - folds to use on the data when doing a
 test - train split .
 crossval _ scoring _ metric : str
 This is a string that describes how the cross - validation score is
 calculated for each iteration . See the URL below for how to specify this
 parameter :
 http : / / scikit - learn . org / stable / modules / model _ evaluation . html # scoring - parameter
 By default , this is tuned for binary classification and uses the F1
 scoring metric . Change the ` crossval _ scoring _ metric ` to another metric
 ( probably ' accuracy ' ) for multi - class classification , e . g . for periodic
 variable classification .
 classifier _ to _ pickle : str
 If this is a string indicating the name of a pickle file to write , will
 write the trained classifier to the pickle that can be later loaded and
 used to classify data .
 nworkers : int
 This is the number of parallel workers to use in the
 RandomForestClassifier . Set to - 1 to use all CPUs on your machine .
 Returns
 dict
 A dict containing the trained classifier , cross - validation results , the
 input data set , and all input kwargs used is returned , along with
 cross - validation score metrics .'''

implementation:
if ( isinstance ( collected_features , str ) and os . path . exists ( collected_features ) ) :
    with open ( collected_features , 'rb' ) as infd :
        fdict = pickle . load ( infd )
elif isinstance ( collected_features , dict ) :
    fdict = collected_features
else :
    LOGERROR ( "can't figure out the input collected_features arg" )
    return None
tfeatures = fdict [ 'features_array' ]
tlabels = fdict [ 'labels_array' ]
tfeaturenames = fdict [ 'availablefeatures' ]
tmagcol = fdict [ 'magcol' ]
tobjectids = fdict [ 'objectids' ]
# split the training set into training / test samples using stratification
# to keep the same fraction of variable / nonvariables in each
training_features , testing_features , training_labels , testing_labels = ( train_test_split ( tfeatures , tlabels , test_size = test_fraction , random_state = RANDSEED , stratify = tlabels ) )
# get a random forest classifier
clf = RandomForestClassifier ( n_jobs = nworkers , random_state = RANDSEED )
# this is the grid def for hyperparam optimization
rf_hyperparams = { "max_depth" : [ 3 , 4 , 5 , None ] , "n_estimators" : sp_randint ( 100 , 2000 ) , "max_features" : sp_randint ( 1 , 5 ) , "min_samples_split" : sp_randint ( 2 , 11 ) , "min_samples_leaf" : sp_randint ( 2 , 11 ) , }
# run the stratified kfold cross - validation on training features using our
# random forest classifier object
cvsearch = RandomizedSearchCV ( clf , param_distributions = rf_hyperparams , n_iter = n_crossval_iterations , scoring = crossval_scoring_metric , cv = StratifiedKFold ( n_splits = n_kfolds , shuffle = True , random_state = RANDSEED ) , random_state = RANDSEED )
LOGINFO ( 'running grid-search CV to optimize RF hyperparameters...' )
cvsearch_classifiers = cvsearch . fit ( training_features , training_labels )
# report on the classifiers ' performance
_gridsearch_report ( cvsearch_classifiers . cv_results_ )
# get the best classifier after CV is done
bestclf = cvsearch_classifiers . best_estimator_
bestclf_score = cvsearch_classifiers . best_score_
bestclf_hyperparams = cvsearch_classifiers . best_params_
# test this classifier on the testing set
test_predicted_labels = bestclf . predict ( testing_features )
recscore = recall_score ( testing_labels , test_predicted_labels )
precscore = precision_score ( testing_labels , test_predicted_labels )
f1score = f1_score ( testing_labels , test_predicted_labels )
confmatrix = confusion_matrix ( testing_labels , test_predicted_labels )
# write the classifier , its training / testing set , and its stats to the
# pickle if requested
outdict = { 'features' : tfeatures , 'labels' : tlabels , 'feature_names' : tfeaturenames , 'magcol' : tmagcol , 'objectids' : tobjectids , 'kwargs' : { 'test_fraction' : test_fraction , 'n_crossval_iterations' : n_crossval_iterations , 'n_kfolds' : n_kfolds , 'crossval_scoring_metric' : crossval_scoring_metric , 'nworkers' : nworkers } , 'collect_kwargs' : fdict [ 'kwargs' ] , 'testing_features' : testing_features , 'testing_labels' : testing_labels , 'training_features' : training_features , 'training_labels' : training_labels , 'best_classifier' : bestclf , 'best_score' : bestclf_score , 'best_hyperparams' : bestclf_hyperparams , 'best_recall' : recscore , 'best_precision' : precscore , 'best_f1' : f1score , 'best_confmatrix' : confmatrix }
if classifier_to_pickle :
    with open ( classifier_to_pickle , 'wb' ) as outfd :
        pickle . dump ( outdict , outfd , pickle . HIGHEST_PROTOCOL )
# return this classifier and accompanying info
return outdict


signature:
def apply_rf_classifier ( classifier , varfeaturesdir , outpickle , maxobjects = None ) :
    '''This applys an RF classifier trained using ` train _ rf _ classifier `
 to varfeatures pickles in ` varfeaturesdir ` .
 Parameters
 classifier : dict or str
 This is the output dict or pickle created by ` get _ rf _ classifier ` . This
 will contain a ` features _ name ` key that will be used to collect the same
 features used to train the classifier from the varfeatures pickles in
 varfeaturesdir .
 varfeaturesdir : str
 The directory containing the varfeatures pickles for objects that will
 be classified by the trained ` classifier ` .
 outpickle : str
 This is a filename for the pickle that will be written containing the
 result dict from this function .
 maxobjects : int
 This sets the number of objects to process in ` varfeaturesdir ` .
 Returns
 dict
 The classification results after running the trained ` classifier ` as
 returned as a dict . This contains predicted labels and their prediction
 probabilities .'''

implementation:
if isinstance ( classifier , str ) and os . path . exists ( classifier ) :
    with open ( classifier , 'rb' ) as infd :
        clfdict = pickle . load ( infd )
elif isinstance ( classifier , dict ) :
    clfdict = classifier
else :
    LOGERROR ( "can't figure out the input classifier arg" )
    return None
# get the features to extract from clfdict
if 'feature_names' not in clfdict :
    LOGERROR ( "feature_names not present in classifier input, " "can't figure out which ones to extract from " "varfeature pickles in %s" % varfeaturesdir )
    return None
# get the feature labeltype , pklglob , and maxobjects from classifier ' s
# collect _ kwargs elem .
featurestouse = clfdict [ 'feature_names' ]
pklglob = clfdict [ 'collect_kwargs' ] [ 'pklglob' ]
magcol = clfdict [ 'magcol' ]
# extract the features used by the classifier from the varfeatures pickles
# in varfeaturesdir using the pklglob provided
featfile = os . path . join ( os . path . dirname ( outpickle ) , 'actual-collected-features.pkl' )
features = collect_nonperiodic_features ( varfeaturesdir , magcol , featfile , pklglob = pklglob , featurestouse = featurestouse , maxobjects = maxobjects )
# now use the trained classifier on these features
bestclf = clfdict [ 'best_classifier' ]
predicted_labels = bestclf . predict ( features [ 'features_array' ] )
# FIXME : do we need to use the probability calibration curves to fix these
# probabilities ? probably . figure out how to do this .
predicted_label_probs = bestclf . predict_proba ( features [ 'features_array' ] )
outdict = { 'features' : features , 'featfile' : featfile , 'classifier' : clfdict , 'predicted_labels' : predicted_labels , 'predicted_label_probs' : predicted_label_probs , }
with open ( outpickle , 'wb' ) as outfd :
    pickle . dump ( outdict , outfd , pickle . HIGHEST_PROTOCOL )
return outdict


signature:
def plot_training_results ( classifier , classlabels , outfile ) :
    '''This plots the training results from the classifier run on the training
 set .
 - plots the confusion matrix
 - plots the feature importances
 - FIXME : plot the learning curves too , see :
 http : / / scikit - learn . org / stable / modules / learning _ curve . html
 Parameters
 classifier : dict or str
 This is the output dict or pickle created by ` get _ rf _ classifier `
 containing the trained classifier .
 classlabels : list of str
 This contains all of the class labels for the current classification
 problem .
 outfile : str
 This is the filename where the plots will be written .
 Returns
 str
 The path to the generated plot file .'''

implementation:
if isinstance ( classifier , str ) and os . path . exists ( classifier ) :
    with open ( classifier , 'rb' ) as infd :
        clfdict = pickle . load ( infd )
elif isinstance ( classifier , dict ) :
    clfdict = classifier
else :
    LOGERROR ( "can't figure out the input classifier arg" )
    return None
confmatrix = clfdict [ 'best_confmatrix' ]
overall_feature_importances = clfdict [ 'best_classifier' ] . feature_importances_
feature_importances_per_tree = np . array ( [ tree . feature_importances_ for tree in clfdict [ 'best_classifier' ] . estimators_ ] )
stdev_feature_importances = np . std ( feature_importances_per_tree , axis = 0 )
feature_names = np . array ( clfdict [ 'feature_names' ] )
plt . figure ( figsize = ( 6.4 * 3.0 , 4.8 ) )
# confusion matrix
plt . subplot ( 121 )
classes = np . array ( classlabels )
plt . imshow ( confmatrix , interpolation = 'nearest' , cmap = plt . cm . Blues )
tick_marks = np . arange ( len ( classes ) )
plt . xticks ( tick_marks , classes )
plt . yticks ( tick_marks , classes )
plt . title ( 'evaluation set confusion matrix' )
plt . ylabel ( 'predicted class' )
plt . xlabel ( 'actual class' )
thresh = confmatrix . max ( ) / 2.
for i , j in itertools . product ( range ( confmatrix . shape [ 0 ] ) , range ( confmatrix . shape [ 1 ] ) ) :
    plt . text ( j , i , confmatrix [ i , j ] , horizontalalignment = "center" , color = "white" if confmatrix [ i , j ] > thresh else "black" )
# feature importances
plt . subplot ( 122 )
features = np . array ( feature_names )
sorted_ind = np . argsort ( overall_feature_importances ) [ : : - 1 ]
features = features [ sorted_ind ]
feature_names = feature_names [ sorted_ind ]
overall_feature_importances = overall_feature_importances [ sorted_ind ]
stdev_feature_importances = stdev_feature_importances [ sorted_ind ]
plt . bar ( np . arange ( 0 , features . size ) , overall_feature_importances , yerr = stdev_feature_importances , width = 0.8 , color = 'grey' )
plt . xticks ( np . arange ( 0 , features . size ) , features , rotation = 90 )
plt . yticks ( [ 0.0 , 0.1 , 0.2 , 0.3 , 0.4 , 0.5 , 0.6 , 0.7 , 0.8 , 0.9 , 1.0 ] )
plt . xlim ( - 0.75 , features . size - 1.0 + 0.75 )
plt . ylim ( 0.0 , 0.9 )
plt . ylabel ( 'relative importance' )
plt . title ( 'relative importance of features' )
plt . subplots_adjust ( wspace = 0.1 )
plt . savefig ( outfile , bbox_inches = 'tight' , dpi = 100 )
plt . close ( 'all' )
return outfile


signature:
def _fourier_func ( fourierparams , phase , mags ) :
    '''This returns a summed Fourier cosine series .
 Parameters
 fourierparams : list
 This MUST be a list of the following form like so : :
 [ period ,
 epoch ,
 [ amplitude _ 1 , amplitude _ 2 , amplitude _ 3 , . . . , amplitude _ X ] ,
 [ phase _ 1 , phase _ 2 , phase _ 3 , . . . , phase _ X ] ]
 where X is the Fourier order .
 phase , mags : np . array
 The input phase and magnitude areas to use as the basis for the cosine
 series . The phases are used directly to generate the values of the
 function , while the mags array is used to generate the zeroth order
 amplitude coefficient .
 Returns
 np . array
 The Fourier cosine series function evaluated over ` phase ` .'''

implementation:
# figure out the order from the length of the Fourier param list
order = int ( len ( fourierparams ) / 2 )
# get the amplitude and phase coefficients
f_amp = fourierparams [ : order ]
f_pha = fourierparams [ order : ]
# calculate all the individual terms of the series
f_orders = [ f_amp [ x ] * npcos ( 2.0 * pi_value * x * phase + f_pha [ x ] ) for x in range ( order ) ]
# this is the zeroth order coefficient - a constant equal to median mag
total_f = npmedian ( mags )
# sum the series
for fo in f_orders :
    total_f += fo
return total_f


signature:
def _fourier_chisq ( fourierparams , phase , mags , errs ) :
    '''This is the chisq objective function to be minimized by ` scipy . minimize ` .
 The parameters are the same as ` _ fourier _ func ` above . ` errs ` is used to
 calculate the chisq value .'''

implementation:
f = _fourier_func ( fourierparams , phase , mags )
chisq = npsum ( ( ( mags - f ) * ( mags - f ) ) / ( errs * errs ) )
return chisq


signature:
def _fourier_residual ( fourierparams , phase , mags ) :
    '''This is the residual objective function to be minimized by ` scipy . leastsq ` .
 The parameters are the same as ` _ fourier _ func ` above .'''

implementation:
f = _fourier_func ( fourierparams , phase , mags )
residual = mags - f
return residual


signature:
def fourier_fit_magseries ( times , mags , errs , period , fourierorder = None , fourierparams = None , sigclip = 3.0 , magsarefluxes = False , plotfit = False , ignoreinitfail = True , verbose = True ) :
    '''This fits a Fourier series to a mag / flux time series .
 Parameters
 times , mags , errs : np . array
 The input mag / flux time - series to fit a Fourier cosine series to .
 period : float
 The period to use for the Fourier fit .
 fourierorder : None or int
 If this is an int , will be interpreted as the Fourier order of the
 series to fit to the input mag / flux times - series . If this is None and
 ` fourierparams ` is specified , ` fourierparams ` will be used directly to
 generate the fit Fourier series . If ` fourierparams ` is also None , this
 function will try to fit a Fourier cosine series of order 3 to the
 mag / flux time - series .
 fourierparams : list of floats or None
 If this is specified as a list of floats , it must be of the form below : :
 [ fourier _ amp1 , fourier _ amp2 , fourier _ amp3 , . . . , fourier _ ampN ,
 fourier _ phase1 , fourier _ phase2 , fourier _ phase3 , . . . , fourier _ phaseN ]
 to specify a Fourier cosine series of order N . If this is None and
 ` fourierorder ` is specified , the Fourier order specified there will be
 used to construct the Fourier cosine series used to fit the input
 mag / flux time - series . If both are None , this function will try to fit a
 Fourier cosine series of order 3 to the input mag / flux time - series .
 sigclip : float or int or sequence of two floats / ints or None
 If a single float or int , a symmetric sigma - clip will be performed using
 the number provided as the sigma - multiplier to cut out from the input
 time - series .
 If a list of two ints / floats is provided , the function will perform an
 ' asymmetric ' sigma - clip . The first element in this list is the sigma
 value to use for fainter flux / mag values ; the second element in this
 list is the sigma value to use for brighter flux / mag values . For
 example , ` sigclip = [ 10 . , 3 . ] ` , will sigclip out greater than 10 - sigma
 dimmings and greater than 3 - sigma brightenings . Here the meaning of
 " dimming " and " brightening " is set by * physics * ( not the magnitude
 system ) , which is why the ` magsarefluxes ` kwarg must be correctly set .
 If ` sigclip ` is None , no sigma - clipping will be performed , and the
 time - series ( with non - finite elems removed ) will be passed through to
 the output .
 magsarefluxes : bool
 If True , will treat the input values of ` mags ` as fluxes for purposes of
 plotting the fit and sig - clipping .
 plotfit : str or False
 If this is a string , this function will make a plot for the fit to the
 mag / flux time - series and writes the plot to the path specified here .
 ignoreinitfail : bool
 If this is True , ignores the initial failure to find a set of optimized
 Fourier parameters using the global optimization function and proceeds
 to do a least - squares fit anyway .
 verbose : bool
 If True , will indicate progress and warn of any problems .
 Returns
 dict
 This function returns a dict containing the model fit parameters , the
 minimized chi - sq value and the reduced chi - sq value . The form of this
 dict is mostly standardized across all functions in this module : :
 ' fittype ' : ' fourier ' ,
 ' fitinfo ' : {
 ' finalparams ' : the list of final model fit params ,
 ' leastsqfit ' : the full tuple returned by scipy . leastsq ,
 ' fitmags ' : the model fit mags ,
 ' fitepoch ' : the epoch of minimum light for the fit ,
 . . . other fit function specific keys . . .
 ' fitchisq ' : the minimized value of the fit ' s chi - sq ,
 ' fitredchisq ' : the reduced chi - sq value ,
 ' fitplotfile ' : the output fit plot if fitplot is not None ,
 ' magseries ' : {
 ' times ' : input times in phase order of the model ,
 ' phase ' : the phases of the model mags ,
 ' mags ' : input mags / fluxes in the phase order of the model ,
 ' errs ' : errs in the phase order of the model ,
 ' magsarefluxes ' : input value of magsarefluxes kwarg
 NOTE : the returned value of ' fitepoch ' in the ' fitinfo ' dict returned by
 this function is the time value of the first observation since this is
 where the LC is folded for the fit procedure . To get the actual time of
 minimum epoch as calculated by a spline fit to the phased LC , use the
 key ' actual _ fitepoch ' in the ' fitinfo ' dict .'''

implementation:
stimes , smags , serrs = sigclip_magseries ( times , mags , errs , sigclip = sigclip , magsarefluxes = magsarefluxes )
# get rid of zero errs
nzind = npnonzero ( serrs )
stimes , smags , serrs = stimes [ nzind ] , smags [ nzind ] , serrs [ nzind ]
phase , pmags , perrs , ptimes , mintime = ( get_phased_quantities ( stimes , smags , serrs , period ) )
# get the fourier order either from the scalar order kwarg . . .
if fourierorder and fourierorder > 0 and not fourierparams :
    fourieramps = [ 0.6 ] + [ 0.2 ] * ( fourierorder - 1 )
    fourierphas = [ 0.1 ] + [ 0.1 ] * ( fourierorder - 1 )
    fourierparams = fourieramps + fourierphas
# or from the fully specified coeffs vector
elif not fourierorder and fourierparams :
    fourierorder = int ( len ( fourierparams ) / 2 )
else :
    LOGWARNING ( 'specified both/neither Fourier order AND Fourier coeffs, ' 'using default Fourier order of 3' )
    fourierorder = 3
    fourieramps = [ 0.6 ] + [ 0.2 ] * ( fourierorder - 1 )
    fourierphas = [ 0.1 ] + [ 0.1 ] * ( fourierorder - 1 )
    fourierparams = fourieramps + fourierphas
if verbose :
    LOGINFO ( 'fitting Fourier series of order %s to ' 'mag series with %s observations, ' 'using period %.6f, folded at %.6f' % ( fourierorder , len ( phase ) , period , mintime ) )
# initial minimize call to find global minimum in chi - sq
initialfit = spminimize ( _fourier_chisq , fourierparams , method = 'BFGS' , args = ( phase , pmags , perrs ) )
# make sure this initial fit succeeds before proceeding
if initialfit . success or ignoreinitfail :
    if verbose :
        LOGINFO ( 'initial fit done, refining...' )
    leastsqparams = initialfit . x
    try :
        leastsqfit = spleastsq ( _fourier_residual , leastsqparams , args = ( phase , pmags ) )
    except Exception as e :
        leastsqfit = None
    # if the fit succeeded , then we can return the final parameters
    if leastsqfit and leastsqfit [ - 1 ] in ( 1 , 2 , 3 , 4 ) :
        finalparams = leastsqfit [ 0 ]
        # calculate the chisq and reduced chisq
        fitmags = _fourier_func ( finalparams , phase , pmags )
        fitchisq = npsum ( ( ( fitmags - pmags ) * ( fitmags - pmags ) ) / ( perrs * perrs ) )
        fitredchisq = fitchisq / ( len ( pmags ) - len ( finalparams ) - 1 )
        if verbose :
            LOGINFO ( 'final fit done. chisq = %.5f, reduced chisq = %.5f' % ( fitchisq , fitredchisq ) )
        # figure out the time of light curve minimum ( i . e . the fit epoch )
        # this is when the fit mag is maximum ( i . e . the faintest )
        # or if magsarefluxes = True , then this is when fit flux is minimum
        if not magsarefluxes :
            fitmagminind = npwhere ( fitmags == npmax ( fitmags ) )
        else :
            fitmagminind = npwhere ( fitmags == npmin ( fitmags ) )
        if len ( fitmagminind [ 0 ] ) > 1 :
            fitmagminind = ( fitmagminind [ 0 ] [ 0 ] , )
        # assemble the returndict
        returndict = { 'fittype' : 'fourier' , 'fitinfo' : { 'fourierorder' : fourierorder , 'finalparams' : finalparams , 'initialfit' : initialfit , 'leastsqfit' : leastsqfit , 'fitmags' : fitmags , 'fitepoch' : mintime , 'actual_fitepoch' : ptimes [ fitmagminind ] } , 'fitchisq' : fitchisq , 'fitredchisq' : fitredchisq , 'fitplotfile' : None , 'magseries' : { 'times' : ptimes , 'phase' : phase , 'mags' : pmags , 'errs' : perrs , 'magsarefluxes' : magsarefluxes } , }
        # make the fit plot if required
        if plotfit and isinstance ( plotfit , str ) :
            make_fit_plot ( phase , pmags , perrs , fitmags , period , mintime , mintime , plotfit , magsarefluxes = magsarefluxes )
            returndict [ 'fitplotfile' ] = plotfit
        return returndict
    # if the leastsq fit did not succeed , return Nothing
    else :
        LOGERROR ( 'fourier-fit: least-squared fit to the light curve failed' )
        return { 'fittype' : 'fourier' , 'fitinfo' : { 'fourierorder' : fourierorder , 'finalparams' : None , 'initialfit' : initialfit , 'leastsqfit' : None , 'fitmags' : None , 'fitepoch' : None } , 'fitchisq' : npnan , 'fitredchisq' : npnan , 'fitplotfile' : None , 'magseries' : { 'times' : ptimes , 'phase' : phase , 'mags' : pmags , 'errs' : perrs , 'magsarefluxes' : magsarefluxes } }
# if the fit didn ' t succeed , we can ' t proceed
else :
    LOGERROR ( 'initial Fourier fit did not succeed, ' 'reason: %s, returning scipy OptimizeResult' % initialfit . message )
    return { 'fittype' : 'fourier' , 'fitinfo' : { 'fourierorder' : fourierorder , 'finalparams' : None , 'initialfit' : initialfit , 'leastsqfit' : None , 'fitmags' : None , 'fitepoch' : None } , 'fitchisq' : npnan , 'fitredchisq' : npnan , 'fitplotfile' : None , 'magseries' : { 'times' : ptimes , 'phase' : phase , 'mags' : pmags , 'errs' : perrs , 'magsarefluxes' : magsarefluxes } }


signature:
def plot_magseries ( times , mags , magsarefluxes = False , errs = None , out = None , sigclip = 30.0 , normto = 'globalmedian' , normmingap = 4.0 , timebin = None , yrange = None , segmentmingap = 100.0 , plotdpi = 100 ) :
    '''This plots a magnitude / flux time - series .
 Parameters
 times , mags : np . array
 The mag / flux time - series to plot as a function of time .
 magsarefluxes : bool
 Indicates if the input ` mags ` array is actually an array of flux
 measurements instead of magnitude measurements . If this is set to True ,
 then the plot y - axis will be set as appropriate for mag or fluxes . In
 addition :
 - if ` normto ` is ' zero ' , then the median flux is divided from each
 observation ' s flux value to yield normalized fluxes with 1.0 as the
 global median .
 - if ` normto ` is ' globalmedian ' , then the global median flux value
 across the entire time series is multiplied with each measurement .
 - if ` norm ` is set to a ` float ` , then this number is multiplied with the
 flux value for each measurement .
 errs : np . array or None
 If this is provided , contains the measurement errors associated with
 each measurement of flux / mag in time - series . Providing this kwarg will
 add errbars to the output plot .
 out : str or StringIO / BytesIO object or None
 Sets the output type and target :
 - If ` out ` is a string , will save the plot to the specified file name .
 - If ` out ` is a StringIO / BytesIO object , will save the plot to that file
 handle . This can be useful to carry out additional operations on the
 output binary stream , or convert it to base64 text for embedding in
 HTML pages .
 - If ` out ` is None , will save the plot to a file called
 ' magseries - plot . png ' in the current working directory .
 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 .
 normto : { ' globalmedian ' , ' zero ' } or a float
 Sets the normalization target : :
 ' 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 .
 timebin : float or None
 The bin size to use to group together measurements closer than this
 amount in time . This is in seconds . If this is None , no time - binning
 will be performed .
 yrange : list of two floats or None
 This is used to provide a custom y - axis range to the plot . If None , will
 automatically determine y - axis range .
 segmentmingap : float or None
 This controls the minimum length of time ( in days ) required to consider
 a timegroup in the light curve as a separate segment . This is useful
 when the light curve consists of measurements taken over several
 seasons , so there ' s lots of dead space in the plot that can be cut out
 to zoom in on the interesting stuff . If ` segmentmingap ` is not None , the
 magseries plot will be cut in this way and the x - axis will show these
 breaks .
 plotdpi : int
 Sets the resolution in DPI for PNG plots ( default = 100 ) .
 Returns
 str or BytesIO / StringIO object
 Returns based on the input :
 - If ` out ` is a str or None , the path to the generated plot file is
 returned .
 - If ` out ` is a StringIO / BytesIO object , will return the
 StringIO / BytesIO object to which the plot was written .'''

implementation:
# sigclip the magnitude timeseries
stimes , smags , serrs = sigclip_magseries ( times , mags , errs , magsarefluxes = magsarefluxes , sigclip = sigclip )
# now we proceed to binning
if timebin and errs is not None :
    binned = time_bin_magseries_with_errs ( stimes , smags , serrs , binsize = timebin )
    btimes , bmags , berrs = ( binned [ 'binnedtimes' ] , binned [ 'binnedmags' ] , binned [ 'binnederrs' ] )
elif timebin and errs is None :
    binned = time_bin_magseries ( stimes , smags , binsize = timebin )
    btimes , bmags , berrs = binned [ 'binnedtimes' ] , binned [ 'binnedmags' ] , None
else :
    btimes , bmags , berrs = stimes , smags , serrs
# check if we need to normalize
if normto is not False :
    btimes , bmags = normalize_magseries ( btimes , bmags , normto = normto , magsarefluxes = magsarefluxes , mingap = normmingap )
btimeorigin = btimes . min ( )
btimes = btimes - btimeorigin
# # FINALLY PLOT THE LIGHT CURVE # #
# if we ' re going to plot with segment gaps highlighted , then find the gaps
if segmentmingap is not None :
    ntimegroups , timegroups = find_lc_timegroups ( btimes , mingap = segmentmingap )
# get the yrange for all the plots if it ' s given
if yrange and isinstance ( yrange , ( list , tuple ) ) and len ( yrange ) == 2 :
    ymin , ymax = yrange
# if it ' s not given , figure it out
else : # the plot y limits are just 0.05 mags on each side if mags are used
    if not magsarefluxes :
        ymin , ymax = ( bmags . min ( ) - 0.05 , bmags . max ( ) + 0.05 )
    # if we ' re dealing with fluxes , limits are 2 % of the flux range per side
    else :
        ycov = bmags . max ( ) - bmags . min ( )
        ymin = bmags . min ( ) - 0.02 * ycov
        ymax = bmags . max ( ) + 0.02 * ycov
# if we ' re supposed to make the plot segment - aware ( i . e . gaps longer than
# segmentmingap will be cut out )
if segmentmingap and ntimegroups > 1 :
    LOGINFO ( '%s time groups found' % ntimegroups )
    # our figure is now a multiple axis plot
    # the aspect ratio is a bit wider
    fig , axes = plt . subplots ( 1 , ntimegroups , sharey = True )
    fig . set_size_inches ( 10 , 4.8 )
    axes = np . ravel ( axes )
    # now go through each axis and make the plots for each timegroup
    for timegroup , ax , axind in zip ( timegroups , axes , range ( len ( axes ) ) ) :
        tgtimes = btimes [ timegroup ]
        tgmags = bmags [ timegroup ]
        if berrs :
            tgerrs = berrs [ timegroup ]
        else :
            tgerrs = None
        LOGINFO ( 'axes: %s, timegroup %s: JD %.3f to %.3f' % ( axind , axind + 1 , btimeorigin + tgtimes . min ( ) , btimeorigin + tgtimes . max ( ) ) )
        ax . errorbar ( tgtimes , tgmags , fmt = 'go' , yerr = tgerrs , markersize = 2.0 , markeredgewidth = 0.0 , ecolor = 'grey' , capsize = 0 )
        # don ' t use offsets on any xaxis
        ax . get_xaxis ( ) . get_major_formatter ( ) . set_useOffset ( False )
        # fix the ticks to use no yoffsets and remove right spines for first
        # axes instance
        if axind == 0 :
            ax . get_yaxis ( ) . get_major_formatter ( ) . set_useOffset ( False )
            ax . spines [ 'right' ] . set_visible ( False )
            ax . yaxis . tick_left ( )
        # remove the right and left spines for the other axes instances
        elif 0 < axind < ( len ( axes ) - 1 ) :
            ax . spines [ 'right' ] . set_visible ( False )
            ax . spines [ 'left' ] . set_visible ( False )
            ax . tick_params ( right = 'off' , labelright = 'off' , left = 'off' , labelleft = 'off' )
        # make the left spines invisible for the last axes instance
        elif axind == ( len ( axes ) - 1 ) :
            ax . spines [ 'left' ] . set_visible ( False )
            ax . spines [ 'right' ] . set_visible ( True )
            ax . yaxis . tick_right ( )
        # set the yaxis limits
        if not magsarefluxes :
            ax . set_ylim ( ymax , ymin )
        else :
            ax . set_ylim ( ymin , ymax )
        # now figure out the xaxis ticklabels and ranges
        tgrange = tgtimes . max ( ) - tgtimes . min ( )
        if tgrange < 10.0 :
            ticklocations = [ tgrange / 2.0 ]
            ax . set_xlim ( npmin ( tgtimes ) - 0.5 , npmax ( tgtimes ) + 0.5 )
        elif 10.0 < tgrange < 30.0 :
            ticklocations = np . linspace ( tgtimes . min ( ) + 5.0 , tgtimes . max ( ) - 5.0 , num = 2 )
            ax . set_xlim ( npmin ( tgtimes ) - 2.0 , npmax ( tgtimes ) + 2.0 )
        elif 30.0 < tgrange < 100.0 :
            ticklocations = np . linspace ( tgtimes . min ( ) + 10.0 , tgtimes . max ( ) - 10.0 , num = 3 )
            ax . set_xlim ( npmin ( tgtimes ) - 2.5 , npmax ( tgtimes ) + 2.5 )
        else :
            ticklocations = np . linspace ( tgtimes . min ( ) + 20.0 , tgtimes . max ( ) - 20.0 , num = 3 )
            ax . set_xlim ( npmin ( tgtimes ) - 3.0 , npmax ( tgtimes ) + 3.0 )
        ax . xaxis . set_ticks ( [ int ( x ) for x in ticklocations ] )
    # done with plotting all the sub axes
    # make the distance between sub plots smaller
    plt . subplots_adjust ( wspace = 0.07 )
    # make the overall x and y labels
    fig . text ( 0.5 , 0.00 , 'JD - %.3f (not showing gaps > %.2f d)' % ( btimeorigin , segmentmingap ) , ha = 'center' )
    if not magsarefluxes :
        fig . text ( 0.02 , 0.5 , 'magnitude' , va = 'center' , rotation = 'vertical' )
    else :
        fig . text ( 0.02 , 0.5 , 'flux' , va = 'center' , rotation = 'vertical' )
# make normal figure otherwise
else :
    fig = plt . figure ( )
    fig . set_size_inches ( 7.5 , 4.8 )
    plt . errorbar ( btimes , bmags , fmt = 'go' , yerr = berrs , markersize = 2.0 , markeredgewidth = 0.0 , ecolor = 'grey' , capsize = 0 )
    # make a grid
    plt . grid ( color = '#a9a9a9' , alpha = 0.9 , zorder = 0 , linewidth = 1.0 , linestyle = ':' )
    # fix the ticks to use no offsets
    plt . gca ( ) . get_yaxis ( ) . get_major_formatter ( ) . set_useOffset ( False )
    plt . gca ( ) . get_xaxis ( ) . get_major_formatter ( ) . set_useOffset ( False )
    plt . xlabel ( 'JD - %.3f' % btimeorigin )
    # set the yaxis limits and labels
    if not magsarefluxes :
        plt . ylim ( ymax , ymin )
        plt . ylabel ( 'magnitude' )
    else :
        plt . ylim ( ymin , ymax )
        plt . ylabel ( 'flux' )
# check if the output filename is actually an instance of StringIO
if sys . version_info [ : 2 ] < ( 3 , 0 ) :
    is_Strio = isinstance ( out , cStringIO . InputType )
else :
    is_Strio = isinstance ( out , Strio )
# write the plot out to a file if requested
if out and not is_Strio :
    if out . endswith ( '.png' ) :
        plt . savefig ( out , bbox_inches = 'tight' , dpi = plotdpi )
    else :
        plt . savefig ( out , bbox_inches = 'tight' )
    plt . close ( )
    return os . path . abspath ( out )
elif out and is_Strio :
    plt . savefig ( out , bbox_inches = 'tight' , dpi = plotdpi , format = 'png' )
    return out
elif not out and dispok :
    plt . show ( )
    plt . close ( )
    return
else :
    LOGWARNING ( 'no output file specified and no $DISPLAY set, ' 'saving to magseries-plot.png in current directory' )
    outfile = 'magseries-plot.png'
    plt . savefig ( outfile , bbox_inches = 'tight' , dpi = plotdpi )
    plt . close ( )
    return os . path . abspath ( outfile )


signature:
def plot_phased_magseries ( times , mags , period , epoch = 'min' , fitknotfrac = 0.01 , errs = None , magsarefluxes = False , normto = 'globalmedian' , normmingap = 4.0 , sigclip = 30.0 , phasewrap = True , phasesort = True , phasebin = None , plotphaselim = ( - 0.8 , 0.8 ) , yrange = None , xtimenotphase = False , xaxlabel = 'phase' , yaxlabel = None , modelmags = None , modeltimes = None , modelerrs = None , outfile = None , plotdpi = 100 ) :
    '''Plots a phased magnitude / flux time - series using the period provided .
 Parameters
 times , mags : np . array
 The mag / flux time - series to plot as a function of phase given ` period ` .
 period : float
 The period to use to phase - fold the time - series . Should be the same unit
 as ` times ` ( usually in days )
 epoch : ' min ' or float or None
 This indicates how to get the epoch to use for phasing the light curve :
 - If None , uses the ` min ( times ) ` as the epoch for phasing .
 - If epoch is the string ' min ' , then fits a cubic spline to the phased
 light curve using ` min ( times ) ` as the initial epoch , finds the
 magnitude / flux minimum of this phased light curve fit , and finally
 uses the that time value as the epoch . This is useful for plotting
 planetary transits and eclipsing binary phased light curves so that
 phase 0.0 corresponds to the mid - center time of primary eclipse ( or
 transit ) .
 - If epoch is a float , then uses that directly to phase the light
 curve and as the epoch of the phased mag series plot .
 fitknotfrac : float
 If ` epoch = ' min ' ` , this function will attempt to fit a cubic spline to
 the phased light curve to find a time of light minimum as phase
 0.0 . This kwarg sets the number of knots to generate the spline as a
 fraction of the total number of measurements in the input
 time - series . By default , this is set so that 100 knots are used to
 generate a spline for fitting the phased light curve consisting of 10000
 measurements .
 errs : np . array or None
 If this is provided , contains the measurement errors associated with
 each measurement of flux / mag in time - series . Providing this kwarg will
 add errbars to the output plot .
 magsarefluxes : bool
 Indicates if the input ` mags ` array is actually an array of flux
 measurements instead of magnitude measurements . If this is set to True ,
 then the plot y - axis will be set as appropriate for mag or fluxes .
 normto : { ' globalmedian ' , ' zero ' } or a float
 Sets the normalization target : :
 ' 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 .
 phasewrap : bool
 If this is True , the phased time - series will be wrapped around phase
 0.0.
 phasesort : bool
 If this is True , the phased time - series will be sorted in phase .
 phasebin : float or None
 If this is provided , indicates the bin size to use to group together
 measurements closer than this amount in phase . This is in units of
 phase . The binned phased light curve will be overplotted on top of the
 phased light curve . Useful for when one has many measurement points and
 needs to pick out a small trend in an otherwise noisy phased light
 curve .
 plotphaselim : sequence of two floats or None
 The x - axis limits to use when making the phased light curve plot . By
 default , this is ( - 0.8 , 0.8 ) , which places phase 0.0 at the center of
 the plot and covers approximately two cycles in phase to make any trends
 clear .
 yrange : list of two floats or None
 This is used to provide a custom y - axis range to the plot . If None , will
 automatically determine y - axis range .
 xtimenotphase : bool
 If True , the x - axis gets units of time ( multiplies phase by period ) .
 xaxlabel : str
 Sets the label for the x - axis .
 yaxlabel : str or None
 Sets the label for the y - axis . If this is None , the appropriate label
 will be used based on the value of the ` magsarefluxes ` kwarg .
 modeltimes , modelmags , modelerrs : np . array or None
 If all of these are provided , then this function will overplot the
 values of modeltimes and modelmags on top of the actual phased light
 curve . This is useful for plotting variability models on top of the
 light curve ( e . g . plotting a Mandel - Agol transit model over the actual
 phased light curve . These arrays will be phased using the already
 provided period and epoch .
 outfile : str or StringIO / BytesIO or matplotlib . axes . Axes or None
 - a string filename for the file where the plot will be written .
 - a StringIO / BytesIO object to where the plot will be written .
 - a matplotlib . axes . Axes object to where the plot will be written .
 - if None , plots to ' magseries - phased - plot . png ' in current dir .
 plotdpi : int
 Sets the resolution in DPI for PNG plots ( default = 100 ) .
 Returns
 str or StringIO / BytesIO or matplotlib . axes . Axes
 This returns based on the input :
 - If ` outfile ` is a str or None , the path to the generated plot file is
 returned .
 - If ` outfile ` is a StringIO / BytesIO object , will return the
 StringIO / BytesIO object to which the plot was written .
 - If ` outfile ` is a matplotlib . axes . Axes object , will return the Axes
 object with the plot elements added to it . One can then directly
 include this Axes object in some other Figure .'''

implementation:
# sigclip the magnitude timeseries
stimes , smags , serrs = sigclip_magseries ( times , mags , errs , magsarefluxes = magsarefluxes , sigclip = sigclip )
# check if we need to normalize
if normto is not False :
    stimes , smags = normalize_magseries ( stimes , smags , normto = normto , magsarefluxes = magsarefluxes , mingap = normmingap )
    if ( isinstance ( modelmags , np . ndarray ) and isinstance ( modeltimes , np . ndarray ) ) :
        stimes , smags = normalize_magseries ( modeltimes , modelmags , normto = normto , magsarefluxes = magsarefluxes , mingap = normmingap )
# figure out the epoch , if it ' s None , use the min of the time
if epoch is None :
    epoch = stimes . min ( )
# if the epoch is ' min ' , then fit a spline to the light curve phased
# using the min of the time , find the fit mag minimum and use the time for
# that as the epoch
elif isinstance ( epoch , str ) and epoch == 'min' :
    try :
        spfit = spline_fit_magseries ( stimes , smags , serrs , period , knotfraction = fitknotfrac )
        epoch = spfit [ 'fitinfo' ] [ 'fitepoch' ]
        if len ( epoch ) != 1 :
            epoch = epoch [ 0 ]
    except Exception as e :
        LOGEXCEPTION ( 'spline fit failed, using min(times) as epoch' )
        epoch = npmin ( stimes )
# now phase the data light curve ( and optionally , phase bin the light curve )
if errs is not None :
    phasedlc = phase_magseries_with_errs ( stimes , smags , serrs , period , epoch , wrap = phasewrap , sort = phasesort )
    plotphase = phasedlc [ 'phase' ]
    plotmags = phasedlc [ 'mags' ]
    ploterrs = phasedlc [ 'errs' ]
    # if we ' re supposed to bin the phases , do so
    if phasebin :
        binphasedlc = phase_bin_magseries_with_errs ( plotphase , plotmags , ploterrs , binsize = phasebin )
        binplotphase = binphasedlc [ 'binnedphases' ]
        binplotmags = binphasedlc [ 'binnedmags' ]
        binploterrs = binphasedlc [ 'binnederrs' ]
else :
    phasedlc = phase_magseries ( stimes , smags , period , epoch , wrap = phasewrap , sort = phasesort )
    plotphase = phasedlc [ 'phase' ]
    plotmags = phasedlc [ 'mags' ]
    ploterrs = None
    # if we ' re supposed to bin the phases , do so
    if phasebin :
        binphasedlc = phase_bin_magseries ( plotphase , plotmags , binsize = phasebin )
        binplotphase = binphasedlc [ 'binnedphases' ]
        binplotmags = binphasedlc [ 'binnedmags' ]
        binploterrs = None
# phase the model light curve
modelplotphase , modelplotmags = None , None
if ( isinstance ( modelerrs , np . ndarray ) and isinstance ( modeltimes , np . ndarray ) and isinstance ( modelmags , np . ndarray ) ) :
    modelphasedlc = phase_magseries_with_errs ( modeltimes , modelmags , modelerrs , period , epoch , wrap = phasewrap , sort = phasesort )
    modelplotphase = modelphasedlc [ 'phase' ]
    modelplotmags = modelphasedlc [ 'mags' ]
# note that we never will phase - bin the model ( no point ) .
elif ( not isinstance ( modelerrs , np . ndarray ) and isinstance ( modeltimes , np . ndarray ) and isinstance ( modelmags , np . ndarray ) ) :
    modelphasedlc = phase_magseries ( modeltimes , modelmags , period , epoch , wrap = phasewrap , sort = phasesort )
    modelplotphase = modelphasedlc [ 'phase' ]
    modelplotmags = modelphasedlc [ 'mags' ]
# finally , make the plots
# check if the outfile is actually an Axes object
if isinstance ( outfile , matplotlib . axes . Axes ) :
    ax = outfile
# otherwise , it ' s just a normal file or StringIO / BytesIO
else :
    fig = plt . figure ( )
    fig . set_size_inches ( 7.5 , 4.8 )
    ax = plt . gca ( )
if xtimenotphase :
    plotphase *= period
if phasebin :
    ax . errorbar ( plotphase , plotmags , fmt = 'o' , color = '#B2BEB5' , yerr = ploterrs , markersize = 3.0 , markeredgewidth = 0.0 , ecolor = '#B2BEB5' , capsize = 0 )
    if xtimenotphase :
        binplotphase *= period
    ax . errorbar ( binplotphase , binplotmags , fmt = 'bo' , yerr = binploterrs , markersize = 5.0 , markeredgewidth = 0.0 , ecolor = '#B2BEB5' , capsize = 0 )
else :
    ax . errorbar ( plotphase , plotmags , fmt = 'ko' , yerr = ploterrs , markersize = 3.0 , markeredgewidth = 0.0 , ecolor = '#B2BEB5' , capsize = 0 )
if ( isinstance ( modelplotphase , np . ndarray ) and isinstance ( modelplotmags , np . ndarray ) ) :
    if xtimenotphase :
        modelplotphase *= period
    ax . plot ( modelplotphase , modelplotmags , zorder = 5 , linewidth = 2 , alpha = 0.9 , color = '#181c19' )
# make a grid
ax . grid ( color = '#a9a9a9' , alpha = 0.9 , zorder = 0 , linewidth = 1.0 , linestyle = ':' )
# make lines for phase 0.0 , 0.5 , and - 0.5
ax . axvline ( 0.0 , alpha = 0.9 , linestyle = 'dashed' , color = 'g' )
if not xtimenotphase :
    ax . axvline ( - 0.5 , alpha = 0.9 , linestyle = 'dashed' , color = 'g' )
    ax . axvline ( 0.5 , alpha = 0.9 , linestyle = 'dashed' , color = 'g' )
else :
    ax . axvline ( - period * 0.5 , alpha = 0.9 , linestyle = 'dashed' , color = 'g' )
    ax . axvline ( period * 0.5 , alpha = 0.9 , linestyle = 'dashed' , color = 'g' )
# fix the ticks to use no offsets
ax . get_yaxis ( ) . get_major_formatter ( ) . set_useOffset ( False )
ax . get_xaxis ( ) . get_major_formatter ( ) . set_useOffset ( False )
# get the yrange
if yrange and isinstance ( yrange , ( list , tuple ) ) and len ( yrange ) == 2 :
    ymin , ymax = yrange
else :
    ymin , ymax = ax . get_ylim ( )
# set the y axis labels and range
if not yaxlabel :
    if not magsarefluxes :
        ax . set_ylim ( ymax , ymin )
        yaxlabel = 'magnitude'
    else :
        ax . set_ylim ( ymin , ymax )
        yaxlabel = 'flux'
# set the x axis limit
if not plotphaselim :
    ax . set_xlim ( ( npmin ( plotphase ) - 0.1 , npmax ( plotphase ) + 0.1 ) )
else :
    if xtimenotphase :
        ax . set_xlim ( ( period * plotphaselim [ 0 ] , period * plotphaselim [ 1 ] ) )
    else :
        ax . set_xlim ( ( plotphaselim [ 0 ] , plotphaselim [ 1 ] ) )
# set up the axis labels and plot title
ax . set_xlabel ( xaxlabel )
ax . set_ylabel ( yaxlabel )
ax . set_title ( 'period: %.6f d - epoch: %.6f' % ( period , epoch ) )
LOGINFO ( 'using period: %.6f d and epoch: %.6f' % ( period , epoch ) )
# check if the output filename is actually an instance of StringIO
if sys . version_info [ : 2 ] < ( 3 , 0 ) :
    is_Strio = isinstance ( outfile , cStringIO . InputType )
else :
    is_Strio = isinstance ( outfile , Strio )
# make the figure
if ( outfile and not is_Strio and not isinstance ( outfile , matplotlib . axes . Axes ) ) :
    if outfile . endswith ( '.png' ) :
        fig . savefig ( outfile , bbox_inches = 'tight' , dpi = plotdpi )
    else :
        fig . savefig ( outfile , bbox_inches = 'tight' )
    plt . close ( )
    return period , epoch , os . path . abspath ( outfile )
elif outfile and is_Strio :
    fig . savefig ( outfile , bbox_inches = 'tight' , dpi = plotdpi , format = 'png' )
    return outfile
elif outfile and isinstance ( outfile , matplotlib . axes . Axes ) :
    return outfile
elif not outfile and dispok :
    plt . show ( )
    plt . close ( )
    return period , epoch
else :
    LOGWARNING ( 'no output file specified and no $DISPLAY set, ' 'saving to magseries-phased-plot.png in current directory' )
    outfile = 'magseries-phased-plot.png'
    plt . savefig ( outfile , bbox_inches = 'tight' , dpi = plotdpi )
    plt . close ( )
    return period , epoch , os . path . abspath ( outfile )


signature:
def skyview_stamp ( ra , decl , survey = 'DSS2 Red' , scaling = 'Linear' , flip = True , convolvewith = None , forcefetch = False , cachedir = '~/.astrobase/stamp-cache' , timeout = 10.0 , retry_failed = False , savewcsheader = True , verbose = False ) :
    '''This downloads a DSS FITS stamp centered on the coordinates specified .
 This wraps the function : py : func : ` astrobase . services . skyview . get _ stamp ` ,
 which downloads Digitized Sky Survey stamps in FITS format from the NASA
 SkyView service :
 https : / / skyview . gsfc . nasa . gov / current / cgi / query . pl
 Also adds some useful operations on top of the FITS file returned .
 Parameters
 ra , decl : float
 The center coordinates for the stamp in decimal degrees .
 survey : str
 The survey name to get the stamp from . This is one of the
 values in the ' SkyView Surveys ' option boxes on the SkyView
 webpage . Currently , we ' ve only tested using ' DSS2 Red ' as the value for
 this kwarg , but the other ones should work in principle .
 scaling : str
 This is the pixel value scaling function to use .
 flip : bool
 Will flip the downloaded image top to bottom . This should usually be
 True because matplotlib and FITS have different image coord origin
 conventions . Alternatively , set this to False and use the
 ` origin = ' lower ' ` in any call to ` matplotlib . pyplot . imshow ` when plotting
 this image .
 convolvewith : astropy . convolution Kernel object or None
 If ` convolvewith ` is an astropy . convolution Kernel object from :
 http : / / docs . astropy . org / en / stable / convolution / kernels . html
 then , this function will return the stamp convolved with that
 kernel . This can be useful to see effects of wide - field telescopes ( like
 the HATNet and HATSouth lenses ) degrading the nominal 1 arcsec / px of
 DSS , causing blending of targets and any variability .
 forcefetch : bool
 If True , will disregard any existing cached copies of the stamp already
 downloaded corresponding to the requested center coordinates and
 redownload the FITS from the SkyView service .
 cachedir : str
 This is the path to the astrobase cache directory . All downloaded FITS
 stamps are stored here as . fits . gz files so we can immediately respond
 with the cached copy when a request is made for a coordinate center
 that ' s already been downloaded .
 timeout : float
 Sets the timeout in seconds to wait for a response from the NASA SkyView
 service .
 retry _ failed : bool
 If the initial request to SkyView fails , and this is True , will retry
 until it succeeds .
 savewcsheader : bool
 If this is True , also returns the WCS header of the downloaded FITS
 stamp in addition to the FITS image itself . Useful for projecting object
 coordinates onto image xy coordinates for visualization .
 verbose : bool
 If True , indicates progress .
 Returns
 tuple or array or None
 This returns based on the value of ` savewcsheader ` :
 - If ` savewcsheader = True ` , returns a tuple :
 ( FITS stamp image as a numpy array , FITS header )
 - If ` savewcsheader = False ` , returns only the FITS stamp image as numpy
 array .
 - If the stamp retrieval fails , returns None .'''

implementation:
stampdict = get_stamp ( ra , decl , survey = survey , scaling = scaling , forcefetch = forcefetch , cachedir = cachedir , timeout = timeout , retry_failed = retry_failed , verbose = verbose )
# DONE WITH FETCHING STUFF
if stampdict : # open the frame
    stampfits = pyfits . open ( stampdict [ 'fitsfile' ] )
    header = stampfits [ 0 ] . header
    frame = stampfits [ 0 ] . data
    stampfits . close ( )
    # finally , we can process the frame
    if flip :
        frame = np . flipud ( frame )
    if verbose :
        LOGINFO ( 'fetched stamp successfully for (%.3f, %.3f)' % ( ra , decl ) )
    if convolvewith :
        convolved = aconv . convolve ( frame , convolvewith )
        if savewcsheader :
            return convolved , header
        else :
            return convolved
    else :
        if savewcsheader :
            return frame , header
        else :
            return frame
else :
    LOGERROR ( 'could not fetch the requested stamp for ' 'coords: (%.3f, %.3f) from survey: %s and scaling: %s' % ( ra , decl , survey , scaling ) )
    return None