        Calculate the Oort function A at (R,phi,t)

        Parameters
        ----------
        R : float
            Radius at which to calculate the moment (can be Quantity)
        phi : float, optional
            Azimuth (rad unless deg=True; can be Quantity), by default 0.0
        t : float or array, optional
            Time at which to evaluate the DF (can be a list or ndarray; if this is the case, list needs to be in descending order and equally spaced) (can be Quantity), by default 0.0
        surfacemass : float, optional
            If set use this pre-calculated surfacemass and mean rotational velocity, by default None
        meanvT : float, optional
            If set use this pre-calculated surfacemass and mean rotational velocity, by default None
        nsigma : float, optional
            Number of sigma to integrate the velocities over (based on an estimate, so be generous), by default None
        deg : bool, optional
            Azimuth is in degree (default=False); do not set this when giving phi as a Quantity, by default False
        epsrel : float, optional
            Scipy.integrate keywords (the integration calculates the ratio of this vmoment to that of the initial DF), by default 1.0e-02
        epsabs : float, optional
            Scipy.integrate keywords (the integration calculates the ratio of this vmoment to that of the initial DF), by default 1.0e-05
        grid : bool or evolveddiskdfGrid or evolveddiskdfHierarchicalGrid, optional
            If set to True, build a grid and use that to evaluate integrals; if set to a grid-objects (such as returned by this procedure), use this grid, by default None
        gridpoints : int, optional
            Number of points to use for the grid in 1D (default=101), by default 101
        returnGrids : bool, optional
            If True, return the grid objects (default=False), by default False
        derivRGrid : bool or evolveddiskdfGrid or evolveddiskdfHierarchicalGrid, optional
            If set to True, build a grid and use that to evaluate integrals of the derivatives of the DF; if set to a grid-objects (such as returned by this procedure), use this grid, by default None
        derivphiGrid : bool or evolveddiskdfGrid or evolveddiskdfHierarchicalGrid, optional
            If set to True, build a grid and use that to evaluate integrals of the derivatives of the DF; if set to a grid-objects (such as returned by this procedure), use this grid, by default None
        derivGridpoints : int, optional
            Number of points to use for the grid in 1D (default=101), by default 101
        derivHierarchgrid : bool, optional
            If True, use a hierarchical grid (default=False), by default False
        hierarchgrid : bool, optional
            If True, use a hierarchical grid (default=False), by default False
        nlevels : int, optional
            Number of hierarchical levels for the hierarchical grid, by default 2
        integrate_method : str, optional
            orbit.integrate method argument, by default "dopr54_c"

        Returns
        -------
        float or tuple
            Oort A at R,phi,t or tuple of Oort A at R,phi,t and grid objects

        Notes
        -----
        - 2011-10-16 - Written - Bovy (NYU)


        Calculate the Oort function B at (R,phi,t)

        Parameters
        ----------
        R : float
            Radius at which to calculate the moment (can be Quantity)
        phi : float, optional
            Azimuth (rad unless deg=True; can be Quantity), by default 0.0
        t : float or array, optional
            Time at which to evaluate the DF (can be a list or ndarray; if this is the case, list needs to be in descending order and equally spaced) (can be Quantity), by default 0.0
        surfacemass : float, optional
            If set use this pre-calculated surfacemass and mean rotational velocity, by default None
        meanvT : float, optional
            If set use this pre-calculated surfacemass and mean rotational velocity, by default None
        nsigma : float, optional
            Number of sigma to integrate the velocities over (based on an estimate, so be generous), by default None
        deg : bool, optional
            Azimuth is in degree (default=False); do not set this when giving phi as a Quantity, by default False
        epsrel : float, optional
            Scipy.integrate keywords (the integration calculates the ratio of this vmoment to that of the initial DF), by default 1.0e-02
        epsabs : float, optional
            Scipy.integrate keywords (the integration calculates the ratio of this vmoment to that of the initial DF), by default 1.0e-05
        grid : bool or evolveddiskdfGrid or evolveddiskdfHierarchicalGrid, optional
            If set to True, build a grid and use that to evaluate integrals; if set to a grid-objects (such as returned by this procedure), use this grid, by default None
        gridpoints : int, optional
            Number of points to use for the grid in 1D (default=101), by default 101
        returnGrids : bool, optional
            If True, return the grid objects (default=False), by default False
        derivRGrid : bool or evolveddiskdfGrid or evolveddiskdfHierarchicalGrid, optional
            If set to True, build a grid and use that to evaluate integrals of the derivatives of the DF; if set to a grid-objects (such as returned by this procedure), use this grid, by default None
        derivphiGrid : bool or evolveddiskdfGrid or evolveddiskdfHierarchicalGrid, optional
            If set to True, build a grid and use that to evaluate integrals of the derivatives of the DF; if set to a grid-objects (such as returned by this procedure), use this grid, by default None
        derivGridpoints : int, optional
            Number of points to use for the grid in 1D (default=101), by default 101
        derivHierarchgrid : bool, optional
            If True, use a hierarchical grid (default=False), by default False
        hierarchgrid : bool, optional
            If True, use a hierarchical grid (default=False), by default False
        nlevels : int, optional
            Number of hierarchical levels for the hierarchical grid, by default 2
        integrate_method : str, optional
            orbit.integrate method argument, by default "dopr54_c"

        Returns
        -------
        float or tuple
            Oort B at R,phi,t or tuple of Oort A at R,phi,t and grid objects

        Notes
        -----
        - 2011-10-16 - Written - Bovy (NYU)


        Calculate the Oort function C at (R,phi,t)

        Parameters
        ----------
        R : float
            Radius at which to calculate the moment (can be Quantity)
        phi : float, optional
            Azimuth (rad unless deg=True; can be Quantity), by default 0.0
        t : float or array, optional
            Time at which to evaluate the DF (can be a list or ndarray; if this is the case, list needs to be in descending order and equally spaced) (can be Quantity), by default 0.0
        surfacemass : float, optional
            If set use this pre-calculated surfacemass and mean rotational velocity, by default None
        meanvT : float, optional
            If set use this pre-calculated surfacemass and mean rotational velocity, by default None
        nsigma : float, optional
            Number of sigma to integrate the velocities over (based on an estimate, so be generous), by default None
        deg : bool, optional
            Azimuth is in degree (default=False); do not set this when giving phi as a Quantity, by default False
        epsrel : float, optional
            Scipy.integrate keywords (the integration calculates the ratio of this vmoment to that of the initial DF), by default 1.0e-02
        epsabs : float, optional
            Scipy.integrate keywords (the integration calculates the ratio of this vmoment to that of the initial DF), by default 1.0e-05
        grid : bool or evolveddiskdfGrid or evolveddiskdfHierarchicalGrid, optional
            If set to True, build a grid and use that to evaluate integrals; if set to a grid-objects (such as returned by this procedure), use this grid, by default None
        gridpoints : int, optional
            Number of points to use for the grid in 1D (default=101), by default 101
        returnGrids : bool, optional
            If True, return the grid objects (default=False), by default False
        derivRGrid : bool or evolveddiskdfGrid or evolveddiskdfHierarchicalGrid, optional
            If set to True, build a grid and use that to evaluate integrals of the derivatives of the DF; if set to a grid-objects (such as returned by this procedure), use this grid, by default None
        derivphiGrid : bool or evolveddiskdfGrid or evolveddiskdfHierarchicalGrid, optional
            If set to True, build a grid and use that to evaluate integrals of the derivatives of the DF; if set to a grid-objects (such as returned by this procedure), use this grid, by default None
        derivGridpoints : int, optional
            Number of points to use for the grid in 1D (default=101), by default 101
        derivHierarchgrid : bool, optional
            If True, use a hierarchical grid (default=False), by default False
        hierarchgrid : bool, optional
            If True, use a hierarchical grid (default=False), by default False
        nlevels : int, optional
            Number of hierarchical levels for the hierarchical grid, by default 2
        integrate_method : str, optional
            orbit.integrate method argument, by default "dopr54_c"

        Returns
        -------
        float or tuple
            Oort C at R,phi,t or tuple of Oort A at R,phi,t and grid objects

        Notes
        -----
        - 2011-10-16 - Written - Bovy (NYU)


        Calculate the Oort function K at (R,phi,t)

        Parameters
        ----------
        R : float
            Radius at which to calculate the moment (can be Quantity)
        phi : float, optional
            Azimuth (rad unless deg=True; can be Quantity), by default 0.0
        t : float or array, optional
            Time at which to evaluate the DF (can be a list or ndarray; if this is the case, list needs to be in descending order and equally spaced) (can be Quantity), by default 0.0
        surfacemass : float, optional
            If set use this pre-calculated surfacemass and mean rotational velocity, by default None
        meanvT : float, optional
            If set use this pre-calculated surfacemass and mean rotational velocity, by default None
        nsigma : float, optional
            Number of sigma to integrate the velocities over (based on an estimate, so be generous), by default None
        deg : bool, optional
            Azimuth is in degree (default=False); do not set this when giving phi as a Quantity, by default False
        epsrel : float, optional
            Scipy.integrate keywords (the integration calculates the ratio of this vmoment to that of the initial DF), by default 1.0e-02
        epsabs : float, optional
            Scipy.integrate keywords (the integration calculates the ratio of this vmoment to that of the initial DF), by default 1.0e-05
        grid : bool or evolveddiskdfGrid or evolveddiskdfHierarchicalGrid, optional
            If set to True, build a grid and use that to evaluate integrals; if set to a grid-objects (such as returned by this procedure), use this grid, by default None
        gridpoints : int, optional
            Number of points to use for the grid in 1D (default=101), by default 101
        returnGrids : bool, optional
            If True, return the grid objects (default=False), by default False
        derivRGrid : bool or evolveddiskdfGrid or evolveddiskdfHierarchicalGrid, optional
            If set to True, build a grid and use that to evaluate integrals of the derivatives of the DF; if set to a grid-objects (such as returned by this procedure), use this grid, by default None
        derivphiGrid : bool or evolveddiskdfGrid or evolveddiskdfHierarchicalGrid, optional
            If set to True, build a grid and use that to evaluate integrals of the derivatives of the DF; if set to a grid-objects (such as returned by this procedure), use this grid, by default None
        derivGridpoints : int, optional
            Number of points to use for the grid in 1D (default=101), by default 101
        derivHierarchgrid : bool, optional
            If True, use a hierarchical grid (default=False), by default False
        hierarchgrid : bool, optional
            If True, use a hierarchical grid (default=False), by default False
        nlevels : int, optional
            Number of hierarchical levels for the hierarchical grid, by default 2
        integrate_method : str, optional
            orbit.integrate method argument, by default "dopr54_c"

        Returns
        -------
        float or tuple
            Oort K at R,phi,t or tuple of Oort A at R,phi,t and grid objects

        Notes
        -----
        - 2011-10-16 - Written - Bovy (NYU)


Internal function to evaluate vmomentsurfacemass using a grid
        rather than direct integration


Internal function to grid the vDF at a given location


Internal function to evaluate vmomentsurfacemass using a
        hierarchical grid rather than direct integration,
        rather unnecessary


        Plot the velocity distribution.

        Parameters
        ----------
        tt : int, optional
            Time index. Default is 0.

        Returns
        -------
        None

        Other Parameters
        ----------------
        xrange : list
            Range of vRgrid.
        yrange : list
            Range of vTgrid.
        plotthis : array
            Array to be plotted.

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


        Plot the velocity distribution.

        Parameters
        ----------
        tt : int, optional
            Time index. Default is 0.
        vmax : float, optional
            Maximum value for the plot. Default is None.
        aspect : float, optional
            Aspect ratio of the plot. Default is None.
        extent : list, optional
            Extent of the plot. Default is None.

        Returns
        -------
        None

        Notes
        -----
        - 2011-06-27 - Written - Bovy (NYU).


        Turn off automatic returning of outputs in physical units.

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


        Turn on automatic returning of outputs in physical units.

        Parameters
        ----------
        ro : float or Quantity, optional
            Reference distance (kpc). If False, don't turn it on.
        vo : float or Quantity, optional
            Reference velocity (km/s). If False, don't turn it on.

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


        Evaluate the DF for a constant anisotropy Hernquist.

        Parameters
        ----------
        E : float
            The energy.
        L : float
            The angular momentum.

        Returns
        -------
        float
            The value of the DF.

        Notes
        -----
        - 2020-07-22 - Written - Lane (UofT)


Sample the angle eta which defines radial vs tangential velocities


        Calculate the energy portion of a constant-beta distribution function

        Parameters
        ----------
        E : float, numpy.ndarray, or Quantity
            The energy.

        Returns
        -------
        numpy.ndarray
            The value of the energy portion of the DF

        Notes
        -----
        - 2021-02-14 - Written - Bovy (UofT)


    Compute the radial velocity dispersion using the spherical Jeans equation

    Parameters
    ----------
    Pot : potential or list of potentials
        Gravitational potential; evaluated at R=r/sqrt(2),z=r/sqrt(2), sphericity not checked.
    r : float or Quantity
        Galactocentric radius
    dens : function, optional
        tracer density profile (function of r); if None, the density is assumed to be that corresponding to the potential
    beta : float or function, optional
        anisotropy; can be a constant or a function of r

    Returns
    -------
    float
        sigma_r(r)

    Notes
    -----
    - 2018-07-05 - Written - Bovy (UofT)


    Compute the line-of-sight velocity dispersion using the spherical Jeans equation

    Parameters
    ----------
    Pot : potential or list of potentials
        Gravitational potential; evaluated at R=r/sqrt(2),z=r/sqrt(2), sphericity not checked.
    R : float or Quantity
        Galactocentric projected radius
    dens : function, optional
        tracer density profile (function of r); if None, the density is assumed to be that corresponding to the potential
    surfdens : float or function, optional
        tracer surface density profile (value at R or function of R); if None, the surface density is assumed to be that corresponding to the density
    beta : float or function, optional
        anisotropy; can be a constant or a function of r
    sigma_r : float or function, optional
        if given, the solution of the spherical Jeans equation sigma_r(r) (used instead of solving the Jeans equation as part of this routine)

    Returns
    -------
    float
        sigma_los(R)

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


The part of the setup relating to the progenitor's orbit


The part of the setup related to calculating the stream/progenitor offset


If progIsTrack, the progenitor orbit that was passed to the
        streamdf initialization is the track at zero angle separation;
        this routine computes an actual progenitor position that gives
        the desired track given the parameters of the streamdf


        Calculate the misalignment between the progenitor's frequency
        and the direction along which the stream disrupts.

        Parameters
        ----------
        isotropic : bool, optional
            If True, return the misalignment assuming an isotropic action distribution.

        Returns
        -------
        float
            Misalignment in radians.

        Warnings
        --------
        In versions >1.3, the output unit of streamdf.misalignment has been changed to radian (from degree before).

        Notes
        -----
        - 2013-12-05 - Written - Bovy (IAS)
        - 2017-10-28 - Changed output unit to rad - Bovy (UofT)


        Calculate the ratio between the largest and 2nd-to-largest (in abs) eigenvalue of sqrt(dO/dJ^T V_J dO/dJ) (if this is big, a 1D stream will form)

        Parameters
        ----------
        isotropic : bool, optional
            If True, return the ratio assuming an isotropic action distribution (i.e., just of dO/dJ)

        Returns
        -------
        float
            Ratio between eigenvalues of fabs(dO / dJ)

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


        Estimate the time of disruption.

        Parameters
        ----------
        deltaAngle : float
            Spread in angle since disruption.

        Returns
        -------
        float or Quantity
            Time of disruption.

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


        Estimate the number of encounters with subhalos over the lifetime of this stream, using a formalism similar to that of Yoon et al. (2011)

        Parameters
        ----------
        venc : float, optional
            Count encounters with (relative) speeds less than this (relative radial velocity in cylindrical stream frame, unless yoon is True) (can be Quantity)
        sigma : float, optional
            Velocity dispersion of the DM subhalo population (can be Quantity)
        nsubhalo : float, optional
            Spatial number density of subhalos (can be Quantity)
        bmax : float, optional
            Maximum impact parameter (if larger than width of stream) (can be Quantity)
        yoon : bool, optional
            If True, use erroneous Yoon et al. formula

        Returns
        -------
        float
            Number of encounters

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


        Plot the stream track.

        Parameters
        ----------
        d1 : str, optional
            Plot this on the X axis ('x','y','z','R','phi','vx','vy','vz','vR','vt','ll','bb','dist','pmll','pmbb','vlos'). Default is 'x'.
        d2 : str, optional
            Plot this on the Y axis (same list as for d1). Default is 'z'.
        interp : bool, optional
            If True, use the interpolated stream track. Default is True.
        spread : int, optional
            If int > 0, also plot the spread around the track as spread x sigma. Default is 0.
        simple : bool, optional
            If True, use a simple estimate for the spread in perpendicular angle. Default is _USESIMPLE.
        *args : tuple
            Arguments passed to galpy.util.plot.plot.
        **kwargs : dict
            Keyword arguments passed to galpy.util.plot.plot.

        Returns
        -------
        None

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


        Plot the progenitor orbit.

        Parameters
        ----------
        d1 : str, optional
            Plot this on the X axis ('x','y','z','R','phi','vx','vy','vz','vR','vt','ll','bb','dist','pmll','pmbb','vlos'). Default is 'x'.
        d2 : str, optional
            Plot this on the Y axis (same list as for d1). Default is 'z'.
        scaleToPhysical : bool, optional
            If True, plot positions in kpc and velocities in km/s. Default is False.
        *args : tuple
            Arguments passed to `galpy.util.plot.plot`.
        **kwargs : dict
            Keyword arguments passed to `galpy.util.plot.plot`.

        Returns
        -------
        None

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


Parse the dimension to plot the stream track for


Parse the dimension to plot the progenitor orbit for


Determine the spread around the track


        Plot the comparison between the underlying model's dOmega_perp vs. dangle_r (line) and the track in (x,v)'s dOmega_perp vs. dangle_r (dots; explicitly calculating the track's action-angle coordinates)

        Parameters
        ----------
        **kwargs: dict
            galpy.util.plot.plot kwargs

        Returns
        -------
        None

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


Determine a good value for nTrackIterations based on the misalignment between stream and orbit; just based on some rough experience for now


Determine the track of the stream in real space


Determine the spread around the stream track, just sets matrices that describe the covariances


Determine the spread in the stream in observable coordinates


Build interpolations of the stream track


Build interpolations of the stream track in action-angle coordinates


        Convert the stream track to observational coordinates and store

        Parameters
        ----------
        ro : float or Quantity, optional
            Distance scale for translation into internal units (object-wide default.
        vo : float or Quantity, optional
            Velocity scale for translation into internal units (object-wide default.
        R0 : float or Quantity, optional
            Distance to the Galactic center  (object-wide default.
        Zsun : float or Quantity, optional
            Distance to the Galactic plane  (object-wide default.
        vsun : float or Quantity, optional
            Velocity of the Sun  (object-wide default.

        Returns
        -------
        None

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


For backward compatibility


        Find the closest point on the stream track to a given point

        Parameters
        ----------
        R,vR,vT,z,vz,phi : float
            Phase-space coordinates of the given point
        interp : bool, optional
            If True, return the index of the interpolated track
        xy : bool, optional
            If True, input is X,Y,Z,vX,vY,vZ in Galactocentric rectangular coordinates; if xy, some coordinates may be missing (given as None) and they will not be used
        usev : bool, optional
            If True, also use velocities to find the closest point

        Returns
        -------
        int
            Index into the track of the closest track point

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


        Find the closest point on the stream track to a given point in (l,b,...) coordinates

        Parameters
        ----------
        l : float
            Galactic longitude in degrees
        b : float
            Galactic latitude in degrees
        D : float
            Distance in kpc
        vlos : float
            Line-of-sight velocity in km/s
        pmll : float
            Proper motion in Galactic longitude in mas/yr
        pmbb : float
            Proper motion in Galactic latitude in mas/yr
        interp : bool, optional
            If True, return the closest index on the interpolated track (default is True)
        usev : bool, optional
            If True, also use the velocity components (default is False)

        Returns
        -------
        int
            Index of closest track point on the interpolated or not-interpolated track

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


        Find the closest point on the stream track to a given point in
        frequency-angle coordinates

        Parameters
        ----------
        Or : float
            Radial frequency
        Op : float
            Azimuthal frequency
        Oz : float
            Vertical frequency
        ar : float
            Radial angle
        ap : float
            Azimuthal angle
        az : float
            Vertical angle
        interp : bool, optional
            If True, return the index of the interpolated track (default is True)

        Returns
        -------
        int
            Index into the track of the closest track point

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


        Return the probability of a given parallel (frequency,angle) offset pair.

        Parameters
        ----------
        Opar : numpy.ndarray or Quantity
            Parallel frequency offset.
        apar : float or Quantity
            Parallel angle offset along the stream.
        tdisrupt : float, optional
            Time since the start of the simulation at which the stream is disrupted (in galpy time units). If None, the value set at the initialization of the object is used.

        Returns
        -------
        ndarray
            Probability of a given parallel (frequency,angle) offset pair.

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


        Calculate the density as a function of a parallel coordinate

        Parameters
        ----------
        dangle : float
            Parallel angle offset for this coordinate value
        coord : str, optional
            Coordinate to return the density in ('apar' [default],
            'll','ra','customra','phi')
        tdisrupt : float, optional
            Time since the disruption to calculate the density at (in galpy
            natural units). If None, use the current time (default: None).

        Returns
        -------
        float
            Density(angle)

        Notes
        -----
        - 2015-11-17 - Written - Bovy (UofT)


The raw density as a function of parallel angle


        Calculate the length of the stream.

        Parameters
        ----------
        threshold : float, optional
            Threshold down from the density near the progenitor at which to define the 'end' of the stream. Default is 0.2.
        phys : bool, optional
            If True, return the length in physical kpc. Default is False.
        ang : bool, optional
            If True, return the length in sky angular arc length in degree. Default is False.
        tdisrupt : float, optional
            Time since disruption in natural units. Default is None.

        Returns
        -------
        float
            Length (rad for parallel angle; kpc for physical length; deg for sky arc length).

        Notes
        -----
        - 2015-12-22 - Written - Bovy (UofT)


        Calculate the mean frequency as a function of angle, assuming a uniform time distribution up to a maximum time.

        Parameters
        ----------
        dangle : float
            Angle offset.
        oned : bool, optional
            If True, return the 1D offset from the progenitor (along the direction of disruption). Default is False.
        offset_sign : None, optional
            Sign of the frequency offset. Default is None.
        tdisrupt : float, optional
            Maximum time. Default is None.

        Returns
        -------
        float or Quantity
            Mean Omega.

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


        Calculate the 1D sigma in frequency as a function of angle, assuming a uniform time distribution up to a maximum time

        Parameters
        ----------
        dangle : float
            Angle offset

        Returns
        -------
        float or Quantity
            Sigma Omega

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


        Return the probability of a given stripping time at a given angle along the stream.

        Parameters
        ----------
        t : numpy.ndarray
            Stripping time.
        dangle : float
            Angle offset along the stream.

        Returns
        -------
        numpy.ndarray
            p(td|dangle)

        Notes
        -----
        - 2013-12-05 - Written - Bovy (IAS).


        Calculate the mean stripping time at a given angle.

        Parameters
        ----------
        dangle : float
            Angle offset along the stream.

        Returns
        -------
        float or Quantity
            Mean stripping time at this dangle.

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


        Calculate the dispersion in the stripping times at a given angle.

        Parameters
        ----------
        dangle : float
            Angle offset along the stream.

        Returns
        -------
        float or Quantity
            Dispersion in the stripping times at this angle.

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


        Return the probability of a given perpendicular angle at a given angle along the stream.

        Parameters
        ----------
        angleperp : numpy.ndarray
            Perpendicular angle.
        dangle : float
            Angle offset along the stream.
        smallest : bool, optional
            Calculate for smallest eigenvalue direction rather than for middle. Default is False.

        Returns
        -------
        numpy.ndarray
            p(angle_perp|dangle)

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


        Calculate the mean perpendicular angle at a given angle.

        Parameters
        ----------
        dangle : float
            Angle offset along the stream.
        smallest : bool, optional
            Calculate for smallest eigenvalue direction rather than for middle. Default is False.

        Returns
        -------
        float or Quantity
            Mean perpendicular angle.

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


        Calculate the dispersion in the perpendicular angle at a given angle.

        Parameters
        ----------
        dangle : float
            Angle offset along the stream.
        assumeZeroMean : bool, optional
            If True, assume that the mean is zero (should be). Default is True.
        smallest : bool, optional
            Calculate for smallest eigenvalue direction rather than for middle. Default is False.
        simple : bool, optional
            If True, return an even simpler estimate. Default is False.

        Returns
        -------
        float or Quantity
            Dispersion in the perpendicular angle at this angle.

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


        Return action-angle coordinates for a point based on the linear approximation around the stream track

        Parameters
        ----------
        R : float
            Radius
        vR : float
            Radial velocity
        vT : float
            Tangential velocity
        z : float
            Vertical height
        vz : float
            Vertical velocity
        phi : float
            Azimuth
        interp : bool, optional
            If True, use the interpolated track. Default is True.
        cindx : int, optional
            Index of the closest point on the (interpolated) stream track. If not given, determined from the dimensions given.

        Returns
        -------
        tuple
            (Or,Op,Oz,ar,ap,az)

        Notes
        -----
        - 2013-12-03 - Written - Bovy (IAS)
        - 2015-11-12 - Added weighted sum of two nearest Jacobians to help with smoothness - Bovy (UofT)


        Return R,vR,... coordinates for a point based on the linear approximation around the stream track

        Parameters
        ----------
        Or : float
            Radial action
        Op : float
            Azimuthal action
        Oz : float
            Vertical action
        ar : float
            Radial angle
        ap : float
            Azimuthal angle
        az : float
            Vertical angle
        interp : bool, optional
            If True, use the interpolated track. Default is True.

        Returns
        -------
        tuple
            (R,vR,vT,z,vz,phi)

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


        Prepare stream data for the __call__ method.

        Parameters
        ----------
        *args : tuple
            Either:
            a) R,vR,vT,z,vz,phi ndarray [nobjects]
            b) (Omegar,Omegaphi,Omegaz,angler,anglephi,anglez) tuple if aAInput
                where:
                * Omegar - radial frequency
                * Omegaphi - azimuthal frequency
                * Omegaz - vertical frequency
                * angler - radial angle
                * anglephi - azimuthal angle
                * anglez - vertical angle
            c) Orbit instance or list thereof
        log : bool, optional
            If True, return the natural log. Default is True.
        aaInput : bool, optional
            If True, option b above. Default is False.

        Returns
        -------
        tuple
            Tuple containing two arrays (dOmega, dangle), each of shape [3, nobj], wrt the progenitor.

        Notes
        -----
        - 2013-12-04 - Written - Bovy (IAS).


Helper function to parse the arguments to the __call__ and related functions,
        return [6,nobj] array of frequencies (:3) and angles (3:)


        Evaluate the distribution function (DF), marginalizing over some directions, in Galactocentric rectangular coordinates (or in observed l,b,D,vlos,pmll,pmbb) coordinates)

        Parameters
        ----------
        xy : numpy.ndarray
            Phase-space point [X,Y,Z,vX,vY,vZ]; the distribution of the dimensions set to None is returned.
        interp : bool, optional
            If True, use the interpolated stream track. Default is True.
        cindx : int, optional
            Index of the closest point on the (interpolated) stream track if not given, determined from the dimensions given.
        nsigma : int, optional
            Number of sigma to marginalize the DF over (approximate sigma). Default is 3.
        ngl : int, optional
            Order of Gauss-Legendre integration. Default is 5.
        lb : bool, optional
            If True, xy contains [l,b,D,vlos,pmll,pmbb] in [deg,deg,kpc,km/s,mas/yr,mas/yr] and the marginalized PDF in these coordinates is returned. Default is False.
        ro : float or Quantity, optional
            Distance scale for translation into internal units (object-wide default).
        vo : float or Quantity, optional
            Velocity scale for translation into internal units (object-wide default).
        R0 : float or Quantity, optional
            Distance to the Galactic center (object-wide default).
        Zsun : float or Quantity, optional
            Sun's height above the plane (object-wide default).
        vsun : float or Quantity, optional
            Sun's motion in cylindrical coordinates (object-wide default).

        Returns
        -------
        ndarray
            Value of DF.

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


        Return the mean and variance of a Gaussian approximation to the stream DF at a given phase-space point in Galactocentric rectangular coordinates (distribution is over missing directions)

        Parameters
        ----------
        xy : numpy.ndarray
            Phase-space point [X,Y,Z,vX,vY,vZ]; the distribution of the dimensions set to None is returned.
        interp : bool, optional
            If True, use the interpolated stream track. Default is True.
        cindx : int, optional
            Index of the closest point on the (interpolated) stream track if not given, determined from the dimensions given.
        lb : bool, optional
            If True, xy contains [l,b,D,vlos,pmll,pmbb] in [deg,deg,kpc,km/s,mas/yr,mas/yr] and the Gaussian approximation in these coordinates is returned. Default is False.

        Returns
        -------
        tuple
            (mean,variance) of the approximate Gaussian DF for the missing directions in xy.

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


        Sample from the DF.

        Parameters
        ----------
        n : int
            Number of points to return.
        returnaAdt : bool, optional
            If True, return (Omega,angle,dt). Default is False.
        returndt : bool, optional
            If True, also return the time since the star was stripped. Default is False.
        interp : object-wide default, optional
            Use interpolation of the stream track. Default is object-wide default.
        xy : bool, optional
            If True, return Galactocentric rectangular coordinates. Default is False.
        lb : bool, optional
            If True, return Galactic l,b,d,vlos,pmll,pmbb coordinates. Default is False.

        Returns
        -------
        ndarray or tuple
            (R,vR,vT,z,vz,phi) of points on the stream in 6,N array. Or (X,Y,Z,vX,vY,vZ) if xy is True. Or (l,b,d,vlos,pmll,pmbb) if lb is True. Or (Omega,angle,dt) if returnaAdt is True. If returndt is set, also return the time since the star was stripped.

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


Sampling frequencies, angles, and times part of sampling


        Sample the time since the progenitor was stripped

        Parameters
        ----------
        n : int
            Number of points to return

        Returns
        -------
        ndarray
            Array of n stripping times

        Notes
        -----
        - 2015-09-16 - Written - Bovy (UofT)


sigAngle input may either be a function that returns the dispersion in
    perpendicular angle as a function of parallel angle, or a value


    Calculate the Jacobian d(J,theta)/d(x,v)

    Parameters
    ----------
    xv: numpy.ndarray
        Either:
            1) [R,vR,vT,z,vz,phi]
            2) [l,b,D,vlos,pmll,pmbb] (if lb=True, see below)
            3) list/array of 6 numbers that can be transformed into (normalized) R,vR,vT,z,vz,phi using coordFunc
    aA: actionAngle instance
    dxv: float, optional
        Infinitesimal to use (rescaled for lb, so think fractionally))
    freqs: bool, optional
        If True, go to frequencies rather than actions
    dOdJ: bool, optional
        Actually calculate d Frequency / d action
    actionsFreqsAngles: bool, optional
        If True, calculate d(action,freq.,angle)/d (xv)
    lb: bool, optional
        If True, start with (l,b,D,vlos,pmll,pmbb) in (deg,deg,kpc,km/s,mas/yr,mas/yr)
    vo: float, optional
        Circular velocity to normalize with when lb=True
    ro: float, optional
        Galactocentric radius to normalize with when lb=True
    R0: float, optional
        Galactocentric radius of the Sun (kpc)
    Zsun: float, optional
        Sun's height above the plane (kpc)
    vsun: list, optional
        Sun's motion in cylindrical coordinates (vR positive away from center)
    coordFunc: function, optional
        If set, this is a function that takes xv and returns R,vR,vT,z,vz,phi in normalized units (units where vc=1 at r=1 if the potential is normalized that way, for example)
    _initacfs: list, optional
        If set, this is a list of the actions, frequencies, and angles at xv

    Returns
    -------
    jac: numpy.ndarray
        Jacobian matrix

    Notes
    -----
    - 2013-11-25 - Written - Bovy (IAS)


        Return the format-strings to use when writing the parameters of this profile.

        Returns
        -------
        tuple of str
            Tuple of format-strings to use for each parameter in self._params.

        Notes
        -----
        This function defaults to '%6.4f' for each parameter in self._params.

        - 2010-03-28 - Written - Bovy (NYU)


        Return a tuple of parameters of this profile, to create filenames.

        Returns
        -------
        tuple
            Tuple of parameters (given to % ...).

        Notes
        -----
        - 2010-03-28 - Written - Bovy


        Return the surface density profile at this R.

        Parameters
        ----------
        R : float
            Galactocentric radius (/ro).
        log : bool, optional
            If True, return the log (default: False).

        Returns
        -------
        float
            Sigma(R)

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


        Return the radial velocity variance at this R.

        Parameters
        ----------
        R : float
            Galactocentric radius (/ro).
        log : bool, optional
            If True, return the log (default: False).

        Returns
        -------
        float
            sigma^2(R).

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


        Return the surface density profile at this R.

        Parameters
        ----------
        R : float
            Galactocentric radius (/ro).
        log : bool, optional
            If True, return the log (default: False).

        Returns
        -------
        Sigma(R) : float
            Surface density profile at this R.

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


        Return the derivative wrt R of the surface density profile at this R.

        Parameters
        ----------
        R : float
            Galactocentric radius (/ro).
        log : bool, optional
            If True, return the derivative of the log (default: False).

        Returns
        -------
        float
            Sigma'(R) or (log Sigma(r) )'.

        Notes
        -----
        - 2010-03-26 - Written - Bovy (NYU).


        Return the derivative wrt R of the sigma_R^2 profile at this R

        Parameters
        ----------
        R : float
            Galactocentric radius (/ro)
        log : bool, optional
            If True, return the derivative of the log (default: False)

        Returns
        -------
        float
            Sigma_R^2'(R) or (log Sigma_R^2(r) )'

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


        Calculate the energy portion of a Hernquist distribution function

        Parameters
        ----------
        E : float, numpy.ndarray, or Quantity
            The energy.

        Returns
        -------
        float or numpy.ndarray
            The value of the energy portion of the DF

        Notes
        -----
        - 2020-07-22 - Written


Decorator to check the range of interpolated kicks


        Return the probability of a given parallel (frequency,angle) offset pair.

        Parameters
        ----------
        Opar : numpy.ndarray or Quantity
            Parallel frequency offset.
        apar : float or Quantity
            Parallel angle offset along the stream.

        Returns
        -------
        numpy.ndarray
            Probability of a given parallel (frequency,angle) offset pair.

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


The raw density as a function of parallel angle,
        approx= use faster method that directly integrates the spline
        representation


Compute the density as a function of parallel angle using the
        spline representation + approximations


Contribution from non-linear spline terms


Calculate all of the polynomial x Gaussian integrals occurring
        in the higher-order terms, recursively


        Return the approximate minimum parallel frequency at a given angle

        Parameters
        ----------
        dangle : float
            Parallel angle
        tdisrupt : float, optional
            Disruption time (default is the value passed at initialization)
        _return_raw : bool, optional
            If True, return the index of the minimum frequency and the value of the minimum frequency (default is False)

        Returns
        -------
        float or tuple
            Minimum frequency that gets to this parallel angle or a tuple with the index of the minimum frequency and the value of the minimum frequency

        Notes
        -----
        - 2015-12-28 - Written - Bovy (UofT)


        Calculate the mean frequency as a function of angle, assuming a uniform time distribution up to a maximum time.

        Parameters
        ----------
        dangle : float
            Angle offset.
        oned : bool, optional
            If True, return the 1D offset from the progenitor (along the direction of disruption). Default is False.
        tdisrupt : float, optional
            Maximum time. Default is None.
        approx : bool, optional
            If True, compute the mean Omega by direct integration of the spline representation. Default is True.
        higherorder : object, optional
            Higher-order spline terms in the approximate computation. Default is object-wide default higherorderTrack.

        Returns
        -------
        float
            Mean Omega.

        Notes
        -----
        - 2015-11-17 - Written - Bovy (UofT)


Compute the numerator going into meanOmega using the direct integration of the spline representation


Build interpolations of the stream track near the kick


Build interpolations of the stream track near the impact in action-angle coordinates


Function that sets up the transformation between (x,v) and (O,theta)


Setup an Orbit instance that's the progenitor integrated backwards


Sampling frequencies, angles, and times part of sampling, for stream with gap


    Calculate the delta velocity to due an encounter with a Plummer sphere in the impulse approximation; allows for arbitrary velocity vectors, but y is input as the position along the stream

    Parameters
    ----------
    v : numpy.ndarray
        velocity of the stream (nstar,3)
    y : numpy.ndarray
        position along the stream (nstar)
    b : float
        impact parameter
    w : numpy.ndarray
        velocity of the Plummer sphere (3)
    GM : float
        mass of the Plummer sphere (in natural units)
    rs : float
        size of the Plummer sphere

    Returns
    -------
    numpy.ndarray
        velocity kick deltav (nstar,3)

    Notes
    -----
    - 2015-04-30 - Written based on Erkal's expressions - Bovy (IAS)


    Calculate the delta velocity to due an encounter with a Plummer sphere in the impulse approximation; allows for arbitrary velocity vectors, and arbitrary position along the stream

    Parameters
    ----------
    v : numpy.ndarray
        velocity of the stream (nstar,3)
    x : numpy.ndarray
        position along the stream (nstar,3)
    b : float
        impact parameter
    w : numpy.ndarray
        velocity of the Plummer sphere (3)
    x0 : numpy.ndarray
        point of closest approach
    v0 : numpy.ndarray
        velocity of point of closest approach
    GM : float
        mass of the Plummer sphere (in natural units)
    rs : float
        size of the Plummer sphere

    Returns
    -------
    numpy.ndarray
        velocity kick deltav (nstar,3)

    Notes
    -----
    - 2015-05-04 - Written based on above - Sanders (Cambridge)


Computes X function from equations (33) & (34) of Hernquist (1990)


    Calculate the delta velocity to due an encounter with a Hernquist sphere in the impulse approximation; allows for arbitrary velocity vectors, but y is input as the position along the stream

    Parameters
    ----------
    v : numpy.ndarray
        velocity of the stream (nstar,3)
    y : numpy.ndarray
        position along the stream (nstar)
    b : float
        impact parameter
    w : numpy.ndarray
        velocity of the Hernquist sphere (3)
    GM : float
        mass of the Hernquist sphere (in natural units)
    rs : float
        size of the Hernquist sphere

    Returns
    -------
    numpy.ndarray
        velocity kick deltav (nstar,3)

    Notes
    -----
    - 2015-08-13 - Written using Wyn Evans calculation - Sanders (Cambridge)


    Calculate the delta velocity to due an encounter with a Hernquist sphere in the impulse approximation; allows for arbitrary velocity vectors, and arbitrary position along the stream

    Parameters
    ----------
    v : numpy.ndarray
        velocity of the stream (nstar,3)
    x : numpy.ndarray
        position along the stream (nstar,3)
    b : float
        impact parameter
    w : numpy.ndarray
        velocity of the Hernquist sphere (3)
    x0 : numpy.ndarray
        point of closest approach
    v0 : numpy.ndarray
        velocity of point of closest approach
    GM : float
        mass of the Hernquist sphere (in natural units)
    rs : float
        size of the Hernquist sphere

    Returns
    -------
    numpy.ndarray
        velocity kick deltav (nstar,3)

    Notes
    -----
    - 2015-08-13 - Written using Wyn Evans calculation - Sanders (Cambridge)


    Calculate the delta velocity to due an encounter with a general spherical potential in the impulse approximation; allows for arbitrary velocity vectors, but y is input as the position along the stream

    Parameters
    ----------
    v : numpy.ndarray
        velocity of the stream (nstar,3)
    y : numpy.ndarray
        position along the stream (nstar)
    b : float
        impact parameter
    w : numpy.ndarray
        velocity of the subhalo (3)
    pot : Potential object or list thereof
        Potential object or list thereof (should be spherical)

    Returns
    -------
    numpy.ndarray
        velocity kick deltav (nstar,3)

    Notes
    -----
    - 2015-05-04 - Written - Sanders (Cambridge)
    - 2015-06-15 - Tweak to use galpy' potential objects - Bovy (IAS)


    Calculate the delta velocity to due an encounter with a general spherical potential in the impulse approximation; allows for arbitrary velocity vectors, and arbitrary position along the stream

    Parameters
    ----------
    v : numpy.ndarray
        velocity of the stream (nstar,3)
    x : numpy.ndarray
        position along the stream (nstar,3)
    b : float
        impact parameter
    w : numpy.ndarray
        velocity of the subhalo (3)
    x0 : numpy.ndarray
        point of closest approach
    v0 : numpy.ndarray
        velocity of point of closest approach
    pot : Potential object or list thereof
        Potential object or list thereof (should be spherical)

    Returns
    -------
    numpy.ndarray
        velocity kick deltav (nstar,3)

    Notes
    -----
    - 2015-05-04 - Written - Sanders (Cambridge)
    - 2015-06-15 - Tweak to use galpy' potential objects - Bovy (IAS)


    Calculate the delta velocity to due an encounter with a general spherical potential NOT in the impulse approximation by integrating each particle in the underlying galactic potential; allows for arbitrary velocity vectors and arbitrary shaped streams.

    Parameters
    ----------
    v : numpy.ndarray
        velocity of the stream (nstar,3)
    x : numpy.ndarray
        position along the stream (nstar,3)
    b : float
        impact parameter
    w : numpy.ndarray
        velocity of the subhalo (3)
    x0 : numpy.ndarray
        position of closest approach
    v0 : numpy.ndarray
        velocity of point of closest approach
    pot : Potential object or list thereof
        Potential object or list thereof (should be spherical)
    tmax : float
        maximum integration time
    galpot : Potential object or list thereof
        galpy Potential object or list thereof
    tmaxfac : float
        multiple of rs/fabs(w - v0) to use for time integration interval
    nsamp : int
        number of forward integration points
    integrate_method : str
        orbit integrator to use (see Orbit.integrate)

    Returns
    -------
    numpy.ndarray
        velocity kick deltav (nstar,3)

    Notes
    -----
    - 2015-08-17 - Written - Sanders (Cambridge)


    Calculate the delta velocity to due an encounter with a moving Plummer sphere and galactic potential relative to just in galactic potential by integrating each particle in the underlying galactic potential; allows for arbitrary velocity vectors and arbitrary shaped streams.

    Parameters
    ----------
    v : numpy.ndarray
        velocity of the stream (nstar,3)
    x : numpy.ndarray
        position along the stream (nstar,3)
    b : float
        impact parameter
    w : numpy.ndarray
        velocity of the subhalo (3)
    x0 : numpy.ndarray
        position of closest approach
    v0 : numpy.ndarray
        velocity of point of closest approach
    galpot : Potential object or list thereof
        galpy Potential object or list thereof
    GM : float
        mass of Plummer
    rs : float
        scale of Plummer
    tmaxfac : float
        multiple of rs/fabs(w - v0) to use for time integration interval
    N : int
        number of forward integration points
    integrate_method : str
        orbit integrator to use (see Orbit.integrate)

    Returns
    -------
    numpy.ndarray
        velocity kick deltav (nstar,3)

    Notes
    -----
    - 2015-08-18 - Written - Sanders (Cambridge)


    Calculate the delta velocity to due an encounter with a Plummer-softened stream in the impulse approximation; allows for arbitrary velocity vectors, but y is input as the position along the stream

    Parameters
    ----------
    v : numpy.ndarray
        velocity of the stream (nstar,3)
    y : numpy.ndarray
        position along the stream (nstar)
    b : float
        impact parameter
    w : numpy.ndarray
        velocity of the Plummer sphere (3)
    GSigma : function
        surface density of the Plummer-softened stream (in natural units); should be a function of time
    rs : float
        size of the Plummer sphere
    tmin : float
        minimum time to consider for GSigma (need to be set)
    tmax : float
        maximum time to consider for GSigma (need to be set)

    Returns
    -------
    numpy.ndarray
        velocity kick deltav (nstar,3)

    Notes
    -----
    - 2015-11-14 - Written - Bovy (UofT)


    Calculate the delta velocity to due an encounter with a Plummer-softened stream in the impulse approximation; allows for arbitrary velocity vectors, and arbitrary position along the stream; velocities and positions are assumed to lie along an orbit

    Parameters
    ----------
    v : numpy.ndarray
        velocity of the stream (nstar,3)
    x : numpy.ndarray
        position along the stream (nstar,3)
    t : numpy.ndarray
        times at which (v,x) are reached, wrt the closest impact t=0 (nstar)
    b : float
        impact parameter
    w : numpy.ndarray
        velocity of the Plummer sphere (3)
    x0 : numpy.ndarray
        point of closest approach
    v0 : numpy.ndarray
        velocity of point of closest approach
    GSigma : function
        surface density of the Plummer-softened stream (in natural units); should be a function of time
    rs : float
        size of the Plummer sphere
    galpot : Potential object or list thereof
        galpy Potential object or list thereof
    tmin : float
        minimum time to consider for GSigma (need to be set)
    tmax : float
        maximum time to consider for GSigma (need to be set)

    Returns
    -------
    numpy.ndarray
        velocity kick deltav (nstar,3)

    Notes
    -----
    - 2015-11-14 - Written - Bovy (UofT)


        Calculate the energy portion of a DF computed using the Eddington inversion

        Parameters
        ----------
        E : float or Quantity
            The energy.

        Returns
        -------
        fE : ndarray
            The value of the energy portion of the DF.

        Notes
        -----
        - 2021-02-04 - Written - Bovy (UofT)


        Estimate the exponential scale length at R.

        Parameters
        ----------
        R : float or Quantity
            Galactocentric radius.
        z : float or Quantity, optional
            Height (default: 0 pc).
        dR : float or Quantity, optional
            Range in R to use.
        **kwargs
            Density kwargs.

        Returns
        -------
        float or Quantity
            Estimated hR.

        Notes
        -----
        - 2012-09-11 - Written - Bovy (IAS)
        - 2013-01-28 - Re-written - Bovy


        Estimate the exponential scale height at R.

        Parameters
        ----------
        R : float or Quantity
            Galactocentric radius.
        z : float or Quantity
            Height above the Galactic plane.
        dz : float or Quantity, optional
            z range to use.
        **kwargs
            density kwargs.

        Returns
        -------
        float or Quantity
            Estimated hz.

        Notes
        -----
        - 2012-08-30 - Written - Bovy (IAS)
        - 2013-01-28 - Re-written - Bovy


        Estimate the exponential scale length of the radial dispersion at R.

        Parameters
        ----------
        R : float or Quantity
            Galactocentric radius.
        z : float or Quantity, optional
            Height (default: 0 pc).
        dR : float or Quantity, optional
            Range in R to use.
        **kwargs
            Density kwargs.

        Returns
        -------
        float or Quantity
            Estimated hsR.

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


        Estimate the exponential scale length of the vertical dispersion at R.

        Parameters
        ----------
        R : float or Quantity
            Galactocentric radius.
        z : float or Quantity, optional
            Height (default: 0 pc).
        dR : float or Quantity, optional
            Range in R to use.
        **kwargs
            Density kwargs.

        Returns
        -------
        float or Quantity
            Estimated hsz.

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


        Calculate the vertically-integrated surface density.

        Parameters
        ----------
        R : float or Quantity
            Galactocentric radius.
        nz : int, optional
            Number of zs to use to estimate. Default is 7.
        zmax : float or Quantity, optional
            Maximum z to use. Default is 1.0.
        fixed_quad : bool, optional
            If True (default), use Gauss-Legendre integration.
        fixed_order : int, optional
            Order of GL integration to use. Default is 8.
        **kwargs : dict
            Density kwargs.

        Returns
        -------
        float or Quantity
            Surface density at R.

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


        Calculate the an arbitrary moment of the velocity distribution at R times the density

        Parameters
        ----------
        R : float
            radius at which to calculate the moment(/ro)
        z : float
            height at which to calculate the moment(/ro)
        n : int
            vR^n
        m : int
            vT^m
        o : int
            vz^o
        nsigma : int, optional
            number of sigma to integrate the vR and vz velocities over (when doing explicit numerical integral; default: 4)
        vTmax : float, optional
            upper limit for integration over vT (default: 1.5)
        mc : bool, optional
            if True, calculate using Monte Carlo integration
        nmc : int, optional
            if mc, use nmc samples
        gl : bool, optional
            use Gauss-Legendre
        _returngl : bool, optional
            if True, return the evaluated DF
        _return_actions : bool, optional
            if True, return the evaluated actions (does not work with _returngl currently)
        _return_freqs : bool, optional
            if True, return the evaluated frequencies and rg (does not work with _returngl currently)

        Returns
        -------
        float
            <vR^n vT^m  x density> at R,z (no support for units)

        Notes
        -----
        - 2012-08-06 - Written - Bovy (IAS@MPIA)


Non-physical version of vmomentdensity, otherwise the same


        Calculate the an arbitrary moment of an action of the velocity distribution at R times the surfacmass.

        Parameters
        ----------
        R : float
            radius at which to calculate the moment(/ro)
        z : float
            height at which to calculate the moment(/ro)
        n : int
            jr^n
        m : int
            lz^m
        o : int
            jz^o
        nsigma : int, optional
            Number of sigma to integrate the velocities over (when doing explicit numerical integral). Default is None.
        mc : bool, optional
            If True, calculate using Monte Carlo integration. Default is False.
        nmc : int, optional
            If mc is True, use nmc samples. Default is None.

        Returns
        -------
        float or Quantity
            <jr^n lz^m jz^o  x density> at R (no support for units)

        Notes
        -----
        - 2012-08-09 - Written - Bovy (IAS@MPIA)


Non-physical version of jmomentdensity, otherwise the same


        Calculate the density at R,z by marginalizing over velocity.

        Parameters
        ----------
        R : float or Quantity
            Radius at which to calculate the density.
        z : float or Quantity
            Height at which to calculate the density.
        nsigma : float, optional
            Number of sigma to integrate the velocities over.
        mc : bool, optional
            If True, calculate using Monte Carlo integration.
        nmc : int, optional
            If mc, use nmc samples.
        gl : bool, optional
            If True, calculate using Gauss-Legendre integration.
        ngl : int, optional
            If gl, use ngl-th order Gauss-Legendre integration for each dimension.
        **kwargs : dict, optional
            scipy.integrate.tplquad kwargs epsabs and epsrel.

        Returns
        -------
        float
            Density at (R,z).

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


        Calculate sigma_R^2 by marginalizing over velocity.

        Parameters
        ----------
        R : float or Quantity
            Radius at which to calculate this.
        z : float or Quantity
            Height at which to calculate this.
        nsigma : int, optional
            Number of sigma to integrate the velocities over.
        mc : bool, optional
            If True, calculate using Monte Carlo integration.
        nmc : int, optional
            If mc, use nmc samples.
        gl : bool, optional
            If True, calculate using Gauss-Legendre integration.
        ngl : int, optional
            If gl, use ngl-th order Gauss-Legendre integration for each dimension.
        **kwargs : dict, optional
            scipy.integrate.tplquad kwargs epsabs and epsrel.

        Returns
        -------
        float
            sigma_R^2.

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


        Calculate sigma_RZ^2 by marginalizing over velocity.

        Parameters
        ----------
        R : float or Quantity
            Radius at which to calculate this.
        z : float or Quantity
            Height at which to calculate this.
        nsigma : int, optional
            Number of sigma to integrate the velocities over.
        mc : bool, optional
            If True, calculate using Monte Carlo integration.
        nmc : int, optional
            If mc, use nmc samples.
        gl : bool, optional
            If True, calculate using Gauss-Legendre integration.
        ngl : int, optional
            If gl, use ngl-th order Gauss-Legendre integration for each dimension.
        **kwargs
            scipy.integrate.tplquad kwargs epsabs and epsrel.

        Returns
        -------
        float
            sigma_Rz^2.

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


        Calculate the tilt of the velocity ellipsoid by marginalizing over velocity.

        Parameters
        ----------
        R : float or Quantity
            Radius at which to calculate this.
        z : float or Quantity
            Height at which to calculate this.
        nsigma : int, optional
            Number of sigma to integrate the velocities over.
        mc : bool, optional
            If True, calculate using Monte Carlo integration.
        nmc : int, optional
            If mc, use nmc samples.
        gl : bool, optional
            If True, calculate using Gauss-Legendre integration.
        ngl : int, optional
            If gl, use ngl-th order Gauss-Legendre integration for each dimension.

        Returns
        -------
        float
            Tilt in radians.

        Notes
        -----
        - 2012-12-23 - Written - Bovy (IAS)
        - 2017-10-28 - Changed return unit to rad - Bovy (UofT)


        Calculate sigma_z^2 by marginalizing over velocity.

        Parameters
        ----------
        R : float or Quantity
            Radius at which to calculate this.
        z : float or Quantity
            Height at which to calculate this.
        nsigma : int, optional
            Number of sigma to integrate the velocities over.
        mc : bool, optional
            If True, calculate using Monte Carlo integration.
        nmc : int, optional
            If mc, use nmc samples.
        gl : bool, optional
            If True, calculate using Gauss-Legendre integration.
        ngl : int, optional
            If gl, use ngl-th order Gauss-Legendre integration for each dimension.
        **kwargs : dict, optional
            scipy.integrate.tplquad kwargs epsabs and epsrel.

        Returns
        -------
        float
            sigma_z^2.

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


        Calculate the mean rotational velocity by marginalizing over velocity.

        Parameters
        ----------
        R : float or Quantity
            Radius at which to calculate this.
        z : float or Quantity
            Height at which to calculate this.
        nsigma : float, optional
            Number of sigma to integrate the velocities over.
        mc : bool, optional
            If True, calculate using Monte Carlo integration.
        nmc : int, optional
            If mc, use nmc samples.
        gl : bool, optional
            If True, calculate using Gauss-Legendre integration.
        ngl : int, optional
            If gl, use ngl-th order Gauss-Legendre integration for each dimension.
        **kwargs : dict, optional
            scipy.integrate.tplquad kwargs epsabs and epsrel.

        Returns
        -------
        float
            Mean rotational velocity.

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


        Calculate the mean radial velocity by marginalizing over velocity.

        Parameters
        ----------
        R : float or Quantity
            Radius at which to calculate this.
        z : float or Quantity
            Height at which to calculate this.
        nsigma : float, optional
            Number of sigma to integrate the velocities over.
        mc : bool, optional
            If True, calculate using Monte Carlo integration.
        nmc : int, optional
            If mc, use nmc samples.
        gl : bool, optional
            If True, calculate using Gauss-Legendre integration.
        ngl : int, optional
            If gl, use ngl-th order Gauss-Legendre integration for each dimension.
        **kwargs : dict, optional
            scipy.integrate.tplquad kwargs epsabs and epsrel.

        Returns
        -------
        float
            Mean radial velocity.

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


        Calculate the mean vertical velocity by marginalizing over velocity.

        Parameters
        ----------
        R : float or Quantity
            Radius at which to calculate this.
        z : float or Quantity
            Height at which to calculate this.
        nsigma : float, optional
            Number of sigma to integrate the velocities over.
        mc : bool, optional
            If True, calculate using Monte Carlo integration.
        nmc : int, optional
            If mc, use nmc samples.
        gl : bool, optional
            If True, calculate using Gauss-Legendre integration.
        ngl : int, optional
            If gl, use ngl-th order Gauss-Legendre integration for each dimension.
        **kwargs : dict, optional
            scipy.integrate.tplquad kwargs epsabs and epsrel.

        Returns
        -------
        float
            Mean vertical velocity

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


        Calculate sigma_T^2 by marginalizing over velocity.

        Parameters
        ----------
        R : float or Quantity
            Radius at which to calculate this.
        z : float or Quantity
            Height at which to calculate this.
        nsigma : int, optional
            Number of sigma to integrate the velocities over.
        mc : bool, optional
            If True, calculate using Monte Carlo integration.
        nmc : int, optional
            If mc is True, use nmc samples.
        gl : bool, optional
            If True, calculate using Gauss-Legendre integration.
        ngl : int, optional
            If gl is True, use ngl-th order Gauss-Legendre integration for each dimension.
        **kwargs
            scipy.integrate.tplquad kwargs epsabs and epsrel.

        Returns
        -------
        float
            sigma_T^2.

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


        Calculate the mean radial action by marginalizing over velocity

        Parameters
        ----------
        R : float or Quantity
            Radius at which to calculate this
        z : float or Quantity
            Height at which to calculate this
        nsigma : float, optional
            Number of sigma to integrate the velocities over
        mc : bool, optional
            If True, calculate using Monte Carlo integration
        nmc : int, optional
            If mc, use nmc samples
        **kwargs : dict
            scipy.integrate.tplquad kwargs epsabs and epsrel

        Returns
        -------
        float
            Mean jr

        Notes
        -----
        - 2012-08-09 - Written - Bovy (IAS@MPIA)


        Calculate the mean angular momentum by marginalizing over velocity.

        Parameters
        ----------
        R : float or Quantity
            Radius at which to calculate this.
        z : float or Quantity
            Height at which to calculate this.
        nsigma : float, optional
            Number of sigma to integrate the velocities over.
        mc : bool, optional
            If True, calculate using Monte Carlo integration.
        nmc : int, optional
            If mc, use nmc samples.
        **kwargs
            scipy.integrate.tplquad kwargs epsabs and epsrel.

        Returns
        -------
        float
            Mean angular momentum.

        Notes
        -----
        - 2012-08-09 - Written - Bovy (IAS@MPIA)


        Calculate the mean vertical action by marginalizing over velocity.

        Parameters
        ----------
        R : float or Quantity
            Radius at which to calculate this.
        z : float or Quantity
            Height at which to calculate this.
        nsigma : float, optional
            Number of sigma to integrate the velocities over.
        mc : bool, optional
            If True, calculate using Monte Carlo integration.
        nmc : int, optional
            If mc, use nmc samples.
        **kwargs : dict
            scipy.integrate.tplquad kwargs epsabs and epsrel.

        Returns
        -------
        float
            Mean jz.

        Notes
        -----
        - 2012-08-09 - Written - Bovy (IAS@MPIA)


        Sample a radial, azimuthal, and vertical velocity at R,z

        Parameters
        ----------
        R : float or Quantity
            Galactocentric distance.
        z : float or Quantity
            Height.
        n : int, optional
            Number of distances to sample.

        Returns
        -------
        list
            List of samples.

        Notes
        -----
        - 2012-12-17 - Written - Bovy (IAS@MPIA)


        Sample radial, azimuthal, and vertical velocity at R,z using interpolation.

        Parameters
        ----------
        R : numpy.ndarray or Quantity
            Galactocentric distance.
        z : numpy.ndarray or Quantity
            Height.
        R_pixel : float
            The pixel size for creating the grid for interpolation (in natural units).
        z_pixel : float
            The pixel size for creating the grid for interpolation (in natural units).
        num_std : float, optional
            Number of standard deviation to be considered outliers sampled separately from interpolation.
        R_min : float, optional
            Minimum R value for the grid.
        R_max : float, optional
            Maximum R value for the grid.
        z_max : float, optional
            Maximum z value for the grid.

        Returns
        -------
        numpy.ndarray
            A numpy array containing the sampled velocity, (vR, vT, vz), where each row corresponds to the row of (R,z).

        Notes
        -----
        - 2018-08-10 - Written - Samuel Wong (University of Toronto)


        Sample a radial, azimuthal, and vertical velocity at R,z.

        Parameters
        ----------
        R : float or numpy.ndarray
            Galactocentric distance.
        z : float or numpy.ndarray
            Height.
        maxVT : numpy.ndarray
            An array of pre-optimized maximum vT at corresponding R,z.

        Returns
        -------
        numpy.ndarray
            A numpy array containing the sampled velocity, (vR, vT, vz), where each row correspond to the row of (R,z).

        Notes
        -----
        - 2018-08-10 - Written - Samuel Wong (University of Toronto)


        Calculate the marginalized vR probability at this location (NOT normalized by the density).

        Parameters
        ----------
        vR : float or Quantity
            Radial velocity.
        R : float or Quantity
            Radius.
        z : float or Quantity
            Height.
        gl : bool, optional
            If True, use Gauss-Legendre integration.
        ngl : int, optional
            If gl, use ngl-th order Gauss-Legendre integration for each dimension.
        nsigma : float, optional
            Number of sigma to integrate the velocities over.
        vTmax : float, optional
            Sets integration limits to [0,vTmax] for integration over vT.

        Returns
        -------
        float
            p(vR,R,z).

        Notes
        -----
        - 2012-12-22 - Written - Bovy (IAS@MPIA)


        Calculate the marginalized vT probability at this location (NOT normalized by the density).

        Parameters
        ----------
        vT : float or Quantity
            Azimuthal velocity.
        R : float or Quantity
            Radius.
        z : float or Quantity
            Height.
        gl : bool, optional
            If True, use Gauss-Legendre integration.
        ngl : int, optional
            If gl, use ngl-th order Gauss-Legendre integration for each dimension.
        nsigma : float, optional
            Number of sigma to integrate the velocities over.

        Returns
        -------
        float
            p(vT,R,z).

        Notes
        -----
        - 2012-12-22 - Written - Bovy (IAS@MPIA)
        - 2018-01-12 - Added Gauss-Legendre integration prefactor nsigma^2/4 - Trick (MPA)


        Calculate the marginalized vz probability at this location (NOT normalized by the density).

        Parameters
        ----------
        vz : float or Quantity
            Vertical velocity.
        R : float or Quantity
            Radius.
        z : float or Quantity
            Height.
        gl : bool, optional
            If True, use Gauss-Legendre integration.
        ngl : int, optional
            If gl, use ngl-th order Gauss-Legendre integration for each dimension.
        nsigma : float, optional
            Number of sigma to integrate the velocities over.
        vTmax : float, optional
            Sets integration limits to [0,vTmax] for integration over vT.

        Returns
        -------
        float
            p(vz,R,z).

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


        Calculate the marginalized (vR,vT) probability at this location (NOT normalized by the density).

        Parameters
        ----------
        vR : float or Quantity
            Radial velocity.
        vT : float or Quantity
            Azimuthal velocity.
        R : float or Quantity
            Radius.
        z : float or Quantity
            Height.
        gl : bool, optional
            If True, use Gauss-Legendre integration.
        ngl : int, optional
            If gl, use ngl-th order Gauss-Legendre integration for each dimension.
        nsigma : float, optional
            Number of sigma to integrate the velocities over.

        Returns
        -------
        float
            p(vR,vT,R,z).

        Notes
        -----
        - 2012-12-22 - Written - Bovy (IAS)
        - 2018-01-12 - Added Gauss-Legendre integration prefactor nsigma/2 - Trick (MPA)


        Calculate the marginalized (vT,vz) probability at this location (NOT normalized by the density).

        Parameters
        ----------
        vT : float or Quantity
            Azimuthal velocity.
        vz : float or Quantity
            Vertical velocity.
        R : float or Quantity
            Radius.
        z : float or Quantity
            Height.
        gl : bool, optional
            If True, use Gauss-Legendre integration.
        ngl : int, optional
            If gl, use ngl-th order Gauss-Legendre integration for each dimension.
        nsigma : float, optional
            Number of sigma to integrate the velocities over.

        Returns
        -------
        float or Quantity
            p(vT,vz,R,z).

        Notes
        -----
        - 2012-12-22 - Written - Bovy (IAS)
        - 2018-01-12 - Added Gauss-Legendre integration prefactor nsigma/2 - Trick (MPA)


        Calculate the marginalized (vR,vz) probability at this location (NOT normalized by the density).

        Parameters
        ----------
        vR : float or Quantity
            Radial velocity.
        vz : float or Quantity
            Vertical velocity.
        R : float or Quantity
            Radius.
        z : float or Quantity
            Height.
        gl : bool, optional
            If True, use Gauss-Legendre integration.
        ngl : int, optional
            If gl, use ngl-th order Gauss-Legendre integration for each dimension.
        vTmax : float, optional
            Sets integration limits to [0,vTmax] for integration over vT.

        Returns
        -------
        float or Quantity
            p(vR,vz,R,z).

        Notes
        -----
        - 2013-01-02 - Written - Bovy (IAS)
        - 2018-01-12 - Added Gauss-Legendre integration prefactor vTmax/2 - Trick (MPA)


        Calculate the epicycle frequency at r.

        Parameters
        ----------
        r : float
            Radius.

        Returns
        -------
        float
            Epicycle frequency.

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


        Calculate the vertical frequency at r.

        Parameters
        ----------
        r : float
            Radius.

        Returns
        -------
        float
            Vertical frequency.

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


        Calculate the radius of a circular orbit of Lz.

        Parameters
        ----------
        lz : float
            Angular momentum.

        Returns
        -------
        float
            Radius.

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


Internal function that is the integrand for the vmomentsurface mass integration


        Evaluate the DF for an Osipkov-Merritt-anisotropy DF

        Parameters
        ----------
        E : float
            The energy
        L : float
            The angular momentum

        Returns
        -------
        float
            The value of the DF

        Notes
        -----
        - 2020-11-12 - Written - Bovy (UofT)


p( v*sqrt[1+r^2/ra^2*sin^2eta] | r) used in sampling


Generate velocity samples


        Calculate the f(Q) portion of an Osipkov-Merritt Hernquist distribution function

        Parameters
        ----------
        Q : float
            The Osipkov-Merritt 'energy' E-L^2/[2ra^2]

        Returns
        -------
        float
            The value of the f(Q) portion of the DF

        Notes
        -----
        - 2021-02-07 - Written - Bovy (UofT)


    Accepts a parameter dictionary. Returns the response object to be
    served through the API.


    This returns the JSON data for a specific date, which must be a string of the form YYYY-MM-DD. If date is None,
    then it defaults to the current date.
    :param input_date:
    :param use_concept_tags:
    :return:


    This returns the JSON data for a set of randomly chosen dates. The number of dates is specified by the count
    parameter
    :param count:
    :param use_concept_tags:
    :return:


    This returns the JSON data for a range of dates, specified by start_date and end_date, which must be strings of the
    form YYYY-MM-DD. If end_date is None then it defaults to the current date.
    :param start_date:
    :param end_date:
    :param use_concept_tags:
    :return:


Return a custom 404 error.


Return a custom 500 error.


    Accepts a BeautifulSoup object for the APOD HTML page and returns the
    APOD image title.  Highly idiosyncratic with adaptations for different
    HTML structures that appear over time.


    Accepts a BeautifulSoup object for the APOD HTML page and returns the
    APOD image copyright.  Highly idiosyncratic with adaptations for different
    HTML structures that appear over time.


    Accepts a BeautifulSoup object for the APOD HTML page and returns the
    APOD image explanation.  Highly idiosyncratic.


    Accepts a BeautifulSoup object for the APOD HTML page and returns the
    date of the APOD image.


    Accepts a date in '%Y-%m-%d' format. Returns the URL of the APOD image
    of that day, noting that


make directory of path that is passed


function that globs for NEMO files from the raw experiment output looking for velocity files only.

    Parameters
    ----------
    exp_path:  path to NEMO experiment (will glob through the year directories)
    1) 'grid_T_2D' : glob all files of type grid_T_2D

    return_dates:  optional. will run find_dates function before returning and so will return a pandas DataFrame

    :returns:

    For 'grid_T_2D' : single list of globbed files

    Will return pandas DataFrame instead if return_dates=True

    WARNING: if return_dates is true you will get one line for every new date in the pandas dataframe!
    (There will be multiple references to the same file.)

    Notes
    -------
    Runs reg_date by default.

    Typical NEMO output looks like:

        cordex24-ERAI01_1d_19910101_19911231_grid_T_2D.nc

    Example
    -------


function that uses regular expressions to find start and end date from file.

    :string_to_find_date_in: string from NEMO netCDF file.
    :returns: string with start and end date


function that finds dates associated with passed list of NEMO output. Returns in pandas DataFrame.

    NB: assumes daily output on your NEMO files.

    Parameters
    ----------
    :globbedfiles: list of globbed files from raw_nemo_globber with pattern:
        */cordex24*_1d_*_grid_T_2D.nc

    :returns: dataframe of names and dates in pandas DataFrame.


    Loads latitude and longitude vectors from OFAM runs or AVISO
    Assumes root is /mnt/erebor unless cerberus is specified.


    Restricts latitude and longitude vectors given
    input limits.


    Loads sea surface height field from OFAM runs or Aviso
    Assumes root is /mnt/erebor unless cerberus is specified.
     run = 'CTRL' or 'A1B' or 'AVISO'


function to return fixed version of netcdf nav_lon variable

            :netcdf_datasetobj: netCDF4 Dataset object of nemo file
            :returns: nemo_lons numpy array with fixed dateline


Create quick interactive diagnostic plot to double check eddy_detection is doing what we want...


Replaces all instances of 'missing' in 'field' with 'replacement'


    Linearly interpolates over missing values (np.nan's) in data
    Data is defined at locations in vector indices.


    Make all locations that are missing in data2 also missing in data1
    Missing values are assumed to be np.nan.


    Performs a spatial filter, removing all features with
    wavelenth scales larger than cut_lon in longitude and
    cut_lat in latitude from field (defined in grid given
    by lon and lat).  Field has spatial resolution of res
    and land identified by np.nan's


    Detect eddies present in field which satisfy the criteria
    outlined in Chelton et al., Prog. ocean., 2011, App. B.2.

    Field is a 2D array specified on grid defined by lat and lon.

    ssh_crits is an array of ssh levels over which to perform
    eddy detection loop

    res is resolutin in degrees of field

    Npix_min, Npix_max, amp_thresh, d_thresh specify the constants
    used by the eddy detection algorithm (see Chelton paper for
    more details)

    cyc = 'cyclonic' or 'anticyclonic' [default] specifies type of
    eddies to be detected

    Function outputs lon, lat coordinates of detected eddies


function to plot how the eddy detection alogirthm went

    :tt
    :lon
    :lat
    :eta
    :eta_filt
    :anticyc_eddies
    :cyc_eddies
    :ptype
    :plot_dir
    :findrange=True
    :returns: @todo


@todo: Docstring for plot_eddies
        :returns: @todo


Creates list detected eddies


    Initializes list of eddies. The ith element of output is
    a dictionary of the ith eddy containing information about
    position and size as a function of time, as well as type.


    Load first baroclinic wave speed [m/s] and Rossby radius
    of deformation [km] data from rossrad.dat (Chelton et al., 1998)

    Also calculated is the first baroclinic Rossby wave speed [m/s]
    according to the formula:  cR = -beta rossby_rad**2


    Check if point (x,y) is contained in ellipse given by the equation

      (x-x1)**2     (y-y1)**2
      ---------  +  ---------  =  1
         a**2          b**2

    where:

      a = 0.5 * (dE + dW)
      b = dE
      x1 = x0 + 0.5 * (dE - dW)
      y1 = y0


    Calculates length of search area to the west of central point.
    This is equal to the length of the search area to the east of
    central point (dE) unless in the tropics ( abs(lat) < 18 deg )
    in which case the distance a Rossby wave travels in one time step
    (dt, days) is used instead.


    Given a map of detected eddies as a function of time (det_eddies)
    this function will update tracks of individual eddies at time step
    tt in variable eddies


    calculate the normalize cross correlation between I and J
    assumes I, J are sized [batch_size, *vol_shape, nb_feats]


This function creates one contracting block


This function creates one expansive block


This returns final block


This layer resize the layer from contraction block and concat it with expansive block vector


        Push the src and flow through the spatial transform block
            :param src: the original moving image
            :param flow: the output from the U-Net


    @description: str to bool
    @param {str}
    @return: bool


        @description: parser operation about model, especial for hyper-parameters
        @param {training parser options}
        @return: parser


    @description: return an instanced class according the model's name,
                    the model should be a subclass of basedmodel
    @param {model name}
    @return: instanced network class


    @description: like the name, to create a instanced model class
    @param {parser options, data_dict}
    @return: instanced model class


psnr and sam updating with epoch


        Does the work in actually running the scaler.

        Parameters
        ----------
        features : pd.DataFrame or similar
            The input features to run iforest on. Assumes the index is the id
            of each object and all columns are to be used as features.

        Returns
        -------
        pd.DataFrame
            Contains the same original index and columns of the features input
            with the features scaled to zero mean and unit variance.


    Normalise and then perform log transform on image

    Parameters
    ----------
    img : np.ndarray
        Input image (assumed float values)

    Returns
    -------
    np.ndarray
        Transformed image


    Performs inverse hyperbolic sine transform on image

    Parameters
    ----------
    img : np.ndarray
        Input image (assumed float values)

    Returns
    -------
    np.ndarray
        Transformed image


    Normalise and then perform square root transform on image

    Parameters
    ----------
    img : np.ndarray
        Input image (assumed float values)

    Returns
    -------
    np.ndarray
        Transformed image


    Small function to normalise an image between 0 and 1. Useful for deep
    learning.

    Parameters
    ----------
    img : np.ndarray
        Input image

    Returns
    -------
    np.ndarray
        Scaled image


    Resize an image to new dimensions (e.g. to feed into a deep learning
    network).

    Parameters
    ----------
    img : np.ndarray
        Input image
    new_shape : tuple
        Expected new shape for image

    Returns
    -------
    np.ndarray
        Reshaped image


    Crops an image to new dimensions (assumes you want to keep the centre)

    Parameters
    ----------
    img : np.ndarray
        Input image
    new_shape : tuple
        Expected new shape for image

    Returns
    -------
    np.ndarray
        Reshaped image


    Applies a Gaussian window of a given width to the image. This has the
    effect of downweighting possibly interfering objects near the edge of the
    image.

    Parameters
    ----------
    img : np.ndarray
        Input image
    width : float, optional
        The standard deviation of the Gaussian. The Gaussian is evaluated on a
        grid from -5 to 5 so a width=1 corresponds to a unit Gaussian. The
        width of the Gaussian will appear to be around 1/5 of the image, which
        would be fairly aggressive downweighting of outlying sources.

    Returns
    -------
    np.ndarray
        Windowed image


    Applies sigma clipping, fits contours and

    Parameters
    ----------
    img : np.ndarray
        Input image

    Returns
    -------
    np.ndarray


    Simple function that combines the rgb bands into a single image
    using OpenCVs convert colour to grayscale function.

    Parameters
    ----------
    img : np.ndarray
        Input image

    Returns
    -------
    np.ndarray
        Greyscale image


    Sometimes negative values (due to noise) can creep in even after sigma
    clipping which can cause problems later. Use this function before scaling
    to ensure negative values are set to zero.
    Parameters
    ----------
    img : np.ndarray
        Input image
    Returns
    -------
    np.ndarray
        Image with negatives removed


    Function that uses OpenCVs resampling function to resize an image

    Parameters
    ----------
    img : np.ndarray
        Input image

    Returns
    -------
    np.ndarray
        Resized image


    Small function that stacks the different channels together to form
    a new, single band image

    Parameters
    ----------
    img : np.ndarray
        Input image

    Returns
    -------
    np.ndarray
        Stacked image


    Small function that rearranges the different channels together to form
    a new image. Made specifically for the cutout.fits files from DECALS

    Parameters
    ----------
    img : np.ndarray
        Input image

    Returns
    -------
    np.ndarray
        Stacked image


    Band weighting function used to match the display of astronomical images
    from the DECaLS SkyViewer and SDSS. Created specifically for DECaLS fits
    cutout files.

    Requires array shapes to contain the channel axis last in line (Default
    format for astronomical images).

    Parameters
    ----------
    img : np.ndarray
        Input image

    Returns
    -------
    np.ndarray
        Weighted and reordered image


    Small function that shifts the band axis to the end.
    This is used to align a fits file to the default order
    used in astronomical images.

    Parameters
    ----------
    img : np.ndarray
        Input image

    Returns
    -------
    np.ndarray
        Shifted image


    Implements zscaling used in IRAF and DS9. Essentially just truncates the
    brightness histogram at sensibly chosen minima and maxima.

    Parameters
    ----------
    img : np.ndarray
        Input image
    contrast : float, optional
        Essentially tweaks the values of z1 and z2 to be more or less
        restrictive in the brightness distribution. 0.05 works quite well for
        MeerKAT images.

    Returns
    -------
    np.ndarray
        Shifted image


Serves the main page


    Searches for the original id and, if it exists in the index, returns the
    corresponding position in the current ordered list.


Calls the human-in-the-loop learning


    Checks if we're using fits files to decide whether or not to display the
    open viewer button


Runs the local fits viewer (such as ds9)


Deletes the existing labels allowing the user to start again


Sorts the data by a requested column


Let's the frontend know how long the list of objects is


        Runs (or reruns) the pipeline. Reimports the pipeline script so changes
        are reflected.


Runs the selected active learning algorithm.


        Runs a quick check to see if we're working with fits data to decide
        whether or not to display the "open with local viewer" button


        Allows the user to delete all the labels they've applied and start
        again


        Puts the anomaly scores in a random order. If
        show_unlabelled_first is True, puts the unlabelled data up front.


        Sorts the anomaly scores by a particular column. If
        show_unlabelled_first is True, puts the unlabelled data up front (this
        is cheaper than reducing the data to only showing the unlabelled data)


    Any script passed to the Astronomaly server must implement this function.
    run_pipeline must return a dictionary that contains the keys listed below.

    Parameters
    ----------

    Returns
    -------
    pipeline_dict : dictionary
        Dictionary containing all relevant data. Keys must include:
        'dataset' - an astronomaly Dataset object
        'features' - pd.DataFrame containing the features
        'anomaly_scores' - pd.DataFrame with a column 'score' with the anomaly
        scores
        'visualisation' - pd.DataFrame with two columns for visualisation
        (e.g. TSNE or UMAP)
        'active_learning' - an object that inherits from BasePipeline and will
        run the human-in-the-loop learning when requested


    An example of the full astronomaly pipeline run on image data

    Parameters
    ----------
    image_dir : str
        Directory where images are located (can be a single fits file or
        several)
    features : str, optional
        Which set of features to extract on the cutouts
    dim_reduct : str, optional
        Which dimensionality reduction algorithm to use (if any)
    anomaly_algo : str, optional
        Which anomaly detection algorithm to use

    Returns
    -------
    pipeline_dict : dictionary
        Dictionary containing all relevant data including cutouts, features
        and anomaly scores


    Splits the light curves into smaller chunks based on their gaps. This is
    useful for long light curves that span many observing seasons so have
    large gaps that can sometimes interfere with feature extraction.

    Parameters
    ----------
    lc_data : pd.Dataframe
        Light curves
    max_gap : int
        Maximum gap between observations

    Returns
    -------
    pd.DataFrame
        Split light curves


    Converts flux to mags for a given light curve data.

    Parameters
    ----------
    lcs: pd.DataFrame
        Light curve
    mag_ref: float
        Reference magnitude


    Function to convert an array to a png image ready to be served on a web
    page.

    Parameters
    ----------
    arr : np.ndarray
        Input image
    plot_cmap : str, optional
        Which colourmap to use
    interpolation : str, optional
        Allows interpolation so low res images don't look so blocky

    Returns
    -------
    png image object
        Object ready to be passed directly to the frontend


    Applies the transform function(s) given at initialisation to the image.

    Parameters
    ----------
    cutout : np.ndarray
        Cutout of image

    Returns
    -------
    np.ndarray
        Transformed cutout


Closes all open fits files so they don't remain in memory.


        Tiny utility function to make a nice formatted version of the image
        name from the input filename string

        Returns
        -------
        string
            Formatted file name