ATLAS Offline Software
Loading...
Searching...
No Matches
Pythia8Util.py
Go to the documentation of this file.
1# Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
2
3from GeneratorModules.EvgenAlg import EvgenAlg
4from AthenaPython.PyAthena import StatusCode
5import os
6import xml.dom.minidom
7import filecmp
8
9__author__ = 'Giancarlo Panizzo <giancarlo.panizzo@cern.ch>'
10
11
12class Pythia8Util(EvgenAlg):
13 """
14 A python-only algorithm to monitor Pythia8 behaviour / settings
15 """
16
17 def __init__(self, name="Pythia8Util", outputParticleDataFile="ParticleData.local.xml", threshold=50):
18 super(Pythia8Util,self).__init__(name=name)
19 self.threshold = threshold
20
21 self.njobs = 1
22 self.mode = 0
24 self.outputParticleDataFile = outputParticleDataFile
25
26 def ensure_toplevel(self,file_name):
27 """ Insert given string as a new line at the beginning of a file """
28 # define name of temporary dummy file
29 dummy_file = file_name + '.bak'
30 # open original file in read mode and dummy file in write mode
31 with open(file_name, 'r') as read_obj, open(dummy_file, 'w') as write_obj:
32 # Write given line to the dummy file
33 write_obj.write("<particledata>"+'\n')
34 # Read lines from original file one by one and append them to the dummy file
35 for line in read_obj:
36 write_obj.write(line)
37 write_obj.write("</particledata>"+' \n')
38 # remove original file
39 os.remove(file_name)
40 # Rename dummy file as the original file
41 os.rename(dummy_file, file_name)
42
43
44 def cmpsettings(self, requestedsettings):
45 if ( filecmp.cmp("Settings_before.log","Settings_after.log") ):
46 self.msg.info("Settings match before and after initialisation of Pythia8.")
47 else:
48 if "PartonShowers:model" in requestedsettings:
49 if (requestedsettings["PartonShowers:model"] !="1"):
50 self.msg.info("Settings before and after initialisation of Pythia8 don't match, because you asked PartonShowers:model = %s", requestedsettings["PartonShowers:model"])
51 else:
52 self.msg.warning("Settings before and after initialisation of Pythia8 don't match.")
53 with open("Settings_before.log") as f1:
54 f1_lines = f1.read().splitlines()
55 with open("Settings_after.log") as f2:
56 f2_lines = f2.read().splitlines()
57 # Find and print the diff:
58 if (len(f1_lines) == len(f2_lines)):
59 for iline in range(len(f1_lines)):
60 if (f1_lines[iline]!=f2_lines[iline]):
61 if f2_lines[iline].split("=")[0] in requestedsettings:
62 self.msg.warning(" >> %s != %s. You requested %s.", f1_lines[iline], f2_lines[iline].split("=")[1], requestedsettings[f2_lines[iline].split("=")[0]])
63 else:
64 self.msg.info(" >> %s != %s", f1_lines[iline], f2_lines[iline].split("=")[1])
65 else:
66 self.msg.warning("Not even the -number- of settings before and after initialisation of Pythia8 matches, check yourself what's going wrong.")
67
68 def cmpparticledata(self,pids,rpd):
69 # open particledata before initialisation
72 if f1.endswith('xml'):
73 f1 = f1[:-3]
74 f1 += "orig.xml"
75 try:
76 doc1 = xml.dom.minidom.parse(f1)
77 except Exception:
78 # not yet a problem, particledata files needs to be decorated to be xml compliant
79 self.ensure_toplevel(f1)
80 try:
81 doc1 = xml.dom.minidom.parse(f1)
82 except Exception:
83 self.msg.error("Bad file, exiting")
84 return
85
86 # open particledata after initialisation
87 try:
88 doc2 = xml.dom.minidom.parse(f2)
89 except Exception:
90 # not yet a problem, particledata files needs to be decorated to be xml compliant
91 self.ensure_toplevel(f2)
92 try:
93 doc2 = xml.dom.minidom.parse(f2)
94 except Exception:
95 self.msg.error("Bad file, exiting")
96 return
97
98
99 particles1 = doc1.getElementsByTagName("particle")
100 particles2 = doc2.getElementsByTagName("particle")
101 if (particles1.length == particles2.length):
102 self.msg.info("Number of particles before and after Pythia8 initialisation matches ( %d )", particles1.length)
103 else:
104 self.msg.warning("Mismatch in number of particles before and after Pythia8 initialisation. Before: %d , after: %d", particles1.length, particles2.length)
105 for part1 in particles1:
106 if ( part1.getAttribute("id") in pids):
107 for part2 in particles2:
108 if ( part2.getAttribute("id") == part1.getAttribute("id") ):
109 for attrk2, attrv2 in part2.attributes.items():
110 requested="none"
111 trypartprop = part2.getAttribute("id")+":"+attrk2
112 if ( trypartprop in rpd ):
113 requested = rpd[trypartprop]
114 if ( not ( attrk2 in part1.attributes.keys() ) ):
115 self.msg.info("You asked Pythia8 to modify properties for particle %s (%s). Attribute \"%s\" added after initialisation, check it. Requested: %s. After init: %s.", part2.getAttribute("name"), part2.getAttribute("id"), attrk2, requested, attrv2)
116 for attrk1, attrv1 in part1.attributes.items():
117 if (attrk1 == attrk2 and attrv1 != attrv2):
118 self.msg.warning("You asked Pythia8 to modify properties for particle %s (%s). Attribute \"%s\" modified after initialisation. Requested: %s. Before init: %s. After init: %s.", part1.getAttribute("name"), part1.getAttribute("id"), attrk1, requested, attrv1, attrv2)
119
120
121
122 def initialize(self):
123 self.msg.info('Running in serial mode.')
124 return StatusCode.Success
125
126 def execute(self):
127 return StatusCode.Success
128
129 def finalize(self):
130 # get list of PIDs for which user asked some changes
131 joparticles = [ i.replace(" ", "").split(":")[0] for i in self.Pythia8Commands if (i[0].isdigit()) ]
132 requestedparticledata = { i.replace(" ", "").split("=")[0]:i.split("=")[1].strip() for i in self.Pythia8Commands if (i[0].isdigit()) }
133 requestedsettings = { i.replace(" ", "").split("=")[0]:i.split("=")[1].strip() for i in self.Pythia8Commands if (not i[0].isdigit()) }
134 self.cmpsettings(requestedsettings)
135 self.cmpparticledata(joparticles,requestedparticledata)
136 return StatusCode.Success
137
138
__init__(self, name="Pythia8Util", outputParticleDataFile="ParticleData.local.xml", threshold=50)
ensure_toplevel(self, file_name)
cmpparticledata(self, pids, rpd)
cmpsettings(self, requestedsettings)
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:177
void initialize()