pypi galpy 1.12.1
Version 1.12.1

2 hours ago

This release adds truncated NFW and Hernquist potentials, time-dependent SCFPotentials built from functions, densities, or N-body snapshots, variational (integrate_dxdv) integration with the symplectic integrators and for 1D orbits, and a smooth P-spline reconstruction of stream tracks, along with many accuracy improvements (several of which change numerical results, e.g., actionAngleStaeckel and actionAngleAdiabatic with c=True and velocity sampling from spherical distribution functions; see HISTORY.txt), bug fixes, speed-ups, wheels for Python 3.15, and dependency/project maintenance updates.

Major changes

  • TruncatedNFWPotential and TruncatedHernquistPotential (Baltz, Marshall & Oguri 2009) by @jobovy-agent in #1743:

    The new TruncatedNFWPotential and TruncatedHernquistPotential are the NFW and Hernquist profiles with the smooth truncation of Baltz, Marshall & Oguri (2009), (rc^2 / (rc^2 + r^2))^n, with closed-form mass, potential, forces, and second derivatives accurate to ~1e-14. The truncation radius can depend on time, for example to model a satellite that is stripped from the outside in as the pot of a MovingObjectPotential. Both have C implementations and can be used with the spherical distribution functions.

  • Add time-dependent support to SCFPotential by @jobovy with Claude in #1058

  • Add SCFPotential.from_nbody for N-body / particle initialization by @jobovy with Claude in #1061

  • Translate between SCFPotential and MultipoleExpansionPotential by @jobovy with Claude in #1062:

    SCFPotential can now be time-dependent: its expansion coefficients can be functions of time, or be sampled on a time grid, and are interpolated with a cubic spline, with fast evaluation in Python and C; SCFPotential.from_density builds one from a time-dependent density. The new SCFPotential.from_nbody builds an expansion directly from particle positions and masses (a time-dependent one from multiple snapshots), and SCFPotential.from_multipole and MultipoleExpansionPotential.from_scf translate between the SCF and multipole representations.

  • Symplectic C integrators: variational (dxdv) integration — leapfrog_c/symplec4_c/symplec6_c differentiable by @jobovy with Claude in #1086

  • 1D (linear-orbit) variational (dxdv) integration — RK + symplectic by @jobovy with Claude in #1091

  • doc: symplectic and 1D (linear) dxdv examples in the phase-space/chaos tutorial by @jobovy with Claude in #1093:

    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 that the state-transition matrix is symplectic to machine precision. integrate_dxdv also now supports 1D orbits, with both the Runge-Kutta and the symplectic integrators.

  • streamTrack: a smooth P-spline reconstruction (method="pspline") as the default by @jobovy-agent in #1732:

    streamspraydf.streamTrack and StreamTrack.from_particles now reconstruct the track by default with a penalized-spline fit of the particles' offsets from the progenitor's orbit, with each coordinate's smoothing 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. The previous reconstruction remains available as method='binned'.

New Features

  • isConservative: symplectic integration for forces that derive from a potential, including a frame that only accelerates by @jobovy-agent in #1748
  • linearPotential: x2deriv and evaluatelinearx2derivs, the second derivative of 1D potentials by @jobovy-agent in #1519
  • actionAngleVerticalInverse: exact (ODE-based) point transformation by @jobovy-agent in #1309
  • Integrate the 1D exact point transformation in the auxiliary angle by @jobovy-agent in #1320
  • Exact 1D point transformation by quadrature instead of ODE integration by @jobovy-agent in #1351
  • Unit support for actionAngleVerticalInverse by @jobovy-agent in #1342
  • actionAngleVerticalInverse: the momentum-matched canonical map by @jobovy-agent in #1415
  • actionAngleVerticalInverse: speed up the momentum-matched evaluation (Newton on the closed-form derivative) and construction by @jobovy-agent in #1515
  • actionAngleVerticalInverse: the map's action derivatives on each torus, stored as Hermite constraints of the family by @jobovy-agent in #1517
  • OblateStaeckelWrapperPotential: optional tabulated C evaluation (ntab=), ~10-16x faster C integration by @jobovy-agent in #1468
  • actionAngleStaeckel: the focal length from a potential that supplies one by @jobovy-agent in #1560
  • PerfectEllipsoidPotential: the focal length of an axisymmetric oblate perfect ellipsoid by @jobovy-agent in #1561
  • dehnendf/shudf moments: accept a numpy array of radii by @jobovy-agent in #1651
  • SphericalShell/HomogeneousSphere: accept array input; numpy.infty -> numpy.inf by @jobovy-agent in #1324
  • Orbit.from_name: fall back on the other SIMBAD mirrors when one cannot be reached by @jobovy-agent in #1770
  • Add Python 3.15 wheels by @jobovy with Claude in #1583
  • Build Pyodide wheels for Python 3.14 by @jobovy in #1590

Speed-ups

  • Speed up ChandrasekharDynamicalFrictionForce construction ~100x for array-capable potentials by @jobovy-agent in #1422
  • ChandrasekharDynamicalFrictionForce: the force cache has never hit (2.1x on the friction path) by @jobovy-agent in #1484
  • Do not fork a worker per task when numcores=1 (Orbit.lyapunov 94x faster) by @jobovy-agent in #1458
  • actionAngleIsochroneInverse: solve Kepler's equation for all angles at once by @jobovy-agent in #1405
  • interpRZPotential: build the sampling grids with one vectorised call by @jobovy-agent in #1294
  • Orbit: analytic e/rperi/rap/zmax no longer rebuild the spherical-fallback actionAngle on every call by @jobovy-agent in #1660
  • actionAngleStaeckel (c=False): chi-anomaly quadrature mesh matches C (1.6x faster, same accuracy) by @jobovy-agent in #1644

Accuracy improvements

  • actionAngleStaeckel: regularize the action quadratures' sqrt turning points (C + Python) by @jobovy-agent in #1357
  • actionAngleStaeckel: chi-anomaly quadrature at the turning points in C by @jobovy-agent in #1404
  • actionAngleStaeckel C: frequencies and angles near turning points by @jobovy-agent in #1424
  • actionAngleStaeckel C: NaN and near-axis accuracy in the chi quadratures by @jobovy-agent in #1431
  • actionAngleAdiabatic: regularize the action integrands' sqrt endpoints (fixes #1354) by @jobovy-agent in #1356
  • actionAngleSpherical: circular and near-circular orbits by @jobovy-agent in #1527
  • actionAngleSpherical: decide boundedness at infinity, not at a fixed radius by @jobovy-agent in #1553
  • OblateStaeckelWrapperPotential: choose the reference curve from delta by @jobovy-agent in #1379
  • potentials: machine-precision small r (NFW, Burkert, TwoPower), finite edge limits, Staeckel midplane vmin by @jobovy-agent in #1585
  • TwoPowerSphericalPotential: forces, second derivatives and mass from the incomplete beta (accurate near beta = 3, finite at large r) by @jobovy-agent in #1596
  • eddingtondf: f(E) accurate near Emin (NFW was NaN/negative there) by @jobovy-agent in #1586
  • Dynamical friction: sigma_r on a log-r grid (was 20-60% off at small r); Python evaluates C's natural spline by @jobovy-agent in #1633
  • AnyAxisymmetricRazorThinDisk: fix the small-|z| force/2nd-derivative band (exact-complement K + a=R peak resolution) by @jobovy-agent in #1245
  • AnyAxisymmetricRazorThinDisk: evaluate the second derivatives as finite-part integrals by @jobovy-agent in #1296
  • AnyAxisym: Phi misses the midplane cusp for |z| << R (and the test that hid it) by @jobovy-agent in #1333
  • RazorThinExponentialDisk: substitute out the k=R endpoint singularity by @jobovy-agent in #1295
  • EinastoPotential: use regularized P so n=6 force stays finite by @shaneraphel with Cursor in #1501
  • Two wrong tolerances: surfdens quadrature (epsabs) and the streamgapdf sample distance by @jobovy-agent in #1293
  • jeans: don't let scipy.quad's default epsabs truncate sigma_r's small outer tail by @jobovy-agent in #1439
  • AdiabaticContractionWrapperPotential: Phi0 from the exact integral of its force by @jobovy-agent in #1709
  • NFW, ExpTruncNFW: small-r series in the jax radial force that constantbetadf differentiates by @jobovy-agent in #1760
  • constantbetadf: jax derivatives in float64 without turning on jax's x64 for the user by @jobovy-agent in #1762

Bug fixes and minor tweaks

  • Fix spherical DF sampling velocity bias by @jobovy-agent in #1568
  • sphericaldf: evaluate a multi-orbit Orbit with each orbit's own L by @jobovy-agent in #1734
  • interpRZPotential: keep grids and off-grid fallbacks in internal units by @jobovy-agent in #1274
  • AnySphericalPotential: integrate element-wise for array r by @jobovy-agent in #1323
  • Select per-orbit physical parameters when slicing Orbit arrays by @antonsoo in #1739
  • Preserve Orbit array shapes in projections and physical output by @antonsoo in #1740
  • C orbit integration: offsets in size_t (segfault beyond 2^31-1 output elements) by @jobovy-agent in #1741
  • Fix AdiabaticContractionWrapperPotential ignoring amp; quasiisothermaldf: _precomputerg=False, unbound points in arrays, out-of-grid Lz by @jobovy-agent in #1671
  • quasiisothermaldf: rg grid looked up at |Lz| and rl solved for arrays at once (fixes #1671's slowdown) by @jobovy-agent in #1703
  • sphericaldf: honour a per-call ro=/vo= when parsing Quantity inputs by @jobovy with Claude in #1349
  • Orbit: evaluate at a 0-d array time (fixes method='dop853' in a MovingObjectPotential) by @jobovy-agent in #1738
  • Orbit: setting up from sky coordinates with uvw=True no longer modifies the input by @jobovy-agent in #1611
  • Set alpha/beta for NFWPotential rmax/conc init paths by @steps-re in #1108
  • Check interpSphericalPotential range independently of FDM friction by @steps-re in #1107
  • actionAngleAdiabatic: fix multi-point _justjr raising TypeError by @jobovy-agent in #1398
  • actionAngleVerticalInverse: select tori by their actual action with a polynomial point transformation by @jobovy-agent in #1510
  • actionAngleVerticalInverse: compute the polynomial point transformation's action offset in closed form and apply it by @jobovy-agent in #1516
  • actionAngle: stop masking an inner AttributeError as "method not implemented" by @jobovy-agent in #1355
  • actionAngle_c: parse one potentialArg copy per OpenMP thread by @jobovy-agent in #1475
  • integrate_dxdv: transform the base state in C, restoring bit-identity with plain integrate by @jobovy-agent in #1400
  • Programatically define galpy animation <style> to avoid duplication and HTML error by @jobovy in #1588

Dependencies / maintenance

  • Bump to 1.12.1.dev0 and start v1.12.1 HISTORY by @jobovy with Claude in #1042
  • Fix sdist install glob; build/test sdist on every PR (upload still release-only) by @jobovy with Claude in #1044
  • [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci[bot] in #1078
  • [auto] Update documentation notebook outputs (2026-07-16) by @github-actions[bot] in #1135
  • Bump actions/setup-python from 6 to 7 in the actions group by @dependabot[bot] in #1207
  • Bump actions/stale from 10 to 11 in the actions group by @dependabot[bot] in #1240
  • [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci[bot] in #1244
  • tests: drop the expired numpy-version tolerance branch in test_SpiralArmsPotential by @jobovy-agent in #1253
  • Bump pypa/cibuildwheel from 4.1 to 4.2 in the actions group by @dependabot[bot] in #1287
  • Improve Claude diff analysis debugging and error messaging by @jobovy with Claude in #1326
  • [auto] Update documentation notebook outputs (2026-08-16) by @github-actions[bot] in #1329
  • Move the grid-quantity parser to the actionAngleInverse base module by @jobovy-agent in #1350
  • CI: fetch GSL from the nearest GNU mirror rather than ftp.gnu.org by @jobovy in #1409
  • tests: cut the time-dependent SCF coefficient tests from ~76s to ~11s by @jobovy-agent in #1418
  • [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci[bot] in #1456
  • test_orbit: one test case per potential for the four all-potentials walks by @jobovy-agent in #1467
  • Delete copilot setup by @jobovy in #1472
  • Avoid duplicate builds/tests on PRs by @jobovy in #1470
  • [auto] Update documentation notebook outputs (2026-09-15) by @github-actions[bot] in #1502
  • all-clear: ignore superseded check attempts by @jobovy with Codex in #1589
  • [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci[bot] in #1632
  • Pyodide build: fetch GSL from independent mirrors, SHA-256 verified (GNU hosts down) by @jobovy-agent in #1638
  • Bump cibuildwheel to v4.3 and drop CIBW_ENABLE: cpython-prerelease by @jobovy with Claude in #1696
  • test_integrate_c_more_than_intmax_elements: run the subprocess in the tested galpy's directory by @jobovy-agent in #1746
  • CI on ubuntu-26.04 (GCC 15): declare gcov hooks, omp.h outside extern C, central differences in the planar STM test by @jobovy-agent in #1754
  • Doc notebooks: nbody_snapshots' C potential built in kpc; full Gaia DR3 sample in staeckel by @jobovy-agent in #1782
  • [auto] Update documentation notebook outputs (2026-11-02) by @github-actions[bot] in #1783
  • Release 1.12.1 by @jobovy-agent in #1784

New Contributors

Full Changelog: v1.12.0...v1.12.1

Don't miss a new galpy release

NewReleases is sending notifications on new releases.