ATLAS Offline Software
MergeEBWeightsFiles.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 #
3 # Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
4 #
5 
6 from xml.dom import minidom
7 import re
8 
9 from AthenaCommon.Logging import logging
10 log = logging.getLogger('MergeEBWeigtsFiles.py')
11 
12 # Create a list of unique weights and a list of events with updated weights' ids
13 def mergeEBWeightsFiles(input_files):
14  check_weight = []
15  weightsList = []
16  eventsList = []
17 
18  new_id=0
19  log.debug("Processing file {0}".format(list(input_files.keys())[0]))
20  weights = list(input_files.values())[0].getElementsByTagName("weight")
21  for weight in weights:
22  weightsList.append({"value":weight.getAttribute("value"), "unbiased":weight.getAttribute("unbiased"), "id":str(new_id)})
23  check_weight.append({"value": weight.getAttribute("value"), "unbiased":weight.getAttribute("unbiased")})
24  new_id+=1
25  events = list(input_files.values())[0].getElementsByTagName("e")
26  for event in events:
27  eventsList.append({"n":event.getAttribute("n"), "w":event.getAttribute("w")})
28 
29  for fin_name, fin in list(input_files.items())[1:]:
30  log.debug("Processing file {0}".format(fin_name))
31  id_map = {} # mapping between old and new ids
32  weights = fin.getElementsByTagName("weight")
33  for weight in weights:
34  element = {"value": weight.getAttribute("value"), "unbiased":weight.getAttribute("unbiased")}
35  # If the weight is not already in the list, add it to the list, update the id and associate the new id to the old one through id_map
36  # If the weight is already in the list, only associate the new id to the old one through id_map
37  if element not in check_weight:
38  check_weight.append(element.copy())
39  element["id"] = str(new_id)
40  weightsList.append(element)
41  id_map[weight.getAttribute("id")]=element["id"]
42  new_id+=1
43  else:
44  id_map[weight.getAttribute("id")]=weightsList[check_weight.index(element)]["id"]
45  events = fin.getElementsByTagName("e")
46  # Loop on events to update the weights ids
47  for event in events:
48  eventsList.append({"n":event.getAttribute("n"), "w":id_map[event.getAttribute("w")]})
49  return weightsList, eventsList
50 
51 # Create weights node
52 def createWeightsNode(xmlDoc, xmlRoot, weights_list):
53  weights_element = xmlDoc.createElement("weights")
54  xmlRoot.appendChild(weights_element)
55  for weight in weights_list:
56  w=doc.createElement("weight")
57  w.setAttribute("id", weight["id"])
58  w.setAttribute("value", weight["value"])
59  w.setAttribute("unbiased", weight["unbiased"])
60  weights_element.appendChild(w)
61 
62 # Create events node
63 def createEventsNode(xmlDoc, xmlRoot, events_list):
64  events_element = xmlDoc.createElement("events")
65  xmlRoot.appendChild(events_element)
66  for event in events_list:
67  e=doc.createElement("e")
68  e.setAttribute("n", event["n"])
69  e.setAttribute("w", event["w"])
70  events_element.appendChild(e)
71 
72 # Check that all the input files have the same run number
73 def checkRunNumber(runNumber, input_files):
74  for fin in input_files[1:]:
75  rn = re.compile(r'\d+')
76  rn = rn.findall(fin)
77  if rn[-1] != runNumber[-1]:
78  sys.exit("ERROR: run number should be the same for all input files. Exiting.")
79 
80 if __name__=='__main__':
81  import sys
82  from argparse import ArgumentParser
83  parser = ArgumentParser()
84  parser.add_argument('--inputfiles', nargs='*', help='Insert input xml files')
85  parser.add_argument('--outputfile', default="EnhancedBiasWeights_[RUN_NUMBER]_merged.xml", help='Optional: insert output file name')
86  parser.add_argument('--loglevel', type=int, default=3, help='Verbosity level: 1 - VERBOSE, 2 - DEBUG, 3 - INFO')
87  args = parser.parse_args()
88 
89  log.setLevel(args.loglevel)
90 
91  input_files = args.inputfiles
92  if input_files:
93  if len(input_files) < 2:
94  sys.exit("ERROR: insert at least 2 input files. Exiting.")
95  else:
96  sys.exit("ERROR: insert at least 2 input files. Exiting.")
97 
98  # parse run number and check that all the input files have the same run number
99  runNumber = re.compile(r'\d+')
100  runNumber = runNumber.findall(input_files[0])
101  checkRunNumber(runNumber, input_files)
102 
103  parsed_files = {}
104  for fin in input_files:
105  parsed_files[fin] = minidom.parse(fin)
106 
107  # Create weights and events merged lists
108  weights_list, events_list = mergeEBWeightsFiles(parsed_files)
109 
110  # XML document base
111  doc = minidom.parseString("<run/>")
112  root = doc.documentElement
113 
114  # Add weights and events nodes
115  createWeightsNode(doc, root, weights_list)
116  createEventsNode(doc, root, events_list)
117 
118  # Write to file
119  output_filename = args.outputfile
120  if '[RUN_NUMBER]' in output_filename:
121  output_filename = output_filename.replace('[RUN_NUMBER]', runNumber[-1])
122  log.debug("Weights written to file {0}".format(output_filename))
123 
124  xml_str = root.toprettyxml(indent = " ")
125  with open(output_filename, "w") as f:
126  f.write(xml_str)
vtune_athena.format
format
Definition: vtune_athena.py:14
MergeEBWeightsFiles.createWeightsNode
def createWeightsNode(xmlDoc, xmlRoot, weights_list)
Definition: MergeEBWeightsFiles.py:52
MergeEBWeightsFiles.createEventsNode
def createEventsNode(xmlDoc, xmlRoot, events_list)
Definition: MergeEBWeightsFiles.py:63
MergeEBWeightsFiles.checkRunNumber
def checkRunNumber(runNumber, input_files)
Definition: MergeEBWeightsFiles.py:73
histSizes.list
def list(name, path='/')
Definition: histSizes.py:38
Trk::open
@ open
Definition: BinningType.h:40
str
Definition: BTagTrackIpAccessor.cxx:11
MergeEBWeightsFiles.mergeEBWeightsFiles
def mergeEBWeightsFiles(input_files)
Definition: MergeEBWeightsFiles.py:13