Note
Go to the end to download the full example code.
Example for Numeric Amplitude
This example give a full formula and code for numeric results of a total amplitude. Here we use \(\Lambda_c^{+} \rightarrow \Lambda (\rightarrow p \pi^{-}) \pi^{+} \pi^{0}\) as an example to show how its amplitudes are calculated.
0. The inputs
A total amplitude requires two inputs, the ampulitude parameters and data. In TFPWA, amplitude parameters include the coupling, mass, widths and so on. And the data include the 4-momenta \(p^{\mu}\), and some addtional datas, such as charge and weight. In the simple example, we only consider \(p^{\mu}\).
In this example, we will calculate the amplitude with the following data
18 import cmath
19 import itertools
20 import math
21 from pprint import pprint
22
23 m_lc, m_l, m_p, m_pi, m_pi0 = (
24 2.28646,
25 1.115683,
26 0.93827208816,
27 0.13957039,
28 0.1349768,
29 )
30 m_sigma_1660, g_sigma_1660 = 1.665, 0.3
31 m_rho770, g_rho770 = 0.77511, 0.1491
32
33 # the example momentum is generated by the follwing code
34 if False:
35 from tf_pwa import set_random_seed
36 from tf_pwa.phasespace import generate_phsp
37
38 set_random_seed(2025)
39 ((p_p_tf, p_pim_tf), p_pip_tf, p_pi0_tf), _ = generate_phsp(
40 4.6, [(m_lc, [(m_l, [m_p, m_pi]), m_pi, m_pi0]), m_lc], N=1
41 )
42 [p_p, p_pim, p_pip, p_pi0] = [
43 i[0].numpy().tolist() for i in [p_p_tf, p_pim_tf, p_pip_tf, p_pi0_tf]
44 ]
45
46 p_p = [
47 0.9798045738146876,
48 0.023972732547648895,
49 0.16664847395929822,
50 -0.22653054025735844,
51 ]
52 p_pim = [
53 0.19300790258521403,
54 0.12035810723629733,
55 0.004987489309569788,
56 -0.057106984410615395,
57 ]
58 p_pip = [
59 0.8227454084228714,
60 -0.06451285582391393,
61 -0.5452445877195563,
62 0.5966376993721896,
63 ]
64 p_pi0 = [
65 0.3044421333949209,
66 -0.11013601413926419,
67 0.15645293575957042,
68 -0.19457341372741113,
69 ]
70
71 print("p", p_p)
72 print("pim", p_pim)
73 print("pip", p_pip)
74 print("pi0", p_pi0)
p [0.9798045738146876, 0.023972732547648895, 0.16664847395929822, -0.22653054025735844]
pim [0.19300790258521403, 0.12035810723629733, 0.004987489309569788, -0.057106984410615395]
pip [0.8227454084228714, -0.06451285582391393, -0.5452445877195563, 0.5966376993721896]
pi0 [0.3044421333949209, -0.11013601413926419, 0.15645293575957042, -0.19457341372741113]
The example using the following config and parameters
80 config_str = f"""
81 data:
82 dat_order: [p, pim, pip, pi0]
83 random_z: False
84 decay:
85 Lc:
86 - [Sigma, pi0, p_break: True, barrier_factor_norm: True]
87 - [rho, Lambda, p_break: True, barrier_factor_norm: True]
88 Sigma: [Lambda, pip, barrier_factor_norm: True]
89 rho: [pip, pi0, barrier_factor_norm: True]
90 Lambda: [p, pim, p_break: True, barrier_factor_norm: True]
91
92 particle:
93 $top:
94 Lc:
95 J: 1/2
96 P: +1
97 mass: {m_lc}
98 $finals:
99 p:
100 J: 1/2
101 P: +1
102 mass: {m_p}
103 pip:
104 J: 0
105 P: -1
106 mass: {m_pi}
107 pim:
108 J: 0
109 P: -1
110 mass: {m_pi}
111 pi0:
112 J: 0
113 P: -1
114 mass: {m_pi0}
115 Lambda:
116 J: 1/2
117 P: +1
118 mass: {m_l}
119 model: one
120 Sigma:
121 J: 1/2
122 P: +1
123 mass: {m_sigma_1660}
124 width: {g_sigma_1660}
125 model: BW
126 rho:
127 J: 1
128 P: -1
129 mass: {m_rho770}
130 width: {g_rho770}
131 model: BW
132 """
133
134 params = {
135 "Lc->Sigma.pi0Sigma->Lambda.pipLambda->p.pim_total_0r": 1.0,
136 "Lc->Sigma.pi0Sigma->Lambda.pipLambda->p.pim_total_0i": 0.0,
137 "Lc->Sigma.pi0_g_ls_0r": 1.0,
138 "Lc->Sigma.pi0_g_ls_0i": 0.0,
139 "Lc->Sigma.pi0_g_ls_1r": 1.0,
140 "Lc->Sigma.pi0_g_ls_1i": -1.0,
141 "Sigma->Lambda.pip_g_ls_0r": 1.0,
142 "Sigma->Lambda.pip_g_ls_0i": 0.0,
143 "Lambda->p.pim_g_ls_0r": 1.0,
144 "Lambda->p.pim_g_ls_0i": 0.0,
145 "Lambda->p.pim_g_ls_1r": 0.435376,
146 "Lambda->p.pim_g_ls_1i": 0.0,
147 "Lc->rho.Lambdarho->pip.pi0Lambda->p.pim_total_0r": 2.0,
148 "Lc->rho.Lambdarho->pip.pi0Lambda->p.pim_total_0i": 1.0,
149 "Lc->rho.Lambda_g_ls_0r": 1.0,
150 "Lc->rho.Lambda_g_ls_0i": 0.0,
151 "Lc->rho.Lambda_g_ls_1r": 1.0,
152 "Lc->rho.Lambda_g_ls_1i": 0.0,
153 "Lc->rho.Lambda_g_ls_2r": 1.0,
154 "Lc->rho.Lambda_g_ls_2i": 0.0,
155 "Lc->rho.Lambda_g_ls_3r": 1.0,
156 "Lc->rho.Lambda_g_ls_3i": 0.0,
157 "rho->pip.pi0_g_ls_0r": 1.0,
158 "rho->pip.pi0_g_ls_0i": 0.0,
159 }
Here are some basic functions for momentum and angles
166 def M(p):
167 return math.sqrt(p[0] * p[0] - p[1] * p[1] - p[2] * p[2] - p[3] * p[3])
168
169
170 def dot(p1, p2):
171 return p1[0] * p2[0] + p1[1] * p2[1] + p1[2] * p2[2]
172
173
174 def boost(p, v):
175 E, px, py, pz = p
176 vx, vy, vz = v
177 beta2 = vx * vx + vy * vy + vz * vz
178 gamma = 1.0 / math.sqrt(1 - beta2)
179 bp = dot([px, py, pz], [vx, vy, vz])
180 gamma2 = 1 / (math.sqrt(1 - beta2) + 1 - beta2) # (gamma - 1) / beta2
181 r = gamma2 * bp + gamma * E
182 px_prime = px + r * vx
183 py_prime = py + r * vy
184 pz_prime = pz + r * vz
185 E_prime = gamma * (E + bp)
186 return [E_prime, px_prime, py_prime, pz_prime]
187
188
189 def restframe(base, other):
190 E, px, py, pz = base
191 p = -px / E, -py / E, -pz / E
192 return boost(other, p)
193
194
195 def add(*args): # (E1+E2, x1+x2, y1+y2, z1+z2)
196 return [sum(i) for i in zip(*args)]
197
198
199 def unit(p):
200 n = math.sqrt(dot(p, p))
201 return [i / n for i in p]
202
203
204 def cross_unit(p1, p2): # p1 x p2 = (y1z2 - y2z1, z1x2 - z2x1, x1y2 - x2y1)
205 px = p1[1] * p2[2] - p2[1] * p1[2]
206 py = p1[2] * p2[0] - p2[2] * p1[0]
207 pz = p1[0] * p2[1] - p2[0] * p1[1]
208 return unit([px, py, pz])
209
210
211 def angle_phi(xr, x, y): # arg(xr.x +i xr.y)
212 costheta = dot(xr, x)
213 sintheta = dot(xr, y)
214 return math.atan2(sintheta, costheta)
215
216
217 def angle_theta(p1, p2):
218 costheta = dot(p1, p2)
219 return math.acos(costheta)
220
221
222 def angle_zx_p_getzx(z0, x0, p):
223 z1 = unit(p[1:])
224 y1 = cross_unit(z0, z1)
225 y0 = cross_unit(z0, x0)
226 x1 = cross_unit(y1, z1)
227 phi = angle_phi(y1, y0, [-i for i in x0])
228 theta = angle_theta(z0, z1)
229 return phi, theta, z1, x1
230
231
232 def angle_zx_zx(z0, x0, z1, x1):
233 yr = cross_unit(z0, z1)
234 y0 = cross_unit(z0, x0)
235 y1 = cross_unit(z1, x1)
236 phi = angle_phi(yr, y0, [-i for i in x0])
237 theta = angle_theta(z0, z1)
238 psi = -angle_phi(yr, y1, [-i for i in x1])
239 return phi, theta, psi
1. Calculate the angle
Before calculate the amplitude, we calculate the angle in the data based on the 4-momenta and decay structure.
1.1 First Decay chain
The first decay chain is \(\Lambda_c^{+} \rightarrow \Sigma^{+} \pi^{0},\Sigma^{+} \rightarrow \Lambda \pi^{+}, \Lambda \rightarrow p \pi^{-}\).
Firstly we boost all the momentum into the rest frame of \(\Lambda_c^{+}\).
[[1.013485155460205,
0.037149042316438785,
0.2610250084944836,
-0.2779991771813273],
[0.19917831654329266,
0.12295058891840963,
0.02355637857348515,
-0.06723360565511058],
[0.7440749913533434,
-0.054155650528414465,
-0.4710601491012403,
0.556180906214235],
[0.32972155378779994,
-0.10594398070643395,
0.18647876203327152,
-0.2109481233777971]]
Then we choose the initial coordinate system as \(\vec{x}_{0}=(1,0,0)\), \(\vec{z}_{0}=(0,0,1)\), \(\vec{y}_{0} = \vec{z}_{0}\times \vec{x}_{0}=(0,1,0)\), all the angle will be calculated based on it.
In the first decay \(\Lambda_c^{+} \rightarrow \Sigma^{+} \pi^{0}\), we choose the direction of \(\Sigma^{+}\) as the \(z\)-axis of new coordinate system (\(\vec{z}_1 = \frac{\vec{p}_{\Sigma}}{|\vec{p}_{\Sigma}|}\)). In the convention we used, , the third Euler angle is zero in the formula. We have to choose \(\vec{y} = \frac{\vec{z}_{0} \times \vec{z}_{1}}{|\vec{z}_{0} \times \vec{z}_{1}|}\), which is the rotation axis of second rotaion that rotate \(\vec{z}_{0}\) to \(\vec{z}_{1}\). The angle can be calulated by the rotation of axis.
272 p1_sigma = add(p1_p, p1_pim, p1_pip)
273 z1 = unit(p1_sigma[1:]) # using p1 as z axis
274 y1 = cross_unit(z0, z1) # the rotation axis is z0 x z1
275 x1 = cross_unit(y1, z1) # the x-axis of new coordinate system
276 xr = cross_unit(y1, z0) # the x-axis after the first rotation
277
278 phi1_test = angle_phi(
279 xr, x0, y0
280 ) # the angle is calculate based on new x from axis (x, y)
281 # or without xr
282 phi1 = angle_phi(
283 y1, y0, [-i for i in x0]
284 ) # the angle is calculate based on new y from axis (y, -x)
285
286 theta1 = angle_theta(z0, z1) # theta is arccos( z0 . z1 )
287
288 assert phi1_test == phi1
289 print(phi1, theta1)
-1.0541411652888346 0.7936824390985183
In the second decay \(\Sigma^{+} \rightarrow \Lambda \pi^{+}\), the initial coordinate system inherits from the above decay that produce \(\Sigma^{+}\). We choose the direction of \(\Lambda^{+}\) as the \(z\)-axis of new coordinate system (\(\vec{z}_2 = \frac{\vec{p}_{\Lambda}}{|\vec{p}_{\Lambda}|}\)). And also \(\vec{y} = \frac{\vec{z}_{1} \times \vec{z}_{2}}{|\vec{z}_{1} \times \vec{z}_{2}|}\). The angle calulation is similar, we can use a common function angle_zx_p_getzx.
1.141488741005533 2.635475098581215
In the last decay \(\Lambda^{+} \rightarrow p \pi^{-}\), the initial coordinate system inherits from the decay that produce \(\Lambda^{+}\). We choose the direction of \(p\) as the \(z\)-axis of new coordinate system (\(\vec{z}_3 = \frac{\vec{p}_{p}}{|\vec{p}_{p}|}\)). And also \(\vec{y} = \frac{\vec{z}_{3} \times \vec{z}_{3}}{|\vec{z}_{3} \times \vec{z}_{3}|}\).
0.2005695899392871 1.6849581714082897
1.2 Second decay Chain
In the second decay chain \(\Lambda_c^{+} \rightarrow \rho \Lambda, \rho\rightarrow \pi^{+}\pi^{0}, \Lambda\rightarrow p \pi^{-}\), the procedure is similar. In the first decay \(\Lambda_c^{+} \rightarrow \rho \Lambda\), we choose the direction of \(\rho\) as the \(z\)-axis of new coordinate system (\(\vec{z}_1' = \frac{\vec{p}_{\rho}}{|\vec{p}_{\rho}|}\)), and also \(\vec{y} = \frac{\vec{z}_{0} \times \vec{z}_{1}}{|\vec{z}_{0} \times \vec{z}_{1}|}\).
-2.083246114791286 0.7575560832474785
In the second decay \(\rho^{+} \rightarrow \pi^{+} \pi^{0}\), the initial coordinate system inherits from the above decay that produce \(\rho^{+}\). We choose the direction of \(\pi^{+}\) as the \(z\)-axis of new coordinate system (\(\vec{z}_2' = \frac{\vec{p}_{\pi^{+}} }{|\vec{p}_{\pi^{+}}|}\)). And also \(\vec{y}_1' = \frac{\vec{z}_{1}' \times \vec{z}_{2}'}{|\vec{z}_{1}' \times \vec{z}_{2}'|}\).
1.9089059699896964 0.43577968070080797
There are some differences of \(\Lambda \rightarrow p \pi^{-}\). Firstly the initial coordinate system inherits from the decay that produce \(\Lambda\), which is the first decay, no the second decay. And then the direction of \(\Lambda\) is the opposite of \(\rho^{+}\). We need to consider the transform to the opposite aixs. Here we simplely choose \((\vec{x}_{1}', -\vec{y}_{1}',-\vec{z}_{1}')\) as the opposite of \((\vec{x}_{1}', \vec{y}_{1}',\vec{z}_{1}')\). It means a \(\pi\) rotation around x-axis. Then we can calculate the angle using the same procedure.
1.4406467063875559 1.8593100836742338
1.3 Alignment angle
From the above processes, we can see that the final coordinate system of particle \(p\) (and also other final particles) is not the same.
x
[-0.06395677311665698, -0.6890741879517143, 0.7218630719680776]
[-0.034929150029978914, -0.6644561028949505, 0.7465105771546967]
z
[-0.9686396455654857, 0.21689353360891328, 0.12122059279433339]
[-0.9694191132638728, 0.20408496607719684, 0.13629346814853677]
We need to add additonal rotation to align them. In addtion, we also need to consider the effect of boost sequence in it. The sequence boost will introduce an additional rotation. In TFPWA, we record all the boost and rotation in the decay chain, and get a total Lorentz transform for a particle. The Lorentz transform using the following 2-D matrix form.
Here, \(\omega=\tanh^{-1}(|p|/E)\). Base on the 2-D matrix form, we can solve the angle from \(L=R_z(\gamma)R_y(\beta)R_z(\alpha)B_z(\omega)\) as
Here is some code for this form.
397 class LorentzGroup:
398 def __init__(self, x):
399 self.x = x
400
401 def __mul__(self, other): # matrix multiply
402 x, y = self.x, other.x
403 aa = x[0][0] * y[0][0] + x[0][1] * y[1][0]
404 ab = x[0][0] * y[0][1] + x[0][1] * y[1][1]
405 ba = x[1][0] * y[0][0] + x[1][1] * y[1][0]
406 bb = x[1][0] * y[0][1] + x[1][1] * y[1][1]
407 return LorentzGroup([[aa, ab], [ba, bb]])
408
409 def inv(self): # matrix inverse, it has det(M) =1
410 aa, ab = self.x[0]
411 ba, bb = self.x[1]
412 return LorentzGroup([[bb, -ab], [-ba, aa]])
413
414 def get_euler_angle(self): # solve euler angle from the matrix
415 x = self.x
416 cosbeta = (x[0][0] * x[1][1] + x[0][1] * x[1][0]).real
417 cosbeta = min(
418 1.0, cosbeta
419 ) # due to the pricision it could be 1 + epsilon
420 beta = math.acos(cosbeta)
421 alpha_p_gamma = math.atan2(x[1][1].imag, x[1][1].real)
422 alpha_m_gamma = math.atan2(x[1][0].imag, x[1][0].real)
423 alpha = alpha_p_gamma + alpha_m_gamma
424 gamma = alpha_p_gamma - alpha_m_gamma
425 return alpha, beta, gamma
426
427 def __repr__(self):
428 return str(self.x)
429
430
431 def Bz(omega):
432 a = math.exp(omega / 2)
433 return LorentzGroup([[1 / a, 0.0], [0.0, a]])
434
435
436 def Bz_from_p(p4):
437 E, px, py, pz = p4
438 p = math.sqrt(px * px + py * py + pz * pz)
439 omega = math.atanh(p / E)
440 return Bz(omega)
441
442
443 def Rz(alpha):
444 a = cmath.exp(1j * alpha / 2)
445 return LorentzGroup([[1 / a, 0.0], [0.0, a]])
446
447
448 def Ry(beta):
449 s = math.sin(beta / 2)
450 c = math.cos(beta / 2)
451 return LorentzGroup([[c, -s], [s, c]])
For the first decay chain, \(\Lambda_c^{+} \rightarrow \Sigma^{+} \pi^{0},\Sigma^{+} \rightarrow \Lambda \pi^{+}, \Lambda \rightarrow p \pi^{-}\), the total Lorentz transform of \(p\) is
we can remove the first \(B_z(\omega_{1})\), since it is same for all decay chains.
For the second decay chain, \(\Lambda_c^{+} \rightarrow \rho \Lambda, \rho\rightarrow \pi^{+}\pi^{0}, \Lambda\rightarrow p \pi^{-}\), the total Lorentz transform of \(p\) is
There is an additional retation \({\color{ead}R_{x}(\pi)}\), since \(\Lambda\) is in the opposite direction of \(\rho\). Here we choose \(R_{x}(\pi) R_y(\theta_1') R_z(\phi_1') = R_y(\pi-\theta_1') R_z(\phi_1'{\color{red}-\pi})\), so that
The \({\color{red}-\pi}\) can also be \({\color{red}+\pi}\). But for baryon, rotation of \(-\pi\) and \(+\pi\) have different factor \(i\) and \(-i\), we need to choose one of them in the conversion.
The relative Lorentz transform between the two coordinate systems is
We can solve the angle form it
(-4.230335631198603, 0.0, -2.016038195610422)
0.036811480370561256
To inclue the effect \({\color{red}-\pi}\), the range of \(\alpha\) and \(\gamma\) is \((-2\pi,2\pi)\). Here is the same rest frame of \(p\), \(\beta\) is always zero. But it has a non-zero phase \(\alpha + \gamma\). If we do not consider the effect of Lorentz boost, we can use the coordinate system to calculate the angle directly. The value would be a little different, and do not have the property that \(\beta=0\).
(0.061965116196543796, 0.019795740458797503, -0.021156236313810133)
For \(\pi^{\pm,0}\), we can also calculate the angle for alignment. Each particle require independent alignment angles. It could have no-zere \(\beta\). But their spins is 0, no effect will appear. We can skip those steps.
2. Calculate the amplitude
2.1 First decay chain
The total amplitude of decay chain include \(\Sigma(1660)^{+}\) is expanded by the three decays in the decay chain The first one is \(\Lambda_c^{+}\rightarrow \Sigma(1660)^{+} \pi^0\). We start from the LS amplitude \(G_{ls} = g_{ls} q^{l}B_l'(q,q0,d)\). \(g_{ls}\) is the fit parameters.
\(q\) is the momentum in the restframe
\(q\) is the value in data. And \(q_0\) is the value in model, as a normalize factor.
and \(B_l\) is the Blatt-Weisskopf barrier factors.
For this process, we add barrier_factor_norm: True option in config, it becomes \(G_{ls} = g_{ls}\left(\frac{q}{q_0}\right)^{l}B_l'(q,q0,d)\).
Next, we calculate the helicity amplitude, it is
\(\delta=\lambda_{1}-\lambda_{2}\). \(l,s\) is all possible in the range
For the first decay, \(\Lambda_c^{+}\rightarrow \Sigma(1665)^{+} \pi^0\). \(s\) in range \([|\frac{1}{2}-0|, \frac{1}{2}+0]\), so it is only \(\frac{1}{2}\). And \(l\) in range \([|\frac{1}{2}-\frac{1}{2}|, \frac{1}{2}+ \frac{1}{2}]\), could be \(0\) or \(1\). All possible \((l,s)\) is \((0, \frac{1}{2})\) and \((1, \frac{1}{2})\).
For \((l,s)=(0, \frac{1}{2})\), we have the following Clebsch–Gordan coefficients,
For \((l,s)=(1, \frac{1}{2})\), we have the following Clebsch–Gordan coefficients
Combine with the fractor \(\sqrt{\frac{2l+1}{2J_0 + 1}}\), we can get that
The amplitude of this decay is also related to function
The small d matrix \(d^{J}_{m,n}(\beta)\) is \(d^{0}_{m,n}(\beta)=1\) and
here \(m,n = [-J, -J+1,\cdots, J]\). And we use the complex conjugation version.
658 def small_d_matrix(beta, j):
659 if j == 0:
660 return [[1.0]]
661 if j == 1:
662 return [
663 [math.cos(beta / 2), math.sin(beta / 2)],
664 [-math.sin(beta / 2), math.cos(beta / 2)],
665 ]
666 if j == 2:
667 c = math.cos(beta)
668 s = math.sin(beta)
669 k = 1 / math.sqrt(2)
670 return [
671 [(1 + c) / 2, k * s, (1 - c) / 2],
672 [-k * s, c, k * s],
673 [(1 - c) / 2, -k * s, (1 + c) / 2],
674 ]
675
676
677 def D_matrix_conj(alpha, beta, gamma, j):
678 d = small_d_matrix(beta, j)
679 ret = []
680 for i in range(int(j + 1)):
681 tmp = []
682 for k in range(int(j + 1)):
683 tmp.append(
684 cmath.exp(1.0j * (i - j / 2) * alpha)
685 * d[i][k]
686 * cmath.exp(1.0j * (k - j / 2) * gamma)
687 )
688 ret.append(tmp)
689 return ret
690
691
692 j0 = 1 / 2 # spin of Lc+
693 Dm = D_matrix_conj(phi1, theta1, 0.0, 2 * j0)
With helicity amplitude and D-matrix we can calculate the amplitude of this decay as
704 def sum_decay_amplitude(H, D, j0, l0, l1, l2):
705 ret = {}
706 for i in l0:
707 for j in l1:
708 for k in l2:
709 if abs(j - k) <= j0:
710 idx1 = l0.index(i)
711 idx2 = l0.index(j - k)
712 ret[(i, j, k)] = H[(j, k)] * Dm[idx1][idx2]
713 else:
714 ret[(i, j, k)] = 0.0j
715 return ret
716
717
718 A1 = sum_decay_amplitude(H1, Dm, 1 / 2, [-1 / 2, 1 / 2], [-1 / 2, 1 / 2], [0])
719
720 pprint(A1)
{(-0.5, -0.5, 0): (1.0246845284339865+0.09214359867084504j),
(-0.5, 0.5, 0): (0.043001323998895086+0.23632845496901808j),
(0.5, -0.5, 0): (-0.24569717760383605+0.3542951434609425j),
(0.5, 0.5, 0): (0.5410098258810769+0.18934959397575796j)}
For the second decay, \(\Sigma^{+}\rightarrow \Lambda \pi^{+}\), the procedure is similar. But it is strong decay (as we do not use p_break: True), so we required that \((-1)^{l} = P_0 P_1 P_2 = 1 \times 1 \times -1\), only \(l=1\) remain.
726 q = get_relative_p(M(p_sigma), M(p_lambda), M(p_pip))
727 q0 = get_relative_p(m_sigma_1660, m_l, m_pi)
728
729 gls0 = params["Sigma->Lambda.pip_g_ls_0r"] * cmath.exp(
730 1j * params["Sigma->Lambda.pip_g_ls_0i"]
731 )
732
733 G1 = gls0 * (q / q0) ** 1 * Bprime(1, q, q0)
734
735 H2 = {(-1 / 2, 0): G1 / math.sqrt(2), (1 / 2, 0): -G1 / (math.sqrt(2))}
736
737 j0 = 1 / 2 # Sigma+
738 Dm = D_matrix_conj(phi2, theta2, 0.0, 2 * j0)
739
740 A2 = sum_decay_amplitude(H2, Dm, 1 / 2, [-1 / 2, 1 / 2], [-1 / 2, 1 / 2], [0])
741
742 pprint(A2)
{(-0.5, -0.5, 0): (0.16504850460193102-0.10596431571836415j),
(-0.5, 0.5, 0): (-0.638231980063331+0.4097572116760412j),
(0.5, -0.5, 0): (-0.638231980063331-0.4097572116760412j),
(0.5, 0.5, 0): (-0.16504850460193102-0.10596431571836415j)}
For the decay, \(\Lambda \rightarrow p \pi^{-}\), the process is similar as \(\Lambda_c^{+}\rightarrow \Sigma(1660)^{+} \pi^0\).
749 q = get_relative_p(M(p_lambda), M(p_p), M(p_pim))
750 q0 = get_relative_p(m_l, m_p, m_pi)
751 gls0 = params["Lambda->p.pim_g_ls_0r"] * cmath.exp(
752 1j * params["Lambda->p.pim_g_ls_0i"]
753 )
754 gls1 = params["Lambda->p.pim_g_ls_1r"] * cmath.exp(
755 1j * params["Lambda->p.pim_g_ls_1i"]
756 )
757
758
759 G0 = gls0 * (q / q0) ** 0 * Bprime(0, q, q0)
760 G1 = gls1 * (q / q0) ** 1 * Bprime(1, q, q0)
761
762 H3 = {
763 (-1 / 2, 0): (G0 + G1) / math.sqrt(2),
764 (1 / 2, 0): (G0 - G1) / math.sqrt(2),
765 }
766
767
768 Dm = D_matrix_conj(phi3, theta3, 0.0, 2 * 1 / 2)
769
770 A3 = sum_decay_amplitude(H3, Dm, 1 / 2, [-1 / 2, 1 / 2], [-1 / 2, 1 / 2], [0])
771
772 pprint(A3)
{(-0.5, -0.5, 0): (0.6721807828658565-0.06763640483927624j),
(-0.5, 0.5, 0): (0.2964610424603069-0.029830604501111965j),
(0.5, -0.5, 0): (-0.7536574536506793-0.07583477829866517j),
(0.5, 0.5, 0): (0.264411125564959+0.02660566679171078j)}
Then the total amplitude of the decay chain is
\[A_{ \lambda_{\Lambda_c^{+}},\lambda_{p},\lambda_{\pi^{-}},\lambda_{\pi^{+}},\lambda_{\pi^{0}} } = a_{total} \sum_{\lambda_{\Sigma^{+}},\lambda_{\Lambda}} A_{\lambda_{\Lambda_c^{+}},\lambda_{\Sigma^{+}},\lambda_{\pi^{0}} } R_{\Sigma^{+}}(m_{\Sigma^{+}}) A_{\lambda_{\Sigma^{+}},\lambda_{\Lambda},\lambda_{\pi^{+}} } R_{\Lambda}(m_{\Lambda}) A_{\lambda_{\Lambda},\lambda_{p},\lambda_{\pi^{-}} }\]
\(a_{total}\) is a factor in fit parameters. The amplitude sum of all possible helicities of intermidiate states. To be simple, we use the simplest BW shape \(\Sigma(1660)^{+}\), as
and we do not consider the shape of \(\Lambda\)
789 def bw(m, m0, g0):
790 return 1 / (m0 * m0 - m * m - 1.0j * m0 * g0)
791
792
793 r_sigma = bw(M(p_sigma), m_sigma_1660, g_sigma_1660)
794 r_lambda = 1.0
795
796 total = params[
797 "Lc->Sigma.pi0Sigma->Lambda.pipLambda->p.pim_total_0r"
798 ] * cmath.exp(
799 1j * params["Lc->Sigma.pi0Sigma->Lambda.pipLambda->p.pim_total_0i"]
800 )
801
802 A = {}
803 for l_lc, l_p, l_pim, l_pip, l_pi0 in itertools.product(
804 [-1 / 2, 1 / 2], [-1 / 2, 1 / 2], [0], [0], [0]
805 ):
806 tmp = 0.0
807 for l_sigma in [-1 / 2, 1 / 2]:
808 for l_l in [-1 / 2, 1 / 2]:
809 tmp = (
810 tmp
811 + A1[(l_lc, l_sigma, l_pi0)]
812 * A2[(l_sigma, l_l, l_pip)]
813 * A3[(l_l, l_p, l_pim)]
814 )
815 A[(l_lc, l_p, l_pim, l_pip, l_pi0)] = total * tmp * r_sigma * r_lambda
816
817 pprint(A)
{(-0.5, -0.5, 0, 0, 0): (-0.3953877755784625+0.5987680982164796j),
(-0.5, 0.5, 0, 0, 0): (0.10669876852931258-0.03549608323128384j),
(0.5, -0.5, 0, 0, 0): (0.08461940080832495-0.21173858458097958j),
(0.5, 0.5, 0, 0, 0): (0.15116503907073653+0.107932131617686j)}
2.1 Second decay chain
For the first decay, \(\Lambda_c^{+}\rightarrow \rho^{+} \Lambda\), \(s\) in range \([|1-\frac{1}{2}|, 1+\frac{1}{2}]\), so it could be \(\frac{1}{2}\) or \(\frac{3}{2}\). when \(s=\frac{1}{2}\), \(l\) in range \([|\frac{1}{2}-\frac{1}{2}|, \frac{1}{2}+ \frac{1}{2}]\), could be \(0\) or \(1\). when \(s=\frac{3}{2}\), \(l\) in range \([|\frac{3}{2}-\frac{1}{2}|, \frac{3}{2}+ \frac{1}{2}]\), could be \(1\) or \(2\). All possible \((l,s)\) is \((0, \frac{1}{2})\), \((1, \frac{1}{2})\), \((1, \frac{3}{2})\) and \((2, \frac{3}{2})\).
we can find the relation as
844 m0, m1, m2 = M(p_total), M(p_rho), M(p_lambda)
845
846 q = get_relative_p(m0, m1, m2)
847 q0 = get_relative_p(m_lc, m_rho770, m_l)
848
849 gls01 = params["Lc->rho.Lambda_g_ls_0r"] * cmath.exp(
850 1j * params["Lc->rho.Lambda_g_ls_0i"]
851 )
852 gls11 = params["Lc->rho.Lambda_g_ls_1r"] * cmath.exp(
853 1j * params["Lc->rho.Lambda_g_ls_1i"]
854 )
855 gls13 = params["Lc->rho.Lambda_g_ls_2r"] * cmath.exp(
856 1j * params["Lc->rho.Lambda_g_ls_2i"]
857 )
858 gls23 = params["Lc->rho.Lambda_g_ls_3r"] * cmath.exp(
859 1j * params["Lc->rho.Lambda_g_ls_3i"]
860 )
861
862
863 G01 = gls01 * (q / q0) ** 0 * Bprime(0, q, q0)
864 G11 = gls11 * (q / q0) ** 1 * Bprime(1, q, q0)
865 G13 = gls13 * (q / q0) ** 1 * Bprime(1, q, q0)
866 G23 = gls23 * (q / q0) ** 2 * Bprime(2, q, q0)
867
868
869 H1_prime = {
870 (-1, -1 / 2): 1
871 / math.sqrt(6)
872 * (math.sqrt(2) * (-G01 - G11) + (-G13 - G23)),
873 (0, -1 / 2): 1
874 / math.sqrt(6)
875 * ((-G01 + G11) + math.sqrt(2) * (-G13 + G23)),
876 (0, 1 / 2): 1 / math.sqrt(6) * ((G01 + G11) + math.sqrt(2) * (-G13 - G23)),
877 (1, 1 / 2): 1 / math.sqrt(6) * (math.sqrt(2) * (G01 - G11) + (-G13 + G23)),
878 }
879
880 Dm = D_matrix_conj(phi1_2, theta1_2, 0, 2 * 1 / 2)
881
882 A1_prime = sum_decay_amplitude(
883 H1_prime, Dm, 1 / 2, [-1 / 2, 1 / 2], [-1, 0, 1], [-1 / 2, 1 / 2]
884 )
885 pprint(A1_prime)
{(-0.5, -1, -0.5): (-0.8386137946350432-1.4340009423866682j),
(-0.5, -1, 0.5): 0j,
(-0.5, 0, -0.5): (-0.02632096486978926-0.04500795082226156j),
(-0.5, 0, 0.5): (-0.08050457224207319-0.1376600685561207j),
(-0.5, 1, -0.5): 0j,
(-0.5, 1, 0.5): (-0.00639040603033944-0.01092737602024329j),
(0.5, -1, -0.5): (0.33376536678723034-0.5707273760232039j),
(0.5, -1, 0.5): 0j,
(0.5, 0, -0.5): (-0.06613365682719523+0.11308629409673149j),
(0.5, 0, 0.5): (0.03204053910670293-0.054788227390874515j),
(0.5, 1, -0.5): 0j,
(0.5, 1, 0.5): (-0.016056437197026326+0.027455959130660786j)}
For the second decay, \(\rho^{+}\rightarrow \pi^{+} \pi^{0}\), \(s\) in range \([|0-0|, 0+0]\), so it is only \(0\). \(l\) in range \([|1-0|, 1+0]\), so it is only \(1\) . All possible \((l,s)\) is \((1, 0)\). It also satisfies the requirement that \((-1)^l = P_0 P_1 P_2 = -1\). we can find the relation as
898 m0, m1, m2 = M(p_rho), M(p_pip), M(p_pi0)
899
900 q = get_relative_p(m0, m1, m2)
901 q0 = get_relative_p(m_rho770, m_pi, m_pi0)
902
903 gls = params["rho->pip.pi0_g_ls_0r"] * cmath.exp(
904 1j * params["rho->pip.pi0_g_ls_0i"]
905 )
906
907 G = gls * (q / q0) ** 1 * Bprime(1, q, q0)
908
909 H2_prime = {(0, 0): G}
910
911 Dm = D_matrix_conj(phi2_2, theta2_2, 0.0, 2 * 1)
912
913 A2_prime = sum_decay_amplitude(H2_prime, Dm, 1, [-1, 0, 1], [0], [0])
914
915 pprint(A2_prime)
{(-1, 0, 0): (-0.10904456128821746-0.3101280597575634j),
(0, 0, 0): (0.9984404935477759+0j),
(1, 0, 0): (0.10904456128821746-0.3101280597575634j)}
For the last decay, \(\Lambda \rightarrow p \pi^{-}\), the process is similar as the deacy chain of \(\Sigma^{+}\), but it has different angles.
{(-0.5, -0.5, 0): (0.45626222979386544-0.4004340537172614j),
(-0.5, 0.5, 0): (0.24048250582071312-0.21105710349370635j),
(0.5, -0.5, 0): (-0.6113499145798885-0.536545233309202j),
(0.5, 0.5, 0): (0.17947673127193456+0.1575159861109122j)}
The total amplitude of this decay chain is
935 r_rho = bw(M(p_rho), m_rho770, g_rho770)
936
937 total = params["Lc->rho.Lambdarho->pip.pi0Lambda->p.pim_total_0r"] * cmath.exp(
938 1j * params["Lc->rho.Lambdarho->pip.pi0Lambda->p.pim_total_0i"]
939 )
940
941
942 A_prime = {}
943 for l_lc, l_p, l_pim, l_pip, l_pi0 in itertools.product(
944 [-1 / 2, 1 / 2], [-1 / 2, 1 / 2], [0], [0], [0]
945 ):
946 tmp = 0.0
947 for l_rho in [-1, 0, 1]:
948 for l_l in [-1 / 2, 1 / 2]:
949 tmp = (
950 tmp
951 + A1_prime[(l_lc, l_rho, l_l)]
952 * A2_prime[(l_rho, l_pip, l_pi0)]
953 * A3_prime[(l_l, l_p, l_pim)]
954 )
955 A_prime[(l_lc, l_p, l_pim, l_pip, l_pi0)] = total * tmp * r_rho * r_lambda
956
957 pprint(A_prime)
{(-0.5, -0.5, 0, 0, 0): (1.8045559263449882-1.8920214364097845j),
(-0.5, 0.5, 0, 0, 0): (0.4955793141170991-0.5776277297411841j),
(0.5, -0.5, 0, 0, 0): (1.2127312641251653-0.17286687566831907j),
(0.5, 0.5, 0, 0, 0): (0.4339860510630706-0.20365827206528628j)}
2.3 Total amplitude
Before sum of all decay chain, we align the coordinate system of all the finnale particles. For \(\pi^{\pm,0}\), \(J=0\) so \(D^{J}(\alpha,\beta,\gamma)=1\), we can remove them. But we need to align \(p\) in the decay chain of \(\rho(770)^{+}\).
971 Dm = D_matrix_conj(ang[0], ang[1], ang[2], 2 * 1 / 2)
972
973
974 A_prime_aligned = {}
975 for l_lc, l_p, l_pim, l_pip, l_pi0 in itertools.product(
976 [-1 / 2, 1 / 2], [-1 / 2, 1 / 2], [0], [0], [0]
977 ):
978 tmp = 0.0
979 for l_p_a in [-1 / 2, 1 / 2]:
980 idx1 = [-1 / 2, 1 / 2].index(l_p_a)
981 idx2 = [-1 / 2, 1 / 2].index(l_p)
982 tmp = (
983 tmp + A_prime[(l_lc, l_p_a, l_pim, l_pip, l_pi0)] * Dm[idx1][idx2]
984 )
985 A_prime_aligned[(l_lc, l_p, l_pim, l_pip, l_pi0)] = tmp
986
987 pprint(A_prime_aligned)
{(-0.5, -0.5, 0, 0, 0): (-1.7694281803357732+1.9249132764295112j),
(-0.5, 0.5, 0, 0, 0): (-0.5061264381134051+0.5684089015747082j),
(0.5, -0.5, 0, 0, 0): (-1.2093442875118885+0.1951575516148681j),
(0.5, 0.5, 0, 0, 0): (-0.4376608117346166+0.19563639275383493j)}
And then we can sum over all decay chains to get the total amplutude of the process
{(-0.5, -0.5, 0, 0, 0): (-2.1648159559142357+2.5236813746459905j),
(-0.5, 0.5, 0, 0, 0): (-0.3994276695840925+0.5329128183434244j),
(0.5, -0.5, 0, 0, 0): (-1.1247248867035635-0.016581032966111464j),
(0.5, 0.5, 0, 0, 0): (-0.28649577266388004+0.30356852437152093j)}
2.4 Prbability density
If no polarization in the process, the probability density function (not normalized) is
\[P \propto \sum_{\lambda_{\Lambda_c^+},\lambda_{p},\lambda_{\pi^-},\lambda_{\pi^+},\lambda_{\pi^0}}|A_{\lambda_{\Lambda_c^+},\lambda_{p},\lambda_{\pi^-},\lambda_{\pi^+},\lambda_{\pi^0}}|^2\]
prob 12.938449017067997
3. Validation
we can quackly check the results with
1025 import tensorflow as tf
1026 import yaml
1027
1028 from tf_pwa.config_loader import ConfigLoader
1029
1030 config = ConfigLoader(yaml.full_load(config_str))
1031
1032 config.set_params(params)
1033
1034 angle = config.data.cal_angle(
1035 tf.unstack(
1036 tf.cast(tf.stack([[p_p], [p_pim], [p_pip], [p_pi0]]), dtype=tf.float64)
1037 )
1038 )
1039
1040 amp = config.get_amplitude()
1041
1042 prob2 = amp(angle)
1043
1044 print("prob ", prob2)
1045
1046 assert abs(prob2 - prob) / prob < 1e-6
prob tf.Tensor([12.93845315], shape=(1,), dtype=float64)
We can get the same prob values, (would be some difference due to the precision).
The following code is used for an icon in Sphinx-Gallery.
1056 import matplotlib.pyplot as plt
1057
1058 plt.axis("off")
1059 plt.text(
1060 0, 0, "$P\\propto \\sum_{\\lambda}|A_{\\lambda}(p^{\mu})|^2$", fontsize=60
1061 )
1062 plt.tight_layout()

Total running time of the script: (0 minutes 0.399 seconds)