Generate an amplitude model with the helicity formalism.

class HelicityModel(intensity: PoolSum, amplitudes: Mapping[Indexed, Expr], parameter_defaults: Mapping[Basic, ParameterValue], kinematic_variables: Mapping[Symbol, Expr], components: Mapping[str, Expr], reaction_info: ReactionInfo)[source]#

Bases: object

intensity: PoolSum[source]#

Main expression describing the intensity over kinematic_variables.

amplitudes: OrderedDict[Indexed, Expr][source]#

Definitions for the amplitudes that appear in intensity.

The main intensity is a sum over amplitudes for each initial and final state helicity combination. These amplitudes are indicated with as sp.Indexed instances and this attribute provides the definitions for each of these. See also TR-014.

parameter_defaults: ParameterValues[source]#

A mapping of suggested parameter values.

Keys are Basic instances from the main expression that should be interpreted as parameters (as opposed to kinematic_variables). The symbols are ordered alphabetically by name with natural sort order (natural_sorting()). Values have been extracted from the input ReactionInfo.

kinematic_variables: OrderedDict[Symbol, Expr][source]#

Expressions for converting four-momenta to kinematic variables.

components: OrderedDict[str, Expr][source]#

A mapping for identifying main components in the expression.

Keys are the component names (str), formatted as LaTeX, and values are sub- expressions in the main expression. The mapping is an OrderedDict that orders the component names alphabetically with natural sort order (natural_sorting()).

reaction_info: ReactionInfo[source]#
property expression: Expr[source]#

Expression for the intensity with all amplitudes fully expressed.

Constructed from intensity by substituting its amplitude symbols with the definitions with amplitudes.

rename_symbols(renames: Iterable[tuple[str, str]] | Mapping[str, str]) HelicityModel[source]#

Rename certain symbols in the model.

Renames all Symbol instance that appear in expression, parameter_defaults, components, and kinematic_variables. This method can be used to couple parameters.


renames – A mapping from old to new names.


A new instance of a HelicityModel with symbols in all attributes renamed accordingly.

class ParameterValues(parameters: Mapping[Basic, float | complex | int])[source]#

Bases: Mapping

Ordered mapping to ParameterValue with convenient getter and setter.

This class makes it possible to search through a mapping of sympy symbols to their values (a “parameter mapping”) by symbol name or by index in the (ordered) dictionary.

>>> a, b, c = sp.symbols("a b c")
>>> parameters = ParameterValues({a: 0.0, b: 1 + 1j, c: -2})
>>> parameters[a]
>>> parameters["b"]
>>> parameters["b"] = 3
>>> parameters[1]
>>> parameters[2]
>>> parameters[2] = 3.14
>>> parameters[c]
__getitem__(key: Basic | int | str) float | complex | int[source]#
__setitem__(key: Basic | int | str, value: float | complex | int) None[source]#

Allowed value types for parameters.

alias of float | complex | int

class HelicityAmplitudeBuilder(reaction: ReactionInfo)[source]#

Bases: object

Amplitude model generator for the helicity formalism.

property adapter: HelicityAdapter[source]#

Converter for computing kinematic variables from four-momenta.

property config: BuilderConfiguration[source]#
property dynamics: DynamicsSelector[source]#
property naming: NameGenerator[source]#
property reaction: ReactionInfo[source]#
set_dynamics(particle_name: str, dynamics_builder: ResonanceDynamicsBuilder) None[source]#

Assign a ResonanceDynamicsBuilder for a specific resonance.

Deprecated since version 0.16.0: Use the assign() method of the dynamics attribute instead.

formulate() HelicityModel[source]#
class CanonicalAmplitudeBuilder(reaction: ReactionInfo)[source]#

Bases: HelicityAmplitudeBuilder

Amplitude model generator for the canonical helicity formalism.

This class defines a full amplitude in the canonical formalism, using the helicity formalism as a foundation. The key here is that we take the full helicity intensity as a template, and just exchange the helicity amplitudes \(F\) as a sum of canonical amplitudes \(A\):

\[F^J_{\lambda_1,\lambda_2} = \sum_{LS} \mathrm{norm}(A^J_{LS})C^2.\]

Here, \(C\) stands for Clebsch-Gordan factor.

class BuilderConfiguration(spin_alignment: SpinAlignment, scalar_initial_state_mass: bool, stable_final_state_ids: Iterable[int] | None, use_helicity_couplings: bool)[source]#

Bases: object

Configuration class for a HelicityAmplitudeBuilder.

spin_alignment: SpinAlignment[source]#

Method for aligning spin.

scalar_initial_state_mass: bool[source]#

Add initial state mass as scalar value to parameter_defaults.

Put the invariant of the initial state (\(m_{012\dots}\)) under HelicityModel.parameter_defaults (with a scalar suggested value) instead of kinematic_variables. This is useful if four-momenta were generated with or kinematically fit to a specific initial state energy.

See also

Scalar masses

stable_final_state_ids: set[int] | None[source]#

IDs of the final states that should be considered stable.

Put final state ‘invariant’ masses (\(m_0, m_1, \dots\)) under HelicityModel.parameter_defaults (with a scalar suggested value) instead of kinematic_variables (which are expressions to compute an event- wise array of invariant masses). This is useful if final state particles are stable.

use_helicity_couplings: bool[source]#

Use helicity couplings instead of amplitude coefficients.

Helicity couplings are a measure for the strength of each partial two-body decay. Amplitude coefficients are the product of those couplings.

class DynamicsSelector(transitions: ReactionInfo | Iterable[FrozenTransition[State, InteractionProperties]])[source]#

Bases: Mapping

Configure which ResonanceDynamicsBuilder to use for each node.

assign(selection, builder: ResonanceDynamicsBuilder) None[source]#
assign(decay: TwoBodyDecay, builder: ResonanceDynamicsBuilder) None
assign(transition_node: tuple[FrozenTransition[State, InteractionProperties], int], builder: ResonanceDynamicsBuilder) None
assign(particle_name: str, builder: ResonanceDynamicsBuilder) None
assign(particle: Particle, builder: ResonanceDynamicsBuilder) None

Assign a ResonanceDynamicsBuilder to a selection of nodes.

Currently, the following types of selections are implements:

formulate_isobar_cg_coefficients(transition: FrozenTransition[State, InteractionProperties], node_id: int) Expr[source]#

Compute the two Clebsch-Gordan coefficients for an isobar node.

In the canonical basis (also called partial wave basis), Clebsch-Gordan coefficients ensure that the projection of angular momentum is conserved ([Kutschke, 1996], p. 4). When calling generate_transitions() with formalism="canonical-helicity", AmpForm formulates the amplitude in the canonical basis from amplitudes in the helicity basis using the transformation in [Chung, 2014], Eq. (4.32). See also [Kutschke, 1996], Eq. (28).

This function produces the two Clebsch-Gordan coefficients in [Chung, 2014], Eq. (4.32). For a two-body decay \(1 \to 2, 3\), we get:

(1)#\[C^{s_1,\lambda}_{L,0,S,\lambda} C^{S,\lambda}_{s_2,\lambda_2,s_3,-\lambda_3}\]


  • \(s_i\) the intrinsic Spin.magnitude of each state \(i\),

  • \(\lambda_{2}, \lambda_{3}\) the helicities of the decay products (can be taken to be their spin_projection when following a constistent boosting procedure),

  • \(\lambda=\lambda_{2}-\lambda_{3}\),

  • \(L\) the total angular momentum of the final state pair (l_magnitude),

  • \(S\) the coupled spin magnitude of the final state pair (s_magnitude),

  • and \(C^{j_3,m_3}_{j_1,m_1,j_2,m_2} = \langle j1,m1;j2,m2|j3,m3\rangle\), as in Clebsch-Gordan Coefficients.


>>> import qrules
>>> reaction = qrules.generate_transitions(
...     initial_state=[("J/psi(1S)", [+1])],
...     final_state=[("gamma", [-1]), "f(0)(980)"],
... )
>>> transition = reaction.transitions[1]  # angular momentum 2
>>> formulate_isobar_cg_coefficients(transition, node_id=0)
CG(1, -1, 0, 0, 1, -1)*CG(2, 0, 1, -1, 1, -1)
\[C^{s_1,\lambda}_{L,0,S,\lambda} C^{S,\lambda}_{s_2,\lambda_2,s_3,-\lambda_3} = C^{1,(-1-0)}_{2,0,1,(-1-0)} C^{1,(-1-0)}_{1,-1,0,0} = C^{1,-1}_{2,0,1,-1} C^{1,-1}_{1,-1,0,0}\]
formulate_isobar_wigner_d(transition: FrozenTransition[State, InteractionProperties], node_id: int) Expr[source]#

Compute WignerD for an isobar node.

Following [Chung, 2014], Eq. (4.16), but taking the complex conjugate by flipping the sign of the azimuthal angle \(\phi\) (see relation between Wigner-\(D\) and Wigner-\(d\) in Eq. (A.1)).

For a two-body decay \(1 \to 2, 3\), this gives us:



  • \(s_1\) the Spin.magnitude of the decaying state,

  • \(m_1\) the spin_projection of the decaying state,

  • \(\lambda_{2}, \lambda_{3}\) the helicities of the decay products in in the restframe of \(1\) (can be taken to be their intrinsic spin_projection when following a constistent boosting procedure),

  • and \(\phi\) and \(\theta\) the helicity angles (see also get_helicity_angle_symbols()).

Note that \(\lambda_2, \lambda_3\) are ordered by their number of children, then by their state ID (see TwoBodyDecay).

See [Kutschke, 1996], Eq. (30) for an example of Wigner-\(D\) functions in a sequential two-body decay. Note that this source chose \(\Omega=(\phi,\theta,-\phi)\) as argument to the (conjugated) Wigner-\(D\) function, just like the original paper by Jacob & Wick [Jacob and Wick, 1959], Eq. (24). See p.119-120 and p.199 in [Martin and Spearman, 1970] for the two conventions, \(\gamma=0\) versus \(\gamma=-\phi\).


>>> import qrules
>>> reaction = qrules.generate_transitions(
...     initial_state=[("J/psi(1S)", [+1])],
...     final_state=[("gamma", [-1]), "f(0)(980)"],
... )
>>> transition = reaction.transitions[0]
>>> formulate_isobar_wigner_d(transition, node_id=0)
WignerD(1, 1, -1, -phi_0, theta_0, 0)

Submodules and Subpackages