FairShip
Loading...
Searching...
No Matches
darkphoton.py
Go to the documentation of this file.
1# SPDX-License-Identifier: LGPL-3.0-or-later
2# SPDX-FileCopyrightText: Copyright CERN for the benefit of the SHiP Collaboration
3
4import math
5import os
6
7import ROOT as r
8
9# from settings import *
10# from functions import *
11from hnl import mass
12
13# constants
14alphaQED = 1.0 / 137.0
15ccm = 2.99792458e10
16hGeV = 6.58211928 * pow(10.0, -16) * pow(10.0, -9) # no units or it messes up!!
17
18# utilities
19# sigma(e+e- -> hadrons) / sigma(e+e- -> mu+mu-)
20
21
23 "dark photon setup"
24
25 def __init__(self, mass, eps) -> None:
26 self.mDarkPhoton = mass
27 self.epsilon = eps
28 self.dataEcm, self.dataR = self.readPDGtable()
30
31 def readPDGtable(self):
32 """Returns R data from PDG in a easy to use format"""
33 ecm = r.vector("double")()
34 ratio = r.vector("double")()
35 """ecm,ratio = [],[]"""
36 with open(os.path.expandvars("$FAIRSHIP/input/rpp2012-hadronicrpp_page1001.dat")) as f:
37 for line in f:
38 line = line.split()
39 try:
40 numEcm = float(line[0])
41 numR = float(line[3])
42 strType = line[7]
43 strBis = line[8]
44 # if numEcm<2:
45 # print numEcm,numR,strType
46 if ("EXCLSUM" in strType) or ("EDWARDS" in strType) or ("BLINOV" in strType):
47 ecm.push_back(numEcm)
48 ratio.push_back(numR)
49 # print numEcm,numR,strType
50 if "BAI" in strType and "01" in strBis:
51 ecm.push_back(numEcm)
52 ratio.push_back(numR)
53 # print numEcm,numR,strType
54 except Exception:
55 continue
56 return ecm, ratio
57
59 """Find the best value for R for the given center-of-mass energy"""
60 fun = r.Math.Interpolator(len(self.dataEcm), r.Math.Interpolation.kLINEAR)
61 fun.SetData(self.dataEcm, self.dataR)
62 return fun
63
64 def Ree_interp(self, s) -> float | int: # s in GeV
65 """Using PDG values for sigma(e+e- -> hadrons) / sigma(e+e- -> mu+mu-)"""
66 # Da http://pdg.lbl.gov/2012/hadronic-xsections/hadron.html#miscplots
67 # ecm = math.sqrt(s)
68 ecm = s
69 if ecm >= 10.29:
70 print(
71 "Warning! Asking for interpolation beyond 10.29 GeV: not implemented, needs extending! Taking value at 10.29 GeV"
72 )
73 result = float(self.PdgR.Eval(10.29))
74 elif ecm >= self.dataEcm[0]:
75 result = float(self.PdgR.Eval(ecm))
76 else:
77 result = 0
78 # print 'Ree_interp for mass %3.3f is %.3e'%(s,result)
79 return result
80
81 def leptonicDecayWidth(self, lepton: str) -> float: # mDarkPhoton in GeV
82 """Dark photon decay width into leptons, in GeV (input short name of lepton family)"""
83 ml = mass(lepton)
84 # print 'lepton %s mass %.3e'%(lepton,ml)
85
86 constant = (1.0 / 3.0) * alphaQED * self.mDarkPhoton * pow(self.epsilon, 2.0)
87 if 2.0 * ml < self.mDarkPhoton:
88 rad = math.sqrt(1.0 - (4.0 * ml * ml) / (self.mDarkPhoton * self.mDarkPhoton))
89 else:
90 rad = 0.0
91
92 par = 1.0 + (2.0 * ml * ml) / (self.mDarkPhoton * self.mDarkPhoton)
93 tdw = math.fabs(constant * rad * par)
94 # print 'Leptonic decay width to %s is %.3e'%(lepton,tdw)
95 return tdw
96
97 def leptonicBranchingRatio(self, lepton: str) -> float:
98 return self.leptonicDecayWidth(lepton) / self.totalDecayWidth()
99
100 def hadronicDecayWidth(self) -> float:
101 """Dark photon decay into hadrons"""
102 """(mumu)*R"""
103 gmumu = self.leptonicDecayWidth("mu-")
104 tdw = gmumu * self.Ree_interp(self.mDarkPhoton)
105 # print 'Hadronic decay width is %.3e'%(tdw)
106 return tdw
107
108 def hadronicBranchingRatio(self) -> float:
109 return self.hadronicDecayWidth() / self.totalDecayWidth()
110
111 def totalDecayWidth(self) -> float: # mDarkPhoton in GeV
112 """Total decay width in GeV"""
113 # return hGeV*c / cTau(mDarkPhoton, epsilon)
114 tdw = (
115 self.leptonicDecayWidth("e-")
116 + self.leptonicDecayWidth("mu-")
117 + self.leptonicDecayWidth("tau-")
118 + self.hadronicDecayWidth()
119 )
120
121 # print 'Total decay width %e'%(tdw)
122
123 return tdw
124
125 def cTau(self) -> float: # decay length in meters, dark photon mass in GeV
126 """Dark Photon lifetime in cm"""
127 ctau = hGeV * ccm / self.totalDecayWidth()
128 # print "ctau dp.py %.3e"%(ctau)
129 return ctau # GeV/MeV conversion
130
131 def lifetime(self) -> float:
132 return self.cTau() / ccm
133
134 def findBranchingRatio(self, decayString) -> float:
135 br = 0.0
136 if decayString == "A -> e- e+":
137 br = self.leptonicBranchingRatio("e-")
138 elif decayString == "A -> mu- mu+":
139 br = self.leptonicBranchingRatio("mu-")
140 elif decayString == "A -> tau- tau+":
141 br = self.leptonicBranchingRatio("tau-")
142 elif decayString == "A -> hadrons":
143 br = self.hadronicBranchingRatio()
144 else:
145 print("findBranchingRatio ERROR: unknown decay %s" % decayString)
146 quit()
147
148 return br
149
150 def allowedChannels(self) -> dict[str, str]:
151 print("Allowed channels for dark photon mass = %3.3f" % self.mDarkPhoton)
152 allowedDecays = {"A -> hadrons": "yes"}
153 if self.mDarkPhoton > 2.0 * mass("e-"):
154 allowedDecays.update({"A -> e- e+": "yes"})
155 print("allowing decay to e")
156 if self.mDarkPhoton > 2.0 * mass("mu-"):
157 allowedDecays.update({"A -> mu- mu+": "yes"})
158 print("allowing decay to mu")
159 if self.mDarkPhoton > 2.0 * mass("tau-"):
160 allowedDecays.update({"A -> tau- tau+": "yes"})
161 print("allowing decay to tau")
162
163 return allowedDecays
164
166 """Very simple patch to take into account A' -> hadrons"""
167 brh = self.hadronicBranchingRatio()
168 # print brh
169 # if M > m(c cbar):
170 if self.mDarkPhoton > 2.0 * mass("c"):
171 visible_frac = 1.0
172 else:
173 visible_frac = 2.0 / 3.0
174
175 increase = brh * visible_frac
176 # print increase
177 return n * (1.0 + increase)
float leptonicBranchingRatio(self, str lepton)
Definition: darkphoton.py:97
float totalDecayWidth(self)
Definition: darkphoton.py:111
None __init__(self, mass, eps)
Definition: darkphoton.py:25
def readPDGtable(self)
Definition: darkphoton.py:31
def scaleNEventsIncludingHadrons(self, n)
Definition: darkphoton.py:165
float hadronicBranchingRatio(self)
Definition: darkphoton.py:108
def interpolatePDGtable(self)
Definition: darkphoton.py:58
float hadronicDecayWidth(self)
Definition: darkphoton.py:100
float leptonicDecayWidth(self, str lepton)
Definition: darkphoton.py:81
dict[str, str] allowedChannels(self)
Definition: darkphoton.py:150
float findBranchingRatio(self, decayString)
Definition: darkphoton.py:134
float|int Ree_interp(self, s)
Definition: darkphoton.py:64
float lifetime(self)
Definition: darkphoton.py:131
int open(const char *, int)
Opens a file descriptor.