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