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