<EOL>hdulist = pyfits.open(lcfits)<EOL>lchdr, lcdata = hdulist[<NUM_LIT:1>].header, hdulist[<NUM_LIT:1>].data<EOL>lctophdr, lcaperturehdr, lcaperturedata = (hdulist[<NUM_LIT:0>].header,<EOL>hdulist[<NUM_LIT:2>].header,<EOL>hdulist[<NUM_LIT:2>].data)<EOL>hdulist.close()<EOL>hdrinfo = {}<EOL>for key in headerkeys:<EOL><INDENT>if key in lchdr and lchdr[key] is not None:<EOL><INDENT>hdrinfo[key.lower()] = lchdr[key]<EOL><DEDENT>else:<EOL><INDENT>hdrinfo[key.lower()] = None<EOL><DEDENT><DEDENT>ndet = lchdr['<STR_LIT>']<EOL>for key in topkeys:<EOL><INDENT>if key in lctophdr and lctophdr[key] is not None:<EOL><INDENT>hdrinfo[key.lower()] = lctophdr[key]<EOL><DEDENT>else:<EOL><INDENT>hdrinfo[key.lower()] = None<EOL><DEDENT><DEDENT>for key in lcaperturehdr:<EOL><INDENT>if key in lcaperturehdr and lcaperturehdr[key] is not None:<EOL><INDENT>hdrinfo[key.lower()] = lcaperturehdr[key]<EOL><DEDENT>else:<EOL><INDENT>hdrinfo[key.lower()] = None<EOL><DEDENT><DEDENT>if appendto and isinstance(appendto, dict):<EOL><INDENT>lcdict = appendto<EOL>lcdict['<STR_LIT>'].append(hdrinfo['<STR_LIT>'])<EOL>lcdict['<STR_LIT>'].append(hdrinfo['<STR_LIT>'])<EOL>lcdict['<STR_LIT>'].append(hdrinfo['<STR_LIT>'])<EOL>lcdict['<STR_LIT>'].append(hdrinfo['<STR_LIT>'])<EOL>lcdict['<STR_LIT>'].append(hdrinfo['<STR_LIT>'])<EOL>lcdict['<STR_LIT>']['<STR_LIT>'].append(hdrinfo['<STR_LIT>'])<EOL>lcdict['<STR_LIT>']['<STR_LIT>'].append(<EOL>hdrinfo['<STR_LIT>'] + hdrinfo['<STR_LIT>']<EOL>)<EOL>lcdict['<STR_LIT>']['<STR_LIT>'].append(hdrinfo['<STR_LIT>'])<EOL>lcdict['<STR_LIT>']['<STR_LIT>'].append(lcaperturedata)<EOL>lcdict['<STR_LIT>']['<STR_LIT>'].append(hdrinfo['<STR_LIT>'])<EOL>lcdict['<STR_LIT>']['<STR_LIT>'].append(hdrinfo['<STR_LIT>'])<EOL>lcdict['<STR_LIT>']['<STR_LIT>'].append(<EOL>(npabs(hdrinfo['<STR_LIT>']) +<EOL>npabs(hdrinfo['<STR_LIT>']))*<NUM_LIT>/<NUM_LIT><EOL>)<EOL>lcdict['<STR_LIT>']['<STR_LIT>'].append(hdrinfo['<STR_LIT>'])<EOL>lcdict['<STR_LIT>']['<STR_LIT>'].append(hdrinfo['<STR_LIT>'])<EOL>lcdict['<STR_LIT>']['<STR_LIT>'].append(hdrinfo['<STR_LIT>'])<EOL>lcdict['<STR_LIT>']['<STR_LIT>'].append(hdrinfo['<STR_LIT>'])<EOL>lcdict['<STR_LIT>']['<STR_LIT>'].append(ndet)<EOL>lcdict['<STR_LIT>']['<STR_LIT>'].append(hdrinfo['<STR_LIT>'])<EOL>lcdict['<STR_LIT>']['<STR_LIT>'].append(hdrinfo['<STR_LIT>'])<EOL>lcdict['<STR_LIT>']['<STR_LIT>'].append(hdrinfo['<STR_LIT>'])<EOL>lcdict['<STR_LIT>']['<STR_LIT>'].append(hdrinfo['<STR_LIT>'])<EOL>lcdict['<STR_LIT>']['<STR_LIT>'].append(hdrinfo['<STR_LIT>'])<EOL>lcdict['<STR_LIT>']['<STR_LIT>'].append(hdrinfo['<STR_LIT>'])<EOL>lcdict['<STR_LIT>']['<STR_LIT>'].append(hdrinfo['<STR_LIT>'])<EOL>for key in datakeys:<EOL><INDENT>if key.lower() in lcdict:<EOL><INDENT>lcdict[key.lower()] = (<EOL>npconcatenate((lcdict[key.lower()], lcdata[key]))<EOL>)<EOL><DEDENT><DEDENT>for key in sapkeys:<EOL><INDENT>if key.lower() in lcdict['<STR_LIT>']:<EOL><INDENT>sapflux_median = np.nanmedian(lcdata['<STR_LIT>'])<EOL>if normalize and key == '<STR_LIT>':<EOL><INDENT>thislcdata = lcdata[key] / sapflux_median<EOL><DEDENT>elif normalize and key == '<STR_LIT>':<EOL><INDENT>thislcdata = lcdata[key] / sapflux_median<EOL><DEDENT>elif normalize and key == '<STR_LIT>':<EOL><INDENT>thislcdata = lcdata[key] / sapflux_median<EOL><DEDENT>elif normalize and key == '<STR_LIT>':<EOL><INDENT>thislcdata = lcdata[key] / sapflux_median<EOL><DEDENT>else:<EOL><INDENT>thislcdata = lcdata[key]<EOL><DEDENT>lcdict['<STR_LIT>'][key.lower()] = (<EOL>np.concatenate((lcdict['<STR_LIT>'][key.lower()], thislcdata))<EOL>)<EOL><DEDENT><DEDENT>for key in pdckeys:<EOL><INDENT>if key.lower() in lcdict['<STR_LIT>']:<EOL><INDENT>pdcsap_flux_median = np.nanmedian(lcdata['<STR_LIT>'])<EOL>if normalize and key == '<STR_LIT>':<EOL><INDENT>thislcdata = lcdata[key] / pdcsap_flux_median<EOL><DEDENT>elif normalize and key == '<STR_LIT>':<EOL><INDENT>thislcdata = lcdata[key] / pdcsap_flux_median<EOL><DEDENT>else:<EOL><INDENT>thislcdata = lcdata[key]<EOL><DEDENT>lcdict['<STR_LIT>'][key.lower()] = (<EOL>np.concatenate((lcdict['<STR_LIT>'][key.lower()], thislcdata))<EOL>)<EOL><DEDENT><DEDENT>lcdict['<STR_LIT>'] = npconcatenate(<EOL>(lcdict['<STR_LIT>'],<EOL>npfull_like(lcdata['<STR_LIT>'],<EOL>hdrinfo['<STR_LIT>']))<EOL>)<EOL>lcdict['<STR_LIT>'] = npconcatenate(<EOL>(lcdict['<STR_LIT>'],<EOL>npfull_like(lcdata['<STR_LIT>'],<EOL>hdrinfo['<STR_LIT>']))<EOL>)<EOL>lcdict['<STR_LIT>'] = npconcatenate(<EOL>(lcdict['<STR_LIT>'],<EOL>npfull_like(lcdata['<STR_LIT>'],<EOL>hdrinfo['<STR_LIT>']))<EOL>)<EOL>lcdict['<STR_LIT>'] = npconcatenate(<EOL>(lcdict['<STR_LIT>'],<EOL>npfull_like(lcdata['<STR_LIT>'],<EOL>hdrinfo['<STR_LIT>']))<EOL>)<EOL>lcdict['<STR_LIT>'] = npconcatenate(<EOL>(lcdict['<STR_LIT>'],<EOL>npfull_like(lcdata['<STR_LIT>'],<EOL>hdrinfo['<STR_LIT>']))<EOL>)<EOL>lcdict['<STR_LIT>'] = npconcatenate(<EOL>(lcdict['<STR_LIT>'],<EOL>npfull_like(lcdata['<STR_LIT>'],<EOL>hdrinfo['<STR_LIT>']))<EOL>)<EOL>lcdict['<STR_LIT>'] = npconcatenate(<EOL>(lcdict['<STR_LIT>'],<EOL>npfull_like(lcdata['<STR_LIT>'],<EOL>hdrinfo['<STR_LIT>']))<EOL>)<EOL><DEDENT>else:<EOL><INDENT>lcdict = {<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],  <EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':hdrinfo['<STR_LIT:object>'],<EOL>'<STR_LIT>':{<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>'] + hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[lcaperturedata],<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[(npabs(hdrinfo['<STR_LIT>']) +<EOL>npabs(hdrinfo['<STR_LIT>']))*<NUM_LIT>/<NUM_LIT>],<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[ndet],<EOL>},<EOL>'<STR_LIT>':{<EOL>'<STR_LIT>':hdrinfo['<STR_LIT:object>'],  <EOL>'<STR_LIT>':hdrinfo['<STR_LIT>'],<EOL>'<STR_LIT>':hdrinfo['<STR_LIT>'],<EOL>'<STR_LIT>':hdrinfo['<STR_LIT>'],<EOL>'<STR_LIT>':hdrinfo['<STR_LIT>'],<EOL>'<STR_LIT>':hdrinfo['<STR_LIT>'],<EOL>'<STR_LIT>':hdrinfo['<STR_LIT>'],<EOL>'<STR_LIT>':hdrinfo['<STR_LIT>'],<EOL>'<STR_LIT>':hdrinfo['<STR_LIT>'],<EOL>'<STR_LIT>':hdrinfo['<STR_LIT>'],<EOL>'<STR_LIT>':hdrinfo['<STR_LIT>'],<EOL>'<STR_LIT>':hdrinfo['<STR_LIT>'],<EOL>'<STR_LIT>':hdrinfo['<STR_LIT>'],<EOL>'<STR_LIT>':hdrinfo['<STR_LIT>'],<EOL>'<STR_LIT>':hdrinfo['<STR_LIT>'],<EOL>'<STR_LIT>':hdrinfo['<STR_LIT>'],<EOL>'<STR_LIT>':hdrinfo['<STR_LIT>'],<EOL>'<STR_LIT>':hdrinfo['<STR_LIT>'],<EOL>'<STR_LIT>':hdrinfo['<STR_LIT>'],<EOL>},<EOL>'<STR_LIT>':{<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>},<EOL>'<STR_LIT>':{},<EOL>'<STR_LIT>':{},<EOL>}<EOL>for key in datakeys:<EOL><INDENT>lcdict[key.lower()] = lcdata[key]<EOL><DEDENT>for key in sapkeys:<EOL><INDENT>lcdict['<STR_LIT>'][key.lower()] = lcdata[key]<EOL><DEDENT>for key in pdckeys:<EOL><INDENT>lcdict['<STR_LIT>'][key.lower()] = lcdata[key]<EOL><DEDENT>lcdict['<STR_LIT>'] = npfull_like(lcdict['<STR_LIT:time>'],<EOL>lcdict['<STR_LIT>']['<STR_LIT>'][<NUM_LIT:0>])<EOL>lcdict['<STR_LIT>'] = npfull_like(lcdict['<STR_LIT:time>'],<EOL>lcdict['<STR_LIT>']['<STR_LIT>'][<NUM_LIT:0>])<EOL>lcdict['<STR_LIT>'] = npfull_like(lcdict['<STR_LIT:time>'],<EOL>lcdict['<STR_LIT>']['<STR_LIT>'][<NUM_LIT:0>])<EOL>lcdict['<STR_LIT>'] = npfull_like(lcdict['<STR_LIT:time>'],<EOL>lcdict['<STR_LIT>']['<STR_LIT>'][<NUM_LIT:0>])<EOL>lcdict['<STR_LIT>'] = npfull_like(lcdict['<STR_LIT:time>'],<EOL>lcdict['<STR_LIT>'][<NUM_LIT:0>])<EOL>lcdict['<STR_LIT>'] = npfull_like(lcdict['<STR_LIT:time>'],<EOL>lcdict['<STR_LIT>'][<NUM_LIT:0>])<EOL>lcdict['<STR_LIT>'] = npfull_like(lcdict['<STR_LIT:time>'],<EOL>lcdict['<STR_LIT>'][<NUM_LIT:0>])<EOL>if normalize:<EOL><INDENT>sapflux_median = np.nanmedian(lcdict['<STR_LIT>']['<STR_LIT>'])<EOL>pdcsap_flux_median = np.nanmedian(lcdict['<STR_LIT>']['<STR_LIT>'])<EOL>lcdict['<STR_LIT>']['<STR_LIT>'] = (<EOL>lcdict['<STR_LIT>']['<STR_LIT>'] /<EOL>sapflux_median<EOL>)<EOL>lcdict['<STR_LIT>']['<STR_LIT>'] = (<EOL>lcdict['<STR_LIT>']['<STR_LIT>'] /<EOL>sapflux_median<EOL>)<EOL>lcdict['<STR_LIT>']['<STR_LIT>'] = (<EOL>lcdict['<STR_LIT>']['<STR_LIT>'] /<EOL>sapflux_median<EOL>)<EOL>lcdict['<STR_LIT>']['<STR_LIT>'] = (<EOL>lcdict['<STR_LIT>']['<STR_LIT>'] /<EOL>sapflux_median<EOL>)<EOL>lcdict['<STR_LIT>']['<STR_LIT>'] = (<EOL>lcdict['<STR_LIT>']['<STR_LIT>'] /<EOL>pdcsap_flux_median<EOL>)<EOL>lcdict['<STR_LIT>']['<STR_LIT>'] = (<EOL>lcdict['<STR_LIT>']['<STR_LIT>'] /<EOL>pdcsap_flux_median<EOL>)<EOL><DEDENT><DEDENT>lcdict['<STR_LIT>'] = (<EOL>[x.lower() for x in datakeys] +<EOL>['<STR_LIT>' % x.lower() for x in sapkeys] +<EOL>['<STR_LIT>' % x.lower() for x in pdckeys] +<EOL>['<STR_LIT>','<STR_LIT>','<STR_LIT>',<EOL>'<STR_LIT>','<STR_LIT>','<STR_LIT>']<EOL>)<EOL>return lcdict<EOL>

This extracts the light curve from a single Kepler or K2 LC FITS file.

    This works on the light curves available at MAST:

    - `kplr{kepid}-{somedatething}_llc.fits` files from the Kepler mission
    - `ktwo{epicid}-c{campaign}_llc.fits` files from the K2 mission

    Parameters
    ----------

    lcfits : str
        The filename of a MAST Kepler/K2 light curve FITS file.

    headerkeys : list
        A list of FITS header keys that will be extracted from the FITS light
        curve file. These describe the observations. The default value for this
        is given in `LCHEADERKEYS` above.

    datakeys : list
        A list of FITS column names that correspond to the auxiliary
        measurements in the light curve. The default is `LCDATAKEYS` above.

    sapkeys : list
        A list of FITS column names that correspond to the SAP flux
        measurements in the light curve. The default is `LCSAPKEYS` above.

    pdckeys : list
        A list of FITS column names that correspond to the PDC flux
        measurements in the light curve. The default is `LCPDCKEYS` above.

    topkeys : list
        A list of FITS header keys that describe the object in the light
        curve. The default is `LCTOPKEYS` above.

    apkeys : list
        A list of FITS header keys that describe the flux measurement apertures
        used by the Kepler/K2 pipeline. The default is `LCAPERTUREKEYS` above.

    appendto : lcdict or None
        If appendto is an `lcdict`, will append measurements of this `lcdict` to
        that `lcdict`. This is used for consolidating light curves for the same
        object across different files (quarters). The appending does not care
        about the time order. To consolidate light curves in time order, use
        `consolidate_kepler_fitslc` below.

    normalize : bool
        If True, then each component light curve's SAP_FLUX and PDCSAP_FLUX
        measurements will be normalized to 1.0 by dividing out the median flux
        for the component light curve.

    Returns
    -------

    lcdict
        Returns an `lcdict` (this is useable by most astrobase functions for LC
        processing).


LOGINFO('<STR_LIT>' % (lcfitsdir,<EOL>keplerid))<EOL>if sys.version_info[:<NUM_LIT:2>] > (<NUM_LIT:3>,<NUM_LIT:4>):<EOL><INDENT>matching = glob.glob(os.path.join(lcfitsdir,<EOL>'<STR_LIT>',<EOL>'<STR_LIT>' % keplerid),<EOL>recursive=True)<EOL>LOGINFO('<STR_LIT>' % (len(matching), repr(matching)))<EOL><DEDENT>else:<EOL><INDENT>walker = os.walk(lcfitsdir)<EOL>matching = []<EOL>for root, dirs, _files in walker:<EOL><INDENT>for sdir in dirs:<EOL><INDENT>searchpath = os.path.join(root,<EOL>sdir,<EOL>'<STR_LIT>' % keplerid)<EOL>foundfiles = glob.glob(searchpath)<EOL>if foundfiles:<EOL><INDENT>matching.extend(foundfiles)<EOL>LOGINFO('<STR_LIT>' % (repr(foundfiles),<EOL>os.path.join(root,sdir)))<EOL><DEDENT><DEDENT><DEDENT><DEDENT>if len(matching) > <NUM_LIT:0>:<EOL><INDENT>LOGINFO('<STR_LIT>')<EOL>consolidated = read_kepler_fitslc(matching[<NUM_LIT:0>],<EOL>headerkeys=headerkeys,<EOL>datakeys=datakeys,<EOL>sapkeys=sapkeys,<EOL>pdckeys=pdckeys,<EOL>topkeys=topkeys,<EOL>apkeys=apkeys,<EOL>normalize=normalize)<EOL>for lcf in matching:<EOL><INDENT>consolidated = read_kepler_fitslc(lcf,<EOL>appendto=consolidated,<EOL>headerkeys=headerkeys,<EOL>datakeys=datakeys,<EOL>sapkeys=sapkeys,<EOL>pdckeys=pdckeys,<EOL>topkeys=topkeys,<EOL>apkeys=apkeys,<EOL>normalize=normalize)<EOL><DEDENT>LOGINFO('<STR_LIT>')<EOL>finiteind = npisfinite(consolidated['<STR_LIT:time>'])<EOL>if npsum(finiteind) < consolidated['<STR_LIT:time>'].size:<EOL><INDENT>LOGWARNING('<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>')<EOL><DEDENT>column_sort_ind = npargsort(consolidated['<STR_LIT:time>'])<EOL>for col in consolidated['<STR_LIT>']:<EOL><INDENT>if '<STR_LIT:.>' in col:<EOL><INDENT>key, subkey = col.split('<STR_LIT:.>')<EOL>consolidated[key][subkey] = (<EOL>consolidated[key][subkey][column_sort_ind]<EOL>)<EOL><DEDENT>else:<EOL><INDENT>consolidated[col] = consolidated[col][column_sort_ind]<EOL><DEDENT><DEDENT>header_sort_ind = npargsort(consolidated['<STR_LIT>']).tolist()<EOL>for key in ('<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>'):<EOL><INDENT>consolidated[key] = (<EOL>nparray(consolidated[key])[header_sort_ind].tolist()<EOL>)<EOL><DEDENT>for key in ('<STR_LIT>','<STR_LIT>','<STR_LIT>','<STR_LIT>',<EOL>'<STR_LIT>','<STR_LIT>','<STR_LIT>',<EOL>'<STR_LIT>','<STR_LIT>','<STR_LIT>','<STR_LIT>','<STR_LIT>'):<EOL><INDENT>consolidated['<STR_LIT>'][key] = (<EOL>nparray(consolidated['<STR_LIT>'][key])[header_sort_ind].tolist()<EOL>)<EOL><DEDENT>for key in ('<STR_LIT>','<STR_LIT>','<STR_LIT>','<STR_LIT>','<STR_LIT>',<EOL>'<STR_LIT>','<STR_LIT>'):<EOL><INDENT>consolidated['<STR_LIT>'][key] = (<EOL>nparray(consolidated['<STR_LIT>'][key])[header_sort_ind].tolist()<EOL>)<EOL><DEDENT>return consolidated<EOL><DEDENT>else:<EOL><INDENT>LOGERROR('<STR_LIT>'<EOL>'<STR_LIT>' % (keplerid,<EOL>lcfitsdir))<EOL>return None<EOL><DEDENT>

This gets all Kepler/K2 light curves for the given `keplerid`
    in `lcfitsdir`.

    Searches recursively in `lcfitsdir` for all of the files belonging to the
    specified `keplerid`. Sorts the light curves by time. Returns an
    `lcdict`. This is meant to be used to consolidate light curves for a single
    object across Kepler quarters.

    NOTE: `keplerid` is an integer (without the leading zeros). This is usually
    the KIC ID.

    NOTE: if light curve time arrays contain `nans`, these and their associated
    measurements will be sorted to the end of the final combined arrays.

    Parameters
    ----------

    keplerid : int
        The Kepler ID of the object to consolidate LCs for, as an integer
        without any leading zeros. This is usually the KIC or EPIC ID.

    lcfitsdir : str
        The directory to look in for LCs of the specified object.

    normalize : bool
        If True, then each component light curve's SAP_FLUX and PDCSAP_FLUX
        measurements will be normalized to 1.0 by dividing out the median flux
        for the component light curve.

    headerkeys : list
        A list of FITS header keys that will be extracted from the FITS light
        curve file. These describe the observations. The default value for this
        is given in `LCHEADERKEYS` above.

    datakeys : list
        A list of FITS column names that correspond to the auxiliary
        measurements in the light curve. The default is `LCDATAKEYS` above.

    sapkeys : list
        A list of FITS column names that correspond to the SAP flux
        measurements in the light curve. The default is `LCSAPKEYS` above.

    pdckeys : list
        A list of FITS column names that correspond to the PDC flux
        measurements in the light curve. The default is `LCPDCKEYS` above.

    topkeys : list
        A list of FITS header keys that describe the object in the light
        curve. The default is `LCTOPKEYS` above.

    apkeys : list
        A list of FITS header keys that describe the flux measurement apertures
        used by the Kepler/K2 pipeline. The default is `LCAPERTUREKEYS` above.

    Returns
    -------

    lcdict
        Returns an `lcdict` (this is useable by most astrobase functions for LC
        processing).


<EOL>hdulist = pyfits.open(lcfits)<EOL>lchdr, lcdata = hdulist[<NUM_LIT:1>].header, hdulist[<NUM_LIT:1>].data<EOL>lctophdr = hdulist[<NUM_LIT:0>].header<EOL>hdulist.close()<EOL>hdrinfo = {}<EOL>ndet = lchdr['<STR_LIT>']<EOL>for key in SFFTOPKEYS:<EOL><INDENT>if key in lctophdr and lctophdr[key] is not None:<EOL><INDENT>hdrinfo[key.lower()] = lctophdr[key]<EOL><DEDENT>else:<EOL><INDENT>hdrinfo[key.lower()] = None<EOL><DEDENT><DEDENT>for key in SFFHEADERKEYS:<EOL><INDENT>if key in lchdr and lchdr[key] is not None:<EOL><INDENT>hdrinfo[key.lower()] = lchdr[key]<EOL><DEDENT>else:<EOL><INDENT>hdrinfo[key.lower()] = None<EOL><DEDENT><DEDENT>lcdict = {<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':hdrinfo['<STR_LIT:object>'],<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':{<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>'] + hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[None],<EOL>'<STR_LIT>':[None],<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[ndet],<EOL>},<EOL>'<STR_LIT>':{<EOL>'<STR_LIT>':hdrinfo['<STR_LIT>'],<EOL>'<STR_LIT>':hdrinfo['<STR_LIT>'],<EOL>'<STR_LIT>':hdrinfo['<STR_LIT>'],<EOL>'<STR_LIT>':hdrinfo['<STR_LIT>'],<EOL>'<STR_LIT>':hdrinfo['<STR_LIT>'],<EOL>'<STR_LIT>':hdrinfo['<STR_LIT>'],<EOL>'<STR_LIT>':hdrinfo['<STR_LIT>'],<EOL>'<STR_LIT>':hdrinfo['<STR_LIT>'],<EOL>'<STR_LIT>':hdrinfo['<STR_LIT>'],<EOL>'<STR_LIT>':hdrinfo['<STR_LIT>'],<EOL>'<STR_LIT>':hdrinfo['<STR_LIT>'],<EOL>'<STR_LIT>':hdrinfo['<STR_LIT>'],<EOL>'<STR_LIT>':hdrinfo['<STR_LIT>'],<EOL>'<STR_LIT>':hdrinfo['<STR_LIT>'],<EOL>'<STR_LIT>':hdrinfo['<STR_LIT>'],<EOL>'<STR_LIT>':hdrinfo['<STR_LIT>'],<EOL>'<STR_LIT>':hdrinfo['<STR_LIT>'],<EOL>'<STR_LIT>':hdrinfo['<STR_LIT>'],<EOL>},<EOL>'<STR_LIT>':{<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>'<STR_LIT>':[hdrinfo['<STR_LIT>']],<EOL>},<EOL>}<EOL>for key in SFFDATAKEYS:<EOL><INDENT>lcdict[key.lower()] = lcdata[key]<EOL><DEDENT>lcdict['<STR_LIT>'] = npfull_like(lcdict['<STR_LIT:t>'],<EOL>lcdict['<STR_LIT>']['<STR_LIT>'][<NUM_LIT:0>])<EOL>lcdict['<STR_LIT>'] = npfull_like(lcdict['<STR_LIT:t>'],<EOL>lcdict['<STR_LIT>']['<STR_LIT>'][<NUM_LIT:0>])<EOL>lcdict['<STR_LIT>'] = npfull_like(lcdict['<STR_LIT:t>'],<EOL>lcdict['<STR_LIT>']['<STR_LIT>'][<NUM_LIT:0>])<EOL>lcdict['<STR_LIT>'] = npfull_like(lcdict['<STR_LIT:t>'],<EOL>lcdict['<STR_LIT>']['<STR_LIT>'][<NUM_LIT:0>])<EOL>lcdict['<STR_LIT>'] = npfull_like(lcdict['<STR_LIT:t>'],<EOL>lcdict['<STR_LIT>'][<NUM_LIT:0>])<EOL>lcdict['<STR_LIT>'] = npfull_like(lcdict['<STR_LIT:t>'],<EOL>lcdict['<STR_LIT>'][<NUM_LIT:0>])<EOL>lcdict['<STR_LIT>'] = npfull_like(lcdict['<STR_LIT:t>'],<EOL>lcdict['<STR_LIT>'][<NUM_LIT:0>])<EOL>lcdict['<STR_LIT>'] = (<EOL>[x.lower() for x in SFFDATAKEYS] +<EOL>['<STR_LIT>','<STR_LIT>','<STR_LIT>','<STR_LIT>','<STR_LIT>','<STR_LIT>','<STR_LIT>']<EOL>)<EOL>return lcdict<EOL>

This reads a K2 SFF (Vandenberg+ 2014) light curve into an `lcdict`.

    Use this with the light curves from the K2 SFF project at MAST.

    Parameters
    ----------

    lcfits : str
        The filename of the FITS light curve file downloaded from MAST.

    Returns
    -------

    lcdict
        Returns an `lcdict` (this is useable by most astrobase functions for LC
        processing).


if not outfile:<EOL><INDENT>outfile = '<STR_LIT>' % lcdict['<STR_LIT>'].replace('<STR_LIT:U+0020>','<STR_LIT:->')<EOL><DEDENT>with open(outfile,'<STR_LIT:wb>') as outfd:<EOL><INDENT>pickle.dump(lcdict, outfd, protocol=pickle.HIGHEST_PROTOCOL)<EOL><DEDENT>return os.path.abspath(outfile)<EOL>

This writes the `lcdict` to a Python pickle.

    Parameters
    ----------

    lcdict : lcdict
        This is the input `lcdict` to write to a pickle.

    outfile : str or None
        If this is None, the object's Kepler ID/EPIC ID will determined from the
        `lcdict` and used to form the filename of the output pickle file. If
        this is a `str`, the provided filename will be used.

    Returns
    -------

    str
        The absolute path to the written pickle file.


if picklefile.endswith('<STR_LIT>'):<EOL><INDENT>infd = gzip.open(picklefile, '<STR_LIT:rb>')<EOL><DEDENT>else:<EOL><INDENT>infd = open(picklefile, '<STR_LIT:rb>')<EOL><DEDENT>try:<EOL><INDENT>with infd:<EOL><INDENT>lcdict = pickle.load(infd)<EOL><DEDENT><DEDENT>except UnicodeDecodeError:<EOL><INDENT>with open(picklefile,'<STR_LIT:rb>') as infd:<EOL><INDENT>lcdict = pickle.load(infd, encoding='<STR_LIT>')<EOL><DEDENT>LOGWARNING('<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>' % picklefile)<EOL><DEDENT>return lcdict<EOL>

This turns the pickled lightcurve file back into an `lcdict`.

    Parameters
    ----------

    picklefile : str
        The path to a previously written Kepler LC picklefile generated by
        `kepler_lcdict_to_pkl` above.

    Returns
    -------

    lcdict
        Returns an `lcdict` (this is useable by most astrobase functions for LC
        processing).


This stitches Kepler light curves together across quarters.

    FIXME: implement this.

    Parameters
    ----------

    lcdict : lcdict
        An `lcdict` produced by `consolidate_kepler_fitslc`. The flux
        measurements between quarters will be stitched together.

    Returns
    -------

    lcdict
        Returns an `lcdict` (this is useable by most astrobase functions for LC
        processing). The flux measurements will have been shifted to form a
        seamless light curve across quarters suitable for long-term variability
        investigation.


cols = lcdict['<STR_LIT>']<EOL>if filterflags:<EOL><INDENT>nbefore = lcdict['<STR_LIT:time>'].size<EOL>filterind = lcdict['<STR_LIT>'] == <NUM_LIT:0><EOL>for col in cols:<EOL><INDENT>if '<STR_LIT:.>' in col:<EOL><INDENT>key, subkey = col.split('<STR_LIT:.>')<EOL>lcdict[key][subkey] = lcdict[key][subkey][filterind]<EOL><DEDENT>else:<EOL><INDENT>lcdict[col] = lcdict[col][filterind]<EOL><DEDENT><DEDENT>nafter = lcdict['<STR_LIT:time>'].size<EOL>LOGINFO('<STR_LIT>'<EOL>% (nbefore, nafter))<EOL><DEDENT>if nanfilter and nanfilter == '<STR_LIT>':<EOL><INDENT>notnanind = (<EOL>npisfinite(lcdict['<STR_LIT>']['<STR_LIT>']) &<EOL>npisfinite(lcdict['<STR_LIT>']['<STR_LIT>']) &<EOL>npisfinite(lcdict['<STR_LIT:time>'])<EOL>)<EOL><DEDENT>elif nanfilter and nanfilter == '<STR_LIT>':<EOL><INDENT>notnanind = (<EOL>npisfinite(lcdict['<STR_LIT>']['<STR_LIT>']) &<EOL>npisfinite(lcdict['<STR_LIT:time>'])<EOL>)<EOL><DEDENT>elif nanfilter and nanfilter == '<STR_LIT>':<EOL><INDENT>notnanind = (<EOL>npisfinite(lcdict['<STR_LIT>']['<STR_LIT>']) &<EOL>npisfinite(lcdict['<STR_LIT:time>'])<EOL>)<EOL><DEDENT>if nanfilter:<EOL><INDENT>nbefore = lcdict['<STR_LIT:time>'].size<EOL>for col in cols:<EOL><INDENT>if '<STR_LIT:.>' in col:<EOL><INDENT>key, subkey = col.split('<STR_LIT:.>')<EOL>lcdict[key][subkey] = lcdict[key][subkey][notnanind]<EOL><DEDENT>else:<EOL><INDENT>lcdict[col] = lcdict[col][notnanind]<EOL><DEDENT><DEDENT>nafter = lcdict['<STR_LIT:time>'].size<EOL>LOGINFO('<STR_LIT>'<EOL>% (nbefore, nafter))<EOL><DEDENT>if (timestoignore and<EOL>isinstance(timestoignore, list) and<EOL>len(timestoignore) > <NUM_LIT:0>):<EOL><INDENT>exclind = npfull_like(lcdict['<STR_LIT:time>'], True, dtype=np.bool_)<EOL>nbefore = exclind.size<EOL>for ignoretime in timestoignore:<EOL><INDENT>time0, time1 = ignoretime[<NUM_LIT:0>], ignoretime[<NUM_LIT:1>]<EOL>thismask = ~((lcdict['<STR_LIT:time>'] >= time0) & (lcdict['<STR_LIT:time>'] <= time1))<EOL>exclind = exclind & thismask<EOL><DEDENT>for col in cols:<EOL><INDENT>if '<STR_LIT:.>' in col:<EOL><INDENT>key, subkey = col.split('<STR_LIT:.>')<EOL>lcdict[key][subkey] = lcdict[key][subkey][exclind]<EOL><DEDENT>else:<EOL><INDENT>lcdict[col] = lcdict[col][exclind]<EOL><DEDENT><DEDENT>nafter = lcdict['<STR_LIT:time>'].size<EOL>LOGINFO('<STR_LIT>'<EOL>% (nbefore, nafter))<EOL><DEDENT>return lcdict<EOL>

This filters the Kepler `lcdict`, removing nans and bad
    observations.

    By default, this function removes points in the Kepler LC that have ANY
    quality flags set.

    Parameters
    ----------

    lcdict : lcdict
        An `lcdict` produced by `consolidate_kepler_fitslc` or
        `read_kepler_fitslc`.

    filterflags : bool
        If True, will remove any measurements that have non-zero quality flags
        present. This usually indicates an issue with the instrument or
        spacecraft.

    nanfilter : {'sap','pdc','sap,pdc'}
        Indicates the flux measurement type(s) to apply the filtering to.

    timestoignore : list of tuples or None
        This is of the form::

            [(time1_start, time1_end), (time2_start, time2_end), ...]

        and indicates the start and end times to mask out of the final
        lcdict. Use this to remove anything that wasn't caught by the quality
        flags.

    Returns
    -------

    lcdict
        Returns an `lcdict` (this is useable by most astrobase functions for LC
        processing). The `lcdict` is filtered IN PLACE!


def _epd_function(coeffs, fluxes, xcc, ycc, bgv, bge):

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

This is the EPD function to fit.

    Parameters
    ----------

    coeffs : array-like of floats
        Contains the EPD coefficients that will be used to generate the EPD fit
        function.

    fluxes : array-like
        The flux measurement array being used.

    xcc,ycc : array-like
        Arrays of the x and y coordinates associated with each measurement in
        `fluxes`.

    bgv,bge : array-like
        Arrays of the flux background value and the flux background error
        associated with each measurement in `fluxes`.

    Returns
    -------

    np.array
        Contains the fit function evaluated at each flux measurement value.


def _epd_residual(coeffs, fluxes, xcc, ycc, bgv, bge):

f = _epd_function(coeffs, fluxes, xcc, ycc, bgv, bge)<EOL>residual = fluxes - f<EOL>return residual<EOL>

This is the residual function to minimize using scipy.optimize.leastsq.

    Parameters
    ----------

    coeffs : array-like of floats
        Contains the EPD coefficients that will be used to generate the EPD fit
        function.

    fluxes : array-like
        The flux measurement array being used.

    xcc,ycc : array-like
        Arrays of the x and y coordinates associated with each measurement in
        `fluxes`.

    bgv,bge : array-like
        Arrays of the flux background value and the flux background error
        associated with each measurement in `fluxes`.

    Returns
    -------

    np.array
        Contains the fit function residual evaluated at each flux measurement
        value.


times, fluxes, background, background_err = (lcdict['<STR_LIT:time>'],<EOL>lcdict['<STR_LIT>']['<STR_LIT>'],<EOL>lcdict['<STR_LIT>']['<STR_LIT>'],<EOL>lcdict['<STR_LIT>']['<STR_LIT>'])<EOL>xcc = lcdict[xccol]<EOL>ycc = lcdict[yccol]<EOL>flags = lcdict['<STR_LIT>']<EOL>if filterflags:<EOL><INDENT>nbefore = times.size<EOL>filterind = flags == <NUM_LIT:0><EOL>times = times[filterind]<EOL>fluxes = fluxes[filterind]<EOL>background = background[filterind]<EOL>background_err = background_err[filterind]<EOL>xcc = xcc[filterind]<EOL>ycc = ycc[filterind]<EOL>flags = flags[filterind]<EOL>nafter = times.size<EOL>LOGINFO('<STR_LIT>'<EOL>% (nbefore, nafter))<EOL><DEDENT>find = (npisfinite(xcc) & npisfinite(ycc) &<EOL>npisfinite(times) & npisfinite(fluxes) &<EOL>npisfinite(background) & npisfinite(background_err))<EOL>nbefore = times.size<EOL>times = times[find]<EOL>fluxes = fluxes[find]<EOL>background = background[find]<EOL>background_err = background_err[find]<EOL>xcc = xcc[find]<EOL>ycc = ycc[find]<EOL>flags = flags[find]<EOL>nafter = times.size<EOL>LOGINFO('<STR_LIT>'<EOL>% (nbefore, nafter))<EOL>if (timestoignore and<EOL>isinstance(timestoignore, list) and<EOL>len(timestoignore) > <NUM_LIT:0>):<EOL><INDENT>exclind = npfull_like(times,True)<EOL>nbefore = times.size<EOL>for ignoretime in timestoignore:<EOL><INDENT>time0, time1 = ignoretime[<NUM_LIT:0>], ignoretime[<NUM_LIT:1>]<EOL>thismask = (times > time0) & (times < time1)<EOL>exclind = exclind & thismask<EOL><DEDENT>times = times[exclind]<EOL>fluxes = fluxes[exclind]<EOL>background = background[exclind]<EOL>background_err = background_err[exclind]<EOL>xcc = xcc[exclind]<EOL>ycc = ycc[exclind]<EOL>flags = flags[exclind]<EOL>nafter = times.size<EOL>LOGINFO('<STR_LIT>'<EOL>% (nbefore, nafter))<EOL><DEDENT>smoothedfluxes = median_filter(fluxes, size=epdsmooth)<EOL>initcoeffs = npones(<NUM_LIT:11>)<EOL>leastsqfit = leastsq(_epd_residual,<EOL>initcoeffs,<EOL>args=(smoothedfluxes,<EOL>xcc, ycc,<EOL>background, background_err))<EOL>if leastsqfit[-<NUM_LIT:1>] in (<NUM_LIT:1>,<NUM_LIT:2>,<NUM_LIT:3>,<NUM_LIT:4>):<EOL><INDENT>fitcoeffs = leastsqfit[<NUM_LIT:0>]<EOL>epdfit = _epd_function(fitcoeffs,<EOL>fluxes,<EOL>xcc,<EOL>ycc,<EOL>background,<EOL>background_err)<EOL>epdfluxes = npmedian(fluxes) + fluxes - epdfit<EOL>if writetodict:<EOL><INDENT>lcdict['<STR_LIT>'] = {}<EOL>lcdict['<STR_LIT>']['<STR_LIT:time>'] = times<EOL>lcdict['<STR_LIT>']['<STR_LIT>'] = fluxes<EOL>lcdict['<STR_LIT>']['<STR_LIT>'] = epdfluxes<EOL>lcdict['<STR_LIT>']['<STR_LIT>'] = epdfit<EOL>lcdict['<STR_LIT>']['<STR_LIT>'] = background<EOL>lcdict['<STR_LIT>']['<STR_LIT>'] = background_err<EOL>lcdict['<STR_LIT>']['<STR_LIT>'] = xcc<EOL>lcdict['<STR_LIT>']['<STR_LIT>'] = ycc<EOL>lcdict['<STR_LIT>']['<STR_LIT>'] = flags<EOL>for newcol in ['<STR_LIT>','<STR_LIT>',<EOL>'<STR_LIT>','<STR_LIT>',<EOL>'<STR_LIT>','<STR_LIT>',<EOL>'<STR_LIT>','<STR_LIT>',<EOL>'<STR_LIT>']:<EOL><INDENT>if newcol not in lcdict['<STR_LIT>']:<EOL><INDENT>lcdict['<STR_LIT>'].append(newcol)<EOL><DEDENT><DEDENT><DEDENT>return times, epdfluxes, fitcoeffs, epdfit<EOL><DEDENT>else:<EOL><INDENT>LOGERROR('<STR_LIT>')<EOL>return None, None, None, None<EOL><DEDENT>

This runs EPD on the Kepler light curve.

    Following Huang et al. 2015, we fit the following EPD function to a smoothed
    light curve, and then subtract it to obtain EPD corrected magnitudes::

        f = c0 +
            c1*sin(2*pi*x) + c2*cos(2*pi*x) + c3*sin(2*pi*y) + c4*cos(2*pi*y) +
            c5*sin(4*pi*x) + c6*cos(4*pi*x) + c7*sin(4*pi*y) + c8*cos(4*pi*y) +
            c9*bgv + c10*bge

    By default, this function removes points in the Kepler LC that have ANY
    quality flags set.

    Parameters
    ----------

    lcdict : lcdict
        An `lcdict` produced by `consolidate_kepler_fitslc` or
        `read_kepler_fitslc`.

    xcol,ycol : str
        Indicates the x and y coordinate column names to use from the Kepler LC
        in the EPD fit.

    timestoignore : list of tuples
        This is of the form::

            [(time1_start, time1_end), (time2_start, time2_end), ...]

        and indicates the start and end times to mask out of the final
        lcdict. Use this to remove anything that wasn't caught by the quality
        flags.

    filterflags : bool
        If True, will remove any measurements that have non-zero quality flags
        present. This usually indicates an issue with the instrument or
        spacecraft.

    writetodict : bool
        If writetodict is True, adds the following columns to the lcdict::

            epd_time = time array
            epd_sapflux = uncorrected flux before EPD
            epd_epdsapflux = corrected flux after EPD
            epd_epdsapcorr = EPD flux corrections
            epd_bkg = background array
            epd_bkg_err = background errors array
            epd_xcc = xcoord array
            epd_ycc = ycoord array
            epd_quality = quality flag array

        and updates the 'columns' list in the lcdict as well.

    epdsmooth : int
        Sets the number of light curve points to smooth over when generating the
        EPD fit function.

    Returns
    -------

    tuple
        Returns a tuple of the form: (times, epdfluxes, fitcoeffs, epdfit)


times, fluxes, background, background_err = (<EOL>lcdict['<STR_LIT:time>'],<EOL>lcdict['<STR_LIT>']['<STR_LIT>'],<EOL>lcdict['<STR_LIT>']['<STR_LIT>'],<EOL>lcdict['<STR_LIT>']['<STR_LIT>']<EOL>)<EOL>xcc = lcdict[xccol]<EOL>ycc = lcdict[yccol]<EOL>flags = lcdict['<STR_LIT>']<EOL>if filterflags:<EOL><INDENT>nbefore = times.size<EOL>filterind = flags == <NUM_LIT:0><EOL>times = times[filterind]<EOL>fluxes = fluxes[filterind]<EOL>background = background[filterind]<EOL>background_err = background_err[filterind]<EOL>xcc = xcc[filterind]<EOL>ycc = ycc[filterind]<EOL>flags = flags[filterind]<EOL>nafter = times.size<EOL>LOGINFO('<STR_LIT>'<EOL>'<STR_LIT>'<EOL>% (nbefore, nafter))<EOL><DEDENT>find = (npisfinite(xcc) & npisfinite(ycc) &<EOL>npisfinite(times) & npisfinite(fluxes) &<EOL>npisfinite(background) & npisfinite(background_err))<EOL>nbefore = times.size<EOL>times = times[find]<EOL>fluxes = fluxes[find]<EOL>background = background[find]<EOL>background_err = background_err[find]<EOL>xcc = xcc[find]<EOL>ycc = ycc[find]<EOL>flags = flags[find]<EOL>nafter = times.size<EOL>LOGINFO('<STR_LIT>'<EOL>% (nbefore, nafter))<EOL>if (timestoignore and<EOL>isinstance(timestoignore, list) and<EOL>len(timestoignore) > <NUM_LIT:0>):<EOL><INDENT>exclind = npfull_like(times,True)<EOL>nbefore = times.size<EOL>for ignoretime in timestoignore:<EOL><INDENT>time0, time1 = ignoretime[<NUM_LIT:0>], ignoretime[<NUM_LIT:1>]<EOL>thismask = (times > time0) & (times < time1)<EOL>exclind = exclind & thismask<EOL><DEDENT>times = times[exclind]<EOL>fluxes = fluxes[exclind]<EOL>background = background[exclind]<EOL>background_err = background_err[exclind]<EOL>xcc = xcc[exclind]<EOL>ycc = ycc[exclind]<EOL>flags = flags[exclind]<EOL>nafter = times.size<EOL>LOGINFO('<STR_LIT>'<EOL>% (nbefore, nafter))<EOL><DEDENT>RFR = RandomForestRegressor(n_estimators=nrftrees)<EOL>if decorr == '<STR_LIT>':<EOL><INDENT>features = npcolumn_stack((xcc,ycc,background,background_err))<EOL><DEDENT>elif decorr == '<STR_LIT>':<EOL><INDENT>features = npcolumn_stack((xcc,ycc))<EOL><DEDENT>elif decorr == '<STR_LIT>':<EOL><INDENT>features = npcolumn_stack((background,background_err))<EOL><DEDENT>else:<EOL><INDENT>LOGERROR("<STR_LIT>")<EOL>return None<EOL><DEDENT>if epdsmooth:<EOL><INDENT>smoothedfluxes = median_filter(fluxes, size=epdsmooth)<EOL><DEDENT>else:<EOL><INDENT>smoothedfluxes = fluxes<EOL><DEDENT>RFR.fit(features, smoothedfluxes)<EOL>flux_corrections = RFR.predict(features)<EOL>corrected_fluxes = npmedian(fluxes) + fluxes - flux_corrections<EOL>del RFR<EOL>if writetodict:<EOL><INDENT>lcdict['<STR_LIT>'] = {}<EOL>lcdict['<STR_LIT>']['<STR_LIT:time>'] = times<EOL>lcdict['<STR_LIT>']['<STR_LIT>'] = fluxes<EOL>lcdict['<STR_LIT>']['<STR_LIT>'] = corrected_fluxes<EOL>lcdict['<STR_LIT>']['<STR_LIT>'] = flux_corrections<EOL>lcdict['<STR_LIT>']['<STR_LIT>'] = background<EOL>lcdict['<STR_LIT>']['<STR_LIT>'] = background_err<EOL>lcdict['<STR_LIT>']['<STR_LIT>'] = xcc<EOL>lcdict['<STR_LIT>']['<STR_LIT>'] = ycc<EOL>lcdict['<STR_LIT>']['<STR_LIT>'] = flags<EOL>for newcol in ['<STR_LIT>','<STR_LIT>',<EOL>'<STR_LIT>','<STR_LIT>',<EOL>'<STR_LIT>','<STR_LIT>',<EOL>'<STR_LIT>','<STR_LIT>',<EOL>'<STR_LIT>']:<EOL><INDENT>if newcol not in lcdict['<STR_LIT>']:<EOL><INDENT>lcdict['<STR_LIT>'].append(newcol)<EOL><DEDENT><DEDENT><DEDENT>return times, corrected_fluxes, flux_corrections<EOL>

This uses a `RandomForestRegressor` to fit and decorrelate Kepler light
    curves.

    Fits the X and Y positions, the background, and background error.

    By default, this function removes points in the Kepler LC that have ANY
    quality flags set.

    Parameters
    ----------

    lcdict : lcdict
        An `lcdict` produced by `consolidate_kepler_fitslc` or
        `read_kepler_fitslc`.

    xcol,ycol : str
        Indicates the x and y coordinate column names to use from the Kepler LC
        in the EPD fit.

    timestoignore : list of tuples
        This is of the form::

            [(time1_start, time1_end), (time2_start, time2_end), ...]

        and indicates the start and end times to mask out of the final
        lcdict. Use this to remove anything that wasn't caught by the quality
        flags.

    filterflags : bool
        If True, will remove any measurements that have non-zero quality flags
        present. This usually indicates an issue with the instrument or
        spacecraft.

    writetodict : bool
        If writetodict is True, adds the following columns to the lcdict::

            rfepd_time = time array
            rfepd_sapflux = uncorrected flux before EPD
            rfepd_epdsapflux = corrected flux after EPD
            rfepd_epdsapcorr = EPD flux corrections
            rfepd_bkg = background array
            rfepd_bkg_err = background errors array
            rfepd_xcc = xcoord array
            rfepd_ycc = ycoord array
            rfepd_quality = quality flag array

        and updates the 'columns' list in the lcdict as well.

    epdsmooth : int
        Sets the number of light curve points to smooth over when generating the
        EPD fit function.

    decorr : {'xcc,ycc','bgv,bge','xcc,ycc,bgv,bge'}
        Indicates whether to use the x,y coords alone; background value and
        error alone; or x,y coords and background value, error in combination as
        the features to training the `RandomForestRegressor` on and perform the
        fit.

    nrftrees : int
        The number of trees to use in the `RandomForestRegressor`.

    Returns
    -------

    tuple
        Returns a tuple of the form: (times, corrected_fluxes, flux_corrections)


def detrend_centroid(lcd, detrend='<STR_LIT>', sigclip=None, mingap=<NUM_LIT:0.5>):

qnum = npunique(lcd['<STR_LIT>'])<EOL>try:<EOL><INDENT>assert qnum.size == <NUM_LIT:1>, '<STR_LIT>'<EOL>assert detrend == '<STR_LIT>'<EOL>qnum = int(qnum)<EOL><DEDENT>except Exception as e:<EOL><INDENT>errflag = True<EOL><DEDENT>nbefore = lcd['<STR_LIT:time>'].size<EOL>times = lcd['<STR_LIT:time>'][lcd['<STR_LIT>'] == <NUM_LIT:0>]<EOL>ctd_x = lcd['<STR_LIT>'][lcd['<STR_LIT>'] == <NUM_LIT:0>]<EOL>ctd_y = lcd['<STR_LIT>'][lcd['<STR_LIT>'] == <NUM_LIT:0>]<EOL>ctd_x_err = lcd['<STR_LIT>'][lcd['<STR_LIT>'] == <NUM_LIT:0>]<EOL>ctd_y_err = lcd['<STR_LIT>'][lcd['<STR_LIT>'] == <NUM_LIT:0>]<EOL>find = npisfinite(times) & npisfinite(ctd_x) & npisfinite(ctd_y)<EOL>find &= (npisfinite(ctd_x_err)) & (npisfinite(ctd_y_err))<EOL>f_times, f_ctd_x, f_ctd_y = times[find], ctd_x[find], ctd_y[find]<EOL>f_ctd_x_err, f_ctd_y_err = ctd_x_err[find], ctd_y_err[find]<EOL>stimes_x, s_ctd_x, s_ctd_x_err = sigclip_magseries(<EOL>f_times,<EOL>f_ctd_x,<EOL>f_ctd_x_err,<EOL>magsarefluxes=True,<EOL>sigclip=<NUM_LIT><EOL>)<EOL>stimes_y, s_ctd_y, s_ctd_y_err = sigclip_magseries(<EOL>f_times,<EOL>f_ctd_y,<EOL>f_ctd_y_err,<EOL>magsarefluxes=True,<EOL>sigclip=<NUM_LIT><EOL>)<EOL>mask_x = npin1d(stimes_x, stimes_y)<EOL>s_times, s_ctd_x, s_ctd_x_err = (<EOL>stimes_x[mask_x],<EOL>s_ctd_x[mask_x],<EOL>s_ctd_x_err[mask_x]<EOL>)<EOL>mask_y = npin1d(stimes_y, stimes_x)<EOL>tmp, s_ctd_y, s_ctd_y_err = (<EOL>stimes_y[mask_y],<EOL>s_ctd_y[mask_y],<EOL>s_ctd_y_err[mask_y]<EOL>)<EOL>try:<EOL><INDENT>np.testing.assert_array_equal(s_times, tmp)<EOL>assert len(s_ctd_y) == len(s_times)<EOL>assert len(s_ctd_y_err) == len(s_times)<EOL>assert len(s_ctd_x) == len(s_times)<EOL>assert len(s_ctd_x_err) == len(s_times)<EOL><DEDENT>except AssertionError:<EOL><INDENT>return lcd, True<EOL><DEDENT>nqflag = s_times.size<EOL>ngroups, groups = find_lc_timegroups(s_times, mingap=mingap)<EOL>tmp_times, tmp_ctd_x, tmp_ctd_y = [], [], []<EOL>tmp_ctd_x_err, tmp_ctd_y_err = [], []<EOL>for group in groups:<EOL><INDENT>tg_times = s_times[group]<EOL>tg_ctd_x = s_ctd_x[group]<EOL>tg_ctd_y = s_ctd_y[group]<EOL>tg_ctd_x_err = s_ctd_x_err[group]<EOL>tg_ctd_y_err = s_ctd_y_err[group]<EOL>try:<EOL><INDENT>sel = ((tg_times > npmin(tg_times)+mingap) &<EOL>(tg_times < npmax(tg_times)-mingap))<EOL><DEDENT>except ValueError:<EOL><INDENT>continue<EOL><DEDENT>tmp_times.append(tg_times[sel])<EOL>tmp_ctd_x.append(tg_ctd_x[sel])<EOL>tmp_ctd_y.append(tg_ctd_y[sel])<EOL>tmp_ctd_x_err.append(tg_ctd_x_err[sel])<EOL>tmp_ctd_y_err.append(tg_ctd_y_err[sel])<EOL><DEDENT>s_times,s_ctd_x,s_ctd_y,s_ctd_x_err,s_ctd_y_err = (<EOL>nparray([]),nparray([]),nparray([]),nparray([]),nparray([])<EOL>)<EOL>for ix, _ in enumerate(tmp_times):<EOL><INDENT>s_times = npappend(s_times, tmp_times[ix])<EOL>s_ctd_x = npappend(s_ctd_x, tmp_ctd_x[ix])<EOL>s_ctd_y = npappend(s_ctd_y, tmp_ctd_y[ix])<EOL>s_ctd_x_err = npappend(s_ctd_x_err, tmp_ctd_x_err[ix])<EOL>s_ctd_y_err = npappend(s_ctd_y_err, tmp_ctd_y_err[ix])<EOL><DEDENT>try:<EOL><INDENT>s_ctd_x = s_ctd_x[(s_times > (npmin(s_times)+mingap)) &<EOL>(s_times < (npmax(s_times)-mingap))]<EOL><DEDENT>except Exception as e:<EOL><INDENT>LOGERROR('<STR_LIT>'.format(qnum))<EOL>return npnan, True<EOL><DEDENT>s_ctd_y = s_ctd_y[(s_times > (npmin(s_times)+mingap)) &<EOL>(s_times < (npmax(s_times)-mingap))]<EOL>s_ctd_x_err = s_ctd_x_err[(s_times > (npmin(s_times)+mingap)) &<EOL>(s_times < (npmax(s_times)-mingap))]<EOL>s_ctd_y_err = s_ctd_y_err[(s_times > (npmin(s_times)+mingap)) &<EOL>(s_times < (npmax(s_times)-mingap))]<EOL>s_times = s_times[(s_times > (npmin(s_times)+mingap)) &<EOL>(s_times < (npmax(s_times)-mingap))]<EOL>nafter = s_times.size<EOL>LOGINFO(<EOL>'<STR_LIT>'.format(qnum) +<EOL>'<STR_LIT>'.format(<EOL>nbefore, <NUM_LIT:1.><EOL>) +<EOL>'<STR_LIT>'.format(<EOL>nqflag, nqflag/float(nbefore)<EOL>) +<EOL>'<STR_LIT>'.format(<EOL>nafter, nafter/float(nbefore)<EOL>)<EOL>)<EOL>ctd_dtr = {}<EOL>if detrend == '<STR_LIT>':<EOL><INDENT>mingap = <NUM_LIT:0.5>  <EOL>ngroups, groups = find_lc_timegroups(s_times, mingap=mingap)<EOL>tmpctdxlegfit, tmpctdylegfit, legdegs = [], [], []<EOL>for group in groups:<EOL><INDENT>tg_times = s_times[group]<EOL>tg_ctd_x = s_ctd_x[group]<EOL>tg_ctd_x_err = s_ctd_x_err[group]<EOL>tg_ctd_y = s_ctd_y[group]<EOL>tg_ctd_y_err = s_ctd_y_err[group]<EOL>legdeg = _get_legendre_deg_ctd(len(tg_times))<EOL>tg_ctd_x_fit, _, _ = _legendre_dtr(tg_times,tg_ctd_x,tg_ctd_x_err,<EOL>legendredeg=legdeg)<EOL>tg_ctd_y_fit, _, _ = _legendre_dtr(tg_times,tg_ctd_y,tg_ctd_y_err,<EOL>legendredeg=legdeg)<EOL>tmpctdxlegfit.append(tg_ctd_x_fit)<EOL>tmpctdylegfit.append(tg_ctd_y_fit)<EOL>legdegs.append(legdeg)<EOL><DEDENT>fit_ctd_x, fit_ctd_y = nparray([]), nparray([])<EOL>for ix, _ in enumerate(tmpctdxlegfit):<EOL><INDENT>fit_ctd_x = npappend(fit_ctd_x, tmpctdxlegfit[ix])<EOL>fit_ctd_y = npappend(fit_ctd_y, tmpctdylegfit[ix])<EOL><DEDENT><DEDENT>ctd_dtr = {'<STR_LIT>':s_times,<EOL>'<STR_LIT>':s_ctd_x,<EOL>'<STR_LIT>':s_ctd_x_err,<EOL>'<STR_LIT>':fit_ctd_x,<EOL>'<STR_LIT>':s_ctd_y,<EOL>'<STR_LIT>':s_ctd_y_err,<EOL>'<STR_LIT>':fit_ctd_y}<EOL>lcd['<STR_LIT>'] = ctd_dtr<EOL>return lcd, False<EOL>

Detrends the x and y coordinate centroids for a Kepler light curve.

    Given an `lcdict` for a single quarter of Kepler data, returned by
    `read_kepler_fitslc`, this function returns this same dictionary,
    appending detrended centroid_x and centroid_y values.

    Here "detrended" means "finite, SAP quality flag set to 0, sigma clipped,
    timegroups selected based on `mingap` day gaps, then fit vs time by a
    legendre polynomial of lowish degree".

    Parameters
    ----------

    lcd : lcdict
        An `lcdict` generated by the `read_kepler_fitslc` function.

    detrend : {'legendre'}
        Method by which to detrend the LC. 'legendre' is the only thing
        implemented at the moment.

    sigclip : None or float or int or sequence of floats/ints
        Determines the type and amount of sigma-clipping done on the light curve
        to remove outliers. If None, no sigma-clipping is performed. If a two
        element sequence of floats/ints, the first element corresponds to the
        fainter sigma-clip limit, and the second element corresponds to the
        brighter sigma-clip limit.

    mingap : float
        Number of days by which to define "timegroups" (for individual fitting
        each of timegroup, and to eliminate "burn-in" of Kepler spacecraft. For
        long cadence data, 0.5 days is typical.

    Returns
    -------

    tuple
        This is of the form `(lcd, errflag)`, where:

        `lcd` : an `lcdict` with the new key `lcd['centroids']`, containing the
        detrended times, (centroid_x, centroid_y) values, and their errors.

        `errflag` : boolean error flag, could be raised at various points.


def get_centroid_offsets(lcd, t_ing_egr, oot_buffer_time=<NUM_LIT:0.1>, sample_factor=<NUM_LIT:3>):

<EOL>qnum = int(np.unique(lcd['<STR_LIT>']))<EOL>LOGINFO('<STR_LIT>'.format(qnum))<EOL>arcsec_per_px = <NUM_LIT><EOL>times = lcd['<STR_LIT>']['<STR_LIT>']<EOL>ctd_resid_x = lcd['<STR_LIT>']['<STR_LIT>'] - lcd['<STR_LIT>']['<STR_LIT>']<EOL>ctd_resid_y = lcd['<STR_LIT>']['<STR_LIT>'] - lcd['<STR_LIT>']['<STR_LIT>']<EOL>cd = {}<EOL>for ix,(t_ing,t_egr) in enumerate(t_ing_egr):<EOL><INDENT>in_tra_times = times[(times > t_ing) & (times < t_egr)]<EOL>transit_dur = t_egr - t_ing<EOL>oot_window_len = sample_factor * transit_dur<EOL>oot_before = times[<EOL>(times < (t_ing-oot_buffer_time)) &<EOL>(times > (t_ing-oot_buffer_time-oot_window_len))<EOL>]<EOL>oot_after = times[<EOL>(times > (t_egr+oot_buffer_time)) &<EOL>(times < (t_egr+oot_buffer_time+oot_window_len))<EOL>]<EOL>oot_times = npconcatenate([oot_before, oot_after])<EOL>mask_tra = npin1d(times, in_tra_times)<EOL>mask_oot = npin1d(times, oot_times)<EOL>ctd_x_in_tra = ctd_resid_x[mask_tra]*arcsec_per_px<EOL>ctd_y_in_tra = ctd_resid_y[mask_tra]*arcsec_per_px<EOL>ctd_x_oot = ctd_resid_x[mask_oot]*arcsec_per_px<EOL>ctd_y_oot = ctd_resid_y[mask_oot]*arcsec_per_px<EOL>cd[ix] = {'<STR_LIT>':ctd_x_in_tra,<EOL>'<STR_LIT>':ctd_y_in_tra,<EOL>'<STR_LIT>':ctd_x_oot,<EOL>'<STR_LIT>':ctd_y_oot,<EOL>'<STR_LIT>':len(ctd_x_in_tra),<EOL>'<STR_LIT>':len(ctd_x_oot),<EOL>'<STR_LIT>':in_tra_times,<EOL>'<STR_LIT>':oot_times}<EOL><DEDENT>LOGINFO('<STR_LIT>'.format(qnum))<EOL>return cd<EOL>

After running `detrend_centroid`, this gets positions of centroids during
    transits, and outside of transits.

    These positions can then be used in a false positive analysis.

    This routine requires knowing the ingress and egress times for every
    transit of interest within the quarter this routine is being called for.
    There is currently no astrobase routine that automates this for periodic
    transits (it must be done in a calling routine).

    To get out of transit centroids, this routine takes points outside of the
    "buffer" set by `oot_buffer_time`, sampling 3x as many points on either
    side of the transit as are in the transit (or however many are specified by
    `sample_factor`).

    Parameters
    ----------

    lcd : lcdict
        An `lcdict` generated by the `read_kepler_fitslc` function. We assume
        that the `detrend_centroid` function has been run on this `lcdict`.

    t_ing_egr : list of tuples
        This is of the form::

            [(ingress time of i^th transit, egress time of i^th transit)]

        for i the transit number index in this quarter (starts at zero at the
        beginning of every quarter). Assumes units of BJD.

    oot_buffer_time : float
        Number of days away from ingress and egress times to begin sampling "out
        of transit" centroid points. The number of out of transit points to take
        per transit is 3x the number of points in transit.

    sample_factor : float
        The size of out of transit window from which to sample.

    Returns
    -------

    dict
        This is a dictionary keyed by transit number (i.e., the same index as
        `t_ing_egr`), where each key contains the following value::

            {'ctd_x_in_tra':ctd_x_in_tra,
             'ctd_y_in_tra':ctd_y_in_tra,
             'ctd_x_oot':ctd_x_oot,
             'ctd_y_oot':ctd_y_oot,
             'npts_in_tra':len(ctd_x_in_tra),
             'npts_oot':len(ctd_x_oot),
             'in_tra_times':in_tra_times,
             'oot_times':oot_times}


from scipy.interpolate import interp1d<EOL>degs = nparray([<NUM_LIT:4>,<NUM_LIT:5>,<NUM_LIT:6>,<NUM_LIT:10>,<NUM_LIT:15>])<EOL>pts = nparray([<NUM_LIT>,<NUM_LIT>,<NUM_LIT>,<NUM_LIT>,<NUM_LIT>])<EOL>fn = interp1d(pts, degs, kind='<STR_LIT>',<EOL>bounds_error=False,<EOL>fill_value=(min(degs), max(degs)))<EOL>legendredeg = int(npfloor(fn(npts)))<EOL>return legendredeg<EOL>

This is a helper function for centroid detrending.


def _legendre_dtr(x, y, y_err, legendredeg=<NUM_LIT:10>):

try:<EOL><INDENT>p = Legendre.fit(x, y, legendredeg)<EOL>fit_y = p(x)<EOL><DEDENT>except Exception as e:<EOL><INDENT>fit_y = npzeros_like(y)<EOL><DEDENT>fitchisq = npsum(<EOL>((fit_y - y)*(fit_y - y)) / (y_err*y_err)<EOL>)<EOL>nparams = legendredeg + <NUM_LIT:1><EOL>fitredchisq = fitchisq/(len(y) - nparams - <NUM_LIT:1>)<EOL>LOGINFO(<EOL>'<STR_LIT>' %<EOL>(fitchisq, fitredchisq)<EOL>)<EOL>return fit_y, fitchisq, fitredchisq<EOL>

This calculates the residual and chi-sq values for a Legendre
    function fit.

    Parameters
    ----------

    x : np.array
        Array of the independent variable.

    y : np.array
        Array of the dependent variable.

    y_err : np.array
        Array of errors associated with each `y` value. Used to calculate fit
        weights.

    legendredeg : int
        The degree of the Legendre function to use when fitting.

    Returns
    -------

    tuple
        The tuple returned is of the form: (fit_y, fitchisq, fitredchisq)


def pre(self, command, output_dir, vars):

<EOL>vars['<STR_LIT>'] = '<STR_LIT>'<EOL>vars['<STR_LIT>'] = time.strftime('<STR_LIT>', time.localtime())<EOL>


def frictional_resistance_coef(length, speed, **kwargs):

Cf = <NUM_LIT> / (np.log10(reynolds_number(length, speed, **kwargs)) - <NUM_LIT:2>) ** <NUM_LIT:2><EOL>return Cf<EOL>

Flat plate frictional resistance of the ship according to ITTC formula.
ref: https://ittc.info/media/2021/75-02-02-02.pdf

:param length: metres length of the vehicle
:param speed: m/s speed of the vehicle
:param kwargs: optional could take in temperature to take account change of water property
:return: Frictional resistance coefficient of the vehicle


def reynolds_number(length, speed, temperature=<NUM_LIT>):

kinematic_viscosity = interpolate.interp1d([<NUM_LIT:0>, <NUM_LIT:10>, <NUM_LIT:20>, <NUM_LIT>, <NUM_LIT:30>, <NUM_LIT>],<EOL>np.array([<NUM_LIT>, <NUM_LIT>, <NUM_LIT>, <NUM_LIT>, <NUM_LIT>, <NUM_LIT>]) / <NUM_LIT:10> ** <NUM_LIT:7>)<EOL>Re = length * speed / kinematic_viscosity(temperature)<EOL>return Re<EOL>

Reynold number utility function that return Reynold number for vehicle at specific length and speed.
Optionally, it can also take account of temperature effect of sea water.

    Kinematic viscosity from: http://web.mit.edu/seawater/2017_MIT_Seawater_Property_Tables_r2.pdf

:param length: metres length of the vehicle
:param speed: m/s speed of the vehicle
:param temperature: degree C
:return: Reynolds number of the vehicle (dimensionless)


g = <NUM_LIT>  <EOL>Fr = speed / np.sqrt(g * length)<EOL>return Fr<EOL>

Froude number utility function that return Froude number for vehicle at specific length and speed.

:param speed: m/s speed of the vehicle
:param length: metres length of the vehicle
:return: Froude number of the vehicle (dimensionless)


def residual_resistance_coef(slenderness, prismatic_coef, froude_number):

Cr = cr(slenderness, prismatic_coef, froude_number)<EOL>if math.isnan(Cr):<EOL><INDENT>Cr = cr_nearest(slenderness, prismatic_coef, froude_number)<EOL><DEDENT>return Cr<EOL>

Residual resistance coefficient estimation from slenderness function, prismatic coefficient and Froude number.

:param slenderness: Slenderness coefficient dimensionless :math:`L/(∇^{1/3})` where L is length of ship, ∇ is displacement
:param prismatic_coef: Prismatic coefficient dimensionless :math:`∇/(L\cdot A_m)` where L is length of ship, ∇ is displacement Am is midsection area of the ship
:param froude_number: Froude number of the ship dimensionless
:return: Residual resistance of the ship


def dimension(self, length, draught, beam, speed,<EOL>slenderness_coefficient, prismatic_coefficient):

self.length = length<EOL>self.draught = draught<EOL>self.beam = beam<EOL>self.speed = speed<EOL>self.slenderness_coefficient = slenderness_coefficient<EOL>self.prismatic_coefficient = prismatic_coefficient<EOL>self.displacement = (self.length / self.slenderness_coefficient) ** <NUM_LIT:3><EOL>self.surface_area = <NUM_LIT> * (<NUM_LIT> * self.length * self.draught +<EOL>self.displacement / self.draught)<EOL>

Assign values for the main dimension of a ship.

:param length: metres length of the vehicle
:param draught: metres draught of the vehicle
:param beam: metres beam of the vehicle
:param speed: m/s speed of the vehicle
:param slenderness_coefficient: Slenderness coefficient dimensionless :math:`L/(∇^{1/3})` where L is length of ship,
    ∇ is displacement
:param prismatic_coefficient: Prismatic coefficient dimensionless :math:`∇/(L\cdot A_m)` where L is length of ship,
    ∇ is displacement Am is midsection area of the ship


self.total_resistance_coef = frictional_resistance_coef(self.length, self.speed) +residual_resistance_coef(self.slenderness_coefficient,<EOL>self.prismatic_coefficient,<EOL>froude_number(self.speed, self.length))<EOL>RT = <NUM_LIT:1> / <NUM_LIT:2> * self.total_resistance_coef * <NUM_LIT> * self.surface_area * self.speed ** <NUM_LIT:2><EOL>return RT<EOL>

Return resistance of the vehicle.

:return: newton the resistance of the ship


AD = self.beam * self.length * water_plane_coef<EOL>return AD<EOL>

Return the maximum deck area of the ship

:param water_plane_coef: optional water plane coefficient
:return: Area of the deck


return reynolds_number(self.length, self.speed)<EOL>

Return Reynold number of the ship

:return: Reynold number of the ship


def prop_power(self, propulsion_eff=<NUM_LIT>, sea_margin=<NUM_LIT>):

PP = (<NUM_LIT:1> + sea_margin) * self.resistance() * self.speed/propulsion_eff<EOL>return PP<EOL>

Total propulsion power of the ship.

:param propulsion_eff: Shaft efficiency of the ship
:param sea_margin: Sea margin take account of interaction between ship and the sea, e.g. wave
:return: Watts shaft propulsion power of the ship


return len(str(n).split('<STR_LIT:.>')[-<NUM_LIT:1>])<EOL>

Count the digits of a given float number
:param n: the float number
:return: number of digits


return '<STR_LIT>'.join(random.SystemRandom().choice(string.ascii_letters + string.digits) for _ in range(n))<EOL>

Generate a random string from a-zA-Z0-9
:param n: length of the string
:return: the random string


return '<STR_LIT>'.join(random.SystemRandom().choice(string.ascii_letters) for _ in range(n))<EOL>

Generate a random string from a-zA-Z
:param n: length of the string
:return: the random string


return '<STR_LIT>'.join(random.SystemRandom().choice(string.digits) for _ in range(n))<EOL>

Generate a random string from 0-9
:param n: length of the string
:return: the random string


for i in range(len(d)):<EOL><INDENT>if d[i][k] == v:<EOL><INDENT>return i<EOL><DEDENT><DEDENT>return None<EOL>

Search dictionary list by key and value
:param d: dictionary list
:param k: key
:param v: value
:return: the index of the first dictionary in the array with the specific key / value


c = a.copy()<EOL>for j in range(len(b)):<EOL><INDENT>flag = False<EOL>for i in range(len(c)):<EOL><INDENT>if c[i][k] == b[j][k]:<EOL><INDENT>c[i] = b[j].copy()<EOL>flag = True<EOL><DEDENT><DEDENT>if not flag:<EOL><INDENT>c.append(b[j].copy())<EOL><DEDENT><DEDENT>return c<EOL>

Merge two dictionary lists
:param a: original list
:param b: alternative list, element will replace the one in original list with same key
:param k: key
:return: the merged list


return sorted(d.copy(), key=lambda i: i[k])<EOL>

Sort a dictionary list by key
:param d: dictionary list
:param k: key
:return: sorted dictionary list


h = list()<EOL>for i in range(len(d)):<EOL><INDENT>heappush(h, (-d[i][k] if reverse else d[i][k], i))<EOL><DEDENT>r = list()<EOL>while len(r) < n and len(h) > <NUM_LIT:0>:<EOL><INDENT>_, i = heappop(h)<EOL>r.append(d[i].copy())<EOL><DEDENT>return r<EOL>

Return top n of a dictionary list sorted by key
:param d: dictionary list
:param k: key
:param n: top n
:param reverse: whether the value should be reversed
:return: top n of the sorted dictionary list


if type(d) != dict:<EOL><INDENT>return d<EOL><DEDENT>else:<EOL><INDENT>dd = dict()<EOL>for key, value in d.items():<EOL><INDENT>if type(value) == dict:<EOL><INDENT>for k, v in value.items():<EOL><INDENT>dd[key + '<STR_LIT:_>' + k] = dict_flatten(v)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>dd[key] = value<EOL><DEDENT><DEDENT>return dd<EOL><DEDENT>

Replace nested dict keys to underscore-connected keys
:param d: the dictionary
:return: flattened dictionary


def dict_format_type(d, source, formatter, include_list=True):

if not isinstance(d, dict):<EOL><INDENT>if isinstance(d, source):<EOL><INDENT>return formatter(d)<EOL><DEDENT>else:<EOL><INDENT>return d<EOL><DEDENT><DEDENT>else:<EOL><INDENT>dd = dict()<EOL>for key, value in d.items():<EOL><INDENT>if include_list and isinstance(value, list):<EOL><INDENT>dd[key] = [dict_format_type(i, source, formatter) for i in value]<EOL><DEDENT>elif isinstance(value, dict):<EOL><INDENT>dd[key] = dict_format_type(value, source, formatter)<EOL><DEDENT>elif isinstance(value, source):<EOL><INDENT>dd[key] = formatter(value)<EOL><DEDENT>else:<EOL><INDENT>dd[key] = value<EOL><DEDENT><DEDENT>return dd<EOL><DEDENT>

Replace the values of a dict with certain type to other values
:param d: the dictionary
:param source: the source type, e.g., int
:param formatter: the formatter method, e.g., return the string format of an int
:param include_list: whether list should be formatted, otherwise list will be considered as source type
:return: formatted dictionary


dd = dict()<EOL>for key, value in d.items():<EOL><INDENT>if not key == k:<EOL><INDENT>if isinstance(value, dict):<EOL><INDENT>dd[key] = dict_remove_key(value, k)<EOL><DEDENT>elif isinstance(value, list):<EOL><INDENT>dd[key] = [dict_remove_key(i, k) for i in value]<EOL><DEDENT>else:<EOL><INDENT>dd[key] = value<EOL><DEDENT><DEDENT><DEDENT>return dd<EOL>

Recursively remove a key from a dict
:param d: the dictionary
:param k: key which should be removed
:return: formatted dictionary


dd = dict()<EOL>for key, value in d.items():<EOL><INDENT>if not value == v:<EOL><INDENT>if isinstance(value, dict):<EOL><INDENT>dd[key] = dict_remove_value(value, v)<EOL><DEDENT>elif isinstance(value, list):<EOL><INDENT>dd[key] = [dict_remove_value(i, v) for i in value]<EOL><DEDENT>else:<EOL><INDENT>dd[key] = value<EOL><DEDENT><DEDENT><DEDENT>return dd<EOL>

Recursively remove keys with a certain value from a dict
:param d: the dictionary
:param v: value which should be removed
:return: formatted dictionary


dd = list()<EOL>for k, v in d.items():<EOL><INDENT>dd.append([k, v] if as_list else (k, v))<EOL><DEDENT>return dd<EOL>

Format a dict to a list of tuples
:param d: the dictionary
:param as_list: return a list of lists rather than a list of tuples
:return: formatted dictionary list


for e in t:<EOL><INDENT>if e[i] == v:<EOL><INDENT>return e<EOL><DEDENT><DEDENT>return None<EOL>

Search tuple array by index and value
:param t: tuple array
:param i: index of the value in each tuple
:param v: value
:return: the first tuple in the array with the specific index / value


return str1[:i] + str2 + str1[i:]<EOL>

Insert a string in the middle of another string
:param str1: the original string
:param str2: the string to be inserted
:param i: the index of the insertion position
:return: the resulting string


def format_datetime(t: datetime = None):

return (datetime.now() if t is None else t).strftime('<STR_LIT>')<EOL>

Format a datetime object into yyyy-MM-dd hh:mm:ss
:param t: datetime object, default: now
:return: the formatted string


Format a datetime object into yyyy-MM-dd
:param t: datetime object, default: now
:return: the formatted string


Format a datetime object into hh:mm:ss
:param t: datetime object, default: now
:return: the formatted string


def progress(count, total, prefix='<STR_LIT>', suffix='<STR_LIT>', length=<NUM_LIT>):

bar_len = length<EOL>filled_len = int(round(bar_len * count / float(total)))<EOL>percents = round(<NUM_LIT> * count / float(total), <NUM_LIT:1>)<EOL>bar = '<STR_LIT:=>' * filled_len + '<STR_LIT:->' * (bar_len - filled_len)<EOL>sys.stdout.write('<STR_LIT>' % (prefix, bar, percents, '<STR_LIT:%>', '<STR_LIT:U+0020>' + suffix))<EOL>sys.stdout.flush()<EOL>

Show a progress bar
:param count: current progress
:param total: total progress
:param prefix: prefix shown before the progress bar
:param suffix: suffix shown after the progress bar
:param length: length of the progress bar, default: 60
:return: none


def __init__(self, path='<STR_LIT:.>', prefix='<STR_LIT>', buffer=<NUM_LIT>):

self.data = list()<EOL>self.path = path<EOL>self.prefix = prefix<EOL>self.buffer = buffer<EOL>

Buffered writer
:param path: writing path where files will be stored as <timestamp>.dat.gz
:param prefix: prefix for all files
:param buffer: the buffer size


Xsim = rk4(SIR_D, y0, time, args=(beta,gamma,))<EOL>Xsim = Xsim.transpose()<EOL>return Xsim<EOL>

Integrate SIR epidemic model

    Simulate a very basic deterministic SIR system.

    :param 2x1 numpy array y0: initial conditions
    :param Ntimestep length numpy array time: Vector of time points that \
    solution is returned at
    :param float beta: transmission rate
    :param float gamma: recovery rate

    :returns: (2)x(Ntimestep) numpy array Xsim: first row S(t), second row I(t)


def __init__(self, filename, damethod, date, ensize):

self.filename = filename<EOL>self.damethod = damethod<EOL>self.date = date<EOL>self.ensize = ensize<EOL>self.dafile = h5py.File(self.filename, "<STR_LIT:a>")<EOL>self.dafile.attrs['<STR_LIT>'] = self.damethod<EOL>self.dafile.attrs['<STR_LIT:date>'] = self.date<EOL>self.dafile.attrs['<STR_LIT>'] = self.ensize<EOL>self.dafile.create_group("<STR_LIT>")<EOL>self.dafile.create_group("<STR_LIT>")<EOL>self.dafile.create_group("<STR_LIT>")<EOL>self.dafile.create_group("<STR_LIT>")<EOL>self.dafile.create_group("<STR_LIT>")<EOL>self.dafile.create_group("<STR_LIT>")<EOL>

Initialize darun attributes

        Args:
            filename (str): Absolute path of file name as a string with `hdf5` extension
            damethod (str): Name of the assimilation method used, i.e. `enkf`.
            date (str): Date of the experiment `MM-DD-YYYY:HHHH`
            ensize (int): ensemble size


return (time.mktime(when.timetuple()) if sys.version_info < (<NUM_LIT:3>,) else<EOL>when.timestamp())<EOL>

Python 2 compatibility for `datetime.timestamp()`.


if isinstance(data, bytes):<EOL><INDENT>return data<EOL><DEDENT>elif isinstance(data, str):<EOL><INDENT>return data.encode('<STR_LIT:ascii>')  <EOL><DEDENT>else:<EOL><INDENT>raise TypeError(data)<EOL><DEDENT>


if getattr(settings, '<STR_LIT>', None):<EOL><INDENT>return hmac.new(<EOL>key=_hashable_bytes(settings.INTERCOM_HMAC_SECRET_KEY),<EOL>msg=_hashable_bytes(data),<EOL>digestmod=hashlib.sha256,<EOL>).hexdigest()<EOL><DEDENT>else:<EOL><INDENT>return None<EOL><DEDENT>

Return a SHA-256 HMAC `user_hash` as expected by Intercom, if configured.

Return None if the `INTERCOM_HMAC_SECRET_KEY` setting is not configured.


bits = token.split_contents()<EOL>if len(bits) > <NUM_LIT:1>:<EOL><INDENT>raise TemplateSyntaxError("<STR_LIT>" % bits[<NUM_LIT:0>])<EOL><DEDENT>return IntercomNode()<EOL>

Intercom.io template tag.

Renders Javascript code to intercom.io testing.  You must supply
your APP ID account number in the ``INTERCOM_APP_ID``
setting.


bits = token.split_contents()<EOL>if len(bits) > <NUM_LIT:1>:<EOL><INDENT>raise TemplateSyntaxError("<STR_LIT>" % bits[<NUM_LIT:0>])<EOL><DEDENT>return PiwikNode()<EOL>

Piwik tracking template tag.

Renders Javascript code to track page visits.  You must supply
your Piwik domain (plus optional URI path), and tracked site ID
in the ``PIWIK_DOMAIN_PATH`` and the ``PIWIK_SITE_ID`` setting.

Custom variables can be passed in the ``piwik_vars`` context
variable.  It is an iterable of custom variables as tuples like:
``(index, name, value[, scope])`` where scope may be ``'page'``
(default) or ``'visit'``.  Index should be an integer and the
other parameters should be strings.


bits = token.split_contents()<EOL>if len(bits) > <NUM_LIT:1>:<EOL><INDENT>raise TemplateSyntaxError("<STR_LIT>" % bits[<NUM_LIT:0>])<EOL><DEDENT>return WoopraNode()<EOL>

Woopra tracking template tag.

Renders Javascript code to track page visits.  You must supply
your Woopra domain in the ``WOOPRA_DOMAIN`` setting.


bits = token.split_contents()<EOL>if len(bits) > <NUM_LIT:1>:<EOL><INDENT>raise TemplateSyntaxError("<STR_LIT>" % bits[<NUM_LIT:0>])<EOL><DEDENT>return ClickmapNode()<EOL>

Clickmap tracker template tag.

Renders Javascript code to track page visits.  You must supply
your clickmap tracker ID (as a string) in the ``CLICKMAP_TRACKER_ID``
setting.


bits = token.split_contents()<EOL>if len(bits) > <NUM_LIT:1>:<EOL><INDENT>raise TemplateSyntaxError("<STR_LIT>" % bits[<NUM_LIT:0>])<EOL><DEDENT>return OptimizelyNode()<EOL>

Optimizely template tag.

Renders Javascript code to set-up A/B testing.  You must supply
your Optimizely account number in the ``OPTIMIZELY_ACCOUNT_NUMBER``
setting.


bits = token.split_contents()<EOL>if len(bits) > <NUM_LIT:1>:<EOL><INDENT>raise TemplateSyntaxError("<STR_LIT>" % bits[<NUM_LIT:0>])<EOL><DEDENT>return UserVoiceNode()<EOL>

UserVoice tracking template tag.

Renders Javascript code to track page visits.  You must supply
your UserVoice Widget Key in the ``USERVOICE_WIDGET_KEY``
setting or the ``uservoice_widget_key`` template context variable.


bits = token.split_contents()<EOL>if len(bits) > <NUM_LIT:1>:<EOL><INDENT>raise TemplateSyntaxError("<STR_LIT>" % bits[<NUM_LIT:0>])<EOL><DEDENT>return KissInsightsNode()<EOL>

KISSinsights set-up template tag.

Renders Javascript code to set-up surveys.  You must supply
your account number and site code in the
``KISS_INSIGHTS_ACCOUNT_NUMBER`` and ``KISS_INSIGHTS_SITE_CODE``
settings.


bits = token.split_contents()<EOL>if len(bits) > <NUM_LIT:1>:<EOL><INDENT>raise TemplateSyntaxError("<STR_LIT>" % bits[<NUM_LIT:0>])<EOL><DEDENT>return MatomoNode()<EOL>

Matomo tracking template tag.

Renders Javascript code to track page visits.  You must supply
your Matomo domain (plus optional URI path), and tracked site ID
in the ``MATOMO_DOMAIN_PATH`` and the ``MATOMO_SITE_ID`` setting.

Custom variables can be passed in the ``matomo_vars`` context
variable.  It is an iterable of custom variables as tuples like:
``(index, name, value[, scope])`` where scope may be ``'page'``
(default) or ``'visit'``.  Index should be an integer and the
other parameters should be strings.


bits = token.split_contents()<EOL>if len(bits) > <NUM_LIT:1>:<EOL><INDENT>raise TemplateSyntaxError("<STR_LIT>" % bits[<NUM_LIT:0>])<EOL><DEDENT>return SpringMetricsNode()<EOL>

Spring Metrics tracking template tag.

Renders Javascript code to track page visits.  You must supply
your Spring Metrics Tracking ID in the
``SPRING_METRICS_TRACKING_ID`` setting.


bits = token.split_contents()<EOL>if len(bits) > <NUM_LIT:1>:<EOL><INDENT>raise TemplateSyntaxError("<STR_LIT>" % bits[<NUM_LIT:0>])<EOL><DEDENT>return PerformableNode()<EOL>

Performable template tag.

Renders Javascript code to set-up Performable tracking.  You must
supply your Performable API key in the ``PERFORMABLE_API_KEY``
setting.


return mark_safe(EMBED_CODE % {<EOL>'<STR_LIT>': hostname,<EOL>'<STR_LIT>': page_id,<EOL>})<EOL>


bits = token.split_contents()<EOL>if len(bits) > <NUM_LIT:1>:<EOL><INDENT>raise TemplateSyntaxError("<STR_LIT>" % bits[<NUM_LIT:0>])<EOL><DEDENT>return RatingMailruNode()<EOL>

Rating@Mail.ru counter template tag.

Renders Javascript code to track page visits. You must supply
your website counter ID (as a string) in the
``RATING_MAILRU_COUNTER_ID`` setting.


bits = token.split_contents()<EOL>if len(bits) > <NUM_LIT:1>:<EOL><INDENT>raise TemplateSyntaxError("<STR_LIT>" % bits[<NUM_LIT:0>])<EOL><DEDENT>return GoogleAnalyticsJsNode()<EOL>

Google Analytics tracking template tag.

Renders Javascript code to track page visits.  You must supply
your website property ID (as a string) in the
``GOOGLE_ANALYTICS_JS_PROPERTY_ID`` setting.


bits = token.split_contents()<EOL>if len(bits) > <NUM_LIT:1>:<EOL><INDENT>raise TemplateSyntaxError("<STR_LIT>" % bits[<NUM_LIT:0>])<EOL><DEDENT>return HubSpotNode()<EOL>

HubSpot tracking template tag.

Renders Javascript code to track page visits.  You must supply
your portal ID (as a string) in the ``HUBSPOT_PORTAL_ID`` setting.


bits = token.split_contents()<EOL>if len(bits) > <NUM_LIT:1>:<EOL><INDENT>raise TemplateSyntaxError("<STR_LIT>" % bits[<NUM_LIT:0>])<EOL><DEDENT>return CrazyEggNode()<EOL>

Crazy Egg tracking template tag.

Renders Javascript code to track page clicks.  You must supply
your Crazy Egg account number (as a string) in the
``CRAZY_EGG_ACCOUNT_NUMBER`` setting.


bits = token.split_contents()<EOL>if len(bits) > <NUM_LIT:1>:<EOL><INDENT>raise TemplateSyntaxError("<STR_LIT>" % bits[<NUM_LIT:0>])<EOL><DEDENT>return YandexMetricaNode()<EOL>

Yandex.Metrica counter template tag.

Renders Javascript code to track page visits. You must supply
your website counter ID (as a string) in the
``YANDEX_METRICA_COUNTER_ID`` setting.


bits = token.split_contents()<EOL>if len(bits) > <NUM_LIT:1>:<EOL><INDENT>raise TemplateSyntaxError("<STR_LIT>" % bits[<NUM_LIT:0>])<EOL><DEDENT>return ChartbeatTopNode()<EOL>

Top Chartbeat template tag.

Render the top Javascript code for Chartbeat.


bits = token.split_contents()<EOL>if len(bits) > <NUM_LIT:1>:<EOL><INDENT>raise TemplateSyntaxError("<STR_LIT>" % bits[<NUM_LIT:0>])<EOL><DEDENT>return ChartbeatBottomNode()<EOL>

Bottom Chartbeat template tag.

Render the bottom Javascript code for Chartbeat.  You must supply
your Chartbeat User ID (as a string) in the ``CHARTBEAT_USER_ID``
setting.


_validate_no_args(token)<EOL>return HotjarNode()<EOL>


_validate_no_args(token)<EOL>return FacebookPixelHeadNode()<EOL>


_validate_no_args(token)<EOL>return FacebookPixelBodyNode()<EOL>


bits = token.split_contents()<EOL>if len(bits) > <NUM_LIT:1>:<EOL><INDENT>raise TemplateSyntaxError("<STR_LIT>" % bits[<NUM_LIT:0>])<EOL><DEDENT>return GaugesNode()<EOL>

Gaug.es template tag.

Renders Javascript code to gaug.es testing.  You must supply
your Site ID account number in the ``GAUGES_SITE_ID``
setting.


bits = token.split_contents()<EOL>if len(bits) > <NUM_LIT:1>:<EOL><INDENT>raise TemplateSyntaxError("<STR_LIT>" % bits[<NUM_LIT:0>])<EOL><DEDENT>return OlarkNode()<EOL>

Olark set-up template tag.

Renders Javascript code to set-up Olark chat.  You must supply
your site ID in the ``OLARK_SITE_ID`` setting.


bits = token.split_contents()<EOL>if len(bits) > <NUM_LIT:1>:<EOL><INDENT>raise TemplateSyntaxError("<STR_LIT>" % bits[<NUM_LIT:0>])<EOL><DEDENT>return ClickyNode()<EOL>

Clicky tracking template tag.

Renders Javascript code to track page visits.  You must supply
your Clicky Site ID (as a string) in the ``CLICKY_SITE_ID``
setting.


bits = token.split_contents()<EOL>if len(bits) > <NUM_LIT:1>:<EOL><INDENT>raise TemplateSyntaxError("<STR_LIT>" % bits[<NUM_LIT:0>])<EOL><DEDENT>return MixpanelNode()<EOL>

Mixpanel tracking template tag.

Renders Javascript code to track page visits.  You must supply
your Mixpanel token in the ``MIXPANEL_API_TOKEN`` setting.


bits = token.split_contents()<EOL>if len(bits) > <NUM_LIT:1>:<EOL><INDENT>raise TemplateSyntaxError("<STR_LIT>" % bits[<NUM_LIT:0>])<EOL><DEDENT>return KissMetricsNode()<EOL>

KISSinsights tracking template tag.

Renders Javascript code to track page visits.  You must supply
your KISSmetrics API key in the ``KISS_METRICS_API_KEY``
setting.


bits = token.split_contents()<EOL>if len(bits) > <NUM_LIT:1>:<EOL><INDENT>raise TemplateSyntaxError("<STR_LIT>" % bits[<NUM_LIT:0>])<EOL><DEDENT>return GoogleAnalyticsNode()<EOL>

Google Analytics tracking template tag.

Renders Javascript code to track page visits.  You must supply
your website property ID (as a string) in the
``GOOGLE_ANALYTICS_PROPERTY_ID`` setting.


bits = token.split_contents()<EOL>if len(bits) > <NUM_LIT:1>:<EOL><INDENT>raise TemplateSyntaxError("<STR_LIT>" % bits[<NUM_LIT:0>])<EOL><DEDENT>return SnapEngageNode()<EOL>

SnapEngage set-up template tag.

Renders Javascript code to set-up SnapEngage chat.  You must supply
your widget ID in the ``SNAPENGAGE_WIDGET_ID`` setting.


bits = token.split_contents()<EOL>if len(bits) > <NUM_LIT:1>:<EOL><INDENT>raise TemplateSyntaxError("<STR_LIT>" % bits[<NUM_LIT:0>])<EOL><DEDENT>return GoSquaredNode()<EOL>

GoSquared tracking template tag.

Renders Javascript code to track page visits.  You must supply
your GoSquared site token in the ``GOSQUARED_SITE_TOKEN`` setting.


def get_required_setting(setting, value_re, invalid_msg):

try:<EOL><INDENT>value = getattr(settings, setting)<EOL><DEDENT>except AttributeError:<EOL><INDENT>raise AnalyticalException("<STR_LIT>" % setting)<EOL><DEDENT>if not value:<EOL><INDENT>raise AnalyticalException("<STR_LIT>" % setting)<EOL><DEDENT>value = str(value)<EOL>if not value_re.search(value):<EOL><INDENT>raise AnalyticalException("<STR_LIT>"<EOL>% (setting, invalid_msg, value))<EOL><DEDENT>return value<EOL>

Return a constant from ``django.conf.settings``.  The `setting`
argument is the constant name, the `value_re` argument is a regular
expression used to validate the setting value and the `invalid_msg`
argument is used as exception message if the value is not valid.


try:<EOL><INDENT>return context['<STR_LIT:user>']<EOL><DEDENT>except KeyError:<EOL><INDENT>pass<EOL><DEDENT>try:<EOL><INDENT>request = context['<STR_LIT>']<EOL>return request.user<EOL><DEDENT>except (KeyError, AttributeError):<EOL><INDENT>pass<EOL><DEDENT>return None<EOL>

Get the user instance from the template context, if possible.

If the context does not contain a `request` or `user` attribute,
`None` is returned.


if callable(user.is_authenticated):<EOL><INDENT>return user.is_authenticated()<EOL><DEDENT>else:<EOL><INDENT>return user.is_authenticated<EOL><DEDENT>

Check if the user is authenticated.

    This is a compatibility function needed to support both Django 1.x and 2.x;
    Django 2.x turns the function into a proper boolean so function calls will
    fail.


def get_identity(context, prefix=None, identity_func=None, user=None):

if prefix is not None:<EOL><INDENT>try:<EOL><INDENT>return context['<STR_LIT>' % prefix]<EOL><DEDENT>except KeyError:<EOL><INDENT>pass<EOL><DEDENT><DEDENT>try:<EOL><INDENT>return context['<STR_LIT>']<EOL><DEDENT>except KeyError:<EOL><INDENT>pass<EOL><DEDENT>if getattr(settings, '<STR_LIT>', True):<EOL><INDENT>try:<EOL><INDENT>if user is None:<EOL><INDENT>user = get_user_from_context(context)<EOL><DEDENT>if get_user_is_authenticated(user):<EOL><INDENT>if identity_func is not None:<EOL><INDENT>return identity_func(user)<EOL><DEDENT>else:<EOL><INDENT>return user.get_username()<EOL><DEDENT><DEDENT><DEDENT>except (KeyError, AttributeError):<EOL><INDENT>pass<EOL><DEDENT><DEDENT>return None<EOL>

Get the identity of a logged in user from a template context.

The `prefix` argument is used to provide different identities to
different analytics services.  The `identity_func` argument is a
function that returns the identity of the user; by default the
identity is the username.


domain = context.get('<STR_LIT>' % prefix)<EOL>if domain is None:<EOL><INDENT>domain = context.get('<STR_LIT>')<EOL><DEDENT>if domain is None:<EOL><INDENT>domain = getattr(settings, '<STR_LIT>' % prefix.upper(), None)<EOL><DEDENT>if domain is None:<EOL><INDENT>domain = getattr(settings, '<STR_LIT>', None)<EOL><DEDENT>if domain is None:<EOL><INDENT>if '<STR_LIT>' in settings.INSTALLED_APPS:<EOL><INDENT>from django.contrib.sites.models import Site<EOL>try:<EOL><INDENT>domain = Site.objects.get_current().domain<EOL><DEDENT>except (ImproperlyConfigured, Site.DoesNotExist):<EOL><INDENT>pass<EOL><DEDENT><DEDENT><DEDENT>return domain<EOL>

Return the domain used for the tracking code.  Each service may be
configured with its own domain (called `<name>_domain`), or a
django-analytical-wide domain may be set (using `analytical_domain`.

If no explicit domain is found in either the context or the
settings, try to get the domain from the contrib sites framework.


try:<EOL><INDENT>request = context['<STR_LIT>']<EOL>remote_ip = request.META.get('<STR_LIT>', '<STR_LIT>')<EOL>if not remote_ip:<EOL><INDENT>remote_ip = request.META.get('<STR_LIT>', '<STR_LIT>')<EOL><DEDENT>if not remote_ip:<EOL><INDENT>return False<EOL><DEDENT>internal_ips = None<EOL>if prefix is not None:<EOL><INDENT>internal_ips = getattr(settings, '<STR_LIT>' % prefix, None)<EOL><DEDENT>if internal_ips is None:<EOL><INDENT>internal_ips = getattr(settings, '<STR_LIT>', None)<EOL><DEDENT>if internal_ips is None:<EOL><INDENT>internal_ips = getattr(settings, '<STR_LIT>', None)<EOL><DEDENT>return remote_ip in (internal_ips or [])<EOL><DEDENT>except (KeyError, AttributeError):<EOL><INDENT>return False<EOL><DEDENT>

Return whether the visitor is coming from an internal IP address,
based on information from the template context.

The prefix is used to allow different analytics services to have
different notions of internal addresses.


return HTML_COMMENT % {'<STR_LIT:html>': html, '<STR_LIT>': service}<EOL>

Disable HTML code by commenting it out.

The `service` argument is used to display a friendly message.


return [target.getParam(getattr(ode, '<STR_LIT>'.format(param, s)))<EOL>for s in ['<STR_LIT>', '<STR_LIT:2>', '<STR_LIT:3>'][:dof]]<EOL>

Get the given param from each of the DOFs for a joint.


def _set_params(target, param, values, dof):

if not isinstance(values, (list, tuple, np.ndarray)):<EOL><INDENT>values = [values] * dof<EOL><DEDENT>assert dof == len(values)<EOL>for s, value in zip(['<STR_LIT>', '<STR_LIT:2>', '<STR_LIT:3>'][:dof], values):<EOL><INDENT>target.setParam(getattr(ode, '<STR_LIT>'.format(param, s)), value)<EOL><DEDENT>

Set the given param for each of the DOFs for a joint.


x, y, z = axis<EOL>r = np.sqrt(x * x + y * y + z * z)<EOL>st = np.sin(theta / <NUM_LIT>)<EOL>ct = np.cos(theta / <NUM_LIT>)<EOL>return [x * st / r, y * st / r, z * st / r, ct]<EOL>

Given an angle and an axis, create a quaternion.


x = np.zeros(<NUM_LIT>)<EOL>t = <NUM_LIT:0.><EOL>for b in bodies:<EOL><INDENT>m = b.mass<EOL>x += b.body_to_world(m.c) * m.mass<EOL>t += m.mass<EOL><DEDENT>return x / t<EOL>

Given a set of bodies, compute their center of mass in world coordinates.


return self.ode_body.getMass()<EOL>


return BodyState(self.name,<EOL>tuple(self.position),<EOL>tuple(self.quaternion),<EOL>tuple(self.linear_velocity),<EOL>tuple(self.angular_velocity))<EOL>

The state of this body includes:

            - name of the body (str)
            - position (3-tuple)
            - quaternion (4-tuple)
            - linear velocity (3-tuple)
            - angular velocity (3-tuple)


assert self.name == state.name,'<STR_LIT>'.format(state.name, self.name)<EOL>self.position = state.position<EOL>self.quaternion = state.quaternion<EOL>self.linear_velocity = state.linear_velocity<EOL>self.angular_velocity = state.angular_velocity<EOL>

Set the state of this body.

        Parameters
        ----------
        state : BodyState tuple
            The desired state of the body.


return np.array(self.ode_body.getPosition())<EOL>

The (x, y, z) coordinates of the center of this body.


self.ode_body.setPosition(tuple(position))<EOL>

Set the (x, y, z) coordinates of the center of this body.

        Parameters
        ----------
        position : 3-tuple of float
            The coordinates of the desired center of this body.


return np.array(self.ode_body.getRotation()).reshape((<NUM_LIT:3>, <NUM_LIT:3>))<EOL>


if isinstance(rotation, np.ndarray):<EOL><INDENT>rotation = rotation.ravel()<EOL><DEDENT>self.ode_body.setRotation(tuple(rotation))<EOL>

Set the rotation of this body using a rotation matrix.

        Parameters
        ----------
        rotation : sequence of 9 floats
            The desired rotation matrix for this body.


return np.array(self.ode_body.getQuaternion())<EOL>

The (w, x, y, z) rotation quaternion for this body.


return np.array(self.ode_body.getLinearVel())<EOL>

Current linear velocity of this body (in world coordinates).


self.ode_body.setLinearVel(tuple(velocity))<EOL>

Set the linear velocity for this body.

        Parameters
        ----------
        velocity : 3-tuple of float
            The desired velocity for this body, in world coordinates.


return np.array(self.ode_body.getAngularVel())<EOL>

Current angular velocity of this body (in world coordinates).


self.ode_body.setAngularVel(tuple(velocity))<EOL>

Set the angular velocity for this body.

        Parameters
        ----------
        velocity : 3-tuple of float
            The desired angular velocity for this body, in world coordinates.


return np.array(self.ode_body.getForce())<EOL>

Current net force acting on this body (in world coordinates).


self.ode_body.setForce(tuple(force))<EOL>

Set the force acting on this body.

        Parameters
        ----------
        force : 3-tuple of float
            The desired force acting on this body, in world coordinates.


return np.array(self.ode_body.getTorque())<EOL>

Current net torque acting on this body (in world coordinates).


self.ode_body.setTorque(tuple(torque))<EOL>

Set the torque acting on this body.

        Parameters
        ----------
        torque : 3-tuple of float
            The desired torque acting on this body, in world coordinates.


return self.ode_body.isKinematic()<EOL>


if is_kinematic:<EOL><INDENT>self.ode_body.setKinematic()<EOL><DEDENT>else:<EOL><INDENT>self.ode_body.setDynamic()<EOL><DEDENT>

Set the kinematic/dynamic attribute for this body.

        In pagoda, kinematic bodies have infinite mass and do interact with
        other bodies via collisions.

        Parameters
        ----------
        is_kinematic : bool
            If True, this body will be set to kinematic. If False, it will be
            set to dynamic.


return self.ode_body.getGravityMode()<EOL>


self.ode_body.setGravityMode(follows_gravity)<EOL>

Set whether this body follows gravity.

        Parameters
        ----------
        follows_gravity : bool
            This body will follow gravity iff this parameter is True.


return np.dot(x, self.rotation)<EOL>

Rotate the given vector to the same orientation as this body.

        Parameters
        ----------
        x : 3-tuple of float
            A point in three dimensions.

        Returns
        -------
        xrot : 3-tuple of float
            The same point after rotation into the orientation of this body.


return np.array(self.ode_body.getRelPointPos(tuple(position)))<EOL>

Convert a body-relative offset to world coordinates.

        Parameters
        ----------
        position : 3-tuple of float
            A tuple giving body-relative offsets.

        Returns
        -------
        position : 3-tuple of float
            A tuple giving the world coordinates of the given offset.


return np.array(self.ode_body.getPosRelPoint(tuple(position)))<EOL>

Convert a point in world coordinates to a body-relative offset.

        Parameters
        ----------
        position : 3-tuple of float
            A world coordinates position.

        Returns
        -------
        offset : 3-tuple of float
            A tuple giving the body-relative offset of the given position.


return np.array(self.body_to_world(offset * self.dimensions / <NUM_LIT:2>))<EOL>

Convert a relative body offset to world coordinates.

        Parameters
        ----------
        offset : 3-tuple of float
            The offset of the desired point, given as a relative fraction of the
            size of this body. For example, offset (0, 0, 0) is the center of
            the body, while (0.5, -0.2, 0.1) describes a point halfway from the
            center towards the maximum x-extent of the body, 20% of the way from
            the center towards the minimum y-extent, and 10% of the way from the
            center towards the maximum z-extent.

        Returns
        -------
        position : 3-tuple of float
            A position in world coordinates of the given body offset.


def add_force(self, force, relative=False, position=None, relative_position=None):

b = self.ode_body<EOL>if relative_position is not None:<EOL><INDENT>op = b.addRelForceAtRelPos if relative else b.addForceAtRelPos<EOL>op(force, relative_position)<EOL><DEDENT>elif position is not None:<EOL><INDENT>op = b.addRelForceAtPos if relative else b.addForceAtPos<EOL>op(force, position)<EOL><DEDENT>else:<EOL><INDENT>op = b.addRelForce if relative else b.addForce<EOL>op(force)<EOL><DEDENT>

Add a force to this body.

        Parameters
        ----------
        force : 3-tuple of float
            A vector giving the forces along each world or body coordinate axis.
        relative : bool, optional
            If False, the force values are assumed to be given in the world
            coordinate frame. If True, they are assumed to be given in the
            body-relative coordinate frame. Defaults to False.
        position : 3-tuple of float, optional
            If given, apply the force at this location in world coordinates.
            Defaults to the current position of the body.
        relative_position : 3-tuple of float, optional
            If given, apply the force at this relative location on the body. If
            given, this method ignores the ``position`` parameter.


def add_torque(self, torque, relative=False):

op = self.ode_body.addRelTorque if relative else self.ode_body.addTorque<EOL>op(torque)<EOL>

Add a torque to this body.

        Parameters
        ----------
        force : 3-tuple of float
            A vector giving the torque along each world or body coordinate axis.
        relative : bool, optional
            If False, the torque values are assumed to be given in the world
            coordinate frame. If True, they are assumed to be given in the
            body-relative coordinate frame. Defaults to False.


def join_to(self, joint, other_body=None, **kwargs):

self.world.join(joint, self, other_body, **kwargs)<EOL>

Connect this body to another one using a joint.

        This method creates a joint to fasten this body to the other one. See
        :func:`World.join`.

        Parameters
        ----------
        joint : str
            The type of joint to use when connecting these bodies.
        other_body : :class:`Body` or str, optional
            The other body to join with this one. If not given, connects this
            body to the world.


def connect_to(self, joint, other_body, offset=(<NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:0>), other_offset=(<NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:0>),<EOL>**kwargs):

anchor = self.world.move_next_to(self, other_body, offset, other_offset)<EOL>self.world.join(joint, self, other_body, anchor=anchor, **kwargs)<EOL>

Move another body next to this one and join them together.

        This method will move the ``other_body`` so that the anchor points for
        the joint coincide. It then creates a joint to fasten the two bodies
        together. See :func:`World.move_next_to` and :func:`World.join`.

        Parameters
        ----------
        joint : str
            The type of joint to use when connecting these bodies.
        other_body : :class:`Body` or str
            The other body to join with this one.
        offset : 3-tuple of float, optional
            The body-relative offset where the anchor for the joint should be
            placed. Defaults to (0, 0, 0). See :func:`World.move_next_to` for a
            description of how offsets are specified.
        other_offset : 3-tuple of float, optional
            The offset on the second body where the joint anchor should be
            placed. Defaults to (0, 0, 0). Like ``offset``, this is given as an
            offset relative to the size and shape of ``other_body``.


return self.ode_obj.getFeedback()<EOL>

Feedback buffer (list of 3-tuples) for this ODE motor/joint.


return [self.ode_obj.getPosition(i) for i in range(self.LDOF)]<EOL>

List of positions for linear degrees of freedom.


return [self.ode_obj.getPositionRate(i) for i in range(self.LDOF)]<EOL>

List of position rates for linear degrees of freedom.


return [self.ode_obj.getAngle(i) for i in range(self.ADOF)]<EOL>

List of angles for rotational degrees of freedom.


return [self.ode_obj.getAngleRate(i) for i in range(self.ADOF)]<EOL>

List of angle rates for rotational degrees of freedom.


return [np.array(self.ode_obj.getAxis(i))<EOL>for i in range(self.ADOF or self.LDOF)]<EOL>

List of axes for this object's degrees of freedom.


assert self.ADOF == len(axes) or self.LDOF == len(axes)<EOL>for i, axis in enumerate(axes):<EOL><INDENT>if axis is not None:<EOL><INDENT>self.ode_obj.setAxis(i, <NUM_LIT:0>, axis)<EOL><DEDENT><DEDENT>

Set the axes for this object's degrees of freedom.

        Parameters
        ----------
        axes : list of axes specifications
            A list of axis values to set. This list must have the same number of
            elements as the degrees of freedom of the underlying ODE object.
            Each element can be

            (a) None, which has no effect on the corresponding axis, or
            (b) three floats specifying the axis to set.


return _get_params(self.ode_obj, '<STR_LIT>', self.ADOF + self.LDOF)<EOL>

List of lo stop values for this object's degrees of freedom.


_set_params(self.ode_obj, '<STR_LIT>', lo_stops, self.ADOF + self.LDOF)<EOL>

Set the lo stop values for this object's degrees of freedom.

        Parameters
        ----------
        lo_stops : float or sequence of float
            A lo stop value to set on all degrees of freedom, or a list
            containing one such value for each degree of freedom. For rotational
            degrees of freedom, these values must be in radians.


List of hi stop values for this object's degrees of freedom.


_set_params(self.ode_obj, '<STR_LIT>', hi_stops, self.ADOF + self.LDOF)<EOL>

Set the hi stop values for this object's degrees of freedom.

        Parameters
        ----------
        hi_stops : float or sequence of float
            A hi stop value to set on all degrees of freedom, or a list
            containing one such value for each degree of freedom. For rotational
            degrees of freedom, these values must be in radians.


List of target velocity values for rotational degrees of freedom.


_set_params(self.ode_obj, '<STR_LIT>', velocities, self.ADOF + self.LDOF)<EOL>

Set the target velocities for this object's degrees of freedom.

        Parameters
        ----------
        velocities : float or sequence of float
            A target velocity value to set on all degrees of freedom, or a list
            containing one such value for each degree of freedom. For rotational
            degrees of freedom, these values must be in radians / second.


List of max force values for rotational degrees of freedom.


_set_params(self.ode_obj, '<STR_LIT>', max_forces, self.ADOF + self.LDOF)<EOL>

Set the maximum forces for this object's degrees of freedom.

        Parameters
        ----------
        max_forces : float or sequence of float
            A maximum force value to set on all degrees of freedom, or a list
            containing one such value for each degree of freedom.


List of ERP values for this object's degrees of freedom.


_set_params(self.ode_obj, '<STR_LIT>', erps, self.ADOF + self.LDOF)<EOL>

Set the ERP values for this object's degrees of freedom.

        Parameters
        ----------
        erps : float or sequence of float
            An ERP value to set on all degrees of freedom, or a list
            containing one such value for each degree of freedom.


List of CFM values for this object's degrees of freedom.


_set_params(self.ode_obj, '<STR_LIT>', cfms, self.ADOF + self.LDOF)<EOL>

Set the CFM values for this object's degrees of freedom.

        Parameters
        ----------
        cfms : float or sequence of float
            A CFM value to set on all degrees of freedom, or a list
            containing one such value for each degree of freedom.


_set_params(self.ode_obj, '<STR_LIT>', stop_cfms, self.ADOF + self.LDOF)<EOL>

Set the CFM values for this object's DOF limits.

        Parameters
        ----------
        stop_cfms : float or sequence of float
            A CFM value to set on all degrees of freedom limits, or a list
            containing one such value for each degree of freedom limit.


_set_params(self.ode_obj, '<STR_LIT>', stop_erps, self.ADOF + self.LDOF)<EOL>

Set the ERP values for this object's DOF limits.

        Parameters
        ----------
        stop_erps : float or sequence of float
            An ERP value to set on all degrees of freedom limits, or a list
            containing one such value for each degree of freedom limit.


return self.ode_obj.getNumAxes()<EOL>

Number of angular degrees of freedom for this motor.


return [np.array(self.ode_obj.getAxis(i)) for i in range(self.ADOF)]<EOL>

List of axes for this object's degrees of freedom.


assert len(axes) == self.ADOF<EOL>for i, ax in enumerate(axes):<EOL><INDENT>if ax is None:<EOL><INDENT>continue<EOL><DEDENT>if not isinstance(ax, dict):<EOL><INDENT>ax = dict(axis=ax)<EOL><DEDENT>self.ode_obj.setAxis(i, ax.get('<STR_LIT>', <NUM_LIT:0>), ax['<STR_LIT>'])<EOL><DEDENT>

Set the axes for this object's degrees of freedom.

        Parameters
        ----------
        axes : list of axis parameters
            A list of axis values to set. This list must have the same number of
            elements as the degrees of freedom of the underlying ODE object.
            Each element can be

            (a) None, which has no effect on the corresponding axis, or
            (b) three floats specifying the axis to set, or
            (c) a dictionary with an "axis" key specifying the axis to set and
                an optional "rel" key (defaults to 0) specifying the relative
                body to set the axis on.


Add the given torques along this motor's axes.

        Parameters
        ----------
        torques : sequence of float
            A sequence of torque values to apply to this motor's axes.


return self.ode_obj.getNumAxes()<EOL>

Number of linear degrees of freedom for this motor.


return np.array(self.ode_obj.getAnchor())<EOL>

3-tuple specifying location of this joint's anchor.


return np.array(self.ode_obj.getAnchor2())<EOL>

3-tuple specifying location of the anchor on the second body.


Add the given torques along this joint's axes.

        Parameters
        ----------
        torques : sequence of float
            A sequence of torque values to apply to this motor's axes.


return [self.ode_obj.getPosition()]<EOL>

List of positions for this joint's linear degrees of freedom.


return [self.ode_obj.getPositionRate()]<EOL>

List of position rates for this joint's degrees of freedom.


return [np.array(self.ode_obj.getAxis())]<EOL>


self.lmotor.axes = [axes[<NUM_LIT:0>]]<EOL>self.ode_obj.setAxis(tuple(axes[<NUM_LIT:0>]))<EOL>

Set the linear axis of displacement for this joint.

        Parameters
        ----------
        axes : list containing one 3-tuple of floats
            A list of the axes for this joint. For a slider joint, which has one
            degree of freedom, this must contain one 3-tuple specifying the X,
            Y, and Z axis for the joint.


return [self.ode_obj.getAngle()]<EOL>

List of angles for this joint's rotational degrees of freedom.


return [self.ode_obj.getAngleRate()]<EOL>

List of angle rates for this joint's degrees of freedom.


self.amotor.axes = [axes[<NUM_LIT:0>]]<EOL>self.ode_obj.setAxis(tuple(axes[<NUM_LIT:0>]))<EOL>

Set the angular axis of rotation for this joint.

        Parameters
        ----------
        axes : list containing one 3-tuple of floats
            A list of the axes for this joint. For a hinge joint, which has one
            degree of freedom, this must contain one 3-tuple specifying the X,
            Y, and Z axis for the joint.


Axis of rotation and displacement for this joint.


return [np.array(self.ode_obj.getAxis1()),<EOL>np.array(self.ode_obj.getAxis2())]<EOL>

A list of axes of rotation for this joint.


return [self.ode_obj.getAngle1(), self.ode_obj.getAngle2()]<EOL>

A list of two angles for this joint's degrees of freedom.


return [self.ode_obj.getAngle1Rate(), self.ode_obj.getAngle2Rate()]<EOL>

A list of two angle rates for this joint's degrees of freedom.


return self.ode_world.getGravity()<EOL>


return self.ode_world.setGravity(gravity)<EOL>

Set the gravity vector in the world.

        Parameters
        ----------
        gravity : 3-tuple of float
            The vector where gravity should point.


return self.ode_world.getCFM()<EOL>


return self.ode_world.setCFM(cfm)<EOL>

Set the global CFM value.

        Parameters
        ----------
        cfm : float
            The desired global CFM value.


return self.ode_world.getERP()<EOL>


return self.ode_world.setERP(erp)<EOL>

Set the global ERP value.

        Parameters
        ----------
        erp : float
            The desired global ERP value.


for k in sorted(self._bodies):<EOL><INDENT>yield self._bodies[k]<EOL><DEDENT>

Sequence of all bodies in the world, sorted by name.


for k in sorted(self._joints):<EOL><INDENT>yield self._joints[k]<EOL><DEDENT>

Sequence of all joints in the world, sorted by name.


return self._bodies.get(key, key)<EOL>

Get a body by key.

        Parameters
        ----------
        key : str, None, or :class:`Body`
            The key for looking up a body. If this is None or a :class:`Body`
            instance, the key itself will be returned.

        Returns
        -------
        body : :class:`Body`
            The body in the world with the given key.