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 # Generators whose unstable particles without end vertex have to be purged
50 # n.b. "Pythia8-Angantyr" is not a 'real' name, the real name would be just 'Pythia8'
51 PurgeNoEndVtxGenerators = ["Pythia8-Angantyr", "Herwig7", "Hijing"]
52 
53 def gen_require_steering(gennames):
54  """Return a boolean of whether this set of generators requires the steering command line flag"""
55  if "EvtGen" not in gennames: return False
56  if any(("Pythia" in gen and "Pythia8" not in gen) for gen in gennames): return True
57  if any(("Herwig" in gen and "Herwig7" not in gen) for gen in gennames): return True
58  return False
59 
60 def gen_known(genname):
61  """Return whether a generator name is known"""
62  return genname in KnownGenerators
63 
64 def gens_known(gennames):
65  """Return whether all generator names are known"""
66  return all(gen_known(g) for g in gennames)
67 
68 def gen_lhef(genname):
69  """Return whether a generator uses LHEF input files"""
70  return genname in LHEFGenerators
71 
72 def gens_lhef(gennames):
73  """Return whether any of the generators uses LHEF input files"""
74  return any(gen_lhef(g) for g in gennames)
75 
76 def gen_testhepmc(genname):
77  """Return whether a generator should be sanity tested with TestHepMC"""
78  return genname not in NoTestHepMCGenerators
79 
80 def gens_testhepmc(gennames):
81  """Return whether all of the generators should be sanity tested with TestHepMC"""
82  return all(gen_testhepmc(g) for g in gennames)
83 
84 def gen_notune(genname):
85  """Return whether a generator is allowed to not provide PDF and tune information"""
86  return genname not in NoTuneGenerators
87 
88 def gens_notune(gennames):
89  """Return whether all of the generators are allowed to not provide PDF and tune information"""
90  return all(gen_notune(g) for g in gennames)
91 
92 def gen_purgenoendvtx(genname):
93  """Return whether a generator may produce unstable particles
94  without end vertex that have to be purged"""
95  return genname in PurgeNoEndVtxGenerators
96 
97 def gens_purgenoendvtx(gennames):
98  """Return whether any of the generators may produce unstable particles
99  without end vertex that have to be purged"""
100  return any(gen_purgenoendvtx(g) for g in gennames)
101 
102 def gen_sortkey(genname):
103  """Return a key suitable for sorting a generator name by stage, then alphabetically"""
104 
105  # Sort mainly in order of generator stage
106  genstage = None
107  for istage, gens in enumerate([LHEFGenerators, HIMainGenerators, MainGenerators,AfterburnerGenerators]):
108  if genname in gens:
109  genstage = istage
110  break
111 
112  # Return a tuple
113  return (genstage, genname)
114 
115 # Function to perform consistency check on jO
116 def checkJOConsistency(jofile):
117  import os, sys, string
118  officialJO = False
119  joparts = (os.path.basename(jofile)).split(".")
120  # Perform some consistency checks
121  if joparts[0].startswith("mc") and all(c in string.digits for c in joparts[0][2:]):
122  officialJO = True
123  # Check that there are exactly 4 name parts separated by '.': MCxx, DSID, physicsShort, .py
124  if len(joparts) != 3:
125  evgenLog.error(jofile + " name format is wrong: must be of the form mc.<physicsShort>.py: please rename.")
126  sys.exit(1)
127  # Check the length limit on the physicsShort portion of the filename
128  jo_physshortpart = joparts[1]
129  if len(jo_physshortpart) > 50:
130  evgenLog.error(jofile + " contains a physicsShort field of more than 60 characters: please rename.")
131  sys.exit(1)
132  # There must be at least 2 physicsShort sub-parts separated by '_': gens, (tune)+PDF, and process
133  jo_physshortparts = jo_physshortpart.split("_")
134  if len(jo_physshortparts) < 2:
135  evgenLog.error(jofile + " has too few physicsShort fields separated by '_': should contain <generators>(_<tune+PDF_if_available>)_<process>. Please rename.")
136  sys.exit(1)
137 
138  # NOTE: a further check on physicsShort consistency is done below, after fragment loading
139  check_jofiles="/cvmfs/atlas.cern.ch/repo/sw/Generators/MC16JobOptions/scripts"
140  sys.path.append(check_jofiles)
141  from check_jo_consistency import check_naming
142  if os.path.exists(check_jofiles):
143  check_naming(os.path.basename(jofile))
144  else:
145  evgenLog.error("check_jo_consistency.py not found")
146  sys.exit(1)
147  return officialJO
148 
149 def checkNEventsPerJob(sample):
150  if sample.nEventsPerJob < 1:
151  raise RuntimeError("nEventsPerJob must be at least 1")
152  elif sample.nEventsPerJob > 100000:
153  raise RuntimeError("nEventsPerJob can be max. 100000")
154  else:
155  allowed_nEventsPerJob_lt1000 = [1, 2, 5, 10, 20, 25, 50, 100, 200, 500, 1000]
156  if sample.nEventsPerJob >= 1000 and sample.nEventsPerJob <= 10000 and \
157  (sample.nEventsPerJob % 1000 != 0 or 10000 % sample.nEventsPerJob != 0):
158  raise RuntimeError("nEventsPerJob in range [1K, 10K] must be a multiple of 1K and a divisor of 10K")
159  elif sample.nEventsPerJob > 10000 and sample.nEventsPerJob % 10000 != 0:
160  raise RuntimeError("nEventsPerJob >10K must be a multiple of 10K")
161  elif sample.nEventsPerJob < 1000 and sample.nEventsPerJob not in allowed_nEventsPerJob_lt1000:
162  raise RuntimeError("nEventsPerJob in range <= 1000 must be one of %s" % allowed_nEventsPerJob_lt1000)
163 
164 def checkKeywords(sample, evgenLog, officialJO):
165  # Get file containing keywords
166  from AthenaCommon.Utils.unixtools import find_datafile
167  kwpath = find_datafile("evgenkeywords.txt")
168 
169  # Load the allowed keywords from the file
170  allowed_keywords = []
171  if kwpath:
172  evgenLog.info("evgenkeywords = %s", kwpath)
173  kwf = open(kwpath, "r")
174  for l in kwf:
175  allowed_keywords += l.strip().lower().split()
176  # Check the JO keywords against the allowed ones
177  evil_keywords = []
178  for k in sample.keywords:
179  if k.lower() not in allowed_keywords:
180  evil_keywords.append(k)
181  if evil_keywords:
182  msg = "keywords contains non-standard keywords: %s. " % ", ".join(evil_keywords)
183  msg += "Please check the allowed keywords list and fix."
184  evgenLog.error(msg)
185  if officialJO:
186  import sys
187  sys.exit(1)
188  else:
189  evgenLog.warning("evgenkeywords.txt not found ")
190 
191 def checkCategories(sample, evgenLog, officialJO):
192  # Get file containing category names
193  from AthenaCommon.Utils.unixtools import find_datafile
194  lkwpath = find_datafile("CategoryList.txt")
195 
196  # Load the allowed categories names from the file
197  allowed_cat = []
198  if lkwpath:
199  from ast import literal_eval
200  with open(lkwpath, 'r') as catlist:
201  for line in catlist:
202  allowed_list = literal_eval(line)
203  allowed_cat.append(allowed_list)
204 
205  # Check the JO categories against the allowed ones
206  bad_cat =[]
207  it = iter(sample.categories)
208  for x in it:
209  l1 = x
210  l2 = next(it)
211  if "L1:" in l2 and "L2:" in l1:
212  l1, l2 = l2, l1
213  print ("first",l1,"second",l2)
214  bad_cat.extend([l1, l2])
215  for a1,a2 in allowed_cat:
216  if l1.strip().lower()==a1.strip().lower() and l2.strip().lower()==a2.strip().lower():
217  bad_cat=[]
218  if bad_cat:
219  msg = "categories contains non-standard category: %s. " % ", ".join(bad_cat)
220  msg += "Please check the allowed categories list and fix."
221  evgenLog.error(msg)
222  if officialJO:
223  import sys
224  sys.exit(1)
225  else:
226  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:80
python.GenConfigHelpers.gen_lhef
def gen_lhef(genname)
Definition: GenConfigHelpers.py:68
python.GenConfigHelpers.gens_known
def gens_known(gennames)
Definition: GenConfigHelpers.py:64
python.GenConfigHelpers.gens_purgenoendvtx
def gens_purgenoendvtx(gennames)
Definition: GenConfigHelpers.py:97
python.GenConfigHelpers.checkJOConsistency
def checkJOConsistency(jofile)
Definition: GenConfigHelpers.py:116
python.GenConfigHelpers.gen_testhepmc
def gen_testhepmc(genname)
Definition: GenConfigHelpers.py:76
python.GenConfigHelpers.gen_known
def gen_known(genname)
Definition: GenConfigHelpers.py:60
fillPileUpNoiseLumi.next
next
Definition: fillPileUpNoiseLumi.py:52
python.GenConfigHelpers.gen_purgenoendvtx
def gen_purgenoendvtx(genname)
Definition: GenConfigHelpers.py:92
python.GenConfigHelpers.checkNEventsPerJob
def checkNEventsPerJob(sample)
Definition: GenConfigHelpers.py:149
python.GenConfigHelpers.gen_require_steering
def gen_require_steering(gennames)
Definition: GenConfigHelpers.py:53
python.GenConfigHelpers.gens_notune
def gens_notune(gennames)
Definition: GenConfigHelpers.py:88
python.GenConfigHelpers.gens_lhef
def gens_lhef(gennames)
Definition: GenConfigHelpers.py:72
python.GenConfigHelpers.checkKeywords
def checkKeywords(sample, evgenLog, officialJO)
Definition: GenConfigHelpers.py:164
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:102
python.GenConfigHelpers.gen_notune
def gen_notune(genname)
Definition: GenConfigHelpers.py:84
Cut::all
@ all
Definition: SUSYToolsAlg.cxx:67
Trk::open
@ open
Definition: BinningType.h:40
python.GenConfigHelpers.checkCategories
def checkCategories(sample, evgenLog, officialJO)
Definition: GenConfigHelpers.py:191
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