ATLAS Offline Software
skel.GENtoEVGEN.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
2 #
3 """Functionality core of the Gen_tf transform"""
4 
5 
8 
9 
11 
12 import ast
13 import os, re, string, subprocess
14 import AthenaCommon.AlgSequence as acas
15 import AthenaCommon.AppMgr as acam
16 from AthenaCommon.AthenaCommonFlags import jobproperties
17 
18 from xAODEventInfoCnv.xAODEventInfoCnvConf import xAODMaker__EventInfoCnvAlg
19 acam.athMasterSeq += xAODMaker__EventInfoCnvAlg(xAODKey="TMPEvtInfo")
20 
21 theApp = acam.theApp
22 acam.athMasterSeq += acas.AlgSequence("EvgenGenSeq")
23 genSeq = acam.athMasterSeq.EvgenGenSeq
24 acam.athMasterSeq += acas.AlgSequence("EvgenFixSeq")
25 fixSeq = acam.athMasterSeq.EvgenFixSeq
26 acam.athMasterSeq += acas.AlgSequence("EvgenPreFilterSeq")
27 prefiltSeq = acam.athMasterSeq.EvgenPreFilterSeq
28 acam.athMasterSeq += acas.AlgSequence("EvgenTestSeq")
29 testSeq = acam.athMasterSeq.EvgenTestSeq
30 
31 from EvgenProdTools.LogicalExpressionFilter import LogicalExpressionFilter
32 acam.athMasterSeq += LogicalExpressionFilter("EvgenFilterSeq")
33 filtSeq = acam.athMasterSeq.EvgenFilterSeq
34 topSeq = acas.AlgSequence()
35 anaSeq = topSeq
36 topSeq += acas.AlgSequence("EvgenPostSeq")
37 postSeq = topSeq.EvgenPostSeq
38 #topAlg = topSeq #< alias commented out for now, so that accidental use throws an error
39 
40 
41 
44 
45 
46 include("AthenaCommon/Atlas_Gen.UnixStandardJob.py")
47 include("PartPropSvc/PartPropSvc.py")
48 
49 
50 from PerfMonComps.PerfMonFlags import jobproperties as perfmonjp
51 perfmonjp.PerfMonFlags.doMonitoring = True
52 perfmonjp.PerfMonFlags.doSemiDetailedMonitoring = True
53 
54 
55 from RngComps.RngCompsConf import AthRNGSvc
56 svcMgr += AthRNGSvc()
57 
58 
59 jobproperties.AthenaCommonFlags.AllowIgnoreConfigError = False
60 
61 
62 from AthenaCommon.Logging import logging
63 evgenLog = logging.getLogger('Gen_tf')
64 
65 
68 
69 
70 evgenLog.debug("****************** CHECKING EVENT GENERATION ARGS *****************")
71 evgenLog.debug(str(runArgs))
72 
73 if hasattr(runArgs, "inputGeneratorFile"):
74  evgenLog.info("inputGeneratorFile = " + runArgs.inputGeneratorFile)
75 
76 if hasattr(runArgs, "outputYODAFile"):
77  evgenLog.info("specified outputYODAFile = " + runArgs.outputYODAFile)
78 
79 
81 if not hasattr(runArgs, "outputEVNTFile") and not hasattr(runArgs, "outputEVNT_PreFile"):
82  if hasattr(runArgs, "outputYODAFile"):
83  evgenLog.info("No outputEVNTFile specified but outputYODAFile is used")
84  evgenLog.info("Will run GENtoEVGEN without saving the output EVNT file, asuming a valid outputYODAFile will be produced")
85  else:
86  raise RuntimeError("No output evgen EVNT or EVNT_Pre file provided.")
87 
88 
89 if not hasattr(runArgs, "ecmEnergy"):
90  raise RuntimeError("No center of mass energy provided.")
91 else:
92  evgenLog.info(' ecmEnergy = ' + str(runArgs.ecmEnergy) )
93 if not hasattr(runArgs, "randomSeed"):
94  raise RuntimeError("No random seed provided.")
95  # TODO: or guess it from the JO name??
96 if not hasattr(runArgs, "firstEvent"):
97  raise RuntimeError("No first number provided.")
98 if ( runArgs.firstEvent <= 0):
99  evgenLog.warning("Run argument firstEvent should be > 0")
100 
101 
104 
105 
106 evgenLog.debug("****************** CONFIGURING EVENT GENERATION *****************")
107 
108 
110 from EvgenJobTransforms.EvgenConfig import evgenConfig
111 from GeneratorConfig.GenConfigHelpers import gens_known, gen_lhef, gens_lhef, gen_sortkey, gens_testhepmc, gens_notune, gen_require_steering
112 
113 
114 from EvgenProdTools.EvgenProdToolsConf import FixHepMC
115 if not hasattr(fixSeq, "FixHepMC"):
116  fixSeq += FixHepMC()
117 
118 
119 from EvgenProdTools.EvgenProdToolsConf import TestHepMC
120 testSeq += TestHepMC(CmEnergy=runArgs.ecmEnergy*Units.GeV)
121 #testSeq += TestHepMC(CmEnergy=runArgs.ecmEnergy)
122 if not hasattr(svcMgr, 'THistSvc'):
123  from GaudiSvc.GaudiSvcConf import THistSvc
124  svcMgr += THistSvc()
125 svcMgr.THistSvc.Output = ["TestHepMCname DATAFILE='TestHepMC.root' OPT='RECREATE'"]
126 
127 
129 from EvgenProdTools.EvgenProdToolsConf import CopyEventWeight
130 if not hasattr(postSeq, "CopyEventWeight"):
131  postSeq += CopyEventWeight(mcEventWeightsKey="TMPEvtInfo.mcEventWeights")
132 
133 from EvgenProdTools.EvgenProdToolsConf import FillFilterValues
134 if not hasattr(postSeq, "FillFilterValues"):
135  postSeq += FillFilterValues(mcFilterHTKey="TMPEvtInfo.mcFilterHT")
136 
137 
139 from EvgenProdTools.EvgenProdToolsConf import CountHepMC
140 svcMgr.EventSelector.FirstEvent = runArgs.firstEvent
141 theApp.EvtMax = -1
142 # This is necessary for athenaMP # commented out for now
143 #if hasattr(runArgs, "maxEvents"):
144 # theApp.EvtMax = runArgs.maxEvents
145 
146 if not hasattr(postSeq, "CountHepMC"):
147  postSeq += CountHepMC(InputEventInfo="TMPEvtInfo",
148  OutputEventInfo="EventInfo",
149  mcEventWeightsKey="TMPEvtInfo.mcEventWeights")
150 #postSeq.CountHepMC.RequestedOutput = evgenConfig.nEventsPerJob if runArgs.maxEvents == -1 else runArgs.maxEvents
151 
152 postSeq.CountHepMC.FirstEvent = runArgs.firstEvent
153 postSeq.CountHepMC.CorrectHepMC = True
154 postSeq.CountHepMC.CorrectEventID = True
155 
156 
158 if hasattr(runArgs, "printEvts") and runArgs.printEvts > 0:
159  from TruthIO.TruthIOConf import PrintMC
160  postSeq += PrintMC()
161  postSeq.PrintMC.McEventKey = "GEN_EVENT"
162  postSeq.PrintMC.VerboseOutput = True
163  postSeq.PrintMC.PrintStyle = "Barcode"
164  postSeq.PrintMC.FirstEvent = 1
165  postSeq.PrintMC.LastEvent = runArgs.printEvts
166 
167 
168 from EvgenProdTools.EvgenProdToolsConf import SimTimeEstimate
169 if not hasattr(postSeq, "SimTimeEstimate"):
170  postSeq += SimTimeEstimate()
171 
172 
174 if hasattr(runArgs, "rivetAnas"):
175  from Rivet_i.Rivet_iConf import Rivet_i
176  anaSeq += Rivet_i()
177  anaSeq.Rivet_i.Analyses = runArgs.rivetAnas
178  anaSeq.Rivet_i.AnalysisPath = os.environ['PWD']
179  if hasattr(runArgs, "outputYODAFile"):
180  anaSeq.Rivet_i.HistoFile = runArgs.outputYODAFile
181 
182 # in case of mc23 protect against changing run number in McEventSelector
183 rel = os.popen("echo $AtlasVersion").read()
184 rel = rel.strip()
185 if not rel or int(rel[:2]) > 22:
186  from AthenaCommon.AppMgr import ServiceMgr
187  ServiceMgr.EventSelector.EventsPerRun = int(2**63 - 1) #sys.maxint on a 64-bit machine
188 
189 
192 
193 
194 evgenLog.debug("****************** LOADING PRE-INCLUDES AND JOB CONFIG *****************")
195 
196 
197 if hasattr(runArgs, "preInclude"):
198  for fragment in runArgs.preInclude:
199  include(fragment)
200 
201 
202 if hasattr(runArgs, "preExec"):
203  evgenLog.info("Transform pre-exec")
204  for cmd in runArgs.preExec:
205  evgenLog.info(cmd)
206  exec(cmd)
207 
209  return [name for name in os.listdir(a_dir)
210  if os.path.isdir(os.path.join(a_dir, name))]
211 
212 # TODO: Explain!!!
213 def OutputTXTFile():
214  outputTXTFile = None
215  if hasattr(runArgs,"outputTXTFile"): outputTXTFile=runArgs.outputTXTFile
216  return outputTXTFile
217 
219 if len(runArgs.jobConfig) != 1:
220  evgenLog.info("runArgs.jobConfig = %s" % runArgs.jobConfig)
221  evgenLog.error("You must supply one and only one jobConfig file argument")
222  sys.exit(1)
223 
224 evgenLog.info("Using JOBOPTSEARCHPATH (as seen in skeleton) = '%s'" % os.environ["JOBOPTSEARCHPATH"])
225 FIRST_DIR = (os.environ['JOBOPTSEARCHPATH']).split(":")[0]
226 
227 jofiles = [f for f in os.listdir(FIRST_DIR) if (f.startswith('mc') and f.endswith('.py'))]
228 if len(jofiles) !=1:
229  evgenLog.error("You must supply one and only one jobOption file in DSID directory")
230  sys.exit(1)
231 jofile = jofiles[0]
232 
233 joparts = (os.path.basename(jofile)).split(".")
234 
235 officialJO = False
236 if joparts[0].startswith("mc") and all(c in string.digits for c in joparts[0][2:]):
237  officialJO = True
238 
239  if len(joparts) != 3:
240  evgenLog.error(jofile + " name format is wrong: must be of the form mc.<physicsShort>.py: please rename.")
241  sys.exit(1)
242 
243  jo_physshortpart = joparts[1]
244  max_jo_physshort_length = 50
245  if len(jo_physshortpart) > max_jo_physshort_length:
246  evgenLog.error(f"{jofile} contains a physicsShort field of more than {max_jo_physshort_length} characters: please rename.")
247  sys.exit(1)
248 
249  jo_physshortparts = jo_physshortpart.split("_")
250  if len(jo_physshortparts) < 2:
251  evgenLog.error(jofile + " has too few physicsShort fields separated by '_': should contain <generators>(_<tune+PDF_if_available>)_<process>. Please rename.")
252  sys.exit(1)
253 
254  check_jofiles="/cvmfs/atlas.cern.ch/repo/sw/Generators/MC16JobOptions/scripts/check_jo_consistency.py"
255  if os.path.exists(check_jofiles):
256  include(check_jofiles)
257  check_naming(os.path.basename(jofile))
258  else:
259  evgenLog.error("check_jo_consistency.py not found")
260  sys.exit(1)
261 
262 
263 include(jofile)
264 
265 
268 
269 
270 evgenLog.debug("****************** CHECKING EVGEN CONFIGURATION *****************")
271 
272 if hasattr(runArgs,'inputGeneratorFile') and int(evgenConfig.inputFilesPerJob) == 0 :
273  evgenConfig.inputFilesPerJob = 1
274 
275 
276 for opt in str(evgenConfig).split(os.linesep):
277  evgenLog.info(opt)
278 evgenLog.info(".transform = Gen_tf")
279 
280 
281 evgenLog.info(".platform = "+str(os.environ['BINARY_TAG']))
282 
283 
286 if evgenConfig.obsolete:
287  evgenLog.error("JOs or icludes are obsolete, please check them")
288  sys.exit(1)
289 
290 if not evgenConfig.generators:
291  evgenLog.error("No entries in evgenConfig.generators: invalid configuration, please check your JO")
292  sys.exit(1)
293 
294 if len(evgenConfig.generators) > len(set(evgenConfig.generators)):
295  evgenLog.error("Duplicate entries in evgenConfig.generators: invalid configuration, please check your JO")
296  sys.exit(1)
297 
298 gennames = sorted(evgenConfig.generators, key=gen_sortkey)
299 
300 if joparts[0].startswith("MC"): #< if this is an "official" JO
301  genpart = jo_physshortparts[0]
302  expectedgenpart = ''.join(gennames)
303 
304  expectedgenpart = expectedgenpart.replace("HerwigJimmy", "Herwig")
305  def _norm(s):
306  # TODO: add EvtGen to this normalization for MC14?
307  return s.replace("Photospp", "").replace("Photos", "").replace("TauolaPP", "").replace("Tauolapp", "").replace("Tauola", "")
308  def _norm2(s):
309  return s.replace("Py", "Pythia").replace("MG","MadGraph").replace("Ph","Powheg").replace("Hpp","Herwigpp").replace("H7","Herwig7").replace("Sh","Sherpa").replace("Ag","Alpgen").replace("EG","EvtGen").replace("PG","ParticleGun").replace("Gva","Geneva")
310 
311  def _short2(s):
312  return s.replace("Pythia","Py").replace("MadGraph","MG").replace("Powheg","Ph").replace("Herwigpp","Hpp").replace("Herwig7","H7").replace("Sherpa","Sh").replace("Alpgen","Ag").replace("EvtGen","EG").replace("PG","ParticleGun").replace("Geneva","Gva")
313 
314  if genpart != _norm(expectedgenpart) and _norm2(genpart) != _norm(expectedgenpart):
315  evgenLog.error("Expected first part of JO name to be '%s' or '%s', but found '%s'" % (_norm(expectedgenpart), _norm(_short2(expectedgenpart)), genpart))
316  evgenLog.error("gennames '%s' " %(expectedgenpart))
317  sys.exit(1)
318 
319  del _norm
320 
321  if not gens_notune(gennames) and len(jo_physshortparts) < 3:
322  evgenLog.error(jofile + " with generators " + expectedgenpart +
323  " has too few physicsShort fields separated by '_'." +
324  " It should contain <generators>_<tune+PDF_<process>. Please rename.")
325  sys.exit(1)
326 
327 
329 if gen_require_steering(gennames):
330  if hasattr(runArgs, "outputEVNTFile") and not hasattr(runArgs, "outputEVNT_PreFile"):
331  raise RuntimeError("'EvtGen' found in job options name, please set '--steering=afterburn'")
332 
333 
334 
336 rounding = 0
337 if hasattr(runArgs,'inputGeneratorFile') and ',' in runArgs.inputGeneratorFile: multiInput = runArgs.inputGeneratorFile.count(',')+1
338 else:
339  multiInput = 0
340 
341 # check if default nEventsPerJob used
342 if not evgenConfig.nEventsPerJob:
343  evgenLog.info('#############################################################')
344  evgenLog.info(' !!!! no nEventsPerJob set !!! The default 10000 used. !!! ')
345  evgenLog.info('#############################################################')
346 else:
347  evgenLog.info(' nEventsPerJob = ' + str(evgenConfig.nEventsPerJob) )
348 
349 if evgenConfig.minevents > 0 :
350  raise RuntimeError("evgenConfig.minevents is obsolete and should be removed from the JOs")
351 if evgenConfig.nEventsPerJob < 1:
352  raise RuntimeError("evgenConfig.nEventsPerJob must be at least 1")
353 elif evgenConfig.nEventsPerJob > 100000:
354  raise RuntimeError("evgenConfig.nEventsPerJob can be max. 100000")
355 else:
356  allowed_nEventsPerJob_lt1000 = [1, 2, 5, 10, 20, 25, 50, 100, 200, 500, 1000]
357  msg = "evgenConfig.nEventsPerJob = %d: " % evgenConfig.nEventsPerJob
358 
359  if evgenConfig.nEventsPerJob >= 1000 and evgenConfig.nEventsPerJob <=10000 and (evgenConfig.nEventsPerJob % 1000 != 0 or 10000 % evgenConfig.nEventsPerJob != 0):
360  msg += "nEventsPerJob in range [1K, 10K] must be a multiple of 1K and a divisor of 10K"
361  raise RuntimeError(msg)
362  elif evgenConfig.nEventsPerJob > 10000 and evgenConfig.nEventsPerJob % 10000 != 0:
363  msg += "nEventsPerJob >10K must be a multiple of 10K"
364  raise RuntimeError(msg)
365  elif evgenConfig.nEventsPerJob < 1000 and evgenConfig.nEventsPerJob not in allowed_nEventsPerJob_lt1000:
366  msg += "nEventsPerJob in range <= 1000 must be one of %s" % allowed_nEventsPerJob_lt1000
367  raise RuntimeError(msg)
368  postSeq.CountHepMC.RequestedOutput = evgenConfig.nEventsPerJob if runArgs.maxEvents == -1 else runArgs.maxEvents
369  evgenLog.info('Requested output events = '+str(postSeq.CountHepMC.RequestedOutput))
370 
371 
372 if evgenConfig.keywords:
373 
375  kwfile = "evgenkeywords.txt"
376  kwpath = None
377  for p in os.environ["DATAPATH"].split(":"):
378  kwpath = os.path.join(p, kwfile)
379  if os.path.exists(kwpath):
380  break
381  kwpath = None
382 
383  allowed_keywords = []
384  if kwpath:
385  evgenLog.info("evgenkeywords = "+kwpath)
386  kwf = open(kwpath, "r")
387  for l in kwf:
388  allowed_keywords += l.strip().lower().split()
389 
390  evil_keywords = []
391  for k in evgenConfig.keywords:
392  if k.lower() not in allowed_keywords:
393  evil_keywords.append(k)
394  if evil_keywords:
395  msg = "evgenConfig.keywords contains non-standard keywords: %s. " % ", ".join(evil_keywords)
396  msg += "Please check the allowed keywords list and fix."
397  evgenLog.error(msg)
398  if officialJO:
399  sys.exit(1)
400  else:
401  evgenLog.warning("evgenkeywords = not found ")
402 
403 
404 if evgenConfig.categories:
405 
407  lkwfile = "CategoryList.txt"
408  lkwpath = None
409  for p in os.environ["DATAPATH"].split(":"):
410  lkwpath = os.path.join(p, lkwfile)
411  if os.path.exists(lkwpath):
412  break
413  lkwpath = None
414 
415  allowed_cat = []
416  if lkwpath:
417  with open(lkwpath, 'r') as catlist:
418  for line in catlist:
419  allowed_list = ast.literal_eval(line)
420  allowed_cat.append(allowed_list)
421 
422 
423  bad_cat =[]
424  it = iter(evgenConfig.categories)
425  for x in it:
426  l1 = x
427  l2 = next(it)
428  if "L1:" in l2 and "L2:" in l1:
429  l1, l2 = l2, l1
430  print ("first",l1,"second",l2)
431  bad_cat.extend([l1, l2])
432  for a1,a2 in allowed_cat:
433  if l1.strip().lower()==a1.strip().lower() and l2.strip().lower()==a2.strip().lower():
434  bad_cat=[]
435  if bad_cat:
436  msg = "evgenConfig.categories contains non-standard category: %s. " % ", ".join(bad_cat)
437  msg += "Please check the allowed categories list and fix."
438  evgenLog.error(msg)
439  if officialJO:
440  sys.exit(1)
441  else:
442  evgenLog.warning("Could not find CategoryList.txt file %s in $DATAPATH" % lkwfile)
443 
444 if hasattr( runArgs, "outputEVNTFile") or hasattr( runArgs, "outputEVNT_PreFile"):
445 
446  from AthenaPoolCnvSvc.WriteAthenaPool import AthenaPoolOutputStream
447  from AthenaPoolCnvSvc.AthenaPoolCnvSvcConf import AthenaPoolCnvSvc
448  # remove because it was removed from Database/AthenaPOOL/AthenaPoolCnvSvc
449  #svcMgr.AthenaPoolCnvSvc.CommitInterval = 10 #< tweak for MC needs
450  if hasattr(runArgs, "outputEVNTFile"):
451  poolFile = runArgs.outputEVNTFile
452  elif hasattr(runArgs, "outputEVNT_PreFile"):
453  poolFile = runArgs.outputEVNT_PreFile
454  else:
455  raise RuntimeError("Output pool file, either EVNT or EVNT_Pre, is not known.")
456 
457  StreamEVGEN = AthenaPoolOutputStream("StreamEVGEN", poolFile, noTag=True, eventInfoKey="EventInfo")
458 
459  StreamEVGEN.ForceRead = True
460  StreamEVGEN.ItemList += ["EventInfo#*", "xAOD::EventInfo#EventInfo*", "xAOD::EventAuxInfo#EventInfoAux.*", "McEventCollection#*"]
461  StreamEVGEN.RequireAlgs += ["EvgenFilterSeq"]
462 
463  if evgenConfig.saveJets:
464  StreamEVGEN.ItemList += ["xAOD::JetContainer#AntiKt4TruthJets", "xAOD::AuxContainerBase!#AntiKt4TruthJetsAux.-PseudoJet.-constituentLinks.-constituentWeights"]
465  StreamEVGEN.ItemList += ["xAOD::JetContainer#AntiKt6TruthJets", "xAOD::AuxContainerBase!#AntiKt6TruthJetsAux.-PseudoJet.-constituentLinks.-constituentWeights"]
466  if evgenConfig.savePileupTruthParticles:
467  StreamEVGEN.ItemList += ["xAOD::TruthParticleContainer#TruthPileupParticles*"]
468  StreamEVGEN.ItemList += ["xAOD::TruthParticleAuxContainer#TruthPileupParticlesAux.*"]
469 
470  # Remove any requested items from the ItemList so as not to write out
471  for removeItem in evgenConfig.doNotSaveItems: StreamEVGEN.ItemList.remove( removeItem )
472 
473  # Allow (re-)addition to the output stream
474  for addItem in evgenConfig.extraSaveItems: StreamEVGEN.ItemList += [ addItem ]
475 
476 
477 dsid = os.path.basename(runArgs.jobConfig[0])
478 if not dsid.isdigit():
479  dsid = "999999"
480 svcMgr.EventSelector.RunNumber = int(dsid)
481 
482 
483 from GeneratorConfig.Versioning import generatorsGetInitialVersionedDictionary, generatorsVersionedStringList
485 gennamesvers = generatorsVersionedStringList(gendict)
486 
487 import EventInfoMgt.EventInfoMgtInit
488 svcMgr.TagInfoMgr.ExtraTagValuePairs.update({"hepmc_version": "HepMC" + str(os.environ['HEPMCVER'])})
489 svcMgr.TagInfoMgr.ExtraTagValuePairs.update({"mc_channel_number":str(dsid)})
490 svcMgr.TagInfoMgr.ExtraTagValuePairs.update({"lhefGenerator": '+'.join( filter( gen_lhef, gennames ) ) })
491 svcMgr.TagInfoMgr.ExtraTagValuePairs.update({"generators": '+'.join(gennamesvers)})
492 svcMgr.TagInfoMgr.ExtraTagValuePairs.update({"evgenProcess": evgenConfig.process})
493 svcMgr.TagInfoMgr.ExtraTagValuePairs.update({"evgenTune": evgenConfig.tune})
494 if hasattr( evgenConfig, "hardPDF" ) : svcMgr.TagInfoMgr.ExtraTagValuePairs.update({"hardPDF": evgenConfig.hardPDF})
495 if hasattr( evgenConfig, "softPDF" ) : svcMgr.TagInfoMgr.ExtraTagValuePairs.update({"softPDF": evgenConfig.softPDF})
496 if hasattr( runArgs, "randomSeed") : svcMgr.TagInfoMgr.ExtraTagValuePairs.update({"randomSeed": str(runArgs.randomSeed)})
497 svcMgr.TagInfoMgr.ExtraTagValuePairs.update({"keywords": ", ".join(evgenConfig.keywords).lower()})
498 
499 # print version of HepMC to the log
500 evgenLog.info("HepMC version " + str(os.environ['HEPMCVER']))
501 
502 # Set AMITag in in-file metadata
503 from PyUtils import AMITagHelper
504 AMITagHelper.SetAMITag(runArgs=runArgs)
505 
506 
507 svcMgr.TagInfoMgr.ExtraTagValuePairs.update({"beam_energy": str(int(runArgs.ecmEnergy*Units.GeV/2.0))})
508 svcMgr.TagInfoMgr.ExtraTagValuePairs.update({"beam_type": 'collisions'})
509 
510 
512 include("EvgenJobTransforms/Generate_ecmenergies.py")
513 
514 if 'ParticleGun' in evgenConfig.generators:
515 
516  from RngComps.RngCompsConf import AtRndmGenSvc
517  svcMgr += AtRndmGenSvc()
518  include("EvgenJobTransforms/Generate_randomseeds.py")
519 else:
520 # Propagate DSID and seed to the generators
521  include("EvgenJobTransforms/Generate_dsid_ranseed.py")
522 
523 
524 if (hasattr( runArgs, "VERBOSE") and runArgs.VERBOSE ) or (hasattr( runArgs, "loglevel") and runArgs.loglevel == "DEBUG") or (hasattr( runArgs, "loglevel") and runArgs.loglevel == "VERBOSE"):
525  include("EvgenJobTransforms/Generate_debug_level.py")
526 
527 
528 svcMgr.TagInfoMgr.ExtraTagValuePairs.update({"specialConfiguration": evgenConfig.specialConfig })
529 
530 
532 if hasattr(testSeq, "TestHepMC") and not gens_testhepmc(evgenConfig.generators):
533  evgenLog.info("Removing TestHepMC sanity checker")
534  del testSeq.TestHepMC
535 
536 
540 def checkBlackList(relFlavour,cache,generatorName) :
541  isError = None
542  with open('/cvmfs/atlas.cern.ch/repo/sw/Generators/MC16JobOptions/common/BlackList_caches.txt') as bfile:
543  for line in bfile.readlines():
544  if not line.strip():
545  continue
546  # Blacklisted release flavours
547  badRelFlav=line.split(',')[0].strip()
548  # Blacklisted caches
549  badCache=line.split(',')[1].strip()
550  # Blacklisted generators
551  badGens=line.split(',')[2].strip()
552 
553  used_gens = ','.join(generatorName)
554  #Match Generator and release type e.g. AtlasProduction, MCProd
555  if relFlavour==badRelFlav and cache==badCache and re.search(badGens,used_gens) is not None:
556  if badGens=="": badGens="all generators"
557  isError=relFlavour+","+cache+" is blacklisted for " + badGens
558  return isError
559  return isError
560 
561 def checkPurpleList(relFlavour,cache,generatorName) :
562  isError = None
563  with open('/cvmfs/atlas.cern.ch/repo/sw/Generators/MC16JobOptions/common/PurpleList_generators.txt') as bfile:
564  for line in bfile.readlines():
565  if not line.strip():
566  continue
567  # Purple-listed release flavours
568  purpleRelFlav=line.split(',')[0].strip()
569  # Purple-listed caches
570  purpleCache=line.split(',')[1].strip()
571  # Purple-listed generators
572  purpleGens=line.split(',')[2].strip()
573  # Purple-listed process
574  purpleProcess=line.split(',')[3].strip()
575 
576  used_gens = ','.join(generatorName)
577  #Match Generator and release type e.g. AtlasProduction, MCProd
578  if relFlavour==purpleRelFlav and cache==purpleCache and re.search(purpleGens,used_gens) is not None:
579  isError=relFlavour+","+cache+" is blacklisted for " + purpleGens + " if it uses " + purpleProcess
580  return isError
581  return isError
582 
583 
584 evgenLog.debug("****************** CHECKING RELEASE IS NOT BLACKLISTED *****************")
585 errorBL = checkBlackList("AthGeneration",rel,gennames)
586 if (errorBL):
587  if (hasattr( runArgs, "ignoreBlackList") and runArgs.ignoreBlackList):
588  evgenLog.warning("This run is blacklisted for this generator, please use a different one for production !! "+ errorBL )
589  else:
590  raise RuntimeError("This run is blacklisted for this generator, please use a different one !! "+ errorBL)
591 
592 errorPL = checkPurpleList("AthGeneration",rel,gennames)
593 if (errorPL):
594  evgenLog.warning("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
595  evgenLog.warning("!!! WARNING !!! "+ errorPL )
596  evgenLog.warning("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
597 
598 
601 
602 if hasattr(runArgs, "postInclude"):
603  for fragment in runArgs.postInclude:
604  include(fragment)
605 
606 if hasattr(runArgs, "postExec"):
607  evgenLog.info("Transform post-exec")
608  for cmd in runArgs.postExec:
609  evgenLog.info(cmd)
610  exec(cmd)
611 
612 
613 
616 acas.dumpMasterSequence()
617 
618 
619 
622 
623 
624 evgenLog.debug("****************** HANDLING EVGEN INPUT FILES *****************")
625 
626 
627 datFile = None
628 if "McAtNlo" in evgenConfig.generators and "Herwig" in evgenConfig.generators:
629  datFile = "inparmMcAtNlo.dat"
630 elif "Alpgen" in evgenConfig.generators:
631  datFile = "inparmAlpGen.dat"
632 elif "Protos" in evgenConfig.generators:
633  datFile = "protos.dat"
634 elif "ProtosLHEF" in evgenConfig.generators:
635  datFile = "protoslhef.dat"
636 elif "AcerMC" in evgenConfig.generators:
637  datFile = "inparmAcerMC.dat"
638 elif "CompHep" in evgenConfig.generators:
639  datFile = "inparmCompHep.dat"
640 
641 
642 eventsFile = None
643 if "Alpgen" in evgenConfig.generators:
644  eventsFile = "alpgen.unw_events"
645 elif "Protos" in evgenConfig.generators:
646  eventsFile = "protos.events"
647 elif "ProtosLHEF" in evgenConfig.generators:
648  eventsFile = "protoslhef.events"
649 elif "BeamHaloGenerator" in evgenConfig.generators:
650  eventsFile = "beamhalogen.events"
651 elif "HepMCAscii" in evgenConfig.generators:
652  eventsFile = "events.hepmc"
653 elif "ReadMcAscii" in evgenConfig.generators:
654  eventsFile = "events.hepmc"
655 elif gens_lhef(evgenConfig.generators):
656  eventsFile = "events.lhe"
657 
658 
659 
660 def find_unique_file(pattern):
661  "Return a matching file, provided it is unique"
662  import glob
663  files = glob.glob(pattern)
664 
665  if not files:
666  raise RuntimeError("No '%s' file found" % pattern)
667  elif len(files) > 1:
668  raise RuntimeError("More than one '%s' file found" % pattern)
669  return files[0]
670 
671 # This function merges a list of input LHE file to make one outputFile. The header is taken from the first
672 # file, but the number of events is updated to equal the total number of events in all the input files
673 def merge_lhe_files(listOfFiles,outputFile):
674  if(os.path.exists(outputFile)):
675  print ("outputFile ",outputFile," already exists. Will rename to ",outputFile,".OLD")
676  os.rename(outputFile,outputFile+".OLD")
677  output = open(outputFile,'w')
678  holdHeader = ""
679  nevents=0
680  for file in listOfFiles:
681  cmd = "grep /event "+file+" | wc -l"
682  nevents+=int(subprocess.check_output(cmd,stderr=subprocess.STDOUT,shell=True))
683 
684  for file in listOfFiles:
685  inHeader = True
686  header = ""
687  print ("*** Starting file ",file)
688  for line in open(file,"r"):
689 
694  if("<event" in line and inHeader):
695  inHeader = False
696  if(len(holdHeader)<1):
697  holdHeader = header
698  output.write(header)
699  output.write(line)
700 
702  elif(not inHeader and not ("</LesHouchesEvents>" in line)):
703  output.write(line)
704  if(inHeader):
705 
706  if("nevents" in line):
707 
708  tmp = line.split("=")
709  line = line.replace(tmp[0],str(nevents))
710  elif("numevts" in line):
711 
712  tmp = line.split(" ")
713  nnn = str(nevents)
714  line = line.replace(tmp[1],nnn)
715  header+=line
716  output.write("</LesHouchesEvents>\n")
717  output.close()
718 
719 
720 def mk_symlink(srcfile, dstfile):
721  "Make a symlink safely"
722  if dstfile:
723  if os.path.exists(dstfile) and not os.path.samefile(dstfile, srcfile):
724  os.remove(dstfile)
725  if not os.path.exists(dstfile):
726  evgenLog.info("Symlinking %s to %s" % (srcfile, dstfile))
727  print ("Symlinking %s to %s" % (srcfile, dstfile))
728  os.symlink(srcfile, dstfile)
729  else:
730  evgenLog.debug("Symlinking: %s is already the same as %s" % (dstfile, srcfile))
731 
732 
733 if eventsFile or datFile:
734  if not hasattr(runArgs, "inputGeneratorFile") or runArgs.inputGeneratorFile == "NONE":
735  raise RuntimeError("%s needs input file (argument inputGeneratorFile)" % runArgs.jobConfig)
736  if evgenConfig.inputfilecheck and not re.search(evgenConfig.inputfilecheck, runArgs.inputGeneratorFile):
737  raise RuntimeError("inputGeneratorFile=%s is incompatible with inputfilecheck '%s' in %s" %
738  (runArgs.inputGeneratorFile, evgenConfig.inputfilecheck, runArgs.jobConfig))
739  if datFile:
740  if ".tar" in os.path.basename(runArgs.inputGeneratorFile):
741  inputroot = os.path.basename(runArgs.inputGeneratorFile).split(".tar.")[0]
742  else:
743  inputroot = os.path.basename(runArgs.inputGeneratorFile).split("._")[0]
744 
745  realDatFile = find_unique_file('*%s*.dat' % inputroot)
746  mk_symlink(realDatFile, datFile)
747  if eventsFile:
748  myinputfiles = runArgs.inputGeneratorFile
749  genInputFiles = myinputfiles.split(',')
750  numberOfFiles = len(genInputFiles)
751  # if there is a single file, make a symlink. If multiple files, merge them into one output eventsFile
752  if(numberOfFiles<2):
753  if ".tar" in os.path.basename(runArgs.inputGeneratorFile):
754  inputroot = os.path.basename(runArgs.inputGeneratorFile).split(".tar.")[0]
755  else:
756  inputroot = os.path.basename(runArgs.inputGeneratorFile).split("._")[0]
757 
758  if "events" in inputroot :
759  inputroot = inputroot.replace(".events","")
760  realEventsFile = find_unique_file('*%s.*ev*ts' % inputroot)
761  mk_symlink(realEventsFile, eventsFile)
762  else:
763  allFiles = []
764  for file in genInputFiles:
765 # Since we can have multiple files from the same task, inputroot must include more of the filename
766 # to make it unique
767  if ".tar" in os.path.basename(runArgs.inputGeneratorFile):
768  inputroot = os.path.basename(runArgs.inputGeneratorFile).split(".tar.")[0]
769  else:
770  input0 = os.path.basename(file).split("._")[0]
771  input1 = (os.path.basename(file).split("._")[1]).split(".")[0]
772  inputroot = input0+"._"+input1
773  evgenLog.info("inputroot = ",inputroot)
774  realEventsFile = find_unique_file('*%s.*ev*ts' % inputroot)
775 # The only input format where merging is permitted is LHE
776  with open(realEventsFile, 'r') as f:
777  first_line = f.readline()
778  if(not ("LesHouche" in first_line)):
779  raise RuntimeError("%s is NOT a LesHouche file" % realEventsFile)
780  allFiles.append(realEventsFile)
781  merge_lhe_files(allFiles,eventsFile)
782 
783 else:
784  if hasattr(runArgs, "inputGeneratorFile") and runArgs.inputGeneratorFile != "NONE":
785  raise RuntimeError("inputGeneratorFile arg specified for %s, but generators %s do not require an input file" %
786  (runArgs.jobConfig, str(gennames)))
787  if evgenConfig.inputfilecheck:
788  raise RuntimeError("evgenConfig.inputfilecheck specified in %s, but generators %s do not require an input file" %
789  (runArgs.jobConfig, str(gennames)))
790 
791 
792 if evgenConfig.auxfiles:
793  from PyJobTransformsCore.trfutil import get_files
794  get_files(evgenConfig.auxfiles, keepDir=False, errorIfNotFound=True)
795 
796 
797 
800 
801 def _checkattr(attr, required=False):
802  if not hasattr(evgenConfig, attr) or not getattr(evgenConfig, attr):
803  msg = "evgenConfig attribute '%s' not found." % attr
804  if required:
805  raise RuntimeError("Required " + msg)
806  return False
807  return True
808 
809 if hasattr(runArgs, "outputTXTFile"):
810  # counting the number of events in LHE output
811  count_ev = 0
812  with open(eventsFile) as f:
813  for line in f:
814  count_ev += line.count('/event')
815 
816  print("MetaData: %s = %s" % ("Number of produced LHE events ", count_ev))
817 elif hasattr(runArgs, "inputGeneratorFile"):
818  # counting the number of events in LHE input
819  count_ev = 0
820  with open(eventsFile) as f:
821  for line in f:
822  count_ev += line.count('/event')
823 
824  print("MetaData: %s = %s" % ("Number of input LHE events ", count_ev))
825 
826 
827 if _checkattr("description", required=True):
828  msg = evgenConfig.description
829  if _checkattr("notes"):
830  msg += " " + evgenConfig.notes
831  print ("MetaData: %s = %s" % ("physicsComment", msg))
832 
833 if _checkattr("generators", required=True):
834  print ("MetaData: %s = %s" % ("generatorName", "+".join(gennamesvers)))
835 if _checkattr("process"):
836  print ("MetaData: %s = %s" % ("physicsProcess", evgenConfig.process))
837 if _checkattr("tune"):
838  print ("MetaData: %s = %s" % ("generatorTune", evgenConfig.tune))
839 if _checkattr("hardPDF"):
840  print ("MetaData: %s = %s" % ("hardPDF", evgenConfig.hardPDF))
841 if _checkattr("softPDF"):
842  print ("MetaData: %s = %s" % ("softPDF", evgenConfig.softPDF))
843 if _checkattr("nEventsPerJob"):
844  print ("MetaData: %s = %s" % ("nEventsPerJob", evgenConfig.nEventsPerJob))
845 if _checkattr("keywords"):
846  print ("MetaData: %s = %s" % ("keywords", ", ".join(evgenConfig.keywords).lower()))
847 if _checkattr("categories"):
848  print ("MetaData: %s = %s" % ("categories", ", ".join(evgenConfig.categories)))
849 if _checkattr("specialConfig"):
850  print ("MetaData: %s = %s" % ("specialConfig", evgenConfig.specialConfig))
851 # TODO: Require that a contact / JO author is always set
852 if _checkattr("contact"):
853  print ("MetaData: %s = %s" % ("contactPhysicist", ", ".join(evgenConfig.contact)))
854 print ("MetaData: %s = %s" % ("randomSeed", str(runArgs.randomSeed)))
855 
856 # Output list of generator filters used
857 filterNames = [alg.getType() for alg in acas.iter_algseq(filtSeq)]
858 excludedNames = ['AthSequencer', 'PyAthena::Alg', 'TestHepMC']
859 filterNames = list(set(filterNames) - set(excludedNames))
860 print ("MetaData: %s = %s" % ("genFilterNames", ", ".join(filterNames)))
861 
862 
863 
866 
867 from PyJobTransformsCore.runargs import RunArguments
868 runPars = RunArguments()
869 runPars.nEventsPerJob = evgenConfig.nEventsPerJob
870 runPars.maxeventsstrategy = evgenConfig.maxeventsstrategy
871 with open("config.pickle", "wb") as f:
872  import pickle
873  pickle.dump(runPars, f)
874 
875 
876 
879 evgenLog.info("****************** STARTING EVENT GENERATION *****************")
read
IovVectorMap_t read(const Folder &theFolder, const SelectionCriterion &choice, const unsigned int limit=10)
Definition: openCoraCool.cxx:569
replace
std::string replace(std::string s, const std::string &s2, const std::string &s3)
Definition: hcg.cxx:307
python.GenConfigHelpers.gens_testhepmc
def gens_testhepmc(gennames)
Definition: GenConfigHelpers.py:76
skel.find_unique_file
def find_unique_file(pattern)
Helper functions for input file handling.
Definition: skel.ABtoEVGEN.py:489
RngCompsConfig.AtRndmGenSvc
AtRndmGenSvc
Definition: RngCompsConfig.py:9
Logging
trfutil
skel.merge_lhe_files
def merge_lhe_files(listOfFiles, outputFile)
Check that there is exactly 1 match.
Definition: skel.GENtoEVGEN.py:673
Cut::all
@ all
Definition: SUSYToolsAlg.cxx:64
covarianceTool.filter
filter
Definition: covarianceTool.py:514
skel.OutputTXTFile
def OutputTXTFile()
==============================================================
Definition: skel.ABtoEVGEN.py:182
find_unique_file
Definition: find_unique_file.py:1
fillPileUpNoiseLumi.next
next
Definition: fillPileUpNoiseLumi.py:53
skel.checkBlackList
def checkBlackList(relFlavour, cache, generatorName)
Propagate debug output level requirement to generators.
Definition: skel.GENtoEVGEN.py:540
LArG4FSStartPointFilter.exec
exec
Definition: LArG4FSStartPointFilter.py:103
python.GenConfigHelpers.gen_require_steering
def gen_require_steering(gennames)
Definition: GenConfigHelpers.py:49
LogicalExpressionFilter
Definition: LogicalExpressionFilter.py:1
python.Versioning.generatorsGetInitialVersionedDictionary
def generatorsGetInitialVersionedDictionary(generators)
Definition: Versioning.py:25
python.GenConfigHelpers.gens_notune
def gens_notune(gennames)
Definition: GenConfigHelpers.py:84
skel._short2
def _short2(s)
Definition: skel.ABtoEVGEN.py:273
python.GenConfigHelpers.gens_lhef
def gens_lhef(gennames)
Definition: GenConfigHelpers.py:68
RngCompsConfig.AthRNGSvc
AthRNGSvc
Definition: RngCompsConfig.py:9
python.Include.include
include
Definition: Include.py:319
DerivationFramework::TriggerMatchingUtils::sorted
std::vector< typename T::value_type > sorted(T begin, T end)
Helper function to create a sorted vector from an unsorted one.
merge_lhe_files
Definition: merge_lhe_files.py:1
CxxUtils::set
constexpr std::enable_if_t< is_bitmask_v< E >, E & > set(E &lhs, E rhs)
Convenience function to set bits in a class enum bitmask.
Definition: bitmask.h:224
TCS::join
std::string join(const std::vector< std::string > &v, const char c=',')
Definition: Trigger/TrigT1/L1Topo/L1TopoCommon/Root/StringUtils.cxx:10
skel._norm
def _norm(s)
Definition: skel.ABtoEVGEN.py:267
skel.checkPurpleList
def checkPurpleList(relFlavour, cache, generatorName)
Definition: skel.GENtoEVGEN.py:561
python.Versioning.generatorsVersionedStringList
def generatorsVersionedStringList(generatorsDictionary)
Definition: Versioning.py:44
Lb2Lll.THistSvc
THistSvc
Definition: Lb2Lll.py:216
skel.get_immediate_subdirectories
def get_immediate_subdirectories(a_dir)
==============================================================
Definition: skel.GENtoEVGEN.py:208
Trk::open
@ open
Definition: BinningType.h:40
skel._checkattr
def _checkattr(attr, required=False)
==============================================================
Definition: skel.ABtoEVGEN.py:522
skel.mk_symlink
def mk_symlink(srcfile, dstfile)
Definition: skel.ABtoEVGEN.py:500
readCCLHist.int
int
Definition: readCCLHist.py:84
python.KeyStore.list
def list(self, key=None)
Definition: KeyStore.py:318
Muon::print
std::string print(const MuPatSegment &)
Definition: MuonTrackSteering.cxx:28
if
if(febId1==febId2)
Definition: LArRodBlockPhysicsV0.cxx:569
skel._norm2
def _norm2(s)
Definition: skel.ABtoEVGEN.py:270
str
Definition: BTagTrackIpAccessor.cxx:11
python.CreateOutputStreams.AthenaPoolOutputStream
def AthenaPoolOutputStream
backward compat
Definition: CreateOutputStreams.py:144
python.trfutil.get_files
def get_files(listOfFiles, fromWhere='data', doCopy='ifNotLocal', errorIfNotFound=True, keepDir=True, depth=0, sep=os.pathsep)
Definition: trfutil.py:40
Trk::split
@ split
Definition: LayerMaterialProperties.h:38