Skip to content

FEAT: derive C-parity sign for charge-conjugate decay chains - #203

Open
Zeyna777 wants to merge 9 commits into
mainfrom
c-parity-sign
Open

FEAT: derive C-parity sign for charge-conjugate decay chains#203
Zeyna777 wants to merge 9 commits into
mainfrom
c-parity-sign

Conversation

@Zeyna777

@Zeyna777 Zeyna777 commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Closes #204.

Generalises the C-parity sign convention derived in ComPWA/jpsi-nstar#573 from $J/\psi \to p\bar p\eta$ to an arbitrary three-body decay, as a new ampform_dpd.cparity module.

What

If charge conjugation maps the final state of a decay onto itself, the strong interaction relates each decay chain to the chain of its charge-conjugate resonance. The two chains are then one model component with a single set of couplings and a fixed relative sign,

$$\mathcal{H}[\bar R, \dots] = s , \mathcal{H}[R, \dots] , , \qquad s = \pm 1 , .$$

jpsi-nstar computes $s$ as C_parent * C_meson * (-1)**L — correct for that channel, but it hard-codes both the fact that there is exactly one self-conjugate final-state particle and the fact that the decay vertex is the one that gets re-ordered. Here $s$ is assembled from the three factors of the general derivation instead:

$$s = \underbrace{C_0}_\text{initial state} ; \underbrace{\prod_a C_a}_\text{self-conjugate finals} ; \underbrace{\prod_v \eta_v}_\text{re-ordered vertices}$$

For three-body DPD this can be evaluated in closed form. Charge conjugation is an involution, so the permutation it induces on the final state is either the identity or a single transposition; the production vertex $0 \to R,k$ is written as (resonance, spectator) in both chains and never mismatches; and the cyclic pair ordering $(23)1,(31)2,(12)3$ is orientation-preserving, so the decay vertex $R \to i,j$ is re-ordered exactly when charge conjugation acts non-trivially on $i$ or $j$. Its exchange phase depends on the basis,

$$\eta^\text{LS} = (-1)^{l+s_i+s_j-S} , , \qquad \eta^\text{helicity} = (-1)^{J_R-s_i-s_j} , ,$$

which is why a sign derived in one basis must never be applied to the couplings of the other.

C-parities and antiparticles are read from a QRules ParticleCollection (load_particles() by default), so nothing about the decay has to be supplied by hand.

API (src/ampform_dpd/cparity.py)

function purpose
get_conjugate_state_map / is_c_symmetric the gate: the permutation of the final-state IDs, or False if C maps the decay to a different process
get_conjugate_coupling_sign $s$, per chain and per basis
get_exchange_phase $\eta_v$ on its own
get_conjugate_chain_pairs the chains that are tied to each other, particle first
get_c_forbidden_chains the selection rule for chains that C maps onto themselves
relate_conjugate_couplings the coupling substitutions, sign on the production coupling
symmetrize_conjugate_couplings applies them to an AmplitudeModel and drops the dependent parameters

The tie handles LS couplings, helicity couplings, mixed bases and the single-coefficient form of formulate(). In the helicity basis the two indices of the decay node are swapped as well, since charge conjugation delivers the decay products in the order in which the partner chain lists them the other way round.

Validation

Reproduces the reference table of jpsi-nstar#573, including the disagreement between the two bases:

$R$ $J^P$ $s_\text{LS}$ $s_\text{hel}$
$N(1535)$ $\tfrac12^-$ $-1$ $-1$
$N(1650)$ $\tfrac12^-$ $-1$ $-1$
$N(1710)$ $\tfrac12^+$ $+1$ $-1$

and passes two independent cross-checks that involve neither of those states:

  • isospin. For the $\rho^\pm$ pair of $J/\psi \to \pi^0\pi^-\pi^+$ the module gives $s=+1$, which is what the equal $\rho^+\pi^-$ and $\rho^-\pi^+$ coefficients of the $I=0$ combination require.
  • QRules. For the same decay the selection rule forbids the $f_2(1270)$ chain and allows the $\rho^0$; re-generating the reaction with allowed_interaction_types="strong" makes QRules drop exactly the $f_2(1270)$.

On top of the unit tests, TestMirrorSymmetry checks the tie against the amplitudes themselves: charge conjugation relabels the final state without touching a momentum, so a tied model's intensity has to be invariant under the induced permutation of the Mandelstam variables. Untied couplings give an asymmetry of ~1e-01, the tie brings it to ~1e-16.

That check is degenerate in $s$ for a model that consists of a conjugate pair alone — both signs are eigenstates of the tie and an overall $s$ drops out of the modulus — but not once the model also contains a chain that charge conjugation maps onto itself, since that chain interferes with the pair. $J/\psi \to 3\pi$ with $\rho^\pm$ and $\rho^0$ is the smallest example and is worked out in the notebook.

Docs

docs/cparity.ipynb walks through the derivation on the real implementation: the gate, the sign factor by factor in both bases, the selection rule with its two cross-checks, the coupling substitutions, and Dalitz plots showing that the sign leaves both bands untouched and only moves the interference where they cross, that tying restores mirror symmetry, and — in the $J/\psi \to 3\pi$ section — when mirror symmetry is and is not able to tell the two signs apart.

Known limitation

Fixing the sign of a conjugate pair turned out to be a good probe of the pair-ordering conventions inside the builder, and it found one: in the $LS$ basis the Clebsch-Gordan factors of subsystem 2 are built in a different pair ordering than the isobar Wigner-$d$ function of the same node (#202). The derived sign is stated in the ordering of the DPD paper, so an $LS$ model whose conjugate pair involves subsystem 2 is tied with the wrong relative sign between waves of different $l$, off by exactly $\eta^\text{LS}$.

That is a property of DalitzPlotDecompositionBuilder, not of this module, so it is fixed separately in #207. Helicity couplings are unaffected and are the safe choice until that lands.

Merge-order note: the xfail in TestMirrorSymmetry is strict=True, so it starts failing the moment #207 makes it pass. Whichever of the two PRs is merged second needs test_tying_restores_mirror_symmetry_for_different_waves stripped of its @pytest.mark.xfail decorator — the test body itself already asserts the correct behaviour and needs no other change.

Notes

  • No existing behaviour is touched; cparity is a new module and the only changes elsewhere are two test fixtures, three api_target_substitutions, five spell-check entries and the docs toctree.
  • docs/cparity.ipynb is added to the [[tool.ty.overrides]] list that already covers the other documentation notebooks.

🤖 Generated with Claude Code

@Zeyna777 Zeyna777 added ✨ Feature New feature added to the package 📝 Docs Improvements or additions to documentation labels Aug 3, 2026
@Zeyna777
Zeyna777 requested a review from redeboer August 3, 2026 14:20
@Zeyna777 Zeyna777 self-assigned this Aug 3, 2026
@redeboer

redeboer commented Aug 3, 2026

Copy link
Copy Markdown
Member

47a94e9: it would be good to check in a separate branch/PR whether #202 is really a bug. We can then also test this downstream in the polarimetry repo, because that does floating-point comparisons to a published model.

Lena Poepping and others added 8 commits August 3, 2026 22:17
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>
Generalises the sign convention of ComPWA/jpsi-nstar#573 from J/psi -> p pbar
eta to an arbitrary three-body decay, as a new `ampform_dpd.cparity` module.

The sign is assembled from the three factors of the general derivation: the
C-parity of the initial state, the C-parities of the final-state particles that
charge conjugation leaves in place, and the exchange phase of every isobar
vertex whose children charge conjugation re-orders. In the cyclic pair ordering
of the DPD paper only the decay vertex can be re-ordered, and its phase is
(-1)^(l+s_i+s_j-S) for LS couplings and (-1)^(J_R-s_i-s_j) for helicity
couplings, so the two bases give different signs.

Public API:

- `get_conjugate_state_map` / `is_c_symmetric`: the gate, i.e. the permutation
  of the final-state IDs induced by charge conjugation.
- `get_conjugate_coupling_sign`: the sign itself, per chain and per basis.
- `get_conjugate_chain_pairs`: the chains that are tied to each other.
- `get_c_forbidden_chains`: the selection rule for chains that charge
  conjugation maps onto themselves.
- `relate_conjugate_couplings` / `symmetrize_conjugate_couplings`: apply the
  tie to an `AmplitudeModel`, for LS, helicity, mixed and single-coefficient
  couplings, with the sign on the production coupling.

C-parities and antiparticles are read from a QRules `ParticleCollection`, so no
decay-specific input is needed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Walks through the general derivation and shows it at work on the actual
`ampform_dpd.cparity` implementation:

- the gate, i.e. which decays charge conjugation constrains at all, with
  J/psi -> K0 Sigma+ pbar as the counter-example;
- the sign of J/psi -> eta p pbar factor by factor, in both bases, showing
  that it collapses to the parity of the N* in the LS basis and that the
  helicity basis disagrees for the 1/2+ state;
- the selection rule for chains that are mapped onto themselves, with the
  rho+- / rho0 / f2(1270) case of J/psi -> pi0 pi- pi+ and its independent
  isospin and QRules cross-checks;
- the coupling substitutions on an AmplitudeModel;
- Dalitz plots: the sign leaves both bands untouched and only moves the
  interference between the conjugate chains, and tying the couplings restores
  the mirror symmetry that untied couplings break;
- why mirror symmetry cannot arbitrate the sign, and the convention caveats,
  including a plot of the LS-basis pair-ordering asymmetry.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The relative sign between waves of different l comes out wrong when the tie is
applied to an LS model whose conjugate pair involves subsystem 2, because the
builder writes that subsystem's Clebsch-Gordan factors in a different pair
ordering than the derivation assumes. Records that in the module docstring, the
xfail reason and the notebook, and points all three at the issue.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A model made of a conjugate pair alone is mirror-symmetric for either sign,
since an overall factor s drops out of the modulus. Adding a chain that charge
conjugation maps onto itself breaks that degeneracy, because the self-mapped
chain interferes with the pair. J/psi -> 3pi with rho+- and rho0 is the
smallest example: the derived sign leaves the intensity mirror-symmetric to
6e-14, the flipped one to 3e-01.
ComPWA/jpsi-nstar is a private repository, so the anonymous linkcheck job gets
a 404 on the derivation PR that the C-parity notebook cites.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The notebook and the module docstring defined the same three math labels, and
both are rendered into the documentation, so Sphinx reported duplicate labels
and the build failed on warnings. The canonical names stay with the module,
whose functions cross-reference them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Base automatically changed from fix-ls-pair-ordering to main August 4, 2026 18:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

📝 Docs Improvements or additions to documentation ✨ Feature New feature added to the package

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Tie the couplings of charge-conjugate decay chains, with the correct C-parity sign

3 participants