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.
Simplified model: \(J/\psi \to f_0\gamma\)
As Step 3: Perform fit serves to illustrate usage only, we make the amplitude model here a bit simpler by not allowing \(\omega\) resonances (which are narrow and therefore hard to fit). For this reason, we can also limit the InteractionTypes
to Strong
.
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)
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.