Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reconsider amplitude builder design to improve implementation of spin alignment #318

Open
1 task
redeboer opened this issue Aug 2, 2022 · 2 comments
Open
1 task
Assignees
Labels
Epic Collection of issues ⚠️ Interface Breaking changes to the API ❔ Question Discuss this matter in the team
Milestone

Comments

@redeboer
Copy link
Member

redeboer commented Aug 2, 2022

Requirements

  1. Epic ⚠️ Interface 🔨 Maintenance
    redeboer

To-do [WIP]

  • Move scalar_initial_state_mass and stable_final_state_ids config to HelicityAdapter (that should untangle this mess)

Problem description

The latest (unreleased) implementation of Dalitz-plot decomposition (#307) makes use of the existing HelicityAmplitudeBuilder. This is problematic, because the choice of spin alignment method influences the way the 'unaligned' amplitudes are formulated. In particular, in the case of DPD, there should be no 'isobar Wigner-D'.

Here's an attempt to summarize the processes that go on when calling HelicityAmplitudeBuilder.formulate():

  • [Core] Loop over QRules' StateTransition objects to formulate (unaligned) helicity amplitudes for each decay chain. This also takes care of particle symmetrisation, through perform_external_edge_identical_particle_combinatorics().
  • The helicity formalism assumes a decay proceeds through a chain of isobar decays, so that the 'unaligned' amplitude for, for example, a three-body decay $0 \to R (\to 12) 3$ can be formulated as a product of two couplings for the two isobars:

    with $\mathcal{H}$ some scalar, complex coupling strength for each isobar, $D$ a Wigner-D function over helicity angles $\left(\phi^i_j, \theta^i_j\right)$ (polar angles of $j$ in the rest frame of $i$), $s_i$ the spin magnitude of particle $i$, $\lambda_i$ its helicity1, and $\mathcal{D}$ a dynamics lineshape that depends on kinematic variables $\tau$ (usually Mandelstam variable, widths, masses of decay products and angular momentum of the decaying pair).2
  • Keep track of lineshape choices $\mathcal{D}\left(\tau\right)$ for each isobar node. This is outsourced to DynamicsSelector.
  • Generate suggested parameter values for each parameter sympy.Symbol in the resulting expression. The amplitude builder only generates suggested parameter values for the helicity couplings $\mathcal{H}$ (simply set to 1+0j). ResonanceDynamicsBuilders suggest values for the remaining parameters, like pole position or meson radius.
  • Formulate conversion from four-momentum to kinematic variables. This currently done through the HelicityAdapter and computes only invariant masses and helicity angles $\phi, \theta$.
  • Generate coefficient/coupling names for each StateTransition through a NameGenerator. For some state transitions, the coupling name is the same, for parity conservation concerns (the intelligence there comes from QRules, though). See HelicityAmplitudeNameGenerator for the implementation used by the HelicityAmplitudeBuilder.
  • Align spin (see 1). This is currently to be done through an external class that the HelicityAmplitudeBuilder is unaware of. This class also has the responsibility to compute any additional kinematic variables, like $\zeta^i_{j(k)}$ for Dalitz-plot decomposition.

Example

All in all, as of 148c8c9, this results in the following amplitudes, using NoAlignment and DalitzPlotDecomposition3:

import ampform
import qrules
from ampform.helicity.align import NoAlignment

reaction = qrules.generate_transitions(
    initial_state=("J/psi(1S)", [-1, +1]),
    final_state=["K0", "Sigma+", "p~"],
    allowed_intermediate_particles=["Sigma(1660)", "N(1650)"],
    allowed_interaction_types=["strong"],
    formalism="helicity",
)

builder = ampform.get_builder(reaction)
builder.config.spin_alignment = NoAlignment()
builder.config.use_helicity_couplings = True
non_aligned_model = builder.formulate()
non_aligned_model.intensity

no-alignment-intensity

non_aligned_model.amplitudes

no-alignment-amplitudes

For DPD, the reaction needs to be relabeled:4

from ampform.helicity.align.dpd import DalitzPlotDecomposition, relabel_edge_ids

reaction_123 = relabel_edge_ids(reaction)
builder_123 = ampform.get_builder(reaction_123)
builder_123.config.spin_alignment = DalitzPlotDecomposition(reference_subsystem=1)
builder_123.config.use_helicity_couplings = True
dpd_model = builder_123.formulate()
dpd_model.intensity

dpd-intensity

dpd_model.amplitudes

dpd-amplitudes

Note that the choice for DPD does not affect the individual amplitudes. This is incorrect, if I understand @mmikhasenko correctly. In combination with #309, this points in the direction of a fundamental design problem, namely the assumption that the choice of 'spin alignment method' does not affect the form of the 'unaligned' amplitudes.

Related issues

Footnotes

  1. This causes the need for 'spin alignment'. 2

  2. The CanonicalAmplitudeBuilder forms an extension of the HelicityAmplitudeBuilder class that (only) inserts Clebsch-Gordan coefficients (formulate_clebsch_gordan_coefficients()). Amplitude $\mathcal{A}^R$ then becomes a sum over all allowed $LS$-couplings for $0 \to R (\to 12) 3$ with two CG coefficients for each node (four in the case of a three-body decay).

  3. Yes, there is a minor bug in the second set of summations, see https://github.com/ComPWA/ampform/issues/309.

  4. The relabeled reactions look as follows:

    Standard labeling DPD labeling
    reaction reaction123
@redeboer redeboer added Epic Collection of issues ❔ Question Discuss this matter in the team ⚠️ Interface Breaking changes to the API labels Aug 2, 2022
@redeboer
Copy link
Member Author

redeboer commented Aug 2, 2022

Tagging @spflueger here as well, who knows more about the implementation for symmetrization [code] and "parity prefactor" [code] (see also #284).

@redeboer
Copy link
Member Author

redeboer commented Aug 4, 2022

Conclusion after discussion with @spflueger: write a new builder for DPD and don't let this work through dependency injection (spin_alignment member). A core method seems to be _formulate_partial_decay(), which is overwritten by CanonicalAmplitudeBuilder. If this could somehow be made into a function or separate interface, we can also get of this risky inheritance-in-order-to-share-functionality.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Epic Collection of issues ⚠️ Interface Breaking changes to the API ❔ Question Discuss this matter in the team
Projects
Status: 🏗 In progress
Development

No branches or pull requests

1 participant