ATLAS Offline Software
RatesAnalysis/python/Util.py
Go to the documentation of this file.
1 #
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 
11 from AthenaCommon.Logging import logging
12 log = logging.getLogger('RatesPostProcessing')
13 
14 def 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 
26 def 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 
65 def 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 
122 def 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 
132 def 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 
196 def 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 
221 def 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 
232 def 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 
246 def 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 
257 def 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
python.Util.toCSV
def toCSV(fileName, metadata, HLTTriggers, readL1=False)
Definition: RatesAnalysis/python/Util.py:26
RatesScanTrigger
Used to calculate a rate scan as a function of some threshold value.
Definition: RatesScanTrigger.h:14
vtune_athena.format
format
Definition: vtune_athena.py:14
python.Util.slice_dictionary
def slice_dictionary(directory, object_key)
Definition: RatesAnalysis/python/Util.py:221
python.Util.getGlobalGroup
def getGlobalGroup(inputFile, filter)
Definition: RatesAnalysis/python/Util.py:246
python.Util.readDBFromAMI
def readDBFromAMI(amiTag)
Definition: RatesAnalysis/python/Util.py:257
python.Util.populateTriggers
def populateTriggers(inputFile, metadata, globalGroupDict, filter)
Definition: RatesAnalysis/python/Util.py:196
RatesTrigger
Used to calculate the rate for a single trigger at L1 or the HLT.
Definition: RatesTrigger.h:15
plotBeamSpotVxVal.range
range
Definition: plotBeamSpotVxVal.py:194
python.Util.getMetadata
def getMetadata(inputFile)
Definition: RatesAnalysis/python/Util.py:132
print
void print(char *figname, TCanvas *c1)
Definition: TRTCalib_StrawStatusPlots.cxx:25
python.Util.getTableName
def getTableName(name)
Definition: RatesAnalysis/python/Util.py:14
python.Util.toJson
def toJson(fileName, metadata, L1Triggers, HLTTriggers)
Definition: RatesAnalysis/python/Util.py:65
Trk::open
@ open
Definition: BinningType.h:40
get
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition: hcg.cxx:127
python.Util.populateScanTriggers
def populateScanTriggers(inputFile, metadata)
Definition: RatesAnalysis/python/Util.py:232
str
Definition: BTagTrackIpAccessor.cxx:11
python.Util.toROOT
def toROOT(fileName, triggers)
Definition: RatesAnalysis/python/Util.py:122
Trk::split
@ split
Definition: LayerMaterialProperties.h:38
python.LArMinBiasAlgConfig.float
float
Definition: LArMinBiasAlgConfig.py:65