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.append({k: v})
112
113 metajsonDict = {}
114 metajsonDict['text'] = 'metadata'
115 metajsonDict['children'] = metajsonData
116
117 with open('metadata.json', 'w') as outMetaFile:
118 json.dump(obj=metajsonDict, fp=outMetaFile, indent=2, sort_keys=True)
119
120
121def toROOT(fileName, triggers):
122 mydict = {}
123 for trigger in triggers:
124 trigger.export(mydict)
125 from ROOT import TFile
126 with TFile.Open(fileName, 'RECREATE') as fout:
127 for key, scanDict in mydict.items():
128 fout.WriteObject(scanDict['rate'], f"{key}_rate")
129
130
131def getMetadata(inputFile):
132 '''Get metadata for rates.json file'''
133 metatree = inputFile.Get("metadata")
134 if metatree is None:
135 return None
136
137 metatree.GetEntry(0)
138 metadata = {}
139
140 metadata['runNumber'] = metatree.runNumber
141
142 metadata['targetMu'] = metatree.targetMu
143 metadata['targetBunches'] = metatree.targetBunches
144 metadata['targetLumi'] = metatree.targetLumi
145
146 metadata['masterKey'] = metatree.masterKey
147 metadata['lvl1PrescaleKey'] = metatree.lvl1PrescaleKey
148 metadata['hltPrescaleKey'] = metatree.hltPrescaleKey
149
150 metadata['AtlasProject'] = str(metatree.AtlasProject)
151 metadata['AtlasVersion'] = str(metatree.AtlasVersion)
152
153 metadata['bunchCrossingRate'] = metatree.bunchCrossingRate
154
155 metadata['multiSliceDiJet'] = metatree.multiSliceDiJet
156
157 prescales = {}
158 lowers = {}
159 express = {}
160 for i in range(0, metatree.triggers.size()):
161 prescale = metatree.prescales.at(i)
162 expressPrescale = metatree.express.at(i)
163 # Handle group prescale values
164 prescales[metatree.triggers.at(i)] = prescale if prescale >= -1 else "Multiple"
165 lowers[metatree.triggers.at(i)] = str(metatree.lowers.at(i))
166 express[metatree.triggers.at(i)] = expressPrescale if expressPrescale >= -1 else "Multiple"
167
168 metadata['prescales'] = prescales
169 metadata['lowers'] = lowers
170 metadata['express'] = express
171
172 chainid = {}
173 chaingroup = {}
174 for i in range(0, metatree.hltChainIDGroup.size()):
175 chainid[metatree.hltChainIDGroup.at(i).at(0)] = metatree.hltChainIDGroup.at(i).at(1)
176 chaingroup[metatree.hltChainIDGroup.at(i).at(0)] = metatree.hltChainIDGroup.at(i).at(2)
177
178 metadata['chainID'] = chainid
179 metadata['chainGroup'] = chaingroup
180
181 itemid = {}
182 for i in range(0, metatree.l1ItemID.size()):
183 itemid[metatree.l1ItemID.at(i).at(0)] = metatree.l1ItemID.at(i).at(1)
184
185 metadata['itemID'] = itemid
186
187 bunchGroups = []
188 for bg in metatree.bunchGroups:
189 bunchGroups.append(bg)
190 metadata['bunchGroups'] = bunchGroups
191
192 return metadata
193
194
195def populateTriggers(inputFile, metadata, globalGroupDict, filter):
196 # Fix groups' names that are also not GLOBAL
197 def getTriggerName(name, filter):
198 if "Group" in filter and "GLOBAL" not in name:
199 return name.replace('_', ':', 1)
200 else:
201 return name
202
203 from .RatesTrigger import RatesTrigger
204 triggerList = []
205 for key in inputFile.GetListOfKeys():
206 if key.GetName() == 'All':
207 for subdirKey in key.ReadObj().GetListOfKeys():
208 if filter not in subdirKey.GetName(): continue
209 for triggerKey in subdirKey.ReadObj().GetListOfKeys():
210 numeratorDict = slice_dictionary(triggerKey.ReadObj(),"data")
211 for suffix, data in numeratorDict.items():
212 try:
213 triggerList.append(RatesTrigger(getTriggerName(triggerKey.GetName(), filter)+suffix, metadata, data, globalGroupDict[suffix], suffix))
214 except ValueError:
215 log.error("Cannot create a new trigger for {0}".format(triggerKey.GetName()))
216 return []
217 return triggerList
218
219
220def slice_dictionary(directory, object_key):
221 slices_dict = {}
222 for hist in directory.GetListOfKeys():
223 if str(hist.GetName()).startswith(object_key):
224 try:
225 slice_index = "_"+str(hist.GetName()).split("_")[1]
226 except IndexError:
227 slice_index = ""
228 slices_dict[slice_index] = hist.ReadObj()
229 return slices_dict
230
231def populateScanTriggers(inputFile, metadata):
232 from .RatesScanTrigger import RatesScanTrigger
233 triggerList = []
234 for key in inputFile.GetListOfKeys():
235 if key.GetName() == 'ScanTriggers':
236 for scanName in key.ReadObj().GetListOfKeys():
237 numerator_dict = slice_dictionary(scanName.ReadObj(), "rateVsThreshold")
238 if len(numerator_dict) == 0:
239 log.error(f"Empty dictionary in populateScanTriggers for scan {scanName}")
240 continue
241 else:
242 triggerList.append(RatesScanTrigger(scanName.GetName(), metadata, numerator_dict))
243 return triggerList
244
245def getGlobalGroup(inputFile, filter):
246 for key in inputFile.GetListOfKeys():
247 if key.GetName() == 'All':
248 for subdirKey in key.ReadObj().GetListOfKeys():
249 if not subdirKey.GetName() == "Rate_Group_HLT" : pass
250 for globalsKey in subdirKey.ReadObj().GetListOfKeys():
251 if filter in globalsKey.GetName():
252 groupsDict = slice_dictionary(globalsKey.ReadObj(), "data")
253 return groupsDict
254
255
256def readDBFromAMI(amiTag):
257 ''' Read used database based on AMI tag '''
258 try:
259 import pyAMI.client
260 import pyAMI.atlas.api as AtlasAPI
261 except ModuleNotFoundError:
262 log.warning("Unable to import AMIClient from pyAMI. Maybe you didn't do localSetupPyAMI?")
263 return ""
264
265 amiclient = pyAMI.client.Client('atlas')
266 AtlasAPI.init()
267
268 command = [ 'AMIGetAMITagInfo', '-amiTag="%s"' % amiTag, '-cached' ]
269 amiTagInfo = amiclient.execute(command, format = 'dict_object').get_rows('amiTagInfo')[0]
270
271 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:132
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:179
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)