ATLAS Offline Software
Loading...
Searching...
No Matches
RatesAnalysis/python/Util.py
Go to the documentation of this file.
2# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
3#
4#
5
6'''
7@file Util.py
8@brief Utility functions used by RatesPostProcessing
9'''
10
11from AthenaCommon.Logging import logging
12log = logging.getLogger('RatesPostProcessing')
13
14def getTableName(name):
15 tabName = "Table_Rate_"
16 if name == "HLT" or name == "L1":
17 tabName += "Chain" + name
18 else:
19 tabName += name
20
21 tabName += "_HLT_All.csv"
22
23 return tabName
24
25
26def toCSV(fileName, metadata, HLTTriggers, readL1=False):
27 import csv
28
29 with open(fileName, mode='w') as outputCSV_file:
30 rates_csv_writer = csv.writer(outputCSV_file, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)
31
32 rates_csv_writer.writerow(['Name','Active Time [s]','Group','Weighted PS Rate [Hz]','Weighted PS Rate Err [Hz]', \
33 'Unique Rate [Hz]','Unique Rate Err [Hz]','Express Rate [Hz]','Express Rate Err [Hz]','Prescale','Express Prescale','ID', \
34 'Raw Active Events','Raw Pass Events','Active Events','Input Rate [Hz]','Pass Fraction after PS [%]','Pass Weighted PS'])
35 rates_csv_writer.writerow(['Trigger name','Integrated length of all lumi blocks which contributed events to this rates prediction.','The group this chain belongs to.','Rate after applying all prescale(s) as weights.','Error on rate after applying all prescale(s) as weights','Total rate without this chain rate','Error on unique rate','Express stream rate','Error on express rate','The prescale of this chain. Only displayed for simple combinations.','The prescale of the chain including express prescale','The CPTID or HLT Chain ID','Raw underlying statistics on the number events processed for this chain.','Raw underlying statistics on the number events passed by this chain.','Number of events in which the chain - or at least one chain in the combination - was executed.','Input rate to this chain or combination of chains. At L1 this will be the collision frequency for the bunch pattern.','Fraction of events which pass this trigger after prescale.','Number of events this chain or combination passed after applying prescales as weighting factors.'])
36
37 for trig in HLTTriggers:
38
39 group_name = chain_id = ""
40 if "ChainL1" in fileName:
41 group_name = "None"
42 chain_id = metadata["itemID"].get(trig.name)
43 elif "ChainHLT" in fileName:
44 group_name = metadata["chainGroup"].get(trig.name)
45 chain_id = metadata["chainID"].get(trig.name)
46 elif "Group" in fileName:
47 chain_id = 0
48 group_name = "All" if "GLOBAL" in trig.name else group_name
49
50 if float(trig.rateDenominator)==0:
51 print("float(trig.rateDenominator) is ZERO! This shouldn't happen")
52 if float(trig.activeWeighted)==0:
53 passFrac_afterPS=0
54 else:
55 passFrac_afterPS=100*float(trig.passWeighted)/float(trig.activeWeighted)
56
57 isL1 = trig.name.startswith("L1_")
58 rates_csv_writer.writerow([trig.name,"%.4f" % trig.rateDenominator,group_name,"%.4f" % trig.rate,"%.4f" % trig.rateErr, \
59 "%.4f" % trig.rateUnique,"%.4f" % trig.rateUniqueErr, ("%.4f" % trig.rateExpress if not isL1 else "-"), ("%.4f" % trig.rateExpressErr if not isL1 else "-"), \
60 trig.prescale, (trig.expressPrescale if not isL1 else "-"), chain_id, "%.0f" % trig.activeRaw,"%.0f" % trig.passRaw,"%.4f" % trig.activeWeighted, \
61 "%.4f" % (float(trig.activeWeighted)/float(trig.rateDenominator)),"%.4f" % passFrac_afterPS,"%.4f" % trig.passWeighted])
62
63
64
65def toJson(fileName, metadata, L1Triggers, HLTTriggers):
66 import json
67 l1 = {}
68 for trig in L1Triggers:
69 trig.export(l1)
70 hlt = {}
71 for trig in HLTTriggers:
72 trig.export(hlt)
73
74 level = {}
75 level['L1'] = l1
76 level['HLT'] = hlt
77
78 jsonDict = {}
79 jsonDict['PredictionLumi'] = metadata['targetLumi']
80 for k,v in metadata.items():
81 if k.startswith("n_evts"):
82 jsonDict[k] = v
83 jsonDict['AtlasProject'] = metadata['AtlasProject']
84 jsonDict['AtlasVersion'] = metadata['AtlasVersion']
85 jsonDict['triggerMenuSetup'] = metadata['masterKey']
86 jsonDict['L1PrescaleSet'] = metadata['lvl1PrescaleKey']
87 jsonDict['HLTPrescaleSet'] = metadata['hltPrescaleKey']
88 jsonDict['bunchgroup'] = metadata['bunchGroups']
89 jsonDict['level'] = level
90
91 with open(fileName, 'w') as outFile:
92 json.dump(obj=jsonDict, fp=outFile, indent=2, sort_keys=True)
93
94
95 metajsonData = [
96 {'PredictionLumi' : metadata['targetLumi']},
97 {'TargetMu' : metadata['targetMu']},
98 {'RunNumber' : metadata['runNumber']},
99 {'Details' : metadata['details']},
100 {'JIRA' : metadata['JIRA']},
101 {'AMITag' : metadata['amiTag']},
102 {'SMK' : metadata['masterKey']},
103 {'DB' : readDBFromAMI(metadata['amiTag']) if metadata['amiTag'] else None},
104 {'LVL1PSK' : metadata['lvl1PrescaleKey']},
105 {'HLTPSK' : metadata['hltPrescaleKey']},
106 {'AtlasProject' : metadata['AtlasProject']},
107 {'AtlasVersion' : metadata['AtlasVersion']}
108 ]
109 for k,v in metadata.items():
110 if k.startswith("n_evts"):
111 metajsonData+={jsonDict[k] : v}
112
113
114 metajsonDict = {}
115 metajsonDict['text'] = 'metadata'
116 metajsonDict['children'] = metajsonData
117
118 with open('metadata.json', 'w') as outMetaFile:
119 json.dump(obj=metajsonDict, fp=outMetaFile, indent=2, sort_keys=True)
120
121
122def toROOT(fileName, triggers):
123 mydict = {}
124 for trigger in triggers:
125 trigger.export(mydict)
126 from ROOT import TFile
127 with TFile.Open(fileName, 'RECREATE') as fout:
128 for key, scanDict in mydict.items():
129 fout.WriteObject(scanDict['rate'], f"{key}_rate")
130
131
132def getMetadata(inputFile):
133 '''Get metadata for rates.json file'''
134 metatree = inputFile.Get("metadata")
135 if metatree is None:
136 return None
137
138 metatree.GetEntry(0)
139 metadata = {}
140
141 metadata['runNumber'] = metatree.runNumber
142
143 metadata['targetMu'] = metatree.targetMu
144 metadata['targetBunches'] = metatree.targetBunches
145 metadata['targetLumi'] = metatree.targetLumi
146
147 metadata['masterKey'] = metatree.masterKey
148 metadata['lvl1PrescaleKey'] = metatree.lvl1PrescaleKey
149 metadata['hltPrescaleKey'] = metatree.hltPrescaleKey
150
151 metadata['AtlasProject'] = str(metatree.AtlasProject)
152 metadata['AtlasVersion'] = str(metatree.AtlasVersion)
153
154 metadata['bunchCrossingRate'] = metatree.bunchCrossingRate
155
156 metadata['multiSliceDiJet'] = metatree.multiSliceDiJet
157
158 prescales = {}
159 lowers = {}
160 express = {}
161 for i in range(0, metatree.triggers.size()):
162 prescale = metatree.prescales.at(i)
163 expressPrescale = metatree.express.at(i)
164 # Handle group prescale values
165 prescales[metatree.triggers.at(i)] = prescale if prescale >= -1 else "Multiple"
166 lowers[metatree.triggers.at(i)] = str(metatree.lowers.at(i))
167 express[metatree.triggers.at(i)] = expressPrescale if expressPrescale >= -1 else "Multiple"
168
169 metadata['prescales'] = prescales
170 metadata['lowers'] = lowers
171 metadata['express'] = express
172
173 chainid = {}
174 chaingroup = {}
175 for i in range(0, metatree.hltChainIDGroup.size()):
176 chainid[metatree.hltChainIDGroup.at(i).at(0)] = metatree.hltChainIDGroup.at(i).at(1)
177 chaingroup[metatree.hltChainIDGroup.at(i).at(0)] = metatree.hltChainIDGroup.at(i).at(2)
178
179 metadata['chainID'] = chainid
180 metadata['chainGroup'] = chaingroup
181
182 itemid = {}
183 for i in range(0, metatree.l1ItemID.size()):
184 itemid[metatree.l1ItemID.at(i).at(0)] = metatree.l1ItemID.at(i).at(1)
185
186 metadata['itemID'] = itemid
187
188 bunchGroups = []
189 for bg in metatree.bunchGroups:
190 bunchGroups.append(bg)
191 metadata['bunchGroups'] = bunchGroups
192
193 return metadata
194
195
196def populateTriggers(inputFile, metadata, globalGroupDict, filter):
197 # Fix groups' names that are also not GLOBAL
198 def getTriggerName(name, filter):
199 if "Group" in filter and "GLOBAL" not in name:
200 return name.replace('_', ':', 1)
201 else:
202 return name
203
204 from .RatesTrigger import RatesTrigger
205 triggerList = []
206 for key in inputFile.GetListOfKeys():
207 if key.GetName() == 'All':
208 for subdirKey in key.ReadObj().GetListOfKeys():
209 if filter not in subdirKey.GetName(): continue
210 for triggerKey in subdirKey.ReadObj().GetListOfKeys():
211 numeratorDict = slice_dictionary(triggerKey.ReadObj(),"data")
212 for suffix, data in numeratorDict.items():
213 try:
214 triggerList.append(RatesTrigger(getTriggerName(triggerKey.GetName(), filter)+suffix, metadata, data, globalGroupDict[suffix], suffix))
215 except ValueError:
216 log.error("Cannot create a new trigger for {0}".format(triggerKey.GetName()))
217 return []
218 return triggerList
219
220
221def slice_dictionary(directory, object_key):
222 slices_dict = {}
223 for hist in directory.GetListOfKeys():
224 if str(hist.GetName()).startswith(object_key):
225 try:
226 slice_index = "_"+str(hist.GetName()).split("_")[1]
227 except IndexError:
228 slice_index = ""
229 slices_dict[slice_index] = hist.ReadObj()
230 return slices_dict
231
232def populateScanTriggers(inputFile, metadata):
233 from .RatesScanTrigger import RatesScanTrigger
234 triggerList = []
235 for key in inputFile.GetListOfKeys():
236 if key.GetName() == 'ScanTriggers':
237 for scanName in key.ReadObj().GetListOfKeys():
238 numerator_dict = slice_dictionary(scanName.ReadObj(), "rateVsThreshold")
239 if len(numerator_dict) == 0:
240 log.error(f"Empty dictionary in populateScanTriggers for scan {scanName}")
241 continue
242 else:
243 triggerList.append(RatesScanTrigger(scanName.GetName(), metadata, numerator_dict))
244 return triggerList
245
246def getGlobalGroup(inputFile, filter):
247 for key in inputFile.GetListOfKeys():
248 if key.GetName() == 'All':
249 for subdirKey in key.ReadObj().GetListOfKeys():
250 if not subdirKey.GetName() == "Rate_Group_HLT" : pass
251 for globalsKey in subdirKey.ReadObj().GetListOfKeys():
252 if filter in globalsKey.GetName():
253 groupsDict = slice_dictionary(globalsKey.ReadObj(), "data")
254 return groupsDict
255
256
257def readDBFromAMI(amiTag):
258 ''' Read used database based on AMI tag '''
259 try:
260 import pyAMI.client
261 import pyAMI.atlas.api as AtlasAPI
262 except ModuleNotFoundError:
263 log.warning("Unable to import AMIClient from pyAMI. Maybe you didn't do localSetupPyAMI?")
264 return ""
265
266 amiclient = pyAMI.client.Client('atlas')
267 AtlasAPI.init()
268
269 command = [ 'AMIGetAMITagInfo', '-amiTag="%s"' % amiTag, '-cached' ]
270 amiTagInfo = amiclient.execute(command, format = 'dict_object').get_rows('amiTagInfo')[0]
271
272 return amiTagInfo['DBserver'] if "DBserver" in amiTagInfo else None
void print(char *figname, TCanvas *c1)
Used to calculate a rate scan as a function of some threshold value.
Used to calculate the rate for a single trigger at L1 or the HLT.
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition hcg.cxx:130
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:177
getGlobalGroup(inputFile, filter)
slice_dictionary(directory, object_key)
toCSV(fileName, metadata, HLTTriggers, readL1=False)
populateTriggers(inputFile, metadata, globalGroupDict, filter)
populateScanTriggers(inputFile, metadata)
toJson(fileName, metadata, L1Triggers, HLTTriggers)
toROOT(fileName, triggers)