import ampform.helicity

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.

sum_components(components: Iterable[str]) Expr[source]#

Coherently or incoherently add components of a helicity model.

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 Union[float, complex, int]

class DynamicsSelector(transitions: ReactionInfo | Iterable[StateTransition])[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[StateTransition, 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:

class HelicityAmplitudeBuilder(reaction: ReactionInfo, stable_final_state_ids: Iterable[int] | None = None, scalar_initial_state_mass: bool = False)[source]#

Bases: object

Amplitude model generator for the helicity formalism.

  • reaction – The ReactionInfo from which to formulate() an amplitude model.

  • stable_final_state_ids – 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.

  • stable_final_state_ids

    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

naming: NameGenerator[source]#

Name generator for amplitude names and coefficient names.

See also

Coefficient names.

align_spin: bool[source]#

(De)activate spin alignment.

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.

property adapter: HelicityAdapter[source]#

Converter for computing kinematic variables from four-momenta.

property dynamics_choices: DynamicsSelector[source]#
property stable_final_state_ids: set[int] | None[source]#

IDs of the final states that should be considered stable.

The ‘invariant’ mass symbols for these final states will be inserted as scalar values into the parameter_defaults.

property scalar_initial_state_mass: bool[source]#

Add initial state mass as scalar value to parameter_defaults.

See also

Scalar masses

set_dynamics(particle_name: str, dynamics_builder: ResonanceDynamicsBuilder) None[source]#
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.

formulate_clebsch_gordan_coefficients(transition: StateTransition, node_id: int) Expr[source]#

Compute the two Clebsch-Gordan coefficients for a state transition node.

In the canonical basis (also called partial wave basis), Clebsch-Gordan coefficients ensure that the projection of angular momentum is conserved ([9], 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 [7], Eq. (4.32). See also [9], Eq. (28).

This function produces the two Clebsch-Gordan coefficients in [7], 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_clebsch_gordan_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_wigner_d(transition: StateTransition, node_id: int) Expr[source]#

Compute WignerD for a transition node.

Following [7], 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 [9], 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 [14], Eq. (24). See p.119-120 and p.199 in [15] 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_wigner_d(transition, node_id=0)
WignerD(1, 1, -1, -phi_0, theta_0, 0)
formulate_spin_alignment(transition: StateTransition) PoolSum[source]#

Generate all Wigner-\(D\) combinations for a spin alignment sum.

Generate all Wigner-\(D\) function combinations that appear in [1], Eq.(45), but for a generic multibody decay. Each element in the returned list is a tuple of Wigner-\(D\) functions that appear in the summation, for a specific set of helicities were are summing over. To generate the full sum, make a multiply the Wigner-\(D\) functions in each tuple and sum over all these products.

formulate_rotation_chain(transition: StateTransition, rotated_state_id: int) PoolSum[source]#

Formulate the spin alignment sum for a specific chain.

See Eq.(45) from [1]. The chain consists of a series of helicity rotations (see formulate_helicity_rotation_chain()) plus a Wigner rotation (see formulate_wigner_rotation()) in case there is more than one helicity rotation.

formulate_helicity_rotation_chain(transition: StateTransition, rotated_state_id: int, helicity_symbol: Symbol) PoolSum[source]#

Formulate a Wigner-\(D\) for each helicity rotation up some state.

The helicity rotations are performed going through the decay Topology starting from the initial state up some rotated_state_id. Each rotation operates on the spin state and is therefore formulated as a WignerD function (see formulate_helicity_rotation()). See {doc}`/usage/helicity/spin-alignment` for more info.

formulate_wigner_rotation(transition: StateTransition, rotated_state_id: int, helicity_symbol: Symbol, m_prime: Symbol) PoolSum[source]#

Formulate the spin rotation matrices for a Wigner rotation.

A Wigner rotation is the ‘average’ rotation that results form a chain of Lorentz boosts to a new reference frame with regard to a direct boost. See [1], p.6, especially Eq.(36).

  • transition – The Transition in which you want to rotate one of the spin states.

  • rotated_state_id – The state ID of a spin State that you want to rotate.

  • helicity_symbol – Optional Symbol for \(m\) in \(D^s_{mm'}. Falls back to the value of `~qrules.transition.State.spin_projection\) embedded in the provided transition.

  • m_prime – The summation symbol \(m'\) that should be used when summing over the Wigner-\(D\) functions for this rotation.

formulate_helicity_rotation(spin_magnitude, spin_projection, m_prime, alpha, beta, gamma, no_zero_spin: bool = False) PoolSum[source]#

Formulate action of an Euler rotation on a spin state.

When rotation a spin state \(\left|s,m\right\rangle\) over Euler angles \(\alpha,\beta,\gamma\), the new state can be expressed in terms of other spin states \(\left|s,m'\right\rangle\) with the help of Wigner-\(D\) expansion coefficients:

(3)#\[R(\alpha,\beta,\gamma)\left|s,m\right\rangle = \sum^s_{m'=-s} D^s_{m',m}\left(\alpha,\beta,\gamma\right) \left|s,m'\right\rangle\]

See [1], Eq.(B.5).

This function gives the summation over these Wigner-\(D\) functions and can be used for spin alignment following [1], Eq.(45).

  • spin_magnitude – Spin magnitude \(s\) of spin state that is being rotated.

  • spin_projection – Spin projection component \(m\) of the spin state that is being rotated.

  • m_prime – A index Symbol or Dummy that represents \(m'\) helicities in Eq. (3).

  • alpha – First Euler angle.

  • beta – Second Euler angle.

  • gamma – Third Euler angle.

  • no_zero_spin – Skip value 0.0 in the generated spin projection range. Useful for massless particles.


>>> a, b, c, i = sp.symbols("a b c i")
>>> formulate_helicity_rotation(0, 0, i, a, b, c)
PoolSum(WignerD(0, 0, i, a, b, c), (i, (0,)))
>>> formulate_helicity_rotation(1 / 2, -1 / 2, i, a, b, c)
PoolSum(WignerD(1/2, -1/2, i, a, b, c), (i, (-1/2, 1/2)))

Submodules and Subpackages