Welcome to AmpForm-DPD!

Welcome to AmpForm-DPD!#

Supported Python versions Google Colab Binder

This Python package is a (temporary) extension of AmpForm and provides a symbolic implementation of Dalitz-plot decomposition (10.1103/PhysRevD.101.034033) with SymPy. It has been extracted from the ComPWA/polarimetry repository, which is not yet public.

Installation#

The fastest way of installing this package is through PyPI (ampform-dpd):

python3 -m pip install ampform-dpd

This installs the latest version that you can find on the stable branch. The latest version on the main branch can be installed as follows:

python3 -m pip install git+https://github.com/ComPWA/ampform@main

You can substitute main in the above command with any of the tags listed under the releases or any other commit hashes. However, we highly recommend using the more dynamic, ‘editable installation’ instead. This goes as follows:

  1. Get the source code (see the Pro Git Book):

    git clone https://github.com/ComPWA/ampform-dpd
    cd ampform-dpd
    
  2. [Recommended] Create a virtual environment (see here or the tip below).

  3. Install the project in ‘editable installation’ with additional dependencies for the developer:

    python3 -m pip install -e . --group dev
    

That’s all! Have a look at the Welcome to AmpForm-DPD! page to try out the package, and see Help developing for tips on how to work with this ‘editable’ developer setup!

Tip

It’s easiest to install the project in a virtual environment with uv. In that case, to install in editable mode, just run:

uv sync
source .venv/bin/activate

This way of installing is also safer, because it pins all dependencies.

Physics#

Dalitz-plot decomposition allows us to separate variables that affect the angular distribution from variables that describe the dynamics. It allows rewriting a transition amplitude \(T\) as

\[ T^{\Lambda}_{\{\lambda\}}(\alpha,\beta,\gamma; \{\sigma\}) = \sum_{\nu} {\color{RoyalBlue} D_{\Lambda,\nu}^{J}(\alpha,\beta,\gamma)} \, {\color{Orange} O^\nu_{\{\lambda\}}(\{\sigma\})}. \]

Here, \(\Lambda\) and \(\nu\) indicate the allowed spin projections of the initial state, \(\{\lambda\}\) are the allowed spin projections of the final state (e.g. \(\{\lambda\}=\lambda_1,\lambda_3,\lambda_3\) for a three-body decay). The Euler angles \(\alpha,\beta,\gamma\) are obtained by choosing a specific aligned center-of-momentum frame (“aligned CM”), see Fig. 2 in Ref [1], which gives us an “aligned” transition amplitude \(O^\nu_{\{\lambda\}}\) that only depends on dynamic variables \(\{\sigma\}\) (in the case of a three-body decay, the three Mandelstam variables \(\sigma_1,\sigma_2,\sigma_3\)).

These aligned transition amplitudes are then combined into an observable differential cross section (intensity distribution), using a spin density matrix \(\rho_{_{\Lambda,\Lambda'}}\) for the spin projections \(\Lambda\) of the initial state,

\[ \mathrm{d}\sigma/\mathrm{d}\Phi_3 = N \sum_{\Lambda,\Lambda'} \rho_{_{\Lambda,\Lambda'}} \sum_{\nu,\nu'} {\color{RoyalBlue} D^{J^*}_{\Lambda,\nu}\left(\alpha,\beta,\gamma\right) D^{J}_{\Lambda',\nu'}\left(\alpha,\beta,\gamma\right) } \sum_{\{\lambda\}} {\color{Orange} O^\nu_{\{\lambda\}}\left(\{\sigma\}\right) O^{\nu'*}_{\{\lambda\}}\left(\{\sigma\}\right) }. \]

Given the right alignment, the aligned transition amplitude can be written as

(1)#\[\begin{split}\begin{eqnarray} {\color{Orange}O^\nu_{\{\lambda\}}\left(\{\sigma\}\right)} &=& \sum_{(ij)k} \sum^{(ij)\to i,j}_s \sum_\tau \sum_{\{\lambda'\}} \; {\color{Orange}X_s\!\left(\sigma_k\right)} \\ {\color{LightGray}\text{production:}} && \quad \times\; \eta_J\, d^J_{\nu,\tau-\lambda'_k}\!\left(\hat\theta_{k(1)}\right)\, H^{0\to(ij),k}_{\tau,\lambda_k'}\,(-1)^{j_k-\lambda_k'} \\ {\color{LightGray}\text{decay:}} && \quad \times\; \eta_s\, d^s_{\tau,\lambda'_i-\lambda_j'}\!\left(\theta_{ij}\right)\, H^{(ij)\to i,j}_{\lambda'_i,\lambda'_j}\,(-1)^{j_j-\lambda_j'} \\ {\color{LightGray}\text{rotations:}} && \quad \times\; d^{j_1}_{\lambda'_1,\lambda_1}\!\left(\zeta^1_{k(0)}\right)\, d^{j_2}_{\lambda'_2,\lambda_2}\!\left(\zeta^2_{k(0)}\right)\, d^{j_3}_{\lambda'_3,\lambda_3}\!\left(\zeta^3_{k(0)}\right). \end{eqnarray}\end{split}\]

Notice the general structure:

  • Summations: The outer sum is taken over the three decay chain combinations \((ij)k \in \left\{(23)1, (31)2, (12)3\right\}\). Next, we sum over the spin magnitudes \(s\) of all resonances[1], the corresponding allowed helicities \(\tau\), and allowed spin projections \(\{\lambda'\}\) of the final state.

  • Dynamics: The function \(X_s\) only depends on a single Mandelstam variable and carries all the dynamical information about the decay chain. Typically, these are your \(K\)-matrix or Breit-Wigner lineshape functions.

  • Isobars: There is a Wigner \(d\)-function and a helicity coupling \(H\) for each isobar in the three-body decay chain: the \(0\to(ij),k\) production node and the \((ij)\to i,j\) decay node. The argument of these Wigner \(d\)-functions are the polar angles. The factors \(\eta_J=\sqrt{2S+1}\) and \(\eta_s=\sqrt{2s+1}\) are normalization factors. The phase \((-1)^{j-\lambda}\) is added to both helicity couplings to convert to the Jacob-Wick particle-2 convention.[2] The convention treats the first and the second particle unequally, however, it enables the simple relation of the helicity couplings to the \(LS\) couplings explained below.

  • Wigner rotations: The last three Wigner \(d\)-functions represent Wigner rotations that appear when rotating the boosted frames of the production and decay isobar amplitudes back to the space-fixed CM frame.

If \(k=1\), we have \(\hat\theta_{k(1)}=0\), so the Wigner \(d\) function for the production isobar reduces to a Kronecker delta, \(d^J_{\nu,\tau-\lambda'_k}\!\left(\hat\theta_{k(1)}\right) = \delta_{\nu,\tau-\lambda'_k}\).

Equation (1) is written in terms of helicity couplings, but can be rewritten in terms of \(LS\) couplings, using

\[\begin{split} \begin{aligned} H^{0\to(ij),k}_{\tau,\lambda'_k} \;&=\; \sum_{LS} H^{0\to(ij),k}_{LS} \sqrt{\frac{2L+1}{2J+1}} C^{S,\tau-\lambda'_k}_{s,\tau,j_k,-\lambda'_k} C^{J,\tau-\lambda'_k}_{L,0,S,\tau-\lambda'_k} \\ H^{(ij)\to i,j}_{\lambda'_i,\lambda'_j} \;&=\; \sum_{l's'} H^{0\to(ij),k}_{l's'} \sqrt{\frac{2l'+1}{2s+1}} C^{s',\lambda'_i-\lambda'_j}_{j_i,\lambda'_i,j_j,-\lambda'_j} C^{s,\lambda'_i-\lambda'_j}_{l',0,s',\lambda'_i-\lambda'_j}\,. \end{aligned} \end{split}\]

The dynamics function is dependent on the \(LS\) values and we write \(X_s^{LS;l's'}\) instead of \(X_s\).

Usage#

The core class of this package is the DalitzPlotDecompositionBuilder. It requires a ThreeBodyDecay object to formulate amplitude models. You can create such a decay object by hand, but it is easier to generate it with QRules. Here is an example for the decay \(J/\psi \to p \bar{\varSigma}^- \bar{K}^0\). In the last step, we “normalize” the state IDs of the incoming and outgoing states so that they match the index naming scheme of the Dalitz-Plot Decomposition paper.

import qrules

from ampform_dpd.adapter.qrules import normalize_state_ids

reaction = qrules.generate_transitions(
    initial_state="J/psi(1S)",
    final_state=["p", "Sigma~-", "K~0"],
    allowed_interaction_types="strong",
    mass_conservation_factor=0,
)
reaction = normalize_state_ids(reaction)

Hide code cell source

import graphviz

dot = qrules.io.asdot(reaction, collapse_graphs=True)
graphviz.Source(dot)
_images/c5bb69bab45cfe968d3101e506728851717d9fb8c42e4283762daaa3320a3c2a.svg

Since AmpForm-DPD formulates amplitudes for three-body decays only, it defines its own topology class for encoding the decay chains. You can convert the QRules ReactionInfo object to such a ThreeBodyDecay as follows:

from ampform_dpd.adapter.qrules import to_three_body_decay

decay = to_three_body_decay(reaction.transitions)

The ampform_dpd.io module offers some handy functions for rendering the decay chains in different format.

Hide code cell content

resonance

\(J^P\)

mass (MeV)

width (MeV)

\(L_\mathrm{dec}^\mathrm{min}\)

\(L_\mathrm{prod}^\mathrm{min}\)

\(\overline{N}(1700)^{-} \to \overline{\Sigma}^{-} \overline{K}^{0}\)

\(\frac{3}{2}^+\)

1,720

200

2

1

\(\overline{N}(1700)^{-} \to \overline{\Sigma}^{-} \overline{K}^{0}\)

\(\frac{3}{2}^+\)

1,720

200

2

1

\(\overline{N}(1710)^{-} \to \overline{\Sigma}^{-} \overline{K}^{0}\)

\(\frac{1}{2}^-\)

1,710

140

1

0

\(\overline{N}(1710)^{-} \to \overline{\Sigma}^{-} \overline{K}^{0}\)

\(\frac{1}{2}^-\)

1,710

140

1

2

\(\overline{N}(1720)^{-} \to \overline{\Sigma}^{-} \overline{K}^{0}\)

\(\frac{3}{2}^-\)

1,720

250

1

0

\(\overline{N}(1720)^{-} \to \overline{\Sigma}^{-} \overline{K}^{0}\)

\(\frac{3}{2}^-\)

1,720

250

1

2

\(\overline{N}(1720)^{-} \to \overline{\Sigma}^{-} \overline{K}^{0}\)

\(\frac{3}{2}^-\)

1,720

250

1

2

\(\Sigma(1660)^{+} \to p \overline{K}^{0}\)

\(\frac{1}{2}^+\)

1,660

200

1

0

\(\Sigma(1660)^{+} \to p \overline{K}^{0}\)

\(\frac{1}{2}^+\)

1,660

200

1

2

\(\Sigma(1670)^{+} \to p \overline{K}^{0}\)

\(\frac{3}{2}^-\)

1,675

70

2

1

\(\Sigma(1670)^{+} \to p \overline{K}^{0}\)

\(\frac{3}{2}^-\)

1,675

70

2

1

\(\Sigma(1750)^{+} \to p \overline{K}^{0}\)

\(\frac{1}{2}^-\)

1,750

150

0

1

\(\Sigma(1750)^{+} \to p \overline{K}^{0}\)

\(\frac{1}{2}^-\)

1,750

150

0

1

\(\Sigma(1775)^{+} \to p \overline{K}^{0}\)

\(\frac{5}{2}^-\)

1,775

120

2

1

Hide code cell content

from IPython.display import Math

from ampform_dpd.io import aslatex

Math(aslatex(decay))
\[\begin{split}\displaystyle \begin{array}{c} J/\psi(1S) \xrightarrow[S=1]{L=1} \left(\overline{N}(1700)^{-} \xrightarrow[S=1/2]{L=2} \overline{\Sigma}^{-} \overline{K}^{0}\right) p \\ J/\psi(1S) \xrightarrow[S=2]{L=1} \left(\overline{N}(1700)^{-} \xrightarrow[S=1/2]{L=2} \overline{\Sigma}^{-} \overline{K}^{0}\right) p \\ J/\psi(1S) \xrightarrow[S=1]{L=0} \left(\overline{N}(1710)^{-} \xrightarrow[S=1/2]{L=1} \overline{\Sigma}^{-} \overline{K}^{0}\right) p \\ J/\psi(1S) \xrightarrow[S=1]{L=2} \left(\overline{N}(1710)^{-} \xrightarrow[S=1/2]{L=1} \overline{\Sigma}^{-} \overline{K}^{0}\right) p \\ J/\psi(1S) \xrightarrow[S=1]{L=0} \left(\overline{N}(1720)^{-} \xrightarrow[S=1/2]{L=1} \overline{\Sigma}^{-} \overline{K}^{0}\right) p \\ J/\psi(1S) \xrightarrow[S=1]{L=2} \left(\overline{N}(1720)^{-} \xrightarrow[S=1/2]{L=1} \overline{\Sigma}^{-} \overline{K}^{0}\right) p \\ J/\psi(1S) \xrightarrow[S=2]{L=2} \left(\overline{N}(1720)^{-} \xrightarrow[S=1/2]{L=1} \overline{\Sigma}^{-} \overline{K}^{0}\right) p \\ J/\psi(1S) \xrightarrow[S=1]{L=0} \left(\Sigma(1660)^{+} \xrightarrow[S=1/2]{L=1} p \overline{K}^{0}\right) \overline{\Sigma}^{-} \\ J/\psi(1S) \xrightarrow[S=1]{L=2} \left(\Sigma(1660)^{+} \xrightarrow[S=1/2]{L=1} p \overline{K}^{0}\right) \overline{\Sigma}^{-} \\ J/\psi(1S) \xrightarrow[S=1]{L=1} \left(\Sigma(1670)^{+} \xrightarrow[S=1/2]{L=2} p \overline{K}^{0}\right) \overline{\Sigma}^{-} \\ J/\psi(1S) \xrightarrow[S=2]{L=1} \left(\Sigma(1670)^{+} \xrightarrow[S=1/2]{L=2} p \overline{K}^{0}\right) \overline{\Sigma}^{-} \\ J/\psi(1S) \xrightarrow[S=0]{L=1} \left(\Sigma(1750)^{+} \xrightarrow[S=1/2]{L=0} p \overline{K}^{0}\right) \overline{\Sigma}^{-} \\ J/\psi(1S) \xrightarrow[S=1]{L=1} \left(\Sigma(1750)^{+} \xrightarrow[S=1/2]{L=0} p \overline{K}^{0}\right) \overline{\Sigma}^{-} \\ J/\psi(1S) \xrightarrow[S=2]{L=1} \left(\Sigma(1775)^{+} \xrightarrow[S=1/2]{L=2} p \overline{K}^{0}\right) \overline{\Sigma}^{-} \\ \end{array}\end{split}\]

Hide code cell content

Math(aslatex(decay, with_jp=True))
\[\begin{split}\displaystyle \begin{array}{c} J/\psi(1S)\left[1^-\right] \xrightarrow[S=1]{L=1} \left(\overline{N}(1700)^{-}\left[\frac{3}{2}^+\right] \xrightarrow[S=1/2]{L=2} \overline{\Sigma}^{-}\left[\frac{1}{2}^-\right] \overline{K}^{0}\left[0^-\right]\right) p\left[\frac{1}{2}^+\right] \\ J/\psi(1S)\left[1^-\right] \xrightarrow[S=2]{L=1} \left(\overline{N}(1700)^{-}\left[\frac{3}{2}^+\right] \xrightarrow[S=1/2]{L=2} \overline{\Sigma}^{-}\left[\frac{1}{2}^-\right] \overline{K}^{0}\left[0^-\right]\right) p\left[\frac{1}{2}^+\right] \\ J/\psi(1S)\left[1^-\right] \xrightarrow[S=1]{L=0} \left(\overline{N}(1710)^{-}\left[\frac{1}{2}^-\right] \xrightarrow[S=1/2]{L=1} \overline{\Sigma}^{-}\left[\frac{1}{2}^-\right] \overline{K}^{0}\left[0^-\right]\right) p\left[\frac{1}{2}^+\right] \\ J/\psi(1S)\left[1^-\right] \xrightarrow[S=1]{L=2} \left(\overline{N}(1710)^{-}\left[\frac{1}{2}^-\right] \xrightarrow[S=1/2]{L=1} \overline{\Sigma}^{-}\left[\frac{1}{2}^-\right] \overline{K}^{0}\left[0^-\right]\right) p\left[\frac{1}{2}^+\right] \\ J/\psi(1S)\left[1^-\right] \xrightarrow[S=1]{L=0} \left(\overline{N}(1720)^{-}\left[\frac{3}{2}^-\right] \xrightarrow[S=1/2]{L=1} \overline{\Sigma}^{-}\left[\frac{1}{2}^-\right] \overline{K}^{0}\left[0^-\right]\right) p\left[\frac{1}{2}^+\right] \\ J/\psi(1S)\left[1^-\right] \xrightarrow[S=1]{L=2} \left(\overline{N}(1720)^{-}\left[\frac{3}{2}^-\right] \xrightarrow[S=1/2]{L=1} \overline{\Sigma}^{-}\left[\frac{1}{2}^-\right] \overline{K}^{0}\left[0^-\right]\right) p\left[\frac{1}{2}^+\right] \\ J/\psi(1S)\left[1^-\right] \xrightarrow[S=2]{L=2} \left(\overline{N}(1720)^{-}\left[\frac{3}{2}^-\right] \xrightarrow[S=1/2]{L=1} \overline{\Sigma}^{-}\left[\frac{1}{2}^-\right] \overline{K}^{0}\left[0^-\right]\right) p\left[\frac{1}{2}^+\right] \\ J/\psi(1S)\left[1^-\right] \xrightarrow[S=1]{L=0} \left(\Sigma(1660)^{+}\left[\frac{1}{2}^+\right] \xrightarrow[S=1/2]{L=1} p\left[\frac{1}{2}^+\right] \overline{K}^{0}\left[0^-\right]\right) \overline{\Sigma}^{-}\left[\frac{1}{2}^-\right] \\ J/\psi(1S)\left[1^-\right] \xrightarrow[S=1]{L=2} \left(\Sigma(1660)^{+}\left[\frac{1}{2}^+\right] \xrightarrow[S=1/2]{L=1} p\left[\frac{1}{2}^+\right] \overline{K}^{0}\left[0^-\right]\right) \overline{\Sigma}^{-}\left[\frac{1}{2}^-\right] \\ J/\psi(1S)\left[1^-\right] \xrightarrow[S=1]{L=1} \left(\Sigma(1670)^{+}\left[\frac{3}{2}^-\right] \xrightarrow[S=1/2]{L=2} p\left[\frac{1}{2}^+\right] \overline{K}^{0}\left[0^-\right]\right) \overline{\Sigma}^{-}\left[\frac{1}{2}^-\right] \\ J/\psi(1S)\left[1^-\right] \xrightarrow[S=2]{L=1} \left(\Sigma(1670)^{+}\left[\frac{3}{2}^-\right] \xrightarrow[S=1/2]{L=2} p\left[\frac{1}{2}^+\right] \overline{K}^{0}\left[0^-\right]\right) \overline{\Sigma}^{-}\left[\frac{1}{2}^-\right] \\ J/\psi(1S)\left[1^-\right] \xrightarrow[S=0]{L=1} \left(\Sigma(1750)^{+}\left[\frac{1}{2}^-\right] \xrightarrow[S=1/2]{L=0} p\left[\frac{1}{2}^+\right] \overline{K}^{0}\left[0^-\right]\right) \overline{\Sigma}^{-}\left[\frac{1}{2}^-\right] \\ J/\psi(1S)\left[1^-\right] \xrightarrow[S=1]{L=1} \left(\Sigma(1750)^{+}\left[\frac{1}{2}^-\right] \xrightarrow[S=1/2]{L=0} p\left[\frac{1}{2}^+\right] \overline{K}^{0}\left[0^-\right]\right) \overline{\Sigma}^{-}\left[\frac{1}{2}^-\right] \\ J/\psi(1S)\left[1^-\right] \xrightarrow[S=2]{L=1} \left(\Sigma(1775)^{+}\left[\frac{5}{2}^-\right] \xrightarrow[S=1/2]{L=2} p\left[\frac{1}{2}^+\right] \overline{K}^{0}\left[0^-\right]\right) \overline{\Sigma}^{-}\left[\frac{1}{2}^-\right] \\ \end{array}\end{split}\]

Hide code cell content

Markdown(as_markdown_table([decay.initial_state, *decay.final_state.values()]))

index

name

LaTeX

\(J^P\)

mass (MeV)

width (MeV)

0

J/psi(1S)

\(J/\psi(1S)\)

\(1^-\)

3,096

0

1

p

\(p\)

\(\frac{1}{2}^+\)

938

0

2

Sigma~-

\(\overline{\Sigma}^{-}\)

\(\frac{1}{2}^-\)

1,189

0

3

K~0

\(\overline{K}^{0}\)

\(0^-\)

497

0

Hide code cell content

resonances = sorted(
    {t.resonance for t in decay.chains},
    key=lambda p: (p.name[0], p.mass),
)
Markdown(as_markdown_table(resonances))

name

LaTeX

\(J^P\)

mass (MeV)

width (MeV)

N(1710)~-

\(\overline{N}(1710)^{-}\)

\(\frac{1}{2}^-\)

1,710

140

N(1720)~-

\(\overline{N}(1720)^{-}\)

\(\frac{3}{2}^-\)

1,720

250

N(1700)~-

\(\overline{N}(1700)^{-}\)

\(\frac{3}{2}^+\)

1,720

200

Sigma(1660)+

\(\Sigma(1660)^{+}\)

\(\frac{1}{2}^+\)

1,660

200

Sigma(1670)+

\(\Sigma(1670)^{+}\)

\(\frac{3}{2}^-\)

1,675

70

Sigma(1750)+

\(\Sigma(1750)^{+}\)

\(\frac{1}{2}^-\)

1,750

150

Sigma(1775)+

\(\Sigma(1775)^{+}\)

\(\frac{5}{2}^-\)

1,775

120

We an now use the decay object to formulate amplitude models. Notice that we do not parametrize the dynamics for each of the chains yet, we only have a simple expression for the unpolarized differential cross-section (“intensity”) that contains the expected Wigner-\(d\) functions for the spin alignment.

\[\displaystyle \sum_{\lambda_{0}=-1}^{1} \sum_{\lambda_{1}=-1/2}^{1/2} \sum_{\lambda_{2}=-1/2}^{1/2} \sum_{\lambda_{3}=0}{\left|{\sum_{\lambda_0^{\prime}=-1}^{1} \sum_{\lambda_1^{\prime}=-1/2}^{1/2} \sum_{\lambda_2^{\prime}=-1/2}^{1/2} \sum_{\lambda_3^{\prime}=0}{{A^{1}}_{\lambda_0^{\prime},\lambda_1^{\prime},\lambda_2^{\prime},\lambda_3^{\prime}} d^{\frac{1}{2}}_{\lambda_1^{\prime},\lambda_{1}}\left(\zeta^1_{1(1)}\right) d^{\frac{1}{2}}_{\lambda_2^{\prime},\lambda_{2}}\left(\zeta^2_{1(1)}\right) d^{1}_{\lambda_{0},\lambda_0^{\prime}}\left(\zeta^0_{1(1)}\right) + {A^{2}}_{\lambda_0^{\prime},\lambda_1^{\prime},\lambda_2^{\prime},\lambda_3^{\prime}} d^{\frac{1}{2}}_{\lambda_1^{\prime},\lambda_{1}}\left(\zeta^1_{2(1)}\right) d^{\frac{1}{2}}_{\lambda_2^{\prime},\lambda_{2}}\left(\zeta^2_{2(1)}\right) d^{1}_{\lambda_{0},\lambda_0^{\prime}}\left(\zeta^0_{2(1)}\right)}}\right|^{2}}\]

Unfortunately, sympy.Indexed symbols with a superscript don’t render nicely. To fix this, AmpForm-DPD provides the following configuration function.

\[\displaystyle \sum_{\lambda_{0}=-1}^{1} \sum_{\lambda_{1}=-1/2}^{1/2} \sum_{\lambda_{2}=-1/2}^{1/2} \sum_{\lambda_{3}=0}{\left|{\sum_{\lambda_0^{\prime}=-1}^{1} \sum_{\lambda_1^{\prime}=-1/2}^{1/2} \sum_{\lambda_2^{\prime}=-1/2}^{1/2} \sum_{\lambda_3^{\prime}=0}{A^{1}_{\lambda_0^{\prime}, \lambda_1^{\prime}, \lambda_2^{\prime}, \lambda_3^{\prime}} d^{\frac{1}{2}}_{\lambda_1^{\prime},\lambda_{1}}\left(\zeta^1_{1(1)}\right) d^{\frac{1}{2}}_{\lambda_2^{\prime},\lambda_{2}}\left(\zeta^2_{1(1)}\right) d^{1}_{\lambda_{0},\lambda_0^{\prime}}\left(\zeta^0_{1(1)}\right) + A^{2}_{\lambda_0^{\prime}, \lambda_1^{\prime}, \lambda_2^{\prime}, \lambda_3^{\prime}} d^{\frac{1}{2}}_{\lambda_1^{\prime},\lambda_{1}}\left(\zeta^1_{2(1)}\right) d^{\frac{1}{2}}_{\lambda_2^{\prime},\lambda_{2}}\left(\zeta^2_{2(1)}\right) d^{1}_{\lambda_{0},\lambda_0^{\prime}}\left(\zeta^0_{2(1)}\right)}}\right|^{2}}\]

More interesting is to formulate a model with a dynamics parametrization. The most common choice is a relativistic Breit–Wigner function. It can optionally have form factors for the production vertex and/or for the decay vertex and have an energy-dependent width.

from ampform.dynamics.phasespace import PhaseSpaceFactor

from ampform_dpd.dynamics.builder import BreitWignerBuilder

dynamics_builder = BreitWignerBuilder(
    energy_dependent_width=True,
    production_form_factor=True,
    decay_form_factor=True,
    phsp_factor=PhaseSpaceFactor,
)
for chain in model_builder.decay.chains:
    model_builder.dynamics_choices.register_builder(chain, dynamics_builder)
model = model_builder.formulate()

…or everything as a one-liner:

from ampform_dpd import DalitzPlotDecompositionBuilder
from ampform_dpd.dynamics.builder import BreitWignerBuilder

model_builder = DalitzPlotDecompositionBuilder(decay)
dynamics_builder = BreitWignerBuilder()
for chain in model_builder.decay.chains:
    model_builder.dynamics_choices.register_builder(chain, dynamics_builder)
model = model_builder.formulate()

Hide code cell source

selection = {k: v for i, (k, v) in enumerate(model.amplitudes.items()) if i % 13 == 0}
Math(aslatex(selection, terms_per_line=1))
\[\begin{split}\displaystyle \begin{aligned} A^{1}_{-1, - \frac{1}{2}, - \frac{1}{2}, 0} \;&=\; 2 \sum_{\lambda_{R}=-3/2}^{3/2}{- \delta_{-1, \lambda_{R} + \frac{1}{2}} \mathcal{F}_{1}\left(m_{0}^{2}, m_{\overline{N}(1700)^{-}}, m_{1}\right) \mathcal{F}_{2}\left(\sigma_{1}^{2}, m_{2}, m_{3}\right) \mathcal{H}^\mathrm{decay}_{\overline{N}(1700)^{-}, - \frac{1}{2}, 0} \mathcal{H}^\mathrm{production}_{\overline{N}(1700)^{-}, \lambda_{R}, - \frac{1}{2}} \mathcal{R}_{2}\left(\sigma_{1}, m_{\overline{N}(1700)^{-}}, \Gamma_{\overline{N}(1700)^{-}}\right) d^{\frac{3}{2}}_{\lambda_{R},- \frac{1}{2}}\left(\theta_{23}\right)} \\ \;&+\; \sum_{\lambda_{R}=-1/2}^{1/2}{- \delta_{-1, \lambda_{R} + \frac{1}{2}} \mathcal{F}_{0}\left(m_{0}^{2}, m_{\overline{N}(1710)^{-}}, m_{1}\right) \mathcal{F}_{1}\left(\sigma_{1}^{2}, m_{2}, m_{3}\right) \mathcal{H}^\mathrm{decay}_{\overline{N}(1710)^{-}, - \frac{1}{2}, 0} \mathcal{H}^\mathrm{production}_{\overline{N}(1710)^{-}, \lambda_{R}, - \frac{1}{2}} \mathcal{R}_{1}\left(\sigma_{1}, m_{\overline{N}(1710)^{-}}, \Gamma_{\overline{N}(1710)^{-}}\right) d^{\frac{1}{2}}_{\lambda_{R},- \frac{1}{2}}\left(\theta_{23}\right)} \\ \;&+\; \sum_{\lambda_{R}=-1/2}^{1/2}{- \delta_{-1, \lambda_{R} + \frac{1}{2}} \mathcal{F}_{2}\left(m_{0}^{2}, m_{\overline{N}(1710)^{-}}, m_{1}\right) \mathcal{F}_{1}\left(\sigma_{1}^{2}, m_{2}, m_{3}\right) \mathcal{H}^\mathrm{decay}_{\overline{N}(1710)^{-}, - \frac{1}{2}, 0} \mathcal{H}^\mathrm{production}_{\overline{N}(1710)^{-}, \lambda_{R}, - \frac{1}{2}} \mathcal{R}_{1}\left(\sigma_{1}, m_{\overline{N}(1710)^{-}}, \Gamma_{\overline{N}(1710)^{-}}\right) d^{\frac{1}{2}}_{\lambda_{R},- \frac{1}{2}}\left(\theta_{23}\right)} \\ \;&+\; \sum_{\lambda_{R}=-3/2}^{3/2}{- \delta_{-1, \lambda_{R} + \frac{1}{2}} \mathcal{F}_{0}\left(m_{0}^{2}, m_{\overline{N}(1720)^{-}}, m_{1}\right) \mathcal{F}_{1}\left(\sigma_{1}^{2}, m_{2}, m_{3}\right) \mathcal{H}^\mathrm{decay}_{\overline{N}(1720)^{-}, - \frac{1}{2}, 0} \mathcal{H}^\mathrm{production}_{\overline{N}(1720)^{-}, \lambda_{R}, - \frac{1}{2}} \mathcal{R}_{1}\left(\sigma_{1}, m_{\overline{N}(1720)^{-}}, \Gamma_{\overline{N}(1720)^{-}}\right) d^{\frac{3}{2}}_{\lambda_{R},- \frac{1}{2}}\left(\theta_{23}\right)} \\ \;&+\; 2 \sum_{\lambda_{R}=-3/2}^{3/2}{- \delta_{-1, \lambda_{R} + \frac{1}{2}} \mathcal{F}_{2}\left(m_{0}^{2}, m_{\overline{N}(1720)^{-}}, m_{1}\right) \mathcal{F}_{1}\left(\sigma_{1}^{2}, m_{2}, m_{3}\right) \mathcal{H}^\mathrm{decay}_{\overline{N}(1720)^{-}, - \frac{1}{2}, 0} \mathcal{H}^\mathrm{production}_{\overline{N}(1720)^{-}, \lambda_{R}, - \frac{1}{2}} \mathcal{R}_{1}\left(\sigma_{1}, m_{\overline{N}(1720)^{-}}, \Gamma_{\overline{N}(1720)^{-}}\right) d^{\frac{3}{2}}_{\lambda_{R},- \frac{1}{2}}\left(\theta_{23}\right)} \\ A^{2}_{0, \frac{1}{2}, - \frac{1}{2}, 0} \;&=\; \sum_{\lambda_{R}=-1/2}^{1/2}{- \delta_{0, \lambda_{R} + \frac{1}{2}} \mathcal{F}_{0}\left(m_{0}^{2}, m_{\Sigma(1660)^{+}}, m_{2}\right) \mathcal{F}_{1}\left(\sigma_{2}^{2}, m_{1}, m_{3}\right) \mathcal{H}^\mathrm{decay}_{\Sigma(1660)^{+}, 0, \frac{1}{2}} \mathcal{H}^\mathrm{production}_{\Sigma(1660)^{+}, \lambda_{R}, - \frac{1}{2}} \mathcal{R}_{1}\left(\sigma_{2}, m_{\Sigma(1660)^{+}}, \Gamma_{\Sigma(1660)^{+}}\right) d^{\frac{1}{2}}_{\lambda_{R},- \frac{1}{2}}\left(\theta_{31}\right)} \\ \;&+\; \sum_{\lambda_{R}=-1/2}^{1/2}{- \delta_{0, \lambda_{R} + \frac{1}{2}} \mathcal{F}_{2}\left(m_{0}^{2}, m_{\Sigma(1660)^{+}}, m_{2}\right) \mathcal{F}_{1}\left(\sigma_{2}^{2}, m_{1}, m_{3}\right) \mathcal{H}^\mathrm{decay}_{\Sigma(1660)^{+}, 0, \frac{1}{2}} \mathcal{H}^\mathrm{production}_{\Sigma(1660)^{+}, \lambda_{R}, - \frac{1}{2}} \mathcal{R}_{1}\left(\sigma_{2}, m_{\Sigma(1660)^{+}}, \Gamma_{\Sigma(1660)^{+}}\right) d^{\frac{1}{2}}_{\lambda_{R},- \frac{1}{2}}\left(\theta_{31}\right)} \\ \;&+\; 2 \sum_{\lambda_{R}=-3/2}^{3/2}{- \delta_{0, \lambda_{R} + \frac{1}{2}} \mathcal{F}_{1}\left(m_{0}^{2}, m_{\Sigma(1670)^{+}}, m_{2}\right) \mathcal{F}_{2}\left(\sigma_{2}^{2}, m_{1}, m_{3}\right) \mathcal{H}^\mathrm{decay}_{\Sigma(1670)^{+}, 0, \frac{1}{2}} \mathcal{H}^\mathrm{production}_{\Sigma(1670)^{+}, \lambda_{R}, - \frac{1}{2}} \mathcal{R}_{2}\left(\sigma_{2}, m_{\Sigma(1670)^{+}}, \Gamma_{\Sigma(1670)^{+}}\right) d^{\frac{3}{2}}_{\lambda_{R},- \frac{1}{2}}\left(\theta_{31}\right)} \\ \;&+\; 2 \sum_{\lambda_{R}=-1/2}^{1/2}{- \delta_{0, \lambda_{R} + \frac{1}{2}} \mathcal{F}_{1}\left(m_{0}^{2}, m_{\Sigma(1750)^{+}}, m_{2}\right) \mathcal{F}_{0}\left(\sigma_{2}^{2}, m_{1}, m_{3}\right) \mathcal{H}^\mathrm{decay}_{\Sigma(1750)^{+}, 0, \frac{1}{2}} \mathcal{H}^\mathrm{production}_{\Sigma(1750)^{+}, \lambda_{R}, - \frac{1}{2}} \mathcal{R}_{0}\left(\sigma_{2}, m_{\Sigma(1750)^{+}}, \Gamma_{\Sigma(1750)^{+}}\right) d^{\frac{1}{2}}_{\lambda_{R},- \frac{1}{2}}\left(\theta_{31}\right)} \\ \;&+\; \sum_{\lambda_{R}=-5/2}^{5/2}{- \delta_{0, \lambda_{R} + \frac{1}{2}} \mathcal{F}_{1}\left(m_{0}^{2}, m_{\Sigma(1775)^{+}}, m_{2}\right) \mathcal{F}_{2}\left(\sigma_{2}^{2}, m_{1}, m_{3}\right) \mathcal{H}^\mathrm{decay}_{\Sigma(1775)^{+}, 0, \frac{1}{2}} \mathcal{H}^\mathrm{production}_{\Sigma(1775)^{+}, \lambda_{R}, - \frac{1}{2}} \mathcal{R}_{2}\left(\sigma_{2}, m_{\Sigma(1775)^{+}}, \Gamma_{\Sigma(1775)^{+}}\right) d^{\frac{5}{2}}_{\lambda_{R},- \frac{1}{2}}\left(\theta_{31}\right)} \\ \end{aligned}\end{split}\]

Here’s an example with a simple Breit–Wigner without form factors:

bw_builder = BreitWignerBuilder(
    energy_dependent_width=False,
    production_form_factor=False,
    decay_form_factor=False,
)
for chain in model_builder.decay.chains:
    model_builder.dynamics_choices.register_builder(chain, bw_builder)
simple_model = model_builder.formulate()

Hide code cell source

(amp_symbol, amp_expr), *_ = simple_model.amplitudes.items()
Math(aslatex({amp_symbol: amp_expr}, terms_per_line=1))
\[\begin{split}\displaystyle \begin{aligned} A^{1}_{-1, - \frac{1}{2}, - \frac{1}{2}, 0} \;&=\; 2 \sum_{\lambda_{R}=-3/2}^{3/2}{- \delta_{-1, \lambda_{R} + \frac{1}{2}} \mathcal{H}^\mathrm{decay}_{\overline{N}(1700)^{-}, - \frac{1}{2}, 0} \mathcal{H}^\mathrm{production}_{\overline{N}(1700)^{-}, \lambda_{R}, - \frac{1}{2}} \mathcal{R}^\mathrm{BW}\left(\sigma_{1}; m_{\overline{N}(1700)^{-}}, \Gamma_{\overline{N}(1700)^{-}}\right) d^{\frac{3}{2}}_{\lambda_{R},- \frac{1}{2}}\left(\theta_{23}\right)} \\ \;&+\; 2 \sum_{\lambda_{R}=-1/2}^{1/2}{- \delta_{-1, \lambda_{R} + \frac{1}{2}} \mathcal{H}^\mathrm{decay}_{\overline{N}(1710)^{-}, - \frac{1}{2}, 0} \mathcal{H}^\mathrm{production}_{\overline{N}(1710)^{-}, \lambda_{R}, - \frac{1}{2}} \mathcal{R}^\mathrm{BW}\left(\sigma_{1}; m_{\overline{N}(1710)^{-}}, \Gamma_{\overline{N}(1710)^{-}}\right) d^{\frac{1}{2}}_{\lambda_{R},- \frac{1}{2}}\left(\theta_{23}\right)} \\ \;&+\; 3 \sum_{\lambda_{R}=-3/2}^{3/2}{- \delta_{-1, \lambda_{R} + \frac{1}{2}} \mathcal{H}^\mathrm{decay}_{\overline{N}(1720)^{-}, - \frac{1}{2}, 0} \mathcal{H}^\mathrm{production}_{\overline{N}(1720)^{-}, \lambda_{R}, - \frac{1}{2}} \mathcal{R}^\mathrm{BW}\left(\sigma_{1}; m_{\overline{N}(1720)^{-}}, \Gamma_{\overline{N}(1720)^{-}}\right) d^{\frac{3}{2}}_{\lambda_{R},- \frac{1}{2}}\left(\theta_{23}\right)} \\ \end{aligned}\end{split}\]

Custom dynamics can be defined by defining a dynamics builder function that has a signature that matches the DynamicsBuilder protocol.

import sympy as sp

from ampform_dpd import DefinedExpression
from ampform_dpd.decay import ThreeBodyDecayChain
from ampform_dpd.dynamics.builder import create_mass_symbol, get_mandelstam_s


def formulate_gaussian(decay_chain: ThreeBodyDecayChain) -> DefinedExpression:
    resonance = decay_chain.resonance
    s = get_mandelstam_s(decay_chain.decay_node)
    x = sp.sqrt(s)
    mu = create_mass_symbol(resonance)
    sigma2 = sp.Symbol(Rf"\sigma_{{{resonance.latex}}}^2", nonnegative=True)
    return DefinedExpression(
        expression=sp.exp(-((x - mu) ** 2) / (2 * sigma2)),
        parameters={
            mu: resonance.mass,
            sigma2: resonance.width**2,
        },
    )


for chain in model_builder.decay.chains:
    model_builder.dynamics_choices.register_builder(chain, formulate_gaussian)
gaussian_model = model_builder.formulate()

Hide code cell source

(amp_symbol, amp_expr), *_ = gaussian_model.amplitudes.items()
Math(aslatex({amp_symbol: amp_expr}, terms_per_line=1))
\[\begin{split}\displaystyle \begin{aligned} A^{1}_{-1, - \frac{1}{2}, - \frac{1}{2}, 0} \;&=\; 2 \sum_{\lambda_{R}=-3/2}^{3/2}{- e^{- \frac{\left(- m_{\overline{N}(1700)^{-}} + \sqrt{\sigma_{1}}\right)^{2}}{2 \sigma_{\overline{N}(1700)^{-}}^2}} \delta_{-1, \lambda_{R} + \frac{1}{2}} \mathcal{H}^\mathrm{decay}_{\overline{N}(1700)^{-}, - \frac{1}{2}, 0} \mathcal{H}^\mathrm{production}_{\overline{N}(1700)^{-}, \lambda_{R}, - \frac{1}{2}} d^{\frac{3}{2}}_{\lambda_{R},- \frac{1}{2}}\left(\theta_{23}\right)} \\ \;&+\; 2 \sum_{\lambda_{R}=-1/2}^{1/2}{- e^{- \frac{\left(- m_{\overline{N}(1710)^{-}} + \sqrt{\sigma_{1}}\right)^{2}}{2 \sigma_{\overline{N}(1710)^{-}}^2}} \delta_{-1, \lambda_{R} + \frac{1}{2}} \mathcal{H}^\mathrm{decay}_{\overline{N}(1710)^{-}, - \frac{1}{2}, 0} \mathcal{H}^\mathrm{production}_{\overline{N}(1710)^{-}, \lambda_{R}, - \frac{1}{2}} d^{\frac{1}{2}}_{\lambda_{R},- \frac{1}{2}}\left(\theta_{23}\right)} \\ \;&+\; 3 \sum_{\lambda_{R}=-3/2}^{3/2}{- e^{- \frac{\left(- m_{\overline{N}(1720)^{-}} + \sqrt{\sigma_{1}}\right)^{2}}{2 \sigma_{\overline{N}(1720)^{-}}^2}} \delta_{-1, \lambda_{R} + \frac{1}{2}} \mathcal{H}^\mathrm{decay}_{\overline{N}(1720)^{-}, - \frac{1}{2}, 0} \mathcal{H}^\mathrm{production}_{\overline{N}(1720)^{-}, \lambda_{R}, - \frac{1}{2}} d^{\frac{3}{2}}_{\lambda_{R},- \frac{1}{2}}\left(\theta_{23}\right)} \\ \end{aligned}\end{split}\]

The DalitzPlotDecompositionBuilder.formulate() method has other arguments that allow you to select a different reference subsystem and to use one complex-valued coefficient rather than two couplings per decay vertex. Also notice the tricks used here to hide the trivial summations over the helicities of spin-0 particles.

for chain in model_builder.decay.chains:
    model_builder.dynamics_choices.register_builder(chain, bw_builder)
coefficient_model = model_builder.formulate(
    cleanup_summations=True,
    reference_subsystem=2,
    use_coefficients=True,
)
coefficient_model.intensity.cleanup()
\[\displaystyle \sum_{\lambda_{0}=-1}^{1} \sum_{\lambda_{1}=-1/2}^{1/2} \sum_{\lambda_{2}=-1/2}^{1/2}{\left|{\sum_{\lambda_0^{\prime}=-1}^{1} \sum_{\lambda_1^{\prime}=-1/2}^{1/2} \sum_{\lambda_2^{\prime}=-1/2}^{1/2}{A^{1}_{\lambda_0^{\prime}, \lambda_1^{\prime}, \lambda_2^{\prime}, 0} d^{\frac{1}{2}}_{\lambda_1^{\prime},\lambda_{1}}\left(\zeta^1_{1(2)}\right) d^{\frac{1}{2}}_{\lambda_2^{\prime},\lambda_{2}}\left(\zeta^2_{1(2)}\right) d^{1}_{\lambda_{0},\lambda_0^{\prime}}\left(\zeta^0_{1(2)}\right) + A^{2}_{\lambda_0^{\prime}, \lambda_1^{\prime}, \lambda_2^{\prime}, 0} d^{\frac{1}{2}}_{\lambda_1^{\prime},\lambda_{1}}\left(\zeta^1_{2(2)}\right) d^{\frac{1}{2}}_{\lambda_2^{\prime},\lambda_{2}}\left(\zeta^2_{2(2)}\right) d^{1}_{\lambda_{0},\lambda_0^{\prime}}\left(\zeta^0_{2(2)}\right)}}\right|^{2}}\]

Hide code cell source

(symbol, expr), *_ = coefficient_model.amplitudes.items()
Latex(aslatex({symbol: expr}, terms_per_line=1))
\[\begin{split}\begin{aligned} A^{1}_{-1, - \frac{1}{2}, - \frac{1}{2}, 0} \;&=\; 2 \sum_{\lambda_{R}=-3/2}^{3/2}{- \delta_{-1, \lambda_{R} + \frac{1}{2}} \mathcal{H}^\mathrm{\overline{N}(1700)^{-}}_{\lambda_{R}, - \frac{1}{2}, - \frac{1}{2}, 0} \mathcal{R}^\mathrm{BW}\left(\sigma_{1}; m_{\overline{N}(1700)^{-}}, \Gamma_{\overline{N}(1700)^{-}}\right) d^{\frac{3}{2}}_{\lambda_{R},- \frac{1}{2}}\left(\theta_{23}\right)} \\ \;&+\; 2 \sum_{\lambda_{R}=-1/2}^{1/2}{- \delta_{-1, \lambda_{R} + \frac{1}{2}} \mathcal{H}^\mathrm{\overline{N}(1710)^{-}}_{\lambda_{R}, - \frac{1}{2}, - \frac{1}{2}, 0} \mathcal{R}^\mathrm{BW}\left(\sigma_{1}; m_{\overline{N}(1710)^{-}}, \Gamma_{\overline{N}(1710)^{-}}\right) d^{\frac{1}{2}}_{\lambda_{R},- \frac{1}{2}}\left(\theta_{23}\right)} \\ \;&+\; 3 \sum_{\lambda_{R}=-3/2}^{3/2}{- \delta_{-1, \lambda_{R} + \frac{1}{2}} \mathcal{H}^\mathrm{\overline{N}(1720)^{-}}_{\lambda_{R}, - \frac{1}{2}, - \frac{1}{2}, 0} \mathcal{R}^\mathrm{BW}\left(\sigma_{1}; m_{\overline{N}(1720)^{-}}, \Gamma_{\overline{N}(1720)^{-}}\right) d^{\frac{3}{2}}_{\lambda_{R},- \frac{1}{2}}\left(\theta_{23}\right)} \\ \end{aligned}\end{split}\]

Examples#