FIX: use cyclic pair ordering for LS couplings - #207
Merged
Conversation
The Clebsch-Gordan factors of a decay node were built from IsobarNode.child1/child2, which to_three_body_decay() sorts by final-state ID, while the isobar Wigner-d function of the same node uses the cyclic pair ordering (23)1, (31)2, (12)3 of the DPD paper. The two orderings coincide for subsystems 1 and 3, but (31)2 is the one cyclic pair that is not in ascending order, so subsystem 2 got its Clebsch-Gordan factors with lambda_1 - lambda_3 while its Wigner-d carried lambda_3 - lambda_1. Exchanging the two particles of an LS-coupled state costs (-1)^(l+s_i+s_j-S), which depends on the wave, so the mismatch does not cancel between resonances with different l and cannot be absorbed into the couplings. It also made the LS basis inconsistent with the helicity basis, whose decay couplings are indexed by get_decay_product_ids() and are therefore cyclic already. Closes #202. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
redeboer
force-pushed
the
fix-ls-pair-ordering
branch
from
August 3, 2026 20:18
4cfeb55 to
bafbfdd
Compare
redeboer
approved these changes
Aug 4, 2026
redeboer
left a comment
Member
There was a problem hiding this comment.
Thanks! 🐉
Verified on ComPWA/polarimetry@cf68fe0 (ComPWA/polarimetry#444), with decay rates for the LS model asserted to be unaffected 🎉
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #202
🐛 Bug fixes
The decay node is brought into the DPD cyclic pair ordering before its Clebsch-Gordan factors are formulated, so the$LS$ couplings and the isobar Wigner-d of that same node agree on which decay product comes first. The inline swap suggested in LS Clebsch-Gordan factors use a different pair ordering than the isobar Wigner-d function #202 is extracted into a documented
_order_decay_productshelper, which leaves one call site:Of the two options in LS Clebsch-Gordan factors use a different pair ordering than the isobar Wigner-d function #202, this takes the one that fixes it in the builder:
to_three_body_decaykeeps sorting by final-state ID, soThreeBodyDecayChain.decay_products— and therefore the dynamics builders and the serialization round-trip — stay untouched.❗ Behavioral changes
🖱️ Developer experience
test_ls_amplitude_does_not_depend_on_child_orderstates the invariant directly, rather than through the C-symmetry observable of LS Clebsch-Gordan factors use a different pair ordering than the isobar Wigner-d function #202: which of the two children anIsobarNodehappens to store first is an implementation detail of whoever built theThreeBodyDecay, so reversing it may not change the amplitude. The test builds each subsystem amplitude twice, once from the decay asto_three_body_decayproduces it and once with every decay node's children reversed, and asserts that the two expressions are symbolically equal.Without the fix it fails on the subsystem whose ordering flips, with a relative sign:
No existing test or notebook covered this: the three$LS$ basis but only asserts non-NaN, and
docs/comparisonnotebooks that assertDPD == AmpFormall usemin_ls=True,docs/xib2pkk.ipynbuses thedocs/lc2pkpi.ipynbusesmin_ls=(False, True), whose decay node is in the helicity basis and therefore unaffected. The whole suite passes unchanged either way, which is why this went unnoticed.