ATLAS Offline Software
Loading...
Searching...
No Matches
LVL1CaloMonitoringConfig.py
Go to the documentation of this file.
2# Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3#
4
6
7 """
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.
10 """
11
12
13
14 from collections import defaultdict
15 hanConfigs = {} # nested structure as required, keys will be either "dir XXX" or "hist YYY"
16 hanAlgConfigs = {}
17 hanThresholdConfigs = {}
18 xmlConfigs = {} # flat dictionary of histograms that are in the shifter folders, so are used for online monitoring
19 embargoed = [] # list of embargoed dqdm plots
20
21 SIGNATURES = ["gJ","gLJ","gLJRho","gXEJWOJ","gXEJWOJMHT","gXEJWOJMST","gTEJWOJ","gXENC","gTENC","gXERHO","gTERHO","jJ","jEM","jTAU","jXE","jTE","eTAU","eEM"]
22 HELPURL = "" #"https://codimd.web.cern.ch/s/678H65Tk9" No longer adding a help url
23
24 @staticmethod
26 # First create the DQAlgorithm config file
27 import config
28 db = config.Configuration()
29 db.create_db("l1calo_gen_phase1.data.xml",["daq/schema/dqm.schema.xml","daq/sw/dqm-algorithms.data.xml","daq/sw/repository.data.xml","daq/sw/dqm-default-streams.data.xml"])
30
31 # first ensure all the algorithms exist
32 for confName,conf in L1CaloMonitorCfgHelper.hanAlgConfigs.items():
33 # only need algorithms for Shifter histograms
34 algUsed = False
35 for histPath,value in L1CaloMonitorCfgHelper.xmlConfigs.items():
36 if value.get("algorithm","") == confName:
37 algUsed = True
38 break
39 if not algUsed: continue
40 updated = False
41 try:
42 dqAlgo = db.get_dal("DQAlgorithm",conf["name"])
43 except RuntimeError:
44 # algorithm doesn't exist, create it ...
45 updated=True
46 db.create_obj("DQAlgorithm",conf["name"])
47 dqAlgo = db.get_dal("DQAlgorithm",conf["name"])
48 dqAlgo.LibraryName = conf["libname"]
49 print("Created dqAlgo",conf["name"])
50 # ensure all parameters appear in ParametersNames, and thresholds in ThresholdsNames
51 for par,val in conf.items():
52 if par=="thresholds" and val in L1CaloMonitorCfgHelper.hanThresholdConfigs:
53 for thresh,vals in L1CaloMonitorCfgHelper.hanThresholdConfigs[val].items():
54 if thresh not in dqAlgo.ThresholdsNames:
55 updated=True
56 dqAlgo.ThresholdsNames += [thresh]
57 print("Added",thresh,"to",conf["name"],"ThresholdNames")
58 elif par not in ["name","libname","thresholds"]+dqAlgo.ParametersNames:
59 updated=True
60 dqAlgo.ParametersNames += [par]
61 print("Added",par,"to",conf["name"],"ParameterNames")
62 if updated:
63 db.update_dal(dqAlgo)
64
65
66 # now create DQParameter object for each histogram with a DQ algorithm
67 # need to have them all in a DQRegion that belongs to a DQLayout
68 db.create_obj("DQShape","L1CaloShapeDeveloper")
69 db.create_obj("DQLayout","L1CaloLayoutDeveloper")
70 db.create_obj("DQRegion","L1CaloRegionDeveloper")
71 dqLayout = db.get_dal("DQLayout","L1CaloLayoutDeveloper")
72 dqLayout.DefaultChildrenShape = db.get_dal("DQShape","L1CaloShapeDeveloper")
73 db.update_dal(dqLayout)
74 dqRegion = db.get_dal("DQRegion","L1CaloRegionDeveloper")
75 dqRegion.Description = "L1Calo Monitoring Development Folder"
76 dqRegion.Label = "Developer"
77 dqRegion.DQLayout = dqLayout
78 dqRegion.DQSummaryMaker = db.get_dal("DQSummaryMaker","WorstCaseSummary")
79
80 for histPath,value in L1CaloMonitorCfgHelper.xmlConfigs.items():
81 if "algorithm" not in value.keys(): continue # only add histograms that have an algorithm
82
83 name = "_".join(histPath.split("/"))
84 db.create_obj("DQParameter",name)
85 dqPar = db.get_dal("DQParameter",name)
86 dqPar.InputDataSource = ["Histogramming.l1calo-athenaHLT-Phase1./"+histPath]
87 dqPar.Description = value["description"]
88
89 if value["algorithm"] in L1CaloMonitorCfgHelper.hanAlgConfigs:
90 algConf = L1CaloMonitorCfgHelper.hanAlgConfigs[value["algorithm"]]
91 dqPar.DQAlgorithm = db.get_dal("DQAlgorithm",algConf["name"])
92 for par,val in algConf.items():
93 if par in dqPar.DQAlgorithm.ParametersNames:
94 dqPar.Parameters += [f"{par}={val}"]
95 if "thresholds" in algConf:
96 for thresh,vals in L1CaloMonitorCfgHelper.hanThresholdConfigs[algConf["thresholds"]].items():
97 dqPar.GreenThresholds += [f"{thresh}={vals['warning']}"]
98 dqPar.RedThresholds += [f"{thresh}={vals['error']}"]
99 else:
100 dqPar.DQAlgorithm = db.get_dal("DQAlgorithm",value["algorithm"]) # catches cases of e.g. predefined parameterless alg like Histogram_Empty
101
102 dqRegion.DQParameters += [dqPar]
103 db.update_dal(dqPar)
104
105 db.update_dal(dqRegion)
106 db.commit("Autogenerated")
107
108
109 @staticmethod
110 def printHanConfig(filename="collisions_run.config"):
111 L1CaloMonitorCfgHelper.createXmls()
112 from contextlib import redirect_stdout
113 from PathResolver import PathResolver
114 header = PathResolver.FindCalibFile("TrigT1CaloMonitoring/hanConfig_header.txt")
115 with open(filename,'w') as f:
116 # copy the header if we have one
117 if header != "":
118 with open(header,'r') as fh:
119 for line in fh: f.write(line)
120 with redirect_stdout(f):
121 # Note: common configs (see common dir in DataQualityConfiguration) provides following algorithms by default:
122 # algorithm All_Bins_Filled
123 # algorithm Histogram_Effective_Empty
124 # algorithm Histogram_Empty
125 # algorithm Histogram_Not_Empty
126 # algorithm No_OverFlows
127 # algorithm No_UnderFlows
128
129 outputs = set()
130 algorithms = set()
131 def printConf(d,prefix="",currentOutput=""):
132 for key,value in d.items():
133 if type(value)==dict:
134 print(prefix,key,"{")
135 newCurrentOutput=str(currentOutput)
136 if(key=="dir detail" or key=="dir Developer"):
137 print(prefix+" algorithm = GatherData") # define GatherData as default algo for all of these hists
138 if key.startswith("dir ") and any([x.startswith("hist ") for x in value.keys()]):
139 # this is a dir with hists, so specify output as the path .. take from the first hist child
140 for childKey,childVal in value.items():
141 if childKey.startswith("hist ") and "output" in childVal:
142 print(prefix+" output = "+childVal["output"])
143 newCurrentOutput = str(childVal["output"])
144 break
145 printConf(value,prefix + " ",newCurrentOutput)
146 print(prefix,"}")
147 else:
148 # save all output paths to add to output block (don't need to print here b.c. specified at dir level
149 # exception is if plot was embargoed!
150 if key == "output": outputs.add(value)
151 if key != "output" or value != currentOutput: print(prefix,key,"=",value)
152 if key == "algorithm": algorithms.add(value)
153
154
155 print("#inputs")
156 print("dir L1Calo {")
157 printConf(L1CaloMonitorCfgHelper.hanConfigs," ")
158 print("}")
159 print("#outputs")
160 print("output top_level {")
161 print(" output L1Calo {")
162
163 # go through outputs set, build a nested dictionary of paths
164 outputsDict = {}
165 for o in outputs:
166 theDict = outputsDict
167 for p in o.split("/"):
168 if p not in theDict: theDict[p] = {}
169 theDict = theDict[p]
170 def printOutputs(d,prefix=""):
171 for key,value in d.items():
172 print(prefix,"output",key,"{")
173 if key=="detail" or key=="Developer": print(prefix," algorithm = L1Calo_AlwaysUndefinedSummary")
174 printOutputs(value,prefix + " ")
175 print(prefix,"}")
176 printOutputs(outputsDict["L1Calo"]," ")
177 print(" }")
178 print("}")
179 # include example of adding algorithms and thresholds
180 print("""
181#algorithms
182algorithm AnyNonZeroBinIsError {
183 # Use this algo if want error on any non-zero bin content
184 libname = libdqm_summaries.so
185 name = Bins_NotEqual_Threshold
186 BinThreshold = 0.
187 thresholds = th_AnyBinIsError
188}
189algorithm L1Calo_AlwaysUndefinedSummary {
190 libname = libdqm_summaries.so
191 name = AlwaysUndefinedSummary
192}
193""")
194 thresholds = set()
195 for algName,algProps in L1CaloMonitorCfgHelper.hanAlgConfigs.items():
196 if algName not in algorithms: continue # only print the algorithms that were used
197 print(f"algorithm {algName} {{")
198 for propName,propVal in algProps.items():
199 if propName == "thresholds": thresholds.add(propVal)
200 print(f" {propName} = {propVal}")
201 print(" }")
202 print("""
203#thresholds
204thresholds th_AnyBinIsError {
205 limits NBins {
206 warning = 0
207 error = 1
208 }
209}
210""")
211 for threshName,threshProps in L1CaloMonitorCfgHelper.hanThresholdConfigs.items():
212 if threshName not in thresholds: continue # only print used thresholds
213 print(f"thresholds {threshName} {{")
214 for parName,parLims in threshProps.items():
215 print(f" limits {parName} {{")
216 for limName,limVal in parLims.items():
217 print(f" {limName} = {limVal}")
218 print(" }")
219 print("}")
220
221
222
223 def __init__(self, flags, algClassOrObj = None, name = None, *args, **kwargs):
224 '''
225 Create the configuration helper.
226
227 Arguments:
228 flags -- the configuration flag object
229 algClassOrObj -- the name you want to assign the family of algorithms
230 '''
231 from AthenaMonitoring import AthMonitorCfgHelper
232 self.helper = AthMonitorCfgHelper(flags,name)
233 self.alg = self.helper.addAlgorithm(algClassOrObj,name,*args, **kwargs) if algClassOrObj is not None else None
234 self.fillGroups = {}
235 self.dqEnv = flags.DQ.Environment # used to decide if should defineTree or not ...
236
237 def defineDQAlgorithm(self,name,hanConfig,thresholdConfig=None):
238
239 """
240
241 :param name: name of algorithm
242 :param hanConfig: dict of algo properties
243 :param thresholdConfig: dict of thresholds, key = ParName, value = pair of thresholds [warning,error]
244 :return:
245 """
246
247 # note: this method will replace any existing alg definition
248
249 #thresNum = len(self.hanThresholdConfigs)
250 if thresholdConfig is not None:
251 hanConfig["thresholds"] = f"{name}Thresholds"
252 threshDict = {}
253 for parName,limVals in thresholdConfig.items():
254 if len(limVals) != 2:
255 raise Exception("must specify two limits: warning and error")
256 if parName not in threshDict: threshDict[parName] = {}
257 threshDict[parName]["warning"] = limVals[0]
258 threshDict[parName]["error"] = limVals[1]
259 # see if any existing thresholds are identical, if so we can reuse
260 for threshName,thresh in self.hanThresholdConfigs.items():
261 if str(thresh)==str(threshDict):
262 threshDict = None
263 hanConfig["thresholds"] = threshName
264 break
265 if threshDict is not None: self.hanThresholdConfigs[hanConfig["thresholds"]] = threshDict
266 self.hanAlgConfigs[name] = hanConfig
267
268 return
269
270
271 def defineHistogram(self,*args,fillGroup=None,hanConfig={},paths=[],**kwargs):
272 '''
273
274 :param path:
275 :param fillGroup:
276 :param args:
277 :param kwargs:
278 :return:
279 '''
280
281 hanConfig = dict(hanConfig) # create a copy since will modify below (otherwise we end up modifying the default empty dict)
282
283 if paths != []:
284 for path in paths:
285 if self.dqEnv=='online' and any([x.startswith("Shifter/") for x in paths]) and not path.startswith("Shifter/"): continue # only fill Shifter folder copies online
286 # create a copy of the histogram in each of the extra locations
287 self.defineHistogram(*args,fillGroup=fillGroup,hanConfig=hanConfig,paths=[],path=path,**kwargs)
288 return None
289
290 argsCopy = list(args) # need to convert tuple to list to convert it
291 if ";" not in args[0]:
292 argsCopy[0] += ";h_" + argsCopy[0].replace(":","_")
293
294 if kwargs.get("path",None) is None:
295 # put in the Developer path, under the name of the algorithm
296 kwargs["path"] = "Developer/" + self.alg.name
297 elif kwargs["path"][-1] == '/':
298 kwargs["path"] = kwargs["path"][:-1] # strip trailing slash
299 # verify path obeys convention
300 splitPath = kwargs["path"].split("/")
301 if splitPath[0] not in ["Shifter","Expert","Developer"]:
302 raise Exception("Path of histogram invalid, does not start with one of the allowed audiences (Shifter,Expert,Developer)")
303
304 # don't bother registering Shifter plots in tier0 ... only needed in p1 and user environments
305 if splitPath[0]=="Shifter" and self.dqEnv == 'tier0':
306 return None
307
308 # require a hanConfig not in Developer or a detail dir
309 if splitPath[0] != "Developer" and splitPath[-1] != "detail" and ("algorithm" not in hanConfig) and (splitPath[0]+"/algorithm" not in hanConfig):
310 # will default to using GatherData as long as there is a description
311 if "description" not in hanConfig and splitPath[0]+"/description" not in hanConfig:
312 raise Exception("Must specify a hanConfig for a Shifter or Expert (non-detail) histogram")
313 else:
314 hanConfig["algorithm"] = "GatherData" # must have an algo, otherwise wont be valid han config
315 elif "algorithm" in hanConfig and hanConfig["algorithm"] not in self.hanAlgConfigs and hanConfig["algorithm"] not in ["All_Bins_Filled","Histogram_Effective_Empty","Histogram_Empty","Histogram_Not_Empty","No_OverFlows","No_UnderFlows"]:
316 # if algorithm specified, must have been defined
317 raise Exception(f'DQ Algorithm {hanConfig["algorithm"]} for histogram {args[0]} not defined. Please use defineDQAlgorithm method to define it')
318 elif splitPath[0]+"/algorithm" in hanConfig and hanConfig[splitPath[0]+"/algorithm"] not in self.hanAlgConfigs and hanConfig[splitPath[0]+"/algorithm"] not in ["All_Bins_Filled","Histogram_Effective_Empty","Histogram_Empty","Histogram_Not_Empty","No_OverFlows","No_UnderFlows"]:
319 # if algorithm specified, must have been defined
320 raise Exception(f'{splitPath[0]} DQ Algorithm {hanConfig[splitPath[0]+"/algorithm"]} for histogram {args[0]} not defined. Please use defineDQAlgorithm method to define it')
321
322 if fillGroup is None: fillGroup = self.alg.name + "_fillGroup"
323 if fillGroup not in self.fillGroups:
324 self.fillGroups[fillGroup] = self.helper.addGroup(self.alg,fillGroup,topPath="L1Calo")
325
326
327 if "merge" not in kwargs and kwargs.get("type","") !="TEfficiency":
328 kwargs["merge"] = "merge" # ensures we don't get a warning about not specifying merge method
329 out = self.fillGroups[fillGroup].defineHistogram(*argsCopy,**kwargs)
330 histName = argsCopy[0].split(";")[-1]
331
332 # add help link for all expert plots
333 if splitPath[0] == "Expert" and self.HELPURL!="":
334 linkUrl = self.HELPURL + "#" + "".join(splitPath[1:]+[histName])
335 linkUrl = f"<a href=\"{linkUrl}\">Help</a>"
336 if "description" not in hanConfig and "Expert/descripton" not in hanConfig: hanConfig["description"] = linkUrl
337 elif "description" in hanConfig: hanConfig["description"] += " - " + linkUrl
338 else: hanConfig["Expert/description"] += " - " + linkUrl
339
340 # only add to hanConfig if in Expert or Developer folder
341 if splitPath[0] == "Expert" or splitPath[0] == "Developer":
342 splitPathWithHist = splitPath + [histName]
343 # check if hist is in the embargoed list
344 embargo = ("/".join(splitPathWithHist) in L1CaloMonitorCfgHelper.embargoed)
345 if embargo:
346 if "Expert/description" not in hanConfig: hanConfig["description"] = "<b>EMBARGOED PLOT</b> - " + (hanConfig.get("description",""))
347 else: hanConfig["Expert/description"] = "<b>EMBARGOED PLOT</b> - " + (hanConfig.get("Expert/description",""))
348 if "description" in hanConfig and hanConfig["description"]=="":
349 del hanConfig["description"]
350 if splitPath[0]+"/description" in hanConfig and hanConfig[splitPath[0]+"/description"]=="":
351 del hanConfig[splitPath[0]+"/description"]
352 x = L1CaloMonitorCfgHelper.hanConfigs
353 for i,p in enumerate(splitPathWithHist):
354 key = ("dir " if i!=len(splitPathWithHist)-1 else "hist ") + p
355 if key not in x:
356 x[key] = {}
357 x = x[key]
358 hanConfig["output"] = "/".join(["L1Calo"]+[splitPath[0] if not embargo else "Developer"]+splitPath[1:]) #embargoed plots appear in developer folder in DQDM, but come from Expert folder in ROOT file
359 # create a copy of the hanConfig and remove any keys beginning with "Shifter/", which means its a shifter-only config attribute
360 myConfig = {}
361 for k,v in hanConfig.items():
362 if k.startswith("Shifter/"): continue
363 # strip Expert/ prefix if it exists
364 myConfig[str(k).replace("Expert/","")] = v
365 if "algorithm" in myConfig and myConfig["algorithm"] in self.hanAlgConfigs:
366 # if there are any string parameters in the config, add them to the description
367 # need this until WebDisplay shows string parameters
368 for pName,pVal in self.hanAlgConfigs[myConfig["algorithm"]].items():
369 if len(str(pVal))>0 and str(pVal)[0]=="\"":
370 myConfig["description"] += f"<br>{pName} : {pVal[1:-1]}"
371 x.update(myConfig)
372 elif splitPath[0] == "Shifter": # record shifter histograms in another map, for generating xmls
373 # create a copy of the hanConfig and remove any keys beginning with "Expert/", which means its a expert-only config attribute
374 myConfig = {}
375 for k,v in hanConfig.items():
376 if k.startswith("Expert/"): continue
377 # strip Shifter/ prefix if it exists
378 myConfig[str(k).replace("Shifter/","")] = v
379 L1CaloMonitorCfgHelper.xmlConfigs["/".join(["L1Calo"]+splitPath+[histName])] = {}
380 L1CaloMonitorCfgHelper.xmlConfigs["/".join(["L1Calo"]+splitPath+[histName])].update(myConfig) # copy in the config
381
382 return out
383
384 def defineTree(self,*args,fillGroup=None,**kwargs):
385
386 if ";" not in args[0]:
387 raise Exception("Must specify a tree name using ';name' suffix")
388 treeName = args[0].split(";")[-1]
389
390 if "," in args[1]: # catch a subtle typo that can screw up monitoring
391 raise Exception("Should not have comma in list of branch names and types")
392
393 if kwargs.get("path",None) is None:
394 # put in the Developer path, under the name of the algorithm
395 kwargs["path"] = "Developer/" + self.alg.name
396
397 # verify path obeys convention
398 splitPath = kwargs["path"].split("/")
399 if splitPath[0] not in ["Developer"]:
400 raise Exception("Path of tree invalid, must be in the audience=Developer directory")
401
402
403 if fillGroup is None: fillGroup = self.alg.name + "_fillGroup"
404 if fillGroup not in self.fillGroups:
405 self.fillGroups[fillGroup] = self.helper.addGroup(self.alg,fillGroup,topPath="L1Calo")
406
407 # always define a histogram to go with the tree, which will indicate how many entries there are
408 # this also ensures we satisfy the requirement that every fillGroup has an object defined
409 # (in the cases of running online/tier0 the defineTrees are blocked, but we still need a hist then)
410 histName = "h_" + treeName + "_entries"
411 argsCopy = list(args)
412 argsCopy[0] = argsCopy[0].replace(";"+treeName,";"+histName)
413 kwargsCopy = dict(kwargs)
414 kwargsCopy["title"] = f"Number of Entries in {treeName} TTree" + ";" + ";".join(kwargsCopy.get("title","").split(";")[1:])
415 kwargsCopy["opt"] = ['kCanRebin','kAddBinsDynamically','kAlwaysCreate']
416 kwargsCopy["merge"] = "merge"
417 is2d = (kwargsCopy["title"].count(";")>1)
418 # take the right number of variables for defining the histogram
419 if is2d:
420 argsCopy[0] = argsCopy[0].split(",")[0] + "," + argsCopy[0].split(",")[1] + ";" + argsCopy[0].rsplit(";",1)[-1]
421 else:
422 argsCopy[0] = argsCopy[0].split(",")[0] + ";" + argsCopy[0].rsplit(";",1)[-1]
423 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)
424 if not any([x in self.dqEnv for x in ['tier0','online']]):
425 out = self.fillGroups[fillGroup].defineTree(*args,**kwargs)
426 else:
427 out = None
428 return out
429
430 def result(self):
431 return self.helper.result()
432
433
435 '''Function to call l1calo DQ monitoring algorithms'''
436 from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
437 from AthenaConfiguration.Enums import Format
438 import logging
439
440 # local printing
441 local_logger = logging.getLogger('AthenaMonitoringCfg')
442 info = local_logger.info
443 info('In LVL1CaloMonitoringConfig')
444
445 result = ComponentAccumulator()
446
447 # If we're not putting trigger objects in event store, can't monitor them
448 if not flags.Trigger.Online.isPartition:
449 if not flags.DQ.triggerDataAvailable:
450 return result
451
452 isData = not flags.Input.isMC
453
454 # check if validation requested
455 validation=flags.DQ.Steering.LVL1Calo.doValidation
456
457 # monitoring algorithm configs
458 # do not run on MC or RAW->ESD(tier0), or AOD-only
459 if not validation and isData and flags.DQ.Environment not in ('tier0Raw', 'AOD'):
460
461 from TrigT1CaloMonitoring.PprMonitorAlgorithm import PprMonitoringConfig
462 from TrigT1CaloMonitoring.JepJemMonitorAlgorithm import JepJemMonitoringConfig
463
464 # Use metadata to check Run3 compatible trigger info is available
465 from AthenaConfiguration.AutoConfigFlags import GetFileMD
466 md = GetFileMD(flags.Input.Files)
467 inputContainsRun3FormatConfigMetadata = ("metadata_items" in md and any(('TriggerMenuJson' in key) for key in md["metadata_items"].keys()))
468 result.merge(PprMonitoringConfig(flags))
469 result.merge(JepJemMonitoringConfig(flags))
470 if flags.Input.Format is not Format.POOL or inputContainsRun3FormatConfigMetadata:
471 # L1 menu available in the POOL file
472
473 # since the legacy system started getting turned off in 2024, use detMask to determine
474 # which things are included, and therefore need monitoring ...
475 import eformat
476 detMask=eformat.helper.DetectorMask(f'{md.get("detectorMask",[0x0])[0]:032x}') #DetectorMask constructor swallows two 64bit ints
477 hasCPM = detMask.is_set(eformat.helper.SubDetector.TDAQ_CALO_CLUSTER_PROC_DAQ)
478 hasJEP = detMask.is_set(eformat.helper.SubDetector.TDAQ_CALO_JET_PROC_DAQ)
479
480 if hasCPM:
481 from TrigT1CaloMonitoring.CpmMonitorAlgorithm import CpmMonitoringConfig
482 from TrigT1CaloMonitoring.CpmSimMonitorAlgorithm import CpmSimMonitoringConfig
483 result.merge(CpmMonitoringConfig(flags))
484 result.merge(CpmSimMonitoringConfig(flags))
485
486 if hasJEP:
487 from TrigT1CaloMonitoring.JepCmxMonitorAlgorithm import JepCmxMonitoringConfig
488 result.merge(JepCmxMonitoringConfig(flags))
489
490 from TrigT1CaloMonitoring.OverviewMonitorAlgorithm import OverviewMonitoringConfig
491 from TrigT1CaloMonitoring.PPMSimBSMonitorAlgorithm import PPMSimBSMonitoringConfig
492 result.merge(PPMSimBSMonitoringConfig(flags))
493 result.merge(OverviewMonitoringConfig(flags))
494
495 if not hasCPM:
496 # CPM was disabled for run 480893 onwards, so stop monitoring that part
497 OverviewMonAlg = result.getEventAlgo("OverviewMonAlg")
498 OverviewMonAlg.CPMErrorLocation = ""
499 OverviewMonAlg.CPMMismatchLocation = ""
500
501 if flags.Input.TriggerStream == "physics_Mistimed":
502 from TrigT1CaloMonitoring.MistimedStreamMonitorAlgorithm import MistimedStreamMonitorConfig
503 result.merge(MistimedStreamMonitorConfig(flags))
504
505 # For running on bytestream data
506 if flags.Input.Format is Format.BS:
507 from TrigT1CaloByteStream.LVL1CaloRun2ByteStreamConfig import LVL1CaloRun2ReadBSCfg
508 result.merge(LVL1CaloRun2ReadBSCfg(flags))
509
510 # Phase 1 monitoring of inputs and sim-vs-hw
511 if flags.Trigger.enableL1CaloPhase1 and flags.Input.Format is not Format.POOL:
512
513 # run the L1Calo simulation (causes conflicts with DAOD)
514 from L1CaloFEXSim.L1CaloFEXSimCfg import L1CaloFEXSimCfg
515 result.merge(L1CaloFEXSimCfg(flags))
516
517 #efex monitoring
518 if flags.Trigger.L1.doeFex:
519 from TrigT1CaloMonitoring.EfexInputMonitorAlgorithm import EfexInputMonitoringConfig
520 result.merge(EfexInputMonitoringConfig(flags))
521
522 # monitoring of simulation vs hardware
523 from TrigT1CaloMonitoring.EfexSimMonitorAlgorithm import EfexSimMonitoringConfig
524 result.merge(EfexSimMonitoringConfig(flags))
525
526 #gfex monitoring
527 if flags.Trigger.L1.dogFex:
528 #gfex input monitoring
529 from TrigT1CaloMonitoring.GfexInputMonitorAlgorithm import GfexInputMonitoringConfig
530 result.merge(GfexInputMonitoringConfig(flags))
531
532 from TrigT1CaloMonitoring.GfexSimMonitorAlgorithm import GfexSimMonitoringConfig
533 result.merge(GfexSimMonitoringConfig(flags))
534
535 #jfex monitoring
536 if flags.Trigger.L1.dojFex:
537 #jfex monitoring for input data
538 from TrigT1CaloMonitoring.JfexInputMonitorAlgorithm import JfexInputMonitoringConfig
539 result.merge(JfexInputMonitoringConfig(flags))
540
541 #jfex monitoring for Data Vs Simulation
542 from TrigT1CaloMonitoring.JfexSimMonitorAlgorithm import JfexSimMonitoringConfig
543 JfexSimMonitoring = JfexSimMonitoringConfig(flags)
544 result.merge(JfexSimMonitoring)
545
546 if flags.Trigger.L1.doTopo and isData:
547 #L1TopoSimulation (with monitoring Off to avoid clash with next call)
548 from L1TopoSimulation.L1TopoSimulationConfig import L1TopoSimulationCfg
549 result.merge(L1TopoSimulationCfg(flags,readMuCTPI=True,doMonitoring=False, useMuonDecoder=True, writeMuonRoIs = False))
550 #L1TopoOnlineMonitoring specific for L1Calo DQPlots
551 from L1TopoOnlineMonitoring.L1TopoOnlineMonitoringConfig import Phase1TopoMonitoringCfg
552 result.merge(Phase1TopoMonitoringCfg(flags))
553
554 # run FEX output monitoring if doing validation or running on data not @ tier0 or on AOD
555 if validation or (isData and flags.DQ.Environment not in ('tier0Raw', 'AOD')):
556
557 if validation:
558 # only run this monitoring if doing validation
559 from TrigT1CaloMonitoring.L1CaloLegacyEDMMonitorAlgorithm import L1CaloLegacyEDMMonitoringConfig
560 result.merge(L1CaloLegacyEDMMonitoringConfig(flags))
561
562 #efex monitoring
563 if flags.Trigger.L1.doeFex:
564 from TrigT1CaloMonitoring.EfexMonitorAlgorithm import EfexMonitoringConfig
565 result.merge(EfexMonitoringConfig(flags))
566 from TrigT1CaloMonitoring.EfexMonitorAlgorithm import EfexMonitoringHistConfig
567 result.merge(EfexMonitoringHistConfig(flags,result.getEventAlgo('EfexMonAlg')))
568
569 #gfex monitoring
570 if flags.Trigger.L1.dogFex:
571 from TrigT1CaloMonitoring.GfexMonitorAlgorithm import GfexMonitoringConfig
572 result.merge(GfexMonitoringConfig(flags))
573
574 #jfex monitoring
575 if flags.Trigger.L1.dojFex:
576 from TrigT1CaloMonitoring.JfexMonitorAlgorithm import JfexMonitoringConfig
577 result.merge(JfexMonitoringConfig(flags))
578
579 # jet efficiency monitoring -- needs either gfex or jfex to be worth scheduling
580 if flags.Trigger.L1.dojFex or flags.Trigger.L1.dogFex:
581 from TrigT1CaloMonitoring.JetEfficiencyMonitorAlgorithm import JetEfficiencyMonitoringConfig
582 result.merge(JetEfficiencyMonitoringConfig(flags))
583
584 result.printConfig( withDetails= True )
585
586 return result
587
588if __name__ == '__main__':
589 from AthenaConfiguration.AllConfigFlags import initConfigFlags
590 from AthenaConfiguration.ComponentFactory import CompFactory
591 from AthenaMonitoring.DQConfigFlags import DQDataType
592 flags = initConfigFlags()
593 flags.DQ.useTrigger = False
594 flags.DQ.Environment = "user"
595 flags.DQ.DataType = DQDataType.MC
596 flags.DQ.enableLumiAccess = False
597 flags.lock()
598 h = L1CaloMonitorCfgHelper(flags,CompFactory.JfexSimMonitorAlgorithm,"MyAlg")
599 h.defineHistogram("x,y;h_myHist",type='TH2D',path="Shifter/Blah",hanConfig={"algorithm":"blah"})
600 h.defineHistogram("x,y;h_myHis2t",type='TH2D',path="Shifter/Blah",hanConfig={"algorithm":"blah2"})
601 h.defineHistogram("x;anotherHist",type='TH1D',path="Developer/whatever",hanConfig={"aaa":2})
602 h.defineTree("x,y,z,a,b;myTree","x/i:y/i:z/i:a/I:b/I",path="Developer/whatever")
603
604 # example of an algorithm requiring all bins to be empty
605 h.defineDQAlgorithm("MyAlgo",
606 hanConfig={"libname":"libdqm_summaries.so","name":"Bins_NotEqual_Threshold","BinThreshold":"0."},
607 thresholdConfig={"NBins":[1,1]}) # first number if warning threshold, second is error threshold
608
609 L1CaloMonitorCfgHelper.printHanConfig()
if(febId1==febId2)
void print(char *figname, TCanvas *c1)
defineDQAlgorithm(self, name, hanConfig, thresholdConfig=None)
defineTree(self, *args, fillGroup=None, **kwargs)
defineHistogram(self, *args, fillGroup=None, hanConfig={}, paths=[], **kwargs)
__init__(self, flags, algClassOrObj=None, name=None, *args, **kwargs)
static std::string FindCalibFile(const std::string &logical_file_name)
STL class.
std::string replace(std::string s, const std::string &s2, const std::string &s3)
Definition hcg.cxx:310
int count(std::string s, const std::string &regx)
count how many occurances of a regx are in a string
Definition hcg.cxx:146
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:177
HLT::TypeInformation::for_each_type_c< typenameEDMLIST::map, my_functor, my_result<>, my_arg< HLT::TypeInformation::get_cont, CONTAINER > >::type result