v2.0.0b1 (2026-11-05)
=====================

galpy 2.0 is based on v1.12.1 and includes every change through 1.12.1. This
is a pre-release (beta), so ``pip`` only installs it when given ``--pre``:
``pip install --pre galpy``, or ``pip install --pre "galpy[jax]"`` /
``pip install --pre "galpy[torch]"`` to also install the JAX or PyTorch
backend. galpy 2.x requires Python >= 3.11.

- Array backends: galpy now computes with JAX arrays and PyTorch tensors as
  well as with NumPy arrays (``galpy.backend``). Potentials, orbit
  integration, action-angle coordinates, distribution functions, and stream
  models accept JAX or PyTorch inputs, compute with that framework, and
  return arrays of the same kind, so galpy calculations can be differentiated
  with automatic differentiation (``jax.grad``, ``torch.autograd``), compiled
  (``jax.jit``, ``torch.compile``), vectorized (``jax.vmap``), and run on a
  GPU. With NumPy inputs, galpy behaves as before. The backend is chosen by
  the type of the arrays that are passed in (including an object's
  parameters: a potential set up with a JAX parameter computes with JAX in
  every call), by the ``with galpy.backend.use("jax"):`` (or ``"torch"``)
  context manager when there is no array to dispatch on, or by the new
  ``default`` option in the ``[backend]`` section of the configuration file.
  See the "JAX and PyTorch Backends: Quick Start" tutorial and the backend
  tutorial of each section of the documentation. In more detail:

  - Potentials, forces, and wrappers evaluate on backend arrays and are
    differentiable with respect to the coordinates and to their parameters.

  - Orbits can be integrated inside the backend with the differentiable
    adaptive-step integrators ``method='diffrax'`` (JAX) and
    ``method='torchode'`` or ``'torchdiffeq'`` (PyTorch), with constant-step
    in-backend versions of the leapfrog and symplectic integrators
    (``method='leapfrog_jax'``, ``'leapfrog_torch'``, ...) for many orbits at
    once, and through galpy's C integrators, which return the derivative with
    respect to the initial condition from their variational equations.
    In-backend orbits are differentiable with respect to the initial
    conditions and the parameters of the potential, in forward and reverse
    mode, and batches of orbits can be integrated with ``jax.vmap``.

  - The Staeckel (``c=False`` and ``c=True``), adiabatic, spherical, and
    isochrone-approximation actions, frequencies, and angles, and the inverse
    transformation of ``actionAngleVerticalInverse``, are differentiable with
    respect to the phase-space coordinates and the parameters of the
    potential.

  - The spherical, disk (``quasiisothermaldf`` and the two-dimensional disk
    DFs), and stream (``streamdf``, ``streamgapdf``, ``streamspraydf``)
    distribution functions evaluate on backend arrays and are differentiable
    with respect to their parameters and those of the potential, including
    the stream track. The King model's DF and potential are differentiable
    with respect to ``W0``.

  - Sampling takes an explicit random key on the backends (``key=``, a JAX
    key or its PyTorch equivalent) and draws by inverse transformation from a
    tabulated cumulative distribution, which makes the samples
    differentiable with respect to the parameters of the distribution.
    ``key=None`` keeps the NumPy behavior.

  - Precision: galpy computes in double precision. Switch on JAX's 64-bit
    mode before creating JAX arrays. A single-precision PyTorch input returns
    a single-precision result (galpy computes in double precision
    internally), so create ``dtype=torch.float64`` tensors for the full
    precision.

- Changes to the NumPy results: the NumPy path is byte-for-byte identical to
  v1.12.1, with these deliberate exceptions:

  - The King model (``KingPotential``, ``kingdf``) now solves its Poisson
    equation to a relative tolerance of 1e-10 rather than scipy's default of
    1e-3, which changes its potential and DF at the 1e-5 to 1e-3 level.

  - The velocity sampler of ``quasiisothermaldf``, the samplers of the
    two-dimensional disk DFs (``dehnendf``, ``shudf``, ``schwarzschilddf``),
    and the sampler of ``streamdf`` draw by inverse transformation rather
    than by rejection. The particular draws change, but not their
    distribution, except for the two-dimensional disk DFs, whose previous
    draws had a mean azimuthal velocity that was biased by a few per cent
    and whose new draws do not.

  - The forces of ``EinastoPotential`` and ``PowerSphericalPotentialwCutoff``
    were rewritten in forms that are accurate and differentiable at small
    radii; their values differ from v1.12.1 by at most a few units in the
    last place (5e-15 relative).

- Removed the features that were deprecated for removal after v1.13:

  - Lists of potentials are no longer accepted anywhere; combining potentials
    with a list now raises a ``TypeError``. Combine potentials with the ``+``
    operator instead (``pot1 + pot2``), which returns a
    ``CompositePotential``.

  - ``Orbit.integrate`` and ``Orbit.integrate_dxdv`` require the times to be
    an array (a list of times now raises a ``TypeError``; it never worked).

  - ``streamdf``: the ``Rnorm=``, ``Vnorm=``, and ``custom_transform=``
    keywords and the ``calc_stream_lb`` method.

  - ``fardal15spraydf`` and ``chen24spraydf``: the ``leading=`` keyword; use
    ``tail=``.

- Python >= 3.11 is required. The new ``jax`` and ``torch`` extras
  (``pip install "galpy[jax]"``, ``"galpy[torch]"``) install the backend
  dependencies (jax >= 0.10.1 with diffrax >= 0.7.2; torch >= 2.12 with
  torchdiffeq >= 0.2.5 and torchode >= 1.0.1; array-api-compat >= 1.14).

- The new-version check at import time now queries PyPI's JSON API and, when
  running a pre-release, also reports newer pre-releases.

- ``TruncatedNFWPotential`` and ``TruncatedHernquistPotential`` run on the JAX
  and PyTorch backends, differentiable with respect to ``a``, ``rc`` and the
  tabulated ``rc(t)`` values.

v1.12.1 (2026-11-02)
====================

- Added ``TruncatedNFWPotential`` and ``TruncatedHernquistPotential``: the NFW
  and Hernquist profiles times the truncation of Baltz, Marshall & Oguri
  (2009), ``(rc^2 / (rc^2 + r^2))^n`` for any positive integer ``n``, with
  closed-form mass, potential, forces, and second derivatives accurate to
  ~1e-14. The truncation radius can depend on time (``tgrid=``), e.g., for a
  satellite that is stripped from the outside in, used as the ``pot`` of a
  ``MovingObjectPotential``. Both have C implementations (including
  ``integrate_dxdv``) and can be used with the spherical distribution
  functions.

- Added time-dependent support to ``SCFPotential``: the expansion coefficients
  ``Acos`` and ``Asin`` can be functions of time, given as callables or as
  arrays sampled on a ``tgrid``, interpolated in time with a cubic spline, with
  fast evaluation in Python and C. ``SCFPotential.from_density`` likewise
  accepts a ``tgrid`` to build a potential from a time-dependent density
  (analogous to the time-dependent ``MultipoleExpansionPotential``).

- Added ``SCFPotential.from_nbody`` to build an ``SCFPotential`` directly from
  particle positions and masses. Multiple snapshots with a ``tgrid`` build a
  time-dependent potential, and the particle sum is accumulated in batches, so
  memory use stays bounded for any number of particles.

- Added ``SCFPotential.from_multipole`` and
  ``MultipoleExpansionPotential.from_scf`` to translate between the two
  expansions. Because both expand in the same real spherical harmonics, the
  translation is purely radial; it supports time-dependent potentials.

- ``Orbit.integrate_dxdv`` now works with the symplectic C integrators
  (``leapfrog_c``, ``symplec4_c``, ``symplec6_c``), which propagate the
  deviations with the exact tangent map of each step, so the state-transition
  matrix is symplectic to machine precision. ``integrate_dxdv`` now also
  supports 1D orbits, with both the Runge-Kutta and the symplectic integrators.

- Added an ``isConservative`` attribute to all potentials and forces, True when
  the force derives from a (possibly time-dependent) potential. The symplectic
  integrators now fall back to a non-symplectic integrator only for forces that
  are not conservative, so they can, e.g., integrate orbits in a
  ``NonInertialFrameForce`` frame that accelerates without rotating.

- ``streamspraydf.streamTrack`` and ``StreamTrack.from_particles`` have a new
  default reconstruction, ``method='pspline'``: the particles' offsets from the
  progenitor's orbit are fit with a penalized cubic spline, with each
  coordinate's penalty chosen by restricted maximum likelihood. The track is
  now a smooth function of the particles and the progenitor, and for large
  samples the fit takes about half the time and a quarter of the memory.
  ``smoothing=`` and ``smoothing_s`` are now the 6 per-coordinate penalty
  weights; the previous reconstruction remains available as
  ``method='binned'``.

- ``actionAngleVerticalInverse`` now evaluates through a momentum-matched
  canonical map by default, whose auxiliary torus is the harmonic oscillator of
  the same action. The map, its momentum, and the angle are closed form, so the
  map is exactly symplectic, preserves the requested action to ~1e-13, and
  ``Freqs`` returns exactly the frequency of the returned orbits; the family of
  tori can be as small as a single torus. The previous evaluation remains
  available with ``momentum_matched=False``. Also fixes the frequency of the
  zero-energy grid torus.

- Added an exact point transformation to ``actionAngleVerticalInverse``
  (``use_pointtransform="exact"``), which maps each torus exactly onto its
  auxiliary harmonic-oscillator torus by quadrature along the orbit, so the
  point transformation alone is the complete torus mapping. With
  ``pt_only=True``, the inverse transformation is evaluated with the point
  transformation alone (much faster).

- ``actionAngleVerticalInverse`` now supports physical units (``ro=``,
  ``vo=``, and Quantity inputs and outputs).

- ``OblateStaeckelWrapperPotential`` is ~3x faster in C, and the new ``ntab=``
  option tabulates its functions along the reference curves as splines for
  ~15x faster C orbit integration (agreeing with the exact evaluation to
  ~2e-8 at ``ntab=3000``).

- ``actionAngleStaeckel`` no longer needs ``delta=`` for a potential that
  supplies its own focal length: the exact Staeckel potentials
  ``KuzminKutuzovStaeckelPotential`` and the axisymmetric oblate (b = 1,
  c < 1) ``PerfectEllipsoidPotential``, and
  ``OblateStaeckelWrapperPotential``.

- ``OblateStaeckelWrapperPotential`` now places its reference curve ``u0`` at
  R = 1 by default (computed from the focal length) rather than on the symmetry
  axis (u0 = 0), where a flattened potential looks nothing like it does in the
  disk. This improves the default Staeckel approximation and changes its
  values.

- Added ``x2deriv`` to 1D (``linearPotential``) potentials and the
  corresponding ``evaluatelinearx2derivs`` function: the second derivative
  d^2 Phi / dx^2, with physical units.

- More array inputs: the ``dehnendf`` and ``shudf`` moments (``surfacemass``,
  ``sigma2surfacemass``, ``sigmaR2``, ``meanvT``, the Oort functions, etc.)
  accept an array of radii; ``rl`` accepts an array of Lz (~300x faster than
  a loop); ``SphericalShellPotential`` and ``HomogeneousSpherePotential``
  accept arrays.

- ``Orbit.from_name`` now falls back on the other SIMBAD mirrors that astroquery
  knows when the configured one cannot be reached (previously, every lookup
  failed whenever the CDS service was down).

- Added wheels for Python 3.15 and Pyodide wheels for Python 3.14. galpy now
  also compiles with GCC 15.

- ``ChandrasekharDynamicalFrictionForce`` and ``FDMDynamicalFrictionForce``:
  construction is ~100x faster for hosts whose potential accepts arrays (e.g.,
  14 s to 0.14 s for ``MWPotential2014``) and orbit integration ~2x faster
  (the force cache never hit). The host's velocity dispersion is now
  tabulated in log r (it was 20-60% wrong at r < 0.03 for common hosts) and
  the Python force uses the same spline as C, so orbits sinking to the center
  integrate identically in C and Python.

- ``Orbit.lyapunov`` is ~100x faster: it no longer forks a process for each of
  its short integration segments (its default is now ``numcores=1``, and
  ``parallel_map`` with ``numcores=1`` now runs serially).

- ``actionAngleIsochroneInverse`` is ~100x faster, solving Kepler's equation
  for all angles at once (identical output).

- ``Orbit.e``, ``rperi``, ``rap``, and ``zmax`` with ``analytic=True`` in a
  spherical potential no longer redo the action-angle setup on every call.

- Fixed a bias in sampling velocities from spherical distribution functions,
  which underestimated the velocity dispersion by ~0.8%; sampled values for a
  fixed random seed change. Sampling also no longer raises ``ValueError: x
  must be increasing`` when the mass converges well inside ``rmax`` (e.g.,
  for ``ExpTruncNFWPotential``).

- Spherical DFs evaluated on an ``Orbit`` instance holding several orbits now
  use each orbit's own angular momentum; before, every orbit was assigned the
  norm of all orbits' L combined, so anisotropic DFs returned wrong values for
  such ``Orbit`` instances.

- ``interpRZPotential`` built from a potential with ``ro``/``vo`` set
  tabulated values in physical units, so its interpolated density, second
  derivatives, and frequencies (and, with ``use_c=False``, its potential and
  forces) were wrong by unit-conversion factors; it now tabulates internal
  units. Its grids are also built ~20x faster for potentials that accept
  arrays.

- ``AnySphericalPotential`` evaluated with an array of radii returned forces
  computed with the enclosed mass at the first radius for all elements, and
  its potential raised an error; both are now evaluated element by element.

- Slicing an ``Orbit`` with per-orbit physical parameters (array ``ro``,
  ``vo``, ``zo``, or solar motion) now selects them along with the orbits
  (previously, e.g., ``orbits[1].R()`` returned values for every ``ro``).
  ``Orbit.toPlanar`` and ``Orbit.toLinear`` now preserve the shape of the
  ``Orbit`` instance (previously flattened).

- Integrating many orbits in C no longer crashes with a segmentation fault
  when the output has more than 2^31-1 elements (e.g., 1e5 3D orbits at 3,600
  times), in all C integrators and in ``actionAngleTorus``'s
  ``xvJacobianFreqs``.

- ``quasiisothermaldf``: guiding-center radii for Lz outside of the
  precomputed grid (Lz < 0.01, including all counter-rotating Lz, or
  Lz > 5 hr vc(5 hr)) are now solved for exactly instead of extrapolated
  (previously up to 60% off, and with the wrong sign for Lz < 0), and
  counter-rotating points inside the grid use the grid at abs(Lz). When the
  actionAngle object raises ``UnboundError`` for an array of points, the DF is
  now evaluated point by point (zero DF for unbound points), which fixes
  ``gl=True`` moments in, e.g., low-mass potentials. ``_precomputerg=False``
  no longer raises an error.

- ``AdiabaticContractionWrapperPotential`` now applies its ``amp`` (which had
  no effect in Python or C), and its potential is offset by the exact integral
  of its force (it was 3e-7 to 5e-7 off).

- The ``sphericaldf`` family now honors a per-call ``ro=``/``vo=`` when
  parsing ``Quantity`` inputs (previously the DF's own ``ro`` and ``vo`` were
  always used).

- ``constantbetadf`` now computes its JAX derivatives in 64-bit precision even
  when JAX's 64-bit mode is off (JAX's default), enabling it only for its own
  calls, and uses the small-radius series of the ``NFWPotential`` and
  ``ExpTruncNFWPotential`` forces. In 32-bit precision the DF was badly wrong
  at the most bound energies (e.g., eight times too small for an NFW
  potential), and the closed-form forces changed the DF there by up to ~5e-5.

- The ``actionAngleStaeckel`` integrals are now regularized at the turning
  points in C and in Python, using a quadrature in an anomaly that absorbs
  their square-root behavior. Actions at the default order are converged to
  ~1e-12 (previously ~5e-4 off; ``c=True`` actions change at that level), and
  C frequencies and angles near the turning points to ~1e-11 (previously up to
  2e-4), stable as the order increases. Orbits that pass close to the axis
  (whose C radial actions were ~5e-5 off, or NaN at high order) use a graded
  rule, and orbits in the midplane without vertical velocity get zmax = 0
  exactly in C (was ~1e-8). The Python path uses the same quadrature mesh as C
  and is ~1.6x faster.

- The C ``actionAngleAdiabatic`` now regularizes its action integrals at the
  turning points (and uses order 20 instead of 10), reducing the errors in the
  actions from ~1e-4 to ~1e-9 (``c=True`` values change; ~30% slower).

- ``actionAngleSpherical`` now handles circular and near-circular orbits,
  where it lost precision, returned NaN, or failed to find a turning point:
  frequencies and angles are accurate to ~1e-9 down to a radial excursion of
  1e-5 of the circular radius, and exactly circular orbits return J_R = 0 and
  the epicycle and circular frequencies. Its azimuthal integrals are now done
  in the inverse radius, improving the azimuthal frequency of nearly radial
  orbits from ~1e-4 to typically ~1e-9. Bound orbits with apocenters beyond
  r = 100 (e.g., eccentricities above 0.98 in a Hernquist potential) are no
  longer declared unbound.

- ``TwoPowerSphericalPotential`` with general (alpha, beta) now computes its
  potential, forces, second derivatives, and enclosed mass from incomplete
  beta functions, in Python and C. The previous closed forms were badly off
  near beta = 3 and at large beta (NaN at large r), especially in C; values
  are now accurate to ~1e-12 or better for 0 <= alpha < 3, 2 < beta <= 180,
  and 1e-12 <= r/a <= 1e8, and C no longer aborts for beta >~ 170.

- ``NFWPotential``, ``BurkertPotential``, and ``TwoPowerSphericalPotential``
  are now accurate to machine precision at small radii (in Python and C), the
  densities and forces of these and of ``EinastoPotential``,
  ``IsochronePotential``, ``LogarithmicHaloPotential``, and
  ``PowerSphericalPotential`` take their limits at r = 0 and r = infinity
  rather than NaN, and ``rE`` is solved to a relative tolerance at small radii.

- ``eddingtondf``'s f(E) is now accurate near the most-bound energy (for NFW it
  was NaN or large and negative there), takes its correct limit at that energy
  (infinite for a cusp), and works with ``rmax=numpy.inf``.

- ``AnyAxisymmetricRazorThinDiskPotential`` is now accurate close to the disk:
  for |z| << R, its vertical force went to zero instead of -2 pi Sigma and its
  potential missed the cusp at the midplane, its second derivatives were NaN or
  infinite at some small |z|, and at z = 0 they were wrong in the 5th to 7th
  digit (they are now evaluated as finite-part integrals).

- ``RazorThinExponentialDiskPotential``'s forces just above |z| = 1e-6 are now
  ~100x more accurate (they were up to 5e-3 off).

- ``EinastoPotential`` with a large index (e.g., the cosmological n = 6) no
  longer returns a zero or wrong radial force and second derivative at the
  radii used in halo modeling, where the enclosed-mass factor rounded to zero.

- ``surfdens`` and ``jeans.sigmar`` integrals are no longer cut short by
  scipy's default absolute tolerance when they are small (e.g., the surface
  density of ``MWPotential2014``'s bulge at R = 1, |z| = 8 was 2e-5 off, and
  sigma_r of an ``SCFPotential`` at r = 25 6e-6 off).

- ``Orbit`` instances can now be evaluated at a time given as a 0-d numpy
  array, which previously raised an error; this broke integrating any orbit in
  a ``MovingObjectPotential`` with ``method='dop853'``.

- Setting up an ``Orbit`` from sky coordinates with ``uvw=True`` no longer
  modifies the input array.

- ``NFWPotential`` set up with ``rmax``/``vmax`` or ``conc``/``mvir`` no
  longer raises an ``AttributeError`` when used with spherical distribution
  functions such as ``eddingtondf``.

- ``actionAngleAdiabaticGrid`` with ``c=False`` no longer raises a
  ``TypeError`` when two or more points fall outside the grid.

- ``actionAngleVerticalInverse`` with a polynomial point transformation
  (``use_pointtransform=True``) now selects tori by their actual action. Each
  torus was labeled by its mean auxiliary action, which differs from the
  actual action (by ~4e-4 at the default degree, more at high energy), so
  requesting a torus's action returned a neighboring torus, and the top
  torus's action crashed the lookup.

- ``Orbit.integrate`` now warns when an orbit leaves an
  ``interpSphericalPotential``'s range also when the potential includes an
  ``FDMDynamicalFrictionForce``.

- An ``AttributeError`` raised inside an actionAngle method is no longer
  reported as "method not implemented".

- ``Orbit.integrate_dxdv`` with a C integrator now gives a base orbit that is
  bit-identical to that of ``Orbit.integrate``.

- ``Orbit.animate`` now defines its button style once per page, avoiding
  duplicated ``<style>`` elements and an HTML error.

v1.12.0 (2026-07-01)
====================

- Added the full 3D variational equations (the state-transition matrix
  dx(t)/dx0, integrated via ``Orbit.integrate_dxdv``) in C for most of the
  potential library, the 3D analogue of the existing planar machinery. This
  enables fast tangent-dynamics, Lyapunov-exponent (see ``Orbit.lyapunov``
  below), and chaos calculations, and lays the groundwork for differentiable
  orbit integration. Many potentials gained their analytic 3D Hessian in C as
  part of this work.

- Added ``Orbit.lyapunov`` to estimate the largest Lyapunov exponent of an orbit
  from the variational equations using the renormalization method of Benettin et
  al. (1980), for both planar and full 3D orbits (using the C variational
  integrators when available). Setting ``spectrum=True`` computes the full
  Lyapunov spectrum instead.

- Extended the 3D variational equations in C to velocity-dependent (dissipative)
  forces, starting with ``ChandrasekharDynamicalFrictionForce`` and
  ``FDMDynamicalFrictionForce``.

- Added the remaining C second derivatives used by these variational equations,
  including ``NonInertialFrameForce`` (so phase-space volumes can be integrated
  in rotating/accelerating frames), the ``OblateStaeckelWrapperPotential`` and
  ``CylindricallySeparablePotentialWrapper`` wrappers, and the
  ``SteadyLogSpiralPotential`` and ``TransientLogSpiralPotential`` spirals.

- Added ``MultipoleExpansionPotential``, which represents the potential of an
  arbitrary (and optionally time-dependent) density distribution via a real
  spherical-harmonic multipole expansion, with both Python and C evaluation of
  the potential, forces, second derivatives, and density. Build it from a density
  function with the ``from_density`` classmethod.

- Added ``DiskMultipoleExpansionPotential``, which represents disk+halo systems
  by solving the Poisson equation with a multipole expansion (the analogue of
  ``DiskSCFPotential`` built on ``MultipoleExpansionPotential``); the two now
  share a ``KuijkenDubinskiDiskExpansionPotential`` base class, with C orbit
  integration support.

- Added a ``StreamTrack`` class holding a smooth, precomputed phase-space track
  through a tidal stream, with accessors for every standard galpy coordinate
  system, a ``cov`` method for the 6x6 phase-space covariance along the track
  (via analytic Jacobians), and plotting with an optional ±σ spread band. Tracks
  can be built from a particle sample (``StreamTrack.from_particles``) or
  directly from a ``streamdf`` or ``streamspraydf`` via their new ``streamTrack``
  methods.

- Added ``ExpTruncNFWPotential``, an NFW profile with an exponential truncation
  ``exp(-r/rc)`` and hence finite total mass, with closed-form mass, potential,
  force, and second derivative. Supports isotropic, Osipkov-Merritt, and
  constant-beta distribution functions and has a C implementation (including the
  full 3D Hessian for the variational equations). A ``from_nfw`` classmethod
  truncates an existing ``NFWPotential``, and the total mass can alternatively be
  set directly with the ``mass=`` keyword.

- Added analytic power-law spherical distribution functions for tracer densities
  nu(r) ~ r^-gamma in power-law potentials (following Evans et al. 1997):
  ``isotropicPowerLawdf``, ``constantbetaPowerLawdf``, and
  ``osipkovmerrittPowerLawdf``, each supporting both the self-consistent and the
  non-self-consistent (tracer != potential-generating density) cases.

- Added support for non-uniform stripping-time distributions (with a pericenter
  helper) and callable, time-dependent ``progenitor_mass`` to the stream spray
  DFs (``streamspraydf``).

- Added support for per-orbit integration time arrays in ``Orbit.integrate``, so
  each orbit in a multi-orbit ``Orbit`` can be integrated over its own time
  range; this also enables batched ``streamspraydf`` integration.

- Added a ``tail=`` keyword to ``fardal15spraydf`` and ``chen24spraydf`` (and
  ``basestreamspraydf``) to select which tidal tail(s) to model (``'leading'``,
  ``'trailing'``, or ``'both'``, the default). This replaces the now-deprecated
  ``leading=`` keyword, which will be removed in v1.14.

- Added an ``align_to_orbit`` helper (to ``galpy.util.coords`` and as an
  ``Orbit`` method) that aligns an orbit horizontally.

- Added a ``cinterp`` option (default ``True``) to ``NonInertialFrameForce``
  that, during C integration, replaces its time-dependent inputs by cubic-spline
  interpolations evaluated natively in C, giving large speed-ups (>100x when the
  inputs are not ``numba``-compatible). Set ``cinterp=False`` to evaluate the
  provided functions directly, which is required for surface-of-section
  integration.

- Vectorized ``EllipsoidalPotential`` evaluations so the triaxial ellipsoidal
  potentials accept array inputs.

- Added frequencies and angles computation for ``actionAngleStaeckel`` in pure
  Python (``c=False``).

- Rewrote the documentation tutorials as tested Jupyter notebooks with gallery
  navigation.

- Fixed a segmentation fault (or silently-dropped force) when integrating planar
  orbits with a C integrator for potentials whose 3D version has a C
  implementation but whose planar version does not (e.g. ``interpRZPotential``,
  ``ChandrasekharDynamicalFrictionForce``); such potentials now fall back to
  Python integration.

- Fixed a stale-force bug in the C implementation of
  ``RotateAndTiltWrapperPotential``, whose force cache was keyed on position only
  and so returned stale forces when re-evaluating a time-dependent wrapped
  potential at the same position but a different time.

- Fixed an incorrect physical-unit conversion for ``phitorque`` in
  ``DissipativeForce`` and ``planarDissipativeForce``.

- Fixed compatibility with astropy >= 8.0, where the ``Galactocentric``
  ``galcen_v_sun`` attribute is now a ``CartesianRepresentation`` rather than a
  ``CartesianDifferential`` (astropy/astropy#18362), so initializing an ``Orbit``
  from a ``SkyCoord`` carrying ``galcen_v_sun`` works again.

- Fixed compatibility with numpy 2.5.0 (complex ``eig``/``eigvals`` results and
  the ``chararray`` deprecation).

- Fixed a crash when sampling a spherical distribution function whose isotropic
  (Eddington-inverted) form dips slightly negative (e.g. near the truncation
  radius of a sharply truncated NFW profile); such regions are now clamped to be
  non-negative and monotonic before sampling.

v1.11.2 (2026-02-27)
====================

- Added CompositePotential, planarCompositePotential, and linearCompositePotential
  classes to represent combinations of multiple potentials in 3D, 2D, and 1D,
  respectively. These classes replace the previous use of lists of potentials
  to represent combined potentials. The new classes provide better performance
  and a cleaner interface for combined potentials. Note that these classes don't
  need to be explicitly instantiated, but instead are created automatically when
  adding potentials using + and, because this was already the recommended way to combine
  potentials, this change is mostly internal. The old way of using lists of potentials
  will be deprecated in a future version (likely v1.14.0).

- Added support for continuing orbit integrations. When an orbit has already
  been integrated and integrate() is called again with a time array that
  continues from the end (for forward continuation) or beginning (for backward
  continuation) of the previous integration, the two integrations are merged.
  This allows integrating an orbit forward and then backward in time, or
  extending an existing integration, without having to re-integrate from the
  initial conditions. The integration times can be obtained using the time()
  method.

- Added frequencies and angles computation for actionAngleAdiabatic in Python.

- Added C implementation for TwoPowerSphericalPotential (including
  HernquistPotential, JaffePotential, and NFWPotential) to enable fast
  orbit integration using the xsf library for hypergeometric functions.

- Added C implementation for TwoPowerTriaxialPotential to enable fast orbit
  integration. The C implementation uses the hyp2f1 hypergeometric function
  and handles the special case where alpha=2.

- Added C implementation of planar second derivatives for
  EllipsoidalPotential, enabling fast variational-equation integration
  for triaxial potentials.

- Added automatic time determination for orbit integration. Orbits can now be
  integrated without specifying an explicit time array by calling integrate(pot),
  which integrates for 10 dynamical times by default. The dynamical time is
  calculated using the potential's tdyn method at the initial position, with
  fallback to 2π·R/vcirc for 2D orbits. This simplifies exploratory orbit analysis
  by providing physics-based default integration times. For composite potentials
  where some components don't support tdyn, galpy automatically filters to working
  components. The feature uses 101 points per dynamical time for good temporal
  resolution.

- Added CylindricallySeparablePotentialWrapper, a wrapper potential that
  constructs a cylindrically-separable potential from a given potential's
  radial and vertical force profiles. Includes a C implementation.

- Added support for Python 3.14.

- Added enhanced ``__repr__`` methods to potential, force, and wrapper
  classes for better display.

- Fixed spherical distribution function sampling for divergent
  potentials/densities.

- Fixed missing boundary term in Eddington inversion calculation.

- Fixed handling of Simbad distances in units other than kpc.

- Auto-detect GSL paths in setup.py to fix compilation failures when
  CFLAGS/LDFLAGS are not set.

- Removed support for Python 3.9 (which has reached its end of life in Oct 2025).

v1.11.1 (2025-11-02)
====================

- Added EinastoPotential, the potential corresponding to the Einasto density
  profile.

- Add Fuzzy Dark Matter (FDM) dynamical friction (#731)

- Added wrapper potential to turn a potential into an oblate Staeckel potential
  (OblateStaeckelWrapperPotential).

- Added wheels for Python 3.14.

- Build wheels for multiple Pyodide versions and share on AWS site.

v1.11.0 (2025-07-02)
====================

- Removed support for Python 3.8 (which has reached its end of life in Oct 2024).

- Implement caching of PowerSphericalPotentialwCutoff to speed up evaluation of
  the forces during orbit integration.

- Turn physical units on when surface density input to AnyAxisymmetricRazorThinDiskPotential
  is given in physical units.

- Allow TwoPowerSphericalPotential to be evaluated at r=0 (#729).

- Switch to controlling compilation options through environment variables to be
  more compatible with modern pip/setup.py standards.

v1.10.2 (2025-03-03)
====================

 - Implemented the IAS15 integrator of Rein & Spiegel 2015.

 - Speed-up the C implementation of PowerSphericalPotentialwCutoff (#706).

 - Combine the drift calculations in the Python leapfrog integrator for a small
   speed-up (#690).

- Clarify the use of non-equispaced time arrays in orbit integration (#711).

- Fix the handling of unbound orbits in the Orbit action-angle interface (#712).

 - Move the checks for non-axisymmetric and dissipative potentials from internal to
   public potential/force evaluation functions (e.g., from _evaluate[Potentials,
   Rforces, phitorques, zforces] to evaluate[Potentials, Rforces, phitorques, zforces])
   for performance improvements.

- Add an isDissipative attribute to force classes.

- Print warning when initializing an Orbit with a SkyCoord that does not have the Sun's
  positional and velocity parameters set (#715).

v1.10.1 (2024-11-01)
====================

- Propagate general plotting keywords in Potential.plot/plotPotentials. Also allow
  plotting potentials on physical axes.

- Added the generalized particle-spray model as galpy.df.basestreamspraydf with two
  subclasses: chen24spraydf and fadal15spraydf. Enabled integrating orbits of stream
  particles with the progenitor's potential. Deprecating the old particle-spray
  model galpy.df.streamspraydf.

v1.10.0 (2024-07-07)
====================

- Increased support for using OpenMP with clang and, in particular, added OpenMP support
  in the released Mac wheels.

- Removed explicit support for using Intel compilers.

- Switch to using Ruff as the code formatter.

v1.9.2 (2024-03-04)
===================

- Added KuzminLikeWrapperPotential, a potential wrapper that allows
  one to make a Kuzmin-like or Miyamoto-Nagai-like potential out of any
  spherical or axisymmetric potential (evaluated in the plane, i.e.,
  treated as a spherical potential). Kuzmin-like potentials are obtained by
  replacing the spherical radius r with \sqrt(R^2 + (a + |z|^2)), while
  Miyamoto-Nagai-like potentials are obtained by replacing the spherical
  radius with \sqrt(R^2 + (a + \sqrt(z^2 + b^2))^2). The standard KuzminDiskPotential
  and MiyamotoNagaiPotential are obtained by applying this procedure to a point-mass
  potential and the Kuzmin/Miyamoto-Nagai-like potentials generalize this to any
  spherical potential.

v1.9.1 (2023-11-06)
===================

- Allow vector inputs of solar parameters to Orbit initialization: ro, zo, vo,
  and solarmotion (#595). Useful when sampling over the uncertainty in the solar
  parameters.

- Converted all docstrings to numpy-style format with the help of GitHub Copilot.

v1.9.0 (2023-07-02)
===================

- Add specialized integration method to determine surfaces of sections of orbits and
  add Orbit.SOS and Orbit.plotSOS methods to compute and plot the surface of section
  of an orbit.

- Also added a brute-force method to determine surfaces of sections and plotting them
  for force fields for which the specialized method does not work (e.g., orbits in a
  non-inertial bar frame). Methods Orbit.bruteSOS and Orbit.plotBruteSOS have similar
  interfaces as Orbit.SOS and Orbit.plotSOS.

- Added a method, dMdE, to calculate the differential energy distribution of
  spherical distribution functions.

- Added general support for DissipativeForce instances in 2D.

- Implemented NonInertialFrameForce in 2D.

- Started using black for code formatting.

- Allow potentials' density and surface density to be plotted on physical axes.

- Don't fail when writing a (fixed) configuration file, instead just warn.

- Removed the deprecated galpy.util.bovy_coords, galpy.util.bovy_plot, and
  galpy.util.bovy_conversion modules. These were replaced by galpy.util.coords,
  galpy.util.plot, and galpy.util.conversion in v1.7.

- Removed the deprecated phiforce method from potentials and the accompanying
  evaluatephiforces and evaluateplanarphiforces potential functions. These were replaced
  by phitorque, evaluatephitorques, and evaluateplanarphitorques in v1.8.0.

- Switched to using Python 3.11 as the default Python version in the test suite.

v1.8.3 (2023-03-27)
===================

- Fixed issue in Linux wheels where the OpenMP library wasn't properly
  linked to (also fixed the setup.py script for the underlying issue).

v1.8.2 (2023-02-28)
===================

- Added actionAngleVertical to the public API, an actionAngle class for
  1D action-angle calculations. actionAngleVertical was used internally in galpy
  before, but now follows the usual method structure for actionAngle classes.

- Added actionAngleVerticalInverse, an inverse actionAngle class that allows one
  to go from (x,v) -> (J,theta,Omega) for 1D potentials using a custom
  implementation of the torus machinery with point transformations.

- Made it possible to use an interpSphericalPotential as the potential in spherical
  distribution functions (#554)

- Made the potential input explicitly positional-only for all galpy.potential
  functions to avoid errors when specifying it as a keyword argument.

- Rewrite actionAngleAdiabatic's Python implementation as a combination of
  actionAngleSpherical (for the 2D planar part) and actionAngleVertical (for
  the 1D vertical part).

- Dropped Python 3.7 support (to allow required positional-only arguments
  using PEP 570).

- Dropped Appveyor CI builds entirely, now only using GitHub Actions for CI.

- Added Orbit.animate3d to display a 3D animation of an integrated orbit (#532)
  with an optional Milky-Way representation at the origin when plotting x,y,z.

- Improved the performance of Orbit.animate performance by using webgl, some UI
  tweaks. Also fixed using Orbit.animate in jupyterlab and retrolab (latter
  #534).

- Run tests with deprecation warnings of various types (DeprecationWarning,
  FutureWarning, AstropyDeprecationWarning) turned into errors to guard against
  coming deprecations (#538)

v1.8.1 (2022-10-31)
===================

- Changed estimateDeltaStaeckel to by default return delta0=1e-6 when
  delta<delta0, because giving delta=0 to an actionAngleStaeckel instance
  does not work.

- Added pre-commit hooks. Many changes to all files for imports, code style,
  spelling, etc.

- Added dependabot alerts to keep GitHub Actions dependencies up to date.

- Added Python 3.11 wheels for all major platforms. Added Python >=3.8 wheels
  for arm64 Macs (M1s)

- Switched to using cibuildwheel to build Linux, Mac (incl. M1/arm64), and
  Windows wheels.

- Switched to using pyodide-build to build the pyodide wheel.

v1.8.0 (2022-07-04)
===================

- Added the particle-spray model galpy.df.streamspraydf that was
  previously part of the jobovy/streamtools package (#479).

- Added necessary derivatives to allow spherical DFs to be constructed using
  PowerSphericalPotentialwCutoff and PlummerPotential.

- Updated existing and added new phase-space positions for MW satellite
  galaxies from Pace et al. (2022; 2205.05699). Also add uncertainties
  (#484 by Anya Dovgal).

- Updated existing and added new phase-space positions for MW globular clusters
  from Baumgardt et al. (2019; 1811.01507),
  Vasiliev & Baumgardt (2021; 2102.09568), and
  Baumgardt & Vasiliev (2021; 2105.09526). Also add uncertainties
  (#485 by Anya Dovgal).

- Added SCFPotential.from_density to directly initialize an SCFPotential based
  on a density function. Allows for full correct and consistent handling of
  Quantity inputs and outputs.

- Renamed phiforce --> phitorque everywhere (including
  potential.evaluatephiforces and potential.evaluateplanarphiforces), such that
  the method's name actually reflect what it returns (a torque, not a force).
  phiforce will be fully removed in version 1.9 and may later be reused
  for the actual phi component of the force, so switch to the new name now.

- Added code to check whether a newer version of galpy is available and, if so
  encourage users to upgrade (to try to have people use more recent versions).

- Added a 'Try galpy' interactive session on the documentation's home page
  powered by the new pyodide/emscripten/wasm wheels for galpy.

- Add support to build pyodide/emscripten/wasm wheels for using galpy in the
  browser at C-ish speeds.

- Fully drop Python 2 support (removed all Python 2 compatibility code).

v1.7.2 (2022-04-15)
===================

- Added NonInertialFrameForce, which provides the fictitious forces
  when integrating orbits in non-inertial frames. Arbitrary rotations
  and origin accelerations are supported (#471).

- Added a progress bar when integrating multiple objects in a single
  orbit instance (requires tqdm) (see #476).

- Turn on NFWPotential physical output when initializing using the
  virial mass mvir (see #465)

- Added TimeDependentAmplitudeWrapperPotential, a wrapper allowing
  for arbitrary time dependence of the amplitude of any potential.

- Added NullPotential, a potential with a constant value.

- Added Potential methods/functions rE and LcE to compute the radius
  and angular momentum of an orbit with energy E. Also added these
  as Orbit methods for efficient calculation for collections of
  orbits.

- Added the offset= keyword to RotateAndTiltWrapperPotential, which allows
  a Potential/Force instance to also be offset from (0,0,0) in addition to
  being rotated or tilted.

- Allow actions to be computed for Orbit instances with actionAngle
  methods that don't compute frequencies.

- Correctly parse potential method/function R/z/x inputs if they
  are given as keyword arguments.

v1.7.1 (2021-11-17)
===================

- Main reason for this minor version is	to add a Python	3.10 wheel

v1.7 (2021-07-04)
=================

- Added a general framework for spherical distribution function as
  well as a general implementation of (a) the Eddington inversion to
  obtain the ergodic distribution function, (b) the equivalent
  inversion to get the Osipkov-Merritt-style anisotropy, and (c) the
  Cuddeford inversion to obtain a distribution function with constant
  anisotropy, all three for any spherical density in any spherical
  potential (where it exists). Also added the distribution function of
  a few well-known distribution functions, including (a) Hernquist
  distribution functions that are isotropic, have constant anisotropy,
  or have Osipkov-Merritt type anisotropy; (b) an isotropic Plummer
  profile; (c) the isotropic NFW profile (either using the
  approx. from Widrow 2000 or using an improved approximation) and the
  Osipkov-Merritt NFW profile (new approximate form); (d) the King
  model (also added as a potential as KingPotential). These
  distribution functions can be evaluated and sampled, and their
  velocity moments can be computed. Work started in #432 and continued
  on from there. Distribution functions with constant anisotropy
  require the JAX.

- Implemented the calculation of SCF density/potential expansion
  coefficients based on an N-body representation of the density
  (#444).

- Added NFWPotential initialization method using rmax and vmax, the
  radius and value at which the rotation curve peaks; also added rmax
  and vmax methods to NFWPotential to compute these quantities for any
  NFWPotential.

- Added general class SphericalPotential to make defining spherical
  potentials easier (#424).

- Added interpSphericalPotential class to build interpolated versions
  of spherical potentials (#424).

- Added AdiabaticContractionWrapperPotential, a wrapper potential to
  adiabatically contract a spherical dark-matter halo in response to
  the adiabatic growth of a baryonic component.

- Added potential functions to compute the zero-velocity curve: zvc
  and zvc_range; the latter computes the range in R over which the
  zero-velocity curve is defined, the former gives the positive z
  position on the zero-velocity curve for a given radius in this
  range.

- Added potential function and method rhalf to compute the half-mass
  radius.

- Added potential function and member tdyn to compute the dynamical
  time from the average density.

- Added TriaxialGaussianPotential, the potential of a Gaussian that is
  stratified on triaxial ellipsoids (Emsellem et al. 1994). Useful for
  implementing multi-Gaussian expansions of galactic potentials.

- Added PowerTriaxialPotential, the potential of a triaxial power-law
  density (like PowerSphericalPotential, but triaxial).

- Added AnyAxisymmetricRazorThinDiskPotential, the potential of an
  arbitrary razor-thin, axisymmetric disk.

- Added AnySphericalPotential, the potential of an arbitrary spherical
  density distribution.

- Added RotateAndTiltWrapperPotential, a wrapper potential to
  re-orient a potential arbitrarily in three dimensions using three
  angles.

- Updated the definition of a Potential's mass to always return the
  mass within a spherical shell if only one argument is
  specified. Also implemented faster implementations of the masses of
  SCF and diskSCF potentials.

- Added mixed azimuthal,vertical second derivative for all
  non-axisymmetric potentials: potential function evaluatephizderivs
  and Potential method phizderiv.

- Added inverse action-angle transformations for the isochrone
  potential (actionAngleIsochroneInverse) and for a one-dimensional
  harmonic oscillator (actionAngleHarmonicInverse; also added the
  [x,v] -> [J,O,a] transformation for the latter,
  actionAngleHarmonic).

- Added Potential.plotSurfaceDensity (potential.plotSurfaceDensities)
  method (function) to plot the surface density of a Potential
  instance (of Potential instance of a list of Potential instances).

- Re-implemented the DoubleExponentialDiskPotential in a simpler and
  more accurate manner, using the double-exponential formula (no
  relation) for integrals of Bessel functions from Ogata 2005. The
  DoubleExponentialDiskPotential is now calculated to ~machine
  precision almost everywhere and there is no longer any switch to a
  Keplerian behavior at large R.

- Made potentials as much as possible numerically stable at r=0 and
  r=numpy.inf (i.e., they don't give NaN). Still a few missing, but
  the majority of potentials are well behaved now.

- Fixed angle calculation for actionAngleIsochrone and
  actionAngleSpherical for non-inclined orbits (which are tricky).

- Replace Quantity parsing through the package as much as possible
  with a set of centralized parsers (#430).

- Renamed galpy.util.bovy_coords to galpy.util.coords,
  galpy.util.bovy_conversion to galpy.util.conversion, and
  galpy.util.bovy_plot to galpy.util.plot (but old 'from galpy.util
  import bovy_X' will keep working for now). Also renamed some other
  internal utility modules in the same way (bovy_symplecticode,
  bovy_quadpack, and bovy_ars; these are not kept
  backwards-compatible).

- Added Python 3.9 support.

- Switched Linux CI from Travis to GitHub Actions. Also added Windows
  CI to GitHub Actions covering almost all tests. Appveyor CI for
  Windows also still running.

v1.6 (2020-04-24)
=================

- Added HomogeneousSpherePotential, the potential of a constant
  density sphere out to some radius R.

- Added DehnenSphericalPotential and DehnenCoreSphericalPotential, the
  general potential from Dehnen (1993) and its cored special case
  (#403).

- Standardized the way packages are imported: numpy as 'import numpy',
  avoid use of math, don't use scipy's numpy interface, internal
  imports for all galpy imports.

- Implemented ChandrasekharDynamicalFrictionForce in C, introducing a
  general scheme for easily implementing velocity-dependent forces in
  C without requiring all forces to take velocity arguments (#420).

- Fixed AMUSE compatibility with Potentials instantiated with physical
  inputs (#405).

- Fix how DiskSCFPotential instances with a hole in the surface
  density get passed to C (was wrong when type == 'exp', but 'Rhole'
  was in the list of parameters, hole was not passed; meant that
  McMillan17 was wrong in C in v1.5).

- Add time dependence to all relevant Potential functions and method
  (#404).

- Raise warning when r < minr (where dynamical friction gets turned
  off) in an orbit integration that includes dynamical friction (to
  avoid silent turning off of the dynamical friction force; #356).

- Improve performance of orbit animations (#414).

- Fixed compilation issue for Intel compilers: no need to include
  'lgomp' in the linking step (#416).

- Compile all main galpy C extensions into a single shared-object
  library libgalpy.

- Automatically build Linux, Mac, and Windows wheels with GitHub
  Actions and upload them to PyPI upon release creation (#421).

v1.5 (2019-09-12)
=================

- Added support for holding multiple objects in an Orbit instance,
  with efficient handling of multiple objects and parallelized
  integration and action-angle-related functions. Orbit instances can
  now have arbitrary shapes. Full re-write of Orbit class (PR #384).

- Added support for 1D orbit integration in C (PR #354).

- Added a (JSON) list with the phase-space coordinates of known
  objects (mainly globular clusters and dwarf galaxies) for easy
  Orbit.from_name initialization. For ease of use,
  Orbit.from_name also supports tab completion for known objects in
  this list in IPython/Jupyter (PR #392).

- Added the galpy.potentials.mwpotentials module with various
  Milky-Way-like potentials. Currently included are MWPotential2014,
  McMillan17 for the potential from McMillan (2017), models 1 through
  4 from Dehnen & Binney (1998), and the three models from Irrgang et
  al. (2013). See PR #395.

- Added potential.to_amuse to create an AMUSE
  (http://www.amusecode.org) representation of any galpy potential,
  allowing galpy potentials to be used as external gravitational
  fields in AMUSE N-body simulations (#398).

- Added potential.toVerticalPotential to convert any 3D potential to a
  1D potential at a given (R,phi) [generalizes RZToverticalPotential
  to non-axi potentials; RZToverticalPotential retained for backwards
  compatibility].

- Re-wrote potential.MovingObjectPotential to allow general mass
  distributions for the moving object, implemented now as standard
  galpy potentials rather than with separate ForceSoftening class,
  which has now been removed (#355). Initialization keywords for
  potential.MovingObjectPotential have changed because of this in a
  non-backwards-compatible manner.

- Added support to combine Potential instances or lists thereof
  through the addition operator. E.g., pot= pot1+pot2+pot3 to create
  the combined potential of the three component potentials
  (pot1,pot2,pot3). Each of these components can be a combined
  potential itself. As before, combined potentials are simply lists of
  potentials, so this is simply an alternative (and perhaps more
  intuitive) way to create these lists (#369).

- Added support to adjust the amplitude of a Potential instance
  through multiplication of the instance by a number or through
  division by a number. E.g., pot= 2.*pot1 returns a Potential instance
  that is the same as pot1, except that the amplitude is twice
  larger. Similarly, pot= pot1/2. decreases the amplitude by a factor
  of two. This is useful, for example, to quickly change the mass of a
  potential. Only works for Potential instances, not for lists of
  Potential instances (#369).

- Added support to plot arbitrary combinations of the basic Orbit
  attributes by giving them as an expression (e.g.,
  orb.plot(d2='vR*R/r+vz*z/r')); requires the numexpr package.

- Switched default Sun's vertical height zo parameter for Orbit
  initialization to be the value of 20.8 pc from Bennett & Bovy
  (2019).

- Added IsothermalDiskPotential, the one-dimensional potential of an
  isothermal self-gravitating disk (sech^2 profile).

- Added NumericalPotentialDerivativesMixin, a Mixin class to add
  numerically-computed forces and second derivatives to any Potential
  class, allowing new potentials to be implemented quickly by only
  implementing the potential itself and obtaining all forces and
  second derivatives numerically.

- Added nemo_accname and nemo_accpars for the HernquistPotential,
  allowing it to be converted to NEMO.

- DehnenSmoothWrapperPotential can now decay rather than grow a
  potential by setting ``decay=True``.

- DehnenBarPotential and SpiralArmsPotential method now work for array
  inputs (PR #388, by @webbjj).

- Allow transformations of custom coordinate systems (positions
  and proper motions) to ICRS (ra,dec) and (pmra,pmdec).

- Allow orbit integrations to be KeyboardInterrupted on Windows as well
  (#362 by Henry Leung)

- Add Python and C implementation of Dormand-Prince 8(5,3) integrator
  (#363 by Henry Leung)

- Added function galpy.util.bovy_conversion.get_physical to obtain the
  ro and vo parameters describing the conversion between physical and
  internal units as a dictionary. This works for any galpy object or
  lists of such objects.

- Improved efficiency of requesting an integrated orbit at the exact
  times at which it was integrated (~10x faster now).

v1.4 (2018-09-09)
=================

- Added ChandrasekharDynamicalFrictionForce, an implementation of
  dynamical friction based on the classical Chandrasekhar formula
  (with recent tweaks from the literature to better represent the
  results from N-body simulations).

- Added galpy.df.jeans with tools for Jeans modeling. Currently only
  contains the functions sigmar and sigmalos to calculate the velocity
  dispersion in the radial or line-of-sight direction using the
  spherical Jeans equation in a given potential, density profile, and
  anisotropy profile (anisotropy can be radially varying).

- Added CorotatingRotationWrapperPotential to galpy.potential: a
  wrapper to make a pattern wind up over time such that it is always
  corotating (for use in simulating corotating spiral structure like
  that of Grand, Kawata, Baba, et al.)

- Added GaussianAmplitudeWrapperPotential to galpy.potential: a
  wrapper to modulate the amplitude of any Potential instance with a
  Gaussian (growing from zero to the full amplitude and dying off
  again).

- Added a general class EllipsoidalPotential that is a superclass for
  implementing potentials with densities that are constant on
  ellipsoids (functions of m^2 = x^2 + y^2/b^2 + z^2/c^2). Also
  implemented in C. Implementing new types of ellipsoidal potentials
  now only requires three simple functions to be defined: the density
  as a function of m, its derivative with respect to m, and its
  integral with respect to m^2 (#348).

- Added PerfectEllipsoidPotential, the potential of a perfect
  ellipsoid (de Zeeuw 1985): this is a fully integrable
  (Staeckel-type), triaxial potential.

- Re-implemented TwoPowerTriaxialPotential and special cases
  TriaxialHernquistPotential, TriaxialJaffePotential, and
  TriaxialNFWPotential using the general EllipsoidalPotential class.

- Allow nested lists of Potential instances everywhere where lists of
  Potential instances were previously allowed; allow easy adding of
  components (e.g., a bar) to previously defined potentials (which may
  be lists themselves): new_pot= [pot,bar_pot].

- Add from_name class method of Orbit, which allows Orbit instances to
  be initialized using the coordinates of a named object found in SIMBAD.

- Add rguiding method of Orbit, to compute the guiding-center radius
  of an orbit. Also added Lz method to easily obtain the z-component
  of the angular momentum for different types of orbits.

- Defined Orbit initialization without any arguments (or, more
  generally, without specifying the vxvv initial phase-space input) to
  return an Orbit instances representing the Sun. Can therefore setup
  an Orbit representing the Sun's as o= Orbit().

- Allow Orbit instances to be initialized using a SkyCoord with
  position and velocity data, with optional Galactocentric frame
  specification as part of the SkyCoord that is correctly propagated
  to the Orbit instance. Requires astropy>3

- Added rtide and ttensor methods/functions for Potentials: tidal
  radius and tidal tensor.

- Added surfdens and evaluateSurfaceDensities method and function,
  respectively, for Potentials for evaluating the surface density up
  to a given z.

- Added potentials SphericalShellPotential and RingPotential for the
  potential of a spherical shell and a circular ring,
  respectively. Useful for talking about Newton's theorems.

- Switched default solarmotion parameter for Orbit initialization to
  be schoenrich (for the Schoenrich, Binney, & Dehnen 2010 solar
  motion wrt the LSR).

- Added Potential method r2deriv and function evaluater2derivs to
  evaluate the second derivative wrt the spherical radius. Also added
  convenience functions evaluatephi2derivs and evaluateRphiderivs.

- Added quasiisothermaldf method sampleV_interpolate that allows
  velocities at different positions to be sampled efficiently
  (quasiisothermaldf.sampleV only works for a single position). See PR
  #350.

- Add warnings/verbose configuration parameter to set level of
  verbosity of non-crucial warnings (like: "Using C implementation to
  integrate orbits").

- If astropy version > 3, Orbit.SkyCoord returns a SkyCoord object
  that includes the velocity information and the Galactocentric frame
  used by the Orbit instance.

- Tweaked coordinate-transformations to Galactocentric coordinates to
  be consistent with astropy's.

- Introduced general Force class of which Potential and
  DissipativeForce inherit, the former for forces that derive from a
  potential, the latter for those that do not.

- Introduced DissipativeForce, a superclass for all dissipative
  forces. ChandrasekharDynamicalFrictionForce is currently the only
  class that inherits from DissipativeForce.

- Re-arranged the package structure to better comply with the standard
  layout. All subpackages (e.g., galpy.potential) are now contained in
  subdirectories of the same name (e.g., galpy/potential/ rather than
  the old galpy/potential_src/).

- Made the code fully compilable on Windows with MSVC and test Windows
  builds automatically on appveyor (#333).

v1.3 (2018-02-06)
==================

- Added a fast and precise method for approximating an orbit's
  eccentricity, peri- and apocenter radii, and maximum height above
  the midplane using the Staeckel approximation (see Mackereth & Bovy
  2018); available as an actionAngle method EccZmaxRperiRap and for
  Orbit instances through the e, rperi, rap, and zmax methods.

- Added support for potential wrappers---classes that wrap existing
  potentials to modify their behavior (#307). See the documentation on
  potentials and the potential API for more information on these.

- Added DehnenSmoothWrapperPotential, a potential wrapper to smoothly
  grow a gravitational potential (e.g., a bar) following Dehnen
  (2000).

- Added SolidBodyRotationWrapperPotential, a potential wrapper to make
  a gravitational potential rotate around the z axis with a fixed,
  uniform pattern speed.

- Added DiskSCFPotential, a class that implements general
  density/potential pairs for disk potentials by combining Kuijken &
  Dubinski (1995)'s trick for turning a separable disk density
  [rho(R,z) = \Sigma(R) x h(z)] into a ellipsoidal-ish density, with
  the SCF basis-function-expansion approach of Hernquist & Ostriker
  (1992) for solving for the ellipsoidal-ish density's potential. This
  is a fully general Poisson solver (i.e., any density can be
  represented in this way).

- Added SoftenedNeedleBarPotential, a simple potential for a bar that
  consists of a needle softened by a Miyamoto-Nagai kernel (Long &
  Murali 1992).

- Added FerrersPotential, a class that implements the potential for
  triaxial ellipsoids (Binney & Tremaine 2008, Ch 2.5) with an option
  to give a pattern speed to the ellipsoid.

- Added SpiralArmsPotential, a class that implements the spiral arms
  potential from Cox and Gomez
  (2002). https://arxiv.org/abs/astro-ph/0207635v1 (#305)

- Added the Henon & Heiles (1964) potential

- Added an Orbit method to display an animation of an integrated orbit
  in jupyter notebooks (Orbit.animate).

- Added galpy.df.schwarzschilddf, the simple Schwarzschild
  distribution function for a razor-thin disk.

- Upgraded LogarithmicHaloPotential to allow it to be a triaxial
  potential.

- Upgraded DehnenBarPotential to a 3D potential following Monari et
  al. (2016) (#304).

- Generalized CosmphiDiskPotential to allow for a break radius within
  which the radial dependence of the potential changes from R^p to
  R^-p; also added C implementation of CosmphiDiskPotential.

- Changed default method for computing actions, frequencies, and
  angles for Orbit instances to be the Staeckel approximation with an
  automatically-estimated delta parameter.

- Added an option to the estimateDeltaStaeckel function to facilitate the
  return of an estimated delta parameter at every phase space point passed,
  rather than returning a median of the estimate at each point.

- Generalized actionAngleStaeckel to allow for different focal lengths
  delta for different phase-space points. Also allowed the order of
  the Gauss-Legendre integration to be specified (default: 10, which
  is good enough when using actionAngleStaeckel to compute approximate
  actions etc. for an axisymmetric potential).

- Allow transformations of (ra,dec) and (pmra,pmdec) to custom
  coordinate systems.

- Allow plotting of the spherical radius in Orbit.plot

- Allow plotting of arbitrary user-supplied functions of time in
  Orbit.plot, Orbit.plot3d, and Orbit.animate.

- Added conversion to and from oblate spheroidal coordinates. Also
  added conversion of velocities to the momenta in oblate or prolate
  spheroidal coordinates (but not the other way around).

- Made SCFPotential compatible with GSL v2.

- Orbit methods now all return a scalar when called with a single
  time (see #247 and #294).

- Added a warning whenever the orbit-integration method that is used
  is different from the requested one (for when C integration falls
  back onto Python; see #286).

- Turn off changing the seaborn default plot configuration to that
  preferred by this code's maintainer; can be turned back on by
  specifying ``seaborn-bovy-defaults = True`` in the configuration
  file (see documentation). Old configuration files will be
  automatically updated to add this option (but remain otherwise the
  same).

- Added button to code examples in the documentation that copies the
  examples to the user's clipboard for easy pasting into a Python
  interpreter.

- Switched test suite from nose to pytest (#303).

- quasiisothermaldf.tilt return unit switched from deg to rad.

- streamdf.misalignment return unit switched from deg to rad.

- evolveddiskdf.vertexdev return unit switched from deg to rad.

- In quasiisothermaldf.py, the following prefactors were added
  to the following functions: [nsigma^2/2] --> pvT(),
  [nsigma/2] --> pvRvT(), [nsigma/2] --> pvTvz(),
  [vTmax/2] --> pvRvz(). This change was required to correctly
  account for the Gauss-Legendre integration limits.

v1.2 (2016-09-06)
==================

- Added support for providing inputs to all initializations, methods,
  and functions as Quantities with units and for providing outputs as
  astropy Quantities. See pull request #258 and the documentation for
  full details.

- Added TwoPowerTriaxialPotential, a set of triaxial potentials with
  iso-density contours that are arbitrary, similar, coaxial ellipsoids
  whose 'radial' density is a (different) power-law at small and large
  radii: 1/m^alpha/(1+m)^beta-alpha (the triaxial generalization of
  TwoPowerSphericalPotential, with flattening in the density rather
  than in the potential, see Merritt & Fridman 1996, Binney & Tremaine
  2008). These include triaxial Hernquist and NFW potentials. Includes
  fast C implementations that allow efficient orbit integration in
  these potentials (<~5 ms / orbit).

- Added SCFPotential, a class that implements general
  density/potential pairs through the basis expansion approach to
  solving the Poisson equation of Hernquist & Ostriker (1992).  Also
  implemented functions to compute the coefficients for a given
  density function.

- Implemented galpy.actionAngle.actionAngleIsochroneApprox (Bovy 2014)
  for the general case of a time-independent potential, allowing
  action-angle coordinates to be computed for triaxial
  potentials. Previously, this module only supported axisymmetric
  potentials. Also allow the maximum number of terms in the expansion
  to be set object-wide and allow a fixed time-step to be used in the
  necessary orbit integration.

- Added an (experimental) interface to Binney & McMillan's TorusMapper
  code for computing positions and velocities for given actions and
  angles. See the installation instructions for how to properly
  install this.

- Re-defined the amplitude parameters of a few potentials to allow for
  easier setups with amplitudes provided as Quantities with
  units. This is the case for FlattenedPowerPotential,
  PowerSphericalPotential, and PowerSphericalPotentialwCutoff,
  CosmphiDiskPotential, LopsidedDiskPotential, and
  EllipticalDiskPotential.

- Added a module for modeling the effect of a subhalo impact on a
  tidal stream (galpy.df.streamgapdf); see Sanders, Bovy, & Erkal
  (2016). Also includes the fast methods for computing the density
  along the stream and the stream track for a perturbed stream from
  Bovy, Erkal, & Sanders (2016).

- Added functions to galpy.df.streamdf to compute the length of the
  stream, the density along the stream quickly (in various
  coordinates, including custom sky coordinates), to compute the
  probability p(freq_parallel,angle_parallel), and to estimate the
  number of encounters with DM subhalos. Also allow the stream track
  to be computing using the new actionAngleTorus (this last addition
  is still very experimental).

- Added PseudoIsothermalPotential, a standard pseudo-isothermal-sphere
  potential.

- Added KuzminDiskPotential, a potential represented by a razor thin
  disk

- Allow transformations to custom sets of sky coordinates in
  galpy.util.bovy_coords.

- Added the spherical radius as an Orbit method.

- Added the spherical-radial force as a Potential method (rforce) and
  function (evaluaterforces).

- Support for flipping the velocities of an orbit in-place (useful for
  backwards integration).

- quasiisothermaldf input ro replaced by refr to avoid clash with ro
  that specifies units (see above).

- Properly intercept CTRL-C (SIGINT) signals during orbit integration
  in C, allowing long orbit integrations to be interrupted without
  killing an entire Python session.

- Internally use astropy.coordinates transformations to transform
  between (ra,dec) and (l,b). Can be tuned using the astropy-coords
  configuration parameter. Also allow general epochs for the (ra,dec)
  specification.

v1.1 (2015-06-30)
==================

- Added Python 3 support: in particular, Python 3.3 and 3.4 are now
  supported; earlier 3.* may also work, but haven't been
  tested. Python 2 and 3 are supported using a single common codebase.

- Added SnapshotRZPotential and InterpSnapshotRZPotential potential
  classes: these can be used to get a frozen snapshot of the potential
  of an N-body simulation into galpy. SnapshotRZPotential directly
  calculates the potential and forces using direct summation;
  InterpSnapshotRZPotential builds an interpolation table (it's a
  subclass of interpRZPotential and can be used in the same way). This
  code was mainly written by Rok Roskar.

- Added KuzminKutuzovStaeckelPotential, a Staeckel potential that can
  be used to approximate the potential of a disk galaxy (see Batsleer
  & Dejonghe 1994).

- Added MN3ExponentialDiskPotential that gives the approximation to a
  radially-exponential disk potential as three Miyamoto-Nagai disks
  from Smith et al. (2015; arXiv:1502.00627v1)

- Added PlummerPotential, a standard Plummer potential.

- Add support for converting potential parameters to NEMO format and
  units: nemo_accname and nemo_accpars (both instance and general
  Potential method).

- Added nemo/ directory for C++ implementations of additional NEMO
  potentials (not included in the NEMO release); add PowSphwCut.cc for
  PowerSphericalPotential2Cutoff and Makefile to compile and install
  it. This allows gyrfalcON simulations with MWPotential2014.

- Allow user to directly specify the integration step size to use in
  orbit integration.

- Better implementations of vcirc, eipfreq, and verticalfreq for lists
  of potentials that allows for negative amplitude components.

- Improvements to streamdf: add progIsTrack keyword to specify that
  the progenitor= keyword actually specifies the desired starting
  phase-space point of the track; the phase-space point of the
  progenitor is calculated. Refactored streamdf setup to make this
  easy to implement.

- Orbit fitting can now be performed in custom sky coordinates
  (requires one to specify customsky=True and to implement and pass
  the functions (a) lb_to_customsky= and (b) pmllpmbb_to_customsky=,
  similar to lb_to_radec and pmllpmbb_to_pmradec). For example, this
  allows one to do an orbit fit in the GD-1 frame of Koposov et
  al. (2010).

- Orbit.time now returns the times at which an Orbit is integrated if
  called without arguments.

- Slightly improved implementation of actionAngleStaeckel.py (more
  robust umin/umax finding).

v1.0 (2014-12-10)
==================

- Added MWPotential2014: a Milky-Way-like potential fit to a bunch of
  relevant data on the Milky Way; supersedes MWPotential, which is
  still included; changed many examples to use this new potential;

- Changed default integrator to symplec4_c;

- Changed default vo and ro to 220 km/s and 8 kpc, respectively;

- Allow Orbit initialization to specify a distance and velocity scale
  that is then used to output distances, velocities, energies,
  actions, etc. in physical coordinates;

- Added an orbit-fitting routine (Orbit.fit).

- Added virial radius of NFW potential, allow initialization of NFW
  potential with concentration and mass;

- Added potential.mass to return the mass enclosed for individual
  potential instances; both spherical and axisymmetric potentials are
  covered.

- Sped up many of the functions in galpy.util.bovy_coords by removing
  scipy.frompyfunc dependency;

- Added galpy.util.bovy_conversion.dens_in_gevcc,
  galpy.util.bovy_conversion.force_in_10m13kms2,
  galpy.util.bovy_conversion.dens_in_criticaldens,
  galpy.util.bovy_conversion.dens_in_meanmatterdens.

- Much improved test coverage.

- Added planarPotential.LinShuReductionFactor to calculate the
  reduction factor for the response of a kinematically warm population
  to a spiral perturbation.

- Added non-axisymmetric DFs to the top-level and the documentation.

- New streamdf track calculation (see arXiv_v2/published version of
  Bovy 2014); better handdling of coordinate-transformation
  parameters in streamdf.

- Installation now prints informative message about whether or not the
  C extensions were installed.

- More informative warning messages when C functions are not used.

- Fix issues with non-square grids in the C implementation of
  interpRZPotential.

- Added Orbit.flip to generate new Orbit instances with flipped
  velocities.

- Improved actionAngle frequencies for circular orbits.

- Removed actionAngleFlat and actionAnglePower, because they are
  superseded.

- Added hasC_dxdv member to Potential instances to indicate whether or
  not they can be used with integrate_dxdv

- Add C implementation of PowerSphericalPotentialwCutoff;

- Moved MovingObjectPotential, BurkertPotential, and interpRZPotential
  to top level; better implementation of interpRZPotential;

- Better handling of vo,ro, and solarmotion in Orbit instances (Orbit
  initialization value is now used to generate RA, Dec, etc. outputs);

- Added --no-openmp installation option to allow installation without
  OpenMP support (workaround for clang not supporting OpenMP; not
  necessary anymore);


v0.1 (2014-01-09)
==================

- Initial release
