<EOL>inputparams = copy.deepcopy(TRILEGAL_INPUT_PARAMS)<EOL>inputparams['<STR_LIT>'] = '<STR_LIT:1>' if usebinaries else '<STR_LIT:0>'<EOL>inputparams['<STR_LIT>'] = '<STR_LIT>' % extinction_sigma<EOL>inputparams['<STR_LIT>'] = '<STR_LIT>' % field_deg2<EOL>inputparams['<STR_LIT>'] = str(maglim_filtercol)<EOL>inputparams['<STR_LIT>'] = '<STR_LIT>' % magnitude_limit<EOL>inputparams['<STR_LIT>'] = str(trilegal_version)<EOL>inputparams['<STR_LIT>'] = '<STR_LIT>' % gal_lon<EOL>inputparams['<STR_LIT>'] = '<STR_LIT>' % gal_lat<EOL>if field_deg2 > <NUM_LIT>:<EOL><INDENT>LOGERROR("<STR_LIT>")<EOL>return None<EOL><DEDENT>extinction_info = dust.extinction_query(gal_lon,<EOL>gal_lat,<EOL>coordtype='<STR_LIT>',<EOL>forcefetch=forcefetch,<EOL>verbose=verbose,<EOL>timeout=timeout)<EOL>try:<EOL><INDENT>Av_infinity = extinction_info['<STR_LIT>']['<STR_LIT>']['<STR_LIT>']<EOL>inputparams['<STR_LIT>'] = '<STR_LIT>' % Av_infinity<EOL><DEDENT>except Exception as e:<EOL><INDENT>LOGEXCEPTION(<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>' % (gal_lon, gal_lat,<EOL>inputparams['<STR_LIT>'])<EOL>)<EOL><DEDENT>if filtersystem in TRILEGAL_FILTER_SYSTEMS:<EOL><INDENT>inputparams['<STR_LIT>'] = (<EOL>TRILEGAL_FILTER_SYSTEMS[filtersystem]['<STR_LIT>']<EOL>)<EOL><DEDENT>else:<EOL><INDENT>LOGERROR('<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>' % filtersystem)<EOL>return None<EOL><DEDENT>trilegal_params = copy.deepcopy(TRILEGAL_DEFAULT_PARAMS)<EOL>trilegal_params.update(inputparams)<EOL>if extraparams and isinstance(extraparams, dict):<EOL><INDENT>trilegal_params.update(extraparams)<EOL><DEDENT>if '<STR_LIT>' in cachedir:<EOL><INDENT>cachedir = os.path.expanduser(cachedir)<EOL><DEDENT>if not os.path.exists(cachedir):<EOL><INDENT>os.makedirs(cachedir)<EOL><DEDENT>cachekey = repr(inputparams)<EOL>cachekey = hashlib.sha256(cachekey.encode()).hexdigest()<EOL>cachefname = os.path.join(cachedir, '<STR_LIT>' % cachekey)<EOL>provenance = '<STR_LIT>'<EOL>lockfile = os.path.join(cachedir, '<STR_LIT>' % cachekey)<EOL>if forcefetch or (not os.path.exists(cachefname)):<EOL><INDENT>if os.path.exists(lockfile):<EOL><INDENT>with open(lockfile,'<STR_LIT:r>') as infd:<EOL><INDENT>lock_contents = infd.read()<EOL><DEDENT>lock_contents = lock_contents.replace('<STR_LIT:\n>','<STR_LIT>')<EOL>LOGERROR('<STR_LIT>'<EOL>'<STR_LIT>' %<EOL>lock_contents)<EOL>return None<EOL><DEDENT>else:<EOL><INDENT>with open(lockfile,'<STR_LIT:w>') as outfd:<EOL><INDENT>outfd.write(datetime.utcnow().isoformat())<EOL><DEDENT><DEDENT>provenance = '<STR_LIT>'<EOL>try:<EOL><INDENT>if verbose:<EOL><INDENT>LOGINFO('<STR_LIT>'<EOL>% repr(inputparams))<EOL><DEDENT>posturl = TRILEGAL_POSTURL.format(formversion=trilegal_version)<EOL>req = requests.post(posturl,<EOL>data=trilegal_params,<EOL>timeout=timeout)<EOL>resp = req.text<EOL>resultfile = TRILEGAL_REGEX.search(resp)<EOL>if resultfile:<EOL><INDENT>resultfile = resultfile[<NUM_LIT:0>]<EOL>waitdone = False<EOL>timeelapsed = <NUM_LIT:0.0><EOL>resultfileurl = '<STR_LIT>' % (<EOL>TRILEGAL_BASEURL,<EOL>resultfile.replace('<STR_LIT>','<STR_LIT>')<EOL>)<EOL>if verbose:<EOL><INDENT>LOGINFO(<EOL>'<STR_LIT>'<EOL>)<EOL><DEDENT>while not waitdone:<EOL><INDENT>if timeelapsed > maxtimeout:<EOL><INDENT>LOGERROR('<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT:%s>' % repr(inputparams))<EOL>if os.path.exists(lockfile):<EOL><INDENT>os.remove(lockfile)<EOL><DEDENT>return None<EOL><DEDENT>time.sleep(refresh)<EOL>timeelapsed = timeelapsed + refresh<EOL>try:<EOL><INDENT>resreq = requests.get(resultfileurl)<EOL>resreq.raise_for_status()<EOL>if verbose:<EOL><INDENT>LOGINFO('<STR_LIT>')<EOL><DEDENT>with gzip.open(cachefname,'<STR_LIT:wb>') as outfd:<EOL><INDENT>for chunk in resreq.iter_content(chunk_size=<NUM_LIT>):<EOL><INDENT>outfd.write(chunk)<EOL><DEDENT><DEDENT>tablefname = cachefname<EOL>waitdone = True<EOL>if verbose:<EOL><INDENT>LOGINFO('<STR_LIT>')<EOL><DEDENT><DEDENT>except Exception as e:<EOL><INDENT>if verbose:<EOL><INDENT>LOGINFO('<STR_LIT>'<EOL>'<STR_LIT>'<EOL>% (timeelapsed, resultfileurl))<EOL><DEDENT>continue<EOL><DEDENT><DEDENT><DEDENT>else:<EOL><INDENT>LOGERROR('<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>')<EOL>LOGINFO(resp)<EOL>if os.path.exists(lockfile):<EOL><INDENT>os.remove(lockfile)<EOL><DEDENT>return None<EOL><DEDENT><DEDENT>except requests.exceptions.Timeout as e:<EOL><INDENT>LOGERROR('<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT:%s>' % repr(inputparams))<EOL>return None<EOL><DEDENT>except Exception as e:<EOL><INDENT>LOGEXCEPTION('<STR_LIT>'<EOL>'<STR_LIT:%s>' % repr(inputparams))<EOL>return None<EOL><DEDENT>finally:<EOL><INDENT>if os.path.exists(lockfile):<EOL><INDENT>os.remove(lockfile)<EOL><DEDENT><DEDENT><DEDENT>else:<EOL><INDENT>if verbose:<EOL><INDENT>LOGINFO('<STR_LIT>'<EOL>'<STR_LIT>' %<EOL>(repr(inputparams)))<EOL><DEDENT>tablefname = cachefname<EOL><DEDENT>resdict = {'<STR_LIT>':inputparams,<EOL>'<STR_LIT>':extraparams,<EOL>'<STR_LIT>':provenance,<EOL>'<STR_LIT>':tablefname}<EOL>return resdict<EOL>

This queries the TRILEGAL model form, downloads results, and parses them.

    Parameters
    ----------

    gal_lon,gal_lat : float
        These are the center galactic longitude and latitude in degrees.

    filtersystem : str
        This is a key in the TRILEGAL_FILTER_SYSTEMS dict. Use the function
        :py:func:`astrobase.services.trilegal.list_trilegal_filtersystems` to
        see a nicely formatted table with the key and description for each of
        these.

    field_deg2 : float
        The area of the simulated field in square degrees.

    usebinaries : bool
        If this is True, binaries will be present in the model results.

    extinction_sigma : float
        This is the applied std dev around the `Av_extinction` value for the
        galactic coordinates requested.

    magnitude_limit : float
        This is the limiting magnitude of the simulation in the
        `maglim_filtercol` band index of the filter system chosen.

    maglim_filtercol : int
        The index in the filter system list of the magnitude limiting band.

    trilegal_version : float
        This is the the version of the TRILEGAL form to use. This can usually be
        left as-is.

    extraparams : dict or None
        This is a dict that can be used to override parameters of the model
        other than the basic ones used for input to this function. All
        parameters are listed in `TRILEGAL_DEFAULT_PARAMS` above. See:

        http://stev.oapd.inaf.it/cgi-bin/trilegal

        for explanations of these parameters.

    forcefetch : bool
        If this is True, the query will be retried even if cached results for
        it exist.

    cachedir : str
        This points to the directory where results will be downloaded.

    verbose : bool
        If True, will indicate progress and warn of any issues.

    timeout : float
        This sets the amount of time in seconds to wait for the service to
        respond to our initial request.

    refresh : float
        This sets the amount of time in seconds to wait before checking if the
        result file is available. If the results file isn't available after
        `refresh` seconds have elapsed, the function will wait for `refresh`
        seconds continuously, until `maxtimeout` is reached or the results file
        becomes available.

    maxtimeout : float
        The maximum amount of time in seconds to wait for a result to become
        available after submitting our query request.

    Returns
    -------

    dict
        This returns a dict of the form::

            {'params':the input param dict used,
             'extraparams':any extra params used,
             'provenance':'cached' or 'new download',
             'tablefile':the path on disk to the downloaded model text file}


infd = gzip.open(modelfile)<EOL>model = np.genfromtxt(infd,names=True)<EOL>infd.close()<EOL>return model<EOL>

This reads a downloaded TRILEGAL model file.

Parameters
----------

modelfile : str
    Path to the downloaded model file to read.

Returns
-------

np.recarray
    Returns the model table as a Numpy record array.


service = '<STR_LIT>'<EOL>xmatch_input = {'<STR_LIT>':[{'<STR_LIT:name>':'<STR_LIT>','<STR_LIT:type>':'<STR_LIT:float>'},<EOL>{'<STR_LIT:name>':'<STR_LIT>','<STR_LIT:type>':'<STR_LIT:float>'}]}<EOL>xmatch_input['<STR_LIT:data>'] = [{'<STR_LIT>':x, '<STR_LIT>':y} for (x,y) in zip(ra, decl)]<EOL>params = {'<STR_LIT>':'<STR_LIT>',<EOL>'<STR_LIT>':'<STR_LIT>',<EOL>'<STR_LIT>':radius_arcsec/<NUM_LIT>}<EOL>return mast_query(service,<EOL>params,<EOL>data=xmatch_input,<EOL>jitter=jitter,<EOL>apiversion=apiversion,<EOL>forcefetch=forcefetch,<EOL>cachedir=cachedir,<EOL>verbose=verbose,<EOL>timeout=timeout,<EOL>refresh=refresh,<EOL>maxtimeout=maxtimeout,<EOL>maxtries=maxtries,<EOL>raiseonfail=raiseonfail)<EOL>

This does a cross-match with TIC.

    Parameters
    ----------

    ra,decl : np.arrays or lists of floats
        The coordinates that will be cross-matched against the TIC.

    radius_arcsec : float
        The cross-match radius in arcseconds.

    apiversion : str
        The API version of the MAST service to use. This sets the URL that this
        function will call, using `apiversion` as key into the `MAST_URLS` dict
        above.

    forcefetch : bool
        If this is True, the query will be retried even if cached results for
        it exist.

    cachedir : str
        This points to the directory where results will be downloaded.

    verbose : bool
        If True, will indicate progress and warn of any issues.

    timeout : float
        This sets the amount of time in seconds to wait for the service to
        respond to our initial request.

    refresh : float
        This sets the amount of time in seconds to wait before checking if the
        result file is available. If the results file isn't available after
        `refresh` seconds have elapsed, the function will wait for `refresh`
        seconds continuously, until `maxtimeout` is reached or the results file
        becomes available.

    maxtimeout : float
        The maximum amount of time in seconds to wait for a result to become
        available after submitting our query request.

    maxtries : int
        The maximum number of tries (across all mirrors tried) to make to either
        submit the request or download the results, before giving up.

    jitter : float
        This is used to control the scale of the random wait in seconds before
        starting the query. Useful in parallelized situations.

    raiseonfail : bool
        If this is True, the function will raise an Exception if something goes
        wrong, instead of returning None.

    Returns
    -------

    dict
        This returns a dict of the following form::

            {'params':dict of the input params used for the query,
             'provenance':'cache' or 'new download',
             'result':path to the file on disk with the downloaded data table}


This runs a TESS Input Catalog cone search on MAST.

    If you use this, please cite the TIC paper (Stassun et al 2018;
    http://adsabs.harvard.edu/abs/2018AJ....156..102S). Also see the "living"
    TESS input catalog docs:

    https://docs.google.com/document/d/1zdiKMs4Ld4cXZ2DW4lMX-fuxAF6hPHTjqjIwGqnfjqI

    Also see: https://mast.stsci.edu/api/v0/_t_i_cfields.html for the fields
    returned by the service and present in the result JSON file.

    Parameters
    ----------

    ra,decl : float
        The center coordinates of the cone-search in decimal degrees.

    radius_arcmin : float
        The cone-search radius in arcminutes.

    apiversion : str
        The API version of the MAST service to use. This sets the URL that this
        function will call, using `apiversion` as key into the `MAST_URLS` dict
        above.

    forcefetch : bool
        If this is True, the query will be retried even if cached results for
        it exist.

    cachedir : str
        This points to the directory where results will be downloaded.

    verbose : bool
        If True, will indicate progress and warn of any issues.

    timeout : float
        This sets the amount of time in seconds to wait for the service to
        respond to our initial request.

    refresh : float
        This sets the amount of time in seconds to wait before checking if the
        result file is available. If the results file isn't available after
        `refresh` seconds have elapsed, the function will wait for `refresh`
        seconds continuously, until `maxtimeout` is reached or the results file
        becomes available.

    maxtimeout : float
        The maximum amount of time in seconds to wait for a result to become
        available after submitting our query request.

    maxtries : int
        The maximum number of tries (across all mirrors tried) to make to either
        submit the request or download the results, before giving up.

    jitter : float
        This is used to control the scale of the random wait in seconds before
        starting the query. Useful in parallelized situations.

    raiseonfail : bool
        If this is True, the function will raise an Exception if something goes
        wrong, instead of returning None.

    Returns
    -------

    dict
        This returns a dict of the following form::

            {'params':dict of the input params used for the query,
             'provenance':'cache' or 'new download',
             'result':path to the file on disk with the downloaded data table}


<EOL>query = (<EOL>"<STR_LIT>"<EOL>"<STR_LIT>"<EOL>"<STR_LIT>"<EOL>"<STR_LIT>"<EOL>"<STR_LIT>"<EOL>)<EOL>ra_min, ra_max, decl_min, decl_max = radeclbox<EOL>ra_center = (ra_max + ra_min)/<NUM_LIT><EOL>decl_center = (decl_max + decl_min)/<NUM_LIT><EOL>ra_width = ra_max - ra_min<EOL>decl_height = decl_max - decl_min<EOL>if extra_filter is not None:<EOL><INDENT>extra_filter_str = '<STR_LIT>' % extra_filter<EOL><DEDENT>else:<EOL><INDENT>extra_filter_str = '<STR_LIT>'<EOL><DEDENT>formatted_query = query.format(columns='<STR_LIT:U+002CU+0020>'.join(columns),<EOL>extra_filter_str=extra_filter_str,<EOL>ra_center=ra_center,<EOL>decl_center=decl_center,<EOL>ra_width=ra_width,<EOL>decl_height=decl_height)<EOL>return tap_query(formatted_query,<EOL>gaia_mirror=gaia_mirror,<EOL>returnformat=returnformat,<EOL>forcefetch=forcefetch,<EOL>cachedir=cachedir,<EOL>verbose=verbose,<EOL>timeout=timeout,<EOL>refresh=refresh,<EOL>maxtimeout=maxtimeout,<EOL>maxtries=maxtries,<EOL>complete_query_later=complete_query_later)<EOL>

This queries the GAIA TAP service for a list of objects in an equatorial
    coordinate box.

    Parameters
    ----------

    radeclbox : sequence of four floats
        This defines the box to search in::

            [ra_min, ra_max, decl_min, decl_max]

    gaia_mirror : {'gaia','heidelberg','vizier'} or None
        This is the key used to select a GAIA catalog mirror from the
        `GAIA_URLS` dict above. If set, the specified mirror will be used. If
        None, a random mirror chosen from that dict will be used.

    columns : sequence of str
        This indicates which columns from the GAIA table to request for the
        objects found within the search radius.

    extra_filter: str or None
        If this is provided, must be a valid ADQL filter string that is used to
        further filter the cone-search results.

    returnformat : {'csv','votable','json'}
        The returned file format to request from the GAIA catalog service.

    forcefetch : bool
        If this is True, the query will be retried even if cached results for
        it exist.

    cachedir : str
        This points to the directory where results will be downloaded.

    verbose : bool
        If True, will indicate progress and warn of any issues.

    timeout : float
        This sets the amount of time in seconds to wait for the service to
        respond to our initial request.

    refresh : float
        This sets the amount of time in seconds to wait before checking if the
        result file is available. If the results file isn't available after
        `refresh` seconds have elapsed, the function will wait for `refresh`
        seconds continuously, until `maxtimeout` is reached or the results file
        becomes available.

    maxtimeout : float
        The maximum amount of time in seconds to wait for a result to become
        available after submitting our query request.

    maxtries : int
        The maximum number of tries (across all mirrors tried) to make to either
        submit the request or download the results, before giving up.

    completequerylater : bool
        If set to True, a submitted query that does not return a result before
        `maxtimeout` has passed will be cancelled but its input request
        parameters and the result URL provided by the service will be saved. If
        this function is then called later with these same input request
        parameters, it will check if the query finally finished and a result is
        available. If so, will download the results instead of submitting a new
        query. If it's not done yet, will start waiting for results again. To
        force launch a new query with the same request parameters, set the
        `forcefetch` kwarg to True.

    Returns
    -------

    dict
        This returns a dict of the following form::

            {'params':dict of the input params used for the query,
             'provenance':'cache' or 'new download',
             'result':path to the file on disk with the downloaded data table}


urlparams = {'<STR_LIT>':<NUM_LIT:1> if strformat else <NUM_LIT:0>,<EOL>'<STR_LIT>':page,<EOL>'<STR_LIT>':<NUM_LIT:1>}<EOL>urlqs = urlencode(urlparams)<EOL>dataset_url = '<STR_LIT>' % (lcc_server, dataset_id, urlqs)<EOL>LOGINFO('<STR_LIT>' % (lcc_server,<EOL>dataset_id,<EOL>dataset_url))<EOL>try:<EOL><INDENT>have_apikey, apikey, expires = check_existing_apikey(lcc_server)<EOL>if not have_apikey:<EOL><INDENT>apikey, expires = get_new_apikey(lcc_server)<EOL><DEDENT>if apikey:<EOL><INDENT>headers = {'<STR_LIT>':'<STR_LIT>' % apikey}<EOL><DEDENT>else:<EOL><INDENT>headers = {}<EOL><DEDENT>req = Request(dataset_url, data=None, headers=headers)<EOL>resp = urlopen(req)<EOL>dataset = json.loads(resp.read())<EOL>return dataset<EOL><DEDENT>except Exception as e:<EOL><INDENT>LOGEXCEPTION('<STR_LIT>')<EOL>return None<EOL><DEDENT>

This downloads a JSON form of a dataset from the specified lcc_server.

    If the dataset contains more than 1000 rows, it will be paginated, so you
    must use the `page` kwarg to get the page you want. The dataset JSON will
    contain the keys 'npages', 'currpage', and 'rows_per_page' to help with
    this. The 'rows' key contains the actual data rows as a list of tuples.

    The JSON contains metadata about the query that produced the dataset,
    information about the data table's columns, and links to download the
    dataset's products including the light curve ZIP and the dataset CSV.

    Parameters
    ----------

    lcc_server : str
        This is the base URL of the LCC-Server to talk to.

    dataset_id : str
        This is the unique setid of the dataset you want to get. In the results
        from the `*_search` functions above, this is the value of the
        `infodict['result']['setid']` key in the first item (the infodict) in
        the returned tuple.

    strformat : bool
        This sets if you want the returned data rows to be formatted in their
        string representations already. This can be useful if you're piping the
        returned JSON straight into some sort of UI and you don't want to deal
        with formatting floats, etc. To do this manually when strformat is set
        to False, look at the `coldesc` item in the returned dict, which gives
        the Python and Numpy string format specifiers for each column in the
        data table.

    page : int
        This sets which page of the dataset should be retrieved.

    Returns
    -------

    dict
        This returns the dataset JSON loaded into a dict.


USERHOME = os.path.expanduser('<STR_LIT>')<EOL>APIKEYFILE = os.path.join(USERHOME,<EOL>'<STR_LIT>',<EOL>'<STR_LIT>',<EOL>'<STR_LIT>' % lcc_server.replace(<EOL>'<STR_LIT>',<EOL>'<STR_LIT>'<EOL>).replace(<EOL>'<STR_LIT>',<EOL>'<STR_LIT>'<EOL>))<EOL>respdict = json.loads(apikey_text_json)<EOL>apikey = respdict['<STR_LIT>']<EOL>expires = respdict['<STR_LIT>']<EOL>if not os.path.exists(os.path.dirname(APIKEYFILE)):<EOL><INDENT>os.makedirs(os.path.dirname(APIKEYFILE))<EOL><DEDENT>with open(APIKEYFILE,'<STR_LIT:w>') as outfd:<EOL><INDENT>outfd.write('<STR_LIT>' % (apikey, expires))<EOL><DEDENT>os.chmod(APIKEYFILE, <NUM_LIT>)<EOL>LOGINFO('<STR_LIT>' % (lcc_server,<EOL>expires))<EOL>LOGINFO('<STR_LIT>' % APIKEYFILE)<EOL>return apikey, expires<EOL>

This imports an API key from text and writes it to the cache dir.

    Use this with the JSON text copied from the API key text box on your
    LCC-Server user home page. The API key will thus be tied to the privileges
    of that user account and can then access objects, datasets, and collections
    marked as private for the user only or shared with that user.

    Parameters
    ----------

    lcc_server : str
        The base URL of the LCC-Server to get the API key for.

    apikey_text_json : str
        The JSON string from the API key text box on the user's LCC-Server home
        page at `lcc_server/users/home`.

    Returns
    -------

    (apikey, expiry) : tuple
        This returns a tuple with the API key and its expiry date.


def object_info(lcc_server, objectid, db_collection_id):

urlparams = {<EOL>'<STR_LIT>':objectid,<EOL>'<STR_LIT>':db_collection_id<EOL>}<EOL>urlqs = urlencode(urlparams)<EOL>url = '<STR_LIT>' % (lcc_server, urlqs)<EOL>try:<EOL><INDENT>LOGINFO(<EOL>'<STR_LIT>' % (<EOL>objectid,<EOL>db_collection_id,<EOL>lcc_server<EOL>)<EOL>)<EOL>have_apikey, apikey, expires = check_existing_apikey(lcc_server)<EOL>if not have_apikey:<EOL><INDENT>apikey, expires = get_new_apikey(lcc_server)<EOL><DEDENT>if apikey:<EOL><INDENT>headers = {'<STR_LIT>':'<STR_LIT>' % apikey}<EOL><DEDENT>else:<EOL><INDENT>headers = {}<EOL><DEDENT>req = Request(url, data=None, headers=headers)<EOL>resp = urlopen(req)<EOL>objectinfo = json.loads(resp.read())['<STR_LIT:result>']<EOL>return objectinfo<EOL><DEDENT>except HTTPError as e:<EOL><INDENT>if e.code == <NUM_LIT>:<EOL><INDENT>LOGERROR(<EOL>'<STR_LIT>'<EOL>'<STR_LIT>' % (objectid,<EOL>db_collection_id)<EOL>)<EOL><DEDENT>else:<EOL><INDENT>LOGERROR('<STR_LIT>'<EOL>'<STR_LIT>' %<EOL>(url, e.code, e.reason))<EOL><DEDENT>return None<EOL><DEDENT>

This gets information on a single object from the LCC-Server.

    Returns a dict with all of the available information on an object, including
    finding charts, comments, object type and variability tags, and
    period-search results (if available).

    If you have an LCC-Server API key present in `~/.astrobase/lccs/` that is
    associated with an LCC-Server user account, objects that are visible to this
    user will be returned, even if they are not visible to the public. Use this
    to look up objects that have been marked as 'private' or 'shared'.

    NOTE: you can pass the result dict returned by this function directly into
    the `astrobase.checkplot.checkplot_pickle_to_png` function, e.g.::

        astrobase.checkplot.checkplot_pickle_to_png(result_dict,
                                                    'object-%s-info.png' %
                                                    result_dict['objectid'])

    to generate a quick PNG overview of the object information.

    Parameters
    ----------

    lcc_server : str
        This is the base URL of the LCC-Server to talk to.

    objectid : str
        This is the unique database ID of the object to retrieve info for. This
        is always returned as the `db_oid` column in LCC-Server search results.

    db_collection_id : str
        This is the collection ID which will be searched for the object. This is
        always returned as the `collection` column in LCC-Server search results.

    Returns
    -------

    dict
        A dict containing the object info is returned. Some important items in
        the result dict:

        - `objectinfo`: all object magnitude, color, GAIA cross-match, and
          object type information available for this object

        - `objectcomments`: comments on the object's variability if available

        - `varinfo`: variability comments, variability features, type tags,
          period and epoch information if available

        - `neighbors`: information on the neighboring objects of this object in
          its parent light curve collection

        - `xmatch`: information on any cross-matches to external catalogs
          (e.g. KIC, EPIC, TIC, APOGEE, etc.)

        - `finderchart`: a base-64 encoded PNG image of the object's DSS2 RED
          finder chart. To convert this to an actual PNG, try the function:
          `astrobase.checkplot.pkl_io._b64_to_file`.

        - `magseries`: a base-64 encoded PNG image of the object's light
          curve. To convert this to an actual PNG, try the function:
          `astrobase.checkplot.pkl_io._b64_to_file`.

        - `pfmethods`: a list of period-finding methods applied to the object if
          any. If this list is present, use the keys in it to get to the actual
          period-finding results for each method. These will contain base-64
          encoded PNGs of the periodogram and phased light curves using the best
          three peaks in the periodogram, as well as period and epoch
          information.


USERHOME = os.path.expanduser('<STR_LIT>')<EOL>APIKEYFILE = os.path.join(USERHOME,<EOL>'<STR_LIT>',<EOL>'<STR_LIT>',<EOL>'<STR_LIT>' % lcc_server.replace(<EOL>'<STR_LIT>',<EOL>'<STR_LIT>'<EOL>).replace(<EOL>'<STR_LIT>',<EOL>'<STR_LIT>'<EOL>))<EOL>url = '<STR_LIT>' % lcc_server<EOL>resp = urlopen(url)<EOL>if resp.code == <NUM_LIT:200>:<EOL><INDENT>respdict = json.loads(resp.read())<EOL><DEDENT>else:<EOL><INDENT>LOGERROR('<STR_LIT>' %<EOL>lcc_server)<EOL>LOGERROR('<STR_LIT>' % resp.status_code)<EOL>return None<EOL><DEDENT>apikey = respdict['<STR_LIT:result>']['<STR_LIT>']<EOL>expires = respdict['<STR_LIT:result>']['<STR_LIT>']<EOL>if not os.path.exists(os.path.dirname(APIKEYFILE)):<EOL><INDENT>os.makedirs(os.path.dirname(APIKEYFILE))<EOL><DEDENT>with open(APIKEYFILE,'<STR_LIT:w>') as outfd:<EOL><INDENT>outfd.write('<STR_LIT>' % (apikey, expires))<EOL><DEDENT>os.chmod(APIKEYFILE, <NUM_LIT>)<EOL>LOGINFO('<STR_LIT>' % (lcc_server,<EOL>expires))<EOL>LOGINFO('<STR_LIT>' % APIKEYFILE)<EOL>return apikey, expires<EOL>

This gets a new API key from the specified LCC-Server.

    NOTE: this only gets an anonymous API key. To get an API key tied to a user
    account (and associated privilege level), see the `import_apikey` function
    below.

    Parameters
    ----------

    lcc_server : str
        The base URL of the LCC-Server from where the API key will be fetched.

    Returns
    -------

    (apikey, expiry) : tuple
        This returns a tuple with the API key and its expiry date.


urlparams = {'<STR_LIT>':nrecent}<EOL>urlqs = urlencode(urlparams)<EOL>url = '<STR_LIT>' % (lcc_server, urlqs)<EOL>try:<EOL><INDENT>LOGINFO(<EOL>'<STR_LIT>'<EOL>'<STR_LIT>' % (<EOL>lcc_server,<EOL>)<EOL>)<EOL>have_apikey, apikey, expires = check_existing_apikey(lcc_server)<EOL>if not have_apikey:<EOL><INDENT>apikey, expires = get_new_apikey(lcc_server)<EOL><DEDENT>if apikey:<EOL><INDENT>headers = {'<STR_LIT>':'<STR_LIT>' % apikey}<EOL><DEDENT>else:<EOL><INDENT>headers = {}<EOL><DEDENT>req = Request(url, data=None, headers=headers)<EOL>resp = urlopen(req)<EOL>recent_datasets = json.loads(resp.read())['<STR_LIT:result>']<EOL>return recent_datasets<EOL><DEDENT>except HTTPError as e:<EOL><INDENT>LOGERROR('<STR_LIT>'<EOL>'<STR_LIT>' %<EOL>(url, e.code, e.reason))<EOL>return None<EOL><DEDENT>

This lists recent publicly visible datasets available on the LCC-Server.

    If you have an LCC-Server API key present in `~/.astrobase/lccs/` that is
    associated with an LCC-Server user account, datasets that belong to this
    user will be returned as well, even if they are not visible to the public.

    Parameters
    ----------

    lcc_server : str
        This is the base URL of the LCC-Server to talk to.

    nrecent : int
        This indicates how many recent public datasets you want to list. This is
        always capped at 1000.

    Returns
    -------

    list of dicts
        Returns a list of dicts, with each dict containing info on each dataset.


url = '<STR_LIT>' % lcc_server<EOL>try:<EOL><INDENT>LOGINFO(<EOL>'<STR_LIT>'<EOL>'<STR_LIT>' % (<EOL>lcc_server,<EOL>)<EOL>)<EOL>have_apikey, apikey, expires = check_existing_apikey(lcc_server)<EOL>if not have_apikey:<EOL><INDENT>apikey, expires = get_new_apikey(lcc_server)<EOL><DEDENT>if apikey:<EOL><INDENT>headers = {'<STR_LIT>':'<STR_LIT>' % apikey}<EOL><DEDENT>else:<EOL><INDENT>headers = {}<EOL><DEDENT>req = Request(url, data=None, headers=headers)<EOL>resp = urlopen(req)<EOL>lcc_list = json.loads(resp.read())['<STR_LIT:result>']['<STR_LIT>']<EOL>return lcc_list<EOL><DEDENT>except HTTPError as e:<EOL><INDENT>LOGERROR('<STR_LIT>'<EOL>'<STR_LIT>' %<EOL>(url, e.code, e.reason))<EOL>return None<EOL><DEDENT>

This lists all light curve collections made available on the LCC-Server.

    If you have an LCC-Server API key present in `~/.astrobase/lccs/` that is
    associated with an LCC-Server user account, light curve collections visible
    to this user will be returned as well, even if they are not visible to the
    public.

    Parameters
    ----------

    lcc_server : str
        The base URL of the LCC-Server to talk to.

    Returns
    -------

    dict
        Returns a dict containing lists of info items per collection. This
        includes collection_ids, lists of columns, lists of indexed columns,
        lists of full-text indexed columns, detailed column descriptions, number
        of objects in each collection, collection sky coverage, etc.


<EOL>coords = '<STR_LIT>' % (center_ra, center_decl, radiusarcmin)<EOL>params = {<EOL>'<STR_LIT>':coords<EOL>}<EOL>if collections:<EOL><INDENT>params['<STR_LIT>'] = collections<EOL><DEDENT>if columns:<EOL><INDENT>params['<STR_LIT>'] = columns<EOL><DEDENT>if filters:<EOL><INDENT>params['<STR_LIT>'] = filters<EOL><DEDENT>if sortspec:<EOL><INDENT>params['<STR_LIT>'] = json.dumps([sortspec])<EOL><DEDENT>if samplespec:<EOL><INDENT>params['<STR_LIT>'] = int(samplespec)<EOL><DEDENT>if limitspec:<EOL><INDENT>params['<STR_LIT>'] = int(limitspec)<EOL><DEDENT>params['<STR_LIT>'] = result_visibility<EOL>params['<STR_LIT>'] = email_when_done<EOL>if email_when_done:<EOL><INDENT>download_data = False<EOL><DEDENT>have_apikey, apikey, expires = check_existing_apikey(lcc_server)<EOL>if not have_apikey:<EOL><INDENT>apikey, expires = get_new_apikey(lcc_server)<EOL><DEDENT>api_url = '<STR_LIT>' % lcc_server<EOL>searchresult = submit_post_searchquery(api_url, params, apikey)<EOL>status = searchresult[<NUM_LIT:0>]<EOL>if download_data:<EOL><INDENT>if status == '<STR_LIT>':<EOL><INDENT>LOGINFO('<STR_LIT>')<EOL>csv, lczip, pkl = retrieve_dataset_files(searchresult,<EOL>outdir=outdir,<EOL>apikey=apikey)<EOL>if pkl:<EOL><INDENT>return searchresult[<NUM_LIT:1>], csv, lczip, pkl<EOL><DEDENT>else:<EOL><INDENT>return searchresult[<NUM_LIT:1>], csv, lczip<EOL><DEDENT><DEDENT>elif status == '<STR_LIT>':<EOL><INDENT>LOGINFO('<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>' %<EOL>(maxtimeout/<NUM_LIT>, refresh))<EOL>timewaited = <NUM_LIT:0.0><EOL>while timewaited < maxtimeout:<EOL><INDENT>try:<EOL><INDENT>time.sleep(refresh)<EOL>csv, lczip, pkl = retrieve_dataset_files(searchresult,<EOL>outdir=outdir,<EOL>apikey=apikey)<EOL>if (csv and os.path.exists(csv) and<EOL>lczip and os.path.exists(lczip)):<EOL><INDENT>LOGINFO('<STR_LIT>')<EOL>return searchresult[<NUM_LIT:1>], csv, lczip<EOL><DEDENT>timewaited = timewaited + refresh<EOL><DEDENT>except KeyboardInterrupt:<EOL><INDENT>LOGWARNING('<STR_LIT>')<EOL>return searchresult[<NUM_LIT:1>], None, None<EOL><DEDENT><DEDENT>LOGERROR('<STR_LIT>')<EOL>return searchresult[<NUM_LIT:1>], None, None<EOL><DEDENT>else:<EOL><INDENT>LOGERROR('<STR_LIT>')<EOL>return searchresult[<NUM_LIT:1>], None, None<EOL><DEDENT><DEDENT>else:<EOL><INDENT>return searchresult[<NUM_LIT:1>], None, None<EOL><DEDENT>

This runs a cone-search query.

    Parameters
    ----------

    lcc_server : str
        This is the base URL of the LCC-Server to talk to.  (e.g. for HAT, use:
        https://data.hatsurveys.org)

    center_ra,center_decl : float
        These are the central coordinates of the search to conduct. These can be
        either decimal degrees of type float, or sexagesimal coordinates of type
        str:

        - OK: 290.0, 45.0
        - OK: 15:00:00 +45:00:00
        - OK: 15 00 00.0 -45 00 00.0
        - NOT OK: 290.0 +45:00:00
        - NOT OK: 15:00:00 45.0

    radiusarcmin : float
        This is the search radius to use for the cone-search. This is in
        arcminutes. The maximum radius you can use is 60 arcminutes = 1 degree.

    result_visibility : {'private', 'unlisted', 'public'}
        This sets the visibility of the dataset produced from the search
        result::

               'private' -> the dataset and its products are not visible or
                            accessible by any user other than the one that
                            created the dataset.

               'unlisted' -> the dataset and its products are not visible in the
                             list of public datasets, but can be accessed if the
                             dataset URL is known

               'public' -> the dataset and its products are visible in the list
                           of public datasets and can be accessed by anyone.

    email_when_done : bool
        If True, the LCC-Server will email you when the search is complete. This
        will also set `download_data` to False. Using this requires an
        LCC-Server account and an API key tied to that account.

    collections : list of str or None
        This is a list of LC collections to search in. If this is None, all
        collections will be searched.

    columns : list of str or None
        This is a list of columns to return in the results. Matching objects'
        object IDs, RAs, DECs, and links to light curve files will always be
        returned so there is no need to specify these columns. If None, only
        these columns will be returned: 'objectid', 'ra', 'decl', 'lcfname'

    filters : str or None
        This is an SQL-like string to use to filter on database columns in the
        LCC-Server's collections. To see the columns available for a search,
        visit the Collections tab in the LCC-Server's browser UI. The filter
        operators allowed are::

            lt      -> less than
            gt      -> greater than
            ge      -> greater than or equal to
            le      -> less than or equal to
            eq      -> equal to
            ne      -> not equal to
            ct      -> contains text
            isnull  -> column value is null
            notnull -> column value is not null

        You may use the `and` and `or` operators between filter specifications
        to chain them together logically.

        Example filter strings::

            "(propermotion gt 200.0) and (sdssr lt 11.0)"
            "(dered_jmag_kmag gt 2.0) and (aep_000_stetsonj gt 10.0)"
            "(gaia_status ct 'ok') and (propermotion gt 300.0)"
            "(simbad_best_objtype ct 'RR') and (dered_sdssu_sdssg lt 0.5)"

    sortspec : tuple of two strs or None
        If not None, this should be a tuple of two items::

            ('column to sort by', 'asc|desc')

        This sets the column to sort the results by. For cone_search, the
        default column and sort order are 'dist_arcsec' and 'asc', meaning the
        distance from the search center in ascending order.

    samplespec : int or None
        If this is an int, will indicate how many rows from the initial search
        result will be uniformly random sampled and returned.

    limitspec : int or None
        If this is an int, will indicate how many rows from the initial search
        result to return in total.

        `sortspec`, `samplespec`, and `limitspec` are applied in this order:

            sample -> sort -> limit

    download_data : bool
        This sets if the accompanying data from the search results will be
        downloaded automatically. This includes the data table CSV, the dataset
        pickle file, and a light curve ZIP file. Note that if the search service
        indicates that your query is still in progress, this function will block
        until the light curve ZIP file becomes available. The maximum wait time
        in seconds is set by maxtimeout and the refresh interval is set by
        refresh.

        To avoid the wait block, set download_data to False and the function
        will write a pickle file to `~/.astrobase/lccs/query-[setid].pkl`
        containing all the information necessary to retrieve these data files
        later when the query is done. To do so, call the
        `retrieve_dataset_files` with the path to this pickle file (it will be
        returned).

    outdir : str or None
        If this is provided, sets the output directory of the downloaded dataset
        files. If None, they will be downloaded to the current directory.

    maxtimeout : float
        The maximum time in seconds to wait for the LCC-Server to respond with a
        result before timing out. You can use the `retrieve_dataset_files`
        function to get results later as needed.

    refresh : float
        The time to wait in seconds before pinging the LCC-Server to see if a
        search query has completed and dataset result files can be downloaded.

    Returns
    -------

    tuple
        Returns a tuple with the following elements::

            (search result status dict,
             search result CSV file path,
             search result LC ZIP path)


jdutc = astime.Time(dt, format='<STR_LIT>',scale='<STR_LIT>')<EOL>return jdutc.jd<EOL>

This converts a Python datetime object (naive, time in UT) to JD_UTC.

    Parameters
    ----------

    dt : datetime
        A naive Python `datetime` object (e.g. with no tz attribute) measured at
        UTC.

    Returns
    -------

    jd : float
        The Julian date corresponding to the `datetime` object.


kwargarr = np.array([isinstance(err_t_mid,np.ndarray),<EOL>t0_fixed,<EOL>t0_percentile])<EOL>if not _single_true(kwargarr) and not np.all(~kwargarr.astype(bool)):<EOL><INDENT>raise AssertionError(<EOL>'<STR_LIT>')<EOL><DEDENT>t_mid = t_mid[np.isfinite(t_mid)]<EOL>N_midtimes = len(t_mid)<EOL>if t0_fixed:<EOL><INDENT>t0 = t0_fixed<EOL><DEDENT>elif isinstance(err_t_mid,np.ndarray):<EOL><INDENT>t0_avg = np.average(t_mid, weights=<NUM_LIT:1>/err_t_mid**<NUM_LIT:2>)<EOL>t0_options = np.arange(min(t_mid), max(t_mid)+period, period)<EOL>t0 = t0_options[np.argmin(np.abs(t0_options - t0_avg))]<EOL><DEDENT>else:<EOL><INDENT>if not t0_percentile:<EOL><INDENT>if N_midtimes % <NUM_LIT:2> == <NUM_LIT:1>:<EOL><INDENT>t0 = np.median(t_mid)<EOL><DEDENT>else:<EOL><INDENT>t0 = t_mid[int(N_midtimes/<NUM_LIT:2>)]<EOL><DEDENT><DEDENT>else:<EOL><INDENT>t0 = np.sort(t_mid)[int(N_midtimes*t0_percentile/<NUM_LIT:100>)]<EOL><DEDENT><DEDENT>epoch = (t_mid - t0)/period<EOL>int_epoch = np.round(epoch, <NUM_LIT:0>)<EOL>if verbose:<EOL><INDENT>LOGINFO('<STR_LIT>')<EOL>LOGINFO('<STR_LIT>'.format(repr(epoch)))<EOL>LOGINFO('<STR_LIT>')<EOL>LOGINFO('<STR_LIT>'.format(repr(int_epoch)))<EOL><DEDENT>return int_epoch, t0<EOL>

This calculates the future epochs for a transit, given a period and a
    starting epoch

    The equation used is::

        t_mid = period*epoch + t0

    Default behavior if no kwargs are used is to define `t0` as the median
    finite time of the passed `t_mid` array.

    Only one of `err_t_mid` or `t0_fixed` should be passed.

    Parameters
    ----------

    t_mid : np.array
        A np.array of transit mid-time measurements

    period : float
        The period used to calculate epochs, per the equation above. For typical
        use cases, a period precise to ~1e-5 days is sufficient to get correct
        epochs.

    err_t_mid : None or np.array
        If provided, contains the errors of the transit mid-time
        measurements. The zero-point epoch is then set equal to the average of
        the transit times, weighted as `1/err_t_mid^2` . This minimizes the
        covariance between the transit epoch and the period (e.g., Gibson et
        al. 2013). For standard O-C analysis this is the best method.

    t0_fixed : None or float:
        If provided, use this t0 as the starting epoch. (Overrides all others).

    t0_percentile : None or float
        If provided, use this percentile of `t_mid` to define `t0`.

    Returns
    -------

    tuple
        This is the of the form `(integer_epoch_array, t0)`.
        `integer_epoch_array` is an array of integer epochs (float-type),
        of length equal to the number of *finite* mid-times passed.


return convert_constants(jmag,hmag,kmag,<EOL>RJHK,<EOL>RJH, RJK, RHK,<EOL>RJ, RH, RK)<EOL>

Converts given J, H, Ks mags to an R magnitude value.

    Parameters
    ----------

    jmag,hmag,kmag : float
        2MASS J, H, Ks mags of the object.

    Returns
    -------

    float
        The converted R band magnitude.


return convert_constants(jmag,hmag,kmag,<EOL>VJHK,<EOL>VJH, VJK, VHK,<EOL>VJ, VH, VK)<EOL>

Converts given J, H, Ks mags to a V magnitude value.

    Parameters
    ----------

    jmag,hmag,kmag : float
        2MASS J, H, Ks mags of the object.

    Returns
    -------

    float
        The converted V band magnitude.


return convert_constants(jmag,hmag,kmag,<EOL>SDSSZ_JHK,<EOL>SDSSZ_JH, SDSSZ_JK, SDSSZ_HK,<EOL>SDSSZ_J, SDSSZ_H, SDSSZ_K)<EOL>

Converts given J, H, Ks mags to an SDSS z magnitude value.

    Parameters
    ----------

    jmag,hmag,kmag : float
        2MASS J, H, Ks mags of the object.

    Returns
    -------

    float
        The converted SDSS z band magnitude.


cols = lcdict['<STR_LIT>']<EOL>if filterqualityflags:<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>if not quiet:<EOL><INDENT>LOGINFO('<STR_LIT>'<EOL>'<STR_LIT>'<EOL>% (nbefore, nafter))<EOL><DEDENT><DEDENT>if nanfilter and nanfilter == '<STR_LIT>':<EOL><INDENT>notnanind = (<EOL>np.isfinite(lcdict['<STR_LIT>']['<STR_LIT>']) &<EOL>np.isfinite(lcdict['<STR_LIT>']['<STR_LIT>']) &<EOL>np.isfinite(lcdict['<STR_LIT>']['<STR_LIT>']) &<EOL>np.isfinite(lcdict['<STR_LIT>']['<STR_LIT>']) &<EOL>np.isfinite(lcdict['<STR_LIT:time>'])<EOL>)<EOL><DEDENT>elif nanfilter and nanfilter == '<STR_LIT>':<EOL><INDENT>notnanind = (<EOL>np.isfinite(lcdict['<STR_LIT>']['<STR_LIT>']) &<EOL>np.isfinite(lcdict['<STR_LIT>']['<STR_LIT>']) &<EOL>np.isfinite(lcdict['<STR_LIT:time>'])<EOL>)<EOL><DEDENT>elif nanfilter and nanfilter == '<STR_LIT>':<EOL><INDENT>notnanind = (<EOL>np.isfinite(lcdict['<STR_LIT>']['<STR_LIT>']) &<EOL>np.isfinite(lcdict['<STR_LIT>']['<STR_LIT>']) &<EOL>np.isfinite(lcdict['<STR_LIT:time>'])<EOL>)<EOL><DEDENT>elif nanfilter is None:<EOL><INDENT>pass<EOL><DEDENT>else:<EOL><INDENT>raise NotImplementedError<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>if not quiet:<EOL><INDENT>LOGINFO('<STR_LIT>'<EOL>% (nbefore, nafter))<EOL><DEDENT><DEDENT>if (timestoignore and<EOL>isinstance(timestoignore, list) and<EOL>len(timestoignore) > <NUM_LIT:0>):<EOL><INDENT>exclind = np.full_like(lcdict['<STR_LIT:time>'],True).astype(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>if not quiet:<EOL><INDENT>LOGINFO('<STR_LIT>'<EOL>% (nbefore, nafter))<EOL><DEDENT><DEDENT>return lcdict<EOL>

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

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

    Parameters
    ----------

    lcdict : lcdict
        An `lcdict` produced by `consolidate_tess_fitslc` or
        `read_tess_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!


<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>']['<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(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>(np.abs(hdrinfo['<STR_LIT>']) +<EOL>np.abs(hdrinfo['<STR_LIT>']))*<NUM_LIT>/<NUM_LIT><EOL>)<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>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>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(<EOL>hdrinfo['<STR_LIT>']<EOL>)<EOL>lcdict['<STR_LIT>']['<STR_LIT>'].append(<EOL>hdrinfo['<STR_LIT>']<EOL>)<EOL>for key in datakeys:<EOL><INDENT>if key.lower() in lcdict:<EOL><INDENT>lcdict[key.lower()] = (<EOL>np.concatenate((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>'] = np.concatenate(<EOL>(lcdict['<STR_LIT>'],<EOL>np.full_like(lcdata['<STR_LIT>'],<EOL>hdrinfo['<STR_LIT>'],<EOL>dtype=np.float64))<EOL>)<EOL>lcdict['<STR_LIT>'] = np.concatenate(<EOL>(lcdict['<STR_LIT>'],<EOL>np.full_like(lcdata['<STR_LIT>'],<EOL>hdrinfo['<STR_LIT>'],<EOL>dtype=np.int64))<EOL>)<EOL>lcdict['<STR_LIT>'] = np.concatenate(<EOL>(lcdict['<STR_LIT>'],<EOL>np.full_like(lcdata['<STR_LIT>'],<EOL>hdrinfo['<STR_LIT>'],<EOL>dtype=np.int64))<EOL>)<EOL>lcdict['<STR_LIT>'] = np.concatenate(<EOL>(lcdict['<STR_LIT>'],<EOL>np.full_like(lcdata['<STR_LIT>'],<EOL>hdrinfo['<STR_LIT>'],<EOL>dtype=np.int64))<EOL>)<EOL>lcdict['<STR_LIT>'] = np.concatenate(<EOL>(lcdict['<STR_LIT>'],<EOL>np.full_like(lcdata['<STR_LIT>'],<EOL>hdrinfo['<STR_LIT>'],<EOL>dtype=np.int64))<EOL>)<EOL>lcdict['<STR_LIT>'] = np.concatenate(<EOL>(lcdict['<STR_LIT>'],<EOL>np.full_like(lcdata['<STR_LIT>'],<EOL>hdrinfo['<STR_LIT>'],<EOL>dtype='<STR_LIT>'))<EOL>)<EOL>lcdict['<STR_LIT>'] = np.concatenate(<EOL>(lcdict['<STR_LIT>'],<EOL>np.full_like(lcdata['<STR_LIT>'],<EOL>hdrinfo['<STR_LIT>'],<EOL>dtype='<STR_LIT>'))<EOL>)<EOL>lcdict['<STR_LIT>'] = np.concatenate(<EOL>(lcdict['<STR_LIT>'],<EOL>np.full_like(lcdata['<STR_LIT>'],<EOL>hdrinfo['<STR_LIT>'],<EOL>dtype='<STR_LIT>'))<EOL>)<EOL>lcdict['<STR_LIT>'] = np.concatenate(<EOL>(lcdict['<STR_LIT>'],<EOL>np.full_like(lcdata['<STR_LIT>'],<EOL>hdrinfo['<STR_LIT>'],<EOL>dtype='<STR_LIT>'))<EOL>)<EOL>lcdict['<STR_LIT>'] = np.concatenate(<EOL>(lcdict['<STR_LIT>'],<EOL>np.full_like(lcdata['<STR_LIT>'],<EOL>hdrinfo['<STR_LIT>'],<EOL>dtype=np.int64))<EOL>)<EOL><DEDENT>else:<EOL><INDENT>lcdict = {<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>':[(np.abs(hdrinfo['<STR_LIT>']) +<EOL>np.abs(hdrinfo['<STR_LIT>']))*<NUM_LIT>/<NUM_LIT>],<EOL>'<STR_LIT>':[ndet],<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: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>':'<STR_LIT>',<EOL>'<STR_LIT>':'<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>'] = np.full_like(lcdict['<STR_LIT:time>'],<EOL>lcdict['<STR_LIT>']['<STR_LIT>'][<NUM_LIT:0>],<EOL>dtype=np.float64)<EOL>lcdict['<STR_LIT>'] = np.full_like(lcdict['<STR_LIT:time>'],<EOL>lcdict['<STR_LIT>']['<STR_LIT>'][<NUM_LIT:0>],<EOL>dtype=np.int64)<EOL>lcdict['<STR_LIT>'] = np.full_like(lcdict['<STR_LIT:time>'],<EOL>lcdict['<STR_LIT>']['<STR_LIT>'][<NUM_LIT:0>],<EOL>dtype=np.int64)<EOL>lcdict['<STR_LIT>'] = np.full_like(lcdict['<STR_LIT:time>'],<EOL>lcdict['<STR_LIT>']['<STR_LIT>'][<NUM_LIT:0>],<EOL>dtype=np.int64)<EOL>lcdict['<STR_LIT>'] = np.full_like(<EOL>lcdict['<STR_LIT:time>'],<EOL>lcdict['<STR_LIT>']['<STR_LIT>'][<NUM_LIT:0>],<EOL>dtype=np.int64,<EOL>)<EOL>lcdict['<STR_LIT>'] = np.full_like(<EOL>lcdict['<STR_LIT:time>'],<EOL>lcdict['<STR_LIT>']['<STR_LIT>'][<NUM_LIT:0>],<EOL>dtype='<STR_LIT>',<EOL>)<EOL>lcdict['<STR_LIT>'] = np.full_like(<EOL>lcdict['<STR_LIT:time>'],<EOL>lcdict['<STR_LIT>']['<STR_LIT>'][<NUM_LIT:0>],<EOL>dtype='<STR_LIT>',<EOL>)<EOL>lcdict['<STR_LIT>'] = np.full_like(<EOL>lcdict['<STR_LIT:time>'],<EOL>lcdict['<STR_LIT>']['<STR_LIT>'][<NUM_LIT:0>],<EOL>dtype='<STR_LIT>',<EOL>)<EOL>lcdict['<STR_LIT>'] = np.full_like(<EOL>lcdict['<STR_LIT:time>'],<EOL>lcdict['<STR_LIT>']['<STR_LIT>'][<NUM_LIT:0>],<EOL>dtype='<STR_LIT>',<EOL>)<EOL>lcdict['<STR_LIT>'] = np.full_like(<EOL>lcdict['<STR_LIT:time>'],<EOL>lcdict['<STR_LIT>']['<STR_LIT>'][<NUM_LIT:0>],<EOL>dtype=np.int64,<EOL>)<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>','<STR_LIT>', '<STR_LIT>',<EOL>'<STR_LIT>', '<STR_LIT>', '<STR_LIT>',<EOL>'<STR_LIT>', '<STR_LIT>']<EOL>)<EOL>lcdict['<STR_LIT>']['<STR_LIT>'] = sum(lcdict['<STR_LIT>']['<STR_LIT>'])<EOL>if (filterqualityflags is not False or<EOL>nanfilter is not None or<EOL>timestoignore is not None):<EOL><INDENT>lcdict = filter_tess_lcdict(lcdict,<EOL>filterqualityflags,<EOL>nanfilter=nanfilter,<EOL>timestoignore=timestoignore)<EOL><DEDENT>return lcdict<EOL>

This extracts the light curve from a single TESS .lc.fits file.

    This works on the light curves available at MAST.

    TODO: look at:

    https://archive.stsci.edu/missions/tess/doc/EXP-TESS-ARC-ICD-TM-0014.pdf

    for details on the column descriptions and to fill in any other info we
    need.

    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 TESS pipeline. The default is `LCAPERTUREKEYS` above.

    normalize : bool
        If True, then the 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.

    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 (sectors/cameras/CCDs?). The appending
        does not care about the time order. To consolidate light curves in time
        order, use `consolidate_tess_fitslc` below.

    filterqualityflags : 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'} or None
        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).


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
        `tess_lcdict_to_pkl` above.

    Returns
    -------

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


def aov_theta(times, mags, errs, frequency,<EOL>binsize=<NUM_LIT>, minbin=<NUM_LIT:9>):

period = <NUM_LIT:1.0>/frequency<EOL>fold_time = times[<NUM_LIT:0>]<EOL>phased = phase_magseries(times,<EOL>mags,<EOL>period,<EOL>fold_time,<EOL>wrap=False,<EOL>sort=True)<EOL>phases = phased['<STR_LIT>']<EOL>pmags = phased['<STR_LIT>']<EOL>bins = nparange(<NUM_LIT:0.0>, <NUM_LIT:1.0>, binsize)<EOL>ndets = phases.size<EOL>binnedphaseinds = npdigitize(phases, bins)<EOL>bin_s1_tops = []<EOL>bin_s2_tops = []<EOL>binndets = []<EOL>goodbins = <NUM_LIT:0><EOL>all_xbar = npmedian(pmags)<EOL>for x in npunique(binnedphaseinds):<EOL><INDENT>thisbin_inds = binnedphaseinds == x<EOL>thisbin_mags = pmags[thisbin_inds]<EOL>if thisbin_mags.size > minbin:<EOL><INDENT>thisbin_ndet = thisbin_mags.size<EOL>thisbin_xbar = npmedian(thisbin_mags)<EOL>thisbin_s1_top = (<EOL>thisbin_ndet *<EOL>(thisbin_xbar - all_xbar) *<EOL>(thisbin_xbar - all_xbar)<EOL>)<EOL>thisbin_s2_top = npsum((thisbin_mags - all_xbar) *<EOL>(thisbin_mags - all_xbar))<EOL>bin_s1_tops.append(thisbin_s1_top)<EOL>bin_s2_tops.append(thisbin_s2_top)<EOL>binndets.append(thisbin_ndet)<EOL>goodbins = goodbins + <NUM_LIT:1><EOL><DEDENT><DEDENT>bin_s1_tops = nparray(bin_s1_tops)<EOL>bin_s2_tops = nparray(bin_s2_tops)<EOL>binndets = nparray(binndets)<EOL>s1 = npsum(bin_s1_tops)/(goodbins - <NUM_LIT:1.0>)<EOL>s2 = npsum(bin_s2_tops)/(ndets - goodbins)<EOL>theta_aov = s1/s2<EOL>return theta_aov<EOL>

Calculates the Schwarzenberg-Czerny AoV statistic at a test frequency.

    Parameters
    ----------

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

    frequency : float
        The test frequency to calculate the theta statistic at.

    binsize : float
        The phase bin size to use.

    minbin : int
        The minimum number of items in a phase bin to consider in the
        calculation of the statistic.

    Returns
    -------

    theta_aov : float
        The value of the AoV statistic at the specified `frequency`.


<EOL>stimes, smags, serrs = sigclip_magseries(times,<EOL>mags,<EOL>errs,<EOL>magsarefluxes=magsarefluxes,<EOL>sigclip=sigclip)<EOL>if len(stimes) > <NUM_LIT:9> and len(smags) > <NUM_LIT:9> and len(serrs) > <NUM_LIT:9>:<EOL><INDENT>if startp:<EOL><INDENT>endf = <NUM_LIT:1.0>/startp<EOL><DEDENT>else:<EOL><INDENT>endf = <NUM_LIT:1.0>/<NUM_LIT:0.1><EOL><DEDENT>if endp:<EOL><INDENT>startf = <NUM_LIT:1.0>/endp<EOL><DEDENT>else:<EOL><INDENT>startf = <NUM_LIT:1.0>/(stimes.max() - stimes.min())<EOL><DEDENT>if not autofreq:<EOL><INDENT>frequencies = nparange(startf, endf, stepsize)<EOL>if verbose:<EOL><INDENT>LOGINFO(<EOL>'<STR_LIT>' %<EOL>(frequencies.size, <NUM_LIT:1.0>/endf, <NUM_LIT:1.0>/startf)<EOL>)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>frequencies = get_frequency_grid(stimes,<EOL>minfreq=startf,<EOL>maxfreq=endf)<EOL>if verbose:<EOL><INDENT>LOGINFO(<EOL>'<STR_LIT>'<EOL>'<STR_LIT>' %<EOL>(frequencies.size,<EOL><NUM_LIT:1.0>/frequencies.max(),<EOL><NUM_LIT:1.0>/frequencies.min())<EOL>)<EOL><DEDENT><DEDENT>if (not nworkers) or (nworkers > NCPUS):<EOL><INDENT>nworkers = NCPUS<EOL>if verbose:<EOL><INDENT>LOGINFO('<STR_LIT>' % nworkers)<EOL><DEDENT><DEDENT>pool = Pool(nworkers)<EOL>if normalize:<EOL><INDENT>nmags = (smags - npmedian(smags))/npstd(smags)<EOL><DEDENT>else:<EOL><INDENT>nmags = smags<EOL><DEDENT>tasks = [(stimes, nmags, serrs, x, phasebinsize, mindetperbin)<EOL>for x in frequencies]<EOL>lsp = pool.map(_aov_worker, tasks)<EOL>pool.close()<EOL>pool.join()<EOL>del pool<EOL>lsp = nparray(lsp)<EOL>periods = <NUM_LIT:1.0>/frequencies<EOL>finitepeakind = npisfinite(lsp)<EOL>finlsp = lsp[finitepeakind]<EOL>finperiods = periods[finitepeakind]<EOL>try:<EOL><INDENT>bestperiodind = npargmax(finlsp)<EOL><DEDENT>except ValueError:<EOL><INDENT>LOGERROR('<STR_LIT>'<EOL>'<STR_LIT>')<EOL>return {'<STR_LIT>':npnan,<EOL>'<STR_LIT>':npnan,<EOL>'<STR_LIT>':nbestpeaks,<EOL>'<STR_LIT>':None,<EOL>'<STR_LIT>':None,<EOL>'<STR_LIT>':None,<EOL>'<STR_LIT>':None,<EOL>'<STR_LIT>':'<STR_LIT>',<EOL>'<STR_LIT>':{'<STR_LIT>':startp,<EOL>'<STR_LIT>':endp,<EOL>'<STR_LIT>':stepsize,<EOL>'<STR_LIT>':normalize,<EOL>'<STR_LIT>':phasebinsize,<EOL>'<STR_LIT>':mindetperbin,<EOL>'<STR_LIT>':autofreq,<EOL>'<STR_LIT>':periodepsilon,<EOL>'<STR_LIT>':nbestpeaks,<EOL>'<STR_LIT>':sigclip}}<EOL><DEDENT>sortedlspind = npargsort(finlsp)[::-<NUM_LIT:1>]<EOL>sortedlspperiods = finperiods[sortedlspind]<EOL>sortedlspvals = finlsp[sortedlspind]<EOL>nbestperiods, nbestlspvals, peakcount = (<EOL>[finperiods[bestperiodind]],<EOL>[finlsp[bestperiodind]],<EOL><NUM_LIT:1><EOL>)<EOL>prevperiod = sortedlspperiods[<NUM_LIT:0>]<EOL>for period, lspval in zip(sortedlspperiods, sortedlspvals):<EOL><INDENT>if peakcount == nbestpeaks:<EOL><INDENT>break<EOL><DEDENT>perioddiff = abs(period - prevperiod)<EOL>bestperiodsdiff = [abs(period - x) for x in nbestperiods]<EOL>if (perioddiff > (periodepsilon*prevperiod) and<EOL>all(x > (periodepsilon*period) for x in bestperiodsdiff)):<EOL><INDENT>nbestperiods.append(period)<EOL>nbestlspvals.append(lspval)<EOL>peakcount = peakcount + <NUM_LIT:1><EOL><DEDENT>prevperiod = period<EOL><DEDENT>return {'<STR_LIT>':finperiods[bestperiodind],<EOL>'<STR_LIT>':finlsp[bestperiodind],<EOL>'<STR_LIT>':nbestpeaks,<EOL>'<STR_LIT>':nbestlspvals,<EOL>'<STR_LIT>':nbestperiods,<EOL>'<STR_LIT>':lsp,<EOL>'<STR_LIT>':periods,<EOL>'<STR_LIT>':'<STR_LIT>',<EOL>'<STR_LIT>':{'<STR_LIT>':startp,<EOL>'<STR_LIT>':endp,<EOL>'<STR_LIT>':stepsize,<EOL>'<STR_LIT>':normalize,<EOL>'<STR_LIT>':phasebinsize,<EOL>'<STR_LIT>':mindetperbin,<EOL>'<STR_LIT>':autofreq,<EOL>'<STR_LIT>':periodepsilon,<EOL>'<STR_LIT>':nbestpeaks,<EOL>'<STR_LIT>':sigclip}}<EOL><DEDENT>else:<EOL><INDENT>LOGERROR('<STR_LIT>')<EOL>return {'<STR_LIT>':npnan,<EOL>'<STR_LIT>':npnan,<EOL>'<STR_LIT>':nbestpeaks,<EOL>'<STR_LIT>':None,<EOL>'<STR_LIT>':None,<EOL>'<STR_LIT>':None,<EOL>'<STR_LIT>':None,<EOL>'<STR_LIT>':'<STR_LIT>',<EOL>'<STR_LIT>':{'<STR_LIT>':startp,<EOL>'<STR_LIT>':endp,<EOL>'<STR_LIT>':stepsize,<EOL>'<STR_LIT>':normalize,<EOL>'<STR_LIT>':phasebinsize,<EOL>'<STR_LIT>':mindetperbin,<EOL>'<STR_LIT>':autofreq,<EOL>'<STR_LIT>':periodepsilon,<EOL>'<STR_LIT>':nbestpeaks,<EOL>'<STR_LIT>':sigclip}}<EOL><DEDENT>

This runs a parallelized Analysis-of-Variance (AoV) period search.

    NOTE: `normalize = True` here as recommended by Schwarzenberg-Czerny 1996,
    i.e. mags will be normalized to zero and rescaled so their variance = 1.0.

    Parameters
    ----------

    times,mags,errs : np.array
        The mag/flux time-series with associated measurement errors to run the
        period-finding on.

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

    startp,endp : float or None
        The minimum and maximum periods to consider for the transit search.

    stepsize : float
        The step-size in frequency to use when constructing a frequency grid for
        the period search.

    autofreq : bool
        If this is True, the value of `stepsize` will be ignored and the
        :py:func:`astrobase.periodbase.get_frequency_grid` function will be used
        to generate a frequency grid based on `startp`, and `endp`. If these are
        None as well, `startp` will be set to 0.1 and `endp` will be set to
        `times.max() - times.min()`.

    normalize : bool
        This sets if the input time-series is normalized to 0.0 and rescaled
        such that its variance = 1.0. This is the recommended procedure by
        Schwarzenberg-Czerny 1996.

    phasebinsize : float
        The bin size in phase to use when calculating the AoV theta statistic at
        a test frequency.

    mindetperbin : int
        The minimum number of elements in a phase bin to consider it valid when
        calculating the AoV theta statistic at a test frequency.

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

    periodepsilon : float
        The fractional difference between successive values of 'best' periods
        when sorting by periodogram power to consider them as separate periods
        (as opposed to part of the same periodogram peak). This is used to avoid
        broad peaks in the periodogram and make sure the 'best' periods returned
        are all actually independent.

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

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

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

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

    verbose : bool
        If this is True, will indicate progress and details about the frequency
        grid used for the period search.

    Returns
    -------

    dict
        This function returns a dict, referred to as an `lspinfo` dict in other
        astrobase functions that operate on periodogram results. This is a
        standardized format across all astrobase period-finders, and is of the
        form below::

            {'bestperiod': the best period value in the periodogram,
             'bestlspval': the periodogram peak associated with the best period,
             'nbestpeaks': the input value of nbestpeaks,
             'nbestlspvals': nbestpeaks-size list of best period peak values,
             'nbestperiods': nbestpeaks-size list of best periods,
             'lspvals': the full array of periodogram powers,
             'periods': the full array of periods considered,
             'method':'aov' -> the name of the period-finder method,
             'kwargs':{ dict of all of the input kwargs for record-keeping}}


try:<EOL><INDENT>return generalized_lsp_value_notau(*task)<EOL><DEDENT>except Exception as e:<EOL><INDENT>return npnan<EOL><DEDENT>

This is a worker to wrap the generalized Lomb-Scargle single-freq func.

    This version doesn't use tau.


def specwindow_lsp_value(times, mags, errs, omega):

norm_times = times - times.min()<EOL>tau = (<EOL>(<NUM_LIT:1.0>/(<NUM_LIT>*omega)) *<EOL>nparctan( npsum(npsin(<NUM_LIT>*omega*norm_times)) /<EOL>npsum(npcos(<NUM_LIT>*omega*norm_times)) )<EOL>)<EOL>lspval_top_cos = (npsum(<NUM_LIT:1.0> * npcos(omega*(norm_times-tau))) *<EOL>npsum(<NUM_LIT:1.0> * npcos(omega*(norm_times-tau))))<EOL>lspval_bot_cos = npsum( (npcos(omega*(norm_times-tau))) *<EOL>(npcos(omega*(norm_times-tau))) )<EOL>lspval_top_sin = (npsum(<NUM_LIT:1.0> * npsin(omega*(norm_times-tau))) *<EOL>npsum(<NUM_LIT:1.0> * npsin(omega*(norm_times-tau))))<EOL>lspval_bot_sin = npsum( (npsin(omega*(norm_times-tau))) *<EOL>(npsin(omega*(norm_times-tau))) )<EOL>lspval = <NUM_LIT:0.5> * ( (lspval_top_cos/lspval_bot_cos) +<EOL>(lspval_top_sin/lspval_bot_sin) )<EOL>return lspval<EOL>

This calculates the peak associated with the spectral window function
    for times and at the specified omega.

    NOTE: this is classical Lomb-Scargle, not the Generalized
    Lomb-Scargle. `mags` and `errs` are silently ignored since we're calculating
    the periodogram of the observing window function. These are kept to present
    a consistent external API so the `pgen_lsp` function below can call this
    transparently.

    Parameters
    ----------

    times,mags,errs : np.array
        The time-series to calculate the periodogram value for.

    omega : float
        The frequency to calculate the periodogram value at.

    Returns
    -------

    periodogramvalue : float
        The normalized periodogram at the specified test frequency `omega`.


<EOL>stimes, smags, serrs = sigclip_magseries(times,<EOL>mags,<EOL>errs,<EOL>magsarefluxes=magsarefluxes,<EOL>sigclip=sigclip)<EOL>nzind = npnonzero(serrs)<EOL>stimes, smags, serrs = stimes[nzind], smags[nzind], serrs[nzind]<EOL>if len(stimes) > <NUM_LIT:9> and len(smags) > <NUM_LIT:9> and len(serrs) > <NUM_LIT:9>:<EOL><INDENT>if startp:<EOL><INDENT>endf = <NUM_LIT:1.0>/startp<EOL><DEDENT>else:<EOL><INDENT>endf = <NUM_LIT:1.0>/<NUM_LIT:0.1><EOL><DEDENT>if endp:<EOL><INDENT>startf = <NUM_LIT:1.0>/endp<EOL><DEDENT>else:<EOL><INDENT>startf = <NUM_LIT:1.0>/(stimes.max() - stimes.min())<EOL><DEDENT>if not autofreq:<EOL><INDENT>omegas = <NUM_LIT:2>*pi_value*nparange(startf, endf, stepsize)<EOL>if verbose:<EOL><INDENT>LOGINFO(<EOL>'<STR_LIT>' %<EOL>(omegas.size, <NUM_LIT:1.0>/endf, <NUM_LIT:1.0>/startf)<EOL>)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>freqs = get_frequency_grid(stimes,<EOL>minfreq=startf,<EOL>maxfreq=endf)<EOL>omegas = <NUM_LIT:2>*pi_value*freqs<EOL>if verbose:<EOL><INDENT>LOGINFO(<EOL>'<STR_LIT>'<EOL>'<STR_LIT>' %<EOL>(omegas.size, <NUM_LIT:1.0>/freqs.max(), <NUM_LIT:1.0>/freqs.min())<EOL>)<EOL><DEDENT><DEDENT>if (not nworkers) or (nworkers > NCPUS):<EOL><INDENT>nworkers = NCPUS<EOL>if verbose:<EOL><INDENT>LOGINFO('<STR_LIT>' % nworkers)<EOL><DEDENT><DEDENT>pool = Pool(nworkers)<EOL>tasks = [(stimes, smags, serrs, x) for x in omegas]<EOL>if workchunksize:<EOL><INDENT>lsp = pool.map(glspfunc, tasks, chunksize=workchunksize)<EOL><DEDENT>else:<EOL><INDENT>lsp = pool.map(glspfunc, tasks)<EOL><DEDENT>pool.close()<EOL>pool.join()<EOL>del pool<EOL>lsp = nparray(lsp)<EOL>periods = <NUM_LIT>*pi_value/omegas<EOL>finitepeakind = npisfinite(lsp)<EOL>finlsp = lsp[finitepeakind]<EOL>finperiods = periods[finitepeakind]<EOL>try:<EOL><INDENT>bestperiodind = npargmax(finlsp)<EOL><DEDENT>except ValueError:<EOL><INDENT>LOGERROR('<STR_LIT>'<EOL>'<STR_LIT>')<EOL>return {'<STR_LIT>':npnan,<EOL>'<STR_LIT>':npnan,<EOL>'<STR_LIT>':nbestpeaks,<EOL>'<STR_LIT>':None,<EOL>'<STR_LIT>':None,<EOL>'<STR_LIT>':None,<EOL>'<STR_LIT>':omegas,<EOL>'<STR_LIT>':None,<EOL>'<STR_LIT>':'<STR_LIT>',<EOL>'<STR_LIT>':{'<STR_LIT>':startp,<EOL>'<STR_LIT>':endp,<EOL>'<STR_LIT>':stepsize,<EOL>'<STR_LIT>':autofreq,<EOL>'<STR_LIT>':periodepsilon,<EOL>'<STR_LIT>':nbestpeaks,<EOL>'<STR_LIT>':sigclip}}<EOL><DEDENT>sortedlspind = npargsort(finlsp)[::-<NUM_LIT:1>]<EOL>sortedlspperiods = finperiods[sortedlspind]<EOL>sortedlspvals = finlsp[sortedlspind]<EOL>nbestperiods, nbestlspvals, peakcount = (<EOL>[finperiods[bestperiodind]],<EOL>[finlsp[bestperiodind]],<EOL><NUM_LIT:1><EOL>)<EOL>prevperiod = sortedlspperiods[<NUM_LIT:0>]<EOL>for period, lspval in zip(sortedlspperiods, sortedlspvals):<EOL><INDENT>if peakcount == nbestpeaks:<EOL><INDENT>break<EOL><DEDENT>perioddiff = abs(period - prevperiod)<EOL>bestperiodsdiff = [abs(period - x) for x in nbestperiods]<EOL>if (perioddiff > (periodepsilon*prevperiod) and<EOL>all(x > (periodepsilon*period) for x in bestperiodsdiff)):<EOL><INDENT>nbestperiods.append(period)<EOL>nbestlspvals.append(lspval)<EOL>peakcount = peakcount + <NUM_LIT:1><EOL><DEDENT>prevperiod = period<EOL><DEDENT>return {'<STR_LIT>':finperiods[bestperiodind],<EOL>'<STR_LIT>':finlsp[bestperiodind],<EOL>'<STR_LIT>':nbestpeaks,<EOL>'<STR_LIT>':nbestlspvals,<EOL>'<STR_LIT>':nbestperiods,<EOL>'<STR_LIT>':lsp,<EOL>'<STR_LIT>':omegas,<EOL>'<STR_LIT>':periods,<EOL>'<STR_LIT>':'<STR_LIT>',<EOL>'<STR_LIT>':{'<STR_LIT>':startp,<EOL>'<STR_LIT>':endp,<EOL>'<STR_LIT>':stepsize,<EOL>'<STR_LIT>':autofreq,<EOL>'<STR_LIT>':periodepsilon,<EOL>'<STR_LIT>':nbestpeaks,<EOL>'<STR_LIT>':sigclip}}<EOL><DEDENT>else:<EOL><INDENT>LOGERROR('<STR_LIT>')<EOL>return {'<STR_LIT>':npnan,<EOL>'<STR_LIT>':npnan,<EOL>'<STR_LIT>':nbestpeaks,<EOL>'<STR_LIT>':None,<EOL>'<STR_LIT>':None,<EOL>'<STR_LIT>':None,<EOL>'<STR_LIT>':None,<EOL>'<STR_LIT>':None,<EOL>'<STR_LIT>':'<STR_LIT>',<EOL>'<STR_LIT>':{'<STR_LIT>':startp,<EOL>'<STR_LIT>':endp,<EOL>'<STR_LIT>':stepsize,<EOL>'<STR_LIT>':autofreq,<EOL>'<STR_LIT>':periodepsilon,<EOL>'<STR_LIT>':nbestpeaks,<EOL>'<STR_LIT>':sigclip}}<EOL><DEDENT>

This calculates the generalized Lomb-Scargle periodogram.

    Uses the algorithm from Zechmeister and Kurster (2009).

    Parameters
    ----------

    times,mags,errs : np.array
        The mag/flux time-series with associated measurement errors to run the
        period-finding on.

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

    startp,endp : float or None
        The minimum and maximum periods to consider for the transit search.

    stepsize : float
        The step-size in frequency to use when constructing a frequency grid for
        the period search.

    autofreq : bool
        If this is True, the value of `stepsize` will be ignored and the
        :py:func:`astrobase.periodbase.get_frequency_grid` function will be used
        to generate a frequency grid based on `startp`, and `endp`. If these are
        None as well, `startp` will be set to 0.1 and `endp` will be set to
        `times.max() - times.min()`.

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

    periodepsilon : float
        The fractional difference between successive values of 'best' periods
        when sorting by periodogram power to consider them as separate periods
        (as opposed to part of the same periodogram peak). This is used to avoid
        broad peaks in the periodogram and make sure the 'best' periods returned
        are all actually independent.

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

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

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

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

    workchunksize : None or int
        If this is an int, will use chunks of the given size to break up the
        work for the parallel workers. If None, the chunk size is set to 1.

    glspfunc : Python function
        The worker function to use to calculate the periodogram. This can be
        used to make this function calculate the time-series sampling window
        function instead of the time-series measurements' GLS periodogram by
        passing in `_glsp_worker_specwindow` instead of the default
        `_glsp_worker_withtau` function.

    verbose : bool
        If this is True, will indicate progress and details about the frequency
        grid used for the period search.

    Returns
    -------

    dict
        This function returns a dict, referred to as an `lspinfo` dict in other
        astrobase functions that operate on periodogram results. This is a
        standardized format across all astrobase period-finders, and is of the
        form below::

            {'bestperiod': the best period value in the periodogram,
             'bestlspval': the periodogram peak associated with the best period,
             'nbestpeaks': the input value of nbestpeaks,
             'nbestlspvals': nbestpeaks-size list of best period peak values,
             'nbestperiods': nbestpeaks-size list of best periods,
             'lspvals': the full array of periodogram powers,
             'periods': the full array of periods considered,
             'method':'gls' -> the name of the period-finder method,
             'kwargs':{ dict of all of the input kwargs for record-keeping}}


return (<NUM_LIT:1.0> - peakval)**((times.size - <NUM_LIT>)/<NUM_LIT>)<EOL>

This calculates the probability that periodogram values exceed the given
    peak value.

    This is from page 3 of Zechmeister and Kurster (2009)::

        Prob(p > p_best) = (1 − p_best)**((N−3)/2)

    where::

        p_best is the peak value in consideration
        N is the number of times

    Note that this is for the default normalization of the periodogram,
    e.g. P_normalized = P(omega), such that P represents the sample variance
    (see Table 1).

    Parameters
    ----------

    lspvals : np.array
        The periodogram power value array.

    peakval : float
        A single peak value to calculate the probability for.

    Returns
    -------

    prob: float
        The probability value.


try:<EOL><INDENT>me_epochbin = int((thistransegressbin +<EOL>thistransingressbin)/<NUM_LIT>)<EOL>me_phases = (<EOL>(stimes - stimes.min())/thisbestperiod -<EOL>npfloor((stimes - stimes.min())/thisbestperiod)<EOL>)<EOL>me_phases_sortind = npargsort(me_phases)<EOL>me_sorted_phases = me_phases[me_phases_sortind]<EOL>me_sorted_times = stimes[me_phases_sortind]<EOL>me_bins = nplinspace(<NUM_LIT:0.0>, <NUM_LIT:1.0>, thisnphasebins)<EOL>me_bininds = npdigitize(me_sorted_phases, me_bins)<EOL>me_centertransit_ind = me_bininds == me_epochbin<EOL>me_centertransit_phase = (<EOL>npmedian(me_sorted_phases[me_centertransit_ind])<EOL>)<EOL>me_centertransit_timeloc = npwhere(<EOL>npabs(me_sorted_phases - me_centertransit_phase) ==<EOL>npmin(npabs(me_sorted_phases - me_centertransit_phase))<EOL>)<EOL>me_centertransit_time = me_sorted_times[<EOL>me_centertransit_timeloc<EOL>]<EOL>if me_centertransit_time.size > <NUM_LIT:1>:<EOL><INDENT>LOGWARNING('<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>' %<EOL>(thisbestperiod, repr(me_centertransit_time)))<EOL><DEDENT>thisminepoch = me_centertransit_time[<NUM_LIT:0>]<EOL><DEDENT>except Exception as e:<EOL><INDENT>LOGEXCEPTION(<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>)<EOL>savfit = savgol_fit_magseries(stimes, smags, serrs,<EOL>thisbestperiod,<EOL>magsarefluxes=magsarefluxes,<EOL>verbose=verbose,<EOL>sigclip=None)<EOL>thisminepoch = savfit['<STR_LIT>']['<STR_LIT>']<EOL><DEDENT>if isinstance(thisminepoch, npndarray):<EOL><INDENT>if verbose:<EOL><INDENT>LOGWARNING('<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>% repr(thisminepoch))<EOL><DEDENT>thisminepoch = thisminepoch[<NUM_LIT:0>]<EOL><DEDENT>transitparams = [<EOL>thisbestperiod,<EOL>thisminepoch,<EOL>thistransdepth,<EOL>thistransduration,<EOL>ingressdurationfraction*thistransduration<EOL>]<EOL>modelfit = traptransit_fit_magseries(<EOL>stimes,<EOL>smags,<EOL>serrs,<EOL>transitparams,<EOL>sigclip=None,<EOL>magsarefluxes=magsarefluxes,<EOL>verbose=verbose<EOL>)<EOL>if modelfit and modelfit['<STR_LIT>']['<STR_LIT>'] is not None:<EOL><INDENT>fitparams = modelfit['<STR_LIT>']['<STR_LIT>']<EOL>fiterrs = modelfit['<STR_LIT>']['<STR_LIT>']<EOL>modelmags, actualmags, modelphase = (<EOL>modelfit['<STR_LIT>']['<STR_LIT>'],<EOL>modelfit['<STR_LIT>']['<STR_LIT>'],<EOL>modelfit['<STR_LIT>']['<STR_LIT>']<EOL>)<EOL>subtractedmags = actualmags - modelmags<EOL>subtractedrms = npstd(subtractedmags)<EOL>fit_period, fit_epoch, fit_depth, fit_duration, fit_ingress_dur = (<EOL>fitparams<EOL>)<EOL>npts_in_transit = modelfit['<STR_LIT>']['<STR_LIT>']<EOL>transit_snr = (<EOL>npsqrt(npts_in_transit) * npabs(fit_depth/subtractedrms)<EOL>)<EOL>if verbose:<EOL><INDENT>LOGINFO('<STR_LIT>'<EOL>'<STR_LIT>' %<EOL>(fit_period, fit_epoch))<EOL>LOGINFO('<STR_LIT>' % npts_in_transit)<EOL>LOGINFO('<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>' %<EOL>(fit_depth,<EOL>fit_duration,<EOL>transit_snr))<EOL><DEDENT>return {'<STR_LIT>':fit_period,<EOL>'<STR_LIT>':fit_epoch,<EOL>'<STR_LIT>':transit_snr,<EOL>'<STR_LIT>':fit_depth,<EOL>'<STR_LIT>':fit_duration,<EOL>'<STR_LIT>':nphasebins,<EOL>'<STR_LIT>':thistransingressbin,<EOL>'<STR_LIT>':thistransegressbin,<EOL>'<STR_LIT>':npts_in_transit,<EOL>'<STR_LIT>':modelmags,<EOL>'<STR_LIT>':subtractedmags,<EOL>'<STR_LIT>':actualmags,<EOL>'<STR_LIT>':modelphase,<EOL>'<STR_LIT>':fitparams,<EOL>'<STR_LIT>':fiterrs,<EOL>'<STR_LIT>':modelfit}<EOL><DEDENT>else:<EOL><INDENT>phased_magseries = phase_magseries_with_errs(stimes,<EOL>smags,<EOL>serrs,<EOL>thisbestperiod,<EOL>thisminepoch,<EOL>wrap=False,<EOL>sort=True)<EOL>tphase = phased_magseries['<STR_LIT>']<EOL>tmags = phased_magseries['<STR_LIT>']<EOL>transitphase = thistransduration/<NUM_LIT><EOL>transitindices = ((tphase < transitphase) |<EOL>(tphase > (<NUM_LIT:1.0> - transitphase)))<EOL>blsmodel = npfull_like(tmags, npmedian(tmags))<EOL>if magsarefluxes:<EOL><INDENT>blsmodel[transitindices] = (<EOL>blsmodel[transitindices] - thistransdepth<EOL>)<EOL><DEDENT>else:<EOL><INDENT>blsmodel[transitindices] = (<EOL>blsmodel[transitindices] - thistransdepth<EOL>)<EOL><DEDENT>subtractedmags = tmags - blsmodel<EOL>subtractedrms = npstd(subtractedmags)<EOL>npts_in_transit = len(tmags[transitindices])<EOL>thissnr = (<EOL>npsqrt(npts_in_transit) * npabs(thistransdepth/subtractedrms)<EOL>)<EOL>if verbose:<EOL><INDENT>LOGINFO('<STR_LIT>'<EOL>'<STR_LIT>' %<EOL>(thisbestperiod, thisminepoch))<EOL>LOGINFO('<STR_LIT>' % (<NUM_LIT:1.0> -<EOL>transitphase,<EOL><NUM_LIT:1.0>))<EOL>LOGINFO('<STR_LIT>' % (<NUM_LIT:0.0>,<EOL>transitphase))<EOL>LOGINFO('<STR_LIT>' % tmags[transitindices].size)<EOL>LOGINFO('<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>' %<EOL>(thistransdepth,<EOL>thistransduration,<EOL>thissnr))<EOL><DEDENT>return {'<STR_LIT>':thisbestperiod,<EOL>'<STR_LIT>':thisminepoch,<EOL>'<STR_LIT>':thissnr,<EOL>'<STR_LIT>':thistransdepth,<EOL>'<STR_LIT>':thistransduration,<EOL>'<STR_LIT>':nphasebins,<EOL>'<STR_LIT>':thistransingressbin,<EOL>'<STR_LIT>':thistransegressbin,<EOL>'<STR_LIT>':blsmodel,<EOL>'<STR_LIT>':subtractedmags,<EOL>'<STR_LIT>':tmags,<EOL>'<STR_LIT>':tphase}<EOL><DEDENT>


def bls_serial_pfind(<EOL>times, mags, errs,<EOL>magsarefluxes=False,<EOL>startp=<NUM_LIT:0.1>,  <EOL>endp=<NUM_LIT>,  <EOL>stepsize=<NUM_LIT>,<EOL>mintransitduration=<NUM_LIT>,  <EOL>maxtransitduration=<NUM_LIT>,   <EOL>nphasebins=<NUM_LIT:200>,<EOL>autofreq=True,  <EOL>periodepsilon=<NUM_LIT:0.1>,<EOL>nbestpeaks=<NUM_LIT:5>,<EOL>sigclip=<NUM_LIT>,<EOL>verbose=True,<EOL>get_stats=True,<EOL>):

<EOL>stimes, smags, serrs = sigclip_magseries(times,<EOL>mags,<EOL>errs,<EOL>magsarefluxes=magsarefluxes,<EOL>sigclip=sigclip)<EOL>if len(stimes) > <NUM_LIT:9> and len(smags) > <NUM_LIT:9> and len(serrs) > <NUM_LIT:9>:<EOL><INDENT>if autofreq:<EOL><INDENT>nphasebins = int(npceil(<NUM_LIT>/mintransitduration))<EOL>if nphasebins > <NUM_LIT>:<EOL><INDENT>nphasebins = <NUM_LIT><EOL><DEDENT>stepsize = <NUM_LIT>*mintransitduration/(stimes.max()-stimes.min())<EOL>minfreq = <NUM_LIT:1.0>/endp<EOL>maxfreq = <NUM_LIT:1.0>/startp<EOL>nfreq = int(npceil((maxfreq - minfreq)/stepsize))<EOL>if verbose:<EOL><INDENT>LOGINFO('<STR_LIT>'<EOL>'<STR_LIT>' % (startp, endp, nfreq,<EOL>minfreq, maxfreq))<EOL>LOGINFO('<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>' %<EOL>(stepsize, nphasebins,<EOL>mintransitduration, maxtransitduration))<EOL><DEDENT><DEDENT>else:<EOL><INDENT>minfreq = <NUM_LIT:1.0>/endp<EOL>maxfreq = <NUM_LIT:1.0>/startp<EOL>nfreq = int(npceil((maxfreq - minfreq)/stepsize))<EOL>if verbose:<EOL><INDENT>LOGINFO('<STR_LIT>'<EOL>'<STR_LIT>' % (startp, endp, nfreq,<EOL>minfreq, maxfreq))<EOL>LOGINFO('<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>' %<EOL>(stepsize, nphasebins,<EOL>mintransitduration, maxtransitduration))<EOL><DEDENT><DEDENT>if nfreq > <NUM_LIT>:<EOL><INDENT>if verbose:<EOL><INDENT>LOGWARNING('<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>')<EOL><DEDENT><DEDENT>if minfreq < (<NUM_LIT:1.0>/(stimes.max() - stimes.min())):<EOL><INDENT>if verbose:<EOL><INDENT>LOGWARNING('<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>% (endp, stimes.max() - stimes.min()))<EOL><DEDENT>minfreq = <NUM_LIT>/(stimes.max() - stimes.min())<EOL>if verbose:<EOL><INDENT>LOGINFO('<STR_LIT>' %<EOL>(minfreq, maxfreq))<EOL><DEDENT><DEDENT>try:<EOL><INDENT>blsresult = _bls_runner(stimes,<EOL>smags,<EOL>nfreq,<EOL>minfreq,<EOL>stepsize,<EOL>nphasebins,<EOL>mintransitduration,<EOL>maxtransitduration)<EOL>frequencies = minfreq + nparange(nfreq)*stepsize<EOL>periods = <NUM_LIT:1.0>/frequencies<EOL>lsp = blsresult['<STR_LIT>']<EOL>finitepeakind = npisfinite(lsp)<EOL>finlsp = lsp[finitepeakind]<EOL>finperiods = periods[finitepeakind]<EOL>try:<EOL><INDENT>bestperiodind = npargmax(finlsp)<EOL><DEDENT>except ValueError:<EOL><INDENT>LOGERROR('<STR_LIT>'<EOL>'<STR_LIT>')<EOL>return {'<STR_LIT>':npnan,<EOL>'<STR_LIT>':npnan,<EOL>'<STR_LIT>':nbestpeaks,<EOL>'<STR_LIT>':None,<EOL>'<STR_LIT>':None,<EOL>'<STR_LIT>':None,<EOL>'<STR_LIT>':None,<EOL>'<STR_LIT>':'<STR_LIT>',<EOL>'<STR_LIT>':{'<STR_LIT>':startp,<EOL>'<STR_LIT>':endp,<EOL>'<STR_LIT>':stepsize,<EOL>'<STR_LIT>':mintransitduration,<EOL>'<STR_LIT>':maxtransitduration,<EOL>'<STR_LIT>':nphasebins,<EOL>'<STR_LIT>':autofreq,<EOL>'<STR_LIT>':periodepsilon,<EOL>'<STR_LIT>':nbestpeaks,<EOL>'<STR_LIT>':sigclip,<EOL>'<STR_LIT>':magsarefluxes}}<EOL><DEDENT>sortedlspind = npargsort(finlsp)[::-<NUM_LIT:1>]<EOL>sortedlspperiods = finperiods[sortedlspind]<EOL>sortedlspvals = finlsp[sortedlspind]<EOL>nbestperiods, nbestlspvals, peakcount = (<EOL>[finperiods[bestperiodind]],<EOL>[finlsp[bestperiodind]],<EOL><NUM_LIT:1><EOL>)<EOL>prevperiod = sortedlspperiods[<NUM_LIT:0>]<EOL>for period, lspval in zip(sortedlspperiods, sortedlspvals):<EOL><INDENT>if peakcount == nbestpeaks:<EOL><INDENT>break<EOL><DEDENT>perioddiff = abs(period - prevperiod)<EOL>bestperiodsdiff = [abs(period - x) for x in nbestperiods]<EOL>if (perioddiff > (periodepsilon*prevperiod) and<EOL>all(x > (periodepsilon*period)<EOL>for x in bestperiodsdiff)):<EOL><INDENT>nbestperiods.append(period)<EOL>nbestlspvals.append(lspval)<EOL>peakcount = peakcount + <NUM_LIT:1><EOL><DEDENT>prevperiod = period<EOL><DEDENT>resultdict = {<EOL>'<STR_LIT>':finperiods[bestperiodind],<EOL>'<STR_LIT>':finlsp[bestperiodind],<EOL>'<STR_LIT>':nbestpeaks,<EOL>'<STR_LIT>':nbestlspvals,<EOL>'<STR_LIT>':nbestperiods,<EOL>'<STR_LIT>':lsp,<EOL>'<STR_LIT>':frequencies,<EOL>'<STR_LIT>':periods,<EOL>'<STR_LIT>':blsresult,<EOL>'<STR_LIT>':stepsize,<EOL>'<STR_LIT>':nfreq,<EOL>'<STR_LIT>':nphasebins,<EOL>'<STR_LIT>':mintransitduration,<EOL>'<STR_LIT>':maxtransitduration,<EOL>'<STR_LIT>':'<STR_LIT>',<EOL>'<STR_LIT>':{'<STR_LIT>':startp,<EOL>'<STR_LIT>':endp,<EOL>'<STR_LIT>':stepsize,<EOL>'<STR_LIT>':mintransitduration,<EOL>'<STR_LIT>':maxtransitduration,<EOL>'<STR_LIT>':nphasebins,<EOL>'<STR_LIT>':autofreq,<EOL>'<STR_LIT>':periodepsilon,<EOL>'<STR_LIT>':nbestpeaks,<EOL>'<STR_LIT>':sigclip,<EOL>'<STR_LIT>':magsarefluxes}<EOL>}<EOL>if get_stats:<EOL><INDENT>resultdict['<STR_LIT>'] = []<EOL>for bp in nbestperiods:<EOL><INDENT>if verbose:<EOL><INDENT>LOGINFO("<STR_LIT>" % bp)<EOL><DEDENT>this_pstats = bls_stats_singleperiod(<EOL>times, mags, errs, bp,<EOL>magsarefluxes=resultdict['<STR_LIT>']['<STR_LIT>'],<EOL>sigclip=resultdict['<STR_LIT>']['<STR_LIT>'],<EOL>nphasebins=resultdict['<STR_LIT>'],<EOL>mintransitduration=resultdict['<STR_LIT>'],<EOL>maxtransitduration=resultdict['<STR_LIT>'],<EOL>verbose=verbose,<EOL>)<EOL>resultdict['<STR_LIT>'].append(this_pstats)<EOL><DEDENT><DEDENT>return resultdict<EOL><DEDENT>except Exception as e:<EOL><INDENT>LOGEXCEPTION('<STR_LIT>')<EOL>return {'<STR_LIT>':npnan,<EOL>'<STR_LIT>':npnan,<EOL>'<STR_LIT>':nbestpeaks,<EOL>'<STR_LIT>':None,<EOL>'<STR_LIT>':None,<EOL>'<STR_LIT>':None,<EOL>'<STR_LIT>':None,<EOL>'<STR_LIT>':None,<EOL>'<STR_LIT>':stepsize,<EOL>'<STR_LIT>':nfreq,<EOL>'<STR_LIT>':nphasebins,<EOL>'<STR_LIT>':mintransitduration,<EOL>'<STR_LIT>':maxtransitduration,<EOL>'<STR_LIT>':'<STR_LIT>',<EOL>'<STR_LIT>':{'<STR_LIT>':startp,<EOL>'<STR_LIT>':endp,<EOL>'<STR_LIT>':stepsize,<EOL>'<STR_LIT>':mintransitduration,<EOL>'<STR_LIT>':maxtransitduration,<EOL>'<STR_LIT>':nphasebins,<EOL>'<STR_LIT>':autofreq,<EOL>'<STR_LIT>':periodepsilon,<EOL>'<STR_LIT>':nbestpeaks,<EOL>'<STR_LIT>':sigclip,<EOL>'<STR_LIT>':magsarefluxes}}<EOL><DEDENT><DEDENT>else:<EOL><INDENT>LOGERROR('<STR_LIT>')<EOL>return {'<STR_LIT>':npnan,<EOL>'<STR_LIT>':npnan,<EOL>'<STR_LIT>':nbestpeaks,<EOL>'<STR_LIT>':None,<EOL>'<STR_LIT>':None,<EOL>'<STR_LIT>':None,<EOL>'<STR_LIT>':None,<EOL>'<STR_LIT>':None,<EOL>'<STR_LIT>':stepsize,<EOL>'<STR_LIT>':None,<EOL>'<STR_LIT>':None,<EOL>'<STR_LIT>':mintransitduration,<EOL>'<STR_LIT>':maxtransitduration,<EOL>'<STR_LIT>':'<STR_LIT>',<EOL>'<STR_LIT>':{'<STR_LIT>':startp,<EOL>'<STR_LIT>':endp,<EOL>'<STR_LIT>':stepsize,<EOL>'<STR_LIT>':mintransitduration,<EOL>'<STR_LIT>':maxtransitduration,<EOL>'<STR_LIT>':nphasebins,<EOL>'<STR_LIT>':autofreq,<EOL>'<STR_LIT>':periodepsilon,<EOL>'<STR_LIT>':nbestpeaks,<EOL>'<STR_LIT>':sigclip,<EOL>'<STR_LIT>':magsarefluxes}}<EOL><DEDENT>

Runs the Box Least Squares Fitting Search for transit-shaped signals.

    Based on eebls.f from Kovacs et al. 2002 and python-bls from Foreman-Mackey
    et al. 2015. This is the serial version (which is good enough in most cases
    because BLS in Fortran is fairly fast). If nfreq > 5e5, this will take a
    while.

    Parameters
    ----------

    times,mags,errs : np.array
        The magnitude/flux time-series to search for transits.

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

    startp,endp : float
        The minimum and maximum periods to consider for the transit search.

    stepsize : float
        The step-size in frequency to use when constructing a frequency grid for
        the period search.

    mintransitduration,maxtransitduration : float
        The minimum and maximum transitdurations (in units of phase) to consider
        for the transit search.

    nphasebins : int
        The number of phase bins to use in the period search.

    autofreq : bool
        If this is True, the values of `stepsize` and `nphasebins` will be
        ignored, and these, along with a frequency-grid, will be determined
        based on the following relations::

            nphasebins = int(ceil(2.0/mintransitduration))
            if nphasebins > 3000:
                nphasebins = 3000

            stepsize = 0.25*mintransitduration/(times.max()-times.min())

            minfreq = 1.0/endp
            maxfreq = 1.0/startp
            nfreq = int(ceil((maxfreq - minfreq)/stepsize))

    periodepsilon : float
        The fractional difference between successive values of 'best' periods
        when sorting by periodogram power to consider them as separate periods
        (as opposed to part of the same periodogram peak). This is used to avoid
        broad peaks in the periodogram and make sure the 'best' periods returned
        are all actually independent.

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

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

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

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

    verbose : bool
        If this is True, will indicate progress and details about the frequency
        grid used for the period search.

    get_stats : bool
        If True, runs :py:func:`.bls_stats_singleperiod` for each of the best
        periods in the output and injects the output into the output dict so you
        only have to run this function to get the periods and their stats.

    Returns
    -------

    dict
        This function returns a dict, referred to as an `lspinfo` dict in other
        astrobase functions that operate on periodogram results. This is a
        standardized format across all astrobase period-finders, and is of the
        form below::

            {'bestperiod': the best period value in the periodogram,
             'bestlspval': the periodogram peak associated with the best period,
             'nbestpeaks': the input value of nbestpeaks,
             'nbestlspvals': nbestpeaks-size list of best period peak values,
             'nbestperiods': nbestpeaks-size list of best periods,
             'stats': BLS stats for each best period,
             'lspvals': the full array of periodogram powers,
             'frequencies': the full array of frequencies considered,
             'periods': the full array of periods considered,
             'blsresult': the result dict from the eebls.f wrapper function,
             'stepsize': the actual stepsize used,
             'nfreq': the actual nfreq used,
             'nphasebins': the actual nphasebins used,
             'mintransitduration': the input mintransitduration,
             'maxtransitduration': the input maxtransitdurations,
             'method':'bls' -> the name of the period-finder method,
             'kwargs':{ dict of all of the input kwargs for record-keeping}}