Loading [MathJax]/extensions/tex2jax.js
ATLAS Offline Software
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
skel.GENtoEVGEN.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2025 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  if "P8B" in s:
309  return s.replace("P8B","Pythia8B").replace("MG","MadGraph").replace("Ph","Powheg").replace("Ag","Alpgen").replace("EG","EvtGen")
310  else:
311  return s.replace("Py","Pythia").replace("MG","MadGraph").replace("Ph","Powheg").replace("H7","Herwig7").replace("Sh","Sherpa").replace("Ag","Alpgen").replace("EG","EvtGen").replace("PG","ParticleGun").replace("HepMC","HepMCAscii")
312  def _short2(s):
313  if "Pythia8B" in s:
314  return s.replace("Pythia8B","P8B").replace("MadGraph","MG").replace("Powheg","Ph").replace("Herwig7","H7").replace("Sherpa","Sh").replace("Alpgen","Ag").replace("EvtGen","EG").replace("PG","ParticleGun")
315  else:
316  return s.replace("Pythia","Py").replace("MadGraph","MG").replace("Powheg","Ph").replace("Herwigpp","Hpp").replace("Sherpa","Sh").replace("Alpgen","Ag").replace("EvtGen","EG").replace("PG","ParticleGun").replace("HepMCAscii","HepMC")
317 
318  if genpart != _norm(expectedgenpart) and _norm2(genpart) != _norm(expectedgenpart):
319  evgenLog.error("Expected first part of JO name to be '%s' or '%s', but found '%s'" % (_norm(expectedgenpart), _norm(_short2(expectedgenpart)), genpart))
320  evgenLog.error("gennames '%s' " %(expectedgenpart))
321  sys.exit(1)
322 
323  del _norm
324 
325  if not gens_notune(gennames) and len(jo_physshortparts) < 3:
326  evgenLog.error(jofile + " with generators " + expectedgenpart +
327  " has too few physicsShort fields separated by '_'." +
328  " It should contain <generators>_<tune+PDF_<process>. Please rename.")
329  sys.exit(1)
330 
331 
333 if gen_require_steering(gennames):
334  if hasattr(runArgs, "outputEVNTFile") and not hasattr(runArgs, "outputEVNT_PreFile"):
335  raise RuntimeError("'EvtGen' found in job options name, please set '--steering=afterburn'")
336 
337 
338 
340 rounding = 0
341 if hasattr(runArgs,'inputGeneratorFile') and ',' in runArgs.inputGeneratorFile: multiInput = runArgs.inputGeneratorFile.count(',')+1
342 else:
343  multiInput = 0
344 
345 # check if default nEventsPerJob used
346 if not evgenConfig.nEventsPerJob:
347  evgenLog.info('#############################################################')
348  evgenLog.info(' !!!! no nEventsPerJob set !!! The default 10000 used. !!! ')
349  evgenLog.info('#############################################################')
350 else:
351  evgenLog.info(' nEventsPerJob = ' + str(evgenConfig.nEventsPerJob) )
352 
353 if evgenConfig.minevents > 0 :
354  raise RuntimeError("evgenConfig.minevents is obsolete and should be removed from the JOs")
355 if evgenConfig.nEventsPerJob < 1:
356  raise RuntimeError("evgenConfig.nEventsPerJob must be at least 1")
357 elif evgenConfig.nEventsPerJob > 100000:
358  raise RuntimeError("evgenConfig.nEventsPerJob can be max. 100000")
359 else:
360  allowed_nEventsPerJob_lt1000 = [1, 2, 5, 10, 20, 25, 50, 100, 200, 500, 1000]
361  msg = "evgenConfig.nEventsPerJob = %d: " % evgenConfig.nEventsPerJob
362 
363  if evgenConfig.nEventsPerJob >= 1000 and evgenConfig.nEventsPerJob <=10000 and (evgenConfig.nEventsPerJob % 1000 != 0 or 10000 % evgenConfig.nEventsPerJob != 0):
364  msg += "nEventsPerJob in range [1K, 10K] must be a multiple of 1K and a divisor of 10K"
365  raise RuntimeError(msg)
366  elif evgenConfig.nEventsPerJob > 10000 and evgenConfig.nEventsPerJob % 10000 != 0:
367  msg += "nEventsPerJob >10K must be a multiple of 10K"
368  raise RuntimeError(msg)
369  elif evgenConfig.nEventsPerJob < 1000 and evgenConfig.nEventsPerJob not in allowed_nEventsPerJob_lt1000:
370  msg += "nEventsPerJob in range <= 1000 must be one of %s" % allowed_nEventsPerJob_lt1000
371  raise RuntimeError(msg)
372  postSeq.CountHepMC.RequestedOutput = evgenConfig.nEventsPerJob if runArgs.maxEvents == -1 else runArgs.maxEvents
373  evgenLog.info('Requested output events = '+str(postSeq.CountHepMC.RequestedOutput))
374 
375  # Special case of N<100: adjust TestHepMC. We will allow _one_ event to fail the checks.
376  # This means the minimum efficiency is N/N+1 for N generated events. Note that if N<100,
377  # each failed event costs us more than 1% of efficiency.
378  if hasattr(testSeq, "TestHepMC") and postSeq.CountHepMC.RequestedOutput<100:
379  testSeq.TestHepMC.EffFailThreshold = postSeq.CountHepMC.RequestedOutput/(postSeq.CountHepMC.RequestedOutput+1) - 0.01
380 
381 
382 if evgenConfig.keywords:
383  from GeneratorConfig.GenConfigHelpers import checkKeywords
384  checkKeywords(evgenConfig, evgenLog, officialJO)
385 
386 
387 if evgenConfig.categories:
388 
390  lkwfile = "CategoryList.txt"
391  lkwpath = None
392  for p in os.environ["DATAPATH"].split(":"):
393  lkwpath = os.path.join(p, lkwfile)
394  if os.path.exists(lkwpath):
395  break
396  lkwpath = None
397 
398  allowed_cat = []
399  if lkwpath:
400  with open(lkwpath, 'r') as catlist:
401  for line in catlist:
402  allowed_list = ast.literal_eval(line)
403  allowed_cat.append(allowed_list)
404 
405 
406  bad_cat =[]
407  it = iter(evgenConfig.categories)
408  for x in it:
409  l1 = x
410  l2 = next(it)
411  if "L1:" in l2 and "L2:" in l1:
412  l1, l2 = l2, l1
413  print ("first",l1,"second",l2)
414  bad_cat.extend([l1, l2])
415  for a1,a2 in allowed_cat:
416  if l1.strip().lower()==a1.strip().lower() and l2.strip().lower()==a2.strip().lower():
417  bad_cat=[]
418  if bad_cat:
419  msg = "evgenConfig.categories contains non-standard category: %s. " % ", ".join(bad_cat)
420  msg += "Please check the allowed categories list and fix."
421  evgenLog.error(msg)
422  if officialJO:
423  sys.exit(1)
424  else:
425  evgenLog.warning("Could not find CategoryList.txt file %s in $DATAPATH" % lkwfile)
426 
427 if hasattr( runArgs, "outputEVNTFile") or hasattr( runArgs, "outputEVNT_PreFile"):
428 
429  from AthenaPoolCnvSvc.WriteAthenaPool import AthenaPoolOutputStream
430  from AthenaPoolCnvSvc.AthenaPoolCnvSvcConf import AthenaPoolCnvSvc
431  if hasattr(runArgs, "outputEVNTFile"):
432  poolFile = runArgs.outputEVNTFile
433  elif hasattr(runArgs, "outputEVNT_PreFile"):
434  poolFile = runArgs.outputEVNT_PreFile
435  else:
436  raise RuntimeError("Output pool file, either EVNT or EVNT_Pre, is not known.")
437 
438  # ROOT inadvertently broke forward compatibility in v6.30+ (see root/issues/15964)
439  # This workaround is needed so that older releases can read files created by the new ones
440  # For more information see ATEAM-1001 and ATEAM-1015 (for DataHeaderForm)
441  svcMgr.AthenaPoolCnvSvc.PoolAttributes += [ f"DatabaseName = '{poolFile}'; FILEFORWARD_COMPATIBILITY = '1'" ]
442  svcMgr.AthenaPoolCnvSvc.OneDataHeaderForm = False
443 
444  StreamEVGEN = AthenaPoolOutputStream("StreamEVGEN", poolFile, noTag=True, eventInfoKey="EventInfo")
445 
446  StreamEVGEN.ForceRead = True
447  StreamEVGEN.ItemList += ["EventInfo#*", "xAOD::EventInfo#EventInfo*", "xAOD::EventAuxInfo#EventInfoAux.*", "McEventCollection#*"]
448  StreamEVGEN.RequireAlgs += ["EvgenFilterSeq"]
449 
450  if evgenConfig.saveJets:
451  StreamEVGEN.ItemList += ["xAOD::JetContainer#AntiKt4TruthJets", "xAOD::AuxContainerBase!#AntiKt4TruthJetsAux.-PseudoJet.-constituentLinks.-constituentWeights"]
452  StreamEVGEN.ItemList += ["xAOD::JetContainer#AntiKt6TruthJets", "xAOD::AuxContainerBase!#AntiKt6TruthJetsAux.-PseudoJet.-constituentLinks.-constituentWeights"]
453  if evgenConfig.savePileupTruthParticles:
454  StreamEVGEN.ItemList += ["xAOD::TruthParticleContainer#TruthPileupParticles*"]
455  StreamEVGEN.ItemList += ["xAOD::TruthParticleAuxContainer#TruthPileupParticlesAux.*"]
456 
457  # Remove any requested items from the ItemList so as not to write out
458  for removeItem in evgenConfig.doNotSaveItems: StreamEVGEN.ItemList.remove( removeItem )
459 
460  # Allow (re-)addition to the output stream
461  for addItem in evgenConfig.extraSaveItems: StreamEVGEN.ItemList += [ addItem ]
462 
463 
464 dsid = os.path.basename(runArgs.jobConfig[0])
465 if not dsid.isdigit():
466  dsid = "999999"
467 svcMgr.EventSelector.RunNumber = int(dsid)
468 
469 
470 from GeneratorConfig.Versioning import generatorsGetInitialVersionedDictionary, generatorsVersionedStringList
472 gennamesvers = generatorsVersionedStringList(gendict)
473 
474 import EventInfoMgt.EventInfoMgtInit
475 svcMgr.TagInfoMgr.ExtraTagValuePairs.update({"hepmc_version": "HepMC" + str(os.environ['HEPMCVER'])})
476 svcMgr.TagInfoMgr.ExtraTagValuePairs.update({"mc_channel_number":str(dsid)})
477 svcMgr.TagInfoMgr.ExtraTagValuePairs.update({"lhefGenerator": '+'.join( filter( gen_lhef, gennames ) ) })
478 svcMgr.TagInfoMgr.ExtraTagValuePairs.update({"generators": '+'.join(gennamesvers)})
479 svcMgr.TagInfoMgr.ExtraTagValuePairs.update({"evgenProcess": evgenConfig.process})
480 svcMgr.TagInfoMgr.ExtraTagValuePairs.update({"evgenTune": evgenConfig.tune})
481 if hasattr( evgenConfig, "hardPDF" ) : svcMgr.TagInfoMgr.ExtraTagValuePairs.update({"hardPDF": evgenConfig.hardPDF})
482 if hasattr( evgenConfig, "softPDF" ) : svcMgr.TagInfoMgr.ExtraTagValuePairs.update({"softPDF": evgenConfig.softPDF})
483 if hasattr( runArgs, "randomSeed") : svcMgr.TagInfoMgr.ExtraTagValuePairs.update({"randomSeed": str(runArgs.randomSeed)})
484 svcMgr.TagInfoMgr.ExtraTagValuePairs.update({"keywords": ", ".join(evgenConfig.keywords).lower()})
485 
486 # print version of HepMC to the log
487 evgenLog.info("HepMC version " + str(os.environ['HEPMCVER']))
488 
489 # Set AMITag in in-file metadata
490 from PyUtils import AMITagHelper
491 AMITagHelper.SetAMITag(runArgs=runArgs)
492 
493 
494 svcMgr.TagInfoMgr.ExtraTagValuePairs.update({"beam_energy": str(int(runArgs.ecmEnergy*Units.GeV/2.0))})
495 svcMgr.TagInfoMgr.ExtraTagValuePairs.update({"beam_type": 'collisions'})
496 
497 
498 from OutputStreamAthenaPool.OutputStreamAthenaPoolConf import CopyEventStreamInfo
499 streamInfoTool = CopyEventStreamInfo( "StreamEVGEN_CopyEventStreamInfo" )
500 ToolSvc += streamInfoTool
501 svcMgr.MetaDataSvc.MetaDataTools += [ streamInfoTool ]
502 
503 
505 include("EvgenJobTransforms/Generate_ecmenergies.py")
506 
507 if 'ParticleGun' in evgenConfig.generators:
508 
509  from RngComps.RngCompsConf import AtRndmGenSvc
510  svcMgr += AtRndmGenSvc()
511  include("EvgenJobTransforms/Generate_randomseeds.py")
512 else:
513 # Propagate DSID and seed to the generators
514  include("EvgenJobTransforms/Generate_dsid_ranseed.py")
515 
516 
517 if 'Hijing' in evgenConfig.generators:
518  fixSeq.FixHepMC.PurgeUnstableWithoutEndVtx = True
519 
520 
521 if (hasattr( runArgs, "VERBOSE") and runArgs.VERBOSE ) or (hasattr( runArgs, "loglevel") and runArgs.loglevel == "DEBUG") or (hasattr( runArgs, "loglevel") and runArgs.loglevel == "VERBOSE"):
522  include("EvgenJobTransforms/Generate_debug_level.py")
523 
524 
525 svcMgr.TagInfoMgr.ExtraTagValuePairs.update({"specialConfiguration": evgenConfig.specialConfig })
526 
527 
529 if hasattr(testSeq, "TestHepMC") and not gens_testhepmc(evgenConfig.generators):
530  evgenLog.info("Removing TestHepMC sanity checker")
531  del testSeq.TestHepMC
532 
533 
537 def checkBlackList(relFlavour,cache,generatorName) :
538  isError = None
539  with open('/cvmfs/atlas.cern.ch/repo/sw/Generators/MC16JobOptions/common/BlackList_caches.txt') as bfile:
540  for line in bfile.readlines():
541  if not line.strip():
542  continue
543  # Blacklisted release flavours
544  badRelFlav=line.split(',')[0].strip()
545  # Blacklisted caches
546  badCache=line.split(',')[1].strip()
547  # Blacklisted generators
548  badGens=line.split(',')[2].strip()
549 
550  used_gens = ','.join(generatorName)
551  #Match Generator and release type e.g. AtlasProduction, MCProd
552  if relFlavour==badRelFlav and cache==badCache and re.search(badGens,used_gens) is not None:
553  if badGens=="": badGens="all generators"
554  isError=relFlavour+","+cache+" is blacklisted for " + badGens
555  return isError
556  return isError
557 
558 def checkPurpleList(relFlavour,cache,generatorName) :
559  isError = None
560  with open('/cvmfs/atlas.cern.ch/repo/sw/Generators/MC16JobOptions/common/PurpleList_generators.txt') as bfile:
561  for line in bfile.readlines():
562  if not line.strip():
563  continue
564  # Purple-listed release flavours
565  purpleRelFlav=line.split(',')[0].strip()
566  # Purple-listed caches
567  purpleCache=line.split(',')[1].strip()
568  # Purple-listed generators
569  purpleGens=line.split(',')[2].strip()
570  # Purple-listed process
571  purpleProcess=line.split(',')[3].strip()
572 
573  used_gens = ','.join(generatorName)
574  #Match Generator and release type e.g. AtlasProduction, MCProd
575  if relFlavour==purpleRelFlav and cache==purpleCache and re.search(purpleGens,used_gens) is not None:
576  isError=relFlavour+","+cache+" is blacklisted for " + purpleGens + " if it uses " + purpleProcess
577  return isError
578  return isError
579 
580 
581 evgenLog.debug("****************** CHECKING RELEASE IS NOT BLACKLISTED *****************")
582 if os.path.exists('/cvmfs/atlas.cern.ch/repo/sw/Generators/MC16JobOptions/common'):
583  errorBL = checkBlackList("AthGeneration",rel,gennames)
584  if (errorBL):
585  if (hasattr( runArgs, "ignoreBlackList") and runArgs.ignoreBlackList):
586  evgenLog.warning("This run is blacklisted for this generator, please use a different one for production !! "+ errorBL )
587  else:
588  raise RuntimeError("This run is blacklisted for this generator, please use a different one !! "+ errorBL)
589 
590  errorPL = checkPurpleList("AthGeneration",rel,gennames)
591  if (errorPL):
592  evgenLog.warning("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
593  evgenLog.warning("!!! WARNING !!! "+ errorPL )
594  evgenLog.warning("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
595 
596 else:
597  msg.waring("No access to cvmfs, so blacklisted runs will not be checked")
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 if (hasattr( runArgs, "allowOldFilter") and runArgs.allowOldFilter):
863  for alg in acas.iter_algseq(filtSeq):
864  filtName = alg.getType()
865  exceptName =['xAOD','Jet']
866  if filtName not in excludedNames:
867  if not any(ex in filtName for ex in exceptName):
868  alg.AllowOldFilter=True
869  print("eA old filter allowed via transform param.")
870 
871 
874 
875 from PyJobTransformsCore.runargs import RunArguments
876 runPars = RunArguments()
877 runPars.nEventsPerJob = evgenConfig.nEventsPerJob
878 runPars.maxeventsstrategy = evgenConfig.maxeventsstrategy
879 with open("config.pickle", "wb") as f:
880  import pickle
881  pickle.dump(runPars, f)
882 
883 
884 
887 evgenLog.info("****************** STARTING EVENT GENERATION *****************")
read
IovVectorMap_t read(const Folder &theFolder, const SelectionCriterion &choice, const unsigned int limit=10)
Definition: openCoraCool.cxx:569
DerivationFramework::TriggerMatchingUtils::sorted
std::vector< typename R::value_type > sorted(const R &r, PROJ proj={})
Helper function to create a sorted vector from an unsorted range.
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:77
skel.find_unique_file
def find_unique_file(pattern)
Helper functions for input file handling.
Definition: skel.ABtoEVGEN.py:473
RngCompsConfig.AtRndmGenSvc
AtRndmGenSvc
Definition: RngCompsConfig.py:9
trfutil
skel.merge_lhe_files
def merge_lhe_files(listOfFiles, outputFile)
Check that there is exactly 1 match.
Definition: skel.GENtoEVGEN.py:673
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:537
LArG4FSStartPointFilter.exec
exec
Definition: LArG4FSStartPointFilter.py:103
python.LArMinBiasAlgConfig.int
int
Definition: LArMinBiasAlgConfig.py:59
python.GenConfigHelpers.gen_require_steering
def gen_require_steering(gennames)
Definition: GenConfigHelpers.py:50
histSizes.list
def list(name, path='/')
Definition: histSizes.py:38
LogicalExpressionFilter
Definition: LogicalExpressionFilter.py:1
python.Versioning.generatorsGetInitialVersionedDictionary
def generatorsGetInitialVersionedDictionary(generators)
Definition: Versioning.py:40
python.GenConfigHelpers.gens_notune
def gens_notune(gennames)
Definition: GenConfigHelpers.py:85
skel._short2
def _short2(s)
Definition: skel.ABtoEVGEN.py:272
python.GenConfigHelpers.gens_lhef
def gens_lhef(gennames)
Definition: GenConfigHelpers.py:69
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:151
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:558
python.Versioning.generatorsVersionedStringList
def generatorsVersionedStringList(generatorsDictionary)
Definition: Versioning.py:59
Lb2Lll.THistSvc
THistSvc
Definition: Lb2Lll.py:216
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:506
skel.mk_symlink
def mk_symlink(srcfile, dstfile)
Definition: skel.ABtoEVGEN.py:484
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
Cut::all
@ all
Definition: SUSYToolsAlg.cxx:67
Trk::split
@ split
Definition: LayerMaterialProperties.h:38