Reaction via qrules#

Address to issue ✅ ComPWA/gluex-nstar#5, this section is an investigation of creating a virtual particle that represents the state \(p \gamma\) in QRules

As an example of side note, create a virtual particle that represents state \(e^+ e^-\) can be seen here.

Finding particles#

Our reaction is \(p + \gamma \to \eta + \pi^0 + p\), so we can look for each of the reaction and decay particles

Hide code cell content
from __future__ import annotations

import graphviz
import qrules
from ampform.io import improve_latex_rendering
from IPython.display import Math
from qrules import InteractionType, StateTransitionManager, io
from qrules.particle import Particle, Spin, load_pdg

improve_latex_rendering()
particle_db = load_pdg()

The ParticleCollection class offers some methods to search for particles by name or by PID, name, or other properties.

Proton#

Search by Particle ID (PID) for proton:

particle_db.find(2212)
Particle(
  name='p',
  pid=2212,
  latex='p',
  spin=0.5,
  mass=0.93827208816,
  charge=1,
  isospin=Spin(1/2, +1/2),
  baryon_number=1,
  parity=+1,
)

Search by Particle name for proton:

particle_db.find("p")
proton = particle_db["p"]
Math(proton.latex)
\[\displaystyle p\]

\(\gamma\)#

similarly for \(\gamma\):

particle_db.find("gamma")
Particle(
  name='gamma',
  pid=22,
  latex='\\gamma',
  spin=1.0,
  mass=0.0,
  parity=-1,
  c_parity=-1,
)
gamma = particle_db["gamma"]
Math(gamma.latex)
\[\displaystyle \gamma\]

\(\eta\)#

particle_db.find("eta")
Particle(
  name='eta',
  pid=221,
  latex='\\eta',
  spin=0.0,
  mass=0.547862,
  width=1.31e-06,
  isospin=Spin(0, 0),
  parity=-1,
  c_parity=+1,
  g_parity=+1,
)
eta = particle_db["eta"]
Math(gamma.latex)
\[\displaystyle \gamma\]

\(\pi^0\)#

particle_db.find("pi0")
Particle(
  name='pi0',
  pid=111,
  latex='\\pi^{0}',
  spin=0.0,
  mass=0.1349768,
  width=7.81e-09,
  isospin=Spin(1, 0),
  parity=-1,
  c_parity=+1,
  g_parity=-1,
)
pi0 = particle_db["pi0"]
Math(pi0.latex)
\[\displaystyle \pi^{0}\]

Virtual particle that represents the state pγ#

Adding custom particle#

We add the virtual particle \(p\gamma\) to represent the state of \(p-\gamma\) system in the photoproduction reaction. See PWA101 (temporary here), the value of the mass of the system \(m_{p\gamma}\) in CM frame is about 4.102 GeV in this analysis.

We use Particle from QRules for adding custom particle, so that some quantum numbers we need to determine for the \(p\gamma\) virtual state particle:

  • (Total) Spin

    • \(J_{p\gamma} = \frac{1}{2}\) or \(\frac{3}{2}\)

      because \(J_{p\gamma}\) = from \(|s_p-s_{\gamma}|\) to \(s_p + s_{\gamma}\) = from \(|\frac{1}{2}-1|\) to \(\frac{1}{2} + 1\)

  • Mass

    • \(m_{p\gamma} = E_{p\gamma} \approx 4.102\)

  • Charge

    • \(Q_{p\gamma} = Q_p + Q_{\gamma} = 1 \)

  • Isospin and \(3^{rd}\) component of isospin

    • \(I_{p\gamma} = I_p = \frac{1}{2}\)

    • \(I_{3_{p\gamma}} = I_{3_p} = +\frac{1}{2}\)

  • Baryon Number

    • \(B_{p\gamma} = B_p = 1\)

  • Parity

    • \(P_{p\gamma} = P_p \times P_{\gamma} = +1 \times (-1) = -1\)

These quantum numbers provide a complete and accurate description of the virtual particle representing the p−γ system with a mass of 4.102 GeV. The pγ virtual particle has two possibilities for the total spin, while the other quantum numbers are fixed.

We add the spin-\(\frac{1}{2}\) \(p\gamma\) virtual particle via QRules and named it \(p\gamma\) with a make-up pid number 99990

pgamma = Particle(
    name="pgamma",
    latex=r"p\gamma (s1/2)",
    spin=0.5,
    mass=4.101931071854584,
    charge=1,
    isospin=Spin(1 / 2, +1 / 2),
    baryon_number=1,
    parity=-1,
    pid=99990,
)
pgamma
Particle(
  name='pgamma',
  pid=99990,
  latex='p\\gamma (s1/2)',
  spin=0.5,
  mass=4.101931071854584,
  charge=1,
  isospin=Spin(1/2, +1/2),
  baryon_number=1,
  parity=-1,
)

We add the spin-\(\frac{3}{2}\) \(p\gamma\) virtual particle via QRules and named it \(p\gamma (s3/2)\) with a make-up pid number 99991

pgamma2 = Particle(
    name="pgamma2",
    latex=R"p\gamma (s3/2)",
    spin=1.5,
    mass=4.101931071854584,
    charge=1,
    isospin=Spin(1 / 2, +1 / 2),
    baryon_number=1,
    parity=-1,
    pid=99991,
)
pgamma2
Particle(
  name='pgamma2',
  pid=99991,
  latex='p\\gamma (s3/2)',
  spin=1.5,
  mass=4.101931071854584,
  charge=1,
  isospin=Spin(1/2, +1/2),
  baryon_number=1,
  parity=-1,
)
Math(pgamma.latex)
\[\displaystyle p\gamma (s1/2)\]
Math(pgamma2.latex)
\[\displaystyle p\gamma (s3/2)\]
particle_db.add(pgamma)
particle_db.add(pgamma2)

The \(`p\gamma`\) virtual states generated via QRules will be used in later stages, both possible spin states \((J= \frac{1}{2}\) and \(\frac{3}{2})\) should be taken into account if possible, otherwise simplified if necessary.

Important

It is possible to add any kind of custom Particle, as long as its quantum numbers comply with the gellmann_nishijima() rule:

Note

Gell-Mann-Nishijima formula: \(Q = I_3 + \frac{1}{2}(B+S+C+B'+T)\)

where Q is charge, \(I_3\) is Spin projection of isospin, B is baryon number, S is strangeness, C is charmness, B’ is bottomness, and T is topness.

reaction1_all = qrules.generate_transitions(
    initial_state=("pgamma"),
    final_state=["eta", "pi0", "p"],
    allowed_interaction_types=["strong", "EM", "weak"],
    formalism="canonical-helicity",
    particle_db=particle_db,
)
dot_all = qrules.io.asdot(reaction1_all, collapse_graphs=True)
graphviz.Source(dot_all)
../_images/4967cab91a70a7d7dc992c49ca316861c49a83462f9fc5f343572006882bcc32.svg
reaction1_strong_em = qrules.generate_transitions(
    initial_state=("pgamma"),
    final_state=["eta", "pi0", "p"],
    allowed_interaction_types=["strong", "EM"],
    formalism="canonical-helicity",
    particle_db=particle_db,
)
dot_se = qrules.io.asdot(reaction1_strong_em, collapse_graphs=True)
graphviz.Source(dot_se)
../_images/9ab4e81a717a8efab6414aca901378710f893f8baaba313c6ef4df6c3baec37b.svg
reaction1_strong = qrules.generate_transitions(
    initial_state=("pgamma"),
    final_state=["eta", "pi0", "p"],
    allowed_interaction_types=["strong"],
    formalism="canonical-helicity",
    particle_db=particle_db,
)
dot_s = qrules.io.asdot(reaction1_strong, collapse_graphs=True)
graphviz.Source(dot_s)
../_images/9bd8dc75625f9ab6bc6f5af9ab188d6ca8b6c3eff457980008ccbb1959043010.svg
stm = StateTransitionManager(
    initial_state=["pgamma"],
    final_state=["eta", "pi0", "p"],
    formalism="canonical-helicity",
    particle_db=particle_db,
)
problem_sets = stm.create_problem_sets()
sorted(problem_sets, reverse=True)
[3600.0, 60.0, 1.0, 0.006, 0.0001, 1e-08]
some_problem_set = problem_sets[60.0][0]
dot = io.asdot(some_problem_set, render_node=True)
graphviz.Source(dot)
../_images/9e17a42d26c6db317e5a7c6f47dc7690aeb1b3109f8912ff7b64a7e970daa1c6.svg
some_problem_set = problem_sets[1][0]
dot = io.asdot(some_problem_set, render_node=True)
graphviz.Source(dot)
../_images/fc8a3941ca6e3e5ada22a9d754a8040297ab89ec7cfa56f1b4b2fdd426ecebcd.svg
some_problem_set = problem_sets[0.0001][1]
dot = io.asdot(some_problem_set, render_node=True)
graphviz.Source(dot)
../_images/e612cad126b21866aaefb979b026e632e312264c6886527b967cfeaf799e67d3.svg
reaction = stm.find_solutions(problem_sets)
print("found", len(reaction.transitions), "solutions!")
reaction.get_intermediate_particles().names
found 2280 solutions!
['a(0)(980)0',
 'a(1)(1260)0',
 'a(0)(1450)0',
 'a(1)(1640)0',
 'b(1)(1235)0',
 'D~0',
 'D0',
 'D*(2007)~0',
 'D*(2007)0',
 'D(0)*(2300)~0',
 'D(0)*(2300)0',
 'D(1)(2430)~0',
 'D(1)(2430)0',
 'D(1)(2420)~0',
 'D(1)(2420)0',
 'Delta(1232)+',
 'Delta(1600)+',
 'Delta(1620)+',
 'Delta(1700)+',
 'Delta(1900)+',
 'Delta(1910)+',
 'Delta(1920)+',
 "eta'(958)",
 'eta(1295)',
 'eta(1405)',
 'eta(1475)',
 'eta(c)(1S)',
 'f(0)(500)',
 'f(0)(980)',
 'f(1)(1285)',
 'f(0)(1370)',
 'f(1)(1420)',
 'f(0)(1500)',
 'f(0)(1710)',
 'f(0)(2020)',
 'h(1)(1170)',
 'J/psi(1S)',
 'K(0)*(700)0',
 'K(0)*(700)~0',
 'K*(892)0',
 'K*(892)~0',
 'K(1)(1270)~0',
 'K(1)(1270)0',
 'K(1)(1400)0',
 'K(1)(1400)~0',
 'K*(1410)~0',
 'K*(1410)0',
 'K(0)*(1430)0',
 'K(0)*(1430)~0',
 'K(1)(1650)0',
 'K(1)(1650)~0',
 'K*(1680)0',
 'K*(1680)~0',
 'K(0)*(1950)0',
 'K(0)*(1950)~0',
 'Lambda(c)+',
 'Lambda(c)(2595)+',
 'Lambda(c)(2625)+',
 'N(1440)+',
 'N(1520)+',
 'N(1535)+',
 'N(1650)+',
 'N(1710)+',
 'N(1700)+',
 'N(1720)+',
 'omega(782)',
 'omega(1420)',
 'omega(1650)',
 'phi(1020)',
 'phi(1680)',
 'pi(1300)0',
 'pi(1)(1600)0',
 'pi(1800)0',
 'rho(770)0',
 'rho(1450)0',
 'rho(1700)0',
 'Sigma+',
 'Sigma(1385)+',
 'Sigma(1660)+',
 'Sigma(1670)+',
 'Sigma(1750)+',
 'Sigma(1910)+',
 'Sigma(c)(2455)+',
 'Sigma(c)(2520)+',
 'Xi(c)+',
 "Xi(c)'+",
 'Xi(c)(2645)+',
 'Xi(c)(2790)+',
 'Xi(c)(2815)+']
stm.set_allowed_interaction_types([InteractionType.STRONG])
problem_sets = stm.create_problem_sets()
reaction = stm.find_solutions(problem_sets)

print("found", len(reaction.transitions), "solutions!")
reaction.get_intermediate_particles().names
found 80 solutions!
['a(0)(980)0',
 'a(0)(1450)0',
 'N(1440)+',
 'N(1535)+',
 'N(1650)+',
 'N(1710)+',
 'pi(1)(1600)0']
stm.set_allowed_interaction_types([InteractionType.STRONG, InteractionType.EM])
problem_sets = stm.create_problem_sets()
reaction = stm.find_solutions(problem_sets)

print("found", len(reaction.transitions), "solutions!")
reaction.get_intermediate_particles().names
found 152 solutions!
['a(0)(980)0',
 'a(0)(1450)0',
 'Delta(1620)+',
 'Delta(1900)+',
 'Delta(1910)+',
 'f(0)(500)',
 'f(0)(980)',
 'f(0)(1370)',
 'f(0)(1500)',
 'f(0)(1710)',
 'f(0)(2020)',
 'N(1440)+',
 'N(1535)+',
 'N(1650)+',
 'N(1710)+',
 'pi(1)(1600)0']