4
# Author: Stephen Mrenna
5
# Add masses to charged leptons, fix kinematics
6
# Insert W/Z when missing
9
from xml.dom import minidom
11
#tolerance for energy momentum conservation
13
#lepton masses from PDGLive
15
massDict[11]=0.000510998910
16
massDict[-11]=massDict[11]
17
massDict[13]=105.6583668e-3
18
massDict[-13]=massDict[13]
20
massDict[-15]=massDict[15]
22
#print out messages if true
25
#default is NOT to insert missing mothers
28
#useful class to describe 4 momentum
30
def __init__(self,px,py,pz,E,m):
36
def __add__(self,other):
37
t=Momentum(self.px+other.px,self.py+other.py,self.pz+other.pz,self.E+other.E,0)
40
def __sub__(self,other):
41
t=Momentum(self.px-other.px,self.py-other.py,self.pz-other.pz,self.E-other.E,0)
45
tempMass2=self.E**2-self.px**2-self.py**2-self.pz**2
47
t=math.sqrt(tempMass2)
54
def boost(self,ref,rdir):
59
DB=math.sqrt(DBX**2+DBY**2+DBZ**2)
60
DGA=1.0/math.sqrt(1.0-DB**2)
61
DBP=DBX*self.px+DBY*self.py+DBZ*self.pz
62
DGABP=DGA*(DGA*DBP/(1.0+DGA)+self.E)
63
self.px = self.px+DGABP*DBX
64
self.py = self.py+DGABP*DBY
65
self.pz = self.pz+DGABP*DBZ
66
self.E = DGA*(self.E+DBP)
67
def reScale(self,pi,po):
68
self.px = self.px/pi*po
69
self.py = self.py/pi*po
70
self.pz = self.pz/pi*po
72
li = [self.px,self.py, self.pz, self.E, self.m]
73
print "| %18.10E %18.10E %18.10E %18.10E %18.10E |" % tuple(li)
75
#useful class to describe a particle
77
def __init__(self,i,l):
85
self.mom = Momentum(l[6],l[7],l[8],l[9],l[10])
89
li = [self.no, self.id, self.status,self.mo1, self.mo2, self.co1, self.co2, self.mom.px,self.mom.py, self.mom.pz, self.mom.E, self.mom.m, self.life, self.polar]
90
print "%2i | %9i | %4i | %4i %4i | %4i %4i | %18.10E %18.10E %18.10E %18.10E %18.10E | %1.0f. %2.0f" % tuple(li)
92
li = [self.id, self.status,self.mo1, self.mo2, self.co1, self.co2, self.mom.px,self.mom.py, self.mom.pz, self.mom.E, self.mom.m, self.life, self.polar]
93
return "%9i %4i %4i %4i %4i %4i %18.10E %18.10E %18.10E %18.10E %18.10E %1.0f. %2.0f\n" % tuple(li)
95
#useful function for converting a string to variables
96
def parseStringToVars(input):
97
if input.find(".")>-1 :
102
#main part of analysis
104
print "Usage: addmasses.py <infile> <outfile> "
105
print " Last modified: Fri Nov 21 10:49:14 CST 2008 "
108
print "Running addmasses.py to add masses and correct kinematics of fixed particles"
110
#first print out leading information
112
f=open(sys.argv[1],'r')
114
print "need a file for reading"
118
g=open(sys.argv[2],'w')
120
print "need a file for writing"
127
print "Problem reading from file ",sys.argv[1]
129
if line.find("<event>")==-1:
136
#let xml find the event tags
138
xmldoc = minidom.parse(sys.argv[1])
140
print " could not open file for xml parsing ",sys.argv[1]
144
reflist = xmldoc.getElementsByTagName('event')
148
slines = lines.split("\n")
157
while counter<nlines:
159
if s.find("<event>")>-1:
161
elif s.find("</event>")>-1:
172
for l in s.split(): t.append(parseStringToVars(l))
174
event.append(Particle(nup,t))
177
#default is to skip this
182
if p.status == -1: continue
186
if idabs>=11 and idabs<=16:
187
if p.mo1==1 or (pmo.co1 !=0 or pmo.co2 !=0):
188
noMotherList.append(p.no)
189
elif idabs<=5 and abs(pmo.id)==6:
190
if not ( p.co1==pmo.co1 and p.co2==pmo.co2):
191
noMotherList.append(p.no)
194
if len(noMotherList)==0:
196
elif len(noMotherList)%2 != 0:
197
print "single orphan; do not know how to process"
200
while ki<len(noMotherList)-1:
201
l1=event[noMotherList[ki]-1]
203
l2=event[noMotherList[ki]-1]
212
lm=[idMom,2,l1.mo1,l1.mo2,0,0,lMom.px,lMom.py,lMom.pz,lMom.E,lMom.calcMass(),0,0]
215
event.append(Particle(nup,lm))
216
l1.mo1=l1.mo2=l2.mo1=l2.mo2=nup
219
# update number of partons if mothers added
221
s1=event_description.split()[0]
222
mySub = re.compile(s1)
223
event_description = mySub.sub(str(nup),event_description)
226
for ip in range(len(event)):
230
event.insert(ip, event.pop(l.mo1-1))
231
event[ip].no = ip + 1
232
for l2 in event[ip + 1:]:
233
if l2.no > ip and l2.no < nmo + 1:
236
l2.mo1 = l2.mo2 = ip + 1
237
elif l2.mo1 > ip and l2.mo1 < nmo:
238
l2.mo1 = l2.mo2 = l2.mo1 + 1
244
if idabs>=11 and idabs<=16:
248
if p.mo1 in particleDict:
249
l=particleDict[p.mo1]
253
particleDict[p.mo1]=l
256
for k in particleDict:
257
if len(particleDict[k]) != 2: continue
260
p1.mom.boost(event[k-1].mom,-1)
262
p2.mom.boost(event[k-1].mom,-1)
264
if p1.id in massDict: p1.mom.m=massDict[p1.id]
265
if p2.id in massDict: p2.mom.m=massDict[p2.id]
266
p1.mom.E = (rsh*rsh + p1.mom.m**2 - p2.mom.m**2)/(2.0*rsh)
267
pmagOld=math.sqrt(p1.mom.px**2+p1.mom.py**2+p1.mom.pz**2)
268
pmagNew=math.sqrt(p1.mom.E**2-p1.mom.m**2)
269
p1.mom.reScale(pmagOld,pmagNew)
270
p2.mom = Momentum(0,0,0,rsh,rsh) - p1.mom
271
p1.mom.boost(event[k-1].mom,1)
272
p2.mom.boost(event[k-1].mom,1)
274
pSum = Momentum(0,0,0,0,0)
283
if abs(pSum.px)>toler or abs(pSum.py)>toler or abs(pSum.pz)>toler or abs(pSum.E)>toler:
284
print "Event does not pass tolerance ",toler
289
g.write(event_description+"\n")
292
g.write(event_poundSign+"\n")
293
g.write("</event>\n")
295
g.write("</LesHouchesEvents>\n")