ATLAS Offline Software
Pythia8Util.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
2 
3 from GeneratorModules.EvgenAlg import EvgenAlg
4 from AthenaPython.PyAthena import StatusCode
5 import os
6 import xml.dom.minidom
7 import filecmp
8 
9 __author__ = 'Giancarlo Panizzo <giancarlo.panizzo@cern.ch>'
10 
11 
12 class 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
23  self.Pythia8Commands = []
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 
grepfile.info
info
Definition: grepfile.py:38
python.Pythia8Util.Pythia8Util.outputParticleDataFile
outputParticleDataFile
Definition: Pythia8Util.py:24
python.Pythia8Util.Pythia8Util.ensure_toplevel
def ensure_toplevel(self, file_name)
Definition: Pythia8Util.py:26
python.Pythia8Util.Pythia8Util.threshold
threshold
Definition: Pythia8Util.py:19
python.Pythia8Util.Pythia8Util.cmpparticledata
def cmpparticledata(self, pids, rpd)
Definition: Pythia8Util.py:68
python.Pythia8Util.Pythia8Util.execute
def execute(self)
Definition: Pythia8Util.py:126
python.Pythia8Util.Pythia8Util.Pythia8Commands
Pythia8Commands
Definition: Pythia8Util.py:23
python.Pythia8Util.Pythia8Util.finalize
def finalize(self)
Definition: Pythia8Util.py:129
plotBeamSpotVxVal.range
range
Definition: plotBeamSpotVxVal.py:195
python.Pythia8Util.Pythia8Util.njobs
njobs
Definition: Pythia8Util.py:21
python.Pythia8Util.Pythia8Util.initialize
def initialize(self)
Definition: Pythia8Util.py:122
python.Pythia8Util.Pythia8Util.cmpsettings
def cmpsettings(self, requestedsettings)
Definition: Pythia8Util.py:44
Trk::open
@ open
Definition: BinningType.h:40
python.Pythia8Util.Pythia8Util.mode
mode
Definition: Pythia8Util.py:22
python.Pythia8Util.Pythia8Util.__init__
def __init__(self, name="Pythia8Util", outputParticleDataFile="ParticleData.local.xml", threshold=50)
Definition: Pythia8Util.py:17
python.Pythia8Util.Pythia8Util
Definition: Pythia8Util.py:12
error
Definition: IImpactPoint3dEstimator.h:70
Trk::split
@ split
Definition: LayerMaterialProperties.h:38