SND@LHC Software
Loading...
Searching...
No Matches
g4Ex_args.py
Go to the documentation of this file.
1#!/usr/bin/env python
2from __future__ import print_function
3debug = False
4withNtuple = True
5muonNuclear = True
6model = "QGSP_BERT_EMX"
7runnr = 1
8nev = 100
9nevTot = 0
10myEventnr = 0
11mytrack = 1
12scoreLog = 1
13myTimer = {'total':0,'pythia':0,'geant4_conv':0}
14tauOnly = False
15work_dir = "./"
16ecut = 10 # GeV with 1 : ~1sec / event, with 2: 0.4sec / event, 10: 0.13sec
17 # pythia = geant4 conversion = 0.4/100
18# should divide number of events over different ecut values.
19import os
20import shutil
21import argparse
22import logging
23logging.info("")
24logger = logging.getLogger(os.path.splitext(os.path.basename(os.sys.argv[0]))[0])
25logger.setLevel(logging.INFO)
26
27
28def get_work_dir(run_number):
29 import socket
30 host = socket.gethostname()
31 job_base_name = os.path.splitext(os.path.basename(os.sys.argv[0]))[0]
32 out_dir = "{host}_{base}_{runnr}".format(host=host, base=job_base_name, runnr=run_number)
33 return out_dir
34
35
36def init():
37 global runnr, nev, ecut, tauOnly, work_dir
38 logger.info("SHiP proton-on-taget simulator (C) Thomas Ruf, 2014")
39
40 ap = argparse.ArgumentParser(
41 description='Run SHiP "pot" simulation')
42 ap.add_argument('-d', '--debug', action='store_true')
43 ap.add_argument('-f', '--force', action='store_true', help="force overwriting output directory")
44 ap.add_argument('-r', '--run-number', type=int, dest='runnr', default=runnr)
45 ap.add_argument('-e', '--ecut', type=float, help="energy cut", dest='ecut', default=ecut)
46 ap.add_argument('-n', '--num-events', type=int, help="number of events to generate", dest='nev', default=nev)
47 ap.add_argument('-t', '--tau-only', action='store_true', dest='tauOnly')
48 ap.add_argument('-o', '--output', type=str, help="output directory", dest='work_dir', default=None)
49 args = ap.parse_args()
50 if args.debug:
51 logger.setLevel(logging.DEBUG)
52 runnr = args.runnr
53 nev = args.nev
54 ecut = args.ecut
55 tauOnly = args.tauOnly
56 if args.work_dir is None:
57 args.work_dir = get_work_dir(runnr)
58 work_dir = args.work_dir
59 logger.info("params: %s" % args)
60 logger.debug("work_dir: %s" % work_dir)
61 logger.debug("command line arguments: %s", args)
62 if os.path.exists(work_dir):
63 logger.warn("output directory '%s' already exists." % work_dir)
64 if args.force:
65 logger.warn("...cleaning")
66 for root, dirs, files in os.walk(work_dir):
67 for f in files:
68 os.unlink(os.path.join(root, f))
69 for d in dirs:
70 shutil.rmtree(os.path.join(root, d))
71 else:
72 logger.warn("...use '-f' option to overwrite it")
73 else:
74 os.makedirs(work_dir)
75
76init()
77os.chdir(work_dir)
78# ==================================================================
79# ROOT IMPORT #
80# ==================================================================
81import ROOT,time
82from ROOT import TLorentzVector
83# ==================================================================
84# GEANT4 IMPORT #
85# ==================================================================
86from Geant4 import *
87import g4py.NISTmaterials
88import g4py.ezgeom
89from g4py.ezgeom import G4EzVolume
90# ==================================================================
91# PYTHIA8 PART #
92# ==================================================================
93ROOT.gSystem.Load("libEG")
94ROOT.gSystem.Load("libpythia8")
95ROOT.gSystem.Load("libEGPythia8")
96myPythia = ROOT.TPythia8()
97rnr = ROOT.TRandom()
98# Configure myPythia.listAll()
99# myPythia.list(431)
100
101myPythia.ReadString("SoftQCD:inelastic = on")
102myPythia.ReadString("SoftQCD:singleDiffractive = on")
103myPythia.ReadString("SoftQCD:doubleDiffractive = on")
104myPythia.ReadString("SoftQCD:centralDiffractive = on")
105myPythia.ReadString("PhotonCollision:gmgm2mumu = on")
106myPythia.ReadString("PromptPhoton:all = on")
107myPythia.ReadString("WeakBosonExchange:all = on")
108# http://home.thep.lu.se/~torbjorn/pythia81html/ParticleDecays.html
109if tauOnly :
110 myPythia.ReadString("431:new D_s+ D_s- 1 3 0 1.96849 0.00000 0.00000 0.00000 1.49900e-01 0 1 0 1 0")
111 myPythia.ReadString("431:addChannel = 1 0.0640000 0 -15 16")
112
113
114# set random number seed
115myPythia.ReadString("Random:setSeed = On")
116R = int(time.time() % 900000000)
117myPythia.ReadString("Random:seed = "+str(R))
118# Initialize proton (400GeV) on proton at rest
119myPythia.Initialize(2212, 2212, 400., 0.) # required to hack TPythia8 in root !
120# W = 74 protons and 184-74= 110 neutrons
121
122if tauOnly: myPythia.plist(431)
123
124# Open an output file
125h = {}
126if withNtuple:
127 f = ROOT.TFile.Open('pythia8_Geant4_'+str(runnr)+'_'+str(ecut)+'.root', 'RECREATE')
128 h['ntuple'] = ROOT.TNtuple("pythia8-Geant4","muon/nu flux","id:px:py:pz:x:y:z:pythiaid:parentid")
129
130leptons = [12,13,14,15,16] # nu_e, mu, nu_mu, tau, nu_tau
131pionkaons = [211,321]
132rest = [130,310,3122]
133allPart = []
134allPart.extend(leptons)
135allPart.extend(pionkaons)
136allPart.extend(rest)
137notWanted = [22,11,-11,990]
138# ==================================================================
139# Geant4 PART #
140# ==================================================================
141# ------------------------------------------------------------------
142# randum number
143# ------------------------------------------------------------------
144rand_engine = Ranlux64Engine()
145HepRandom.setTheEngine(rand_engine)
146HepRandom.setTheSeed(runnr)
147# ==================================================================
148# user actions in python
149# ==================================================================
150# ------------------------------------------------------------------
151
152
153class MyGeneratorAction(G4VUserPrimaryGeneratorAction):
154 " My Generator Action"
155 def GeneratePrimaries(self,anEvent):
156 global debug,nevTot
157 t_0 = time.time()
158 npart = 0
159 while npart == 0:
160 myPythia.GenerateEvent()
161 nevTot+=1
162 myTimer['pythia']+=time.time()-t_0
163# pythia interaction happens at 0,0,0
164 #x = rnr.Uniform(-3.,3.)
165 #y = rnr.Uniform(-3.,3.)
166 # leave this smearing for later
167 pos = G4ThreeVector(0*cm, 0*cm, -50*m)
168 vertex = G4PrimaryVertex(pos,0.)
169 # create new primaries and set them to the vertex
170 particles = myPythia.GetListOfParticles()
171 for p in particles:
172 if p.GetStatusCode()!=1 : continue
173 pid = p.GetPdgCode()
174 if tauOnly and abs(pid) != 16: continue
175 if pid in notWanted : continue
176 G4particle = G4PrimaryParticle( pid )
177 v = TLorentzVector()
178 p.Momentum(v)
179 if v.E()*GeV < ecut : continue
180 G4particle.Set4Momentum( v.Px()*GeV,v.Py()*GeV,v.Pz()*GeV,v.E()*GeV )
181 vertex.SetPrimary( G4particle )
182# store mother ID
183 mkey = p.GetMother(0)+1
184 mother = myPythia.GetParticle(mkey)
185 curPid = p.GetPdgCode() + 10000 # make it positive
186 moPid = mother.GetPdgCode() + 10000
187 w = curPid + moPid * 100000
188 G4particle.SetWeight(w)
189 npart += 1
190 if tauOnly and debug: myPythia.EventListing()
191 anEvent.AddPrimaryVertex( vertex )
192 myTimer['geant4_conv']+=time.time()-t_0
193class MyRunAction(G4UserRunAction):
194 "My Run Action"
195
196 def EndOfRunAction(self, run):
197 global debug,nevTot
198 print("*** End of Run")
199 print("- Run summary : (id= %d, #events= %d)" \
200 % (run.GetRunID(), nevTot))
201 h['ntuple'].Fill(-1., float(nevTot) )
202 h['ntuple'].Write()
203 print('lepton masses used')
204 for l in leptons:
205 G4particle = G4PrimaryParticle( l )
206 G4def = G4particle.GetParticleDefinition()
207 print(l, G4def.GetParticleName(), G4particle.GetMass())
208
209# ------------------------------------------------------------------
210class MyEventAction(G4UserEventAction):
211 "My Event Action"
212 def EndOfEventAction(self, event):
213 global myEventnr
214 myEventnr += 1
215 # self.myPrintout(event)
216 def myPrintout(self, event):
217 prim = event.GetPrimaryVertex()
218 print('vertex ',prim.GetX0()/m,prim.GetY0()/m,prim.GetZ0()/m)
219 for k in range( prim.GetNumberOfParticle() ):
220 p = prim.GetPrimary(k)
221 print('event',p.GetPDGcode(),p.GetPx()/GeV,p.GetPy()/GeV,p.GetPz()/GeV)
222# ------------------------------------------------------------------
223class MySteppingAction(G4UserSteppingAction):
224 "My Stepping Action"
225
226 def UserSteppingAction(self, step):
227 pass
228
229# ------------------------------------------------------------------
230class MyTrackingAction(G4UserTrackingAction):
231 def PostUserTrackingAction(self,atrack):
232 pass
233 def PreUserTrackingAction(self,atrack):
234 # self.myPrintout(atrack)
235 if atrack.GetTotalEnergy()/GeV < ecut :
236 G4TrackingManager().SetStoreTrajectory(False)
237 atrack.SetTrackStatus(atrack.GetTrackStatus().fStopAndKill)
238 part = atrack.GetDynamicParticle()
239 pid = part.GetPDGcode()
240 if pid in notWanted:
241 G4TrackingManager().SetStoreTrajectory(False)
242 atrack.SetTrackStatus(atrack.GetTrackStatus().fStopAndKill)
243
244 def myPrintout(self, atrack):
245 part = atrack.GetDynamicParticle()
246 pid = part.GetPDGcode()
247 print('TA',pid,atrack.GetTotalEnergy()/GeV,ecut*GeV)
248
249# ------------------------------------------------------------------
250class ScoreSD(G4VSensitiveDetector):
251 "SD for score voxels"
252
253 def __init__(self,Name):
254 G4VSensitiveDetector.__init__(self, Name)
255
256 def ProcessHits(self, step, rohist):
257 preStepPoint = step.GetPreStepPoint()
258 track = step.GetTrack()
259 part = track.GetDynamicParticle()
260 pid = part.GetPDGcode()
261 if abs(pid) in leptons :
262 mom = track.GetMomentum()
263 pos = track.GetPosition()
264#
265 # primPart = part.GetPrimaryParticle()
266 w = track.GetWeight()
267 parentid = int(w)/100000-10000
268 pythiaid = int(w)%100000-10000
269 h['ntuple'].Fill(float(pid), float(mom.x/GeV),float(mom.y/GeV),float(mom.z/GeV),
270 float(pos.x/m),float(pos.y/m),float(pos.z/m),pythiaid,parentid)
271 #print 'xxx',pid, float(mom.x/GeV),float(mom.y/GeV),float(mom.z/GeV),pythiaid,parentid,float(pos.x/m),float(pos.y/m),float(pos.z/m)
272 #myPythia.EventListing()
273
275 print("* Constructing geometry...")
276 world_r = 100.*m
277 # reset world material
278 vac = G4Material.GetMaterial("G4_Galactic")
279 g4py.ezgeom.SetWorldMaterial(vac)
280 g4py.ezgeom.ResizeWorld(world_r, world_r, world_r)
281 # a snoopy world is placed
282 global snoopy,snoopyPhys,scoreLog
283 snoopy = G4EzVolume("Snoopy")
284 snoopy.CreateTubeVolume(vac, 0., 10*m, 50.*m)
285 snoopyPhys = snoopy.PlaceIt(G4ThreeVector(0.,0.,0.*m))
286 snoopyLog = snoopyPhys.GetLogicalVolume()
287 snoopy.SetVisibility(False)
288 # a target box is placed
289 global target,targetPhys
290 iron = G4Material.GetMaterial("G4_Fe")
291 air = G4Material.GetMaterial("G4_AIR")
292 tungsten = G4Material.GetMaterial("G4_W")
293 lead = G4Material.GetMaterial("G4_Pb")
294 alum = G4Material.GetMaterial("G4_Al")
295 target = G4EzVolume("Target")
296 target.CreateTubeVolume(tungsten, 0., 25.*cm, 25.*cm)
297 targetPhys = target.PlaceIt(G4ThreeVector(0.,0.,-50.*m+25.*cm),1,snoopy)
298 target.SetColor(G4Color(0.0,0.5,0.5,1.0))
299 target.SetVisibility(True)
300 # = 0.1m3 = 2t
301 # a hadron absorber is placed
302 absorber = G4EzVolume("Absorber")
303# iron alloys saturate at 1.6-2.2T
304 # inner radius outer radius length
305 absorber.CreateTubeVolume(iron, 0., 100.*cm, 150.*cm)
306 absorberPhys = absorber.PlaceIt(G4ThreeVector(0.,0.,-50*m+2*25.*cm+150.*cm),1,snoopy)
307 absorber.SetColor(G4Color(0.898,0.902,0.91,1.0))
308 absorber.SetVisibility(True)
309 xx = G4VisAttributes()
310 xx.SetForceWireframe(True)
311 absorberlog = absorberPhys.GetLogicalVolume()
312 absorberlog.SetVisAttributes(xx)
313# scoring plane
314 scorez = -50.*m+2*25.*cm+2*150.*cm+1*mm
315 score = G4EzVolume("Score")
316 score.CreateTubeVolume(vac, 0., 50.*m, 1.*mm)
317 scorePhys = score.PlaceIt(G4ThreeVector(0.,0.,scorez),1,snoopy)
318 scoreLog = scorePhys.GetLogicalVolume()
319 g4py.ezgeom.Construct()
320
321g4py.NISTmaterials.Construct()
322#print Geant4.gMaterialTable
323if not muonNuclear:
324 physList = Geant4.FTFP_BERT()
325 gRunManager.SetUserInitialization(physList)
326# with muon nuclear
327else:
328 if 'G4PhysListFactory' in dir(G4physicslists):
329 factory = G4physicslists.G4PhysListFactory()
330 xx = factory.GetReferencePhysList(model)
331 else: xx = G4physicslists.GetReferencePhysList(model)
332 gRunManager.SetUserInitialization(xx)
333
335gRunManager.SetUserAction(myGE)
336#
338gRunManager.SetUserAction(myTA)
339#
340
342
344gRunManager.SetUserAction(myRA)
345
347gRunManager.SetUserAction(myEA)
348
349# initialize
350gRunManager.Initialize()
351# scoring should be set after geometry construction
352sens = ScoreSD('Score')
353scoreLog.SetSensitiveDetector(sens)
354
355t0 = time.time()
356gRunManager.BeamOn(nev)
357t1 = time.time()
358print('Time used',t1-t0, ' seconds')
359for x in myTimer:
360 print(x,myTimer[x])
361
362logger.info("output directory: %s" % work_dir)
myPrintout(self, event)
Definition g4Ex_args.py:216
EndOfEventAction(self, event)
Definition g4Ex_args.py:212
GeneratePrimaries(self, anEvent)
Definition g4Ex_args.py:155
EndOfRunAction(self, run)
Definition g4Ex_args.py:196
UserSteppingAction(self, step)
Definition g4Ex_args.py:226
PreUserTrackingAction(self, atrack)
Definition g4Ex_args.py:233
PostUserTrackingAction(self, atrack)
Definition g4Ex_args.py:231
__init__(self, Name)
Definition g4Ex_args.py:253
ProcessHits(self, step, rohist)
Definition g4Ex_args.py:256
get_work_dir(run_number)
Definition g4Ex_args.py:28
ConstructGeom()
Definition g4Ex_args.py:274