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