    Compute the auxiliary angle in the harmonic-oscillator for a grid in x and E

    Parameters
    ----------
    xa : numpy.ndarray
        Position.
    E : float
        Energy.
    pot : Potential object
        The potential.
    omega : numpy.ndarray
        Harmonic-oscillator frequencies.
    ptcoeffs : numpy.ndarray
        Coefficients of the polynomial point transformation.
    ptderivcoeffs : numpy.ndarray
        Coefficients of the derivative of the polynomial point transformation.
    xmax : float
        Xmax of the true torus.
    ptxmax : float
        Xmax of the point-transformed torus.
    vsign : float, optional
        Sign of the velocity. Default is 1.0.

    Returns
    -------
    numpy.ndarray
        Auxiliary angles.

    Notes
    -----
    - 2018-04-13 - Written - Bovy (UofT)
    - 2018-11-19 - Added point transformation - Bovy (UofT)


    Compute the derivative of the auxiliary angle in the harmonic-oscillator for a grid in x and E at constant E

    Parameters
    ----------
    xa : numpy.ndarray
        Position.
    E : float
        Energy.
    pot : Potential object
        The potential.
    omega : numpy.ndarray
        Harmonic-oscillator frequencies.
    ptcoeffs : numpy.ndarray
        Coefficients of the polynomial point transformation.
    ptderivcoeffs : numpy.ndarray
        Coefficients of the derivative of the polynomial point transformation.
    ptderiv2coeffs : numpy.ndarray
        Coefficients of the second derivative of the polynomial point transformation.
    xmax : float
        Xmax of the true torus.
    ptxmax : float
        Xmax of the point-transformed torus.
    vsign : float, optional
        Sign of the velocity. Default is 1.0.

    Returns
    -------
    numpy.ndarray
        d auxiliary angles / d x (2D array)

    Notes
    -----
    - 2018-04-13 - Written - Bovy (UofT)
    - 2018-11-22 - Added point transformation - Bovy (UofT)


    Compute the auxiliary action in the harmonic-oscillator for a grid in x and E

    Parameters
    ----------
    xa : numpy.ndarray
        position
    E : numpy.ndarray
        Energy
    pot : Potential object
        the potential
    omega : numpy.ndarray
        harmonic-oscillator frequencies
    ptcoeffs : numpy.ndarray
        coefficients of the polynomial point transformation
    ptderivcoeffs : numpy.ndarray
        coefficients of the derivative of the polynomial point transformation
    xmax : float
        xmax of the true torus
    ptxmax : float
        xmax of the point-transformed torus

    Returns
    -------
    numpy.ndarray
        auxiliary actions

    Notes
    -----
    - 2018-04-14 - Written - Bovy (UofT)
    - 2018-11-22 - Added point transformation - Bovy (UofT)


    Compute the derivative of the auxiliary action in the harmonic-oscillator wrt the action for a grid in x and E

    Parameters
    ----------
    xa : numpy.ndarray
        position
    E : float
        Energy
    pot : galpy.potential.Potential
        the potential
    omega : numpy.ndarray
        harmonic-oscillator frequencies
    ptcoeffs : numpy.ndarray
        coefficients of the polynomial point transformation
    ptderivcoeffs : numpy.ndarray
        coefficients of the derivative of the polynomial point transformation
    ptderiv2coeffs : numpy.ndarray
        coefficients of the second derivative of the polynomial point transformation
    xmax : float
        xmax of the true torus
    ptxmax : float
        xmax of the point-transformed torus

    Returns
    -------
    numpy.ndarray
        d(auxiliary actions)/d(action)

    Notes
    -----
    - 2018-04-14 - Written - Bovy (UofT)
    - 2018-11-23 - Added point transformation - 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
        c: bool, optional
            True/False to override the object-wide setting for whether or not to use the C implementation
        _justjr, _justjz: bool, optional
            If True, only calculate the radial or vertical action (internal use)
        **kwargs : dict
            scipy.integrate.quadrature keywords

        Returns
        -------
        (jr,lz,jz)
            Actions (jr,lz,jz).

        Notes
        -----
        - 2012-07-26 - Written - Bovy (IAS@MPIA).


        Evaluate the eccentricity, maximum height above the plane, peri- and apocenter in the adiabatic 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
        c: bool, optional
            True/False to override the object-wide setting for whether or not to use the C implementation

        Returns
        -------
        (e,zmax,rperi,rap)
            Eccentricity, maximum height above the plane, peri- and apocenter.

        Notes
        -----
        - 2017-12-21 - 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

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

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


        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

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

        Notes
        -----
        - 2013-09-08 - 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

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

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


        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
        -------
        x_vx : list
            A list 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
            Tuple containing:
                - x (numpy.ndarray): x-coordinate.
                - vx (numpy.ndarray): Velocity in x-direction.
                - Omega (float): Frequency.

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


        Return the frequency corresponding to a torus

        Parameters
        ----------
        j : scalar
            action

        Returns
        -------
        Omega : float
            frequency

        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
        fixed_quad: bool, optional
            if True, use n=10 fixed_quad integration
        **kwargs: dict, optional
            scipy.integrate.quadrature or .fixed_quad keywords

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

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


        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
        fixed_quad: bool, optional
            if True, use n=10 fixed_quad integration
        **kwargs: dict, optional
            scipy.integrate.quadrature or .fixed_quad keywords

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

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


        Evaluate the actions, frequencies, and angles (jr,lz,jz,Omegar,Omegaphi,Omegaz,ar,aphi,az).

        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
        fixed_quad: bool, optional
            if True, use n=10 fixed_quad integration
        **kwargs: dict, optional
            scipy.integrate.quadrature or .fixed_quad keywords

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

        Notes
        -----
        - 2013-12-29 - Written - Bovy (IAS)


        Evaluate the eccentricity, maximum height above the plane, peri- and apocenter for a spherical potential.

        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-22 - Written - Bovy (UofT)


    Find adequate start or end points to solve for rap and rperi

    Parameters
    ----------
    R : float
        Galactocentric radius
    E : float
        energy
    L : float
        angular momentum
    pot : Potential object or list thereof
        Potential
    rap : bool, optional
        if True, find the rap end-point (default is False)
    startsign : float, optional
        set to -1 if the function is not positive (due to gamma in the modified adiabatic approximation) (default is 1.0)

    Returns
    -------
    float
        rstart or rend

    Notes
    -----
    - 2010-12-01 - Written - Bovy (NYU)


        Evaluate the action.

        Parameters
        ----------
        *args : tuple
            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-05-19 - Written based on re-write of existing code - Bovy (UofT)


        Evaluate the action and frequency.

        Parameters
        ----------
        *args : tuple
            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-05-19 - Written based on re-write of existing code - Bovy (UofT)


        Evaluate the action, frequency, and angle.

        Parameters
        ----------
        *args : tuple
            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-05-19 - Written based on re-write of existing code - Bovy (UofT)


        Calculate the maximum height

        Parameters
        ----------
        x : float
            Position
        vx : float
            Velocity
        E : float, optional
            Energy (default is None)

        Returns
        -------
        float
            Maximum height

        Notes
        -----
        - 2012-06-01 - Written - Bovy (IAS)
        - 2018-05-19 - Re-written for new framework - Bovy (UofT)


    N-body code using direct summation for force evaluation

    Parameters
    ----------
    q : list
        list of initial positions (numpy.ndarrays)
    p : list
        list of initial momenta (numpy.ndarrays)
    m : list
        list of masses
    t : list
        times at which output is desired
    pot : galpy.potential or list of galpy.potentials, optional
        external potential
    softening_model : str, optional
        type of softening to use ('plummer')
    softening_length : float, optional
        softening length

    Parameters
    ----------
    list
        list of [q,p] at times t

    Notes
    -----
    - 2011-02-03 - Written - Bovy (NYU).


One N-body step: drift-kick-drift


Calculate the force


        Plot the snapshot.

        Notes
        -----
        - 2011-08-15 - Started - Bovy (NYU)


    Turn a list of snapshots into a movie

    Parameters
    ----------
    snap : list
        The snapshots
    filename : str
        Name of the file to save the movie to
    framerate : int, optional
        Frames per second (default is 25)
    bitrate : int, optional
        Bitrate (default is 1000)
    thumbnail : bool, optional
        Create thumbnail image (filename-extension+.jpg) (default is False)
    thumbsize : int, optional
        Size of thumbnail (default is 300)
    *args
        Arguments for Snapshot.plot
    **kwargs
        Keyword arguments for Snapshot.plot

    Returns
    -------
    None

    Notes
    -----
    - 2011-02-06 - Written - Bovy (NYU)


        Integrate the snapshot in time.

        Parameters
        ----------
        t : numpy.ndarray
            Times to save the snapshots at (must start at 0).
        pot : object or list of objects, optional
            Potential object(s) (default=None).
        method : str, optional
            Method to use ('test-particle' or 'direct-python' for now).
        **kwargs
            Additional keyword arguments to pass to the integration method.

        Returns
        -------
        list
            List of snapshots at times t.

        Notes
        -----
        - 2011-02-02 - Written - Bovy (NYU)


Integrate the snapshot using a direct force summation method \
        written entirely in python


        Plot the snapshot (with reasonable defaults)

        Parameters
        ----------
        d1 : str, optional
            First dimension to plot ('x', 'y', 'R', 'vR', 'vT', 'z', 'vz', ...).
        d2 : str, optional
            Second dimension to plot.
        *args : tuple
            Matplotlib.plot inputs + galpy.util.plot.plot inputs.
        **kwargs : dict
            Matplotlib.plot inputs + galpy.util.plot.plot inputs.

        Returns
        -------
        None
            Sends plot to output device.

        Notes
        -----
        - 2011-02-06 - Written based on Orbit's plot


        Plot the snapshot in 3D (with reasonable defaults)

        Parameters
        ----------
        d1 : str, optional
            First dimension to plot ('x', 'y', 'R', 'vR', 'vT', 'z', 'vz', ...).
        d2 : str, optional
            Second dimension to plot.
        d3 : str, optional
            Third dimension to plot.
        *args
            Matplotlib.plot inputs+galpy.util.plot.plot3d inputs.
        **kwargs
            Matplotlib.plot inputs+galpy.util.plot.plot3d inputs.

        Returns
        -------
        None
            Sends plot to output device.

        Notes
        -----
        - 2011-02-06 - Written based on Orbit's plot3d


    Read a NEMO snapshot file consisting of mass, position, velocity.

    Parameters
    ----------
    filename : str
        Name of the file.
    ext : str, optional
        If set, 'nemo' for NEMO binary format, otherwise assumed ASCII; if not set, gleaned from extension.
    swapyz : bool, optional
        If True, swap the y and z axes in the output (only for position and velocity).

    Returns
    -------
    ndarray
        Array of shape (nbody, ndim, nt).

    Notes
    -----
    - 2015-11-18 - Written - Bovy (UofT).


    Decorator to transform angles from and to degrees if necessary

    Parameters
    ----------
    inDegrees : list
        List specifying indices of angle arguments (e.g., [0,1])
    outDegrees : list
        Same as inDegrees, but for function return

    Returns
    -------
    function
        Wrapped function

    Notes
    -----
    - ____-__-__ - Written - Bovy
    - 2019-03-02 - speedup - Nathaniel Starkman (UofT)


    Transform from equatorial coordinates to Galactic coordinates

    Parameters
    ----------
    ra : float or numpy.ndarray
        Right ascension
    dec : float or numpy.ndarray
        Declination
    degree : bool, optional
        If True, ra and dec are given in degree and l and b will be as well
    epoch : float, optional
        Epoch of ra,dec (right now only 2000.0 and 1950.0 are supported when not using astropy's transformations internally; when internally using astropy's coordinate transformations, epoch can be None for ICRS, 'JXXXX' for FK5, and 'BXXXX' for FK4)

    Returns
    -------
    tuple or numpy.ndarray
        Galactic longitude and latitude

    Notes
    -----
    - 2009-11-12 - Written - Bovy (NYU)
    - 2014-06-14 - Re-written w/ numpy functions for speed and w/ decorators for beauty - Bovy (IAS)
    - 2016-05-13 - Added support for using astropy's coordinate transformations and for non-standard epochs - Bovy (UofT)


    Transform from Galactic coordinates to equatorial coordinates

    Parameters
    ----------
    l : float or numpy.ndarray
        Galactic longitude
    b : float or numpy.ndarray
        Galactic latitude
    degree : bool, optional
        If True, l and b are given in degree and ra and dec will be as well
    epoch : float, optional
        Epoch of ra,dec (right now only 2000.0 and 1950.0 are supported when not using astropy's transformations internally; when internally using astropy's coordinate transformations, epoch can be None for ICRS, 'JXXXX' for FK5, and 'BXXXX' for FK4)

    Returns
    -------
    tuple or numpy.ndarray
        Right ascension and declination

    Notes
    -----
    - 2010-04-07 - Written - Bovy (NYU)
    - 2014-06-14 - Re-written w/ numpy functions for speed and w/ decorators for beauty - Bovy (IAS)
    - 2016-05-13 - Added support for using astropy's coordinate transformations and for non-standard epochs - Bovy (UofT)


    Transform from spherical Galactic coordinates to rectangular Galactic coordinates (works with vector inputs)

    Parameters
    ----------
    l : float or numpy.ndarray
        Galactic longitude (rad)
    b : float or numpy.ndarray
        Galactic latitude (rad)
    d : float or numpy.ndarray
        Distance (arbitrary units)
    degree : bool, optional
        If True, l and b are in degrees. Default is False.

    Returns
    -------
    tuple or numpy.ndarray
        [X,Y,Z] in whatever units d was in. For vector inputs [:,3]

    Notes
    -----
    - 2009-10-24 - Written - Bovy (NYU)
    - 2014-06-14 - Re-written w/ numpy functions for speed and w/ decorators for beauty - Bovy (IAS)


    Transform phase-space coordinates in rectangular Galactic coordinates to spherical Galactic coordinates (can take vector inputs)

    Parameters
    ----------
    X : float or numpy.ndarray
        Component towards the Galactic Center (kpc)
    Y : float or numpy.ndarray
        Component in the direction of Galactic rotation (kpc)
    Z : float or numpy.ndarray
        Component towards the North Galactic Pole (kpc)
    vx : float or numpy.ndarray
        Velocity towards the Galactic Center (km/s)
    vy : float or numpy.ndarray
        Velocity in the direction of Galactic rotation (km/s)
    vz : float or numpy.ndarray
        Velocity towards the North Galactic Pole (km/s)
    degree : bool, optional
        If True, return l and b in degrees. Default is False.

    Returns
    -------
    tuple or numpy.ndarray
        [l,b,d,vr,pmll x cos(b),pmbb] in (rad,rad,kpc,km/s,mas/yr,mas/yr). For vector inputs [:,6]

    Notes
    -----
    - 2009-10-25 - Written - Bovy (NYU)


    Transform phase-space coordinates in spherical Galactic coordinates to rectangular Galactic coordinates (can take vector inputs)

    Parameters
    ----------
    l : float or numpy.ndarray
        Galactic longitude
    b : float or numpy.ndarray
        Galactic latitude
    d : float or numpy.ndarray
        Distance (kpc)
    vr : float or numpy.ndarray
        Line-of-sight velocity (km/s)
    pmll : float or numpy.ndarray
        Proper motion in the Galactic longitude direction (mu_l * cos(b)) (mas/yr)
    pmbb : float or numpy.ndarray
        Proper motion in the Galactic latitude (mas/yr)
    degree : bool, optional
        If True, l and b are in degrees. Default is False.

    Returns
    -------
    tuple or numpy.ndarray
        [X,Y,Z,vx,vy,vz] in (kpc,kpc,kpc,km/s,km/s,km/s). For vector inputs [:,6]

    Notes
    -----
    - 2009-10-25 - Written - Bovy (NYU)


    Transform velocities in the spherical Galactic coordinate frame to the rectangular Galactic coordinate frame (can take vector inputs)

    Parameters
    ----------
    vr : float or numpy.ndarray
        Line-of-sight velocity (km/s)
    pmll : float or numpy.ndarray
        Proper motion in the Galactic longitude direction (mu_l * cos(b)) (mas/yr)
    pmbb : float or numpy.ndarray
        Proper motion in the Galactic latitude (mas/yr)
    l : float or numpy.ndarray
        Galactic longitude
    b : float or numpy.ndarray
        Galactic latitude
    d : float or numpy.ndarray
        Distance (kpc)
    XYZ : bool, optional
        If True, then l,b,d is actually X,Y,Z (rectangular Galactic coordinates). Default is False.
    degree : bool, optional
        If True, l and b are in degrees. Default is False.

    Returns
    -------
    tuple or numpy.ndarray
        [vx,vy,vz] in (km/s,km/s,km/s). For vector inputs [:,3]

    Notes
    -----
    - 2009-10-24 - Written - Bovy (NYU)
    - 2014-06-14 - Re-written w/ numpy functions for speed and w/ decorators for beauty - Bovy (IAS)


    Transform velocities in the rectangular Galactic coordinate frame to the spherical Galactic coordinate frame (can take vector inputs)

    Parameters
    ----------
    vx : float or numpy.ndarray
        Velocity towards the Galactic Center (km/s)
    vy : float or numpy.ndarray
        Velocity in the direction of Galactic rotation (km/s)
    vz : float or numpy.ndarray
        Velocity towards the North Galactic Pole (km/s)
    l : float or numpy.ndarray
        Galactic longitude
    b : float or numpy.ndarray
        Galactic latitude
    d : float or numpy.ndarray
        Distance (kpc)
    XYZ : bool, optional
        If True, then l,b,d is actually X,Y,Z (rectangular Galactic coordinates). Default is False.
    degree : bool, optional
        If True, l and b are in degrees. Default is False.

    Returns
    -------
    tuple or numpy.ndarray
        [vr,pmll x cos(b),pmbb] in (km/s,mas/yr,mas/yr). For vector inputs [:,3]

    Notes
    -----
    - 2009-10-24 - Written - Bovy (NYU)
    - 2014-06-14 - Re-written w/ numpy functions for speed and w/ decorators for beauty - Bovy (IAS)


    Transform from rectangular Galactic coordinates to spherical Galactic coordinates (works with vector inputs)

    Parameters
    ----------
    X : float or numpy.ndarray
        Component towards the Galactic Center (in kpc; though this obviously does not matter))
    Y : float or numpy.ndarray
        Component in the direction of Galactic rotation (in kpc)
    Z : float or numpy.ndarray
        Component towards the North Galactic Pole (kpc)
    degree : bool, optional
        If True, return l and b in degrees (default is False)

    Returns
    -------
    tuple or numpy.ndarray
        [l,b,d] in (rad or degree,rad or degree,kpc); for vector inputs [:,3]

    Notes
    -----
    - 2009-10-24 - Written - Bovy (NYU)
    - 2014-06-14 - Re-written w/ numpy functions for speed and w/ decorators for beauty - Bovy (IAS)


    Rotate proper motions in (ra,dec) into proper motions in (l,b)

    Parameters
    ----------
    pmra : float or numpy.ndarray
        Proper motion in ra (multiplied with cos(dec)) (mas/yr)
    pmdec : float or numpy.ndarray
        Proper motion in dec (mas/yr)
    ra : float or numpy.ndarray
        Right ascension
    dec : float or numpy.ndarray
        Declination
    degree : bool, optional
        If True, ra and dec are given in degrees (default=False)
    epoch : float, optional
        Epoch of ra,dec (right now only 2000.0 and 1950.0 are supported when not using astropy's transformations internally; when internally using astropy's coordinate transformations, epoch can be None for ICRS, 'JXXXX' for FK5, and 'BXXXX' for FK4)

    Returns
    -------
    tuple or numpy.ndarray
        [pmll x cos(b),pmbb] in (mas/yr,mas/yr). For vector inputs [:,2]

    Notes
    -----
    - 2010-04-07 - Written - Bovy (NYU)
    - 2014-06-14 - Re-written w/ numpy functions for speed and w/ decorators for beauty - Bovy (IAS)


    Rotate proper motions in (l,b) into proper motions in (ra,dec)

    Parameters
    ----------
    pmll : float or numpy.ndarray
        Proper motion in l (multiplied with cos(b)) (mas/yr)
    pmbb : float or numpy.ndarray
        Proper motion in b (mas/yr)
    l : float or numpy.ndarray
        Galactic longitude
    b : float or numpy.ndarray
        Galactic latitude
    degree : bool, optional
        If True, l and b are given in degrees (default=False)
    epoch : float, optional
        Epoch of ra,dec (right now only 2000.0 and 1950.0 are supported when not using astropy's transformations internally; when internally using astropy's coordinate transformations, epoch can be None for ICRS, 'JXXXX' for FK5, and 'BXXXX' for FK4)

    Returns
    -------
    tuple or numpy.ndarray
        [pmra x cos(dec),pmdec] in (mas/yr,mas/yr). For vector inputs [:,2]

    Notes
    -----
    - 2010-04-07 - Written - Bovy (NYU)
    - 2014-06-14 - Re-written w/ numpy functions for speed and w/ decorators for beauty - Bovy (IAS)


    Propagate the proper motions errors through the rotation from (ra,dec) to (l,b)

    Parameters
    ----------
    cov_pmradec : numpy.ndarray
        Uncertainty covariance matrix of the proper motion in ra (multiplied with cos(dec)) and dec [2,2] or [:,2,2]
    ra : float or numpy.ndarray
        Right ascension
    dec : float or numpy.ndarray
        Declination
    degree : bool, optional
        If True, ra and dec are given in degrees (default=False)
    epoch : float, optional
        Epoch of ra,dec (right now only 2000.0 and 1950.0 are supported when not using astropy's transformations internally; when internally using astropy's coordinate transformations, epoch can be None for ICRS, 'JXXXX' for FK5, and 'BXXXX' for FK4)

    Returns
    -------
    numpy.ndarray
        covar_pmllbb [2,2] or [:,2,2] [pmll here is pmll x cos(b)]

    Notes
    -----
    - 2010-04-12 - Written - Bovy (NYU)
    - 2020-09-21 - Adapted for array input - Mackereth (UofT)


    Propagate distance, radial velocity, and proper motion uncertainties to Galactic coordinates

    Parameters
    ----------
    d : float or numpy.ndarray
        Distance [kpc, as/mas for plx]
    e_d : float or numpy.ndarray
        Distance uncertainty [kpc, [as/mas] for plx]
    e_vr : float or numpy.ndarray
        Low velocity uncertainty [km/s]
    pmll : float or numpy.ndarray
        Proper motion in l (*cos(b)) [ [as/mas]/yr ]
    pmbb : float or numpy.ndarray
        Proper motion in b [ [as/mas]/yr ]
    cov_pmllbb : numpy.ndarray
        Uncertainty covariance for proper motion [pmll is pmll x cos(b)] [:,2,2]
    l : float or numpy.ndarray
        Galactic longitude
    b : float or numpy.ndarray
        Galactic latitude
    plx : bool, optional
        If True, d is a parallax, and e_d is a parallax uncertainty (default=False)
    degree : bool, optional
        If True, l and b are given in degree (default=False)

    Returns
    -------
    numpy.ndarray
        cov(vx,vy,vz) [3,3] or [:,3,3]

    Notes
    -----
    - 2010-04-12 - Written - Bovy (NYU)
    - 2020-09-21 - Adapted for array input - Mackereth (UofT)


    Propagate uncertainties in vxyz to galactocentric cylindrical coordinates

    Parameters
    ----------
    cov_vxyz : numpy.ndarray
        Uncertainty covariance in U,V,W [3,3] or [:,3,3]
    phi : float or numpy.ndarray
        Angular position of star in Galactocentric cylindrical coords [rad]
    Xsun : float, optional
        Cylindrical distance to the GC (can be array of same length as R) [kpc]
    Zsun : float, optional
        Sun's height above the midplane (can be array of same length as R) [kpc]

    Returns
    -------
    numpy.ndarray
        cov(vR,vT,vz) [3,3] or [:,3,3]

    Notes
    -----
    - 2018-03-22 - Written - Mackereth (LJMU)
    - 2020-09-21- Moved to coords.py - Mackereth (UofT)


    Propagate uncertainties in vxyz to galactocentric rectangular coordinates

    Parameters
    ----------
    cov_vxyz : numpy.ndarray
        Uncertainty covariance in U,V,W [3,3] or [:,3,3]
    Xsun : float, optional
        Cylindrical distance to the GC (can be array of same length as R) [kpc]
    Zsun : float, optional
        Sun's height above the midplane (can be array of same length as R) [kpc]

    Returns
    -------
    numpy.ndarray
        cov(vx,vy,vz) [3,3] or [:,3,3]

    Notes
    -----
    - 2018-03-22 - Written - Mackereth (LJMU)
    - 2020-09-21- Moved to coords.py - Mackereth (UofT)


    Propagate uncertainties in galactocentric rectangular to galactocentric cylindrical coordinates

    Parameters
    ----------
    cov_galcenrect : numpy.ndarray
        Uncertainty covariance in vx,vy,vz [3,3] or [:,3,3]
    phi : float or numpy.ndarray
        Angular position of star in Galactocentric cylindrical coords [rad]

    Returns
    -------
    numpy.ndarray
        cov(vR,vT,vz) [3,3] or [:,3,3]

    Notes
    -----
    - 2018-03-22 - Written - Mackereth (LJMU)
    - 2020-09-21- Moved to coords.py - Mackereth (UofT)


    Transform XYZ coordinates (wrt Sun) to rectangular Galactocentric coordinates.

    Parameters
    ----------
    X : float or numpy.ndarray
        X coordinate.
    Y : float or numpy.ndarray
        Y coordinate.
    Z : float or numpy.ndarray
        Z coordinate.
    Xsun : float or numpy.ndarray, optional
        Cylindrical distance to the Galactic center (default is 1.0).
    Zsun : float or numpy.ndarray, optional
        Sun's height above the midplane (default is 0.0).
    _extra_rot : bool, optional
        If True, perform an extra tiny rotation to align the Galactocentric coordinate frame with astropy's definition (default is True).

    Returns
    -------
    numpy.ndarray
        Containing:
            * Xg : X coordinate in Galactocentric frame.
            * Yg : Y coordinate in Galactocentric frame.
            * Zg : Z coordinate in Galactocentric frame.

    Notes
    -----
    - 2010-09-24 - Written - Bovy (NYU)
    - 2016-05-12 - Edited to properly take into account the Sun's vertical position; dropped Ysun keyword - Bovy (UofT)
    - 2018-04-18 - Tweaked to be consistent with astropy's Galactocentric frame - Bovy (UofT)
    - 2023-07-23 - Allowed Xsun/Zsun to be arrays - Bovy (UofT)


    Transform rectangular Galactocentric to XYZ coordinates (wrt Sun) coordinates.

    Parameters
    ----------
    X : float or numpy.ndarray
        Galactocentric rectangular coordinate.
    Y : float or numpy.ndarray
        Galactocentric rectangular coordinate.
    Z : float or numpy.ndarray
        Galactocentric rectangular coordinate.
    Xsun : float or numpy.ndarray, optional
        Cylindrical distance to the GC (can be array of same length as X).
    Zsun : float or numpy.ndarray, optional
        Sun's height above the midplane (can be array of same length as X).
    _extra_rot : bool, optional
        If True, perform an extra tiny rotation to align the Galactocentric coordinate frame with astropy's definition.

    Returns
    -------
    numpy.ndarray
        Containing (X,Y,Z)

    Notes
    -----
    - 2011-02-23 - Written - Bovy (NYU)
    - 2016-05-12 - Edited to properly take into account the Sun's vertical position; dropped Ysun keyword - Bovy (UofT)
    - 2017-10-24 - Allowed Xsun/Zsun to be arrays - Bovy (UofT)
    - 2018-04-18 - Tweaked to be consistent with astropy's Galactocentric frame - Bovy (UofT)


    Convert from rectangular to cylindrical coordinates

    Parameters
    ----------
    X : float or numpy.ndarray
        X coordinate.
    Y : float or numpy.ndarray
        Y coordinate.
    Z : float or numpy.ndarray
        Z coordinate.

    Returns
    -------
    numpy.ndarray
        Containing (R,phi,z)

    Notes
    -----
    - 2010-09-24 - Written - Bovy (NYU)
    - 2019-06-21 - Changed such that phi in [-pi,pi] - Bovy (UofT)


    Convert from cylindrical to rectangular coordinates

    Parameters
    ----------
    R : float or numpy.ndarray
        Cylindrical R coordinate.
    phi : float or numpy.ndarray
        Cylindrical phi coordinate.
    Z : float or numpy.ndarray
        Cylindrical Z coordinate.

    Returns
    -------
    numpy.ndarray
        Containing (X,Y,Z)

    Notes
    -----
    - 2011-02-23 - Written - Bovy (NYU)


    Convert from cylindrical to spherical coordinates

    Parameters
    ----------
    R : float or numpy.ndarray
        Cylindrical R coordinate.
    Z : float or numpy.ndarray
        Cylindrical Z coordinate.
    phi : float or numpy.ndarray
        Cylindrical phi coordinate.

    Returns
    -------
    numpy.ndarray
        Containing (r,theta,phi)

    Notes
    -----
    - 2016-05-16 - Written - Aladdin


    Convert from spherical to cylindrical coordinates

    Parameters
    ----------
    r : float or numpy.ndarray
        Spherical r coordinate.
    theta : float or numpy.ndarray
        Spherical theta coordinate.
    phi : float or numpy.ndarray
        Spherical phi coordinate.

    Returns
    -------
    numpy.ndarray
        Containing (R,z,phi)

    Notes
    -----
    - 2016-05-20 - Written - Aladdin


    Transform XYZ coordinates (wrt Sun) to cylindrical Galactocentric coordinates

    Parameters
    ----------
    X : float or numpy.ndarray
        X coordinate.
    Y : float or numpy.ndarray
        Y coordinate.
    Z : float or numpy.ndarray
        Z coordinate.
    Xsun : float or numpy.ndarray, optional
        Cylindrical distance to the GC (can be array of same length as R).
    Zsun : float or numpy.ndarray, optional
        Sun's height above the midplane (can be array of same length as R).
    _extra_rot : bool, optional
        If True, perform an extra tiny rotation to align the Galactocentric coordinate frame with astropy's definition.

    Returns
    -------
    numpy.ndarray
        Containing (R,phi,z)

    Notes
    -----
    - 2010-09-24 - Written - Bovy (NYU)
    - 2023-07-19 - Allowed Xsun/Zsun to be arrays - Bovy (UofT)


    Transform cylindrical Galactocentric coordinates to XYZ coordinates (wrt Sun)

    Parameters
    ----------
    R : float or numpy.ndarray
        Cylindrical R coordinate.
    phi : float or numpy.ndarray
        Cylindrical phi coordinate.
    Z : float or numpy.ndarray
        Cylindrical Z coordinate.
    Xsun : float or numpy.ndarray, optional
        Cylindrical distance to the GC (can be array of same length as R).
    Zsun : float or numpy.ndarray, optional
        Sun's height above the midplane (can be array of same length as R).
    _extra_rot : bool, optional
        If True, perform an extra tiny rotation to align the Galactocentric coordinate frame with astropy's definition.

    Returns
    -------
    numpy.ndarray
        Containing (X,Y,Z)

    Notes
    -----
    - 2011-02-23 - Written - Bovy (NYU)
    - 2017-10-24 - Allowed Xsun/Zsun to be arrays - Bovy (UofT)


    Transform velocities in XYZ coordinates (wrt Sun) to rectangular Galactocentric coordinates for velocities

    Parameters
    ----------
    vx : float or numpy.ndarray
        U velocity.
    vy : float or numpy.ndarray
        V velocity.
    vz : float or numpy.ndarray
        W velocity.
    vsun : float or numpy.ndarray, optional
        Velocity of the Sun in the GC frame (can also be array of same length as vx; shape [3,N]).
    Xsun : float or numpy.ndarray, optional
        Cylindrical distance to the GC (can be array of same length as vXg).
    Zsun : float or numpy.ndarray, optional
        Sun's height above the midplane (can be array of same length as vXg).
    _extra_rot : bool, optional
        If True, perform an extra tiny rotation to align the Galactocentric coordinate frame with astropy's definition.

    Returns
    -------
    numpy.ndarray
        Containing (vx,vy,vz)

    Notes
    -----
    - 2010-09-24 - Written - Bovy (NYU)
    - 2016-05-12 - Edited to properly take into account the Sun's vertical position; dropped Ysun keyword - Bovy (UofT)
    - 2018-04-18 - Tweaked to be consistent with astropy's Galactocentric frame - Bovy (UofT)
    - 2023-07-23 - Allowed Xsun/Zsun/vsun to be arrays- Bovy (UofT)


    Transform velocities in XYZ coordinates (wrt Sun) to cylindrical Galactocentric coordinates for velocities

    Parameters
    ----------
    vx : float or numpy.ndarray
        U velocity.
    vy : float or numpy.ndarray
        V velocity.
    vz : float or numpy.ndarray
        W velocity.
    X : float or numpy.ndarray
        X in Galactocentric rectangular coordinates.
    Y : float or numpy.ndarray
        Y in Galactocentric rectangular coordinates.
    Z : float or numpy.ndarray
        Z in Galactocentric rectangular coordinates.
    vsun : float or numpy.ndarray, optional
        Velocity of the Sun in the GC frame (can also be array of same length as vx; shape [3,N]).
    Xsun : float or numpy.ndarray, optional
        Cylindrical distance to the GC (can be array of same length as vXg).
    Zsun : float or numpy.ndarray, optional
        Sun's height above the midplane (can be array of same length as vXg).
    galcen : bool, optional
        If True, then X,Y,Z are in cylindrical Galactocentric coordinates rather than rectangular coordinates.
    _extra_rot : bool, optional
        If True, perform an extra tiny rotation to align the Galactocentric coordinate frame with astropy's definition.

    Returns
    -------
    numpy.ndarray
        Containing (vR,vT,vz)

    Notes
    -----
    - 2010-09-24 - Written - Bovy (NYU)
    - 2023-07-19 - Allowed Xsun/Zsun/vsun to be arrays- Bovy (UofT)


    Transform rectangular Galactocentric coordinates to XYZ coordinates (wrt Sun) for velocities

    Parameters
    ----------
    vXg : float or numpy.ndarray
        Galactocentric x-velocity.
    vYg : float or numpy.ndarray
        Galactocentric y-velocity.
    vZg : float or numpy.ndarray
        Galactocentric z-velocity.
    vsun : float or numpy.ndarray, optional
        Velocity of the Sun in the GC frame (can also be array of same length as vXg; shape [3,N]).
    Xsun : float or numpy.ndarray, optional
        Cylindrical distance to the GC (can be array of same length as vXg).
    Zsun : float or numpy.ndarray, optional
        Sun's height above the midplane (can be array of same length as vXg).
    _extra_rot : bool, optional
        If True, perform an extra tiny rotation to align the Galactocentric coordinate frame with astropy's definition.

    Returns
    -------
    numpy.ndarray
        Containing (vx,vy,vz)

    Notes
    -----
    - 2011-02-24 - Written - Bovy (NYU)
    - 2016-05-12 - Edited to properly take into account the Sun's vertical position; dropped Ysun keyword - Bovy (UofT)
    - 2017-10-24 - Allowed Xsun/Zsun/vsun to be arrays - Bovy (UofT)
    - 2018-04-18 - Tweaked to be consistent with astropy's Galactocentric frame - Bovy (UofT)


    Transform cylindrical Galactocentric coordinates to XYZ coordinates (wrt Sun) for velocities

    Parameters
    ----------
    vR : float or numpy.ndarray
        Galactocentric radial velocity.
    vT : float or numpy.ndarray
        Galactocentric rotational velocity.
    vZ : float or numpy.ndarray
        Galactocentric vertical velocity.
    phi : float or numpy.ndarray
        Galactocentric azimuth.
    vsun : float or numpy.ndarray, optional
        Velocity of the Sun in the GC frame (can also be array of same length as vR; shape [3,N]).
    Xsun : float or numpy.ndarray, optional
        Cylindrical distance to the GC (can be array of same length as vR).
    Zsun : float or numpy.ndarray, optional
        Sun's height above the midplane (can be array of same length as vR).
    _extra_rot : bool, optional
        If True, perform an extra tiny rotation to align the Galactocentric coordinate frame with astropy's definition.

    Parameters
    ----------
    numpy.ndarray
        Containing (vx,vy,vz)

    Notes
    -----
    - 2011-02-24 - Written - Bovy (NYU)
    - 2017-10-24 - Allowed vsun/Xsun/Zsun to be arrays - Bovy (NYU)


    Transform vectors from cylindrical to spherical coordinates. vtheta is positive from pole towards equator.

    Parameters
    ----------
    vR : float or numpy.ndarray
        Galactocentric cylindrical radial velocity
    vT : float or numpy.ndarray
        Galactocentric cylindrical rotational velocity
    vz : float or numpy.ndarray
        Galactocentric cylindrical vertical velocity
    R : float or numpy.ndarray
        Galactocentric cylindrical radius
    z : float or numpy.ndarray
        Galactocentric cylindrical height

    Returns
    -------
    tuple
        Containing:
            * vr : Galactocentric spherical radial velocity
            * vT : Galactocentric spherical rotational velocity
            * vtheta : Galactocentric spherical polar velocity

    Notes
    -----
    - 2020-07-01 - Written - James Lane (UofT)


    Transform vectors from spherical polar to cylindrical coordinates.

    Parameters
    ----------
    vr : float or numpy.ndarray
        Galactocentric spherical radial velocity
    vT : float or numpy.ndarray
        Galactocentric spherical azimuthal velocity
    vtheta : float or numpy.ndarray
        Galactocentric spherical polar velocity
    theta : float or numpy.ndarray
        Galactocentric spherical polar angle

    Returns
    -------
    tuple
        A tuple containing the Galactocentric cylindrical radial velocity, azimuthal velocity, and vertical velocity in that order.

    Notes
    -----
    - 2020-07-01 - Written - James Lane (UofT)


    Transform vectors from rectangular to cylindrical coordinates vectors.

    Parameters
    ----------
    vx : float or numpy.ndarray
        Velocity in the x-direction.
    vy : float or numpy.ndarray
        Velocity in the y-direction.
    vz : float or numpy.ndarray
        Velocity in the z-direction.
    X : float or numpy.ndarray
        X-coordinate.
    Y : float or numpy.ndarray
        Y-coordinate.
    Z : float or numpy.ndarray
        Z-coordinate.
    cyl : bool, optional
        If True, X, Y, Z are already cylindrical (i.e., [X,Y,Z] == [R,phi,Z]), by default False.

    Returns
    -------
    tuple
        Tuple containing vR, vT, vz.

    Notes
    -----
    - 2010-09-24 - Written - Bovy (NYU)


    Transform vectors from cylindrical to rectangular coordinate vectors.

    Parameters
    ----------
    vr : float or numpy.ndarray
        Radial velocity.
    vt : float or numpy.ndarray
        Rotational velocity.
    vz : float or numpy.ndarray
        Vertical velocity.
    phi : float or numpy.ndarray
        Azimuth.

    Returns
    -------
    tuple
        Rectangular coordinate vectors (vx, vy, vz).

    Notes
    -----
    - 2011-02-24 - Written - Bovy (NYU)


    Calculate the Jacobian of the cylindrical to rectangular conversion

    Parameters
    ----------
    R : float or numpy.ndarray
        Cylindrical R coordinate.
    phi : float or numpy.ndarray
        Cylindrical phi coordinate.
    Z : float or numpy.ndarray
        Cylindrical Z coordinate.
    vR : float or numpy.ndarray, optional
        Cylindrical vR coordinate.
    vT : float or numpy.ndarray, optional
        Cylindrical vT coordinate.
    vz : float or numpy.ndarray, optional
        Cylindrical vz coordinate.

    Returns
    -------
    numpy.ndarray
        Jacobian of the cylindrical to rectangular conversion either just spatial or spatial+velocity.

    Notes
    -----
    - 2013-12-09 - Written - Bovy (IAS)


    Calculate the Jacobian of the Galactocentric rectangular to Galactic coordinates

    Parameters
    ----------
    X : float or numpy.ndarray
        Galactocentric rectangular coordinate.
    Y : float or numpy.ndarray
        Galactocentric rectangular coordinate.
    Z : float or numpy.ndarray
        Galactocentric rectangular coordinate.
    vX : float or numpy.ndarray, optional
        Galactocentric rectangular velocity.
    vY : float or numpy.ndarray, optional
        Galactocentric rectangular velocity.
    vZ : float or numpy.ndarray, optional
        Galactocentric rectangular velocity.
    Xsun : float or numpy.ndarray, optional
        Cylindrical distance to the GC (can be array of same length as X).
    Zsun : float or numpy.ndarray, optional
        Sun's height above the midplane (can be array of same length as X).

    Returns
    -------
    numpy.ndarray
        Jacobian of the Galactocentric rectangular to Galactic coordinates either just spatial or spatial+velocity.

    Notes
    -----
    - 2013-12-09 - Written - Bovy (IAS)


    Calculate the Jacobian of the Galactic spherical coordinates to Galactic rectangular coordinates transformation

    Parameters
    ----------
    l : float or numpy.ndarray
        Galactic longitude.
    b : float or numpy.ndarray
        Galactic latitude.
    D : float or numpy.ndarray
        Distance.
    vlos : float or numpy.ndarray, optional
        Line-of-sight velocity.
    pmll : float or numpy.ndarray, optional
        Proper motion in Galactic longitude.
    pmbb : float or numpy.ndarray, optional
        Proper motion in Galactic latitude.
    degree : bool, optional
        If True, l and b are in degrees rather than rad.

    Returns
    -------
    numpy.ndarray
        Jacobian of the Galactic spherical coordinates to Galactic rectangular coordinates transformation either just spatial or spatial+velocity.

    Notes
    -----
    - 2013-12-09 - Written - Bovy (IAS)


    Convert Galactic longitude and distance to Galactocentric radius and azimuth

    Parameters
    ----------
    d : float or numpy.ndarray
        Distance.
    l : float or numpy.ndarray
        Galactic longitude.
    degree : bool, optional
        If True, l is in degrees rather than rad, by default False.
    ro : float, optional
        Galactocentric radius of the observer, by default 1.0.
    phio : float, optional
        Galactocentric azimuth of the observer, by default 0.0.

    Returns
    -------
    tuple
        (R, phi); phi in degree if degree

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


    Convert Galactocentric radius and azimuth to distance and Galactic longitude

    Parameters
    ----------
    R : float or numpy.ndarray
        Galactocentric radius.
    phi : float or numpy.ndarray
        Galactocentric azimuth.
    degree : bool, optional
        If True, phi is in degrees rather than rad, by default False.
    ro : float, optional
        Galactocentric radius of the observer, by default 1.0.
    phio : float, optional
        Galactocentric azimuth of the observer, by default 0.0.

    Returns
    -------
    tuple
        (d, l); phi in degree if degree

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


    Calculate prolate confocal cosh(u) and cos(v) coordinates from R,z, and delta.

    Parameters
    ----------
    R : float or numpy.ndarray
        Radius.
    z : float or numpy.ndarray
        Height.
    delta : float or numpy.ndarray, optional
        Focus. Default is 1.0.
    oblate : bool, optional
        If True, compute oblate confocal coordinates instead of prolate. Default is False.

    Returns
    -------
    tuple
        Tuple containing cosh(u) and cos(v).

    Notes
    -----
    - 2012-11-27 - Written - Bovy (IAS)
    - 2017-10-11 - Added oblate coordinates - Bovy (UofT)


    Calculate prolate or oblate confocal u and v coordinates from R, z, and delta.

    Parameters
    ----------
    R : float or numpy.ndarray
        Radius.
    z : float or numpy.ndarray
        Height.
    delta : float or numpy.ndarray, optional
        Focus. Default is 1.0.
    oblate : bool, optional
        If True, compute oblate confocal coordinates instead of prolate. Default is False.

    Returns
    -------
    tuple
        (u, v)

    Notes
    -----
    - 2012-11-27 - Written - Bovy (IAS)
    - 2017-10-11 - Added oblate coordinates - Bovy (UofT)


    Calculate R and z from prolate confocal u and v coordinates.

    Parameters
    ----------
    u : float or numpy.ndarray
        Confocal u.
    v : float or numpy.ndarray
        Confocal v.
    delta : float or numpy.ndarray, optional
        Focus. Default is 1.0.
    oblate : bool, optional
        If True, compute oblate confocal coordinates instead of prolate. Default is False.

    Returns
    -------
    tuple
        (R, z)

    Notes
    -----
    - 2012-11-27 - Written - Bovy (IAS)
    - 2017-10-11 - Added oblate coordinates - Bovy (UofT)


    Calculate momenta in prolate or oblate confocal u and v coordinates from cylindrical velocities vR,vz for a given focal length delta.

    Parameters
    ----------
    vR : float or numpy.ndarray
        Radial velocity in cylindrical coordinates.
    vz : float or numpy.ndarray
        Vertical velocity in cylindrical coordinates.
    R : float or numpy.ndarray
        Radius.
    z : float or numpy.ndarray
        Height.
    delta : float or numpy.ndarray, optional
        Focus. Default is 1.0.
    oblate : bool, optional
        If True, compute oblate confocal coordinates instead of prolate. Default is False.
    uv : bool, optional
        If True, the given R,z are actually u,v. Default is False.

    Returns
    -------
    tuple
        (pu, pv)

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


    Calculate cylindrical vR and vz from momenta in prolate or oblate confocal u and v coordinates for a given focal length delta.

    Parameters
    ----------
    pu : float or numpy.ndarray
        Momentum in u.
    pv : float or numpy.ndarray
        Momentum in v.
    u : float or numpy.ndarray
        Confocal u.
    v : float or numpy.ndarray
        Confocal v.
    delta : float or numpy.ndarray, optional
        Focus. Default is 1.0.
    oblate : bool, optional
        If True, compute oblate confocal coordinates instead of prolate. Default is False.

    Returns
    -------
    tuple
        (vR, vz)

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


    Calculate the prolate spheroidal coordinates (lambda,nu) from galactocentric cylindrical coordinates (R,z) by solving eq. (2.2) in Dejonghe & de Zeeuw (1988a) for (lambda,nu).

    Parameters
    ----------
    R : float
        Galactocentric cylindrical radius
    z : float
        Vertical height
    ac : float, optional
        Axis ratio of the coordinate surfaces (a/c) = sqrt(-a) / sqrt(-g) (default: 5.)
    Delta : float, optional
        Focal distance that defines the spheroidal coordinate system (default: 1.)
        Delta=sqrt(g-a)

    Returns
    -------
    tuple
        (lambda,nu)

    Notes
    -----
    - 2015-02-13 - Written - Trick (MPIA)


    Calculate the Jacobian of the cylindrical (R,z) to prolate spheroidal (lambda,nu) conversion.

    Parameters
    ----------
    R : float or numpy.ndarray
        Galactocentric cylindrical radius.
    z : float or numpy.ndarray
        Vertical height.
    Delta : float, optional
        Focal distance that defines the spheroidal coordinate system (default: 1.). Delta=sqrt(g-a).

    Returns
    -------
    ndarray
        Jacobian d((lambda,nu))/d((R,z)).

    Notes
    -----
    - 2015-02-13 - Written - Trick (MPIA).


    Calculate the Hessian of the cylindrical (R,z) to prolate spheroidal (lambda,nu) conversion.

    Parameters
    ----------
    R : float
        Galactocentric cylindrical radius.
    z : float
        Vertical height.
    Delta : float, optional
        Focal distance that defines the spheroidal coordinate system (default: 1.).
        Delta=sqrt(g-a)

    Returns
    -------
    ndarray
        Hessian [d^2(lambda)/d(R,z)^2 , d^2(nu)/d(R,z)^2].

    Notes
    -----
    - 2015-02-13 - Written - Trick (MPIA).


    Calculate galactocentric cylindrical coordinates (R,z) from prolate spheroidal coordinates (lambda,nu).

    Parameters
    ----------
    l : float
        Prolate spheroidal coordinate lambda.
    n : float
        Prolate spheroidal coordinate nu.
    ac : float, optional
        Axis ratio of the coordinate surfaces (a/c) = sqrt(-a) / sqrt(-g) (default: 5.).
    Delta : float, optional
        Focal distance that defines the spheroidal coordinate system (default: 1.). Delta=sqrt(g-a)

    Returns
    -------
    tuple
        (R,z)

    Notes
    -----
    - 2015-02-13 - Written - Trick (MPIA)


    Transform from equatorial coordinates to a custom set of sky coordinates

    Parameters
    ----------
    ra : float or numpy.ndarray
        Right ascension.
    dec : float or numpy.ndarray
        Declination.
    T : numpy.ndarray, optional
        Matrix defining the transformation: new_rect= T dot old_rect, where old_rect = [cos(dec)cos(ra),cos(dec)sin(ra),sin(dec)] and similar for new_rect.
    degree : bool, optional
        If True, ra and dec are given in degree and l and b will be as well.

    Returns
    -------
    tuple
        (custom longitude, custom latitude) (with longitude -180 to 180)

    Notes
    -----
    - 2009-11-12 - Written - Bovy (NYU)
    - 2014-06-14 - Re-written w/ numpy functions for speed and w/ decorators for beauty - Bovy (IAS)
    - 2019-03-02 - adjusted angle ranges - Nathaniel (UofT)


    Rotate proper motions in (ra,dec) to proper motions in a custom set of sky coordinates (phi1,phi2)

    Parameters
    ----------
    pmra : float or numpy.ndarray
        Proper motion in ra (multiplied with cos(dec)) [mas/yr].
    pmdec : float or numpy.ndarray
        Proper motion in dec [mas/yr].
    ra : float or numpy.ndarray
        Right ascension.
    dec : float or numpy.ndarray
        Declination.
    T : numpy.ndarray, optional
        Matrix defining the transformation: new_rect= T dot old_rect, where old_rect = [cos(dec)cos(ra),cos(dec)sin(ra),sin(dec)] and similar for new_rect.
    degree : bool, optional
        If True, ra and dec are given in degrees (default=False).

    Returns
    -------
    tuple
        (pmphi1 x cos(phi2),pmph2) for vector inputs [:,2]

    Notes
    -----
    - 2016-10-24 - Written - Bovy (UofT/CCA)
    - 2019-03-09 - uses custom_to_radec - Nathaniel Starkman (UofT)


    Rotate a custom set of sky coordinates (phi1,phi2) to (ra,dec) given the rotation matrix T for (ra,dec) -> (phi1,phi2)

    Parameters
    ----------
    phi1 : float or numpy.ndarray
        Custom sky coord.
    phi2 : float or numpy.ndarray
        Custom sky coord.
    T : numpy.ndarray, optional
        Matrix defining the transformation: new_rect= T dot old_rect, where old_rect = [cos(dec)cos(ra),cos(dec)sin(ra),sin(dec)] and similar for new_rect.
    degree : bool, optional
        If True, phi1 and phi2 are given in degrees (default=False).

    Returns
    -------
    tuple
        (ra,dec) for vector inputs [:,2]

    Notes
    -----
    - 2018-10-23 - Written - Starkman (UofT)


    Rotate proper motions in a custom set of sky coordinates (phi1,phi2) to (ra,dec) given the rotation matrix T for (ra,dec) -> (phi1,phi2)

    Parameters
    ----------
    pmphi1 : float or numpy.ndarray
        Proper motion in phi1 (multiplied with cos(phi2)) [mas/yr].
    pmphi2 : float or numpy.ndarray
        Proper motion in phi2 [mas/yr].
    phi1 : float or numpy.ndarray
        Custom sky coord.
    phi2 : float or numpy.ndarray
        Custom sky coord.
    T : numpy.ndarray, optional
        Matrix defining the transformation: new_rect= T dot old_rect, where old_rect = [cos(dec)cos(ra),cos(dec)sin(ra),sin(dec)] and similar for new_rect.
    degree : bool, optional
        If True, phi1 and phi2 are given in degrees (default=False).

    Returns
    -------
    tuple
        (pmra x cos(dec), dec) for vector inputs [:,2]

    Notes
    -----
    - 2019-03-02 - Written - Nathaniel Starkman (UofT)


    Save things to a pickle file.

    Parameters
    ----------
    savefilename : str
        Name of the file to save to; actual save operation will be performed on a temporary file and then that file will be shell mv'ed to savefilename.
    *args : tuple
        Things to pickle (as many as you want!).
    **kwargs : dict
        testKeyboardInterrupt : bool, optional
            If True, raises KeyboardInterrupt to test if the function can handle it.

    Returns
    -------
    None

    Notes
    -----
    - 2010-? - Written - Bovy (NYU)
    - 2011-08-23 - generalized and added to galpy.util - Bovy (NYU)


    Stable version of the cholesky decomposition

    Parameters
    ----------
    x : numpy.ndarray
        Positive definite matrix
    tiny : float, optional
        Tiny number to add to the covariance matrix to make the decomposition stable (has a default)

    Returns
    -------
    tuple
        (L, lowerFlag) - output from scipy.linalg.cho_factor for lower=True

    Notes
    -----
    - 2009-09-25 - Written - Bovy (NYU)


    Invert a positive definite matrix by using its Cholesky decomposition.

    Parameters
    ----------
    A : numpy.ndarray
        Matrix to be inverted.
    logdet : bool, optional
        If True, return the logarithm of the determinant as well.
    tiny : float, optional
        Tiny number to add to the covariance matrix to make the decomposition stable (has a default).

    Returns
    -------
    numpy.ndarray or tuple
        If logdet is False, the inverse of the input matrix. If logdet is True, the inverse and the logarithm of the determinant of the input matrix.

    Notes
    -----
    - 2009-10-07 - Written - Bovy (NYU)


r"""Return a rotation matrix that rotates v to align with unit vector a
    i.e. R . v = |v|\hat{a}


    A worker function that maps an input function over a slice of the input iterable.

    Parameters
    ----------
    f : callable
        function that accepts argument from iterable
    ii : int
        process ID
    chunk : ?
        slice of input iterable
    out_q : ?
        thread-safe output queue
    err_q : ?
        thread-safe queue to populate on exception
    lock : ?
        thread-safe lock to protect a resource ( useful in extending parallel_map() )
    progressbar : bool
        if True, display a progress bar
    iter_elapsed : int
        shared-memory Value to track progress
    tot_iter : int
        total number of iterations (for progressbar)
    pbar_proc : ?
        process to use to display the progressbar


    A function that executes populated processes and processes the resultant array. Checks error queue for any exceptions.

    Parameters
    ----------
    procs : list
        list of Process objects
    out_q : ?
        thread-safe output queue
    err_q : ?
        thread-safe queue to populate on exception
    num : int
        length of resultant array


    A parallelized version of the native Python map function that utilizes the Python multiprocessing module to divide and conquer sequence.

    Parameters
    ----------
    function : callable
        callable function that accepts argument from iterable
    sequence : iterable
        iterable sequence
    numcores : int, optional
        number of cores to use
    progressbar : bool, optional
        if True, display a progress bar


Estimate initial step size


Dense output function, basically extrapolating


Core of DOP8(5, 3) integration


    Solve a system of ordinary differential equations using the DOP853 method, an explicit Runge-Kutta method of order 8(5,3) due to Dormand & Prince with step size control and dense output.

    Parameters
    ----------
    func : callable
        function of the differential equation, usually take func([position, velocity], time) and return velocity, acceleration
    x : float or ndarray
        initial x, usually is [position, velocity]
    t : ndarray
        set of times at which one wants the result
    hmax : float
        Maximal step size, default 0. which will be internally as t[-1]-t[0]
    h : float
        Initial step size, default 0. which will be computed by the function hinit()
    rtol : float or ndarray
        Relative error tolerances, default 1e-8
    atol : float or ndarray
        Absolute error tolerances, default 1e-8
    nmax : int
        Maximum number of steps, default 1e8
    safe : float
        Safety factor in the step size prediction, default 0.9
    beta : float
        The "beta" for stabilized step size control (see section IV.2 of the reference). Larger values for beta (e.g.<= 0.1) make the step size control more stable. Default beta=0.
    fac1, fac2 : float
        Parameters for step size selection; the new step size is chosen subject to the restriction fac1 <= hnew/hold <= fac2

    Returns
    -------
    ndarray
        integrated result

    Notes
    -----
    - 2018-11-23 - Written - Henry Leung (University of Toronto)

    References
    ----------
    - E. Hairer, S.P. Norsett and G. Wanner, Solving ordinary differential equations I, non-stiff problems, 2nd edition, Springer Series in Computational Mathematics, Springer-Verlag (1993).


Vectorize the call to a function.

    This is an internal utility function used by `romberg` and
    `quadrature` to create a vectorized version of a function.

    If `vec_func` is True, the function `func` is assumed to take vector
    arguments.

    Parameters
    ----------
    func : callable
        User defined function.
    args : tuple, optional
        Extra arguments for the function.
    vec_func : bool, optional
        True if the function func takes vector arguments.

    Returns
    -------
    vfunc : callable
        A function that will take a vector argument and return the
        result.


    Compute a definite integral using fixed-tolerance Gaussian quadrature.

    Integrate `func` from `a` to `b` using Gaussian quadrature
    with absolute tolerance `tol`.

    Parameters
    ----------
    func : function
        A Python function or method to integrate.
    a : float
        Lower limit of integration.
    b : float
        Upper limit of integration.
    args : tuple, optional
        Extra arguments to pass to function.
    tol, rtol : float, optional
        Iteration stops when error between last two iterates is less than
        `tol` OR the relative change is less than `rtol`.
    maxiter : int, optional
        Maximum order of Gaussian quadrature.
    vec_func : bool, optional
        True or False if func handles arrays as arguments (is
        a "vector" function). Default is True.
    miniter : int, optional
        Minimum order of Gaussian quadrature.

    Returns
    -------
    val : float
        Gaussian quadrature approximation (within tolerance) to integral.
    err : float
        Difference between last two estimates of the integral.


    Perform part of the trapezoidal rule to integrate a function.
    Assume that we had called difftrap with all lower powers-of-2
    starting with 1. Calling difftrap only returns the summation
    of the new ordinates. It does _not_ multiply by the width
    of the trapezoids. This must be performed by the caller.
        'function' is the function to evaluate (must accept vector arguments).
        'interval' is a sequence with lower and upper limits
                   of integration.
        'numtraps' is the number of trapezoids to use (must be a
                   power-of-2).


    Compute the differences for the Romberg quadrature corrections.
    See Forman Acton's "Real Computing Made Real," p 143.


    Romberg integration of a callable function or method.

    Returns the integral of `function` (a function of one variable)
    over the interval (`a`, `b`).

    If `show` is 1, the triangular array of the intermediate results
    will be printed. If `vec_func` is True (default is False), then
    `function` is assumed to support vector arguments.

    Parameters
    ----------
    function : callable
        Function to be integrated.
    a : float
        Lower limit of integration.
    b : float
        Upper limit of integration.

    Returns
    -------
    results : float
        Result of the integration.

    Other Parameters
    ----------------
    args : tuple, optional
        Extra arguments to pass to function. Each element of `args` will
        be passed as a single argument to `func`. Default is to pass no
        extra arguments.
    tol, rtol : float, optional
        The desired absolute and relative tolerances. Defaults are 1.48e-8.
    divmax : int, optional
        Maximum order of extrapolation. Default is 10.
    vec_func : bool, optional
        Whether `func` handles arrays as arguments (i.e., whether it is a
        "vector" function). Default is False.

    References
    ----------
    .. [1] 'Romberg's method' https://en.wikipedia.org/wiki/Romberg%27s_method


    Leapfrog integration of an ODE

    Parameters
    ----------
    func : function
        function of (y, *args)
    yo : numpy.ndarray
        initial condition [q,p]
    t : numpy.ndarray
        set of times at which one wants the result
    args : tuple, optional
        any extra arguments for func
    rtol : float, optional
        relative tolerance
    atol : float, optional
        absolute tolerance

    Returns
    -------
    numpy.ndarray
        Array containing the value of y for each desired time in t, with the initial value y0 in the first row.

    Notes
    -----
    - 2011-02-02 - Written - Bovy (NYU)


    Save the current figure(s) to a file.

    Parameters
    ----------
    filename : str
        Filename for the plot (with extension).
    **kwargs
        Additional keyword arguments to pass to `pyplot.savefig`.

    Notes
    -----
    - 2009-12-23 - Written - Bovy (NYU)


    Plot a histogram of the input array using matplotlib's hist function.

    Parameters
    ----------
    x : numpy.ndarray
        Array to histogram.
    xlabel : str, optional
        x-axis label, LaTeX math mode, no $s needed.
    ylabel : str, optional
        y-axis label, LaTeX math mode, no $s needed.
    overplot : bool, optional
        If True, plot on top of the current figure.
    **kwargs
        All other keyword arguments are passed to ``pyplot.hist``.

    Returns
    -------
    tuple
        Output from ``pyplot.hist``

    Notes
    -----
    - 2009-12-23 - Written - Bovy (NYU)


    Wrapper around matplotlib's plot function.

    Parameters
    ----------
    *args:
        Inputs to ``pyplot.plot``.
    xlabel : str, optional
        x-axis label, LaTeX math mode, no $s needed.
    ylabel : str, optional
        y-axis label, LaTeX math mode, no $s needed.
    xrange : tuple, optional
        x range to plot over.
    yrange : tuple, optional
        y range to plot over.
    overplot : bool, optional
        If True, plot on top of the current figure.
    gcf : bool, optional
        If True, do not start a new figure.
    onedhists : bool, optional
        If True, make one-d histograms on the sides.
    onedhistcolor : str, optional
        Histogram color.
    onedhistfc : str, optional
        Histogram fill color.
    onedhistec : str, optional
        Histogram edge color.
    onedhistxnormed : bool, optional
        If True, normalize the x-axis histogram.
    onedhistynormed : bool, optional
        If True, normalize the y-axis histogram.
    onedhistxweights : numpy.ndarray, optional
        Weights for the x-axis histogram.
    onedhistyweights : numpy.ndarray, optional
        Weights for the y-axis histogram.
    bins : int, optional
        Number of bins for the one-d histograms.
    semilogx : bool, optional
        If True, plot the x-axis on a log scale.
    semilogy : bool, optional
        If True, plot the y-axis on a log scale.
    loglog : bool, optional
        If True, plot both axes on a log scale.
    scatter : bool, optional
        If True, use ``pyplot.scatter`` instead of ``pyplot.plot``.
    colorbar : bool, optional
        If True, add a colorbar.
    crange : tuple, optional
        Range for the colorbar.
    clabel : str, optional
        Label for the colorbar.
    **kwargs
        All other keyword arguments are passed to ``pyplot.plot`` or ``pyplot.scatter``.

    Returns
    -------
    tuple
        Output from ``pyplot.plot``/``pyplot.scatter`` or 3 Axes instances if ``onedhists=True``.

    Notes
    -----
    - 2009-12-28 - Written - Bovy (NYU)


    Wrapper around ``pyplot.plot`` for 3D plots, much like plot is a wrapper around ``pyplot.plot`` for 2D plots.

    Parameters
    ----------
    *args:
        Inputs to ``pyplot.plot3d``.
    xlabel : str, optional
        x-axis label, LaTeX math mode, no $s needed.
    ylabel : str, optional
        y-axis label, LaTeX math mode, no $s needed.
    zlabel : str, optional
        z-axis label, LaTeX math mode, no $s needed.
    xrange : tuple, optional
        x range to plot over.
    yrange : tuple, optional
        y range to plot over.
    zrange : tuple, optional
        z range to plot over.
    overplot : bool, optional
        If True, plot on top of the current figure.

    Returns
    -------
    tuple
        Output from ``pyplot.plot3d``.

    Notes
    -----
    - 2011-01-08 - Written - Bovy (NYU)


    Plot a 2d density with optional contours.

    Parameters
    ----------
    X : numpy.ndarray
        The density to plot.
    *args :
        Arguments for ``pyplot.imshow``.
    xlabel : str, optional
        x-axis label, LaTeX math mode, no $s needed.
    ylabel : str, optional
        y-axis label, LaTeX math mode, no $s needed.
    xrange : tuple, optional
        x range to plot over.
    yrange : tuple, optional
        y range to plot over.
    noaxes : bool, optional
        If True, don't plot any axes.
    overplot : bool, optional
        If True, overplot.
    gcf : bool, optional
        If True, do not start a new figure.
    colorbar : bool, optional
        If True, add colorbar.
    shrink : float, optional
        Colorbar shrink factor.
    conditional : bool, optional
        Normalize each column separately (for probability densities, i.e., ``cntrmass=True``).
    justcontours : bool, optional
        If True, only draw contours.
    contours : bool, optional
        If True, draw contours (10 by default).
    levels : numpy.ndarray, optional
        Contour levels.
    cntrmass : bool, optional
        If True, the density is a probability and the levels are probability masses contained within the contour.
    cntrcolors : str or list, optional
        Colors for contours (single color or array).
    cntrlabel : bool, optional
        Label the contours.
    cntrlw : float, optional
        Linewidths for contour.
    cntrls : str, optional
        Linestyles for contour.
    cntrlabelsize : float, optional
        Size of contour labels.
    cntrlabelcolors : str, optional
        Color of contour labels.
    cntrinline : bool, optional
        If True, put contour labels inline with contour.
    cntrSmooth : float, optional
        Use ``ndimage.gaussian_filter`` to smooth before contouring.
    retAxes : bool, optional
        Return all Axes instances.
    retCont : bool, optional
        Return the contour instance.

    Returns
    -------
    Axes or tuple
        Plot to output device, Axes instances depending on input.

    Notes
    -----
    - 2010-03-09 - Written - Bovy (NYU)


    Set up a figure for plotting.

    Parameters
    ----------
    fig_width : float, optional
        Width in inches. Default is 5.
    fig_height : float, optional
        Height in inches. Default is 5.
    axes_labelsize : int, optional
        Size of the axis-labels. Default is 16.
    text_fontsize : int, optional
        Font-size of the text (if any). Default is 11.
    legend_fontsize : int, optional
        Font-size of the legend (if any). Default is 12.
    xtick_labelsize : int, optional
        Size of the x-axis labels. Default is 10.
    ytick_labelsize : int, optional
        Size of the y-axis labels. Default is 10.
    xtick_minor_size : int, optional
        Size of the minor x-ticks. Default is 2.
    ytick_minor_size : int, optional
        Size of the minor y-ticks. Default is 2.
    xtick_major_size : int, optional
        Size of the major x-ticks. Default is 4.
    ytick_major_size : int, optional
        Size of the major y-ticks. Default is 4.

    Notes
    -----
    - 2009-12-23 - Written - Bovy (NYU).


    Thin wrapper around matplotlib's text and annotate.

    Parameters
    ----------
    *args :
        See matplotlib's text
        (http://matplotlib.sourceforge.net/api/pyplot_api.html#matplotlib.pyplot.text).
    **kwargs :
        'bottom_left=True', 'bottom_right=True', 'top_left=True', 'top_right=True', 'title=True'
        to place the text in one of the corners or use it as the title.

    Notes
    -----
    - 2010-01-26 - Written - Bovy (NYU)


    Make a 'smart' scatterplot that is a density plot in high-density regions and a regular scatterplot for outliers.

    Parameters
    ----------
    x : numpy.ndarray
        x data.
    y : numpy.ndarray
        y data.
    xlabel : str, optional
        x-axis label, LaTeX math mode, no $s needed.
    ylabel : str, optional
        y-axis label, LaTeX math mode, no $s needed.
    xrange : tuple, optional
        x range to plot over.
    yrange : tuple, optional
        y range to plot over.
    bins : int, optional
        Number of bins to use in each dimension.
    weights : numpy.ndarray, optional
        Data-weights.
    aspect : float, optional
        Aspect ratio.
    conditional : bool, optional
        Normalize each column separately (for probability densities, i.e., ``cntrmass=True``).
    overplot : bool, optional
        If True, overplot.
    gcf : bool, optional
        Do not start a new figure (does change the ranges and labels).
    contours : bool, optional
        If False, don't plot contours.
    justcontours : bool, optional
        If True, only draw contours, no density.
    cntrcolors : str or list, optional
        Color of contours (can be array as for dens2d).
    cntrlw : float, optional
        Linewidths for contour.
    cntrls : str, optional
        Linestyles for contour.
    cntrSmooth : float, optional
        Use ``ndimage.gaussian_filter`` to smooth before contouring.
    levels : numpy.ndarray, optional
        Contour-levels; data points outside of the last level will be individually shown (so, e.g., if this list is descending, contours and data points will be overplotted).
    onedhists : bool, optional
        If True, make one-d histograms on the sides.
    onedhistx : bool, optional
        If True, make one-d histograms on the side of the x distribution.
    onedhisty : bool, optional
        If True, make one-d histograms on the side of the y distribution.
    onedhistcolor : str, optional
        Color of one-d histograms.
    onedhistfc : str, optional
        Facecolor of one-d histograms.
    onedhistec : str, optional
        Edgecolor of one-d histograms.
    onedhistxnormed : bool, optional
        Normed keyword for one-d histograms.
    onedhistynormed : bool, optional
        Normed keyword for one-d histograms.
    onedhistxweights : numpy.ndarray, optional
        Weights keyword for one-d histograms.
    onedhistyweights : numpy.ndarray, optional
        Weights keyword for one-d histograms.
    cmap : matplotlib.colors.Colormap, optional
        Colormap for density plot.
    hist : numpy.ndarray, optional
        You can supply the histogram of the data yourself, this can be useful if you want to censor the data, both need to be set and calculated using scipy.histogramdd with the given range.
    edges : numpy.ndarray, optional
        You can supply the histogram of the data yourself, this can be useful if you want to censor the data, both need to be set and calculated using scipy.histogramdd with the given range.
    retAxes : bool, optional
        Return all Axes instances.

    Returns
    -------
    Axes or tuple
        Plot to output device, Axes instance(s) or not, depending on input.

    Notes
    -----
    - 2010-04-15 - Written - Bovy (NYU)


    Add axis labels to the current figure.

    Parameters
    ----------
    xlabel : str
        x-axis label, LaTeX math mode, no $s needed.
    ylabel : str
        y-axis label, LaTeX math mode, no $s needed.

    Notes
    -----
    = 2009-12-23 - Written - Bovy (NYU).


    Add minor axis ticks to a plot.

    Parameters
    ----------
    xticks : bool, optional
        If True, add minor ticks to the x-axis. Default is True.
    yticks : bool, optional
        If True, add minor ticks to the y-axis. Default is True.

    Notes
    -----
    - 2009-12-23 - Written - Bovy (NYU)


    Implementation of the Adaptive-Rejection Sampling algorithm by Gilks & Wild (1992): Adaptive Rejection Sampling for Gibbs Sampling, Applied Statistics, 41, 337. Based on Wild & Gilks (1993), Algorithm AS 287: Adaptive Rejection Sampling from Log-concave Density Functions, Applied Statistics, 42, 701

    Parameters
    ----------
    domain : list or numpy.ndarray
        [.,.] upper and lower limit to the domain
    isDomainFinite : list or numpy.ndarray
        [.,.] is there a lower/upper limit to the domain?
    abcissae : list or numpy.ndarray
        initial list of abcissae (must lie on either side of the peak in hx if the domain is unbounded)
    hx : function
        function that evaluates h(x) = ln g(x)
    hpx : function
        function that evaluates hp(x) =  d h(x) / d x
    nsamples : int, optional
        number of desired samples (default=1)
    hxparams : tuple, optional
        a tuple of parameters for h(x) and h'(x)
    maxn : int, optional
        maximum number of updates to the hull (default=100)

    Returns
    -------
    list
        list with nsamples of samples from exp(h(x))

    Notes
    -----
    - 2009-05-21 - Written - Bovy (NYU)


    Sample one point by ars

    Parameters
    ----------
    hull : list
        the hull (see doc of setup_hull for definition)
    hx : function
        function that evaluates h(x)
    hpx : function
        function that evaluates hp(x)
    domain : list or numpy.ndarray
        [.,.] upper and lower limit to the domain
    isDomainFinite : list or numpy.ndarray
        [.,.] is there a lower/upper limit to the domain?
    maxn : int
        maximum number of updates to the hull
    nupdates : int
        number of updates to the hull that have occurred
    hxparams : tuple
        tuple of parameters for h(x) and h'(x)

    Returns
    -------
    list
        [0]= a sample
        [1]= a new hull
        [2]= nupdates

    Notes
    -----
    - 2009-05-21 - Written - Bovy (NYU)


    Sample the upper hull

    Parameters
    ----------
    hull : list
        the hull (see doc of setup_hull for definition)
    domain : list or numpy.ndarray
        [.,.] upper and lower limit to the domain
    isDomainFinite : list or numpy.ndarray
        [.,.] is there a lower/upper limit to the domain?

    Returns
    -------
    float
        a sample from the hull

    Notes
    -----
    - 2009-05-21 - Written - Bovy (NYU)


    Evaluate h_u(x) and (optional) h_l(x)

    Parameters
    ----------
    x : float
        abcissa
    hull : list
        the hull (see doc of setup_hull for definition)

    Returns
    -------
    float or tuple
        hu(x) (optional), hl(x)

    Notes
    -----
    - 2009-05-21 - Written - Bovy (NYU)


    Update the hull with a new function evaluation

    Parameters
    ----------
    hull : list
        the hull (see doc of setup_hull for definition)
    newx : float
        new abcissa
    newhx : float
        h(newx)
    newhpx : float
        hp(newx)
    domain : list or numpy.ndarray
        [.,.] upper and lower limit to the domain
    isDomainFinite : list or numpy.ndarray
        [.,.] is there a lower/upper limit to the domain?

    Returns
    -------
    list
        new hull

    Notes
    -----
    - 2009-05-21 - Written - Bovy (NYU)


    Convert density to units of the critical density.

    Parameters
    ----------
    vo : float
        Velocity unit in km/s.
    ro : float
        Length unit in kpc.
    H : float, optional
        Hubble constant in km/s/Mpc. Default is 70.0.

    Returns
    -------
    float
        Conversion from units where vo=1. at ro=1. to units of the critical density.

    Notes
    -----
    - 2014-01-28 - Written - Bovy (IAS)


    Convert density to units of the mean matter density.

    Parameters
    ----------
    vo : float
        Velocity unit in km/s.
    ro : float
        Length unit in kpc.
    H : float, optional
        Hubble constant in km/s/Mpc. Default is 70.0.
    Om : float, optional
        Omega matter. Default is 0.3.

    Returns
    -------
    float
        Conversion from units where vo=1. at ro=1. to units of the mean matter density.

    Notes
    -----
    - 2014-01-28 - Written - Bovy (IAS)


    Convert density to GeV / cm^3.

    Parameters
    ----------
    vo : float
        Velocity unit in km/s.
    ro : float
        Length unit in kpc.

    Returns
    -------
    float
        Conversion from units where vo=1. at ro=1. to GeV/cm^3.

    Notes
    -----
    - 2014-06-16 - Written - Bovy (IAS)


    Convert density to Msolar / pc^3.

    Parameters
    ----------
    vo : float
        Velocity unit in km/s.
    ro : float
        Length unit in kpc.

    Returns
    -------
    float
        Conversion from units where vo=1. at ro=1. to Msolar/pc^3.

    Notes
    -----
    - 2013-09-01 - Written - Bovy (IAS)


    Convert a force or acceleration to 2piG x Msolar / pc^2

    Parameters
    ----------
    vo : float
        Velocity unit in km/s
    ro : float
        Length unit in kpc

    Returns
    -------
    float
        Conversion from units where vo=1. at ro=1.

    Notes
    -----
    - 2013-09-01 - Written - Bovy (IAS)


    Convert a force or acceleration to pc/Myr^2.

    Parameters
    ----------
    vo : float
        Velocity unit in km/s.
    ro : float
        Length unit in kpc.

    Returns
    -------
    float
        Conversion from units where vo=1. at ro=1.

    Notes
    -----
    - 2013-09-01 - Written - Bovy (IAS)


    Convert a force or acceleration to km/s/Myr.

    Parameters
    ----------
    vo : float
        Velocity unit in km/s.
    ro : float
        Length unit in kpc.

    Returns
    -------
    float
        Conversion from units where vo=1. at ro=1.

    Notes
    -----
    - 2013-09-01 - Written - Bovy (IAS)


    Convert a force or acceleration to 10^(-13) km/s^2

    Parameters
    ----------
    vo : float
        Velocity unit in km/s
    ro : float
        Length unit in kpc

    Returns
    -------
    float
        Conversion from units where vo=1. at ro=1.

    Notes
    -----
    - 2014-01-22 - Written - Bovy (IAS)


    Convert a frequency to 1/Gyr.

    Parameters
    ----------
    vo : float
        Velocity unit in km/s.
    ro : float
        Length unit in kpc.

    Returns
    -------
    float
        Conversion from units where vo=1. at ro=1.

    Notes
    -----
    - 2013-09-01 - Written - Bovy (IAS)


    Convert a frequency to km/s/kpc.

    Parameters
    ----------
    vo : float
        Velocity unit in km/s.
    ro : float
        Length unit in kpc.

    Returns
    -------
    float
        Conversion from units where vo=1. at ro=1.

    Notes
    -----
    - 2013-09-01 - Written - Bovy (IAS)


    Convert a surface density to Msolar / pc^2.

    Parameters
    ----------
    vo : float
        Velocity unit in km/s.
    ro : float
        Length unit in kpc.

    Returns
    -------
    float
        Conversion from units where vo=1. at ro=1.

    Notes
    -----
    - 2013-09-01 - Written - Bovy (IAS)


    Convert a mass to Msolar.

    Parameters
    ----------
    vo : float
        Velocity unit in km/s.
    ro : float
        Length unit in kpc.

    Returns
    -------
    float
        Conversion from units where vo=1. at ro=1.

    Notes
    -----
    - 2013-09-01 - Written - Bovy (IAS)


    Convert a mass to 10^10 x Msolar.

    Parameters
    ----------
    vo : float
        Velocity unit in km/s.
    ro : float
        Length unit in kpc.

    Returns
    -------
    float
        Conversion from units where vo=1. at ro=1.

    Notes
    -----
    - 2013-09-01 - Written - Bovy (IAS)


    Convert a time to Gyr.

    Parameters
    ----------
    vo : float
        Velocity unit in km/s.
    ro : float
        Length unit in kpc.

    Returns
    -------
    float
        Conversion from units where vo=1. at ro=1.

    Notes
    -----
    - 2013-09-01 - Written - Bovy (IAS)


    Convert a velocity to kpc/Gyr.

    Parameters
    ----------
    vo : float
        Velocity unit in km/s.
    ro : float
        Length unit in kpc.

    Returns
    -------
    float
        Conversion from units where vo=1. at ro=1.

    Notes
    -----
    - 2014-12-19 - Written - Bovy (IAS)


    Extract the physical kwargs from a kwargs dictionary.

    Parameters
    ----------
    kwargs : dict
        A dictionary of kwargs.

    Returns
    -------
    dict
        A dictionary with just the physical kwargs.

    Notes
    -----
    - 2023-04-24 - Written - Bovy (UofT)


    Test whether the velocity and length units for converting between physical and internal units are compatible for two galpy objects.

    Parameters
    ----------
    obj : galpy object or list of such objects
        A galpy object or list of such objects (e.g., a Potential, list of Potentials, Orbit, actionAngle instance, DF instance)
    other_obj : galpy object or list of such objects
        Another galpy object or list of such objects (e.g., a Potential, list of Potentials, Orbit, actionAngle instance, DF instance)

    Returns
    -------
    bool
        True if the units are compatible, False if not (compatible means that the units are the same when they are set for both objects).

    Notes
    -----
    - 2020-04-22 - Written - Bovy (UofT)


    Decorator to check the inputs to a parse_ function; should be either:
    a) a number
    b) an array of numbers
    c) an astropy Quantity (incl. arrays)

    Also parses ro/vo if they are provided and converts them to the correct
    internal representation


    Determine whether or not outputs will be physical or not

    Parameters
    ----------
    obj : galpy object (or list in case of potentials)
        galpy object.
    kwargs : dict
        Kwargs passed to the method.
    quantity : str
        Quantity to be returned.

    Returns
    -------
    tuple
        A tuple containing:
            - boolean that indicates whether or not to use physical units.
            - ro.
            - vo.

    Notes
    -----
    - 2023-04-24 - Written - Bovy (UofT).


Decorator to convert to physical coordinates:
    quantity = [position,velocity,time]


Decorator to convert to physical coordinates for tuple outputs.
    So outputs are a tuple of quantities that each need to be converted,
    with possibly different conversions, e.g., (R,vR)


Decorator to convert inputs to Potential functions from physical
    to internal coordinates


Decorator to convert to physical coordinates for the actionAngle methods:
    quantity= call, actionsFreqs, or actionsFreqsAngles (or EccZmaxRperiRap for actionAngleStaeckel)


Decorator to convert inputs to actionAngle functions from physical
    to internal coordinates


Decorator to convert to physical coordinates for the actionAngleInverse methods:
    quantity= call, xvFreqs, or Freqs


Decorator to convert inputs to actionAngleInverse functions from
    physical to internal coordinates


Parse the potential so it can be fed to C


    C integrate an ode for a LinearOrbit

    Parameters
    ----------
    pot : Potential or list of such instances
    yo : numpy.ndarray
        initial condition [q,p], shape [N,2] or [2]
    t : numpy.ndarray
        set of times at which one wants the result
    int_method : str
        integration method
    rtol : float, optional
        relative tolerance
    atol : float, optional
        absolute tolerance
    progressbar : bool, optional
        if True, display a tqdm progress bar
    dt : float, optional
        force integrator to use this stepsize (default is to automatically determine one; only for C-based integrators)

    Returns
    -------
    tuple
        (y,err)
        y : Array containing the value of y for each desired time in t, with the initial value y0 in the first row.
        err: error message, if not zero: 1 means maximum step reduction happened for adaptive integrators

    Notes
    -----
    - 2018-10-06 - Written - Bovy (UofT)
    - 2018-10-14 - Adapted to allow multiple orbits to be integrated at once - Bovy (UofT)
    - 2022-04-12 - Add progressbar - Bovy (UofT)


    Integrate an ode for a LinearOrbit

    Parameters
    ----------
    pot : Potential or list of such instances
    yo : numpy.ndarray
        initial condition [q,p], shape [N,2] or [2]
    t : numpy.ndarray
        set of times at which one wants the result
    int_method : str
        integration method
    rtol : float, optional
        relative tolerance
    atol : float, optional
        absolute tolerance
    numcores : int, optional
        number of cores to use
    progressbar : bool, optional
        if True, display a tqdm progress bar
    dt : float, optional
        force integrator to use this stepsize (default is to automatically determine one; only for C-based integrators)

    Returns
    -------
    tuple
        (y,err)
        y : Array containing the value of y for each desired time in t, with the initial value y0 in the first row.
        err: error message, if not zero: 1 means maximum step reduction happened for adaptive integrators

    Notes
    -----
    - 2010-07-13- Written - Bovy (NYU)
    - 2019-04-08 - Adapted to allow multiple orbits to be integrated at once and moved to integrateLinearOrbit.py - Bovy (UofT)
    - 2022-04-12 - Add progressbar - Bovy (UofT)


    The one-dimensional equation-of-motion

    Parameters
    ----------
    y : list or numpy.ndarray
        Current phase-space position
    t : float
        Current time
    pot : list
        (list of) linearPotential instance(s)

    Returns
    -------
    list
        dy/dt

    Notes
    -----
    - 2010-07-13 - Bovy (NYU)


    Integrate an ode for a FullOrbit.

    Parameters
    ----------
    pot : Potential or list of such instances
        The potential (or list thereof) to evaluate the orbit in.
    yo : numpy.ndarray
        Initial condition [q,p], can be [N,6] or [6].
    t : numpy.ndarray
        Set of times at which one wants the result.
    int_method : str
        Integration method. One of 'leapfrog_c', 'rk4_c', 'rk6_c', 'symplec4_c'.
    rtol : float, optional
        Relative tolerance.
    atol : float, optional
        Absolute tolerance.
    progressbar : bool, optional
        If True, display a tqdm progress bar when integrating multiple orbits (requires tqdm to be installed!).
    dt : float, optional
        Force integrator to use this stepsize (default is to automatically determine one; only for C-based integrators).

    Returns
    -------
    tuple
        (y, err)
        y : array, shape (N,len(t),6)  or (len(t),6) if N = 1
            Array containing the value of y for each desired time in t, with the initial value y0 in the first row.
        err : int or array of ints
            Error message, if not zero: 1 means maximum step reduction happened for adaptive integrators.

    Notes
    -----
    - 2011-11-13 - Written - Bovy (IAS)
    - 2018-12-21 - Adapted to allow multiple objects - Bovy (UofT)
    - 2022-04-12 - Add progressbar - Bovy (UofT)


    Integrate an ode for a planarOrbit+phase space volume dxdv.

    Parameters
    ----------
    pot : Potential or list of such instances
        The potential (or list thereof) to evaluate the orbit in.
    yo : numpy.ndarray
        Initial condition [q,p].
    dyo : numpy.ndarray
        Initial condition [dq,dp].
    t : numpy.ndarray
        Set of times at which one wants the result.
    int_method : str
        Integration method. One of 'leapfrog_c', 'rk4_c', 'rk6_c', 'symplec4_c'.
    rtol : float, optional
        Relative tolerance.
    atol : float, optional
        Absolute tolerance.

    Returns
    -------
    tuple
        (y,err)
        y : array, shape (len(y0), len(t))
            Array containing the value of y for each desired time in t, with the initial value y0 in the first row.
        err : int
            Error message if not zero, 1: maximum step reduction happened for adaptive integrators.

    Notes
    -----
    - 2011-11-13 - Written - Bovy (IAS)


    Integrate an ode for a FullOrbit

    Parameters
    ----------
    pot : Potential or list of such instances
        The potential (or list thereof) to evaluate the orbit in.
    yo : numpy.ndarray
        Initial condition [q,p], shape [N,5] or [N,6]
    t : numpy.ndarray
        Set of times at which one wants the result.
    int_method : str
        Integration method. One of 'leapfrog', 'odeint', 'dop853'.
    rtol : float, optional
        Relative tolerance.
    atol : float, optional
        Absolute tolerance.
    numcores : int, optional
        Number of cores to use for multi-processing.
    progressbar : bool, optional
        If True, display a tqdm progress bar when integrating multiple orbits (requires tqdm to be installed!).
    dt : float, optional
        Force integrator to use this stepsize (default is to automatically determine one; only for C-based integrators).

    Returns
    -------
    tuple
        (y,err)
        y : array, shape (N,len(t),5/6)
            Array containing the value of y for each desired time in t, with the initial value y0 in the first row.
        err : int or array of ints
            Error message, if not zero: 1 means maximum step reduction happened for adaptive integrators.

    Notes
    -----
    - 2010-08-01 - Written - Bovy (NYU)
    - 2019-04-09 - Adapted to allow multiple objects and parallel mapping - Bovy (UofT)
    - 2022-04-12 - Add progressbar - Bovy (UofT)


    Integrate an ode for a FullOrbit for integrate_sos in C

    Parameters
    ----------
    pot : Potential or list of such instances
        The potential (or list thereof) to evaluate the orbit in.
    yo : numpy.ndarray
        initial condition [q,p]
    psi : numpy.ndarray
        set of increment angles at which one wants the result [increments wrt initial angle]
    t0 : float or numpy.ndarray
        initial time
    int_method : str
        'rk4_c', 'rk6_c', 'dopr54_c', or 'dop853_c'
    rtol : float, optional
        tolerances (not always used...)
    atol : float, optional
        tolerances (not always used...)
    progressbar : bool, optional
        if True, display a tqdm progress bar when integrating multiple orbits (requires tqdm to be installed!)
    dpsi : float, optional
        force integrator to use this stepsize (default is to automatically determine one; only for C-based integrators)

    Returns
    -------
    tuple
        (y,err)
        y : array, shape (N,len(psi),7) where the last of the last dimension is the time
            Array containing the value of y for each desired angle in psi, \
            with the initial value y0 in the first row.
        err : int
            error message, always zero for now

    Notes
    -----
    - 2023-03-17 - Written based on integrateFullOrbit_c - Bovy (UofT)