ATLAS Offline Software
Loading...
Searching...
No Matches
Pythia8Config.py
Go to the documentation of this file.
1# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
2
3from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
4from AthenaConfiguration.ComponentFactory import CompFactory
5from GeneratorConfig.GeneratorSettingsSemantics import (
6 GeneratorSettingsLayer,
7 GeneratorSettingsPrecedence,
8)
9from GeneratorConfig.Sequences import EvgenSequence, EvgenSequenceFactory
10from Pythia8_i.Pythia8Tunes import (
11 a14_nnpdf23lo_tune_cmds,
12 a2_mstw2008lo_tune_cmds,
13)
14from AthenaCommon.SystemOfUnits import GeV
15
16# Get logger
17from AthenaCommon.Logging import logging
18log = logging.getLogger("Pythia8Config")
19
20
21def Pythia8CommandsCfg(flags, source, commands, precedence, name="Pythia8_i"):
22 """
23 Return a CA fragment that adds one command layer to Pythia8_i.
24 """
25 ca = ComponentAccumulator(EvgenSequenceFactory(EvgenSequence.Generator))
26 ca.addEventAlgo(
27 CompFactory.Pythia8_i(name, Commands=GeneratorSettingsLayer(
28 source=source,
29 values=tuple(commands or ()),
30 precedence=precedence,
31 report_context="Pythia8Cfg.Commands",
32 ))
33 )
34 return ca
35
36
37def Pythia8BaseCfg(flags, name="Pythia8_i", **kwargs):
38 """
39 The main Pythia8 configuration fragment that sets up the Pythia8_i algorithm
40 and returns a CA instance
41 """
42 # Baseline P8 settings
43 base_cmds = [
44 "Main:timesAllowErrors = 500",
45 "ParticleDecays:limitTau0 = on",
46 "ParticleDecays:tau0Max = 10.0"
47 ]
48
49 # Collision energy
50 if "CollisionEnergy" not in kwargs:
51 kwargs["CollisionEnergy"] = flags.Beam.Energy * 2 / GeV
52
53 # Random Seed and DSID
54 kwargs.setdefault("RandomSeed", flags.Random.SeedOffset)
55 kwargs.setdefault("Dsid", flags.Generator.DSID)
56
57 # Load basic parameters
58 base_cmds.extend([
59 "6:m0 = 172.5",
60 "23:m0 = 91.1876",
61 "23:mWidth = 2.4952",
62 "24:m0 = 80.399",
63 "24:mWidth = 2.085",
64 "StandardModel:sin2thetaW = 0.23113",
65 "StandardModel:sin2thetaWbar = 0.23146",
66 ])
67
68 user_cmds = kwargs.pop("Commands", None)
69 kwargs["Commands"] = GeneratorSettingsLayer(
70 source="base_fragment_commands",
71 values=tuple(base_cmds),
72 precedence=GeneratorSettingsPrecedence.BASE,
73 report_context="Pythia8Cfg.Commands",
74 )
75
76 # Create CA object
77 ca = ComponentAccumulator(EvgenSequenceFactory(EvgenSequence.Generator))
78 ca.addEventAlgo(
79 CompFactory.Pythia8_i(name, **kwargs)
80 )
81
82 # Add the user commands
83 if user_cmds:
84 ca.merge(Pythia8CommandsCfg(
85 flags,
86 source="user_commands",
87 commands=user_cmds,
88 precedence=GeneratorSettingsPrecedence.USER,
89 name=name,
90 ))
91
92 # Announce generator to service
93 from GeneratorConfig.GeneratorInfoSvcConfig import GeneratorInfoSvcCfg
94 ca.merge(GeneratorInfoSvcCfg(flags, Generators=["Pythia8"]), sequenceName=EvgenSequence.Generator.value)
95
96 return ca
97
98
99def Pythia8EvtGenBaseCfg(flags, **kwargs):
100 """
101 Fragment for setting up EvtGen on top of Pythia 8
102 """
103 # Custom settings
104 auxfiles = ["inclusiveP8DsDPlus.pdt"]
105 # FHerwig has problems with omega b* (5334), so not present in the base EvtGen fragment.
106 whiteList = [-5334, 5334]
107
108 # Add custom EvtGenCfg
109 from EvtGen_i.EvtGenConfig import EvtGenCfg
110 ca = EvtGenCfg(
111 flags,
112 whiteList = whiteList,
113 auxfiles = auxfiles,
114 **kwargs
115 )
116
117 return ca
118
119
121 """
122 Fragment for setting up A2 MSTW2008LO tune
123 """
124
125 # Remove any user command before calling base config
126 user_cmds = list(kwargs.pop("Commands", []))
127
128 # Get the base config
129 ca = Pythia8BaseCfg(flags, **kwargs)
130
131 # Get the tune commands and apply rapidity ordering
132 tune_cmds = a2_mstw2008lo_tune_cmds()
133 tune_cmds = ensureRapidityOrderMPI(tune_cmds)
134
135 # Add the tune commands
136 ca.merge(Pythia8CommandsCfg(
137 flags,
138 source="pythia_tune_A2_MSTW2008LO",
139 commands=tune_cmds,
140 precedence=GeneratorSettingsPrecedence.TUNE,
141 ))
142
143 # Now apply the user commands
144 if user_cmds:
145 ca.merge(Pythia8CommandsCfg(
146 flags,
147 source="job_options",
148 commands=user_cmds,
149 precedence=GeneratorSettingsPrecedence.USER,
150 ))
151
152 # Broadcast tune to service
153 from GeneratorConfig.GeneratorInfoSvcConfig import GeneratorInfoSvcCfg
154 ca.merge(GeneratorInfoSvcCfg(flags, Tune="A2 MSTW2008LO"), sequenceName=EvgenSequence.Generator.value)
155
156 # Call the base config
157 return ca
158
159
161 """
162 Fragment for setting up A14 tune with NNPDF23LO PDF
163 """
164
165 # Remove any user command before calling base config
166 user_cmds = list(kwargs.pop("Commands", []))
167
168 # Get the base config
169 ca = Pythia8BaseCfg(flags, **kwargs)
170
171 # Get the tune commands and apply rapidity ordering
172 tune_cmds = a14_nnpdf23lo_tune_cmds()
173 tune_cmds = ensureRapidityOrderMPI(tune_cmds)
174
175 # Add the tune commands
176 ca.merge(Pythia8CommandsCfg(
177 flags,
178 source="pythia_tune_A14_NNPDF23LO",
179 commands=tune_cmds,
180 precedence=GeneratorSettingsPrecedence.TUNE,
181 ))
182
183 # Now apply the user commands
184 if user_cmds:
185 ca.merge(Pythia8CommandsCfg(
186 flags,
187 source="job_options",
188 commands=user_cmds,
189 precedence=GeneratorSettingsPrecedence.USER,
190 ))
191
192 # Broadcast tune to service
193 from GeneratorConfig.GeneratorInfoSvcConfig import GeneratorInfoSvcCfg
194 ca.merge(GeneratorInfoSvcCfg(flags, Tune="A14 NNPDF23LO"), sequenceName=EvgenSequence.Generator.value)
195
196 # Call the base config
197 return ca
198
199
201 """
202 Config for Py8 tune A2 with MSTW2008LO tune
203 The default version of this includes EvtGen for standardised b fragmentation
204 This tune is generally only used for pile up samples at the start of run 2
205 for high pT physics at the start of run 2 the A14 tune is more appropriate.
206 There are also more recent soft QCD tunes, such as Monash,
207 but A2 was a conservative choice for initial 13 TeV pile up
208 """
209
210 # Add Pythia 8 to CA with correct tune settings
211 ca = Pythia8_A2_MSTW2008LO_Common_Cfg(flags, **kwargs)
212
213 # Add EvtGen
214 ca.merge(Pythia8EvtGenBaseCfg(flags))
215
216 return ca
217
218
220 """
221 Config for setting up Py8 with A14 tune
222 with EvtGen
223 """
224
225 # Add Pythia 8 to CA with correct tune settings
226 ca = Pythia8_A14_NNPDF23LO_Common_Cfg(flags, **kwargs)
227
228 # Add EvtGen
229 ca.merge(Pythia8EvtGenBaseCfg(flags))
230
231 return ca
232
233
235 """
236 A function that ensures rapidity ordering is set
237 """
238 # if MPI‐ordering already explicitly set, do nothing
239 if any("SpaceShower:rapidityOrderMPI" in c for c in cmds):
240 return cmds
241
242 # find the first rapidityOrder value
243 for c in cmds:
244 if "SpaceShower:rapidityOrder" in c and "MPI" not in c:
245 val = c.split("=", 1)[-1].strip()
246 cmds.append(f"SpaceShower:rapidityOrderMPI = {val}")
247 break
248 return cmds
249
250
251def Pythia8_MadGraph_Cfg(flags, ShowerCfg=Pythia8BaseCfg, **kwargs):
252 """
253 Modular fragment for MadGraph LHE input in Pythia8.
254 The Pythia8_i algorithm is configured through ShowerCfg (defaults to
255 Pythia8BaseCfg) so tune/EvtGen fragments can be injected without
256 instantiating Pythia8_i twice.
257 """
258 # Match Pythia8's input name to the file prepared by EvgenHelpers.
259 # This can still be overridden by setting in the config LHEFile="myfile.lhe[.gz]".
260 lhe_file = (
261 "events.lhe.gz"
262 if flags.Generator.avoidExtracting
263 else "events.lhe"
264 )
265 kwargs.setdefault("LHEFile", lhe_file)
266
267 # Configure Pythia8 through the selected shower fragment.
268 ca = ShowerCfg(flags, **kwargs)
269
270 # Announce MadGraph to service
271 from GeneratorConfig.GeneratorInfoSvcConfig import GeneratorInfoSvcCfg
272 ca.merge(GeneratorInfoSvcCfg(flags, Generators=["MadGraph"]), sequenceName=EvgenSequence.Generator.value)
273
274 return ca
275
276
277def Pythia8_Powheg_Cfg(flags, *, ShowerCfg, **kwargs):
278 """
279 Configure Pythia8 to shower POWHEG-BOX LHE input without veto matching.
280 CA translation of share/common/Pythia8_Powheg.py (+ Pythia8_LHEF.py).
281 The Pythia8_i algorithm is configured through ShowerCfg so tune/EvtGen
282 fragments can be injected without instantiating Pythia8_i twice.
283 """
284 lhe_file = (
285 "events.lhe.gz"
286 if flags.Generator.avoidExtracting
287 else "events.lhe"
288 )
289 kwargs.setdefault("LHEFile", lhe_file)
290
291 ca = ShowerCfg(flags, **kwargs)
292
293 from GeneratorConfig.GeneratorInfoSvcConfig import GeneratorInfoSvcCfg
294
295 ca.merge(GeneratorInfoSvcCfg(flags, Generators=["Powheg"]), sequenceName=EvgenSequence.Generator.value)
296
297 return ca
298
299
301 flags,
302 ShowerCfg=Pythia8BaseCfg,
303 NFinal=None,
304 name="Pythia8_i",
305 enable_shower_weights=True,
306 include_pdf_variations=False,
307 **kwargs,
308):
309 """
310 Configure POWHEG LHE showering with the PowhegMain31 veto hook.
311 CA translation of share/common/Pythia8_Powheg_Main31.py.
312 NFinal is the number of outgoing particles in the Born-level POWHEG
313 process, excluding additional POWHEG radiation.
314
315 By default this fragment also enables the legacy Pythia8 shower
316 uncertainty weights. Set enable_shower_weights=False to disable, or
317 include_pdf_variations=True to add the PDF-variation weights.
318 """
319 if NFinal is None:
320 raise ValueError("Pythia8_Powheg_Main31_Cfg: NFinal is process-specific "
321 "and must be set explicitly (Born final-state multiplicity)")
322
323 # Delay user commands until after the matching layer so that USER
324 # precedence can override matching settings when explicitly requested.
325 user_commands = kwargs.pop("Commands", None)
326
327 user_hooks = list(kwargs.pop("UserHooks", ()) or ())
328 if "PowhegMain31" not in user_hooks:
329 user_hooks.append("PowhegMain31")
330
331 ca = Pythia8_Powheg_Cfg(flags, ShowerCfg=ShowerCfg, name=name, UserHooks=user_hooks, **kwargs)
332
333 ca.merge(Pythia8CommandsCfg(
334 flags,
335 source="powheg_main31_matching",
336 commands=[
337 "SpaceShower:pTmaxMatch = 2",
338 "TimeShower:pTmaxMatch = 2",
339 "Powheg:veto = 1",
340 f"Powheg:NFinal = {NFinal}",
341 ],
342 precedence=GeneratorSettingsPrecedence.MATCHING,
343 name=name,
344 ))
345
346 if enable_shower_weights:
347 from Pythia8_i.Pythia8ShowerWeights import Pythia8ShowerWeightsCfg
348 ca.merge(Pythia8ShowerWeightsCfg(
349 flags,
350 name=name,
351 include_pdf_variations=include_pdf_variations,
352 ))
353
354 if user_commands:
355 ca.merge(Pythia8CommandsCfg(
356 flags,
357 source="job_options",
358 commands=user_commands,
359 precedence=GeneratorSettingsPrecedence.USER,
360 name=name,
361 ))
362
363 return ca
Pythia8CommandsCfg(flags, source, commands, precedence, name="Pythia8_i")
Pythia8_A2_MSTW2008LO_Common_Cfg(flags, **kwargs)
Pythia8_A14_NNPDF23LO_Common_Cfg(flags, **kwargs)
Pythia8EvtGenBaseCfg(flags, **kwargs)
Pythia8_A14_NNPDF23LO_EvtGen_Common_Cfg(flags, **kwargs)
Pythia8_Powheg_Main31_Cfg(flags, ShowerCfg=Pythia8BaseCfg, NFinal=None, name="Pythia8_i", enable_shower_weights=True, include_pdf_variations=False, **kwargs)
Pythia8_Powheg_Cfg(flags, *, ShowerCfg, **kwargs)
Pythia8_MadGraph_Cfg(flags, ShowerCfg=Pythia8BaseCfg, **kwargs)
Pythia8_A2_MSTW2008LO_EvtGen_Common_Cfg(flags, **kwargs)
Pythia8BaseCfg(flags, name="Pythia8_i", **kwargs)