ATLAS Offline Software
Loading...
Searching...
No Matches
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
6from xml.dom import minidom
7import re
8
9from AthenaCommon.Logging import logging
10log = logging.getLogger('MergeEBWeigtsFiles.py')
11
12# Create a list of unique weights and a list of events with updated weights' ids
13def 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
52def 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
63def 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
73def 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
80if __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)
mergeEBWeightsFiles(input_files)
checkRunNumber(runNumber, input_files)
createWeightsNode(xmlDoc, xmlRoot, weights_list)
createEventsNode(xmlDoc, xmlRoot, events_list)