SND@LHC Software
Loading...
Searching...
No Matches
runPythia8PP.py
Go to the documentation of this file.
1import ROOT
2import rootUtils as ut
3from array import array
4theSeed = 0
5ROOT.gRandom.SetSeed(theSeed)
6ROOT.gSystem.Load("libpythia8")
7
8# this C++ code is needed to avoid segmentation violation
9# when accessing pythia.generator.info in PyROOT+Pythia8(since at least v8.309)
10# This issue is likely due to broken python binding of Pythia's infoPython() method.
11ROOT.gInterpreter.Declare('''
12const Pythia8::Info& generator_info(Pythia8::Pythia& pythia) {
13 return pythia.info;
14}
15''')
16
17nudict = {12: "nue", -12: "anue", 14: "numu", -14: "anumu", 16: "nutau", -16: "anutau"}
18
19from argparse import ArgumentParser
20parser = ArgumentParser()
21parser.add_argument("-f", "--nuflavour", action='append', type=int, dest='nu_flavour', help="neutrino flavour", default=None)
22parser.add_argument("-b", "--heartbeat", dest="heartbeat", type=int, help="progress report", default=10000)
23parser.add_argument("-n", "--pot", dest="Np", type=int, help="proton collisions", default=1000000)
24parser.add_argument("-Ecm", "--energyCM", dest="eCM", type=float, help="center of mass energy [GeV]", default=13000.)
25parser.add_argument('-C', '--charm', action='store_true', dest='charm',help="ccbar production", default=False)
26parser.add_argument('-B', '--beauty', action='store_true', dest='beauty',help="bbbar production", default=False)
27parser.add_argument('-H', '--hard', action='store_true', dest='hard',help="all hard processes", default=False)
28parser.add_argument('-X', '--PDFpSet',dest="PDFpSet", type=str, help="PDF pSet to use", default="13")
29parser.add_argument('-EtaMin',dest="eta_min", type=float, help="minimum eta for neutrino to pass", default=6.)
30parser.add_argument('-EtaMax',dest="eta_max", type=float, help="maximum eta for neutrino to pass", default=10.)
31
32# for lhapdf, -X LHAPDF6:MMHT2014lo68cl (popular with LHC experiments, features LHC data till 2014)
33# one PDF set, which is popular with IceCube, is HERAPDF15LO_EIG
34# the default PDFpSet '13' is NNPDF2.3 QCD+QED LO
35
36options = parser.parse_args()
37X=ROOT.Pythia8Generator()
38
39nunames=''
40L=len(options.nu_flavour)
41for i in range(0, L):
42 if i==L-1: nunames +=nudict[options.nu_flavour[i]]
43 else: nunames +=nudict[options.nu_flavour[i]]+'_'
44
45# Make pp events
46generator = ROOT.Pythia8.Pythia()
47generator.settings.mode("Next:numberCount",options.heartbeat)
48generator.settings.mode("Beams:idA", 2212)
49generator.settings.mode("Beams:idB", 2212)
50generator.readString("Beams:eCM = "+str(options.eCM));
51# The Monash 2013 tune (#14) is set by default for Pythia above v8.200.
52# This tune provides slightly higher Ds and Bs fractions, in better agreement with the data.
53# Tune setting comes before PDF setting!
54#generator.readString("Tune:pp = 14")
55generator.readString("PDF:pSet = "+options.PDFpSet)
56tag = 'nobias'
57if options.charm:
58 generator.readString("HardQCD:hardccbar = on")
59 tag = 'ccbar'
60elif options.beauty:
61 generator.readString("HardQCD:hardbbbar = on")
62 tag = 'bbbar'
63elif options.hard:
64 generator.readString("HardQCD:all = on")
65 tag = 'hard'
66else:
67 generator.readString("SoftQCD:inelastic = on")
68
69generator.init()
70
71rc = generator.next()
72hname = 'pythia8_'+tag+'_PDFpset'+options.PDFpSet+'_'+nunames
73hname = hname.replace('*','star')
74hname = hname.replace('->','to')
75hname = hname.replace('/','')
76
77fout = ROOT.TFile(hname+".root","RECREATE")
78dTree = ROOT.TTree('NuTree', nunames)
79dAnc = ROOT.TClonesArray("TParticle")
80# AncstrBranch will hold the neutrino at 0th TParticle entry.
81# Neutrino ancestry is followed backwards in evolution up to the colliding TeV proton
82# and saved as 1st, 2nd,... TParticle entries of AncstrBranch branch
83dAncstrBranch = dTree.Branch("Ancstr",dAnc,32000,-1)
84# EvtId will hold event id
85evtId = array('i', [0])
86dEvtId = dTree.Branch("EvtId", evtId, "evtId/I")
87
88timer = ROOT.TStopwatch()
89timer.Start()
90
91nMade = 0
92py = generator
93for n in range(int(options.Np)):
94 rc = py.next()
95 for ii in range(1,py.event.size()):
96 # Ask for final state neutrino
97 if py.event[ii].isFinal() and py.event[ii].id() in options.nu_flavour:
98 evt = py.event[ii]
99 eta = evt.eta()
100 if (eta > options.eta_min and eta < options.eta_max) or (eta < -options.eta_min and eta > -options.eta_max):
101 dAnc.Clear()
102 neut = ROOT.TParticle(evt.id(), evt.status(),
103 evt.mother1(),evt.mother2(),0,0,
104 evt.px(),evt.py(),evt.pz(),evt.e(),
105 evt.xProd(),evt.yProd(),evt.zProd(),evt.tProd())
106 dAnc[0] = neut
107 evtId[0] = n
108 gm = py.event[ii].mother1()
109 # Chain all mothers (gm)
110 while gm:
111 evtM = py.event[gm]
112 anc = ROOT.TParticle(evtM.id(),evtM.status(),
113 evtM.mother1(),evtM.mother2(),evtM.daughter1(),evtM.daughter2(),
114 evtM.px(),evtM.py(),evtM.pz(),evtM.e(),
115 evtM.xProd(),evtM.yProd(),evtM.zProd(),evtM.tProd())
116 nAnc = dAnc.GetEntries()
117 if dAnc.GetSize() == nAnc: dAnc.Expand(nAnc+10)
118 dAnc[nAnc] = anc
119 gm = py.event[gm].mother1()
120 dTree.Fill()
121 nMade+=1
122fout.cd()
123dTree.Write()
124
125generator.stat()
126
127timer.Stop()
128rtime = timer.RealTime()
129ctime = timer.CpuTime()
130totalXsec = 0 # unit = mb,1E12 fb
131info = ROOT.generator_info(generator)
132processes = info.codesHard()
133for p in processes:
134 totalXsec+=info.sigmaGen(p)
135# nobias: 78.4mb, ccbar=4.47mb, bbbar=0.35mb
136
137IntLumi = options.Np / totalXsec * 1E-12
138
139print("Saving to output %s neutrino flavour(s) having PDG ID(s)"%(nunames), options.nu_flavour)
140print("simulated events = %i, equivalent to integrated luminosity of %5.2G fb-1. Real time %6.1Fs, CPU time %6.1Fs"%(options.Np,IntLumi,rtime,ctime))
141# neutrino CC cross section about 0.7 E-38 cm2 GeV-1 nucleon-1, SND@LHC: 59mm tungsten
142# sigma_CC(100 GeV) = 4.8E-12
143print("corresponding to effective luminosity (folded with neutrino CC cross section at 100GeV) of %5.2G fb-1."%(IntLumi/4.8E-12))
144
145
147 generator.settings.listAll()