SND@LHC Software
Loading...
Searching...
No Matches
run_simScript.py
Go to the documentation of this file.
1#!/usr/bin/env python
2from __future__ import print_function
3from __future__ import division
4import os
5import sys
6import getopt
7import ROOT
8ROOT.gROOT.ProcessLine('#include "FairEventHeader.h"')
9ROOT.gROOT.ProcessLine('#include "FairMCPoint.h"')
10ROOT.gSystem.Load('libEGPythia8')
11import makeALPACAEvents
12# Fix https://root-forum.cern.ch/t/pyroot-hijacks-help/15207 :
13ROOT.PyConfig.IgnoreCommandLineOptions = True
14
15import shipunit as u
16import shipRoot_conf
17import rootUtils as ut
18from ShipGeoConfig import ConfigRegistry
19from argparse import ArgumentParser
20
21debug = 0 # 1 print weights and field
22 # 2 make overlap check
23dryrun = False # True: just setup Pythia and exit
24
25DownScaleDiMuon = False
26
27# Default HNL parameters
28theHNLMass = 1.0*u.GeV
29theProductionCouplings = theDecayCouplings = None
30
31# Default dark photon parameters
32theDPmass = 0.2*u.GeV
33
34# Alpaca
35motherMode = True
36
37mcEngine = "TGeant4"
38simEngine = "Pythia8" # "Genie" # Ntuple
39
40inclusive = "c" # True = all processes if "c" only ccbar -> HNL, if "b" only bbar -> HNL, if "bc" only Bc+/Bc- -> HNL, and for darkphotons: if meson = production through meson decays, pbrem = proton bremstrahlung, qcd = ffbar -> DP.
41
42MCTracksWithHitsOnly = False # copy particles which produced a hit and their history
43MCTracksWithEnergyCutOnly = True # copy particles above a certain kin energy cut
44MCTracksWithHitsOrEnergyCut = False # or of above, factor 2 file size increase compared to MCTracksWithEnergyCutOnly
45
46charmonly = False # option to be set with -A to enable only charm decays, charm x-sec measurement
47HNL = True
48
49inputFile = "/eos/experiment/ship/data/Charm/Cascade-parp16-MSTP82-1-MSEL4-978Bpot.root"
50defaultInputFile = True
51
52globalDesigns = {'2016':{'dy':10.,'dv':5,'ds':7,'nud':1,'caloDesign':0,'strawDesign':4},\
53 '2018':{'dy':10.,'dv':6,'ds':9,'nud':3,'caloDesign':3,'strawDesign':10}}
54default = '2018'
55
56inactivateMuonProcesses = False # provisionally for making studies of various muon background sources
57checking4overlaps = False
58if debug>1 : checking4overlaps = True
59
60parser = ArgumentParser()
61group = parser.add_mutually_exclusive_group()
62parser.add_argument("--Pythia6", dest="pythia6", help="Use Pythia6", required=False, action="store_true")
63parser.add_argument("--Pythia8", dest="pythia8", help="Use Pythia8", required=False, action="store_true")
64parser.add_argument("--PG", dest="pg", help="Use Particle Gun", required=False, action="store_true")
65parser.add_argument("--pID", dest="pID", help="id of particle used by the gun (default=22)", required=False, default=22, type=int)
66parser.add_argument("--Estart", dest="Estart", help="start of energy range of particle gun for muflux detector (default=10 GeV)", required=False, default=10, type=float)
67parser.add_argument("--Eend", dest="Eend", help="end of energy range of particle gun for muflux detector (default=10 GeV)", required=False, default=10, type=float)
68parser.add_argument("--EVx", dest="EVx", help="particle gun xpos", required=False, default=0, type=float)
69parser.add_argument("--EVy", dest="EVy", help="particle gun ypos", required=False, default=0, type=float)
70parser.add_argument("--EVz", dest="EVz", help="particle gun zpos", required=False, default=0, type=float)
71parser.add_argument("-A", dest="A", help="b: signal from b, c: from c (default), bc: from Bc, or inclusive", required=False, default='c')
72parser.add_argument("--Genie", dest="genie", help="Genie for reading and processing neutrino interactions (1 standard, 2 FLUKA, 3 Pythia)", required=False, default = 0, type = int)
73parser.add_argument("--NuRadio", dest="nuradio", help="misuse GenieGenerator for neutrino radiography and geometry timing test", required=False, action="store_true")
74parser.add_argument("--Ntuple", dest="ntuple", help="Use ntuple as input", required=False, action="store_true")
75group.add_argument("--ALPACA", dest="ALPACA", help="Use ALPACA as input", required=False, action="store_true")
76parser.add_argument("--MuonBack",dest="muonback", help="Generate events from muon background file, --Cosmics=0 for cosmic generator data", required=False, action="store_true")
77parser.add_argument("--FollowMuon",dest="followMuon", help="Make muonshield active to follow muons", required=False, action="store_true")
78parser.add_argument("--FastMuon", dest="fastMuon", help="Only transport muons for a fast muon only background estimate", required=False, action="store_true")
79parser.add_argument('--eMin', type=float, help="energy cut", dest='ecut', default=-1.)
80parser.add_argument("--Nuage", dest="nuage", help="Use Nuage, neutrino generator of OPERA", required=False, action="store_true")
81parser.add_argument("--phiRandom", dest="phiRandom", help="only relevant for muon background generator, random phi", required=False, action="store_true")
82parser.add_argument("--Cosmics", dest="cosmics", help="Use cosmic generator, argument switch for cosmic generator 0 or 1", required=False, default=None)
83parser.add_argument("--MuDIS", dest="mudis", help="Use muon deep inelastic scattering generator", required=False, action="store_true")
84parser.add_argument("--RpvSusy", dest="RPVSUSY", help="Generate events based on RPV neutralino", required=False, action="store_true")
85parser.add_argument("--DarkPhoton", dest="DarkPhoton", help="Generate dark photons", required=False, action="store_true")
86parser.add_argument("--SusyBench", dest="RPVSUSYbench", help="Generate HP Susy", required=False, default=2)
87parser.add_argument("-m", "--mass", dest="theMass", help="Mass of hidden particle, default "+str(theHNLMass)+"GeV for HNL, "+str(theDPmass)+"GeV for DP", required=False, default=None, type=float)
88parser.add_argument("-c", "--couplings", "--coupling", dest="thecouplings", help="couplings \'U2e,U2mu,U2tau\' or -c \'U2e,U2mu,U2tau\' to set list of HNL couplings.\
89 TP default for HNL, ctau=53.3km", required=False,default="0.447e-9,7.15e-9,1.88e-9")
90parser.add_argument("-cp", "--production-couplings", dest="theprodcouplings", help="production couplings \'U2e,U2mu,U2tau\' to set the couplings for HNL production only"\
91 ,required=False,default=None)
92parser.add_argument("-cd", "--decay-couplings", dest="thedeccouplings", help="decay couplings \'U2e,U2mu,U2tau\' to set the couplings for HNL decay only", required=False,default=None)
93parser.add_argument("-e", "--epsilon", dest="theDPepsilon", help="to set mixing parameter epsilon", required=False,default=0.00000008, type=float)
94parser.add_argument("-n", "--nEvents",dest="nEvents", help="Number of events to generate", required=False, default=100, type=int)
95parser.add_argument("-i", "--firstEvent",dest="firstEvent", help="First event of input file to use", required=False, default=0, type=int)
96parser.add_argument("-s", "--seed",dest="theSeed", help="Seed for random number. Only for experts, see TRrandom::SetSeed documentation", required=False, default=0, type=int)
97parser.add_argument("-S", "--sameSeed",dest="sameSeed", help="can be set to an integer for the muonBackground simulation with specific seed for each muon, only for experts!"\
98 ,required=False, default=False, type=int)
99group.add_argument("-f", dest="inputFile", help="Input file if not default file", required=False, default=False)
100parser.add_argument("-g", dest="geofile", help="geofile for muon shield geometry, for experts only", required=False, default=None)
101parser.add_argument("-o", "--output",dest="outputDir", help="Output directory", required=False, default=".")
102parser.add_argument("-Y", dest="dy", help="max height of vacuum tank", required=False, default=globalDesigns[default]['dy'])
103parser.add_argument("--tankDesign", dest="dv", help="4=TP elliptical tank design, 5 = optimized conical rectangular design, 6=5 without segment-1"\
104 ,required=False, default=globalDesigns[default]['dv'], type=int)
105parser.add_argument("--muShieldDesign", dest="ds", help="5=TP muon shield, 6=magnetized hadron, 7=short magnet design, 9=optimised with T4 as constraint, 8=requires config file\
106 ,10=with field map for hadron absorber", required=False, default=globalDesigns[default]['ds'], type=int)
107parser.add_argument("--nuTauTargetDesign", dest="nud", help="0=TP, 1=new magnet option for short muon shield, 2= no magnet surrounding neutrino detector"\
108 ,required=False, default=globalDesigns[default]['nud'], type=int)
109parser.add_argument("--caloDesign", dest="caloDesign", help="0=ECAL/HCAL TP 1=ECAL/HCAL TP + preshower 2=splitCal 3=ECAL/ passive HCAL"\
110 ,required=False, default=globalDesigns[default]['caloDesign'], type=int)
111parser.add_argument("--strawDesign", dest="strawDesign", help="simplistic tracker design, 4=sophisticated straw tube design, horizontal wires (default), 10=2cm straw"
112 ,required=False, default=globalDesigns[default]['strawDesign'], type=int)
113parser.add_argument("--Muflux", dest="muflux", help="Muflux fixed target setup", required=False, action="store_true")
114parser.add_argument("--charm", dest="charm", help="!=0 create charm detector instead of SHiP", required=False, default=0)
115parser.add_argument("--CharmdetSetup", dest="CharmdetSetup", help="1 charm cross section setup, 0 muon flux setup", required=False, default=0, type=int)
116parser.add_argument("--CharmTarget", dest="CharmTarget", help="six different configurations used in July 2018 exposure for charm", required=False, default=3, type=int)
117parser.add_argument("-F", dest="deepCopy", help="default = False: copy only stable particles to stack, except for HNL events", required=False, action="store_true")
118parser.add_argument("-t", "--test", dest="testFlag", help="quick test", required=False,action="store_true")
119parser.add_argument("--dry-run", dest="dryrun", help="stop after initialize", required=False,action="store_true")
120parser.add_argument("-D", "--display", dest="eventDisplay", help="store trajectories", required=False, action="store_true")
121parser.add_argument("--stepMuonShield", dest="muShieldStepGeo", help="activate steps geometry for the muon shield", required=False, action="store_true", default=False)
122parser.add_argument("--coMuonShield", dest="muShieldWithCobaltMagnet", help="replace one of the magnets in the shield with 2.2T cobalt one, downscales other fields, works only for muShieldDesign >2", required=False, type=int, default=0)
123parser.add_argument("--MesonMother", dest="MM", help="Choose DP production meson source", required=False, default=True)
124parser.add_argument("--shiplhc", dest="shipLHC", help="ship @ LHC setup", required=False, action='store_true')
125parser.add_argument("--boostFactor", dest="boostFactor", help="boost mu brems", required=False, type=float,default=0)
126
127options = parser.parse_args()
128
129if options.pythia6: simEngine = "Pythia6"
130if options.pythia8: simEngine = "Pythia8"
131if options.pg: simEngine = "PG"
132if options.genie: simEngine = "Genie"
133if options.nuradio: simEngine = "nuRadiography"
134if options.ntuple: simEngine = "Ntuple"
135if options.ALPACA: simEngine = "ALPACA"
136if options.muonback: simEngine = "MuonBack"
137if options.nuage: simEngine = "Nuage"
138if options.mudis: simEngine = "muonDIS"
139if options.muflux:
140 simEngine = "FixedTarget"
141 HNL = False
142if options.A != 'c':
143 inclusive = options.A
144 if options.A =='b': inputFile = "/eos/experiment/ship/data/Beauty/Cascade-run0-19-parp16-MSTP82-1-MSEL5-5338Bpot.root"
145 if options.A.lower() == 'charmonly':
146 charmonly = True
147 HNL = False
148 if options.A not in ['b','c','bc','meson','pbrem','qcd']: inclusive = True
149if options.MM:
150 motherMode=options.MM
151if options.cosmics:
152 simEngine = "Cosmics"
153 Opt_high = int(options.cosmics)
154if options.inputFile:
155 if options.inputFile == "none": options.inputFile = None
156 inputFile = options.inputFile
157 defaultInputFile = False
158if options.RPVSUSY: HNL = False
159if options.DarkPhoton: HNL = False
160if not options.theMass:
161 if options.DarkPhoton: options.theMass = theDPmass
162 else: options.theMass = theHNLMass
163if options.thecouplings:
164 theCouplings = [float(c) for c in options.thecouplings.split(",")]
165if options.theprodcouplings:
166 theProductionCouplings = [float(c) for c in options.theprodcouplings.split(",")]
167if options.thedeccouplings:
168 theDecayCouplings = [float(c) for c in options.thedeccouplings.split(",")]
169if options.testFlag:
170 inputFile = "$FAIRSHIP/files/Cascade-parp16-MSTP82-1-MSEL4-76Mpot_1_5000.root"
171
172
173#sanity check
174if (HNL and options.RPVSUSY) or (HNL and options.DarkPhoton) or (options.DarkPhoton and options.RPVSUSY):
175 print("cannot have HNL and SUSY or DP at the same time, abort")
176 sys.exit(2)
177
178if (simEngine == "Genie" or simEngine == "nuRadiography") and defaultInputFile:
179 inputFile = "/eos/experiment/ship/data/GenieEvents/genie-nu_mu.root"
180 # "/eos/experiment/ship/data/GenieEvents/genie-nu_mu_bar.root"
181if simEngine == "muonDIS" and defaultInputFile:
182 print('input file required if simEngine = muonDIS')
183 print(" for example -f /eos/experiment/ship/data/muonDIS/muonDis_1.root")
184 sys.exit()
185if simEngine == "Nuage" and not inputFile:
186 inputFile = 'Numucc.root'
187
188print("FairShip setup for",simEngine,"to produce",options.nEvents,"events")
189if (simEngine == "Ntuple" or simEngine == "MuonBack") and defaultInputFile :
190 print('input file required if simEngine = Ntuple or MuonBack')
191 print(" for example -f /eos/experiment/ship/data/Mbias/pythia8_Geant4-withCharm_onlyMuons_4magTarget.root")
192 sys.exit()
193ROOT.gRandom.SetSeed(options.theSeed) # this should be propagated via ROOT to Pythia8 and Geant4VMC
194shipRoot_conf.configure(0) # load basic libraries, prepare atexit for python
195# - muShieldDesign = 2 # 1=passive 5=active (default) 7=short design+magnetized hadron absorber
196# - targetOpt = 5 # 0=solid >0 sliced, 5: 5 pieces of tungsten, 4 H20 slits, 17: Mo + W +H2O (default)
197# nuTauTargetDesign = 0 # 0 = TP, 1 = NEW with magnet, 2 = NEW without magnet, 3 = 2018 design
198if options.muShieldWithCobaltMagnet and options.ds < 3:
199 print("--coMuonShield works only for muShieldDesign >2")
200 sys.exit()
201if options.charm == 0: ship_geo = ConfigRegistry.loadpy("$FAIRSHIP/geometry/geometry_config.py", Yheight = options.dy, tankDesign = options.dv, \
202 muShieldDesign = options.ds, nuTauTargetDesign=options.nud, CaloDesign=options.caloDesign, \
203 strawDesign=options.strawDesign, muShieldGeo=options.geofile,
204 muShieldStepGeo=options.muShieldStepGeo, muShieldWithCobaltMagnet=options.muShieldWithCobaltMagnet)
205else:
206 ship_geo = ConfigRegistry.loadpy("$FAIRSHIP/geometry/charm-geometry_config.py", Setup = options.CharmdetSetup, cTarget = options.CharmTarget)
207 if options.CharmdetSetup == 0: print("Setup for muon flux measurement has been set")
208 else:
209 print("Setup for charm cross section measurement has been set")
210 if (((options.CharmTarget > 6) or (options.CharmTarget < 0)) and (options.CharmTarget != 16)): #check if proper option for emulsion target has been set
211 print("ERROR: unavailable option for CharmTarget. Currently implemented options: 1,2,3,4,5,6,16")
212 1/0
213# switch off magnetic field to measure muon flux
214#ship_geo.muShield.Field = 0.
215#ship_geo.EmuMagnet.B = 0.
216#ship_geo.tauMudet.B = 0.
217
218#-------> MODIFIED
219if options.shipLHC:
220 print("Setup for ship LHC measurement has been set")
221 ship_geo = ConfigRegistry.loadpy("$FAIRSHIP/geometry/shipLHC_geom_config.py")
222#<------- MODIFIED
223
224# Output file name, add dy to be able to setup geometry with ambiguities.
225if simEngine == "PG": tag = simEngine + "_"+str(options.pID)+"-"+mcEngine
226else: tag = simEngine+"-"+mcEngine
227if charmonly: tag = simEngine+"CharmOnly-"+mcEngine
228if options.eventDisplay: tag = tag+'_D'
229if options.dv > 4 : tag = 'conical.'+tag
230elif dy: tag = str(options.dy)+'.'+tag
231if not os.path.exists(options.outputDir):
232 os.makedirs(options.outputDir)
233if options.boostFactor>1:
234 tag+='_boost'+str(options.boostFactor)
235outFile = "%s/ship.%s.root" % (options.outputDir, tag)
236
237# rm older files !!!
238for x in os.listdir(options.outputDir):
239 if not x.find(tag)<0: os.system("rm %s/%s" % (options.outputDir, x) )
240# Parameter file name
241parFile="%s/ship.params.%s.root" % (options.outputDir, tag)
242
243# In general, the following parts need not be touched
244# ========================================================================
245
246# -----Timer--------------------------------------------------------
247timer = ROOT.TStopwatch()
248timer.Start()
249# ------------------------------------------------------------------------
250# -----Create simulation run----------------------------------------
251run = ROOT.FairRunSim()
252run.SetName(mcEngine) # Transport engine
253run.SetOutputFile(outFile) # Output file
254run.SetUserConfig("g4Config.C") # user configuration file default g4Config.C
255rtdb = run.GetRuntimeDb()
256# -----Create geometry----------------------------------------------
257# import shipMuShield_only as shipDet_conf # special use case for an attempt to convert active shielding geometry for use with FLUKA
258# import shipTarget_only as shipDet_conf
259if options.charm!=0: import charmDet_conf as shipDet_conf
260else: import shipDet_conf
261if options.shipLHC: import shipLHC_conf as shipDet_conf #<----- MODIFIED
262
263modules = shipDet_conf.configure(run,ship_geo)
264# -----Create PrimaryGenerator--------------------------------------
265primGen = ROOT.FairPrimaryGenerator()
266if simEngine == "Pythia8":
267 if options.shipLHC: primGen.SetTarget(-100*u.m, 0.) #<----- MODIFIED
268 else: primGen.SetTarget(ship_geo.target.z0, 0.) #<----- Added else:
269# -----Pythia8--------------------------------------
270 if HNL or options.RPVSUSY:
271 P8gen = ROOT.HNLPythia8Generator()
272 import pythia8_conf
273 if HNL:
274 print('Generating HNL events of mass %.3f GeV'%options.theMass)
275 if theProductionCouplings is None and theDecayCouplings is None:
276 print('and with couplings=',theCouplings)
277 theProductionCouplings = theDecayCouplings = theCouplings
278 elif theProductionCouplings is not None and theDecayCouplings is not None:
279 print('and with couplings',theProductionCouplings,'at production')
280 print('and',theDecayCouplings,'at decay')
281 else:
282 raise ValueError('Either both production and decay couplings must be specified, or neither.')
283 pythia8_conf.configure(P8gen,options.theMass,theProductionCouplings,theDecayCouplings,inclusive,options.deepCopy)
284 if options.RPVSUSY:
285 print('Generating RPVSUSY events of mass %.3f GeV'%theHNLMass)
286 print('and with couplings=[%.3f,%.3f]'%(theCouplings[0],theCouplings[1]))
287 print('and with stop mass=%.3f GeV\n'%theCouplings[2])
288 pythia8_conf.configurerpvsusy(P8gen,options.theMass,[theCouplings[0],theCouplings[1]],
289 theCouplings[2],options.RPVSUSYbench,inclusive,options.deepCopy)
290 P8gen.SetParameters("ProcessLevel:all = off")
291 if inputFile:
292 ut.checkFileExists(inputFile)
293# read from external file
294 P8gen.UseExternalFile(inputFile, options.firstEvent)
295 if options.DarkPhoton:
296 P8gen = ROOT.DPPythia8Generator()
297 if inclusive=='qcd':
298 P8gen.SetDPId(4900023)
299 else:
300 P8gen.SetDPId(9900015)
301 import pythia8darkphoton_conf
302 passDPconf = pythia8darkphoton_conf.configure(P8gen,options.theMass,options.theDPepsilon,inclusive, motherMode, options.deepCopy)
303 if (passDPconf!=1): sys.exit()
304 if HNL or options.RPVSUSY or options.DarkPhoton:
305 if not options.shipLHC:#<------- MODIFIED
306 #------> Added indentation
307 P8gen.SetSmearBeam(1*u.cm) # finite beam size
308 P8gen.SetLmin((ship_geo.Chamber1.z - ship_geo.chambers.Tub1length) - ship_geo.target.z0 )
309 P8gen.SetLmax(ship_geo.TrackStation1.z - ship_geo.target.z0 )
310 #<------- Added indentation
311 if charmonly:
312 primGen.SetTarget(0., 0.) #vertex is setted in pythia8Generator
313 ut.checkFileExists(inputFile)
314 if ship_geo.Box.gausbeam:
315 primGen.SetBeam(0.,0., 0.5, 0.5) #more central beam, for hits in downstream detectors
316 primGen.SmearGausVertexXY(True) #sigma = x
317 else:
318 if not options.shipLHC: #<----- MODIFIED
319 primGen.SetBeam(0.,0., ship_geo.Box.TX-1., ship_geo.Box.TY-1.) #Uniform distribution in x/y on the target (0.5 cm of margin at both sides)
320 primGen.SmearVertexXY(True)
321 P8gen = ROOT.Pythia8Generator()
322 P8gen.UseExternalFile(inputFile, options.firstEvent)
323 if ship_geo.MufluxSpectrometer.muflux == False :
324 P8gen.SetTarget("volTarget_1",0.,0.) # will distribute PV inside target, beam offset x=y=0.
325 else:
326 print("ERROR: charmonly option should not be used for the muonflux measurement")
327 1/0
328 #------> MODIFIED
329 if options.shipLHC:
330 P8gen = ROOT.Pythia8Generator()
331 P8gen.UseExternalFile(inputFile, options.firstEvent)
332 primGen.SetBeam(0.,0.,ship_geo.EmulsionDet.xdim,ship_geo.EmulsionDet.ydim)
333 primGen.SmearVertexXY(True)
334 P8gen.SetTarget("volTarget_1",0.,0.) # will distribute PV inside target, beam offset x=y=0.
335 #<----- MODIFIED
336# pion on proton 500GeV
337# P8gen.SetMom(500.*u.GeV)
338# P8gen.SetId(-211)
339 primGen.AddGenerator(P8gen)
340
341if simEngine == "ALPACA":
342 print('Generating ALP events of mass {} GeV with the photon coupling coefficient {} GeV^-1'.format(options.theMass, options.theDPepsilon))
343 target = ship_geo.target
344 startZ = target.z0
345 lengthZ = target.length
346 endZ = startZ + lengthZ
347 SmearBeam = 1*u.cm # finite beam size
348 Lmin = ((ship_geo.Chamber1.z - ship_geo.chambers.Tub1length) - ship_geo.target.z0)/100.
349 Lmax = (ship_geo.TrackStation1.z - ship_geo.target.z0)/100.
350 print('ALPACA is initializing.')
351 inputFile = makeALPACAEvents.runEvents(options.theMass,options.theDPepsilon,options.nEvents,Lmin,Lmax,startZ,endZ,SmearBeam)
352 if inputFile: print('ALPACA is done.')
353 ut.checkFileExists(inputFile)
354 ALPACAgen = ROOT.ALPACAGenerator()
355 ALPACAgen.Init(inputFile)
356 print('ALPACAGenerator is reading the ALPACA events')
357 primGen.AddGenerator(ALPACAgen)
358
359if simEngine == "FixedTarget":
360 P8gen = ROOT.FixedTargetGenerator()
361 P8gen.SetTarget("volTarget_1",0.,0.)
362 P8gen.SetMom(400.*u.GeV)
363 P8gen.SetEnergyCut(0.)
364 P8gen.SetHeartBeat(100000)
365 P8gen.SetG4only()
366 primGen.AddGenerator(P8gen)
367if simEngine == "Pythia6":
368# set muon interaction close to decay volume
369 primGen.SetTarget(ship_geo.target.z0+ship_geo.muShield.length, 0.)
370# -----Pythia6-------------------------
371 test = ROOT.TPythia6() # don't know any other way of forcing to load lib
372 P6gen = ROOT.tPythia6Generator()
373 P6gen.SetMom(50.*u.GeV)
374 P6gen.SetTarget("gamma/mu+","n0") # default "gamma/mu-","p+"
375 primGen.AddGenerator(P6gen)
376# -----Particle Gun-----------------------
377if simEngine == "PG":
378 myPgun = ROOT.FairBoxGenerator(options.pID,1)
379 myPgun.SetPRange(options.Estart,options.Eend)
380 myPgun.SetPhiRange(0, 360) # // Azimuth angle range [degree]
381 myPgun.SetXYZ(options.EVx*u.cm, options.EVy*u.cm, options.EVz*u.cm)
382 if options.charm!=0:
383 myPgun.SetThetaRange(0,6) # // Pdefault for muon flux
384 primGen.SetTarget(ship_geo.target.z0,0.)
385 else:
386 myPgun.SetThetaRange(0,0) # // Polar angle in lab system range [degree]
387 primGen.AddGenerator(myPgun)
388 ROOT.FairLogger.GetLogger().SetLogScreenLevel("WARNING") # otherwise stupid printout for each event
389# -----muon DIS Background------------------------
390if simEngine == "muonDIS":
391 ut.checkFileExists(inputFile)
392 primGen.SetTarget(0., 0.)
393 DISgen = ROOT.MuDISGenerator()
394 if options.shipLHC:
395 mu_start, mu_end = (-3.7-2.0)*u.m , -0.3*u.m # tunnel wall -30cm in front of SND
396 DISgen.SetPositions(0, mu_start, mu_end)
397 if options.ecut > 0: modules['Floor'].SetEmin(options.ecut)
398 else:
399 # from nu_tau detector to tracking station 2
400 # mu_start, mu_end = ship_geo.tauMudet.zMudetC,ship_geo.TrackStation2.z
401 #
402 # in front of UVT up to tracking station 1
403 mu_start, mu_end = ship_geo.Chamber1.z-ship_geo.chambers.Tub1length-10.*u.cm,ship_geo.TrackStation1.z
404 DISgen.SetPositions(ship_geo.target.z0, mu_start, mu_end)
405
406 print('MuDIS position info input=',mu_start, mu_end)
407 DISgen.Init(inputFile,options.firstEvent)
408 primGen.AddGenerator(DISgen)
409 options.nEvents = min(options.nEvents,DISgen.GetNevents())
410 inactivateMuonProcesses = True # avoid unwanted hadronic events of "incoming" muon flying backward
411 print('Generate ',options.nEvents,' with DIS input', ' first event',options.firstEvent)
412# -----neutrino interactions from nuage------------------------
413if simEngine == "Nuage" and not options.shipLHC:
414 primGen.SetTarget(0., 0.)
415 Nuagegen = ROOT.NuageGenerator()
416 Nuagegen.EnableExternalDecayer(1) #with 0 external decayer is disable, 1 is enabled
417 print('Nuage position info input=',ship_geo.EmuMagnet.zC-ship_geo.NuTauTarget.zdim, ship_geo.EmuMagnet.zC+ship_geo.NuTauTarget.zdim)
418 #--------------------------------
419 #to Generate neutrino interactions in the whole neutrino target
420# Nuagegen.SetPositions(ship_geo.EmuMagnet.zC, ship_geo.NuTauTarget.zC-ship_geo.NuTauTarget.zdim/2, ship_geo.NuTauTarget.zC+ship_geo.NuTauTarget.zdim/2, -ship_geo.NuTauTarget.xdim/2, ship_geo.NuTauTarget.xdim/2, -ship_geo.NuTauTarget.ydim/2, ship_geo.NuTauTarget.ydim/2)
421 #--------------------------------
422 #to Generate neutrino interactions ONLY in ONE brick
423 ntt = 6
424 nXcells = 7
425 nYcells = 3
426 nZcells = ntt -1
427 startx = -ship_geo.NuTauTarget.xdim/2. + nXcells*ship_geo.NuTauTarget.BrX
428 endx = -ship_geo.NuTauTarget.xdim/2. + (nXcells+1)*ship_geo.NuTauTarget.BrX
429 starty = -ship_geo.NuTauTarget.ydim/2. + nYcells*ship_geo.NuTauTarget.BrY
430 endy = - ship_geo.NuTauTarget.ydim/2. + (nYcells+1)*ship_geo.NuTauTarget.BrY
431 startz = ship_geo.EmuMagnet.zC - ship_geo.NuTauTarget.zdim/2. + ntt *ship_geo.NuTauTT.TTZ + nZcells * ship_geo.NuTauTarget.CellW
432 endz = ship_geo.EmuMagnet.zC - ship_geo.NuTauTarget.zdim/2. + ntt *ship_geo.NuTauTT.TTZ + nZcells * ship_geo.NuTauTarget.CellW + ship_geo.NuTauTarget.BrZ
433 Nuagegen.SetPositions(ship_geo.target.z0, startz, endz, startx, endx, starty, endy)
434 #--------------------------------
435 ut.checkFileExists(inputFile)
436 Nuagegen.Init(inputFile,options.firstEvent)
437 primGen.AddGenerator(Nuagegen)
438 options.nEvents = min(options.nEvents,Nuagegen.GetNevents())
439 run.SetPythiaDecayer("DecayConfigNuAge.C")
440 print('Generate ',options.nEvents,' with Nuage input', ' first event',options.firstEvent)
441 #--------------------> MODIFIED
442if simEngine == "Nuage" and options.shipLHC:
443 primGen.SetTarget(0., 0.)
444 Nuagegen = ROOT.NuageGenerator()
445 Nuagegen.EnableExternalDecayer(1) #with 0 external decayer is disable, 1 is enabled
446 Nuagegen.SetPositions(0., -ship_geo.EmulsionDet.zdim/2, ship_geo.EmulsionDet.zdim/2, -ship_geo.EmulsionDet.xdim/2, ship_geo.EmulsionDet.xdim/2, -ship_geo.EmulsionDet.ydim/2, ship_geo.EmulsionDet.ydim/2)
447 ut.checkFileExists(inputFile)
448 Nuagegen.Init(inputFile,options.firstEvent)
449 primGen.AddGenerator(Nuagegen)
450 options.nEvents = min(options.nEvents,Nuagegen.GetNevents())
451 run.SetPythiaDecayer("DecayConfigNuAge.C")
452 print('Generate ',options.nEvents,' with Nuage input', ' first event',options.firstEvent)
453
454
455
456
457 #<--------------------- MODIFIED
458# -----Neutrino Background------------------------
459if simEngine == "Genie" and not options.shipLHC: #<--------------------- MODIFIED
460# Genie
461 ut.checkFileExists(inputFile)
462 primGen.SetTarget(0., 0.) # do not interfere with GenieGenerator
463 Geniegen = ROOT.GenieGenerator()
464 Geniegen.Init(inputFile,options.firstEvent)
465 Geniegen.SetPositions(ship_geo.target.z0, ship_geo.tauMudet.zMudetC-5*u.m, ship_geo.TrackStation2.z)
466 primGen.AddGenerator(Geniegen)
467 options.nEvents = min(options.nEvents,Geniegen.GetNevents())
468 run.SetPythiaDecayer("DecayConfigNuAge.C")
469 print('Generate ',options.nEvents,' with Genie input', ' first event',options.firstEvent)
470
471#--------------------> MODIFIED
472if simEngine=="Genie" and options.shipLHC:
473 ut.checkFileExists(inputFile)
474 primGen.SetTarget(0., 0.) # do not interfere with GenieGenerator
475 Geniegen = ROOT.GenieGenerator()
476 Geniegen.SetGenerationOption(options.genie - 1) #0 default GenieGen, 1 FLUKA, 2 Pythia
477 Geniegen.Init(inputFile,options.firstEvent)
478 Geniegen.SetCrossingAngle(150e-6) #used only in option 2
479 Geniegen.SetPositions(ship_geo.EmulsionDet.zC-480*u.m, ship_geo.EmulsionDet.zC-ship_geo.EmulsionDet.zdim/2,ship_geo.EmulsionDet.zC+ship_geo.EmulsionDet.zdim/2)
480 #Geniegen.SetPositions(ship_geo.EmulsionDet.zC+60*u.cm, ship_geo.EmulsionDet.zC-ship_geo.EmulsionDet.zdim/2,ship_geo.EmulsionDet.zC+ship_geo.EmulsionDet.zdim/2) #FLUKA scoring position
481 Geniegen.SetDeltaE_Matching_FLUKAGenie(10.) #energy range for the search of a GENIE interaction with similar energy of FLUKA neutrino
482 primGen.AddGenerator(Geniegen)
483 options.nEvents = min(options.nEvents,Geniegen.GetNevents())
484 run.SetPythiaDecayer('DecayConfigPy8.C')
485 print('Generate ',options.nEvents,' with Genie input for Ship@LHC', ' first event',options.firstEvent)
486#<--------------------- MODIFIED
487
488if simEngine == "nuRadiography":
489 ut.checkFileExists(inputFile)
490 primGen.SetTarget(0., 0.) # do not interfere with GenieGenerator
491 Geniegen = ROOT.GenieGenerator()
492 Geniegen.Init(inputFile,options.firstEvent)
493 # Geniegen.SetPositions(ship_geo.target.z0, ship_geo.target.z0, ship_geo.MuonStation3.z)
494 Geniegen.SetPositions(ship_geo.target.z0, ship_geo.tauMudet.zMudetC, ship_geo.MuonStation3.z)
495 Geniegen.NuOnly()
496 primGen.AddGenerator(Geniegen)
497 print('Generate ',options.nEvents,' for nuRadiography', ' first event',options.firstEvent)
498# add tungsten to PDG
499 pdg = ROOT.TDatabasePDG.Instance()
500 pdg.AddParticle('W','Ion', 1.71350e+02, True, 0., 74, 'XXX', 1000741840)
501#
502 run.SetPythiaDecayer('DecayConfigPy8.C')
503 # this requires writing a C macro, would have been easier to do directly in python!
504 # for i in [431,421,411,-431,-421,-411]:
505 # ROOT.gMC.SetUserDecay(i) # Force the decay to be done w/external decayer
506if simEngine == "Ntuple":
507 if options.shipLHC:
508 ut.checkFileExists(inputFile)
509 Ntuplegen = ROOT.NtupleGenerator_FLUKA()
510 Ntuplegen.SetZ(ship_geo.Floor.z)
511 Ntuplegen.Init(inputFile,options.firstEvent)
512 primGen.AddGenerator(Ntuplegen)
513 options.nEvents = min(options.nEvents,Ntuplegen.GetNevents())
514 else:
515# reading previously processed muon events, [-50m - 50m]
516 ut.checkFileExists(inputFile)
517 primGen.SetTarget(ship_geo.target.z0+50*u.m,0.)
518 Ntuplegen = ROOT.NtupleGenerator()
519 Ntuplegen.Init(inputFile,options.firstEvent)
520 primGen.AddGenerator(Ntuplegen)
521 options.nEvents = min(options.nEvents,Ntuplegen.GetNevents())
522 print('Process ',options.nEvents,' from input file')
523#
524
525if simEngine == "MuonBack":
526# reading muon tracks from previous Pythia8/Geant4 simulation with charm replaced by cascade production
527 fileType = ut.checkFileExists(inputFile)
528 if fileType == 'tree':
529 # 2018 background production
530 primGen.SetTarget(ship_geo.target.z0+70.845*u.m,0.)
531 else:
532 primGen.SetTarget(ship_geo.target.z0+50*u.m,0.)
533 #
534 MuonBackgen = ROOT.MuonBackGenerator()
535 # MuonBackgen.FollowAllParticles() # will follow all particles after hadron absorber, not only muons
536 MuonBackgen.Init(inputFile,options.firstEvent,options.phiRandom)
537 if options.charm == 0: MuonBackgen.SetSmearBeam(5 * u.cm) # radius of ring, thickness 8mm
538 elif DownScaleDiMuon:
539 if inputFile[0:4] == "/eos": test = os.environ["EOSSHIP"]+inputFile
540 else: test = inputFile
541 testf = ROOT.TFile.Open(test)
542 if not testf.FileHeader.GetTitle().find('diMu100.0')<0:
543 MuonBackgen.SetDownScaleDiMuon() # avoid interference with boosted channels
544 print("MuonBackgenerator: set downscale for dimuon on")
545 testf.Close()
546 if options.sameSeed: MuonBackgen.SetSameSeed(options.sameSeed)
547 primGen.AddGenerator(MuonBackgen)
548 options.nEvents = min(options.nEvents,MuonBackgen.GetNevents())
549 MCTracksWithHitsOnly = True # otherwise, output file becomes too big
550 print('Process ',options.nEvents,' from input file, with Phi random=',options.phiRandom, ' with MCTracksWithHitsOnly',MCTracksWithHitsOnly)
551
552 # optional, boost gamma2muon conversion
553 # ROOT.kShipMuonsCrossSectionFactor = 100.
554#
555if simEngine == "Cosmics":
556 primGen.SetTarget(0., 0.)
557 Cosmicsgen = ROOT.CosmicsGenerator()
558 import CMBG_conf
559 CMBG_conf.configure(Cosmicsgen, ship_geo)
560 if not Cosmicsgen.Init(Opt_high):
561 print("initialization of cosmic background generator failed ",Opt_high)
562 sys.exit(0)
563 Cosmicsgen.n_EVENTS = options.nEvents
564 primGen.AddGenerator(Cosmicsgen)
565 print('Process ',options.nEvents,' Cosmic events with option ',Opt_high)
566#
567run.SetGenerator(primGen)
568# ------------------------------------------------------------------------
569if options.followMuon :
570 if 'Veto' in modules:
571 options.fastMuon = True
572 modules['Veto'].SetFollowMuon()
573 if 'Floor' in modules:
574 modules['Floor'].MakeSensitive()
575 print('make floor sensitive')
576if options.fastMuon :
577 if 'Veto' in modules: modules['Veto'].SetFastMuon()
578 elif 'Floor' in modules:
579 modules['Floor'].SetFastMuon()
580 print('only transport muons')
581# ------------------------------------------------------------------------
582#---Store the visualiztion info of the tracks, this make the output file very large!!
583#--- Use it only to display but not for production!
584if options.eventDisplay: run.SetStoreTraj(ROOT.kTRUE)
585else: run.SetStoreTraj(ROOT.kFALSE)
586# -----Initialize simulation run------------------------------------
587run.Init()
588if options.dryrun: # Early stop after setting up Pythia 8
589 sys.exit(0)
590gMC = ROOT.TVirtualMC.GetMC()
591fStack = gMC.GetStack()
592if MCTracksWithHitsOnly:
593 fStack.SetMinPoints(1)
594 fStack.SetEnergyCut(-100.*u.MeV)
595elif MCTracksWithEnergyCutOnly:
596 fStack.SetMinPoints(-1)
597 fStack.SetEnergyCut(100.*u.MeV)
598elif MCTracksWithHitsOrEnergyCut:
599 fStack.SetMinPoints(1)
600 fStack.SetEnergyCut(100.*u.MeV)
601elif options.deepCopy:
602 fStack.SetMinPoints(0)
603 fStack.SetEnergyCut(0.*u.MeV)
604
605#
606if options.boostFactor > 1:
607 ROOT.gROOT.ProcessLine('#include "Geant4/G4ProcessTable.hh"')
608 ROOT.gROOT.ProcessLine('#include "Geant4/G4MuBremsstrahlung.hh"')
609 gProcessTable = ROOT.G4ProcessTable.GetProcessTable()
610 procBrems = gProcessTable.FindProcess(ROOT.G4String('muBrems'),ROOT.G4String('mu+'))
611 procBrems.SetCrossSectionBiasingFactor(options.boostFactor)
612#
613
614if options.eventDisplay:
615 # Set cuts for storing the trajectories, can only be done after initialization of run (?!)
616 trajFilter = ROOT.FairTrajFilter.Instance()
617 trajFilter.SetStepSizeCut(1*u.mm);
618 trajFilter.SetVertexCut(-20*u.m, -20*u.m,ship_geo.target.z0-1*u.m, 20*u.m, 20*u.m, 200.*u.m)
619 trajFilter.SetMomentumCutP(0.1*u.GeV)
620 trajFilter.SetEnergyCut(0., 400.*u.GeV)
621 trajFilter.SetStorePrimaries(ROOT.kTRUE)
622 trajFilter.SetStoreSecondaries(ROOT.kTRUE)
623
624# The VMC sets the fields using the "/mcDet/setIsLocalMagField true" option in "gconfig/g4config.in"
625import geomGeant4
626# geomGeant4.setMagnetField() # replaced by VMC, only has effect if /mcDet/setIsLocalMagField false
627
628# Define extra VMC B fields not already set by the geometry definitions, e.g. a global field,
629# any field maps, or defining if any volumes feel only the local or local+global field.
630# For now, just keep the fields already defined by the C++ code, i.e comment out the fieldMaker
631if options.charm == 0 and not options.shipLHC: # charm and muflux testbeam not yet updated for using the new bfield interface <-------- MODIFIED
632 if hasattr(ship_geo.Bfield,"fieldMap"):
633 fieldMaker = geomGeant4.addVMCFields(ship_geo, '', True)
634
635# Print VMC fields and associated geometry objects
636if debug > 0:
638 geomGeant4.printWeightsandFields(onlyWithField = True,\
639 exclude=['DecayVolume','Tr1','Tr2','Tr3','Tr4','Veto','Ecal','Hcal','MuonDetector','SplitCal'])
640# Plot the field example
641#fieldMaker.plotField(1, ROOT.TVector3(-9000.0, 6000.0, 50.0), ROOT.TVector3(-300.0, 300.0, 6.0), 'Bzx.png')
642#fieldMaker.plotField(2, ROOT.TVector3(-9000.0, 6000.0, 50.0), ROOT.TVector3(-400.0, 400.0, 6.0), 'Bzy.png')
643
644if inactivateMuonProcesses :
645 ROOT.gROOT.ProcessLine('#include "Geant4/G4ProcessTable.hh"')
646 mygMC = ROOT.TGeant4.GetMC()
647 mygMC.ProcessGeantCommand("/process/inactivate muPairProd")
648 mygMC.ProcessGeantCommand("/process/inactivate muBrems")
649 mygMC.ProcessGeantCommand("/process/inactivate muIoni")
650 mygMC.ProcessGeantCommand("/process/inactivate muonNuclear")
651 mygMC.ProcessGeantCommand("/particle/select mu+")
652 mygMC.ProcessGeantCommand("/particle/process/dump")
653 gProcessTable = ROOT.G4ProcessTable.GetProcessTable()
654 procmu = gProcessTable.FindProcess(ROOT.G4String('muIoni'),ROOT.G4String('mu+'))
655 procmu.SetVerboseLevel(2)
656
657if debug: ROOT.fair.Logger.SetConsoleSeverity("debug")
658# -----Start run----------------------------------------------------
659run.Run(options.nEvents)
660# -----Runtime database---------------------------------------------
661kParameterMerged = ROOT.kTRUE
662parOut = ROOT.FairParRootFileIo(kParameterMerged)
663parOut.open(parFile)
664rtdb.setOutput(parOut)
665rtdb.saveOutput()
666rtdb.printParamContexts()
667getattr(rtdb,"print")()
668# ------------------------------------------------------------------------
669run.CreateGeometryFile("%s/geofile_full.%s.root" % (options.outputDir, tag))
670# save ShipGeo dictionary in geofile
671import saveBasicParameters
672saveBasicParameters.execute("%s/geofile_full.%s.root" % (options.outputDir, tag),ship_geo)
673
674# checking for overlaps
675if checking4overlaps:
676 fGeo = ROOT.gGeoManager
677 fGeo.SetNmeshPoints(10000)
678 fGeo.CheckOverlaps(0.1) # 1 micron takes 5minutes
679 fGeo.PrintOverlaps()
680 # check subsystems in more detail
681 for x in fGeo.GetTopNode().GetNodes():
682 x.CheckOverlaps(0.0001)
683 fGeo.PrintOverlaps()
684# -----Finish-------------------------------------------------------
685timer.Stop()
686rtime = timer.RealTime()
687ctime = timer.CpuTime()
688print(' ')
689print("Macro finished succesfully.")
690if "P8gen" in globals() :
691 if (HNL): print("number of retries, events without HNL ",P8gen.nrOfRetries())
692 elif (options.DarkPhoton):
693 print("number of retries, events without Dark Photons ",P8gen.nrOfRetries())
694 print("total number of dark photons (including multiple meson decays per single collision) ",P8gen.nrOfDP())
695
696print("Output file is ", outFile)
697print("Parameter file is ",parFile)
698print("Real time ",rtime, " s, CPU time ",ctime,"s")
699
700# remove empty events
701if simEngine == "MuonBack" and not options.followMuon:
702 tmpFile = outFile+"tmp"
703 xxx = outFile.split('/')
704 check = xxx[len(xxx)-1]
705 fin = False
706 for ff in ROOT.gROOT.GetListOfFiles():
707 nm = ff.GetName().split('/')
708 if nm[len(nm)-1] == check: fin = ff
709 if not fin: fin = ROOT.TFile.Open(outFile)
710 t = fin.cbmsim
711 fout = ROOT.TFile(tmpFile,'recreate')
712 sTree = t.CloneTree(0)
713 nEvents = 0
714 pointContainers = []
715 for x in sTree.GetListOfBranches():
716 name = x.GetName()
717 if not name.find('Point')<0: pointContainers.append('sTree.'+name+'.GetEntries()') # makes use of convention that all sensitive detectors fill XXXPoint containers
718 for n in range(t.GetEntries()):
719 rc = t.GetEvent(n)
720 empty = True
721 for x in pointContainers:
722 if eval(x)>0: empty = False
723 if not empty:
724 rc = sTree.Fill()
725 nEvents+=1
726 sTree.AutoSave()
727 fout.Close()
728 print("removed empty events, left with:", nEvents)
729 rc1 = os.system("rm "+outFile)
730 rc2 = os.system("mv "+tmpFile+" "+outFile)
731 fin.SetWritable(False) # bpyass flush error
732# ------------------------------------------------------------------------
733import checkMagFields
737 # after /run/initialize, but prints warning messages, problems with TGeo volume
738 mygMC = ROOT.TGeant4.GetMC()
739 mygMC.ProcessGeantCommand("/geometry/test/recursion_start 0")
740 mygMC.ProcessGeantCommand("/geometry/test/recursion_depth 2")
741 mygMC.ProcessGeantCommand("/geometry/test/run")
configure(CMBG, ship_geo)
Definition CMBG_conf.py:5
printWeightsandFields(onlyWithField=True, exclude=[])
addVMCFields(shipGeo, controlFile='', verbose=False, withVirtualMC=True)
runEvents(mres, gax, nev, Lmin, Lmax, startZ, endZ, SmearBeam)
configurerpvsusy(P8gen, mass, couplings, sfermionmass, benchmark, inclusive, deepCopy=False, debug=True)
configure(P8gen, mass, production_couplings, decay_couplings, process_selection, deepCopy=False, debug=True)
configure(P8gen, mass, epsilon, inclusive, motherMode, deepCopy=False, debug=True)
execute(f, ox, name='ShipGeo')
configure(run, ship_geo)
configure(darkphoton=None)