Skip to content

backend: centralize data-coercion helpers into galpy.backend._coerce#983

Merged
jobovy merged 1 commit into
feat/backendsfrom
backend/coerce-centralize
Jun 20, 2026
Merged

backend: centralize data-coercion helpers into galpy.backend._coerce#983
jobovy merged 1 commit into
feat/backendsfrom
backend/coerce-centralize

Conversation

@jobovy

@jobovy jobovy commented Jun 20, 2026

Copy link
Copy Markdown
Owner

What

Burndown PR-3a (foundational refactor). Relocates the backend data-coercion helpers — which were scattered across the wrong modules (util/conversion.py = units, util/coords.py = coordinate systems, two potential files) — into a new galpy/backend/_coerce.py with a guiding top-level docstring (the canonical reference for how backend coercion works + the numpy-passthrough byte-identity invariant). Resolves the long-standing review note to centralize these.

Moved verbatim (renames only):

  • coerce_coords (from backend/_namespaces.py)
  • promote_scalars (was coords.py::_promote_scalars_for)
  • as_backend_constant (was RotateAndTiltWrapperPotential::_as_xp_constant)
  • zeros_like_backend (was KuzminLikeWrapperPotential::_zero_like)

Call sites (coords.py, conversion.py, RotateAndTilt/KuzminLike/OblateStaeckel wrappers, two test_backend_* modules) now delegate to galpy.backend; _namespaces.py keeps the namespace/dtype/device primitives; __init__ re-exports the coercion API.

Pure relocation — zero behavior change

Each function body is moved byte-for-byte. No new functionality (the new scalar-default coercion is the follow-up PR-3b).

Byte-identity + review

numpy path byte-identical (verified: test_coords 97/97, test_backend_conventions+test_backend_device 47+1, RotateAndTilt/KuzminLike/OblateStaeckel/Spherical 210/210 — exact parent match; the 4 moved bodies diff to renames only). No circular import. Independently adversarially reviewed (all 6 angles refuted: verbatim-move, all-call-sites-rewired, numpy byte-identity, no-cycle, docstring accuracy, no-backend-drift).

🤖 Generated with Claude Code

Pure relocation (no behavior change, numpy byte-identical) of the scattered
backend data-coercion helpers (coerce_coords, promote_scalars [was
_promote_scalars_for], as_backend_constant [was _as_xp_constant],
zeros_like_backend [was _zero_like]) into a new galpy/backend/_coerce.py with a
guiding top-level docstring. Call sites delegate to galpy.backend; _namespaces.py
keeps the namespace/dtype/device primitives. No new functionality (follow-up PR).

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
@codecov

codecov Bot commented Jun 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.93%. Comparing base (fcad3f7) to head (fb796af).

Additional details and impacted files
@@              Coverage Diff               @@
##           feat/backends     #983   +/-   ##
==============================================
  Coverage          99.93%   99.93%           
==============================================
  Files                253      254    +1     
  Lines              39803    39804    +1     
  Branches             839      836    -3     
==============================================
+ Hits               39778    39779    +1     
  Misses                25       25           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions

Copy link
Copy Markdown
Contributor

All-backend test status (jax / torch)

Commit 3b4bfec9bce8f401526add01c2eda5058519881f

Green is achieved via the checked-in xfail-ledger (tests/backend_xfail.txt, applied xfail(strict=False)), so the metric to watch is the shrinking xfail count (burndown), not a raw pass count. A FAIL/ERR is an un-ledgered regression (reds the run). Because the ledger is non-strict, a now-passing ledgered test is a plain pass here (no per-push XPASS); burndown candidates -- in both directions -- are surfaced by the scheduled regen run, which rewrites the ledger from real outcomes. deferred is a separate burndown: tests skipped because they are unrunnable under the backend until the port is vectorized (see tests/backend_slow_skip.txt), e.g. the jax spherical-DF sampling/quadrature tests pending the Track F DF migration.

Overall: jax: 1051 passed · 271 xfail · 725 deferred | torch: 764 passed · 1279 xfail · 1 deferred

Ledger size: 2357 entries (jax=284, torch=2073).

Test shard jax torch
actionAngle ✅ 112 pass · 89 xfail ✅ 26 pass · 175 xfail
sphericaldf ✅ 164 pass · 26 xfail · 28 deferred ✅ 8 pass · 210 xfail
conversion + util + misc ✅ 86 pass · 5 xfail · 1 deferred ✅ 41 pass · 51 xfail
potential + scf + multipole — (no result) — (no result)
quantity + coords ✅ 281 pass · 55 xfail ✅ 189 pass · 147 xfail
orbit (energy/Jacobi + from_name) ✅ 0 pass · 0 xfail · 115 deferred ✅ 53 pass · 62 xfail
orbit + orbits (main) ✅ 0 pass · 0 xfail · 578 deferred ✅ 189 pass · 386 xfail
evolveddiskdf ✅ 35 pass · 0 xfail ✅ 32 pass · 3 xfail
jeans + dynamfric ✅ 17 pass · 2 xfail · 2 deferred ✅ 7 pass · 13 xfail · 1 deferred
qdf + pv2qdf + streamgapdf_impulse + noninertial ✅ 57 pass · 75 xfail · 1 deferred ✅ 14 pass · 119 xfail
streamgapdf ✅ 28 pass · 2 xfail ✅ 27 pass · 3 xfail
diskdf ✅ 129 pass · 0 xfail ✅ 112 pass · 17 xfail
streamdf + streamspraydf + streamTrack ✅ 142 pass · 17 xfail ✅ 66 pass · 93 xfail
Per-shard counts
Test shard backend pass xfail deferred XPASS fail error
actionAngle jax 112 89 0 0 0 0
actionAngle torch 26 175 0 0 0 0
sphericaldf jax 164 26 28 0 0 0
sphericaldf torch 8 210 0 0 0 0
conversion + util + misc jax 86 5 1 0 0 0
conversion + util + misc torch 41 51 0 0 0 0
potential + scf + multipole jax
potential + scf + multipole torch
quantity + coords jax 281 55 0 0 0 0
quantity + coords torch 189 147 0 0 0 0
orbit (energy/Jacobi + from_name) jax 0 0 115 0 0 0
orbit (energy/Jacobi + from_name) torch 53 62 0 0 0 0
orbit + orbits (main) jax 0 0 578 0 0 0
orbit + orbits (main) torch 189 386 0 0 0 0
evolveddiskdf jax 35 0 0 0 0 0
evolveddiskdf torch 32 3 0 0 0 0
jeans + dynamfric jax 17 2 2 0 0 0
jeans + dynamfric torch 7 13 1 0 0 0
qdf + pv2qdf + streamgapdf_impulse + noninertial jax 57 75 1 0 0 0
qdf + pv2qdf + streamgapdf_impulse + noninertial torch 14 119 0 0 0 0
streamgapdf jax 28 2 0 0 0 0
streamgapdf torch 27 3 0 0 0 0
diskdf jax 129 0 0 0 0 0
diskdf torch 112 17 0 0 0 0
streamdf + streamspraydf + streamTrack jax 142 17 0 0 0 0
streamdf + streamspraydf + streamTrack torch 66 93 0 0 0 0

@jobovy jobovy merged commit 9ff2271 into feat/backends Jun 20, 2026
146 checks passed
@jobovy jobovy deleted the backend/coerce-centralize branch June 20, 2026 12:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant