8 This class is designed to handle registering all of L1Calo's monitoring histograms and trees in a
9 coherent way. It will also generate the han config file for all the histograms.
14 from collections
import defaultdict
17 hanThresholdConfigs = {}
19 SIGNATURES = [
"gJ",
"gLJ",
"gLJRho",
"gXEJWOJ",
"gTEJWOJ",
"gXENC",
"gTENC",
"gXERHO",
"gTERHO",
"jJ",
"jEM",
"jTAU",
"jXE",
"jTE",
"eTAU",
"eEM"]
20 HELPURL =
"https://codimd.web.cern.ch/s/678H65Tk9"
24 from contextlib
import redirect_stdout
25 from PathResolver
import PathResolver
27 with open(filename,
'w')
as f:
30 with open(header,
'r')
as fh:
31 for line
in fh: f.write(line)
32 with redirect_stdout(f):
42 def printConf(d,prefix=""):
43 for key,value
in d.items():
46 if(key==
"dir detail" or key==
"dir Developer"):
47 print(prefix+
" algorithm = GatherData")
48 if key.startswith(
"dir ")
and any([x.startswith(
"hist ")
for x
in value.keys()]):
50 for childKey,childVal
in value.items():
51 if childKey.startswith(
"hist ")
and "output" in childVal:
52 print(prefix+
" output = "+childVal[
"output"])
54 printConf(value,prefix +
" ")
58 if key ==
"output": outputs.add(value)
59 else:
print(prefix,key,
"=",value)
64 printConf(L1CaloMonitorCfgHelper.hanConfigs,
" ")
67 print(
"output top_level {")
68 def printOutputs(d,prefix=""):
69 for key,value
in d.items():
70 if(key.startswith(
"hist ")):
72 elif type(value)==dict:
73 print(prefix,key.replace(
"dir ",
"output "),
"{")
74 printOutputs(value,prefix +
" ")
76 print(
" output L1Calo {")
77 printOutputs(L1CaloMonitorCfgHelper.hanConfigs,
" ")
83 algorithm AnyNonZeroBinIsError {
84 # Use this algo if want error on any non-zero bin content
85 libname = libdqm_summaries.so
86 name = Bins_NotEqual_Threshold
88 thresholds = th_AnyBinIsError
91 for algName,algProps
in L1CaloMonitorCfgHelper.hanAlgConfigs.items():
92 print(f
"algorithm {algName} {{")
93 for propName,propVal
in algProps.items():
94 print(f
" {propName} = {propVal}")
98 thresholds th_AnyBinIsError {
105 for threshName,threshProps
in L1CaloMonitorCfgHelper.hanThresholdConfigs.items():
106 print(f
"thresholds {threshName} {{")
107 for parName,parLims
in threshProps.items():
108 print(f
" limits {parName} {{")
109 for limName,limVal
in parLims.items():
110 print(f
" {limName} = {limVal}")
116 def __init__(self, flags, algClassOrObj = None, name = None, *args, **kwargs):
118 Create the configuration helper.
121 flags -- the configuration flag object
122 algClassOrObj -- the name you want to assign the family of algorithms
124 from AthenaMonitoring
import AthMonitorCfgHelper
125 self.
helper = AthMonitorCfgHelper(flags,name)
126 self.
alg = self.
helper.addAlgorithm(algClassOrObj,name,*args, **kwargs)
if algClassOrObj
is not None else None
134 :param name: name of algorithm
135 :param hanConfig: dict of algo properties
136 :param thresholdConfig: dict of thresholds, keys in form of ParName.level
143 if thresholdConfig
is not None:
144 hanConfig[
"thresholds"] = f
"{name}Thresholds"
146 for parName,limVals
in thresholdConfig.items():
147 if len(limVals) != 2:
148 raise Exception(
"must specify two limits: warning and error")
149 if parName
not in threshDict: threshDict[parName] = {}
150 threshDict[parName][
"warning"] = limVals[0]
151 threshDict[parName][
"error"] = limVals[1]
154 if str(thresh)==
str(threshDict):
156 hanConfig[
"thresholds"] = threshName
174 hanConfig = dict(hanConfig)
179 self.
defineHistogram(*args,fillGroup=fillGroup,hanConfig=hanConfig,paths=[],path=path,**kwargs)
182 argsCopy =
list(args)
183 if ";" not in args[0]:
184 argsCopy[0] +=
";h_" + argsCopy[0].
replace(
":",
"_")
186 if kwargs.get(
"path",
None)
is None:
188 kwargs[
"path"] =
"Developer/" + self.
alg.name
189 elif kwargs[
"path"][-1] ==
'/':
190 kwargs[
"path"] = kwargs[
"path"][:-1]
192 splitPath = kwargs[
"path"].
split(
"/")
193 if splitPath[0]
not in [
"Shifter",
"Expert",
"Developer"]:
194 raise Exception(
"Path of histogram invalid, does not start with one of the allowed audiences (Shifter,Expert,Developer)")
197 if splitPath[0] !=
"Developer" and splitPath[-1] !=
"detail" and (
"algorithm" not in hanConfig):
199 if "description" not in hanConfig:
200 raise Exception(
"Must specify a hanConfig for a Shifter or Expert (non-detail) histogram")
202 hanConfig[
"algorithm"] =
"GatherData"
205 if fillGroup
is None: fillGroup = self.
alg.name +
"_fillGroup"
209 if "merge" not in kwargs
and kwargs.get(
"type",
"") !=
"TEfficiency":
210 kwargs[
"merge"] =
"merge"
212 histName = argsCopy[0].
split(
";")[-1]
215 if splitPath[0] ==
"Expert":
216 linkUrl = self.
HELPURL +
"#" +
"".
join(splitPath[1:]+[histName])
217 linkUrl = f
"<a href=\"{linkUrl}\">Help</a>"
218 if "description" not in hanConfig: hanConfig[
"description"] = linkUrl
219 else: hanConfig[
"description"] +=
" - " + linkUrl
222 if splitPath[0] ==
"Expert":
223 splitPathWithHist = splitPath + [histName]
224 x = L1CaloMonitorCfgHelper.hanConfigs
225 for i,p
in enumerate(splitPathWithHist):
226 key = (
"dir " if i!=len(splitPathWithHist)-1
else "hist ") + p
230 hanConfig[
"output"] =
"/".
join([
"L1Calo"]+splitPath)
237 if ";" not in args[0]:
238 raise Exception(
"Must specify a tree name using ';name' suffix")
239 treeName = args[0].
split(
";")[-1]
242 raise Exception(
"Should not have comma in list of branch names and types")
244 if kwargs.get(
"path",
None)
is None:
246 kwargs[
"path"] =
"Developer/" + self.
alg.name
249 splitPath = kwargs[
"path"].
split(
"/")
250 if splitPath[0]
not in [
"Developer"]:
251 raise Exception(
"Path of tree invalid, must be in the audience=Developer directory")
254 if fillGroup
is None: fillGroup = self.
alg.name +
"_fillGroup"
261 histName =
"h_" + treeName +
"_entries"
262 argsCopy =
list(args)
263 argsCopy[0] = argsCopy[0].
replace(
";"+treeName,
";"+histName)
264 kwargsCopy = dict(kwargs)
265 kwargsCopy[
"title"] = f
"Number of Entries in {treeName} TTree" +
";" +
";".
join(kwargsCopy.get(
"title",
"").
split(
";")[1:])
266 kwargsCopy[
"opt"] = [
'kCanRebin',
'kAddBinsDynamically']
267 kwargsCopy[
"merge"] =
"merge"
268 is2d = (kwargsCopy[
"title"].
count(
";")>1)
269 self.
defineHistogram(argsCopy[0],type=
"TH2I" if is2d
else "TH1I",xbins=1,xmin=0,xmax=1,ybins=1
if is2d
else None,ymin=0,ymax=1,fillGroup=fillGroup,**kwargsCopy)
270 if not any([x
in self.
dqEnv for x
in [
'tier0',
'online']]):
281 '''Function to call l1calo DQ monitoring algorithms'''
282 from AthenaConfiguration.ComponentAccumulator
import ComponentAccumulator
283 from AthenaConfiguration.Enums
import Format
287 local_logger = logging.getLogger(
'AthenaMonitoringCfg')
288 info = local_logger.info
289 info(
'In LVL1CaloMonitoringConfig')
294 if not flags.Trigger.Online.isPartition:
295 if not flags.DQ.triggerDataAvailable:
298 isData =
not flags.Input.isMC
301 validation=flags.DQ.Steering.LVL1Calo.doValidation
305 if not validation
and isData
and flags.DQ.Environment
not in (
'tier0Raw',
'AOD'):
307 from TrigT1CaloMonitoring.PprMonitorAlgorithm
import PprMonitoringConfig
308 from TrigT1CaloMonitoring.JepJemMonitorAlgorithm
import JepJemMonitoringConfig
311 from AthenaConfiguration.AutoConfigFlags
import GetFileMD
313 inputContainsRun3FormatConfigMetadata = (
"metadata_items" in md
and any((
'TriggerMenuJson' in key)
for key
in md[
"metadata_items"].
keys()))
316 if flags.Input.Format
is not Format.POOL
or inputContainsRun3FormatConfigMetadata:
322 detMask=eformat.helper.DetectorMask(f
'{md.get("detectorMask",[0x0])[0]:032x}')
323 hasCPM = detMask.is_set(eformat.helper.SubDetector.TDAQ_CALO_CLUSTER_PROC_DAQ)
324 hasJEP = detMask.is_set(eformat.helper.SubDetector.TDAQ_CALO_JET_PROC_DAQ)
327 from TrigT1CaloMonitoring.CpmMonitorAlgorithm
import CpmMonitoringConfig
328 from TrigT1CaloMonitoring.CpmSimMonitorAlgorithm
import CpmSimMonitoringConfig
333 from TrigT1CaloMonitoring.JepCmxMonitorAlgorithm
import JepCmxMonitoringConfig
336 from TrigT1CaloMonitoring.OverviewMonitorAlgorithm
import OverviewMonitoringConfig
337 from TrigT1CaloMonitoring.PPMSimBSMonitorAlgorithm
import PPMSimBSMonitoringConfig
343 OverviewMonAlg = result.getEventAlgo(
"OverviewMonAlg")
344 OverviewMonAlg.CPMErrorLocation =
""
345 OverviewMonAlg.CPMMismatchLocation =
""
347 if flags.Input.TriggerStream ==
"physics_Mistimed":
348 from TrigT1CaloMonitoring.MistimedStreamMonitorAlgorithm
import MistimedStreamMonitorConfig
352 if flags.Input.Format
is Format.BS:
353 from TrigT1CaloByteStream.LVL1CaloRun2ByteStreamConfig
import LVL1CaloRun2ReadBSCfg
357 if flags.Trigger.enableL1CaloPhase1
and flags.Input.Format
is not Format.POOL:
360 from L1CaloFEXSim.L1CaloFEXSimCfg
import L1CaloFEXSimCfg
364 if flags.Trigger.L1.doeFex:
365 from TrigT1CaloMonitoring.EfexInputMonitorAlgorithm
import EfexInputMonitoringConfig
369 from TrigT1CaloMonitoring.EfexSimMonitorAlgorithm
import EfexSimMonitoringConfig
373 if flags.Trigger.L1.dogFex:
375 from TrigT1CaloMonitoring.GfexInputMonitorAlgorithm
import GfexInputMonitoringConfig
378 from TrigT1CaloMonitoring.GfexSimMonitorAlgorithm
import GfexSimMonitoringConfig
382 if flags.Trigger.L1.dojFex:
384 from TrigT1CaloMonitoring.JfexInputMonitorAlgorithm
import JfexInputMonitoringConfig
388 from TrigT1CaloMonitoring.JfexSimMonitorAlgorithm
import JfexSimMonitoringConfig
390 result.merge(JfexSimMonitoring)
393 if validation
or (isData
and flags.DQ.Environment
not in (
'tier0Raw',
'AOD')):
397 from TrigT1CaloMonitoring.L1CaloLegacyEDMMonitorAlgorithm
import L1CaloLegacyEDMMonitoringConfig
401 if flags.Trigger.L1.doeFex:
402 from TrigT1CaloMonitoring.EfexMonitorAlgorithm
import EfexMonitoringConfig
404 from TrigT1CaloMonitoring.EfexMonitorAlgorithm
import EfexMonitoringHistConfig
408 if flags.Trigger.L1.dogFex:
409 from TrigT1CaloMonitoring.GfexMonitorAlgorithm
import GfexMonitoringConfig
413 if flags.Trigger.L1.dojFex:
414 from TrigT1CaloMonitoring.JfexMonitorAlgorithm
import JfexMonitoringConfig
418 if flags.Trigger.L1.dojFex
or flags.Trigger.L1.dogFex:
419 from TrigT1CaloMonitoring.JetEfficiencyMonitorAlgorithm
import JetEfficiencyMonitoringConfig
422 result.printConfig( withDetails=
True )
426 if __name__ ==
'__main__':
427 from AthenaConfiguration.AllConfigFlags
import initConfigFlags
428 from AthenaConfiguration.ComponentFactory
import CompFactory
429 from AthenaMonitoring.DQConfigFlags
import DQDataType
431 flags.DQ.useTrigger =
False
432 flags.DQ.Environment =
"user"
433 flags.DQ.DataType = DQDataType.MC
434 flags.DQ.enableLumiAccess =
False
437 h.defineHistogram(
"x,y;h_myHist",type=
'TH2D',path=
"Shifter/Blah",hanConfig={
"algorithm":
"blah"})
438 h.defineHistogram(
"x,y;h_myHis2t",type=
'TH2D',path=
"Shifter/Blah",hanConfig={
"algorithm":
"blah2"})
439 h.defineHistogram(
"x;anotherHist",type=
'TH1D',path=
"Developer/whatever",hanConfig={
"aaa":2})
440 h.defineTree(
"x,y,z,a,b;myTree",
"x/i:y/i:z/i:a/I:b/I",path=
"Developer/whatever")
443 h.defineDQAlgorithm(
"MyAlgo",
444 hanConfig={
"libname":
"libdqm_summaries.so",
"name":
"Bins_NotEqual_Threshold",
"BinThreshold":
"0."},
445 thresholdConfig={
"NBins":[1,1]})
447 L1CaloMonitorCfgHelper.printHanConfig()