r"""
    This method calculates the jet positon and wind speed at that position by fitting a parabola around the
    maximum of zonally average u-component wind speed, using the magnitude at the maximum ('jet_speed') and latitude at that maximum ('jet_lat').

    This method was originally introduce in Barnes & Polvani (2015) https://doi.org/10.1175/JCLI-D-14-00589.1
    and is described in Section 2b of that study.

    Please see 'Notes' below for any additional information about the implementation of this method
    to this package.

    Parameters
    ----------
    data : xarray.Dataset
        Data which should containing the variables: 'ua', and the coordinates: 'lon', 'lat', 'plev' and 'time'.

    Returns
    ----------
    output : xarray.Dataset
        Data containing the two outputs: 'jet_lat' and 'jet_speed'

    Notes
    -----
    This methodology make an assumption that the a parabola can be fit to windspeed profile, so it performs quite different from
    other jet latitude methods available in the package in cases where the windspeed profile is more complex (multiple jets),
    and on data with finer temporal resolution in general.

    Examples
    --------
    .. code-block:: python

        import jsmetrics
        import xarray as xr

        # Load in dataset with u component wind:
        ua_data = xr.open_dataset('path_to_u_data')

        # Subset dataset to range used in original methodology (700-925 hPa &  30-70N,  130-10W)):
        ua_sub = ua.sel(plev=slice(700, 925), lat=slice(30, 70), lon=slice(230, 350))

        # Run statistic:
        bp15 = jsmetrics.jet_statistics.barnes_polvani_2015(ua_sub)


r"""
    This method calculates two outputs: 'jet_lat' and 'jet_speed' which are defined as the latitude and speed of the 10-day-averaged
    maximum zonally-averaged wind speed.

    This method was originally introduce in Barnes & Simpson 2017 https://doi.org/10.1175/JCLI-D-17-0299.1
    and is described in Section 2b of that study.

    Please see 'Notes' below for any additional information about the implementation of this method
    to this package.

    Parameters
    ----------
    data : xarray.Dataset
        Data which should containing the variables: 'ua', and the coordinates: 'lon', 'lat', 'plev' and 'time'.

    Returns
    ----------
    output : xarray.Dataset
        Data containing the x outputs: 'jet_lat' and 'jet_speed'

    Notes
    -----
    The original methodology was intended to work on one pressure level (700 hPa) and on daily data, for the
    implementation included in this package, we have included methods to automatically average any inputted pressure levels
    and to return the data without 10-day averaging if data above the 10-day resolution is inputted.
    Instead, warnings are returned to user to help them use the method the way it was originally intended.

    Examples
    --------
    .. code-block:: python

        import jsmetrics
        import xarray as xr

        # Load in dataset with u component wind:
        ua_data = xr.open_dataset('path_to_u_data')

        # Subset dataset to range used in original methodology (700 hPa & North Atlantic & North Pacific)):
        ua_na = ua.sel(plev=700, lat=slice(0, 90), lon=slice(280, 350)) # North Atlantic
        ua_np = ua.sel(plev=700, lat=slice(0, 90), lon=slice(120, 230)) # North Pacific

        # Run statistic:
        bp17_na = jsmetrics.jet_statistics.barnes_simpson_2017(ua_na)
        bp17_np = jsmetrics.jet_statistics.barnes_simpson_2017(ua_np)


r"""
    This method calculates the seasonal and annual jet-stream position ('JPOS') and strength ('JSTR')
    by applying a 0.075 degrees cubic spline interpolation to a zonally-averaged wind climatology
    and selecting the maximum.

    This method was originally introduce in Bracegirdle et al (2018) https://doi.org/10.1175/JCLI-D-17-0320.1
    and is described in Section 2 of that study.

    Please see 'Notes' below for any additional information about the implementation of this method
    to this package.

    Parameters
    ----------
    data : xarray.Dataset
        Data which should containing the variables: 'ua', and the coordinates: 'lon', 'lat', 'plev' and 'time'.

    Returns
    ----------
    output : xarray.Dataset
        Data containing the four outputs: 'annual_JPOS', 'seasonal_JPOS', 'annual_JSTR' and 'seasonal_JSTR'

    Notes
    -----
    This method was originally developed for the jet streams in the Southern Hemisphere.

    Examples
    --------
    .. code-block:: python

        import jsmetrics
        import xarray as xr

        # Load in dataset with u component wind:
        ua_data = xr.open_dataset('path_to_u_data')

        # Subset dataset to range used in original methodology (850 hPa &  -75--10N)):
        ua_sub = ua.sel(plev=850, lat=slice(-75, -10))

        # Run statistic:
        b18 = jsmetrics.jet_statistics.bracegirdle_et_al_2018(ua_sub)


r"""
    This method defines the latitude and speed of the jet-stream where the maximum zonal winds occur for
    each longitude and for each time unit (i.e. day). These values are then smoothed across the longitudes
    with a rectangular pulse (by default this has a width of 10 degrees).

    This method was originally introduced in Kerr et al. (2020) https://onlinelibrary.wiley.com/doi/10.1029/2020JD032735
    and is described in Section 2.4.2 of that study.

    Please see 'Notes' below for any additional information about the implementation of this method
    to this package.

    Parameters
    ----------
    data : xarray.Dataset
        Data which should containing the variables: 'ua', and the coordinates: 'lon', 'lat', 'plev' and 'time'.

    Returns
    ----------
    output : xarray.Dataset
        Data containing the two outputs: 'jet_lat' and 'smoothed_jet_lat'

    Notes
    -----
    This method was based on the method from Barnes and Fiore (2013) https://doi.org/10.1002/grl.50411

    The implementation here returns both smoothed and unsmoothed jet latitude outputs.

    Examples
    --------
    .. code-block:: python

        import jsmetrics
        import xarray as xr

        # Load in dataset with u component wind:
        ua_data = xr.open_dataset('path_to_u_data')

        # Subset dataset to range used in original methodology (700 hPa &  20-70N,  300-360W)):
        ua_sub = ua.sel(plev=700, lat=slice(20, 70), lon=slice(300, 360))

        # Run statistic:
        k20 = jsmetrics.jet_statistics.kerr_et_al_2020(ua_sub)


    Adds a number of days to cftime.Datetime360Day format

    Parameters
    ----------
    datetime_360day : cftime.Datetime360Day
        Date to add days to

    num_of_days_to_add : int or float
        Number of days to add to 360 day format

    Returns
    ----------
    new_360day_date : cftime.Datetime360Day
        Date with added number of days

    Raises
    ----------
    AssertionError :
        If not '360_day' format or not a cftime.Datetime object
    ValueError :
        If number of days not more than 0


    Adds a number of days to cftime.DatetimeNoLeap format

    Parameters
    ----------
    datetime_noleap : cftime.DatetimeNoLeap
        Date to add days to

    num_of_days_to_add : int or float
        Number of days to add to noleap day format

    Returns
    ----------
    new_noleap_date : cftime.DatetimeNoLeap
        Date with added number of days

    Raises
    ----------
    AssertionError :
        If not 'noleap' format or not a cftime.Datetime object
    ValueError :
        If number of days not more than 0


    Add a edge of constant values around a numpy array

    Parameters
    ----------
    arr : array-like
        A 2-D array with numeric values (i.e. dtypes float or int)
    pad_width : int
        Width of values to add to edges (default: 1)
    constant_values : int
        Value to add to edges (default: 0)

    Returns
    ----------
    padded_arr : array-like
        A 2-D array with new dimensions as a pad has been added at the edges


    Checks there are at least two pressure-levels (plevs) in xarray dataset

    Parameters
    ----------
    data : xarray.Dataset
        Data to check

    Raises
    ----------
    ValueError :
        If not two pressure levels


    Will check if a given coordinates are in the data and raises a key error if any of them are not.
    This function is needed to check before algorithm continues and uses too much memory.
    Built from xarray.

    Parameters
    ----------
    data : xarray.Dataset
        Data to check
    req_coords : array-like or tuple
        Coordinates to check if in data

    Raises
    ----------
    KeyError :
        If any given coord is not in data


    What it says on the tin.

    Parameters
    ----------
    data : xarray.Dataset
        Data to check

    Raises
    ----------
    TypeError :
        If input is not an xarray data type


    Will check that pressure level units are in data plev coord (i.e. Pa, hPa, mbar, millibars).

    Parameters
    ----------
    data : xr.DataArray or xr.Dataset
        Data containing plev coord and units for plev
    expected_plev_units : list
        List of names of plev units (i.e. mbar, Pa, hPa, etc.)

    Returns
    ----------
    units : str
        Units of plev coord

    Raises
    ----------
    KeyError
        If plev is not a coord in input 'data'. And if the units of plev are not in expected plev units


    What it says on the tin.
    Built from xarray

    Parameters
    ----------
    data : xarray.Dataset
        Data to check
    req_variables : array-like
        Variables needed in data

    Raises
    ----------
    KeyError :
        If variables not in data


    Will find the nearest value to a given array
    Built for use with xarray
    adapted from: https://stackoverflow.com/questions/2566412/find-nearest-value-in-numpy-array

    Parameters
    ----------
    array : array-like
        Array to reference
    value : numeric-like
        Number to check nearest value in input array

    Returns
    ----------
    output : numeric
        Closest value to input value in input array


    Filter local extremes (i.e. outputs of minima or maxima from scipy.signal.argrelextrema)
    so that no neighbours remain in array.

    Parameters
    ----------
    local_extrema : array-like
        likely (stacked) outputs of scipy.signal.argrelextrema
    min_distance_threshold : int
        Minimum distances between indexes in array (default: 2 indexes)

    Returns
    -------
    filtered_extrema : array-like
        (stacked) outputs of scipy.signal.argrelextrema with values less than a min_distance_threshold away removed

    Examples
    --------
    maxima_indices = np.column_stack(jsmetrics.utils.data_utils.get_local_maxima(current['ws'].data))
    filtered_indices = filter_local_extremes_so_no_neighbours(maxima_indices, min_distance_threshold=2)


    Find the intersection between two arrays of arrays. See examples for example.

    Parameters
    ----------
    array1 : np.array
        First array of arrays to compare with array2
    array2 : np.array
        Second array of arrays to compare with array1

    Returns
    -------
    intersection : np.array
        Intesection of the two arrays returning only the arrays within the original two that are in both.

    Examples
    --------
    array1 = [[1, 2], [3, 4]]
    array2 = [[1, 2], [4, 3]]
    find_intersection_between_two_array_of_arrays(array1, array2)
    # returns [[1, 2]]


    Removes duplicates from array. From:
    https://stackoverflow.com/questions/2213923/removing-duplicates-from-a-list-of-lists

    Parameters
    ----------
    arr : array-like
        arr to remove duplicates from

    Returns
    ----------
    arr : array-like
        arr with no duplicates


    What it says on the tin.
    Built from xarray

    Parameters
    ----------
    data : xarray.Dataset
        Data to check

    wanted_coords : array-like or tuple
        Coords to retain in data
    unwanted_coords : array-like or tuple
        Coords to remove from data

    Raises
    ----------
    ValueError :
        If coord cannot be removed from data


    Rescale latitude resolution to input lat resolution in degrees.

    Component of method from Barnes & Polvani (2013) https://doi.org/10.1175/JCLI-D-12-00536.1
    & Grise & Polvani 2014 https://doi.org/10.1002/2013GL058466
    & Bracegirdle et al (2018) https://doi.org/10.1175/JCLI-D-17-0320.1

    Parameters
    ----------
    lats : xr.DataArray or array-like
        Array of latitude values
    lat_resolution : int or float
        Latitude resolution in degrees

    Returns
    ----------
    output : numpy.array
        Rescaled array of latitude values


    Will break an array down into segments based on a list of indexes containing information about where to create slices

    Parameters
    ----------
    array_to_slice : array-like
        Array to break down based on slice breaks
    index_breaks : array-like
        Indexes from which to slice array

    Returns
    ----------
    output: list
        Broken down slices of original array_to_slice


        The reason this exists is that their may be a point in time where
        constraitns on this calculation will need to be made
        i.e. if too much data or too much RAM in use


Check input data is valid for the windspeed slice.


Returns labels where condition is met.


    Guess bounds of grid cells.

    Simplified function from iris.coord.Coord.

    Author: Denis Sergev (https://github.com/dennissergeev) https://gist.github.com/dennissergeev/60bf7b03443f1b2c8eb96ce0b1880150

    Parameters
    ----------
    points: numpy.array
        Array of grid points of shape (N,).
    bound_position: float, optional
        Bounds offset relative to the grid cell centre.

    Returns
    -------
    Array of shape (N, 2).


    Lazy method to fill in gaps for bounds to make sure it is on a regular grid
    Adapted by githubuser:Thomasjkeel

    Author: Denis Sergev (https://github.com/dennissergeev) https://gist.github.com/dennissergeev/60bf7b03443f1b2c8eb96ce0b1880150


    Calculate spherical segment areas.

    Taken from SciTools iris library.

    Area weights are calculated for each lat/lon cell as:
        .. math::
            r^2 (lon_1 - lon_0) ( sin(lat_1) - sin(lat_0))

    The resulting array will have a shape of
    *(radian_lat_bounds.shape[0], radian_lon_bounds.shape[0])*
    The calculations are done at 64 bit precision and the returned array
    will be of type numpy.float64.

    Author: Denis Sergev (https://github.com/dennissergeev) https://gist.github.com/dennissergeev/60bf7b03443f1b2c8eb96ce0b1880150

    Parameters
    ----------
    radian_lat_bounds: numpy.array
        Array of latitude bounds (radians) of shape (M, 2)
    radian_lon_bounds: numpy.array
        Array of longitude bounds (radians) of shape (N, 2)
    radius_of_earth: float
        Radius of the Earth (currently assumed spherical)

    Returns
    -------
    Array of grid cell areas of shape (M, N).


    Calculate spatial integral of xarray.DataArray with grid cell weighting.

    Author: Denis Sergev (https://github.com/dennissergeev) https://gist.github.com/dennissergeev/60bf7b03443f1b2c8eb96ce0b1880150

    Parameters
    ----------
    xr_da: xarray.DataArray
        Data to average
    lon_name: str, optional
        Name of x-coordinate
    lat_name: str, optional
        Name of y-coordinate
    radius: float
        Radius of the planet [metres], currently assumed spherical (not important anyway)

    Returns
    -------
    Spatially averaged xarray.DataArray.


    Calculate spatial mean of xarray.DataArray with grid cell weighting.

    Author: Denis Sergev (https://github.com/dennissergeev) https://gist.github.com/dennissergeev/60bf7b03443f1b2c8eb96ce0b1880150

    Parameters
    ----------
    xr_da: xarray.DataArray
        Data to average
    lon_name: str, optional
        Name of x-coordinate
    lat_name: str, optional
        Name of y-coordinate
    radius: float
        Radius of the planet [metres], currently assumed spherical (not important anyway)

    Returns
    -------
    Spatially averaged xarray.DataArray.


    Returns the total great circle (haversine) distance along a linestring
    or multilinestring

    Component of method from Cattiaux et al (2016) https://doi.org/10.1002/2016GL070309

    Parameters
    ----------
    line : shapely.geometry.LineString or shapely.geometry.MultiLineString
        Line to calculate great circle distance from

    Returns
    ----------
    total_distance : int or float
        Total distance in degrees or m


    Calculate grid cell areas given 1D arrays of longitudes and latitudes
    for a planet with the given radius.

    Author: Denis Sergev (https://github.com/dennissergeev) https://gist.github.com/dennissergeev/60bf7b03443f1b2c8eb96ce0b1880150

    Parameters
    ----------
    lon1d: numpy.array
        Array of longitude points [degrees] of shape (M,)
    lat1d: numpy.array
        Array of latitude points [degrees] of shape (M,)
    radius: float, optional
        Radius of the planet [metres] (currently assumed spherical)

    Returns
    -------
    Array of grid cell areas [metres**2] of shape (M, N).


    Calculate the great circle distance between two points
    on the earth (specified in decimal degrees)


    Seperates a list of vertices of a given contour into multiple segments for
    eventual conversion to multi-linestring.

    Needed with new Matplotlib depreciation to collections and allsegs of the contour plots.

    Component of method from Cattiaux et al (2016) https://doi.org/10.1002/2016GL070309

    Parameters
    ----------
    one_contour : matplotlib.path.Path
        Path object of one contour from a contour plot

    Returns
    ----------
    all_segments : list of lists
        List of all segments that can be converted to a multilinestring


Function to compute the Fisher matrix using our C++ code and store it at the specified output path


        Function to compute the set of y_ell values using our C++ code for a gamma_1 and gamma_2 maps that are given
        as inputs and store them at the location given by the output_path


Function to compute and save the power spectrum using CCL


    Function to generate a mask that is built up of galactic and ecliptic cuts only.

    The parameter theta describes the angular size of these two cuts.


Function to plot a mask in a consistent way that has already been generated


Function to clean up memory in object once the Cl's have been computed by resetting the large matrix variables


Function to compute the parameter Fisher matrix given a Cl covariance matrix


Function to take our existing Fisher matrix and transform it using the provided Jacobian matrix


Function to plot a set of Fisher matrices for multiple parameters as a triangle plot


Function to plot a set of Fisher matrices for just a single parameters as a one-dimensional density plot


    Function that takes the redshift value and computes the "shift" parameter for the log-normal field that it will
    be associated with.

    Taken from the Flask source code


Function to compute the shear power spectrum at the given redshift and save the values accordingly


Function to generate the Flask .config file which is used for generating the maps with Flask


File to generate the field information file that Flask requires


Function to run a single instance of Flask to generate a single realisation of the cosmic shear maps


Function to run Flask a number of times, as given by the num_maps argument


        Return a list of the class attribute names for allowed pulsar
        parameters.


Return a list of the class attribute values.


        Add a pulsar into the object.

        Args:
            psr (:class:`~psrqpy.pulsar.Pulsar`, :class:`~psrqpy.pulsar.Pulsars`): a
                :class:`~psrqpy.pulsar.Pulsar` object, or :class:`~psrqpy.pulsar.Pulsars`
                object


        Remove a pulsar from the object. Only do one at a time.

        Args:
            psrname (str): a string with the name of a pulsar


        Remove a pulsar from the object and return the removed pulsar.

        Args:
            psrname (str): a string with the name of a pulsar


    Check if the ATNF Pulsar Catalogue has been updated compared to the version
    in the cache.

    Returns:
       bool: True if the cache can be updated.


    Download and cache the ATNF catalogue database.

    Args:
        url (str): the URL of the ATNF Pulsar Catalogue tarball.
        usecache (bool): if True try and get the cached version


            Parse a string value and extract the error if given.

            Args:
                value (str): A string containing a value with associated last
                    digit error in parentheses, e.g., "-1.2324(5)"

            Returns:
                tuple: A tuple containing the value and the error as floats, or
                    NaN for the error is not present


            Return a list of the globular cluster names.

            Args:
                ngc (bool): Set to True to return the NGC names rather than
                    common names (some of which may be NGC names anyway!)


            Return a table just containing the pulsars in a requested globular
            cluster. If the cluster is not found then return None.

            Args:
                cluster (str): The name of the globular cluster for which to
                    return the pulsars.

            Returns:
                :class:`~astropy.table.Table`: a table the pulsars in the given
                    cluster.


    Apply a logical expression to a table of values.

    Args:
        table (:class:`astropy.table.Table` or :class:`pandas.DataFrame`): a
            table of pulsar data
        expression (str, :class:`~numpy.ndarray`): a string containing a set of
            logical conditions with respect to pulsar parameter names (also
            containing `conditions
            <http://www.atnf.csiro.au/research/pulsar/psrcat/psrcat_help.html?type=normal#condition>`_
            allowed when accessing the ATNF Pulsar Catalogue), or a boolean
            array of the same length as the table.
        exactMatch (bool): set to true to exactly match some string comparison
            expressions, e.g., if asking for `'ASSOC(SNR)'` and `exactMatch` is
            True then only pulsar with an association that is just `'SNR'` will
            be returned, whereas if it is False then there could be multiple
            associations including `'SNR'`.

    Returns:
        :class:`astropy.table.Table` or :class:`pandas.DataFrame`: the table of
        values conforming to the input condition. Depending on the type of
        input table the returned table will either be a
        :class:`astropy.table.Table` or :class:`pandas.DataFrame`.

    Example:
        Some examples of this might are:

        1. finding all pulsars with frequencies greater than 100 Hz

        >>> newtable = condition(psrtable, 'F0 > 100')

        2. finding all pulsars with frequencies greater than 50 Hz and
        period derivatives less than 1e-15 s/s.

        >>> newtable = condition(psrtable, '(F0 > 50) & (P1 < 1e-15)')

        3. finding all pulsars in binary systems

        >>> newtable = condition(psrtable, 'TYPE(BINARY)')

        4. parsing a boolean array equivalent to the first example

        >>> newtable = condition(psrtable, psrtable['F0'] > 100)


    Function defining the characteristic age of a pulsar. Returns the
    characteristic age in years using

    .. math::

       \\tau = \\frac{P}{\\dot{P}(n-1)}

    NaNs are returned for any negative period derivates, or NaN imput values.

    Args:
        period (float, array_like): the pulsar period in seconds
        pdot (float, array_like): the pulsar period derivative
        braking_idx (float): the pulsar braking index (defaults to :math:`n=3`)

    Returns:
        float: the characteristic age in years


    Function returning the period derivative for a pulsar with a given period
    and characteristic age, using

    .. math::

       \\dot{P} = \\frac{P}{\\tau(n - 1)}

    Args:
        period (list, :class:`numpy.ndarray`): the pulsar period in seconds
        tau (float): the characteristic age in years
        braking_idx (float): the pulsar braking index (defaults to :math:`n=3`)

    Returns:
        :class:`numpy.ndarray`: an array of period derivatives.


    Function defining the polar magnetic field strength at the surface of the
    pulsar in gauss (Equation 5.12 of Lyne & Graham-Smith, Pulsar Astronmy, 2nd
    edition) with

    .. math::

       B = 3.2\\!\\times\\!10^{19} \\sqrt{P\\dot{P}}

    NaNs are returned for any negative period derivates, or NaN imput values.

    Args:
        period (float): a pulsar period (s)
        pdot (float): a period derivative

    Returns:
        float: the magnetic field strength in gauss.


    Function to get the period derivative from a given pulsar period and
    magnetic field strength using

    .. math::

       \\dot{P} = \\frac{1}{P}\\left( \\frac{B}{3.2\\!\\times\\!10^{19}} \\right)^2

    Args:
        period (list, :class:`~numpy.ndarray`): a list of period values
        Bfield (float): the polar magnetic field strength (Defaults to
            :math:`10^{10}` G)

    Returns:
        :class:`numpy.ndarray`: an array of period derivatives


    Convert period derivatives to frequency derivatives. Either periods or
    frequencies must be supplied.

    .. math::

       \\dot{f} = -\\frac{\\dot{P}}{P^2}

    Args:
        pdot (list, :class:`~numpy.ndarray`): a list of period derivative
            values.
        period (list, :class:`~numpy.ndarray`): a list of periods (seconds)
        frequency (list, :class:`~numpy.ndarray`): a list of frequencies (Hz)

    Returns:
        :class:`numpy.ndarray`: an array of frequency derivatives.


    Convert frequency derivatives to period derivatives. Either periods or
    frequencies must be supplied.

    .. math::

       \\dot{P} = -\\frac{\\dot{f}}{f^2}

    Args:
        fdot (list, :class:`~numpy.ndarray`): a list of frequency derivative
            values.
        period (list, :class:`~numpy.ndarray`): a list of periods (seconds)
        frequency (list, :class:`~numpy.ndarray`): a list of frequencies (Hz)

    Returns:
        :class:`numpy.ndarray`: an array of period derivatives.


    The gravitational-wave amplutitude at Earth assuming all rotational energy
    loss is radiated via emission from an :math:`l=m=2` mass quadrupole mode,
    using (see Equation A7 of [LVC]_)

    .. math::

        h_0^{\\text{sd}} = \\frac{1}{d}\\left(\\frac{5}{2} \\frac{G I_{zz}}{c^3} \\frac{|\\dot{f}|}{f}\\right)^{1/2}

    Args:
        frequency (list, :class:`~numpy.ndarray`): a list of frequencies (Hz).
        fdot (list, :class:`~numpy.ndarray`): a list of frequency derivatives
            (Hz/s).
        distance (list, :class:`~numpy.ndarray`): a list of distances (kpc).
        Izz (float): the moment of inertia along the principle axis (defaults
            to 1e38 kg m\\ :sup:`2`).

    Returns:
        :class:`numpy.ndarray`: an array of spin-down limits.

    .. [LVC] Abbott et al, *ApJ*, **879**, 28 (2019),
        `arXiv:1902.08507 <https://arxiv.org/abs/1902.08507>`_


    The gravitational-wave luminosity as derived from a given gravitatonal-wave
    amplitude measured at Earth, assuming all rotational energy loss is
    radiated via emission from an :math:`l=m=2` mass quadrupole mode, using
    (see Equation A5 of [LVC]_)

    .. math::

        \\dot{E}_{\\text{gw}} = \\frac{8\\pi^2c^3}{5G} f^2 h_0^2 d^2

    Args:
        h0 (list, :class:`~numpy.ndarray`): a list of gravitational-wave
            amplitudes.
        frequency (list, :class:`~numpy.ndarray`): a list of frequencies (Hz).
        distance (list, :class:`~numpy.ndarray`): a list of distances (kpc).

    Returns:
        :class:`numpy.ndarray`: an array of luminosities.


    Convert a gravitational-wave amplitude :math:`h_0` at Earth to an
    equivalent :math:`l=m=2` mass quadrupole :math:`Q_{22}` of the pulsar
    using (see Equations A3 and A4 of [LVC]_):

    .. math::

        Q_{22} = h_0 \\left(\\frac{c^4 d}{16\\pi^2 G f^2} \\right) \\sqrt{\\frac{15}{8\\pi}}

    Args:
        h0 (list, :class:`~numpy.ndarray`): a list of gravitational-wave
            amplitudes.
        frequency (list, :class:`~numpy.ndarray`): a list of frequencies (Hz).
        distance (list, :class:`~numpy.ndarray`): a list of distances (kpc).

    Returns:
        :class:`numpy.ndarray`: an array of :math:`Q_{22}` values.


    Convert a :math:`l=m=2` mass quadrupole :math:`Q_{22}` to an
    equivalent fiducial ellipticity :math:`\\varepsilon` of the pulsar
    using (see Equation A3 of [LVC]_):

    .. math::

        \\varepsilon = \\frac{Q_{22}}{I_{zz}}\\sqrt{\\frac{8\\pi}{15}}

    Args:
        q22 (list, :class:`~numpy.ndarray`): a list of mass quadrupole values
            (kg m\\ :sup:`2`).
        Izz (float): the moment of inertia of the principle axis (defaults to
            1e38 kg m\\ :sup:`2`).

    Returns:
        :class:`numpy.ndarray`: an array of :math:`\\varepsilon` values.


    Convert a fiducial ellipticity :math:`\\varepsilon` of the pulsar to the
    equivalent :math:`l=m=2` mass quadrupole :math:`Q_{22}` using (see
    Equation A3 of [LVC]_):

    .. math::

        Q_{22} = \\varepsilon I_{zz} \\sqrt{\\frac{15}{8\\pi}}

    Args:
        ellipticity (list, :class:`~numpy.ndarray`): a list of ellipticity
            values.
        Izz (float): the moment of inertia of the principle axis (defaults to
            1e38 kg m\\ :sup:`2`).

    Returns:
        :class:`numpy.ndarray`: an array of :math:`Q_{22}` values.


    Convert a gravitational-wave amplitude :math:`h_0` at Earth to an
    equivalent fiducial ellipticity :math:`\\varepsilon` of the pulsar
    using (see Equation A4 of [LVC]_):

    .. math::

        \\varepsilon = h_0 \\left(\\frac{c^4 d}{16\\pi^2 G f^2} \\right) \\sqrt{\\frac{15}{8\\pi}}

    Args:
        h0 (list, :class:`~numpy.ndarray`): a list of gravitational-wave
            amplitudes.
        frequency (list, :class:`~numpy.ndarray`): a list of frequencies (Hz).
        distance (list, :class:`~numpy.ndarray`): a list of distances (kpc).
        Izz (float): the moment of inertia of the principle axis (defaults to
            1e38 kg m\\ :sup:`2`).

    Returns:
        :class:`numpy.ndarray`: an array of :math:`Q_{22}` values.


    The pulsar death line. Returns the base-10 logarithm of the period
    derivative for the given values of the period.

    Args:
        logP (list, :class:`~numpy.ndarray`): the base-10 log values of period.
        linemodel (str): a string with one of the above model names. Defaults
            to ``'Ip'``.
        rho6 (float): the value of the :math:`\\rho_6` parameter from [ZHM]_ .
            Defaults to 1 is, which is equivalent to :math:`10^6` cm.

    Returns:
        :class:`numpy.ndarray`: a vector of period derivative values

    .. note::

        The death line models can be:

        * 'I' - Equation 3 of [ZHM]
        * 'Ip' - Equation 4 of [ZHM]
        * 'II' - Equation 5 of [ZHM]
        * 'IIp' - Equation 6 of [ZHM]
        * 'III' - Equation 8 of [ZHM]
        * 'IIIp' - Equation 9 of [ZHM]
        * 'IV' - Equation 10 of [ZHM]
        * 'IVp' - Equation 11 of [ZHM]

    .. [ZHM] Zhang, Harding & Muslimov, *ApJ*, **531**, L135-L138 (2000),
        `arXiv:astro-ph/0001341 <https://arxiv.org/abs/astro-ph/0001341>`_


    Add an annotation to the given line with appropriate placement and
    rotation.

    Based on code from `"How to rotate matplotlib annotation to match a line?"
    <http://stackoverflow.com/a/18800233/230468>`_ and `this
    <https://stackoverflow.com/a/38414616/1862861>`_ answer.

    Args:
        ax (:class:`matplotlib.axes.Axes`): Axes on which the label should be
            added.
        line (:class:`matplotlib.lines.Line2D`): Line which is being labeled.
        label (str): Text which should be drawn as the label.
        color (str): a color string for the label text. Defaults to ``'k'``
        fs (int): the font size for the label text. Defaults to 14.
        frachoffset (float): a number between 0 and 1 giving the fractional
            offset of the label text along the x-axis. Defaults to 0.1, i.e.,
            10%.
        zorder (float): The z-order for added the text.

    Returns:
        :class:`matplotlib.text.Text`: an object containing the label
        information


        This function takes a short format reference string from the ATNF
        Pulsar Catalogue and returns the full format reference. It can
        also return a NASA ADS URL if requested and present.

        Args:
            refs (str, array_like): a single short reference string, or
                an array of reference strings.
            useads (bool): Set whether or not to also return a NASA ADS
                reference URL if present.

        Returns:
            array_like: a single full reference string, or an array of full
            reference strings. If NASA ADS URLs are requested, each return
            value will be a tuple containing the reference string and URL.


Return the table column names.


        Update a column in the internal :class:`pandas.DataFrame` table using
        :meth:`pandas.DataFrame.update`. If the column does not exist, it will
        be added to the table.

        Args:
            column (:class:`pandas.Series`): a named column of values.
            name (str): the name of the column (required if `column` is not a
                :class:`pandas.Series`, or to overwrite the current column
                name)
            overwrite (bool): set whether to overwrite non-NA values or not if
               the column already exists. Defaults to False, so non-NA values
               will not be overwritten.


Set the parameter to sort on.


        Sort the generated catalogue :class:`~pandas.DataFrame` on a given
        attribute and in either ascending or descending order.

        Args:
            sort_attr (str): The parameter on which to perform the sorting of
                the query output. Defaults to 'JNAME'.
            sort_order (str): Set to 'asc' to sort the parameter values in
                ascending order, or 'desc' to sort in descending order.
                Defaults to ascending.
            inplace (bool): If True, and sorting the class' internal
                :class:`~pandas.DataFrame`, then the sorting will be done
                in place without returning a copy of the table, otherwise
                a sorted copy of the table will be returned.

        Returns:
            :class:`~pandas.DataFrame`: a table containing the sorted
            catalogue.


        Output the :class:`~psrqpy.search.QueryATNF` instance to a pickle file
        for future loading.

        Args:
            fname (str): the filename to output the pickle to


        Load a previously saved pickle of this class.

        Args:
            fname (str): the filename of the pickled object
            cleardfonly (bool): set to True to only clear the catalogue
                DataFrame from the current object, but leave other attributes
                intact.


        Returns:
            :class:`~numpy.ndarray`: the output table as an array.


Return the name(s) of particular pulsars asked for in the query.


        Set a list of names of pulsars to be returned by the query.

        Args:
            psrnames (str, list): a list of names, or a single name, of pulsars
                to be returned by the query.


Return the number of pulsars found in with query


Return a :class:`astropy.table.Table` based on the query.


        Return the full catalogue as a :class:`astropy.table.Table` without
        any query conditions applied.

        Note: in this returned table any references will not be converted into
        actual reference strings, but will still be the ATNF Pulsar Catalogue
        tags.


        Return True if the :class:`pandas.DataFrame` containing the catalogue
        is empty.


        Return an :class:`astropy.table.Table` from the query with new
        parameters or conditions if given.

        Args:
            query_params (str, list): a parameter, or list of parameters, to
                return from the query. If this is None then all parameters are
                returned.
            usecondition (bool, str): If True then the condition parsed to the
                :class:`psrqpy.QueryATNF`: class will be used when returning
                the table. If False no condition will be applied to the
                returned table. If a string is given then that will be the
                assumed condition string.
            usepsrs (bool, str): If True then the list of pulsars parsed to the
                :class:`psrqpy.QueryATNF`: class will be used when returning
                the table. If False then all pulsars in the catalogue will be
                returned. If a string, or list of strings, is given then that
                will be assumed to be a set of pulsar names to return.
            useseparation (bool): If True and a set of sky coordinates and
                radius around which to return pulsars was set in the
                :class:`psrqpy.QueryATNF`: class then only pulsars within the
                given radius of the sky position will be returned. Otherwise
                all pulsars will be returned.

        Returns:
            :class:`astropy.table.Table`: a table of the pulsar data returned
            by the query.


Return the string of logical conditions applied to the pulsars.


        Set the logical condition string to apply to queried pulsars.

        Args:
            expression (str): A string containing logical expressions to apply
                to queried pulsars.


Return a boolean stating whether errors are to be included.


        Set whether to include errors with queried pulsars.

        Args:
            inclerr (bool): Set to True to include errors.


        Return the boolean stating whether certain conditions should apply an
        exact match.


        Set whether to apply an exact match criterion for certain conditions.

        Args:
            match (bool): A boolean stating whether or not to apply an exact
                match.


Return the parameters required for the query.


        Set the parameters with which to query from the catalogue.

        Args:
            params (list, str): A list of parameter names to query from the
               catalogue.


        Return the entire stored :class:`~pandas.DataFrame` catalogue
        without any sorting or conditions applied.


Return the query table as a :class:`pandas.DataFrame`.


        Parse information in 'ASSOC', 'TYPE', and 'BINCOMP', as described in
        `<http://www.atnf.csiro.au/research/pulsar/psrcat/psrcat_help.html#psr_types>`_.


        Parse default string representing source associations, extracting (first) value
        and reference. Multiple values and references currently not supported.


        Parse default string representing source type, extracting (first) value
        and reference. Multiple values and references currently not supported.


        Parse default string representing source companion type, extracting (first) value
        and reference. Multiple values and references currently not supported.


Set the `DIST` and `DIST1` parameters using other values.


        Calculate equatorial coordinates if only ecliptic coordinates are
        given. Errors on ecliptical coordinates are converted into
        equavalent errors on equatorial coordinates using a different
        algorithm to that used in `psrcat`.


        Calculate the ecliptic coordinates, and proper motions, from the
        right ascension and declination if they are not already given.
        The ecliptic used here is the astropy's `BarycentricMeanEcliptic
        <http://docs.astropy.org/en/stable/api/astropy.coordinates.BarycentricMeanEcliptic.html>`_
        (note that this does not include nutation unlike the
        `BarycentricTrueEcliptic <http://docs.astropy.org/en/stable/api/astropy.coordinates.BarycentricTrueEcliptic.html>`_
        for which a bug fix was added in `astropy 3.2 <http://docs.astropy.org/en/v3.2.1/changelog.html#id12>`_),
        which may not exactly match that used in `psrcat`.


        Calculate the galactic longitude, latitude and position.

        .. note::
            The cartesian galactic coordinates returned by this function *do
            not* match those returned by the ATNF Pulsar Catalogue and the
            ``psrcat`` software. They are defined using the conventions in the
            :class:`astropy.coordinates.Galactocentric` class. This uses a
            Galactic centre distance of 8.3 kpc compared to 8.5 kpc in
            ``psrcat`` and rotated 90 degrees anticlockwise compared to
            ``psrcat``.

            The Galactic coordinate proper motions returned by this function
            *do not* match those returned by the ATNF Pulsar Catalogue and the
            ``psrcat`` software. The values returned here convert the observed
            proper motions in right ascension and declination (or elliptic
            longitude and latitude) into equivalent values in the Galactic
            coordinate system (via the :class:`astropy.coordinates.Galactic`
            class). However, the values returned by the ATNF Pulsar Catalogue
            and the ``psrcat`` software are in the Galactic cooridinate system,
            but additionally have the local solar system velocity and Galactic
            rotation of the pulsar removed from them as described in Section 3
            of `Harrison, Lyne & Anderson (1993) <https://ui.adsabs.harvard.edu/?#abs/1993MNRAS.261..113H>`_.


Calculate derived binary system parameters.


        Calculate the period from the frequency in cases where period is not
        given.


        Calculate the frequency from the period in cases where frequency is not
        given.


        Calculate the period derivative from the frequency derivative in cases
        where period derivative is not given.


        Calculate the frequency derivative from the period derivative in cases
        where frequency derivative is not given.


Calculate binary orbital period from orbital frequency.


        Calculate binary orbital period derivative from orbital frequency
        derivative.


Calculate orbital frequency from orbital period.


        Calculate the orbital frequency derivative from the binary orbital
        period derivative.


Calculate the intrinsic period derivative.


        Calculate the characteristic age in years (see
        :func:`~psrqpy.utils.characteristic_age`, with an assumed braking index
        of n=3).


        Calculate the characteristic age (in years), dervied from period and
        intrinsic period derivative.


        Calculate the surface magnetic field strength (see
        :func:`~psrqpy.utils.B_field`).


        Calculate the surface magnetic field strength, dervied from period and
        intrinsic period derivative.


        Calculate the limit on the gravitational-wave emission amplitude at
        Earth assuming all rotational kinetic energy is lost via
        gravitational-waves generated from an l=m=2 mass quadrupole (i.e., a
        braking index of n=5). This uses the intrinsic spin-down values rather
        than the observed spin-downs.


Calculate the magnetic field strength at the light cylinder.


Calculate the spin-down luminosity.


        Calculate the spin-down luminosity, dervied from period and intrinsic
        period derivative.


Calculate the spin-down luminosity flux at the Sun.


Calculate the total proper motion and error.


Calculate the transverse velocity.


        Calculate spectral index between 400 and 1400 MHz and radio
        flux at 400 and 1400 MHz.


        Parse a string of `conditions
        <http://www.atnf.csiro.au/research/pulsar/psrcat/psrcat_help.html#condition>`_,
        i.e., logical statements with which to apply to a catalogue query,
        e.g., ``condition = 'f0 > 2.5 && assoc(GC)'``, so that they are in the
        format required for the query URL.

        Args:
            psrtype (list, str): a list of strings, or single string, of
                conditions on the
                `type <http://www.atnf.csiro.au/research/pulsar/psrcat/psrcat_help.html#psr_types>`_
                of pulsars to return (logical AND will be used for any listed
                types)
            assoc (list, str): a list of strings, or single string, of
                conditions on the associations of pulsars to return (logical
                AND will be used for any listed associations)
            bincomp (list, str): a list of strings, or single string, of
                conditions on the
                `binary companion <http://www.atnf.csiro.au/research/pulsar/psrcat/psrcat_help.html?type=normal#bincomp_type>`_
                types of pulsars to return (logical AND will be used for any
                listed associations)
            exactmatch (bool): a boolean stating whether assciations and types
                given as the condition should be an exact match

        Returns:
            str: a string with the format required for use in
            :attr:`~psrqpy.config.QUERY_URL`


        The shape of the entire catalogue table as a tuple containing the
        number of rows and the number of columns.


        The number of rows in the entire catalogue, i.e. the number of pulsars
        it contains.


        The number of columns in the entire catalogue, i.e. the number of
        parameters it contains.


        The length of the entire catalogue, i.e., the number of pulsars it
        contains. This should be the same as ``catalogue_nrows``.


        Draw a lovely period vs period derivative diagram.

        Args:
            intrinsicpdot (bool): use the intrinsic period derivative corrected
                for the `Shklovskii effect <https://en.wikibooks.org/wiki/Pulsars_and_neutron_stars/Pulsar_properties#Pulse_period>`_
                rather than the observed value. Defaults to False.
            excludeGCs (bool): exclude globular cluster pulsars as their period
                derivatives can be contaminated by intra-cluster accelerations.
                Defaults to False.
            showtypes (list, str): a list of pulsar types to highlight with
                markers in the plot. These can contain any of the following:
                ``BINARY``, ``HE``, ``NRAD``, ``RRAT``, ``XINS``, ``AXP`` or
                ``SGR``, or ``ALL`` to show all types. Default to showing no
                types.
            showGCs (bool): show markers to denote the pulsars in globular
                clusters. Defaults to False.
            showSNRs (bool): show markers to denote the pulsars with supernova
                remnants associated with them. Defaults to False.
            markertypes (dict): a dictionary of marker styles and colors keyed
                to the pulsar types above
            deathline (bool): draw the pulsar death line. Defaults to True.
            deathmodel (str): the type of death line to draw based on the
                models in :func:`psrqpy.utils.death_line`. Defaults to
                ``'Ip'``.
            filldeath (bool): set whether to fill the pulsar graveyard under
                the death line. Defaults to True.
            filldeathtype (dict): a dictionary of keyword arguments for the
                fill style of the pulsar graveyard.
            showtau (bool): show lines for a selection of characteritic ages.
                Defaults to True, and shows lines for :math:`10^5` through to
                :math:`10^9` yrs with steps in powers of 10.
            brakingidx (int): a braking index to use for the calculation of the
                characteristic age lines. Defaults to 3 for magnetic dipole
                radiation.
            tau (list): a list of characteristic ages to show on the plot.
            showB (bool): show lines of constant magnetic field strength.
                Defaults to True, and shows lines for :math:`10^{10}` through
                to :math:`10^{14}` gauss with steps in powers of 10.
            Bfield (list): a list of magnetic field strengths to plot.
            periodlims (array_like): the [min, max] period limits to plot with
            pdotlims (array_like): the [min, max] pdot limits to plot with
            usecondition (bool): if True create the P-Pdot diagram only with
                pulsars that conform to the original query condition values.
                Defaults to True.
            usepsrs (bool): if True create the P-Pdot diagram only with pulsars
                specified in the original query. Defaults to True.
            rcparams (dict): a dictionary of :py:obj:`matplotlib.rcParams`
                setup parameters for the plot.

        Returns:
            :class:`matplotlib.figure.Figure`: the figure object


        Return the :math:`l=m=2` mass quadrupoles based on the spin-down limits
        for the pulsars in the catalogue using :func:`~psrqpy.utils.h0_to_q22`.

        Returns:
            :class:`astropy.table.Table`: a table containing ``PSRJ`` names and
                :math:`Q_{22}` values as a column called ``Q22``.


        Return the :math:`l=m=2` mass quadrupoles based on the spin-down limits
        for the pulsars in the catalogue using
        :func:`~psrqpy.utils.h0_to_ellipticity`.

        Returns:
            :class:`astropy.table.Table`: a table containing ``PSRJ`` names and
                :math:`\\varepsilon` values as a column called ``ELL``.


    Calculate the base-10 scale of the final significant figure for a given
    number.

    E.g. for a value of 12000.0 you would get 1000.0 as the scale of the final
    significant figure. Or, for 1.2345e-8 you would get 0.0001.


    Round the derived error to the same number of significant figures at the
    error produced by `psrcat` and used for the ATNF pulsar catalogue, noting
    that `psrcat` rounds error up. Return True if the derived error and
    equivalent ATNF are the same


Test whether a given compiler supports a given option


Like the deprecated scipy.misc.derivative, but using numpy.gradient


Integrate a snapshot in infile until tmax in Gyr, save to outfile


Quick function that returns l for a given apar


Smooth interpolation in time, following Dehnen (2000)


clear warning registry for all match modules


Returns Orbit at (x,vx,y=0) with given E


Returns the maximum v_x at this x and this
        energy: the zero-velocity curve


Compare the output of the orbit fit properly, ro and vo only implemented for radec


Get the rectangular forces in the transformed frame


Check for spherical symmetry by Monte Carlo integration of the
    spherical harmonic Y_lm over the sample, should be zero unless l=m=0


Check that the cumulative distribution of radii follows the
    cumulative mass profile (normalized such that total mass = 1)


Check that sigma_r(r) obtained from a sampling agrees with that coming
    from the Jeans equation
    Does this by logarithmically binning in r between rmin and rmax


Check that beta(r) obtained from a sampling agrees with the expected
    value
    Does this by logarithmically binning in r between rmin and rmax


Check that the density obtained from integrating over the DF agrees
    with the expected density


Check that the mean v_r(r) obtained from integrating over the DF agrees
    with the expected zero


Check that sigma_r(r) obtained from integrating over the DF agrees
    with that coming from the Jeans equation


Check that sigma_r(r) obtained from integrating over the DF agrees
    with that coming from the Jeans equation, using the general sphericaldf
    class' vmomentdensity


Check that beta(r) obtained from integrating over the DF agrees
    with the expected behavior


    NAME:
       vizier
    PURPOSE:
       download a catalog and its associated ReadMe from Vizier
    INPUT:
       cat - name of the catalog (e.g., 'III/272' for RAVE, or J/A+A/... for journal-specific catalogs)
       filePath - path of the file where you want to store the catalog (note: you need to keep the name of the file the same as the catalogname to be able to read the file with astropy.io.ascii)
       ReadMePath - path of the file where you want to store the ReadMe file
       catalogname= (catalog.dat) name of the catalog on the Vizier server
       readmename= (ReadMe) name of the ReadMe file on the Vizier server
    OUTPUT:
       (nothing, just downloads)
    HISTORY:
       2016-09-12 - Written - Bovy (UofT)


Stolen from Jo Bovy's gaia_tools package!


Ensure a a file exists and if not make the relevant path


        Evaluate the actions (jr,lz,jz)

        Parameters
        ----------
        *args : tuple
            Either:
            a) R,vR,vT,z,vz[,phi]:
                1) floats: phase-space value for single object (phi is optional) (each can be a Quantity)
                2) numpy.ndarray: [N] phase-space values for N objects (each can be a Quantity)
            b) Orbit instance: initial condition used if that's it, orbit(t) if there is a time given as well as the second argument
        **kwargs: dict, optional
            Keywords for actionAngleStaeckel.__call__ for off-the-grid evaluations

        Returns
        -------
        tuple
            (jr,lz,jz)

        Notes
        -----
        - 2012-11-29 - Written - Bovy (IAS)


        Evaluate the action jz

        Parameters
        ----------
        *args : tuple
            Either:
            a) R,vR,vT,z,vz[,phi]:
                1) floats: phase-space value for single object (phi is optional) (each can be a Quantity)
                2) numpy.ndarray: [N] phase-space values for N objects (each can be a Quantity)
            b) Orbit instance: initial condition used if that's it, orbit(t) if there is a time given as well as the second argument
        **kwargs: dict, optional
            Keywords for actionAngleStaeckel.__call__ for off-the-grid evaluations

        Returns
        -------
        float or numpy.ndarray
            jz

        Notes
        -----
        - 2012-07-30 - Written - Bovy (IAS@MPIA)


        Evaluate the action jr.

        Parameters
        ----------
        *args : tuple
            Either:
            a) R,vR,vT,z,vz[,phi]:
                1) floats: phase-space value for single object (phi is optional) (each can be a Quantity)
                2) numpy.ndarray: [N] phase-space values for N objects (each can be a Quantity)
            b) Orbit instance: initial condition used if that's it, orbit(t) if there is a time given as well as the second argument
        **kwargs: dict, optional
            Keywords for actionAngleStaeckel.__call__ for off-the-grid evaluations

        Returns
        -------
        float
               The action jr.

        Notes
        -----
        - 2012-07-30 - Written - Bovy (IAS@MPIA)


        Evaluate the eccentricity, maximum height above the plane, peri- and apocenter in the Staeckel approximation

        Parameters
        ----------
        *args : tuple
            Either:
            a) R,vR,vT,z,vz[,phi]:
                1) floats: phase-space value for single object (phi is optional) (each can be a Quantity)
                2) numpy.ndarray: [N] phase-space values for N objects (each can be a Quantity)
            b) Orbit instance: initial condition used if that's it, orbit(t) if there is a time given as well as the second argument

        Returns
        -------
        tuple
            (e,zmax,rperi,rap)
        Notes
        -----
        - 2017-12-15 - Written - Bovy (UofT)


        Calculate the velocity at u0.

        Parameters
        ----------
        E : float
            Energy.
        Lz : float
            Angular momentum.
        u0 : float
            u0.
        R : float
            Radius corresponding to u0, pi/2.
        retv2 : bool, optional
            If True, return v^2. Default is False.

        Returns
        -------
        float or numpy.ndarray
            Velocity or velocity squared if retv2 is True.

        Notes
        -----
        - 2012-11-29 - Written - Bovy (IAS).


        Calculate the minimum of the u potential.

        Parameters
        ----------
        E : float
            Energy.
        Lz : float
            Angular momentum.

        Returns
        -------
        float
            Minimum of the u potential.

        Notes
        -----
        - 2012-11-29 - Written - Bovy (IAS)


        Calculate the 'radial energy'

        Parameters
        ----------
        R : float
            Galactocentric cylindrical radius
        z : float
            vertical height
        vR : float
            Galactocentric radial velocity
        vz : float
            vertical velocity
        E : float
            energy
        Lz : float
            angular momentum
        sinh2u0 : float
            sinh^2 and u0
        u0 : float
            sinh^2 and u0

        Returns
        -------
        float
            radial energy

        Notes
        -----
        - 2012-11-29 - Written - Bovy (IAS).


        Calculate the 'vertical energy'

        Parameters
        ----------
        R : float
            Galactocentric cylindrical radius (can be Quantity)
        z : float
            height above the plane (can be Quantity)
        vR : float
            Galactocentric radial velocity (can be Quantity)
        vz : float
            Galactocentric vertical velocity (can be Quantity)
        E : float
            energy
        Lz : float
            angular momentum
        sinh2u0 : float
            sinh^2 and u0
        u0 : float
            sinh^2 and u0

        Returns
        -------
        float
            vertical energy

        Notes
        -----
        - 2012-12-23 - Written - Bovy (IAS)


The equation that needs to be minimized to find u0


        Evaluate the actions (jr,lz,jz).

        Parameters
        ----------
        *args : tuple
            Either:
            a) R,vR,vT,z,vz[,phi]:
                1) floats: phase-space value for single object (phi is optional) (each can be a Quantity)
                2) numpy.ndarray: [N] phase-space values for N objects (each can be a Quantity)
            b) Orbit instance: initial condition used if that's it, orbit(t) if there is a time given as well as the second argument
        delta: bool, optional
            can be used to override the object-wide focal length; can also be an array with length N to allow different delta for different phase-space points
        u0: float, optional
            if object-wide option useu0 is set, u0 to use (if useu0 and useu0 is None, a good value will be computed).
        c: bool, optional
            True/False to override the object-wide setting for whether or not to use the C implementation.
        order: int, optional
            number of points to use in the Gauss-Legendre numerical integration of the relevant action integrals.
        fixed_quad: bool, optional
            if True, use Gaussian quadrature (scipy.integrate.fixed_quad instead of scipy.integrate.quad).
        **kwargs: dict, optional
            scipy.integrate.fixed_quad or .quad keywords when not using C

        Returns
        -------
        tuple
            (jr,lz,jz)

        Notes
        -----
        - 2012-11-27 - Written - Bovy (IAS)
        - 2017-12-27 - Allowed individual delta for each point - Bovy (UofT)


        Evaluate the actions and frequencies (jr,lz,jz,Omegar,Omegaphi,Omegaz).

        Parameters
        ----------
        *args : tuple
            Either:
            a) R,vR,vT,z,vz[,phi]:
                1) floats: phase-space value for single object (phi is optional) (each can be a Quantity)
                2) numpy.ndarray: [N] phase-space values for N objects (each can be a Quantity)
            b) Orbit instance: initial condition used if that's it, orbit(t) if there is a time given as well as the second argument
        delta: bool, optional
            can be used to override the object-wide focal length; can also be an array with length N to allow different delta for different phase-space points
        u0: float, optional
            if object-wide option useu0 is set, u0 to use (if useu0 and useu0 is None, a good value will be computed).
        c: bool, optional
            True/False to override the object-wide setting for whether or not to use the C implementation.
        order: int, optional
            number of points to use in the Gauss-Legendre numerical integration of the relevant action integrals.
        fixed_quad: bool, optional
            if True, use Gaussian quadrature (scipy.integrate.fixed_quad instead of scipy.integrate.quad).
        **kwargs: dict, optional
            scipy.integrate.fixed_quad or .quad keywords when not using C

        Returns
        -------
        tuple
            (jr,lz,jz,Omegar,Omegaphi,Omegaz)

        Notes
        -----
        - 2013-08-28 - Written - Bovy (IAS)


        Evaluate the actions, frequencies, and angles (jr,lz,jz,Omegar,Omegaphi,Omegaz,angler,anglephi,anglez).

        Parameters
        ----------
        *args : tuple
            Either:
            a) R,vR,vT,z,vz[,phi]:
                1) floats: phase-space value for single object (phi is optional) (each can be a Quantity)
                2) numpy.ndarray: [N] phase-space values for N objects (each can be a Quantity)
            b) Orbit instance: initial condition used if that's it, orbit(t) if there is a time given as well as the second argument
        delta: bool, optional
            can be used to override the object-wide focal length; can also be an array with length N to allow different delta for different phase-space points
        u0: float, optional
            if object-wide option useu0 is set, u0 to use (if useu0 and useu0 is None, a good value will be computed).
        c: bool, optional
            True/False to override the object-wide setting for whether or not to use the C implementation.
        order: int, optional
            number of points to use in the Gauss-Legendre numerical integration of the relevant action integrals.
        fixed_quad: bool, optional
            if True, use Gaussian quadrature (scipy.integrate.fixed_quad instead of scipy.integrate.quad).
        **kwargs: dict, optional
            scipy.integrate.fixed_quad or .quad keywords when not using C

        Returns
        -------
        tuple
            (jr,lz,jz,Omegar,Omegaphi,Omegaz,angler,anglephi,anglez)

        Notes
        -----
        - 2013-08-28 - Written - Bovy (IAS)


        Evaluate the eccentricity, maximum height above the plane, peri- and apocenter in the Staeckel approximation.

        Parameters
        ----------
        *args : tuple
            Either:
            a) R,vR,vT,z,vz[,phi]:
                1) floats: phase-space value for single object (phi is optional) (each can be a Quantity)
                2) numpy.ndarray: [N] phase-space values for N objects (each can be a Quantity)
            b) Orbit instance: initial condition used if that's it, orbit(t) if there is a time given as well as the second argument
        delta: bool, optional
            can be used to override the object-wide focal length; can also be an array with length N to allow different delta for different phase-space points
        u0: float, optional
            if object-wide option useu0 is set, u0 to use (if useu0 and useu0 is None, a good value will be computed).
        c: bool, optional
            True/False to override the object-wide setting for whether or not to use the C implementation.

        Returns
        -------
        tuple
            (e,zmax,rperi,rap)

        Notes
        -----
        - 2017-12-12 - Written - Bovy (UofT)


        Evaluate u_min, u_max, and v_min in the Staeckel approximation.

        Parameters
        ----------
        *args : tuple
            Either:
            a) R,vR,vT,z,vz[,phi]:
                1) floats: phase-space value for single object (phi is optional) (each can be a Quantity)
                2) numpy.ndarray: [N] phase-space values for N objects (each can be a Quantity)
            b) Orbit instance: initial condition used if that's it, orbit(t) if there is a time given as well as the second argument
        delta: bool, optional
            can be used to override the object-wide focal length; can also be an array with length N to allow different delta for different phase-space points
        u0: float, optional
            if object-wide option useu0 is set, u0 to use (if useu0 and useu0 is None, a good value will be computed).
        c: bool, optional
            True/False to override the object-wide setting for whether or not to use the C implementation.

        Returns
        -------
        tuple
            (u_min, u_max, v_min)

        Notes
        -----
        - 2017-12-12 - Written - Bovy (UofT)


        Calculate the radial action

        Parameters
        ----------
        fixed_quad : bool, optional
            If True, use n=10 fixed_quad. Default is False.
        **kwargs
            scipy.integrate.quad keywords

        Returns
        -------
        float
            J_R(R,vT,vT)/ro/vc + estimate of the error (nan for fixed_quad)

        Notes
        -----
        - 2012-11-27 - Written - Bovy (IAS)


        Calculate the vertical action

        Parameters
        ----------
        fixed_quad : bool, optional
            If True, use n=10 fixed_quad. Default is False.
        **kwargs
            scipy.integrate.quad keywords

        Returns
        -------
        float
            J_z(R,vT,vT)/ro/vc + estimate of the error

        Notes
        -----
        - 2012-11-27 - Written - Bovy (IAS)


        Calculate the energy and angular momentum.

        Parameters
        ----------
        **kwargs : dict
            scipy.integrate.quadrature keywords

        Returns
        -------
        tuple
            A tuple containing the energy and angular momentum.

        Notes
        -----
        - 2012-11-27 - Written - Bovy (IAS)


        Calculate the u 'apocenter' and 'pericenter'

        Returns
        -------
        tuple
            (umin,umax)

        Notes
        -----
        - 2012-11-27 - Written - Bovy (IAS)


        Calculate the v 'pericenter'

        Returns
        -------
        float
            v_min(R,vT,vT)/vc + estimate of the error

        Notes
        -----
        - 2012-11-28 - Written - Bovy (IAS)


    Calculate the energy and angular momentum.

    Parameters
    ----------
    R : float
        Galactocentric radius (/ro).
    vR : float
        Radial part of the velocity (/vc).
    vT : float
        Azimuthal part of the velocity (/vc).
    z : float
        Vertical height (/ro).
    vz : float
        Vertical velocity (/vc).
    pot : Potential object
        galpy Potential object or list of such objects.
    vc : float, optional
        Circular velocity at ro (km/s). Default: 1.0.
    ro : float, optional
        Distance to the Galactic center (kpc). Default: 1.0.

    Returns
    -------
    tuple
        Tuple containing energy and angular momentum.

    Notes
    -----
    - 2012-11-30 - Written - Bovy (IAS)


    Return the potential.

    Parameters
    ----------
    u : float
        Confocal u.
    v : float
        Confocal v.
    pot : Potential object
        Potential.
    delta : float
        Focus.

    Returns
    -------
    float
        Potential at (u, v).

    Notes
    -----
    - 2012-11-29 - Written - Bovy (IAS)


    Return the radial force.

    Parameters
    ----------
    u : float
        Confocal u.
    v : float
        Confocal v.
    pot : Potential object
        Potential.
    delta : float
        Focus.

    Returns
    -------
    float
        Radial force.

    Notes
    -----
    - 2012-11-30 - Written - Bovy (IAS)


    Return the vertical force.

    Parameters
    ----------
    u : float
        Confocal u.
    v : float
        Confocal v.
    pot : Potential object
        Potential.
    delta : float
        Focus.

    Returns
    -------
    Ffloat
        Vertical force.

    Notes
    -----
    - 2012-11-30 - Written - Bovy (IAS)


The J_z integrand: p_v(v)/2/delta^2


    Find adequate start or end points to solve for umin and umax

    Parameters
    ----------
    u : float
        Current value of the coordinate to solve for (either umin or umax)
    E : float
        Energy
    Lz : float
        Angular momentum along z
    I3U : float
        Third isolating integral of motion
    delta : float
        Focus parameter of the confocal coordinate system
    u0 : float
        u coordinate of the center of the coordinate system
    sinh2u0 : float
        Hyperbolic sine of twice the u coordinate of the center of the coordinate system
    v0 : float
        v coordinate of the center of the coordinate system
    sin2v0 : float
        Sine of twice the v coordinate of the center of the coordinate system
    potu0v0 : float
        Potential at the center of the coordinate system
    pot : Potential object
        Instance of a galpy Potential object
    umax : bool, optional
        If True, solve for umax instead of umin (default is False)

    Returns
    -------
    float
        Adequate start or end point to solve for umin or umax

    Notes
    -----
    - 2012-11-30 - Written - Bovy (IAS)


    Find adequate start point to solve for vmin

    Parameters
    ----------
    v : float
        Velocity
    E : float
        Energy
    Lz : float
        Angular momentum along z-axis
    I3V : float
        Third isolating integral
    delta : float
        Staeckel delta parameter
    u0 : float
        Staeckel energy
    cosh2u0 : float
        Hyperbolic cosine squared of u0
    sinh2u0 : float
        Hyperbolic sine squared of u0
    potu0pi2 : float
        Potential at u0 times pi/2
    pot : Potential object
        galpy Potential object

    Returns
    -------
    float
        Adequate start point to solve for vmin

    Notes
    -----
    - 2012-11-28 - Written - Bovy (IAS)


    Estimate a good value for delta using eqn. (9) in Sanders (2012)

    Parameters
    ----------
    pot : Potential instance or list thereof
    R : float or numpy.ndarray
        coordinates
    z : float or numpy.ndarray
        coordinates
    no_median : bool, optional
        if True, and input is array, return all calculated values of delta (useful for quickly estimating delta for many phase space points)
    delta0 : float, optional
        value to return when delta<delta0 (because actionAngleStaeckel does not work with delta=0 exactly)

    Returns
    -------
    float or numpy.ndarray
        estimate of delta

    Notes
    -----
    - 2013-08-28 - Written - Bovy (IAS)
    - 2016-02-20 - Changed input order to allow physical conversions - Bovy (UofT)
    - 2022-09-14 - Deal with numerical issues with SCF/DiskSCFPotentials - Bovy (UofT)
    - 2022-09-15 - Add delta0 - Bovy (UofT)


        Evaluate the actions (jr,lz,jz).

        Parameters
        ----------
        *args : tuple
            Either:
            a) R,vR,vT,z,vz[,phi]:
                1) floats: phase-space value for single object (phi is optional) (each can be a Quantity)
                2) numpy.ndarray: [N] phase-space values for N objects (each can be a Quantity)
            b) Orbit instance: initial condition used if that's it, orbit(t) if there is a time given as well as the second argument
        **kwargs: dict, optional
            scipy.integrate.quadrature keywords (used when directly evaluating a point off the grid)

        Returns
        -------
        tuple
            (jr,lz,jz)

        Notes
        -----
        - 2012-07-27 - Written - Bovy (IAS@MPIA)


        Evaluate the action jz.

        Parameters
        ----------
        *args : tuple
            Either:
                a) R,vR,vT,z,vz
                b) Orbit instance: initial condition used if that's it, orbit(t)
                    if there is a time given as well
        **kwargs: dict
            scipy.integrate.quadrature keywords

        Returns
        -------
        float
            The action jz.

        Notes
        -----
        - 2012-07-30 - Written - Bovy (IAS@MPIA)


Internal function to check that the set of units for this object is consistent with that for the potential


Internal function to check that the set of units for this object is consistent with that for an input orbit


        Turn off automatic returning of outputs in physical units.

        Notes
        ------
        - 2017-06-05 - Written - Bovy (UofT)


        Turn on automatic returning of outputs in physical units.

        Parameters
        ----------
        ro : float or Quantity, optional
            Distance scale for translation into internal units (default from configuration file).
        vo : float or Quantity, optional
            Velocity scale for translation into internal units (default from configuration file).

        Notes
        -----
        - 2016-06-05 - Written - Bovy (UofT)
        - 2020-04-22 - Don't turn on a parameter when it is False - Bovy (UofT)


        Evaluate the actions and frequencies (jr,lz,jz,Omegar,Omegaphi,Omegaz)

        Parameters
        ----------
        *args : tuple
            Either:
            a) R,vR,vT,z,vz[,phi]:
                1) floats: phase-space value for single object (phi is optional) (each can be a Quantity)
                2) numpy.ndarray: [N] phase-space values for N objects (each can be a Quantity)
            b) Orbit instance: initial condition used if that's it, orbit(t) if there is a time given as well as the second argument
        **kwargs : dict
            Any other keyword arguments are passed to the _actionsFreqs method.

        Returns
        -------
        tuple
            (jr,lz,jz,Omegar,Omegaphi,Omegaz)

        Notes
        -----
        - 2014-01-03 - Written for top level - Bovy (IAS)


        Evaluate the actions, frequencies, and angles (jr,lz,jz,Omegar,Omegaphi,Omegaz,angler,anglephi,anglez)

        Parameters
        ----------
        *args : tuple
            Either:
            a) R,vR,vT,z,vz,phi:
                1) floats: phase-space value for single object (phi is optional) (each can be a Quantity)
                2) numpy.ndarray: [N] phase-space values for N objects (each can be a Quantity)
            b) Orbit instance: initial condition used if that's it, orbit(t) if there is a time given as well as the second argument
        **kwargs : dict
            Additional keyword arguments to be passed to _actionsFreqsAngles method.

        Returns
        -------
        tuple
            (jr,lz,jz,Omegar,Omegaphi,Omegaz,angler,anglephi,anglez)

        Notes
        -----
        - 2014-01-03 - Written for top level - Bovy (IAS)


        Evaluate the eccentricity, maximum height above the plane, peri- and apocenter.

        Parameters
        ----------
        *args : tuple
            Either:
            a) R,vR,vT,z,vz,phi:
                1) floats: phase-space value for single object (phi is optional) (each can be a Quantity)
                2) numpy.ndarray: [N] phase-space values for N objects (each can be a Quantity)
            b) Orbit instance: initial condition used if that's it, orbit(t) if there is a time given as well as the second argument
        **kwargs : dict
            A dictionary of keyword arguments.

        Returns
        -------
        tuple
            (eccentricity, maximum height above the plane, peri-, and apocenter)

        Notes
        -----
        - 2017-12-12 - Written - Bovy (UofT)


        Evaluate the action for the harmonic oscillator

        Parameters
        ----------
        Either:
            a) x,vx:
                1) floats: phase-space value for single object (each can be a Quantity)
                2) numpy.ndarray: [N] phase-space values for N objects (each can be a Quantity)

        Returns
        -------
        float or numpy.ndarray
            action

        Notes
        -----
        - 2018-04-08 - Written - Bovy (UofT)


        Evaluate the action and frequency for the harmonic oscillator

        Parameters
        ----------
        Either:
            a) x,vx:
                1) floats: phase-space value for single object (each can be a Quantity)
                2) numpy.ndarray: [N] phase-space values for N objects (each can be a Quantity)

        Returns
        -------
        tuple
            (action,frequency)

        Notes
        -----
        - 2018-04-08 - Written - Bovy (UofT)


        Evaluate the action, frequency, and angle for the harmonic oscillator

        Parameters
        ----------
        Either:
            a) x,vx:
                1) floats: phase-space value for single object (each can be a Quantity)
                2) numpy.ndarray: [N] phase-space values for N objects (each can be a Quantity)

        Returns
        -------
        tuple
            (action,frequency,angle)

        Notes
        -----
        - 2018-04-08 - Written - Bovy (UofT)


        Evaluate the actions (jr,lz,jz).

        Parameters
        ----------
        *args : tuple
            Either:
            a) R,vR,vT,z,vz[,phi]:
                1) floats: phase-space value for single object (phi is optional) (each can be a Quantity)
                2) numpy.ndarray: [N] phase-space values for N objects (each can be a Quantity)
            b) Orbit instance: initial condition used if that's it, orbit(t) if there is a time given as well as the second argument
        cumul: bool, optional
            if True, return the cumulative average actions (to look at convergence).

        Returns
        -------
        tuple
            (jr,lz,jz)

        Notes
        -----
        - 2013-09-10 - Written - Bovy (IAS).


        Evaluate the actions (jr,lz,jz) and frequencies (Or,Op,Oz).

        Parameters
        ----------
        *args : tuple
            Either:
            a) R,vR,vT,z,vz[,phi]:
                1) floats: phase-space value for single object (phi is optional) (each can be a Quantity)
                2) numpy.ndarray: [N] phase-space values for N objects (each can be a Quantity)
            b) Orbit instance: initial condition used if that's it, orbit(t) if there is a time given as well as the second argument
        maxn: int, optional
            Use a grid in vec(n) up to this n (zero-based). Default is the object-wide default.
        ts : float, optional
            if set, the phase-space points correspond to these times (IF NOT SET, WE ASSUME THAT ts IS THAT THAT IS ASSOCIATED WITH THIS OBJECT)
        _firstFlip : bool, optional
            if True and Orbits are given, the backward part of the orbit is integrated first and stored in the Orbit object

        Returns
        -------
        tuple
            (jr,lz,jz,Or,Op,Oz)

        Notes
        -----
        - 2013-09-10 - Written - Bovy (IAS).


        Evaluate the actions (jr,lz,jz), frequencies (Or,Op,Oz), and angles (angler,anglephi,anglez).

        Parameters
        ----------
        *args : tuple
            Either:
            a) R,vR,vT,z,vz[,phi]:
                1) floats: phase-space value for single object (phi is optional) (each can be a Quantity)
                2) numpy.ndarray: [N] phase-space values for N objects (each can be a Quantity)
            b) Orbit instance: initial condition used if that's it, orbit(t) if there is a time given as well as the second argument
        maxn: int, optional
            Use a grid in vec(n) up to this n (zero-based). Default is the object-wide default.
        ts : float, optional
            if set, the phase-space points correspond to these times (IF NOT SET, WE ASSUME THAT ts IS THAT THAT IS ASSOCIATED WITH THIS OBJECT)
        _firstFlip : bool, optional
            if True and Orbits are given, the backward part of the orbit is integrated first and stored in the Orbit object

        Returns
        -------
        tuple
            (jr,lz,jz,Or,Op,Oz,angler,anglephi,anglez)

        Notes
        -----
        - 2013-09-10 - Written - Bovy (IAS).


        Plot the angles vs. each other, to check whether the isochrone approximation is good.

        Parameters
        ----------
        *args : tuple
            Either:
            a) R,vR,vT,z,vz[,phi]:
                1) floats: phase-space value for single object (phi is optional) (each can be a Quantity)
                2) numpy.ndarray: [N] phase-space values for N objects (each can be a Quantity)
            b) Orbit instance: initial condition used if that's it, orbit(t) if there is a time given as well as the second argument
        type: {'araz','araphi','azaphi','jr','lz','jz'}, optional
            type of plot to make
        deperiod: bool, optional
            if True, de-period the angles.
        downsample: bool, optional
            if True, downsample what's plotted to 400 points.
        **kwargs: dict, optional
            Any other keyword argument supported by plot.bovy_plot (e.g., xrange=[xmin,xmax])

        Returns
        -------
        plot

        Notes
        -----
        - 2013-09-10 - Written - Bovy (IAS).


Helper function to parse the arguments to the __call__ and actionsFreqsAngles functions


    Estimate a good value for the scale of the isochrone potential by matching the slope of the rotation curve

    Parameters
    ----------
    pot : Potential or list thereof
        Potential or list of potentials to estimate the scale of the isochrone potential for
    R : float or Quantity
        Galactocentric radius.
    z : float or Quantity
        Vertical height.
    phi : float or Quantity, optional
        Azimuth (optional).

    Returns
    -------
    float or tuple
        If a single (R,z,[phi]) is given, a single value b is returned. If a list of (R,z,[phi]) is given, a tuple (bmin,bmedian,bmax) is returned.

    Notes
    -----
    - 2013-09-12 - Written - Bovy (IAS)
    - 2016-02-20 - Changed input order to allow physical conversions - Bovy (UofT)
    - 2016-06-28 - Added phi= keyword for non-axisymmetric potential - Bovy (UofT)


make an array of periodic angles increase linearly


        Evaluate the phase-space coordinates (x,v) for a number of angles on a single torus as well as the frequencies.

        Parameters
        ----------
        jr : float
            Radial action.
        jphi : float
            Azimuthal action.
        jz : float
            Vertical action.
        angler : numpy.ndarray
            Radial angle.
        anglephi : numpy.ndarray
            Azimuthal angle.
        anglez : arrnumpy.ndarrayay_like
            Vertical angle.
        tol : float, optional
            Goal for |dJ|/|J| along the torus. Default is object-wide value.

        Returns
        -------
        tuple
            A tuple containing the following elements:
            - A numpy array of shape (N, 6) containing the phase-space coordinates (R, vR, vT, z, vz, phi) for a number of angles on a single torus.
            - OmegaR : float
                The radial frequency.
            - Omegaphi : float
                The azimuthal frequency.
            - Omegaz : float
                The vertical frequency.
            - AutoFit error message : int
                If AutoFit exited with non-zero return status, a warning message is issued.

        Notes
        -----
        - 2015-08-07 - Written - Bovy (UofT)


        Return the frequencies corresponding to a torus

        Parameters
        ----------
        jr : float
            Radial action
        jphi : float
            Azimuthal action
        jz : float
            Vertical action
        tol : float, optional
            Goal for |dJ|/|J| along the torus (default is object-wide value)

        Returns
        -------
        tuple
            (OmegaR, Omegaphi, Omegaz)

        Notes
        -----
        - 2015-08-07 - Written - Bovy (UofT)


        Return the Hessian d Omega / d J and frequencies Omega corresponding to a torus

        Parameters
        ----------
        jr : float
            Radial action
        jphi : float
            Azimuthal action
        jz : float
            Vertical action
        tol : float, optional
            Goal for |dJ|/|J| along the torus. Default is object-wide value.
        dJ : float, optional
            Action difference when computing derivatives (Hessian or Jacobian). Default is object-wide value.
        nosym : bool, optional
            If True, don't explicitly symmetrize the Hessian (good to check errors). Default is False.

        Returns
        -------
        tuple
            Tuple containing:
            - dO/dJ
            - Omegar
            - Omegaphi
            - Omegaz
            - Autofit error message

        Notes
        -----
        - 2016-07-15 - Written - Bovy (UofT)


        Return [R,vR,vT,z,vz,phi], the Jacobian d [R,vR,vT,z,vz,phi] / d (J,angle), the Hessian dO/dJ, and frequencies Omega corresponding to a torus at multiple sets of angles

        Parameters
        ----------
        jr : float
            Radial action
        jphi : float
            Azimuthal action
        jz : float
            Vertical action
        angler : numpy.ndarray
            Radial angle
        anglephi : numpy.ndarray
            Azimuthal angle
        anglez : numpy.ndarray
            Vertical angle
        tol : float, optional
            Goal for |dJ|/|J| along the torus (default is object-wide value)
        dJ : float, optional
            Action difference when computing derivatives (Hessian or Jacobian) (default is object-wide value)
        nosym : bool, optional
            If True, don't explicitly symmetrize the Hessian (good to check errors) (default is False)

        Returns
        -------
        tuple
            Tuple containing:
            - ([R,vR,vT,z,vz,phi], [N,6] array
            - d[R,vR,vT,z,vz,phi]/d[J,angle], --> (N,6,6) array
            - dO/dJ, --> (3,3) array
            - Omegar,Omegaphi,Omegaz, [N] arrays
            - Autofit error message)

        Notes
        -----
        - 2016-07-19 - Written - Bovy (UofT)


    Compute configuration (x,v) and frequencies of a set of angles on a single torus

    Parameters
    ----------
    pot : Potential object or list thereof
    jr : float
        Radial action
    jphi : float
        Azimuthal action
    jz : float
        Vertical action
    angler : numpy.ndarray
        Radial angle
    anglephi : numpy.ndarray
        Azimuthal angle
    anglez : numpy.ndarray
        Vertical angle
    tol : float, optional
        Goal for |dJ|/|J| along the torus

    Returns
    -------
    tuple
        (R,vR,vT,z,vz,phi,Omegar,Omegaphi,Omegaz,flag)

    Notes
    -----
    - 2015-08-05/07 - Written - Bovy (UofT)


    Compute frequencies on a single torus

    Parameters
    ----------
    pot : Potential object or list thereof
    jr : float
        Radial action
    jphi : float
        Azimuthal action
    jz : float
        Vertical action
    tol : float, optional
        Goal for |dJ|/|J| along the torus

    Returns
    -------
    tuple
        (Omegar,Omegaphi,Omegaz,flag)

    Notes
    -----
    - 2015-08-05/07 - Written - Bovy (UofT)


    Compute dO/dJ on a single torus

    Parameters
    ----------
    pot : Potential object or list thereof
    jr : float
        Radial action
    jphi : float
        Azimuthal action
    jz : float
        Vertical action
    tol : float, optional
        Goal for |dJ|/|J| along the torus
    dJ : float, optional
        Action difference when computing derivatives (Hessian or Jacobian)

    Returns
    -------
    tuple
        (dO/dJ,Omegar,Omegaphi,Omegaz,flag)

    Notes
    -----
    - 2016-07-15 - Written - Bovy (UofT)


    Compute d(x,v)/d(J,theta) on a single torus, also compute dO/dJ and the frequencies

    Parameters
    ----------
    pot : Potential object or list thereof
    jr : float
        Radial action
    jphi : float
        Azimuthal action
    jz : float
        Vertical action
    angler : numpy.ndarray
        Radial angle
    anglephi : numpy.ndarray
        Azimuthal angle
    anglez : numpy.ndarray
        Vertical angle
    tol : float, optional
        Goal for |dJ|/|J| along the torus
    dJ : float, optional
        Action difference when computing derivatives (Hessian or Jacobian)

    Returns
    -------
    tuple
        (d[R,vR,vT,z,vz,phi]/d[J,theta],Omegar,Omegaphi,Omegaz,Autofit error message)

    Notes
    -----
    - 2016-07-19 - Written - Bovy (UofT)


        Evaluate the phase-space coordinates (x,v) for a number of angles on a single torus as well as the frequencies

        Parameters
        ----------
        jr : float
            Radial action.
        jphi : float
            Azimuthal action.
        jz : float
            Vertical action.
        angler : numpy.ndarray
            Radial angle.
        anglephi : numpy.ndarray
            Azimuthal angle.
        anglez : numpy.ndarray
            Vertical angle.

        Returns
        -------
        tuple
            A tuple containing the phase-space coordinates (R,vR,vT,z,vz,phi) and the frequencies (OmegaR,Omegaphi,Omegaz).

        Notes
        -----
        - 2017-11-15 - Written - Bovy (UofT)


        Return the frequencies corresponding to a torus

        Parameters
        ----------
        jr : float
            Radial action.
        jphi : float
            Azimuthal action.
        jz : float
            Vertical action.

        Returns
        -------
        tuple
            A tuple of three floats representing the frequencies (OmegaR, Omegaphi, Omegaz).

        Notes
        -----
        - 2017-11-15 - Written - Bovy (UofT)


        Evaluate the phase-space coordinates (x,v) for a number of angles on a single torus.

        Parameters
        ----------
        jr : float
            Radial action.
        jphi : float
            Azimuthal action.
        jz : float
            Vertical action.
        angler : numpy.ndarray
            Radial angle.
        anglephi : numpy.ndarray
            Azimuthal angle.
        anglez : numpy.ndarray
            Vertical angle.

        Returns
        -------
        numpy.ndarray
            Phase-space coordinates [R,vR,vT,z,vz,phi].

        Notes
        -----
        - 2017-11-14 - Written - Bovy (UofT).


        Evaluate the phase-space coordinates (x,v) for a number of angles on a single torus as well as the frequencies.

        Parameters
        ----------
        jr : float
            Radial action.
        jphi : float
            Azimuthal action.
        jz : float
            Vertical action.
        angler : numpy.ndarray
            Radial angle.
        anglephi : numpy.ndarray
            Azimuthal angle.
        anglez : numpy.ndarray
            Vertical angle.

        Returns
        -------
        tuple
            A tuple containing the phase-space coordinates (R, vR, vT, z, vz, phi), and the frequencies (OmegaR, Omegaphi, Omegaz).

        Notes
        -----
        - 2017-11-15 - Written - Bovy (UofT).


        Return the frequencies corresponding to a torus

        Parameters
        ----------
        jr : float
            Radial action
        jphi : float
            Azimuthal action
        jz : float
            Vertical action

        Returns
        -------
        tuple
            A tuple of three floats representing the frequencies (OmegaR, Omegaphi, Omegaz)

        Notes
        -----
        - 2017-11-15 - Written - Bovy (UofT).


    Use C to calculate actions using the Staeckel approximation

    Parameters
    ----------
    pot : Potential or list of such instances
        Potential
    delta : float
        Focal length of prolate spheroidal coordinates
    R : float
        Galactocentric radius
    vR : float
        Galactocentric radial velocity
    vT : float
        Galactocentric tangential velocity
    z : float
        Height
    vz : float
        Vertical velocity
    u0 : float, optional
        If set, u0 to use
    order : int, optional
        Order of Gauss-Legendre integration of the relevant integrals

    Returns
    -------
    tuple
        (jr,jz,err) where:
           * jr,jz : array, shape (len(R))
           * err - non-zero if error occurred

    Notes
    -----
    - 2012-12-01 - Written - Bovy (IAS)


    Use C to calculate u0 in the Staeckel approximation

    Parameters
    ----------
    E : numpy.ndarray
        Energy.
    Lz : numpy.ndarray
        Angular momentum.
    pot : Potential or list of such instances
        Potential or list of such instances.
    delta : numpy.ndarray
        Focal length of prolate spheroidal coordinates.

    Returns
    -------
    tuple
        (u0,err)
        u0 : array, shape (len(E))
        err - non-zero if error occurred

    Notes
    -----
    - 2012-12-03 - Written - Bovy (IAS)


    Use C to calculate actions and frequencies using the Staeckel approximation

    Parameters
    ----------
    pot : Potential or list of such instances
        Potential or list of such instances.
    delta : float
        Focal length of prolate spheroidal coordinates.
    R : float
        Galactocentric radius.
    vR : float
        Galactocentric radial velocity.
    vT : float
        Galactocentric tangential velocity.
    z : float
        Height.
    vz : float
        Vertical velocity.
    u0 : float, optional
        If set, u0 to use.
    order : int, optional
        Order of Gauss-Legendre integration of the relevant integrals.

    Returns
    -------
    tuple
        (jr,jz,Omegar,Omegaphi,Omegaz,err) where:
            * jr,jz,Omegar,Omegaphi,Omegaz : array, shape (len(R))
            * err - non-zero if error occurred

    Notes
    -----
    - 2012-12-01 - Written - Bovy (IAS)


    Use C to calculate actions, frequencies, and angles using the Staeckel approximation

    Parameters
    ----------
    pot : Potential or list of such instances
        Potential or list of such instances.
    delta : float
        Focal length of prolate spheroidal coordinates.
    R : float
        Galactocentric radius.
    vR : float
        Galactocentric radial velocity.
    vT : float
        Galactocentric tangential velocity.
    z : float
        Height.
    vz : float
        Vertical velocity.
    phi : float
        Azimuth.
    u0 : float, optional
        If set, u0 to use.
    order : int, optional
        Order of Gauss-Legendre integration of the relevant integrals.

    Returns
    -------
    tuple
        (jr,jz,Omegar,Omegaphi,Omegaz,Angler,Anglephi,Anglez,err) where:
            * jr,jz,Omegar,Omegaphi,Omegaz,Angler,Anglephi,Anglez : array, shape (len(R))
            * err - non-zero if error occurred

    Notes
    -----
    - 2013-08-27 - Written - Bovy (IAS)


    Use C to calculate umin, umax, and vmin using the Staeckel approximation

    Parameters
    ----------
    pot : Potential or list of such instances
        Potential or list of such instances.
    delta : float
        Focal length of prolate spheroidal coordinates.
    R : float
        Galactocentric radius.
    vR : float
        Galactocentric radial velocity.
    vT : float
        Galactocentric tangential velocity.
    z : float
        Height.
    vz : float
        Vertical velocity.
    u0 : float, optional
        If set, u0 to use.

    Returns
    -------
    tuple
        (umin,umax,vmin,err) where:
            * umin,umax,vmin : array, shape (len(R))
            * err - non-zero if error occurred

    Notes
    -----
    - 2017-12-12 - Written - Bovy (UofT)


    Use C to calculate actions using the adiabatic approximation

    Parameters
    ----------
    pot : Potential or list of such instances
        Gravitational potential to compute actions in
    gamma : float
        as in Lz -> Lz+gamma * J_z
    R : numpy.ndarray
        R coordinate.
    vR : numpy.ndarray
        vR coordinate.
    vT : numpy.ndarray
        vT coordinate.
    z : numpy.ndarray
        z coordinate.
    vz : numpy.ndarray
        vz coordinate.

    Returns
    -------
    tuple:
       (jr,jz,err) with radial, vertical action (numpy.ndarrays), and error (non-zero if error occurred)

    Notes
    -----
    - 2012-12-10 - Written - Bovy (IAS)


    Calculate planar (Rperi,Rap) and the maximum height Zmax using the adiabatic approximation (rap = sqrt(Rap^2+Zmax^2))

    Parameters
    ----------
    pot : Potential or list of such instances
        Gravitational potential to compute actions in
    gamma : float
        as in Lz -> Lz+gamma * J_z
    R : numpy.ndarray
        R coordinate.
    vR : numpy.ndarray
        vR coordinate.
    vT : numpy.ndarray
        vT coordinate.
    z : numpy.ndarray
        z coordinate.
    vz : numpy.ndarray
        vz coordinate.

    Returns
    -------
    tuple
        (Rperi,Rap,Zmax,err)
        Rperi,Rap,Zmax : numpy.ndarray, shape (len(R))
        err - non-zero if error occurred

    Notes
    -----
    - 2017-12-21 - Written - Bovy (UofT)


        Return the action for the given energy.

        Parameters
        ----------
        E : float
            Energy.

        Returns
        -------
        float
            Action.

        Notes
        -----
        - 2022-11-24 - Written - Bovy (UofT)


        Evaluate the phase-space coordinates (x,v) for a number of angles on a single torus

        Parameters
        ----------
        j : float
            Action
        angle : numpy.ndarray
            Angle
        Returns
        -------
        tuple
            Tuple containing the phase-space coordinates [x,vx]

        Notes
        -----
        - 2018-04-08 - Written - Bovy (UofT)


        Evaluate the phase-space coordinates (x,v) for a number of angles on a single torus as well as the frequency.

        Parameters
        ----------
        j : float
            Action.
        angle : numpy.ndarray
            Angle.

        Returns
        -------
        tuple
            (x,v,frequency)

        Notes
        -----
        - 2018-04-15 - Written - Bovy (UofT)


        Return the frequency corresponding to a torus

        Parameters
        ----------
        j : float
            Action.

        Returns
        -------
        float
            Frequency corresponding to a torus.

        Notes
        -----
        - 2018-04-08 - Written - Bovy (UofT)