fix: align Lorentz/planar coordinate conventions across signatures#717
fix: align Lorentz/planar coordinate conventions across signatures#717henryiii wants to merge 3 commits into
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #717 +/- ##
==========================================
+ Coverage 87.72% 87.73% +0.01%
==========================================
Files 96 96
Lines 11193 11206 +13
==========================================
+ Hits 9819 9832 +13
Misses 1374 1374 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
dc55130 to
09245bb
Compare
Several compute functions produced different results for the same vector depending on which coordinate system it was stored in. Align them with ROOT's TLorentzVector conventions: - Et: make xy_z_t/xy_z_tau sign-preserving in energy (copysign on t), matching the rhophi/theta/eta variants and ROOT's Et(). - Mt/Mt2: drop the clamp on the tau-variants and make Mt sign-preserving via copysign-sqrt, so transverse-spacelike vectors agree between the T and Tau representations (and match ROOT's Mt()). - scale: scale tau by |factor| so a negative factor no longer flips a timelike vector into the spacelike (negative-tau) encoding. - planar unit: rhophi now sends the zero vector to 0 (like the xy variant and spatial/unit.py) instead of returning (1, phi). - spatial eta: add the same nan->0 guard to rhophi_theta that xy_theta already had for theta outside (0, pi). Updates two scale tau-coordinate tests and the sympy Mt _t assertions that encoded the previous (inconsistent) behavior, and adds regression tests for each case. Part of #711 Assisted-by: ClaudeCode:claude-opus-4.8
All 168 parametrizations of test_isSpacelike now match ROOT for the PtEtaPhiM coordinate system after the coordinate-convention fix, so the function-level xfail marker is removed to restore a hard PASS signal. Assisted-by: ClaudeCode:claude-opus-4.8
09245bb to
146f25f
Compare
|
🤖 AI text below 🤖 Ran the full ROOT comparison suite ( ~73% of the previously-marked-failing ROOT comparisons now pass (36635 XPASS vs 13231 still XFAIL). The big wins are concentrated in the Lorentz systems (
Removed it (now a hard Follow-up candidates (still 100% xfailing, untouched by this change): the |
Commit 146f25f dropped test_isSpacelike on the assumption that all 168 parametrizations matched ROOT, but that was only true on macOS. The constructor (1, 2, 3, 0) is exactly massless, so tau = sqrt(t^2 - |p|^2) of a true zero rounds platform-dependently: positive on macOS (timelike, matches ROOT's isSpacelike() == False) but negative on the Linux CI runner (spacelike == True), failing test_isSpacelike[to_xyzt-constructor8] and [to_rhophizt-constructor8]. Re-add the non-strict xfail so the lightlike-boundary cases are tolerated while the matching parametrizations still report XPASS. Assisted-by: ClaudeCode:claude-opus-4.8
|
Hi @henryiii, this is still marked as Draft hence you consider working further towards no failiing test? Anything you would like us to look at in particular? |
|
My question is should we try to match ROOT more closely at the expense of changing our return values (in edge cases, mostly)? I'm inclined to "yes", but want to make sure others are happy with that too. |
|
I would say yes, that sounds reasonable, but I'll let @eduardo-rodrigues confirm |
🤖 AI text below 🤖
Summary
Several
_computefunctions returned different results for the same vector depending on which coordinate system it was stored in. This PR aligns them so all 12 Lorentz coordinate systems (and the planar/spatial helpers) agree, following the project convention of matching ROOT'sTLorentzVector/Math::LorentzVector.Each fix was reproduced before being changed; regression tests cover both the T- and Tau-coordinate representations.
Bugs fixed
Etsign convention differed by signature.xy_z_t/xy_z_taureturnedsqrt(Et2)(always ≥0) while thetheta/eta/rhophivariants returnedt·sinθ(sign-preserving int). E.g.vector.obj(px=3, py=4, pz=0, E=-13).Etgave+13butvector.obj(pt=5, phi=0, pz=0, E=-13).Etgave-13. Nowxy_z_*usecopysign(sqrt(Et2), t), matching ROOT'sTLorentzVector::Et()(E<0 ? -sqrt(Et2) : sqrt(Et2)).Mt/Mt2disagreed between T and Tau coordinates. The T-variants computedt²−z²unclamped (soMt=nanfor transverse-spacelike vectors), while the Tau-variants clamped withmaximum(…, 0)(givingMt=0). E.g.vector.obj(px=3, py=4, pz=10, E=2).Mt2 == -96,.Mt == nan, but the equivalent tau vector gave0.0. Now both representations return the signedMt2 = t²−z²(the Tau-variants reconstruct it astau2 + rho², wheretau2is the signedcopysign(tau², tau)), andMt = copysign(sqrt(|Mt2|), Mt2), matching ROOT'sMt().Lorentz
scaleflippedtau's sign for negative factors. The Tau-variants returnedtau * factor; since negativetauencodes spacelike, scaling a timelike vector by−2produced a spacelike encoding, disagreeing with the T-coordinate version. Nowtau * |factor|: scaling by λ multipliest²−mag²byλ², so|tau|scales by|λ|and the causal character is invariant. (spatial/scale.pyalready takes|factor|forrho.)Planar
unitof the zero vector was inconsistent.xyusednan_to_num(…, nan=0)(zero →(0,0)) butrhophireturned(1, phi)unconditionally.rhophinow mirrorsspatial/unit.py:rho=0 → 0.spatial/eta.pyinconsistent nan guard.xy_thetawrapped-log(tan(θ/2))innan_to_num(nan=0.0, …)butrhophi_thetareturned the raw expression (givingnanfor θ outside(0, π)). The same guard was added torhophi_theta.All changes stay as array-safe
lib.*expressions, so the numba (register_jitable), awkward, and sympy backends keep working (copysign/maximum/nan_to_numhave sympy shims). Two existingscaletau-coordinate test assertions and the sympyMt_tassertions encoded the previous inconsistent behavior and were updated to the now-consistent values.Convention decisions for maintainer review
These are physics-convention choices — please confirm they match the intended ROOT semantics:
Etis sign-preserving in energy (negativeE→ negativeEt), per ROOTTLorentzVector::Et(). Applied uniformly to all 12 signatures.Mt/Mt2are signed (Mt2 = t²−z²unclamped;Mt = copysign(sqrt(|Mt2|), Mt2)), per ROOTMt(), so transverse-spacelike vectors give a negativeMtrather thannan/0. The previous Tau-variant clamp to0is removed.scalepreserves causal character:|tau|scales by|factor|, sign unchanged. A side effect: for vectors stored in Tau coordinates,(v * negative).tnow reports the (always-positive) reconstructed|t|with the correct timelike/spacelike magnitude instead of the previous sign-flipped value — the two updated assertions intests/compute/test_scale.pyreflect this.unitmaps to the zero vector in bothxyandrhophiplanar representations (matching the spatial backend).Note: a Tau-coordinate vector does not store the sign of
t, so(v*negative).treconstructed from tau is always non-negative; this PR makes its magnitude consistent across coordinate systems but does not attempt to recover the lost sign (out of scope).Tests
Added regression cases for: negative-energy
Etacross all signatures; transverse-spacelikeMt/Mt2across both T- and Tau-coordinate vectors; negativescalefactor on Tau-coordinates (timelike and spacelike); zero-vector planarunitinrhophi(object + numpy); andetafor θ outside(0, π)in bothxy_thetaandrhophi_theta.uv run pytest tests/compute/ tests/backends/test_object.py tests/backends/test_numpy.py tests/backends/test_sympy.py tests/backends/test_awkward.py tests/backends/test_numba_object.py— all green.Part of #711
🤖 Generated with Claude Code