Step 1: Create an amplitude model

tensorwaves requires you to first formulate an amplitude model that you want to fit to your data set. The expertsystem helps you to construct such a model.

This notebook briefly illustrates how to create such an amplitude model with the expertsystem and how to write it to a recipe file that can be understood by tensorwaves. For more control, have a look at the usage guides of the PWA Expert System.

In this example, we use the helicity formalism, but you can also use formalism_type="canonical-helicity". As you can see, we analyze the decay \(J/\psi \to \pi^0\pi^0\gamma\) here.

import expertsystem as es

result = es.generate_transitions(
    initial_state=("J/psi(1S)", [-1, +1]),
    final_state=["gamma", "pi0", "pi0"],
    allowed_intermediate_particles=["f(0)"],
    allowed_interaction_types="strong and EM",
)

As a small goodie, you can use graphviz to visualize the found graphs:

from graphviz import Source

graphs = result.collapse_graphs()
dot = es.io.convert_to_dot(graphs)
Source(dot)
../_images/1_create_model_6_0.svg

Next we convert the solutions into an AmplitudeModel. This can be done with the generate_amplitudes() method.

model = es.generate_amplitudes(result)
list(model.parameters)
['MesonRadius_J/psi(1S)',
 'Magnitude_J/psi(1S)_to_f(0)(500)_0+gamma_1;f(0)(500)_to_pi0_0+pi0_0;',
 'Phase_J/psi(1S)_to_f(0)(500)_0+gamma_1;f(0)(500)_to_pi0_0+pi0_0;',
 'Magnitude_J/psi(1S)_to_f(0)(1500)_0+gamma_1;f(0)(1500)_to_pi0_0+pi0_0;',
 'Phase_J/psi(1S)_to_f(0)(1500)_0+gamma_1;f(0)(1500)_to_pi0_0+pi0_0;',
 'Magnitude_J/psi(1S)_to_f(0)(1710)_0+gamma_1;f(0)(1710)_to_pi0_0+pi0_0;',
 'Phase_J/psi(1S)_to_f(0)(1710)_0+gamma_1;f(0)(1710)_to_pi0_0+pi0_0;',
 'Magnitude_J/psi(1S)_to_f(0)(1370)_0+gamma_1;f(0)(1370)_to_pi0_0+pi0_0;',
 'Phase_J/psi(1S)_to_f(0)(1370)_0+gamma_1;f(0)(1370)_to_pi0_0+pi0_0;',
 'Magnitude_J/psi(1S)_to_f(0)(980)_0+gamma_1;f(0)(980)_to_pi0_0+pi0_0;',
 'Phase_J/psi(1S)_to_f(0)(980)_0+gamma_1;f(0)(980)_to_pi0_0+pi0_0;']

Note that we have to specify the dynamics for the resonances. We choose to use RelativisticBreitWigner for all resonances:

for name in result.get_intermediate_particles().names:
    model.dynamics.set_breit_wigner(name)
{name: type(dyn) for name, dyn in model.dynamics.items()}
{'J/psi(1S)': expertsystem.amplitude.model.NonDynamic,
 'f(0)(1500)': expertsystem.amplitude.model.RelativisticBreitWigner,
 'f(0)(500)': expertsystem.amplitude.model.RelativisticBreitWigner,
 'f(0)(1710)': expertsystem.amplitude.model.RelativisticBreitWigner,
 'f(0)(980)': expertsystem.amplitude.model.RelativisticBreitWigner,
 'f(0)(1370)': expertsystem.amplitude.model.RelativisticBreitWigner}

Finally, we can write the AmplitudeModel, using the io.write function:

es.io.write(model, "amplitude_model_helicity.yml")

Cool, that’s it! We now have a recipe for an amplitude model with which to generate data and perform a fit! In the next steps, we will use use this AmplitudeModel as a fit model template for tensorwaves.