ATLAS Offline Software
GenConfigHelpers.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
2 
3 # Get logger
4 from AthenaCommon.Logging import logging
5 evgenLog = logging.getLogger('GenConfigHelpers')
6 
7 # Generators providing input events via the LHEF format
8 # (used to determine the input file dummy-naming strategy for C++ generators)
9 LHEFGenerators = ["Lhef", # generic name: prefer to use the names below
10  "aMcAtNlo", "McAtNlo", "Powheg", "MadGraph", "CompHep", "Geneva",
11  "MCFM", "JHU", "MEtop", "BCVEGPY", "Dire4Pythia8",
12  "BlackMax", "QBH", "gg2ww", "gg2zz", "gg2vv", "HvyN",
13  "VBFNLO", "FPMC", "ProtosLHEF",
14  "BCVEGPY", "STRINGS", "Phantom"]
15 
16 # "Main" generators which typically model QCD showers, hadronisation, decays, etc.
17 # Herwig family
18 MainGenerators = ["Herwig7"]
19 # Pythia family
20 MainGenerators += ["Pythia8", "Pythia8B"]
21 # Sherpa family
22 MainGenerators += ["Sherpa"]
23 # Soft QCD generators
24 MainGenerators += ["Epos"]
25 # ATLAS-specific generators
26 MainGenerators += ["ParticleGun"]
27 MainGenerators += ["CosmicGenerator", "BeamHaloGenerator"]
28 # Heavy ion generators - as a special group to avoid problems in sorting
29 HIMainGenerators = ["AMPT","SuperChic","Starlight", "Hijing", "Hydjet"]
30 # Reading in fully-formed events
31 
32 MainGenerators += ["HepMCAscii"]
33 
34 # Special QED and decay afterburners
35 # note: we have to use TauolaPP, because Tauolapp is used as a namespace in the external Tauolapp code
36 AfterburnerGenerators = ["Photospp", "TauolaPP", "EvtGen", "ParticleDecayer"]
37 
38 # Set up list of allowed generators. The sample.generators list will be used
39 # to set random seeds, determine input config and event files, and report used generators to AMI.
40 KnownGenerators = LHEFGenerators + HIMainGenerators +MainGenerators + AfterburnerGenerators
41 
42 # Note which generators should NOT be sanity tested by the TestHepMC alg
43 NoTestHepMCGenerators = ["Superchic","ParticleDecayer", "ParticleGun", "CosmicGenerator",
44  "BeamHaloGenerator", "FPMC", "Hijing", "Hydjet", "Starlight"]
45 
46 # Generators with no flexibility/concept of a tune or PDF choice
47 NoTuneGenerators = ["ParticleGun", "CosmicGenerator", "BeamHaloGenerator", "HepMCAscii"]
48 
49 
50 def gen_require_steering(gennames):
51  """Return a boolean of whether this set of generators requires the steering command line flag"""
52  if "EvtGen" not in gennames: return False
53  if any(("Pythia" in gen and "Pythia8" not in gen) for gen in gennames): return True
54  if any(("Herwig" in gen and "Herwig7" not in gen) for gen in gennames): return True
55  return False
56 
57 def gen_known(genname):
58  """Return whether a generator name is known"""
59  return genname in KnownGenerators
60 
61 def gens_known(gennames):
62  """Return whether all generator names are known"""
63  return all(gen_known(g) for g in gennames)
64 
65 def gen_lhef(genname):
66  """Return whether a generator uses LHEF input files"""
67  return genname in LHEFGenerators
68 
69 def gens_lhef(gennames):
70  """Return whether any of the generators uses LHEF input files"""
71  return any(gen_lhef(g) for g in gennames)
72 
73 def gen_testhepmc(genname):
74  """Return whether a generator should be sanity tested with TestHepMC"""
75  return genname not in NoTestHepMCGenerators
76 
77 def gens_testhepmc(gennames):
78  """Return whether all of the generators should be sanity tested with TestHepMC"""
79  return all(gen_testhepmc(g) for g in gennames)
80 
81 def gen_notune(genname):
82  """Return whether a generator is allowed to not provide PDF and tune information"""
83  return genname not in NoTuneGenerators
84 
85 def gens_notune(gennames):
86  """Return whether all of the generators are allowed to not provide PDF and tune information"""
87  return all(gen_notune(g) for g in gennames)
88 
89 def gen_sortkey(genname):
90  """Return a key suitable for sorting a generator name by stage, then alphabetically"""
91 
92  # Sort mainly in order of generator stage
93  genstage = None
94  for istage, gens in enumerate([LHEFGenerators, HIMainGenerators, MainGenerators,AfterburnerGenerators]):
95  if genname in gens:
96  genstage = istage
97  break
98 
99  # Return a tuple
100  return (genstage, genname)
101 
102 # Function to perform consistency check on jO
103 def checkJOConsistency(jofile):
104  import os, sys, string
105  officialJO = False
106  joparts = (os.path.basename(jofile)).split(".")
107  # Perform some consistency checks
108  if joparts[0].startswith("mc") and all(c in string.digits for c in joparts[0][2:]):
109  officialJO = True
110  # Check that there are exactly 4 name parts separated by '.': MCxx, DSID, physicsShort, .py
111  if len(joparts) != 3:
112  evgenLog.error(jofile + " name format is wrong: must be of the form mc.<physicsShort>.py: please rename.")
113  sys.exit(1)
114  # Check the length limit on the physicsShort portion of the filename
115  jo_physshortpart = joparts[1]
116  if len(jo_physshortpart) > 50:
117  evgenLog.error(jofile + " contains a physicsShort field of more than 60 characters: please rename.")
118  sys.exit(1)
119  # There must be at least 2 physicsShort sub-parts separated by '_': gens, (tune)+PDF, and process
120  jo_physshortparts = jo_physshortpart.split("_")
121  if len(jo_physshortparts) < 2:
122  evgenLog.error(jofile + " has too few physicsShort fields separated by '_': should contain <generators>(_<tune+PDF_if_available>)_<process>. Please rename.")
123  sys.exit(1)
124 
125  # NOTE: a further check on physicsShort consistency is done below, after fragment loading
126  check_jofiles="/cvmfs/atlas.cern.ch/repo/sw/Generators/MC16JobOptions/scripts"
127  sys.path.append(check_jofiles)
128  from check_jo_consistency import check_naming
129  if os.path.exists(check_jofiles):
130  check_naming(os.path.basename(jofile))
131  else:
132  evgenLog.error("check_jo_consistency.py not found")
133  sys.exit(1)
134  return officialJO
135 
136 def checkNEventsPerJob(sample):
137  if sample.nEventsPerJob < 1:
138  raise RuntimeError("nEventsPerJob must be at least 1")
139  elif sample.nEventsPerJob > 100000:
140  raise RuntimeError("nEventsPerJob can be max. 100000")
141  else:
142  allowed_nEventsPerJob_lt1000 = [1, 2, 5, 10, 20, 25, 50, 100, 200, 500, 1000]
143  if sample.nEventsPerJob >= 1000 and sample.nEventsPerJob <= 10000 and \
144  (sample.nEventsPerJob % 1000 != 0 or 10000 % sample.nEventsPerJob != 0):
145  raise RuntimeError("nEventsPerJob in range [1K, 10K] must be a multiple of 1K and a divisor of 10K")
146  elif sample.nEventsPerJob > 10000 and sample.nEventsPerJob % 10000 != 0:
147  raise RuntimeError("nEventsPerJob >10K must be a multiple of 10K")
148  elif sample.nEventsPerJob < 1000 and sample.nEventsPerJob not in allowed_nEventsPerJob_lt1000:
149  raise RuntimeError("nEventsPerJob in range <= 1000 must be one of %s" % allowed_nEventsPerJob_lt1000)
150 
151 def checkKeywords(sample, evgenLog, officialJO):
152  # Get file containing keywords
153  from AthenaCommon.Utils.unixtools import find_datafile
154  kwpath = find_datafile("evgenkeywords.txt")
155 
156  # Load the allowed keywords from the file
157  allowed_keywords = []
158  if kwpath:
159  evgenLog.info("evgenkeywords = %s", kwpath)
160  kwf = open(kwpath, "r")
161  for l in kwf:
162  allowed_keywords += l.strip().lower().split()
163  # Check the JO keywords against the allowed ones
164  evil_keywords = []
165  for k in sample.keywords:
166  if k.lower() not in allowed_keywords:
167  evil_keywords.append(k)
168  if evil_keywords:
169  msg = "keywords contains non-standard keywords: %s. " % ", ".join(evil_keywords)
170  msg += "Please check the allowed keywords list and fix."
171  evgenLog.error(msg)
172  if officialJO:
173  import sys
174  sys.exit(1)
175  else:
176  evgenLog.warning("evgenkeywords.txt not found ")
177 
178 def checkCategories(sample, evgenLog, officialJO):
179  # Get file containing category names
180  from AthenaCommon.Utils.unixtools import find_datafile
181  lkwpath = find_datafile("CategoryList.txt")
182 
183  # Load the allowed categories names from the file
184  allowed_cat = []
185  if lkwpath:
186  from ast import literal_eval
187  with open(lkwpath, 'r') as catlist:
188  for line in catlist:
189  allowed_list = literal_eval(line)
190  allowed_cat.append(allowed_list)
191 
192  # Check the JO categories against the allowed ones
193  bad_cat =[]
194  it = iter(sample.categories)
195  for x in it:
196  l1 = x
197  l2 = next(it)
198  if "L1:" in l2 and "L2:" in l1:
199  l1, l2 = l2, l1
200  print ("first",l1,"second",l2)
201  bad_cat.extend([l1, l2])
202  for a1,a2 in allowed_cat:
203  if l1.strip().lower()==a1.strip().lower() and l2.strip().lower()==a2.strip().lower():
204  bad_cat=[]
205  if bad_cat:
206  msg = "categories contains non-standard category: %s. " % ", ".join(bad_cat)
207  msg += "Please check the allowed categories list and fix."
208  evgenLog.error(msg)
209  if officialJO:
210  import sys
211  sys.exit(1)
212  else:
213  evgenLog.warning("Could not find CategoryList.txt file ", lkwpath, " in $DATAPATH")
createLinkingScheme.iter
iter
Definition: createLinkingScheme.py:62
python.GenConfigHelpers.gens_testhepmc
def gens_testhepmc(gennames)
Definition: GenConfigHelpers.py:77
python.GenConfigHelpers.gen_lhef
def gen_lhef(genname)
Definition: GenConfigHelpers.py:65
python.GenConfigHelpers.gens_known
def gens_known(gennames)
Definition: GenConfigHelpers.py:61
python.GenConfigHelpers.checkJOConsistency
def checkJOConsistency(jofile)
Definition: GenConfigHelpers.py:103
python.GenConfigHelpers.gen_testhepmc
def gen_testhepmc(genname)
Definition: GenConfigHelpers.py:73
python.GenConfigHelpers.gen_known
def gen_known(genname)
Definition: GenConfigHelpers.py:57
fillPileUpNoiseLumi.next
next
Definition: fillPileUpNoiseLumi.py:52
python.GenConfigHelpers.checkNEventsPerJob
def checkNEventsPerJob(sample)
Definition: GenConfigHelpers.py:136
python.GenConfigHelpers.gen_require_steering
def gen_require_steering(gennames)
Definition: GenConfigHelpers.py:50
python.GenConfigHelpers.gens_notune
def gens_notune(gennames)
Definition: GenConfigHelpers.py:85
python.GenConfigHelpers.gens_lhef
def gens_lhef(gennames)
Definition: GenConfigHelpers.py:69
python.GenConfigHelpers.checkKeywords
def checkKeywords(sample, evgenLog, officialJO)
Definition: GenConfigHelpers.py:151
TCS::join
std::string join(const std::vector< std::string > &v, const char c=',')
Definition: Trigger/TrigT1/L1Topo/L1TopoCommon/Root/StringUtils.cxx:10
python.GenConfigHelpers.gen_sortkey
def gen_sortkey(genname)
Definition: GenConfigHelpers.py:89
python.GenConfigHelpers.gen_notune
def gen_notune(genname)
Definition: GenConfigHelpers.py:81
Trk::open
@ open
Definition: BinningType.h:40
python.GenConfigHelpers.checkCategories
def checkCategories(sample, evgenLog, officialJO)
Definition: GenConfigHelpers.py:178
Cut::all
@ all
Definition: SUSYToolsAlg.cxx:67
python.Utils.unixtools.find_datafile
def find_datafile(fname, pathlist=None, access=os.R_OK)
pathresolver-like helper function --------------------------------------—
Definition: unixtools.py:67
Trk::split
@ split
Definition: LayerMaterialProperties.h:38