def Func(arg_0,
                           arg_1,
                           arg_2=['gaiamag','sdssg'],
                           arg_3=['kmag','kmag'],
                           arg_4=['gaia_absmag','rpmj']):
    '''This makes color-mag diagrams for all checkplot pickles in the provided
    list.

    Can make an arbitrary number of CMDs given lists of x-axis colors and y-axis
    mags to use.

    Parameters
    ----------

    cplist : list of str
        This is the list of checkplot pickles to process.

    outpkl : str
        The filename of the output pickle that will contain the color-mag
        information for all objects in the checkplots specified in `cplist`.

    color_mag1 : list of str
        This a list of the keys in each checkplot's `objectinfo` dict that will
        be used as color_1 in the equation::

                x-axis color = color_mag1 - color_mag2

    color_mag2 : list of str
        This a list of the keys in each checkplot's `objectinfo` dict that will
        be used as color_2 in the equation::

                x-axis color = color_mag1 - color_mag2

    yaxis_mag : list of str
        This is a list of the keys in each checkplot's `objectinfo` dict that
        will be used as the (absolute) magnitude y-axis of the color-mag
        diagrams.

    Returns
    -------

    str
        The path to the generated CMD pickle file for the collection of objects
        in the input checkplot list.

    Notes
    -----

    This can make many CMDs in one go. For example, the default kwargs for
    `color_mag`, `color_mag2`, and `yaxis_mag` result in two CMDs generated and
    written to the output pickle file:

    - CMD1 -> gaiamag - kmag on the x-axis vs gaia_absmag on the y-axis
    - CMD2 -> sdssg - kmag on the x-axis vs rpmj (J reduced PM) on the y-axis

    '''

    # first, we'll collect all of the info
    arg_5 = []
    arg_6 = []
    arg_7 = []

    for arg_8 in arg_0:

        arg_9 = _read_checkplot_picklefile(arg_8)
        arg_5.append(arg_9['objectid'])

        arg_10 = []
        arg_11 = []

        for arg_12, arg_13, arg_14 in zip(arg_2, arg_3, arg_4):

            if (arg_14 in arg_9['objectinfo'] and
                arg_9['objectinfo'][arg_14] is not None):
                arg_10.append(arg_9['objectinfo'][arg_14])
            else:
                arg_10.append(np.nan)

            if (arg_12 in arg_9['objectinfo'] and
                arg_9['objectinfo'][arg_12] is not None and
                arg_13 in arg_9['objectinfo'] and
                arg_9['objectinfo'][arg_13] is not None):
                arg_11.append(arg_9['objectinfo'][arg_12] -
                                     arg_9['objectinfo'][arg_13])
            else:
                arg_11.append(np.nan)

        arg_6.append(arg_10)
        arg_7.append(arg_11)

    # convert these to arrays
    arg_5 = np.array(arg_5)
    arg_6 = np.array(arg_6)
    arg_7 = np.array(arg_7)

    # prepare the outdict
    arg_15 = {'objectids':arg_5,
               'mags':arg_6,
               'colors':arg_7,
               'color_mag1':arg_2,
               'color_mag2':arg_3,
               'yaxis_mag':arg_4}

    # save the pickled figure and dict for fast retrieval later
    with open(arg_1,'wb') as outfd:
        pickle.dump(arg_15, outfd, pickle.HIGHEST_PROTOCOL)

    plt.close('all')

    return arg_15


def Func(
        arg_0,
        arg_1,
        arg_2='checkplot*.pkl*',
        arg_3=['gaiamag','sdssg'],
        arg_4=['kmag','kmag'],
        arg_5=['gaia_absmag','rpmj']
):
    '''This makes CMDs for all checkplot pickles in the provided directory.

    Can make an arbitrary number of CMDs given lists of x-axis colors and y-axis
    mags to use.

    Parameters
    ----------

    cpdir : list of str
        This is the directory to get the list of input checkplot pickles from.

    outpkl : str
        The filename of the output pickle that will contain the color-mag
        information for all objects in the checkplots specified in `cplist`.

    cpfileglob : str
        The UNIX fileglob to use to search for checkplot pickle files.

    color_mag1 : list of str
        This a list of the keys in each checkplot's `objectinfo` dict that will
        be used as color_1 in the equation::

                x-axis color = color_mag1 - color_mag2

    color_mag2 : list of str
        This a list of the keys in each checkplot's `objectinfo` dict that will
        be used as color_2 in the equation::

                x-axis color = color_mag1 - color_mag2

    yaxis_mag : list of str
        This is a list of the keys in each checkplot's `objectinfo` dict that
        will be used as the (absolute) magnitude y-axis of the color-mag
        diagrams.

    Returns
    -------

    str
        The path to the generated CMD pickle file for the collection of objects
        in the input checkplot directory.

    Notes
    -----

    This can make many CMDs in one go. For example, the default kwargs for
    `color_mag`, `color_mag2`, and `yaxis_mag` result in two CMDs generated and
    written to the output pickle file:

    - CMD1 -> gaiamag - kmag on the x-axis vs gaia_absmag on the y-axis
    - CMD2 -> sdssg - kmag on the x-axis vs rpmj (J reduced PM) on the y-axis

    '''

    arg_6 = glob.glob(os.path.join(arg_0, arg_2))

    return colormagdiagram_cplist(arg_6,
                                  arg_1,
                                  arg_3=arg_3,
                                  arg_4=arg_4,
                                  arg_5=arg_5)


def Func(arg_0, arg_1,
                    arg_2=True,
                    arg_3=False):
    '''This adds CMDs for each object in cplist.

    Parameters
    ----------

    cplist : list of str
        This is the input list of checkplot pickles to add the CMDs to.

    cmdpkl : str
        This is the filename of the CMD pickle created previously.

    require_cmd_magcolor : bool
        If this is True, a CMD plot will not be made if the color and mag keys
        required by the CMD are not present or are nan in each checkplot's
        objectinfo dict.

    save_cmd_pngs : bool
        If this is True, then will save the CMD plots that were generated and
        added back to the checkplotdict as PNGs to the same directory as
        `cpx`.

    Returns
    -------

    Nothing.

    '''

    # load the CMD first to save on IO
    with open(arg_1,'rb') as infd:
        arg_4 = pickle.load(infd)

    for arg_5 in arg_0:

        add_cmd_to_checkplot(arg_5, arg_4,
                             arg_2=arg_2,
                             arg_3=arg_3)


def Func(arg_0,
                   arg_1,
                   arg_2='checkplot*.pkl*',
                   arg_3=True,
                   arg_4=False):
    '''This adds CMDs for each object in cpdir.

    Parameters
    ----------

    cpdir : list of str
        This is the directory to search for checkplot pickles.

    cmdpkl : str
        This is the filename of the CMD pickle created previously.

    cpfileglob : str
        The UNIX fileglob to use when searching for checkplot pickles to operate
        on.

    require_cmd_magcolor : bool
        If this is True, a CMD plot will not be made if the color and mag keys
        required by the CMD are not present or are nan in each checkplot's
        objectinfo dict.

    save_cmd_pngs : bool
        If this is True, then will save the CMD plots that were generated and
        added back to the checkplotdict as PNGs to the same directory as
        `cpx`.

    Returns
    -------

    Nothing.

    '''

    arg_5 = glob.glob(os.path.join(arg_0, arg_2))

    return add_cmds_cplist(arg_5,
                           arg_1,
                           arg_3=arg_3,
                           arg_4=arg_4)


def Func(
        arg_0,
        arg_1=None,
        arg_2=None,
        arg_3=arg_4,
        arg_5=False,
        arg_6='gray_r',
        arg_7=None,
        arg_8=True,
        arg_9=None,
        arg_10=10.0,
        arg_11=3,
        arg_12=180.0,
        arg_13=None,
        arg_14=True,
        arg_15=None,
        arg_16=60.0,
        arg_17=5,
        arg_18=100,
        arg_19='~/.astrobase/stamp-cache',
        arg_20=True
):
    '''
    This updates objectinfo for a list of checkplots.

    Useful in cases where a previous round of GAIA/finderchart/external catalog
    acquisition failed. This will preserve the following keys in the checkplots
    if they exist:

    comments
    varinfo
    objectinfo.objecttags

    Parameters
    ----------

    cplist : list of str
        A list of checkplot pickle file names to update.

    liststartindex : int
        The index of the input list to start working at.

    maxobjects : int
        The maximum number of objects to process in this run. Use this with
        `liststartindex` to effectively distribute working on a large list of
        input checkplot pickles over several sessions or machines.

    nworkers : int
        The number of parallel workers that will work on the checkplot
        update process.

    fast_mode : bool or float
        This runs the external catalog operations in a "fast" mode, with short
        timeouts and not trying to hit external catalogs that take a long time
        to respond. See the docstring for
        `checkplot.pkl_utils._pkl_finder_objectinfo` for details on how this
        works. If this is True, will run in "fast" mode with default timeouts (5
        seconds in most cases). If this is a float, will run in "fast" mode with
        the provided timeout value in seconds.

    findercmap : str or matplotlib.cm.Colormap object

    findercmap : str or matplotlib.cm.ColorMap object
        The Colormap object to use for the finder chart image.

    finderconvolve : astropy.convolution.Kernel object or None
        If not None, the Kernel object to use for convolving the finder image.

    deredden_objects : bool
        If this is True, will use the 2MASS DUST service to get extinction
        coefficients in various bands, and then try to deredden the magnitudes
        and colors of the object already present in the checkplot's objectinfo
        dict.

    custom_bandpasses : dict
        This is a dict used to provide custom bandpass definitions for any
        magnitude measurements in the objectinfo dict that are not automatically
        recognized by the `varclass.starfeatures.color_features` function. See
        its docstring for details on the required format.

    gaia_submit_timeout : float
        Sets the timeout in seconds to use when submitting a request to look up
        the object's information to the GAIA service. Note that if `fast_mode`
        is set, this is ignored.

    gaia_submit_tries : int
        Sets the maximum number of times the GAIA services will be contacted to
        obtain this object's information. If `fast_mode` is set, this is
        ignored, and the services will be contacted only once (meaning that a
        failure to respond will be silently ignored and no GAIA data will be
        added to the checkplot's objectinfo dict).

    gaia_max_timeout : float
        Sets the timeout in seconds to use when waiting for the GAIA service to
        respond to our request for the object's information. Note that if
        `fast_mode` is set, this is ignored.

    gaia_mirror : str
        This sets the GAIA mirror to use. This is a key in the
        `services.gaia.GAIA_URLS` dict which defines the URLs to hit for each
        mirror.

    complete_query_later : bool
        If this is True, saves the state of GAIA queries that are not yet
        complete when `gaia_max_timeout` is reached while waiting for the GAIA
        service to respond to our request. A later call for GAIA info on the
        same object will attempt to pick up the results from the existing query
        if it's completed. If `fast_mode` is True, this is ignored.

    lclistpkl : dict or str
        If this is provided, must be a dict resulting from reading a catalog
        produced by the `lcproc.catalogs.make_lclist` function or a str path
        pointing to the pickle file produced by that function. This catalog is
        used to find neighbors of the current object in the current light curve
        collection. Looking at neighbors of the object within the radius
        specified by `nbrradiusarcsec` is useful for light curves produced by
        instruments that have a large pixel scale, so are susceptible to
        blending of variability and potential confusion of neighbor variability
        with that of the actual object being looked at. If this is None, no
        neighbor lookups will be performed.

    nbrradiusarcsec : float
        The radius in arcseconds to use for a search conducted around the
        coordinates of this object to look for any potential confusion and
        blending of variability amplitude caused by their proximity.

    maxnumneighbors : int
        The maximum number of neighbors that will have their light curves and
        magnitudes noted in this checkplot as potential blends with the target
        object.

    plotdpi : int
        The resolution in DPI of the plots to generate in this function
        (e.g. the finder chart, etc.)

    findercachedir : str
        The path to the astrobase cache directory for finder chart downloads
        from the NASA SkyView service.

    verbose : bool
        If True, will indicate progress and warn about potential problems.

    Returns
    -------

    list of str
        Paths to the updated checkplot pickle file.

    '''

    # work around the Darwin segfault after fork if no network activity in
    # main thread bug: https://bugs.python.org/issue30385#msg293958
    if sys.platform == 'darwin':
        import requests
        requests.get('http://captive.apple.com/hotspot-detect.html')

    # handle the start and end indices
    if (arg_1 is not None) and (arg_2 is None):
        arg_0 = arg_0[arg_1:]

    elif (arg_1 is None) and (arg_2 is not None):
        arg_0 = arg_0[:arg_2]

    elif (arg_1 is not None) and (arg_2 is not None):
        arg_0 = (
            arg_0[arg_1:arg_1+arg_2]
        )

    arg_21 = [(x, {'fast_mode':arg_5,
                  'findercmap':arg_6,
                  'finderconvolve':arg_7,
                  'deredden_object':arg_8,
                  'custom_bandpasses':arg_9,
                  'gaia_submit_timeout':arg_10,
                  'gaia_submit_tries':arg_11,
                  'gaia_max_timeout':arg_12,
                  'gaia_mirror':arg_13,
                  'complete_query_later':arg_14,
                  'lclistpkl':arg_15,
                  'nbrradiusarcsec':arg_16,
                  'maxnumneighbors':arg_17,
                  'plotdpi':arg_18,
                  'findercachedir':arg_19,
                  'verbose':arg_20}) for x in arg_0]

    arg_22 = []
    arg_23 = []

    with ProcessPoolExecutor(max_workers=arg_3) as executor:
        arg_22 = executor.map(cp_objectinfo_worker, arg_21)

    arg_23 = [x for x in arg_22]

    executor.shutdown()
    return arg_23


def Func(arg_0,
                                     arg_1='checkplot-*.pkl*',
                                     arg_2=None,
                                     arg_3=None,
                                     arg_4=arg_5,
                                     arg_6=False,
                                     arg_7='gray_r',
                                     arg_8=None,
                                     arg_9=True,
                                     arg_10=None,
                                     arg_11=10.0,
                                     arg_12=3,
                                     arg_13=180.0,
                                     arg_14=None,
                                     arg_15=True,
                                     arg_16=None,
                                     arg_17=60.0,
                                     arg_18=5,
                                     arg_19=100,
                                     arg_20='~/.astrobase/stamp-cache',
                                     arg_21=True):
    '''This updates the objectinfo for a directory of checkplot pickles.

    Useful in cases where a previous round of GAIA/finderchart/external catalog
    acquisition failed. This will preserve the following keys in the checkplots
    if they exist:

    comments
    varinfo
    objectinfo.objecttags

    Parameters
    ----------

    cpdir : str
        The directory to look for checkplot pickles in.

    cpglob : str
        The UNIX fileglob to use when searching for checkplot pickle files.

    liststartindex : int
        The index of the input list to start working at.

    maxobjects : int
        The maximum number of objects to process in this run. Use this with
        `liststartindex` to effectively distribute working on a large list of
        input checkplot pickles over several sessions or machines.

    nworkers : int
        The number of parallel workers that will work on the checkplot
        update process.

    fast_mode : bool or float
        This runs the external catalog operations in a "fast" mode, with short
        timeouts and not trying to hit external catalogs that take a long time
        to respond. See the docstring for
        `checkplot.pkl_utils._pkl_finder_objectinfo` for details on how this
        works. If this is True, will run in "fast" mode with default timeouts (5
        seconds in most cases). If this is a float, will run in "fast" mode with
        the provided timeout value in seconds.

    findercmap : str or matplotlib.cm.Colormap object

    findercmap : str or matplotlib.cm.ColorMap object
        The Colormap object to use for the finder chart image.

    finderconvolve : astropy.convolution.Kernel object or None
        If not None, the Kernel object to use for convolving the finder image.

    deredden_objects : bool
        If this is True, will use the 2MASS DUST service to get extinction
        coefficients in various bands, and then try to deredden the magnitudes
        and colors of the object already present in the checkplot's objectinfo
        dict.

    custom_bandpasses : dict
        This is a dict used to provide custom bandpass definitions for any
        magnitude measurements in the objectinfo dict that are not automatically
        recognized by the `varclass.starfeatures.color_features` function. See
        its docstring for details on the required format.

    gaia_submit_timeout : float
        Sets the timeout in seconds to use when submitting a request to look up
        the object's information to the GAIA service. Note that if `fast_mode`
        is set, this is ignored.

    gaia_submit_tries : int
        Sets the maximum number of times the GAIA services will be contacted to
        obtain this object's information. If `fast_mode` is set, this is
        ignored, and the services will be contacted only once (meaning that a
        failure to respond will be silently ignored and no GAIA data will be
        added to the checkplot's objectinfo dict).

    gaia_max_timeout : float
        Sets the timeout in seconds to use when waiting for the GAIA service to
        respond to our request for the object's information. Note that if
        `fast_mode` is set, this is ignored.

    gaia_mirror : str
        This sets the GAIA mirror to use. This is a key in the
        `services.gaia.GAIA_URLS` dict which defines the URLs to hit for each
        mirror.

    complete_query_later : bool
        If this is True, saves the state of GAIA queries that are not yet
        complete when `gaia_max_timeout` is reached while waiting for the GAIA
        service to respond to our request. A later call for GAIA info on the
        same object will attempt to pick up the results from the existing query
        if it's completed. If `fast_mode` is True, this is ignored.

    lclistpkl : dict or str
        If this is provided, must be a dict resulting from reading a catalog
        produced by the `lcproc.catalogs.make_lclist` function or a str path
        pointing to the pickle file produced by that function. This catalog is
        used to find neighbors of the current object in the current light curve
        collection. Looking at neighbors of the object within the radius
        specified by `nbrradiusarcsec` is useful for light curves produced by
        instruments that have a large pixel scale, so are susceptible to
        blending of variability and potential confusion of neighbor variability
        with that of the actual object being looked at. If this is None, no
        neighbor lookups will be performed.

    nbrradiusarcsec : float
        The radius in arcseconds to use for a search conducted around the
        coordinates of this object to look for any potential confusion and
        blending of variability amplitude caused by their proximity.

    maxnumneighbors : int
        The maximum number of neighbors that will have their light curves and
        magnitudes noted in this checkplot as potential blends with the target
        object.

    plotdpi : int
        The resolution in DPI of the plots to generate in this function
        (e.g. the finder chart, etc.)

    findercachedir : str
        The path to the astrobase cache directory for finder chart downloads
        from the NASA SkyView service.

    verbose : bool
        If True, will indicate progress and warn about potential problems.

    Returns
    -------

    list of str
        Paths to the updated checkplot pickle file.

    '''

    arg_22 = sorted(glob.glob(os.path.join(arg_0, arg_1)))

    return parallel_update_objectinfo_cplist(
        arg_22,
        arg_2=arg_2,
        arg_3=arg_3,
        arg_4=arg_4,
        arg_6=arg_6,
        arg_7=arg_7,
        arg_8=arg_8,
        arg_9=arg_9,
        arg_10=arg_10,
        arg_11=arg_11,
        arg_12=arg_12,
        arg_13=arg_13,
        arg_14=arg_14,
        arg_15=arg_15,
        arg_16=arg_16,
        arg_17=arg_17,
        arg_18=arg_18,
        arg_19=arg_19,
        arg_20=arg_20,
        arg_21=arg_21
    )


def Func(arg_0):
    '''This gets the required keys from the requested file.

    Parameters
    ----------

    task : tuple
        Task is a two element tuple::

        - task[0] is the dict to work on

        - task[1] is a list of lists of str indicating all the key address to
          extract items from the dict for

    Returns
    -------

    list
        This is a list of all of the items at the requested key addresses.

    '''
    arg_1, arg_2 = arg_0

    arg_3 = _read_checkplot_picklefile(arg_1)

    arg_4 = []

    for arg_5 in arg_2:

        try:
            arg_4.append(_dict_get(arg_3, arg_5))
        except Exception as e:
            arg_4.append(np.nan)

    return arg_4


def Func(arg_0,
                              arg_1, arg_2, arg_3,
                              arg_4, arg_5, arg_6):
    '''This is a double inverted gaussian.

    Parameters
    ----------

    x : np.array
        The items at which the Gaussian is evaluated.

    amp1,amp2 : float
        The amplitude of Gaussian 1 and Gaussian 2.

    loc1,loc2 : float
        The central value of Gaussian 1 and Gaussian 2.

    std1,std2 : float
        The standard deviation of Gaussian 1 and Gaussian 2.

    Returns
    -------

    np.array
        Returns a double inverted Gaussian function evaluated at the items in
        `x`, using the provided parameters of `amp`, `loc`, and `std` for two
        component Gaussians 1 and 2.

    '''

    arg_7 = -_gaussian(arg_0,arg_1,arg_2,arg_3)
    arg_8 = -_gaussian(arg_0,arg_4,arg_5,arg_6)
    return arg_7 + arg_8


def Func(arg_0, arg_1, arg_2, arg_3):
    '''This returns a double eclipse shaped function.

    Suitable for first order modeling of eclipsing binaries.

    Parameters
    ----------

    ebparams : list of float
        This contains the parameters for the eclipsing binary::

            ebparams = [period (time),
                        epoch (time),
                        pdepth: primary eclipse depth (mags),
                        pduration: primary eclipse duration (phase),
                        psdepthratio: primary-secondary eclipse depth ratio,
                        secondaryphase: center phase of the secondary eclipse]

        `period` is the period in days.

        `epoch` is the time of minimum in JD.

        `pdepth` is the depth of the primary eclipse.

        - for magnitudes -> pdepth should be < 0
        - for fluxes     -> pdepth should be > 0

        `pduration` is the length of the primary eclipse in phase.

        `psdepthratio` is the ratio in the eclipse depths:
        `depth_secondary/depth_primary`. This is generally the same as the ratio
        of the `T_effs` of the two stars.

        `secondaryphase` is the phase at which the minimum of the secondary
        eclipse is located. This effectively parameterizes eccentricity.

        All of these will then have fitted values after the fit is done.

    times,mags,errs : np.array
        The input time-series of measurements and associated errors for which
        the eclipse model will be generated. The times will be used to generate
        model mags, and the input `times`, `mags`, and `errs` will be resorted
        by model phase and returned.

    Returns
    -------

    (modelmags, phase, ptimes, pmags, perrs) : tuple
        Returns the model mags and phase values. Also returns the input `times`,
        `mags`, and `errs` sorted by the model's phase.

    '''

    (arg_4, arg_5, arg_6, arg_7, arg_8, arg_9) = arg_0

    # generate the phases
    arg_10 = (arg_1 - arg_5)/arg_4
    arg_10 = arg_10 - np.floor(arg_10)

    arg_11 = np.argsort(arg_10)
    arg_12 = arg_10[arg_11]
    arg_13 = arg_1[arg_11]
    arg_14 = arg_2[arg_11]
    arg_15 = arg_3[arg_11]

    arg_16 = np.median(arg_14)
    arg_17 = np.full_like(arg_12, arg_16)

    arg_18 = -arg_6
    arg_19 = -arg_6 * arg_8

    arg_20 = arg_7/5.0    # we use 5-sigma as full-width -> duration
    arg_21 = arg_7/5.0  # secondary eclipse has the same duration

    arg_22 = arg_7/2.0

    # phase indices
    arg_23 = (
        (arg_12 >= (1.0 - arg_22)) & (arg_12 <= 1.0)
    )
    arg_24 = (
        (arg_12 >= 0.0) & (arg_12 <= arg_22)
    )

    arg_25 = (
        (arg_12 >= (arg_9 - arg_22)) &
        (arg_12 <= (arg_9 + arg_22))
    )

    # put in the eclipses
    arg_17[arg_23] = (
        arg_16 + _gaussian(arg_12[arg_23],
                              arg_18,
                              1.0,
                              arg_20)
    )
    arg_17[arg_24] = (
        arg_16 + _gaussian(arg_12[arg_24],
                              arg_18,
                              0.0,
                              arg_20)
    )
    arg_17[arg_25] = (
        arg_16 + _gaussian(arg_12[arg_25],
                              arg_19,
                              arg_9,
                              arg_21)
    )

    return arg_17, arg_12, arg_13, arg_14, arg_15


def Func(arg_0, arg_1, arg_2):
    '''Converts given J, H, Ks mags to a B magnitude value.

    Parameters
    ----------

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

    Returns
    -------

    float
        The converted B band magnitude.

    '''

    return convert_constants(arg_0,arg_1,arg_2,
                             BJHK,
                             BJH, BJK, BHK,
                             BJ, BH, BK)


def Func(arg_0,arg_1,arg_2):
    '''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(arg_0,arg_1,arg_2,
                             VJHK,
                             VJH, VJK, VHK,
                             VJ, VH, VK)


def Func(arg_0,arg_1,arg_2):
    '''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(arg_0,arg_1,arg_2,
                             RJHK,
                             RJH, RJK, RHK,
                             RJ, RH, RK)


def Func(arg_0,arg_1,arg_2):
    '''Converts given J, H, Ks mags to an I magnitude value.

    Parameters
    ----------

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

    Returns
    -------

    float
        The converted I band magnitude.

    '''

    return convert_constants(arg_0,arg_1,arg_2,
                             IJHK,
                             IJH, IJK, IHK,
                             IJ, IH, IK)


def Func(arg_0,arg_1,arg_2):
    '''Converts given J, H, Ks mags to an SDSS u magnitude value.

    Parameters
    ----------

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

    Returns
    -------

    float
        The converted SDSS u band magnitude.

    '''

    return convert_constants(arg_0,arg_1,arg_2,
                             SDSSU_JHK,
                             SDSSU_JH, SDSSU_JK, SDSSU_HK,
                             SDSSU_J, SDSSU_H, SDSSU_K)


def Func(arg_0,arg_1,arg_2):
    '''Converts given J, H, Ks mags to an SDSS g magnitude value.

    Parameters
    ----------

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

    Returns
    -------

    float
        The converted SDSS g band magnitude.

    '''

    return convert_constants(arg_0,arg_1,arg_2,
                             SDSSG_JHK,
                             SDSSG_JH, SDSSG_JK, SDSSG_HK,
                             SDSSG_J, SDSSG_H, SDSSG_K)


def Func(arg_0,arg_1,arg_2):
    '''Converts given J, H, Ks mags to an SDSS i magnitude value.

    Parameters
    ----------

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

    Returns
    -------

    float
        The converted SDSS i band magnitude.

    '''

    return convert_constants(arg_0,arg_1,arg_2,
                             SDSSI_JHK,
                             SDSSI_JH, SDSSI_JK, SDSSI_HK,
                             SDSSI_J, SDSSI_H, SDSSI_K)


def Func(arg_0,arg_1,arg_2):
    '''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.

    '''

    return convert_constants(arg_0,arg_1,arg_2,
                             SDSSZ_JHK,
                             SDSSZ_JH, SDSSZ_JK, SDSSZ_HK,
                             SDSSZ_J, SDSSZ_H, SDSSZ_K)


def Func(arg_0, arg_1, arg_2, arg_3,
              arg_4=0.05, arg_5=9):
    '''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`.

    '''

    arg_6 = 1.0/arg_3
    arg_7 = arg_0[0]

    arg_8 = phase_magseries(arg_0,
                             arg_1,
                             arg_6,
                             arg_7,
                             wrap=False,
                             sort=True)

    arg_9 = arg_8['phase']
    arg_10 = arg_8['mags']
    arg_11 = nparange(0.0, 1.0, arg_4)
    arg_12 = arg_9.size

    arg_13 = npdigitize(arg_9, arg_11)

    arg_14 = []
    arg_15 = []
    arg_16 = []
    arg_17 = 0

    arg_18 = npmedian(arg_10)

    for arg_19 in npunique(arg_13):

        arg_20 = arg_13 == arg_19
        arg_21 = arg_10[arg_20]

        if arg_21.size > arg_5:

            arg_22 = arg_21.size
            arg_23 = npmedian(arg_21)

            # get s1
            arg_24 = (
                arg_22 *
                (arg_23 - arg_18) *
                (arg_23 - arg_18)
            )

            # get s2
            arg_25 = npsum((arg_21 - arg_18) *
                                   (arg_21 - arg_18))

            arg_14.append(arg_24)
            arg_15.append(arg_25)
            arg_16.append(arg_22)
            arg_17 = arg_17 + 1

    # turn the quantities into arrays
    arg_14 = nparray(arg_14)
    arg_15 = nparray(arg_15)
    arg_16 = nparray(arg_16)

    # calculate s1 first
    arg_26 = npsum(arg_14)/(arg_17 - 1.0)

    # then calculate s2
    arg_27 = npsum(arg_15)/(arg_12 - arg_17)

    arg_28 = arg_26/arg_27

    return arg_28


def Func(arg_0, arg_1, arg_2=False):
    '''This just puts all of the period-finders on a single periodogram.

    This will renormalize all of the periodograms so their values lie between 0
    and 1, with values lying closer to 1 being more significant. Periodograms
    that give the same best periods will have their peaks line up together.

    Parameters
    ----------

    pflist : list of dict
        This is a list of result dicts from any of the period-finders in
        periodbase. To use your own period-finders' results here, make sure the
        result dict is of the form and has at least the keys below::

            {'periods': np.array of all periods searched by the period-finder,
             'lspvals': np.array of periodogram power value for each period,
             'bestperiod': a float value that is the period with the highest
                           peak in the periodogram, i.e. the most-likely actual
                           period,
             'method': a three-letter code naming the period-finder used; must
                       be one of the keys in the
                       `astrobase.periodbase.METHODLABELS` dict,
             'nbestperiods': a list of the periods corresponding to periodogram
                             peaks (`nbestlspvals` below) to annotate on the
                             periodogram plot so they can be called out
                             visually,
             'nbestlspvals': a list of the power values associated with
                             periodogram peaks to annotate on the periodogram
                             plot so they can be called out visually; should be
                             the same length as `nbestperiods` above,
             'kwargs': dict of kwargs passed to your own period-finder function}

    outfile : str
        This is the output file to write the output to. NOTE: EPS/PS won't work
        because we use alpha transparency to better distinguish between the
        various periodograms.

    addmethods : bool
        If this is True, will add all of the normalized periodograms together,
        then renormalize them to between 0 and 1. In this way, if all of the
        period-finders agree on something, it'll stand out easily. FIXME:
        implement this kwarg.

    Returns
    -------

    str
        The name of the generated plot file.

    '''

    import matplotlib.pyplot as plt

    for arg_3 in arg_0:

        if arg_3['method'] == 'pdm':

            plt.plot(arg_3['periods'],
                     np.max(arg_3['lspvals'])/arg_3['lspvals'] - 1.0,
                     label='%s P=%.5f' % (arg_3['method'], arg_3['bestperiod']),
                     alpha=0.5)

        else:

            plt.plot(arg_3['periods'],
                     arg_3['lspvals']/np.max(arg_3['lspvals']),
                     label='%s P=%.5f' % (arg_3['method'], arg_3['bestperiod']),
                     alpha=0.5)

    plt.xlabel('period [days]')
    plt.ylabel('normalized periodogram power')

    plt.xscale('log')
    plt.legend()
    plt.tight_layout()
    plt.savefig(arg_1)
    plt.close('all')

    return arg_1


def Func(arg_0, arg_1, arg_2, arg_3, arg_4, arg_5, arg_6, arg_7, arg_8, arg_9,
                   arg_10=2, arg_11=7):
    '''This returns a BATMAN planetary transit model.

    Parameters
    ----------

    times : np.array
        The times at which the model will be evaluated.

    t0 : float
        The time of periastron for the transit.

    per : float
        The orbital period of the planet.

    rp : float
        The stellar radius of the planet's star (in Rsun).

    a : float
        The semi-major axis of the planet's orbit (in Rsun).

    inc : float
        The orbital inclination (in degrees).

    ecc : float
        The eccentricity of the orbit.

    w : float
        The longitude of periastron (in degrees).

    u : list of floats
        The limb darkening coefficients specific to the limb darkening model
        used.

    limb_dark : {"uniform", "linear", "quadratic", "square-root", "logarithmic", "exponential", "power2", "custom"}
        The type of limb darkening model to use. See the full list here:

        https://www.cfa.harvard.edu/~lkreidberg/batman/tutorial.html#limb-darkening-options

    exp_time_minutes : float
        The amount of time to 'smear' the transit LC points over to simulate a
        long exposure time.

    supersample_factor: int
        The number of supersampled time data points to average the lightcurve
        model over.

    Returns
    -------

    (params, batman_model) : tuple
        The returned tuple contains the params list and the generated
        `batman.TransitModel` object.

    '''
    arg_12 = batman.TransitParams()  # object to store transit parameters
    arg_12.t0 = arg_1                   # time of periastron
    arg_12.per = arg_2                 # orbital period
    arg_12.rp = arg_3                   # planet radius (in stellar radii)
    arg_12.a = arg_4                     # semi-major axis (in stellar radii)
    arg_12.inc = arg_5                 # orbital inclination (in degrees)
    arg_12.ecc = arg_6                 # the eccentricity of the orbit
    arg_12.w = arg_7                     # longitude of periastron (in degrees)
    arg_12.u = arg_8                     # limb darkening coefficient list
    arg_12.limb_dark = arg_9     # limb darkening model to use

    arg_13 = arg_0
    arg_14 = batman.TransitModel(arg_12, arg_13, exp_time=arg_10/60./24.,
                            arg_11=arg_11)

    return arg_12, arg_14


def Func(arg_0, arg_1):
    '''
    Assume priors on all parameters have uniform probability.
    '''
    # priorbounds contains the input priors, and because of how we previously
    # sorted theta, its sorted keys tell us which parts of theta correspond to
    # which physical quantities.

    arg_2 = True
    for arg_3, arg_4 in enumerate(np.sort(list(arg_1.keys()))):
        if arg_1[arg_4][0] < arg_0[arg_3] < arg_1[arg_4][1]:
            arg_2 = True and arg_2
        else:
            arg_2 = False

    if arg_2:
        return 0.

    return -np.inf


def Func(arg_0,
                 arg_1,
                 arg_2='sloan_2mass',
                 arg_3=1.0,
                 arg_4=True,
                 arg_5=0.1,
                 arg_6=26.0,
                 arg_7=4,
                 arg_8=1.6,
                 arg_9=None,
                 arg_10=False,
                 arg_11='~/.astrobase/trilegal-cache',
                 arg_12=True,
                 arg_13=60.0,
                 arg_14=150.0,
                 arg_15=700.0):
    '''This runs the TRILEGAL query for decimal equatorial coordinates.

    Parameters
    ----------

    ra,decl : float
        These are the center equatorial coordinates in decimal 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. This is in the
        Galactic coordinate system.

    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}

    '''

    # convert the ra/decl to gl, gb
    arg_16 = SkyCoord(arg_0=arg_0*u.degree, dec=arg_1*u.degree)

    arg_17 = arg_16.galactic.l.degree
    arg_18 = arg_16.galactic.b.degree

    return query_galcoords(arg_17,
                           arg_18,
                           arg_2=arg_2,
                           arg_3=arg_3,
                           arg_4=arg_4,
                           arg_5=arg_5,
                           arg_6=arg_6,
                           arg_7=arg_7,
                           arg_8=arg_8,
                           arg_9=arg_9,
                           arg_10=arg_10,
                           arg_11=arg_11,
                           arg_12=arg_12,
                           arg_13=arg_13,
                           arg_14=arg_14,
                           arg_15=arg_15)


def Func(arg_0):
    '''
    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.

    '''

    arg_1 = gzip.open(arg_0)
    arg_2 = np.genfromtxt(arg_1,names=True)
    arg_1.close()

    return arg_2


def Func(arg_0, arg_1):
    '''
    This compares two values in constant time.

    Taken from tornado:

    https://github.com/tornadoweb/tornado/blob/
    d4eb8eb4eb5cc9a6677e9116ef84ded8efba8859/tornado/web.py#L3060

    '''
    if len(arg_0) != len(arg_1):
        return False
    arg_2 = 0
    if isinstance(arg_0[0], int):  # python3 byte strings
        for arg_3, arg_4 in zip(arg_0, arg_1):
            arg_2 |= arg_3 ^ arg_4
    else:  # python2
        for arg_3, arg_4 in zip(arg_0, arg_1):
            arg_2 |= ord(arg_3) ^ ord(arg_4)
    return arg_2 == 0


def Func(arg_0, arg_1):
        '''Overrides the Func serializer for `JSONEncoder`.

        This can serialize the following objects in addition to what
        `JSONEncoder` can already do.

        - `np.array`
        - `bytes`
        - `complex`
        - `np.float64` and other `np.dtype` objects

        Parameters
        ----------

        obj : object
            A Python object to serialize to JSON.

        Returns
        -------

        str
            A JSON encoded representation of the input object.

        '''

        if isinstance(arg_1, np.ndarray):
            return arg_1.tolist()
        elif isinstance(arg_1, bytes):
            return arg_1.decode()
        elif isinstance(arg_1, complex):
            return (arg_1.real, arg_1.imag)
        elif (isinstance(arg_1, (float, np.float64, np.float_)) and
              not np.isfinite(arg_1)):
            return None
        elif isinstance(arg_1, (np.int8, np.int16, np.int32, np.int64)):
            return int(arg_1)
        else:
            return json.JSONEncoder.Func(arg_0, arg_1)


def Func(arg_0):
        '''This handles GET requests to the index page.

        TODO: provide the correct baseurl from the checkplotserver options dict,
        so the frontend JS can just read that off immediately.

        '''

        # generate the project's list of checkplots
        arg_1 = arg_0.currentproject['checkplots']
        arg_2 = [os.path.basename(x)
                                      for x in arg_1]
        arg_3 = range(len(arg_1))

        # Func the sortkey and order
        arg_4 = arg_0.currentproject['sortkey']
        if arg_0.currentproject['sortorder'] == 'asc':
            arg_5 = 'ascending'
        elif arg_0.currentproject['sortorder'] == 'desc':
            arg_5 = 'descending'

        # Func the filterkey and condition
        arg_6 = arg_0.currentproject['filterstatements']

        arg_0.render('cpindex.html',
                    arg_1=arg_1,
                    arg_5=arg_5,
                    arg_4=arg_4,
                    arg_6=arg_6,
                    arg_2=arg_2,
                    arg_3=arg_3,
                    project_checkplotfile=arg_0.cplistfile,
                    readonly=arg_0.readonly,
                    baseurl=arg_0.baseurl)


def Func(arg_0):
        '''
        This handles GET requests for the current checkplot-list.json file.

        Used with AJAX from frontend.

        '''

        # add the reviewed key to the current dict if it doesn't exist
        # this will hold all the reviewed objects for the frontend
        if 'reviewed' not in arg_0.currentproject:
            arg_0.currentproject['reviewed'] = {}

        # just returns the current project as JSON
        arg_0.write(arg_0.currentproject)


def Func(arg_0, arg_1, arg_2=2):
    '''This smooths the magseries with a Savitsky-Golay filter.

    Parameters
    ----------

    mags : np.array
        The input mags/flux time-series to smooth.

    windowsize : int
        This is a odd integer containing the smoothing window size.

    polyorder : int
        This is an integer containing the polynomial degree order to use when
        generating the Savitsky-Golay filter.

    Returns
    -------

    np.array
        The smoothed mag/flux time-series array.

    '''

    arg_3 = savgol_filter(arg_0, arg_1, arg_2)
    return arg_3


def Func(arg_0, arg_1, arg_2,
                       arg_3, arg_4, arg_5, arg_6, arg_7, arg_8, arg_9,
                       arg_10=21,
                       arg_11=3.0,
                       arg_12=arg_13,
                       arg_14=None):
    '''
    Detrends a magnitude series given in mag using accompanying values of S in
    fsv, D in fdv, K in fkv, x coords in xcc, y coords in ycc, background in
    bgv, and background error in bge. smooth is used to set a smoothing
    parameter for the fit function. Does EPD voodoo.

    '''

    # find all the finite values of the magsnitude
    arg_15 = np.isfinite(arg_1)

    # calculate median and stdev
    arg_16 = np.median(arg_1[arg_15])
    arg_17 = np.nanstd(arg_1)

    # if we're supposed to sigma clip, do so
    if arg_11:
        arg_18 = abs(arg_1 - arg_16) < arg_11*arg_17
        arg_19 = arg_15 & arg_18
    else:
        arg_19 = arg_15

    arg_20 = arg_1[arg_19]
    arg_21 = len(arg_20)

    # smooth the signal
    if isinstance(arg_14, dict):
        arg_22 = arg_12(arg_20,
                                      arg_10,
                                      **arg_14)
    else:
        arg_22 = arg_12(arg_20, arg_10)

    # make the linear equation matrix
    arg_23 = np.c_[arg_3[arg_19]**2.0,
                      arg_3[arg_19],
                      arg_4[arg_19]**2.0,
                      arg_4[arg_19],
                      arg_5[arg_19]**2.0,
                      arg_5[arg_19],
                      np.ones(arg_21),
                      arg_3[arg_19]*arg_4[arg_19],
                      arg_3[arg_19]*arg_5[arg_19],
                      arg_4[arg_19]*arg_5[arg_19],
                      np.sin(2*np.pi*arg_6[arg_19]),
                      np.cos(2*np.pi*arg_6[arg_19]),
                      np.sin(2*np.pi*arg_7[arg_19]),
                      np.cos(2*np.pi*arg_7[arg_19]),
                      np.sin(4*np.pi*arg_6[arg_19]),
                      np.cos(4*np.pi*arg_6[arg_19]),
                      np.sin(4*np.pi*arg_7[arg_19]),
                      np.cos(4*np.pi*arg_7[arg_19]),
                      arg_8[arg_19],
                      arg_9[arg_19]]

    # solve the matrix equation [epdmatrix] . [x] = [smoothedmags]
    # return the EPD differential magss if the solution succeeds
    try:

        arg_24, arg_25, arg_26, arg_27 = lstsq(arg_23, arg_22,
                                                   rcond=None)

        if DEBUG:
            print('coeffs = %s, residuals = %s' % (arg_24, arg_25))

        arg_28 = {'times':arg_0,
                   'mags':(arg_16 +
                           _old_epd_diffmags(arg_24, arg_3, arg_4,
                                             arg_5, arg_6, arg_7, arg_8, arg_9, arg_1)),
                   'errs':arg_2,
                   'fitcoeffs':arg_24,
                   'residuals':arg_25}

        return arg_28

    # if the solution fails, return nothing
    except Exception as e:

        LOGEXCEPTION('EPD solution did not converge')

        arg_28 = {'times':arg_0,
                   'mags':np.full_like(arg_1, np.nan),
                   'errs':arg_2,
                   'fitcoeffs':arg_24,
                   'residuals':arg_25}

        return arg_28


def Func(arg_0, arg_1, arg_2, arg_3, arg_4, arg_5, arg_6, arg_7, arg_8, arg_9):
    '''
    This is the EPD function to fit using a smoothed mag-series.

    '''

    return (arg_0[0]*arg_1*arg_1 +
            arg_0[1]*arg_1 +
            arg_0[2]*arg_2*arg_2 +
            arg_0[3]*arg_2 +
            arg_0[4]*arg_3*arg_3 +
            arg_0[5]*arg_3 +
            arg_0[6] +
            arg_0[7]*arg_1*arg_2 +
            arg_0[8]*arg_1*arg_3 +
            arg_0[9]*arg_2*arg_3 +
            arg_0[10]*np.sin(2*pi_value*arg_4) +
            arg_0[11]*np.cos(2*pi_value*arg_4) +
            arg_0[12]*np.sin(2*pi_value*arg_5) +
            arg_0[13]*np.cos(2*pi_value*arg_5) +
            arg_0[14]*np.sin(4*pi_value*arg_4) +
            arg_0[15]*np.cos(4*pi_value*arg_4) +
            arg_0[16]*np.sin(4*pi_value*arg_5) +
            arg_0[17]*np.cos(4*pi_value*arg_5) +
            arg_0[18]*arg_6 +
            arg_0[19]*arg_7 +
            arg_0[20]*arg_8 +
            arg_0[21]*arg_9)


def Func(arg_0, arg_1, arg_2,
                  arg_3, arg_4, arg_5, arg_6, arg_7, arg_8, arg_9, arg_10, arg_11,
                  arg_12=False,
                  arg_13=3.0,
                  arg_14=21,
                  arg_15=arg_16,
                  arg_17=None):
    '''Detrends a magnitude series using External Parameter Decorrelation.

    Requires a set of external parameters similar to those present in HAT light
    curves. At the moment, the HAT light-curve-specific external parameters are:

    - S: the 'fsv' column in light curves,
    - D: the 'fdv' column in light curves,
    - K: the 'fkv' column in light curves,
    - x coords: the 'xcc' column in light curves,
    - y coords: the 'ycc' column in light curves,
    - background value: the 'bgv' column in light curves,
    - background error: the 'bge' column in light curves,
    - hour angle: the 'iha' column in light curves,
    - zenith distance: the 'izd' column in light curves

    S, D, and K are defined as follows:

    - S -> measure of PSF sharpness (~1/sigma^2 sosmaller S = wider PSF)
    - D -> measure of PSF ellipticity in xy direction
    - K -> measure of PSF ellipticity in cross direction

    S, D, K are related to the PSF's variance and covariance, see eqn 30-33 in
    A. Pal's thesis: https://arxiv.org/abs/0906.3486

    NOTE: The errs are completely ignored and returned unchanged (except for
    sigclip and finite filtering).

    Parameters
    ----------

    times,mags,errs : np.array
        The input mag/flux time-series to detrend.

    fsv : np.array
        Array containing the external parameter `S` of the same length as times.

    fdv : np.array
        Array containing the external parameter `D` of the same length as times.

    fkv : np.array
        Array containing the external parameter `K` of the same length as times.

    xcc : np.array
        Array containing the external parameter `x-coords` of the same length as
        times.

    ycc : np.array
        Array containing the external parameter `y-coords` of the same length as
        times.

    bgv : np.array
        Array containing the external parameter `background value` of the same
        length as times.

    bge : np.array
        Array containing the external parameter `background error` of the same
        length as times.

    iha : np.array
        Array containing the external parameter `hour angle` of the same length
        as times.

    izd : np.array
        Array containing the external parameter `zenith distance` of the same
        length as times.

    magsarefluxes : bool
        Set this to True if `mags` actually contains fluxes.

    epdsmooth_sigclip : float or int or sequence of two floats/ints or None
        This specifies how to sigma-clip the input LC before fitting the EPD
        function to it.

        If a single float or int, a symmetric sigma-clip will be performed using
        the number provided as the sigma-multiplier to cut out from the input
        time-series.

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

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

    epdsmooth_windowsize : int
        This is the number of LC points to smooth over to generate a smoothed
        light curve that will be used to fit the EPD function.

    epdsmooth_func : Python function
        This sets the smoothing filter function to use. A Savitsky-Golay filter
        is used to smooth the light curve by default. The functions that can be
        used with this kwarg are listed in `varbase.trends`. If you want to use
        your own function, it MUST have the following signature::

                def smoothfunc(mags_array, window_size, **extraparams)

        and return a numpy array of the same size as `mags_array` with the
        smoothed time-series. Any extra params can be provided using the
        `extraparams` dict.

    epdsmooth_extraparams : dict
        This is a dict of any extra filter params to supply to the smoothing
        function.

    Returns
    -------

    dict
        Returns a dict of the following form::

            {'times':the input times after non-finite elems removed,
             'mags':the EPD detrended mag values (the EPD mags),
             'errs':the errs after non-finite elems removed,
             'fitcoeffs':EPD fit coefficient values,
             'fitinfo':the full tuple returned by scipy.leastsq,
             'fitmags':the EPD fit function evaluated at times,
             'mags_median': this is median of the EPD mags,
             'mags_mad': this is the MAD of EPD mags}

    '''

    arg_18 = np.isfinite(arg_0) & np.isfinite(arg_1) & np.isfinite(arg_2)
    arg_19, arg_20, arg_21 = arg_0[::][arg_18], arg_1[::][arg_18], arg_2[::][arg_18]
    arg_22, arg_23, arg_24, arg_25, arg_26, arg_27, arg_28, arg_29, arg_30 = (
        arg_3[::][arg_18],
        arg_4[::][arg_18],
        arg_5[::][arg_18],
        arg_6[::][arg_18],
        arg_7[::][arg_18],
        arg_8[::][arg_18],
        arg_9[::][arg_18],
        arg_10[::][arg_18],
        arg_11[::][arg_18],
    )

    arg_31, arg_32, arg_33, arg_34 = sigclip_magseries_with_extparams(
        arg_0, arg_1, arg_2,
        [arg_3, arg_4, arg_5, arg_6, arg_7, arg_8, arg_9, arg_10, arg_11],
        sigclip=arg_13,
        arg_12=arg_12
    )
    arg_35, arg_36, arg_37, arg_38, arg_39, arg_40, arg_41, arg_42, arg_43 = arg_34

    # smooth the signal
    if isinstance(arg_17, dict):
        arg_44 = arg_15(arg_32,
                                      arg_14,
                                      **arg_17)
    else:
        arg_44 = arg_15(arg_32, arg_14)

    # initial fit coeffs
    arg_45 = np.zeros(22)

    # fit the smoothed mags and find the EPD function coefficients
    arg_46 = leastsq(_epd_residual,
                         arg_45,
                         args=(arg_44,
                               arg_35, arg_36, arg_37, arg_38,
                               arg_39, arg_40, arg_41, arg_42, arg_43),
                         full_output=True)

    # if the fit succeeds, then get the EPD mags
    if arg_46[-1] in (1,2,3,4):

        arg_47 = arg_46[0]
        arg_48 = _epd_function(arg_47,
                               arg_22, arg_23, arg_24, arg_25, arg_26,
                               arg_27, arg_28, arg_29, arg_30)

        arg_49 = npmedian(arg_20) + arg_20 - arg_48

        arg_50 = {'times':arg_19,
                   'mags':arg_49,
                   'errs':arg_21,
                   'fitcoeffs':arg_47,
                   'fitinfo':arg_46,
                   'fitmags':arg_48,
                   'mags_median':npmedian(arg_49),
                   'mags_mad':npmedian(npabs(arg_49 - npmedian(arg_49)))}

        return arg_50

    # if the solution fails, return nothing
    else:

        LOGERROR('EPD fit did not converge')
        return None


def Func(arg_0, arg_1, arg_2,
                    arg_3,
                    arg_4=False,
                    arg_5=True,
                    arg_6=3.0,
                    arg_7=21,
                    arg_8=arg_9,
                    arg_10=None,
                    arg_11=1.0,
                    arg_12=300,
                    arg_13={'criterion':'mse',
                                    'oob_score':False,
                                    'n_jobs':-1}):
    '''This uses a `RandomForestRegressor` to de-correlate the given magseries.

    Parameters
    ----------

    times,mags,errs : np.array
        The input mag/flux time-series to run EPD on.

    externalparam_arrs : list of np.arrays
        This is a list of ndarrays of external parameters to decorrelate
        against. These should all be the same size as `times`, `mags`, `errs`.

    epdsmooth : bool
        If True, sets the training LC for the RandomForestRegress to be a
        smoothed version of the sigma-clipped light curve provided in `times`,
        `mags`, `errs`.

    epdsmooth_sigclip : float or int or sequence of two floats/ints or None
        This specifies how to sigma-clip the input LC before smoothing it and
        fitting the EPD function to it. The actual LC will not be sigma-clipped.

        If a single float or int, a symmetric sigma-clip will be performed using
        the number provided as the sigma-multiplier to cut out from the input
        time-series.

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

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

    epdsmooth_windowsize : int
        This is the number of LC points to smooth over to generate a smoothed
        light curve that will be used to fit the EPD function.

    epdsmooth_func : Python function
        This sets the smoothing filter function to use. A Savitsky-Golay filter
        is used to smooth the light curve by default. The functions that can be
        used with this kwarg are listed in `varbase.trends`. If you want to use
        your own function, it MUST have the following signature::

                def smoothfunc(mags_array, window_size, **extraparams)

        and return a numpy array of the same size as `mags_array` with the
        smoothed time-series. Any extra params can be provided using the
        `extraparams` dict.

    epdsmooth_extraparams : dict
        This is a dict of any extra filter params to supply to the smoothing
        function.

    rf_subsample : float
        Defines the fraction of the size of the `mags` array to use for
        training the random forest regressor.

    rf_ntrees : int
        This is the number of trees to use for the `RandomForestRegressor`.

    rf_extraprams : dict
        This is a dict of any extra kwargs to provide to the
        `RandomForestRegressor` instance used.

    Returns
    -------

    dict
        Returns a dict with decorrelated mags and the usual info from the
        `RandomForestRegressor`: variable importances, etc.

    '''

    # get finite times, mags, errs
    arg_14 = np.isfinite(arg_0) & np.isfinite(arg_1) & np.isfinite(arg_2)
    arg_15, arg_16, arg_17 = arg_0[::][arg_14], arg_1[::][arg_14], arg_2[::][arg_14]
    arg_18 = []
    for arg_19 in arg_3:
        arg_18.append(arg_19[::][arg_14])

    arg_20, arg_21, arg_22, arg_23 = sigclip_magseries_with_extparams(
        arg_0, arg_1, arg_2,
        arg_3,
        sigclip=arg_6,
        arg_4=arg_4
    )

    # smoothing is optional for RFR because we train on a fraction of the mag
    # series and so should not require a smoothed input to fit a function to
    if arg_5:

        # smooth the signal
        if isinstance(arg_10, dict):
            arg_24 = arg_8(arg_21,
                                          arg_7,
                                          **arg_10)
        else:
            arg_24 = arg_8(arg_21,
                                          arg_7)

    else:

        arg_24 = arg_21

    # set up the regressor
    if isinstance(arg_13, dict):
        arg_25 = RandomForestRegressor(n_estimators=arg_12,
                                    **arg_13)
    else:
        arg_25 = RandomForestRegressor(n_estimators=arg_12)

    # collect the features
    arg_26 = np.column_stack(arg_23)

    # fit, then generate the predicted values, then get corrected values

    # we fit on a randomly selected subsample of all the mags
    if arg_11 < 1.0:
        arg_27 = np.arange(arg_24.size)

        # these are sorted because time-order should be important
        arg_28 = np.sort(
            npr.choice(arg_27,
                       size=int(arg_11*arg_24.size),
                       replace=False)
        )
    else:
        arg_28 = np.arange(arg_24.size)

    arg_25.fit(arg_26[arg_28,:], arg_24[arg_28])

    # predict on the full feature set
    arg_29 = arg_25.predict(np.column_stack(arg_18))
    arg_30 = npmedian(arg_16) + arg_16 - arg_29

    arg_31 = {'times':arg_15,
               'mags':arg_30,
               'errs':arg_17,
               'feature_importances':arg_25.feature_importances_,
               'regressor':arg_25,
               'mags_median':npmedian(arg_30),
               'mags_mad':npmedian(npabs(arg_30 -
                                         npmedian(arg_30)))}

    return arg_31


def Func(arg_0, arg_1, arg_2, arg_3,
                           arg_4=0.05, arg_5=9):
    '''
    This calculates the Stellingwerf PDM theta value at a test frequency.

    Parameters
    ----------

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

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

    binsize : float
        The phase bin size to use.

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

    Returns
    -------

    theta_pdm : float
        The value of the theta statistic at the specified `frequency`.

    '''

    arg_6 = 1.0/arg_3
    arg_7 = arg_0[0]

    arg_8 = phase_magseries(arg_0,
                             arg_1,
                             arg_6,
                             arg_7,
                             wrap=False,
                             sort=True)

    arg_9 = arg_8['phase']
    arg_10 = arg_8['mags']
    arg_11 = nparange(0.0, 1.0, arg_4)

    arg_12 = npdigitize(arg_9, arg_11)

    arg_13 = []
    arg_14 = []
    arg_15 = 0

    for arg_16 in npunique(arg_12):

        arg_17 = arg_12 == arg_16
        arg_18 = arg_10[arg_17]

        if arg_18.size > arg_5:
            arg_19 = npvar(arg_18,ddof=1)
            arg_13.append(arg_19)
            arg_14.append(arg_18.size)
            arg_15 = arg_15 + 1

    # now calculate theta
    arg_13 = nparray(arg_13)
    arg_14 = nparray(arg_14)

    arg_20 = npsum(arg_13*(arg_14 - 1)) / (npsum(arg_14) -
                                                      arg_15)
    arg_21 = npvar(arg_10,ddof=1)
    arg_22 = arg_20/arg_21

    return arg_22


def Func(arg_0, arg_1, arg_2):
    '''Converts magnitude measurements in Kepler band to SDSS r band.

    Parameters
    ----------

    keplermag : float or array-like
        The Kepler magnitude value(s) to convert to fluxes.

    kic_sdssg,kic_sdssr : float or array-like
        The SDSS g and r magnitudes of the object(s) from the Kepler Input
        Catalog. The .llc.fits MAST light curve file for a Kepler object
        contains these values in the FITS extension 0 header.

    Returns
    -------

    float or array-like
        SDSS r band magnitude(s) converted from the Kepler band magnitude.

    '''
    arg_3 = arg_1 - arg_2

    if arg_3 < 0.8:
        arg_4 = (arg_0 - 0.2*arg_1)/0.8
    else:
        arg_4 = (arg_0 - 0.1*arg_1)/0.9
    return arg_4


def Func(arg_0,
                         arg_1=True,
                         arg_2='sap,pdc',
                         arg_3=None):
    '''This filters the Kepler `lcdict`, removing nans and bad
    observations.

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

    Parameters
    ----------

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

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

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

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

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

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

    Returns
    -------

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

    '''

    arg_4 = arg_0['columns']

    # filter all bad LC points as noted by quality flags
    if arg_1:

        arg_5 = arg_0['time'].size
        arg_6 = arg_0['sap_quality'] == 0

        for arg_7 in arg_4:
            if '.' in arg_7:
                arg_8, arg_9 = arg_7.split('.')
                arg_0[arg_8][arg_9] = arg_0[arg_8][arg_9][arg_6]
            else:
                arg_0[arg_7] = arg_0[arg_7][arg_6]

        arg_10 = arg_0['time'].size
        LOGINFO('applied quality flag filter, ndet before = %s, ndet after = %s'
                % (arg_5, arg_10))

    if arg_2 and arg_2 == 'sap,pdc':
        arg_11 = (
            npisfinite(arg_0['sap']['sap_flux']) &
            npisfinite(arg_0['pdc']['pdcsap_flux']) &
            npisfinite(arg_0['time'])
        )
    elif arg_2 and arg_2 == 'sap':
        arg_11 = (
            npisfinite(arg_0['sap']['sap_flux']) &
            npisfinite(arg_0['time'])
        )
    elif arg_2 and arg_2 == 'pdc':
        arg_11 = (
            npisfinite(arg_0['pdc']['pdcsap_flux']) &
            npisfinite(arg_0['time'])
        )

    # remove nans from all columns
    if arg_2:

        arg_5 = arg_0['time'].size
        for arg_7 in arg_4:
            if '.' in arg_7:
                arg_8, arg_9 = arg_7.split('.')
                arg_0[arg_8][arg_9] = arg_0[arg_8][arg_9][arg_11]
            else:
                arg_0[arg_7] = arg_0[arg_7][arg_11]

        arg_10 = arg_0['time'].size

        LOGINFO('removed nans, ndet before = %s, ndet after = %s'
                % (arg_5, arg_10))

    # exclude all times in timestoignore
    if (arg_3 and
        isinstance(arg_3, list) and
        len(arg_3) > 0):

        arg_12 = npfull_like(arg_0['time'], True, dtype=np.bool_)
        arg_5 = arg_12.size

        # get all the masks
        for arg_13 in arg_3:
            arg_14, arg_15 = arg_13[0], arg_13[1]
            arg_16 = ~((arg_0['time'] >= arg_14) & (arg_0['time'] <= arg_15))
            arg_12 = arg_12 & arg_16

        # apply the masks
        for arg_7 in arg_4:
            if '.' in arg_7:
                arg_8, arg_9 = arg_7.split('.')
                arg_0[arg_8][arg_9] = arg_0[arg_8][arg_9][arg_12]
            else:
                arg_0[arg_7] = arg_0[arg_7][arg_12]

        arg_10 = arg_0['time'].size
        LOGINFO('removed timestoignore, ndet before = %s, ndet after = %s'
                % (arg_5, arg_10))

    return arg_0


def Func(arg_0, arg_1, arg_2=0.1, arg_3=3):
    '''After running `detrend_centroid`, this gets positions of centroids during
    transits, and outside of transits.

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

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

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

    Parameters
    ----------

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

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

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

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

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

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

    Returns
    -------

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

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

    '''

    # NOTE:
    # Bryson+ (2013) gives a more complicated and more correct approach to this
    # problem, computing offsets relative to positions defined on the SKY. This
    # requires using a Kepler focal plane geometry model. I don't have that
    # model, or know how to get it. So I use a simpler approach.

    arg_4 = int(np.unique(arg_0['quarter']))
    LOGINFO('Getting centroid offsets (qnum: {:d})...'.format(arg_4))
    # Kepler pixel scale, cf.
    # https://keplerscience.arc.nasa.gov/the-kepler-space-telescope.html
    arg_5 = 3.98

    # Get the residuals (units: pixel offset).
    arg_6 = arg_0['ctd_dtr']['times']
    arg_7 = arg_0['ctd_dtr']['ctd_x'] - arg_0['ctd_dtr']['fit_ctd_x']
    arg_8 = arg_0['ctd_dtr']['ctd_y'] - arg_0['ctd_dtr']['fit_ctd_y']

    # Return results in "centroid dictionary" (has keys of transit number).
    arg_9 = {}
    for arg_10,(arg_11,arg_12) in enumerate(arg_1):

        # We have in-transit times as input.
        arg_13 = arg_6[(arg_6 > arg_11) & (arg_6 < arg_12)]

        # Compute out of transit times on either side of the in-transit times.
        arg_14 = arg_12 - arg_11
        arg_15 = arg_3 * arg_14

        arg_16 = arg_6[
            (arg_6 < (arg_11-arg_2)) &
            (arg_6 > (arg_11-arg_2-arg_15))
        ]
        arg_17 = arg_6[
            (arg_6 > (arg_12+arg_2)) &
            (arg_6 < (arg_12+arg_2+arg_15))
        ]

        arg_18 = npconcatenate([arg_16, arg_17])

        arg_19 = npin1d(arg_6, arg_13)
        arg_20 = npin1d(arg_6, arg_18)

        # Convert to units of arcseconds.
        arg_21 = arg_7[arg_19]*arg_5
        arg_22 = arg_8[arg_19]*arg_5
        arg_23 = arg_7[arg_20]*arg_5
        arg_24 = arg_8[arg_20]*arg_5

        arg_9[arg_10] = {'ctd_x_in_tra':arg_21,
                  'ctd_y_in_tra':arg_22,
                  'ctd_x_oot':arg_23,
                  'ctd_y_oot':arg_24,
                  'npts_in_tra':len(arg_21),
                  'npts_oot':len(arg_23),
                  'in_tra_times':arg_13,
                  'oot_times':arg_18}

    LOGINFO('Got centroid offsets (qnum: {:d}).'.format(arg_4))

    return arg_9


def Func(arg_0):
    '''This is a helper function for centroid detrending.

    '''

    from scipy.interpolate import interp1d

    arg_1 = nparray([4,5,6,10,15])
    arg_2 = nparray([1e2,3e2,5e2,1e3,3e3])
    arg_3 = interp1d(arg_2, arg_1, kind='linear',
                  bounds_error=False,
                  fill_value=(min(arg_1), max(arg_1)))
    arg_4 = int(npfloor(arg_3(arg_0)))

    return arg_4


def Func(arg_0,
              arg_1,
              arg_2=None,
              arg_3='hat-sql',
              arg_4=None,
              arg_5=None,
              arg_6=None,
              arg_7=None,
              arg_8=7):

    '''This bins the given light curve file in time using the specified bin size.

    Parameters
    ----------

    lcfile : str
        The file name to process.

    binsizesec : float
        The time bin-size in seconds.

    outdir : str or None
        If this is a str, the output LC will be written to `outdir`. If this is
        None, the output LC will be written to the same directory as `lcfile`.

    lcformat : str
        This is the `formatkey` associated with your light curve format, which
        you previously passed in to the `lcproc.register_lcformat`
        function. This will be used to look up how to find and read the light
        curve file.

    lcformatdir : str or None
        If this is provided, gives the path to a directory when you've stored
        your lcformat description JSONs, other than the usual directories lcproc
        knows to search for them in. Use this along with `lcformat` to specify
        an LC format JSON file that's not currently registered with lcproc.

    timecols,magcols,errcols : lists of str
        The keys in the lcdict produced by your light curve reader function that
        correspond to the times, mags/fluxes, and associated measurement errors
        that will be used as inputs to the binning process. If these are None,
        the default values for `timecols`, `magcols`, and `errcols` for your
        light curve format will be used here.

    minbinelems : int
        The minimum number of time-bin elements required to accept a time-bin as
        valid for the output binned light curve.

    Returns
    -------

    str
        The name of the output pickle file with the binned LC.

        Writes the output binned light curve to a pickle that contains the
        lcdict with an added `lcdict['binned'][magcol]` key, which contains the
        binned times, mags/fluxes, and errs as
        `lcdict['binned'][magcol]['times']`, `lcdict['binned'][magcol]['mags']`,
        and `lcdict['epd'][magcol]['errs']` for each `magcol` provided in the
        input or default `magcols` value for this light curve format.

    '''

    try:
        arg_9 = get_lcformat(arg_3,
                                  use_lcformat_dir=arg_4)
        if arg_9:
            (arg_10, arg_11,
             arg_12, arg_13, arg_14,
             arg_15, arg_16) = arg_9
        else:
            LOGERROR("can't figure out the light curve format")
            return None
    except Exception as e:
        LOGEXCEPTION("can't figure out the light curve format")
        return None

    # override the default timecols, magcols, and errcols
    # using the ones provided to the function
    if arg_5 is None:
        arg_5 = arg_12
    if arg_6 is None:
        arg_6 = arg_13
    if arg_7 is None:
        arg_7 = arg_14

    # get the LC into a dict
    arg_17 = arg_11(arg_0)

    # this should handle lists/tuples being returned by readerfunc
    # we assume that the first element is the actual lcdict
    # FIXME: figure out how to not need this assumption
    if ( (isinstance(arg_17, (list, tuple))) and
         (isinstance(arg_17[0], dict)) ):
        arg_17 = arg_17[0]

    # skip already binned light curves
    if 'binned' in arg_17:
        LOGERROR('this light curve appears to be binned already, skipping...')
        return None

    arg_17['binned'] = {}

    for arg_18, arg_19, arg_20 in zip(arg_5, arg_6, arg_7):

        # dereference the columns and get them from the lcdict
        if '.' in arg_18:
            arg_21 = arg_18.split('.')
        else:
            arg_21 = [arg_18]
        arg_22 = _dict_get(arg_17, arg_21)

        if '.' in arg_19:
            arg_23 = arg_19.split('.')
        else:
            arg_23 = [arg_19]
        arg_24 = _dict_get(arg_17, arg_23)

        if '.' in arg_20:
            arg_25 = arg_20.split('.')
        else:
            arg_25 = [arg_20]
        arg_26 = _dict_get(arg_17, arg_25)

        # normalize here if not using special normalization
        if arg_16 is None:
            arg_27, arg_28 = normalize_magseries(
                arg_22, arg_24,
                arg_15=arg_15
            )

            arg_22, arg_24, arg_26 = arg_27, arg_28, arg_26

        # now bin the mag series as requested
        arg_29 = time_bin_magseries_with_errs(arg_22,
                                              arg_24,
                                              arg_26,
                                              binsize=arg_1,
                                              arg_8=arg_8)

        # put this into the special binned key of the lcdict
        arg_17['binned'][arg_19] = {'times':arg_29['binnedtimes'],
                                  'mags':arg_29['binnedmags'],
                                  'errs':arg_29['binnederrs'],
                                  'nbins':arg_29['nbins'],
                                  'timebins':arg_29['jdbins'],
                                  'binsizesec':arg_1}

    # done with binning for all magcols, now generate the output file
    # this will always be a pickle

    if arg_2 is None:
        arg_2 = os.path.dirname(arg_0)

    arg_30 = os.path.join(arg_2, '%s-binned%.1fsec-%s.pkl' %
                           (squeeze(arg_17['objectid']).replace(' ','-'),
                            arg_1, arg_3))

    with open(arg_30, 'wb') as outfd:
        pickle.dump(arg_17, outfd, protocol=pickle.HIGHEST_PROTOCOL)

    return arg_30


def Func(arg_0,
                           arg_1,
                           arg_2=None,
                           arg_3=None,
                           arg_4='hat-sql',
                           arg_5=None,
                           arg_6=None,
                           arg_7=None,
                           arg_8=None,
                           arg_9=7,
                           arg_10=arg_11,
                           arg_12=1000):
    '''
    This time bins all the light curves in the specified directory.

    Parameters
    ----------

    lcdir : list of str
        Directory containing the input LCs to process.

    binsizesec : float
        The time bin size to use in seconds.

    maxobjects : int or None
        If provided, LC processing will stop at `lclist[maxobjects]`.

    outdir : str or None
        The directory where output LCs will be written. If None, will write to
        the same directory as the input LCs.

    lcformat : str
        This is the `formatkey` associated with your light curve format, which
        you previously passed in to the `lcproc.register_lcformat`
        function. This will be used to look up how to find and read the light
        curve file.

    lcformatdir : str or None
        If this is provided, gives the path to a directory when you've stored
        your lcformat description JSONs, other than the usual directories lcproc
        knows to search for them in. Use this along with `lcformat` to specify
        an LC format JSON file that's not currently registered with lcproc.

    timecols,magcols,errcols : lists of str
        The keys in the lcdict produced by your light curve reader function that
        correspond to the times, mags/fluxes, and associated measurement errors
        that will be used as inputs to the binning process. If these are None,
        the default values for `timecols`, `magcols`, and `errcols` for your
        light curve format will be used here.

    minbinelems : int
        The minimum number of time-bin elements required to accept a time-bin as
        valid for the output binned light curve.

    nworkers : int
        Number of parallel workers to launch.

    maxworkertasks : int
        The maximum number of tasks a parallel worker will complete before being
        replaced to guard against memory leaks.

    Returns
    -------

    dict
        The returned dict contains keys = input LCs, vals = output LCs.

    '''
    try:
        arg_13 = get_lcformat(arg_4,
                                  use_lcformat_dir=arg_5)
        if arg_13:
            (arg_14, arg_15,
             arg_16, arg_17, arg_18,
             arg_19, arg_20) = arg_13
        else:
            LOGERROR("can't figure out the light curve format")
            return None
    except Exception as e:
        LOGEXCEPTION("can't figure out the light curve format")
        return None

    arg_21 = sorted(glob.glob(os.path.join(arg_0, arg_14)))

    return parallel_timebin(arg_21,
                            arg_1,
                            arg_2=arg_2,
                            arg_3=arg_3,
                            arg_4=arg_4,
                            arg_6=arg_6,
                            arg_7=arg_7,
                            arg_8=arg_8,
                            arg_9=arg_9,
                            arg_10=arg_10,
                            arg_12=arg_12)


def Func(arg_0,
                         arg_1,
                         arg_2=None,
                         arg_3=None,
                         arg_4=None,
                         arg_5=None,
                         arg_6=1000,
                         arg_7='hat-sql',
                         arg_8=None,
                         arg_9=arg_10):
    '''This runs variable feature extraction in parallel for all LCs in `lclist`.

    Parameters
    ----------

    lclist : list of str
        The list of light curve file names to process.

    outdir : str
        The directory where the output varfeatures pickle files will be written.

    maxobjects : int
        The number of LCs to process from `lclist`.

    timecols : list of str or None
        The timecol keys to use from the lcdict in calculating the features.

    magcols : list of str or None
        The magcol keys to use from the lcdict in calculating the features.

    errcols : list of str or None
        The errcol keys to use from the lcdict in calculating the features.

    mindet : int
        The minimum number of LC points required to generate variability
        features.

    lcformat : str
        This is the `formatkey` associated with your light curve format, which
        you previously passed in to the `lcproc.register_lcformat`
        function. This will be used to look up how to find and read the light
        curves specified in `basedir` or `use_list_of_filenames`.

    lcformatdir : str or None
        If this is provided, gives the path to a directory when you've stored
        your lcformat description JSONs, other than the usual directories lcproc
        knows to search for them in. Use this along with `lcformat` to specify
        an LC format JSON file that's not currently registered with lcproc.

    nworkers : int
        The number of parallel workers to launch.

    Returns
    -------

    dict
        A dict with key:val pairs of input LC file name : the generated
        variability features pickles for each of the input LCs, with results for
        each magcol in the input `magcol` or light curve format's default
        `magcol` list.

    '''
    # make sure to make the output directory if it doesn't exist
    if not os.path.exists(arg_1):
        os.makedirs(arg_1)

    if arg_2:
        arg_0 = arg_0[:arg_2]

    arg_11 = [(x, arg_1, arg_3, arg_4, arg_5, arg_6,
              arg_7, arg_8) for x in arg_0]

    with ProcessPoolExecutor(max_workers=arg_9) as executor:
        arg_12 = executor.map(varfeatures_worker, arg_11)

    arg_13 = [x for x in arg_12]
    arg_14 = {os.path.basename(x):y for (x,y) in zip(arg_0, arg_13)}

    return arg_14


def Func(arg_0,
                               arg_1,
                               arg_2=None,
                               arg_3=None,
                               arg_4=None,
                               arg_5=None,
                               arg_6=None,
                               arg_7=True,
                               arg_8=1000,
                               arg_9='hat-sql',
                               arg_10=None,
                               arg_11=arg_12):
    '''This runs parallel variable feature extraction for a directory of LCs.

    Parameters
    ----------

    lcdir : str
        The directory of light curve files to process.

    outdir : str
        The directory where the output varfeatures pickle files will be written.

    fileglob : str or None
        The file glob to use when looking for light curve files in `lcdir`. If
        None, the default file glob associated for this LC format will be used.

    maxobjects : int
        The number of LCs to process from `lclist`.

    timecols : list of str or None
        The timecol keys to use from the lcdict in calculating the features.

    magcols : list of str or None
        The magcol keys to use from the lcdict in calculating the features.

    errcols : list of str or None
        The errcol keys to use from the lcdict in calculating the features.

    mindet : int
        The minimum number of LC points required to generate variability
        features.

    lcformat : str
        This is the `formatkey` associated with your light curve format, which
        you previously passed in to the `lcproc.register_lcformat`
        function. This will be used to look up how to find and read the light
        curves specified in `basedir` or `use_list_of_filenames`.

    lcformatdir : str or None
        If this is provided, gives the path to a directory when you've stored
        your lcformat description JSONs, other than the usual directories lcproc
        knows to search for them in. Use this along with `lcformat` to specify
        an LC format JSON file that's not currently registered with lcproc.

    nworkers : int
        The number of parallel workers to launch.

    Returns
    -------

    dict
        A dict with key:val pairs of input LC file name : the generated
        variability features pickles for each of the input LCs, with results for
        each magcol in the input `magcol` or light curve format's default
        `magcol` list.

    '''

    try:
        arg_13 = get_lcformat(arg_9,
                                  use_lcformat_dir=arg_10)
        if arg_13:
            (arg_14, arg_15,
             arg_16, arg_17, arg_18,
             arg_19, arg_20) = arg_13
        else:
            LOGERROR("can't figure out the light curve format")
            return None
    except Exception as e:
        LOGEXCEPTION("can't figure out the light curve format")
        return None

    if not arg_2:
        arg_2 = arg_14

    # now find the files
    LOGINFO('searching for %s light curves in %s ...' % (arg_9, arg_0))

    if arg_7 is False:
        arg_21 = glob.glob(os.path.join(arg_0, arg_2))

    else:
        # use recursive glob for Python 3.5+
        if sys.version_info[:2] > (3,4):

            arg_21 = glob.glob(os.path.join(arg_0,
                                              '**',
                                              arg_2),
                                 arg_7=True)

        # otherwise, use os.walk and glob
        else:

            # use os.walk to go through the directories
            arg_22 = os.walk(arg_0)
            arg_21 = []

            for arg_23, arg_24, arg_25 in arg_22:
                for arg_26 in arg_24:
                    arg_27 = os.path.join(arg_23,
                                              arg_26,
                                              arg_2)
                    arg_28 = glob.glob(arg_27)

                    if arg_28:
                        arg_21.extend(arg_28)

    # now that we have all the files, process them
    if arg_21 and len(arg_21) > 0:

        LOGINFO('found %s light curves, getting varfeatures...' %
                len(arg_21))

        return parallel_varfeatures(arg_21,
                                    arg_1,
                                    arg_3=arg_3,
                                    arg_4=arg_4,
                                    arg_5=arg_5,
                                    arg_6=arg_6,
                                    arg_8=arg_8,
                                    arg_9=arg_9,
                                    arg_10=arg_10,
                                    arg_11=arg_11)

    else:

        LOGERROR('no light curve files in %s format found in %s' % (arg_9,
                                                                    arg_0))
        return None


def Func(arg_0, arg_1=None):
    '''This is just a shortened form of the function above for convenience.

    This only handles pickle files as input.

    Parameters
    ----------

    checkplotin : str
        File name of a checkplot pickle file to convert to a PNG.

    extrarows : list of tuples
        This is a list of 4-element tuples containing paths to PNG files that
        will be added to the end of the rows generated from the checkplotin
        pickle/dict. Each tuple represents a row in the final output PNG
        file. If there are less than 4 elements per tuple, the missing elements
        will be filled in with white-space. If there are more than 4 elements
        per tuple, only the first four will be used.

        The purpose of this kwarg is to incorporate periodograms and phased LC
        plots (in the form of PNGs) generated from an external period-finding
        function or program (like VARTOOLS) to allow for comparison with
        astrobase results.

        NOTE: the PNG files specified in `extrarows` here will be added to those
        already present in the input `checkplotdict['externalplots']` if that is
        None because you passed in a similar list of external plots to the
        :py:func:`astrobase.checkplot.pkl.checkplot_pickle` function earlier. In
        this case, `extrarows` can be used to add even more external plots if
        desired.

        Each external plot PNG will be resized to 750 x 480 pixels to fit into
        an output image cell.

        By convention, each 4-element tuple should contain:

        - a periodiogram PNG
        - phased LC PNG with 1st best peak period from periodogram
        - phased LC PNG with 2nd best peak period from periodogram
        - phased LC PNG with 3rd best peak period from periodogram

        Example of extrarows::

            [('/path/to/external/bls-periodogram.png',
              '/path/to/external/bls-phasedlc-plot-bestpeak.png',
              '/path/to/external/bls-phasedlc-plot-peak2.png',
              '/path/to/external/bls-phasedlc-plot-peak3.png'),
             ('/path/to/external/pdm-periodogram.png',
              '/path/to/external/pdm-phasedlc-plot-bestpeak.png',
              '/path/to/external/pdm-phasedlc-plot-peak2.png',
              '/path/to/external/pdm-phasedlc-plot-peak3.png'),
            ...]

    Returns
    -------

    str
        The absolute path to the generated checkplot PNG.

    '''

    if arg_0.endswith('.gz'):
        arg_2 = arg_0.replace('.pkl.gz','.png')
    else:
        arg_2 = arg_0.replace('.pkl','.png')

    return checkplot_pickle_to_png(arg_0, arg_2, arg_1=arg_1)


def Func(arg_0, arg_1, arg_2, arg_3):
    '''This is a flare model function, similar to Kowalski+ 2011.

    From the paper by Pitkin+ 2014:
    http://adsabs.harvard.edu/abs/2014MNRAS.445.2268P

    Parameters
    ----------

    flareparams : list of float
        This defines the flare model::

            [amplitude,
             flare_peak_time,
             rise_gaussian_stdev,
             decay_time_constant]

        where:

        `amplitude`: the maximum flare amplitude in mags or flux. If flux, then
        amplitude should be positive. If mags, amplitude should be negative.

        `flare_peak_time`: time at which the flare maximum happens.

        `rise_gaussian_stdev`: the stdev of the gaussian describing the rise of
        the flare.

        `decay_time_constant`: the time constant of the exponential fall of the
        flare.

    times,mags,errs : np.array
        The input time-series of measurements and associated errors for which
        the model will be generated. The times will be used to generate
        model mags.

    Returns
    -------

    (modelmags, times, mags, errs) : tuple
        Returns the model mags evaluated at the input time values. Also returns
        the input `times`, `mags`, and `errs`.

    '''

    (arg_4, arg_5,
     arg_6, arg_7) = arg_0

    arg_8 = np.median(arg_2)
    arg_9 = np.full_like(arg_1, arg_8)

    # before peak gaussian rise...
    arg_9[arg_1 < arg_5] = (
        arg_2[arg_1 < arg_5] +
        arg_4 * np.exp(
            -((arg_1[arg_1 < arg_5] -
               arg_5) *
              (arg_1[arg_1 < arg_5] -
               arg_5)) /
            (2.0*arg_6*arg_6)
        )
    )

    # after peak exponential decay...
    arg_9[arg_1 > arg_5] = (
        arg_2[arg_1 > arg_5] +
        arg_4 * np.exp(
            -((arg_1[arg_1 > arg_5] -
               arg_5)) /
            (arg_7)
        )
    )

    return arg_9, arg_1, arg_2, arg_3


def Func():
    """This checks the AWS instance data URL to see if there's a pending
    shutdown for the instance.

    This is useful for AWS spot instances. If there is a pending shutdown posted
    to the instance data URL, we'll use the result of this function break out of
    the processing loop and shut everything down ASAP before the instance dies.

    Returns
    -------

    bool
        - True if the instance is going to die soon.
        - False if the instance is still safe.

    """

    arg_0 = 'http://169.254.169.254/latest/meta-data/spot/instance-action'

    try:
        arg_1 = requests.get(arg_0, timeout=1.0)
        arg_1.raise_for_status()

        arg_2 = arg_1.json()
        if 'action' in arg_2 and arg_2['action'] in ('stop',
                                                           'terminate',
                                                           'hibernate'):
            arg_3 = arg_2['time']
            LOGWARNING('instance is going to %s at %s' % (arg_2['action'],
                                                          arg_3))

            arg_1.close()
            return True
        else:
            arg_1.close()
            return False

    except HTTPError as e:
        arg_1.close()
        return False

    except Exception as e:
        arg_1.close()
        return False