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"]
25# ATLAS-specific generators
26MainGenerators += ["ParticleGun"]
27MainGenerators += ["CosmicGenerator", "BeamHaloGenerator"]
28# Heavy ion generators - as a special group to avoid problems in sorting
29HIMainGenerators = ["AMPT","SuperChic","Starlight", "Hijing", "Hydjet"]
30# Reading in fully-formed events
31
32MainGenerators += ["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
36AfterburnerGenerators = ["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.
40KnownGenerators = LHEFGenerators + HIMainGenerators +MainGenerators + AfterburnerGenerators
41
42# Note which generators should NOT be sanity tested by the TestHepMC alg
43NoTestHepMCGenerators = ["Superchic","ParticleDecayer", "ParticleGun", "CosmicGenerator",
44 "BeamHaloGenerator", "FPMC", "Hijing", "Hydjet", "Starlight"]
45
46# Generators with no flexibility/concept of a tune or PDF choice
47NoTuneGenerators = ["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'
51PurgeNoEndVtxGenerators = ["Pythia8-Angantyr", "Herwig7", "Hijing"]
52
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
60def gen_known(genname):
61 """Return whether a generator name is known"""
62 return genname in KnownGenerators
63
64def gens_known(gennames):
65 """Return whether all generator names are known"""
66 return all(gen_known(g) for g in gennames)
67
68def gen_lhef(genname):
69 """Return whether a generator uses LHEF input files"""
70 return genname in LHEFGenerators
71
72def 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
76def gen_testhepmc(genname):
77 """Return whether a generator should be sanity tested with TestHepMC"""
78 return genname not in NoTestHepMCGenerators
79
80def 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
84def gen_notune(genname):
85 """Return whether a generator is allowed to not provide PDF and tune information"""
86 return genname not in NoTuneGenerators
87
88def 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
92def 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
97def 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
102def 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
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
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
164def 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
191def 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")
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)