ATLAS Offline Software
Loading...
Searching...
No Matches
AthMonitorCfgHelper.py
Go to the documentation of this file.
2# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3#
4
5'''@file AthMonitorCfgHelper.py
6@author C. D. Burton
7@author P. Onyisi
8@date 2019-01-25
9@brief Helper classes for Run 3 monitoring algorithm configuration
10'''
11
12from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
13from AthenaConfiguration.ComponentFactory import CompFactory
14
15class AthMonitorCfgHelper(object):
16 '''
17 This class is for the Run 3-style configuration framework. It is intended to be instantiated once
18 per group of related monitoring algorithms.
19 '''
20 def __init__(self, flags, monName):
21 '''
22 Create the configuration helper. Needs the job flags and the name of the set of
23 monitoring algorithms.
24
25 Arguments:
26 flags -- the configuration flag object
27 monName -- the name you want to assign the family of algorithms
28 '''
29
30 AthSequencer=CompFactory.AthSequencer
31 self.flags = flags
32 self.monName = monName
33 self.monSeq = AthSequencer('AthMonSeq_' + monName)
34 self.monSeq.StopOverride=True
35 self.resobj = ComponentAccumulator()
36 # self.resobj.addSequence(self.monSeq) - postpone adding sequence unless actually adding an alg
37 if self.flags.DQ.useTrigger:
38 from .TriggerInterface import TrigDecisionToolCfg
39 self.resobj.merge(TrigDecisionToolCfg(flags))
40
41 def addAlgorithm(self, algClassOrObj, name = None, addFilterTools = [], addToSubSequence=True, *args, **kwargs):
42 '''
43 Instantiate/add a monitoring algorithm
44
45 Arguments:
46 algClassOrObj -- the Configurable class object of the algorithm to create, or an instance
47 of the algorithm Configurable. The former is recommended. In the former case,
48 the name argument is required.
49 name -- the name of the algorithm to create. Required when passing a Configurable class object
50 as algClassOrObj. No effect if a Configurable instance is passed.
51 addToSubSequence -- if the algorithm should be added to a subsequence in the component accumulator,
52 or just to the top level sequence.
53 *args, **kwargs -- additional arguments will be forwarded to the Configurable constructor if
54 a Configurable class object is passed. No effect if a Configurable instance
55 is passed.
56
57 Returns:
58 algObj -- an algorithm Configurable object
59 '''
60 from inspect import isclass
61 if isclass(algClassOrObj):
62 if name is None:
63 raise TypeError('addAlgorithm with a class argument requires a name for the algorithm')
64 algObj = algClassOrObj(name, *args, **kwargs)
65 else:
66 algObj = algClassOrObj
67
68 # configure these properties; users really should have no reason to override them
69 algObj.Environment = self.flags.DQ.Environment
70 algObj.DataType = self.flags.DQ.DataType.value
71 if self.flags.DQ.useTrigger:
72 algObj.TrigDecisionTool = self.resobj.getPublicTool("TrigDecisionTool")
73
74 if self.flags.DQ.enableLumiAccess:
75 algObj.EnableLumi = True
76 from LumiBlockComps.LuminosityCondAlgConfig import LuminosityCondAlgCfg
77 self.resobj.merge (LuminosityCondAlgCfg (self.flags))
78 if not self.flags.Input.isMC:
79 from LumiBlockComps.LBDurationCondAlgConfig import LBDurationCondAlgCfg
80 from LumiBlockComps.TrigLiveFractionCondAlgConfig import TrigLiveFractionCondAlgCfg
81 self.resobj.merge (LBDurationCondAlgCfg (self.flags))
82 self.resobj.merge (TrigLiveFractionCondAlgCfg (self.flags))
83 else:
84 algObj.EnableLumi = False
85
86 # add some optional filters?
87 for obj in addFilterTools:
88 # accept either ComponentAccumulators or tools (trusting that user has already merged CA)
89 if isinstance(obj, ComponentAccumulator):
90 filter = self.resobj.popToolsAndMerge(obj)
91 elif hasattr(obj, 'getGaudiType') and obj.getGaudiType() == 'AlgTool':
92 filter = obj
93 else:
94 raise ValueError(f'Object {obj} passed to addFilterTools is not a ComponentAccumulator or an AlgTool')
95 algObj.FilterTools += [filter]
96
97 if addToSubSequence:
98 if self.resobj.getSequence(self.monSeq.name) is None:
99 self.resobj.addSequence(self.monSeq) # add the sequence now
100 self.resobj.addEventAlgo(algObj, sequenceName=self.monSeq.name)
101 else:
102 self.resobj.addEventAlgo(algObj) # not bothering with subsequences
103 return algObj
104
105 def addGroup(self, alg, name, topPath='', defaultDuration='run'):
106 '''Add a group to an algorithm
107
108 Technically, adding a GenericMonitoringTool instance. The name given here can be
109 used to retrieve the group from within the algorithm when calling the fill()
110 function. Note this is *not* the same thing as the Monitored::Group class. To
111 avoid replication of code, this calls the more general case, getArray with an 1D
112 array of length 1.
113
114 Arguments:
115 alg -- algorithm Configurable object (e.g. one returned from addAlgorithm)
116 name -- name of the group
117 topPath -- directory name in the output ROOT file under which histograms will be
118 produced
119 defaultDuration -- default time between histogram reset for all histograms in
120 group; can be overridden for each specific histogram
121
122 Returns:
123 tool -- a GenericMonitoringTool Configurable object. This can be used to define
124 histograms associated with that group (using defineHistogram).
125 '''
126 if alg is not None and name == alg.getName():
127 raise ValueError(f"Cannot have a monitoring group with the same name as the parent algorithm ({name})")
128 array = self.addArray([1],alg,name,topPath=topPath,defaultDuration=defaultDuration)
129 return array[0]
130
131 def addArray(self, dimensions, alg, baseName, topPath='', defaultDuration='run'):
132 '''Add many groups to an algorithm
133
134 Arguments:
135 dimensions -- list holding the size in each dimension [n1,n2,n3,n4,...]
136 alg -- algorithm Configurable object
137 baseName -- base name of the group. postfixes are added by GMT Array initialize
138 topPath -- directory name in the output ROOT file under which histograms will be
139 produced
140 duration -- default time between histogram reset for all histograms in group
141
142 Returns:
143 tool -- a GenericMonitoringToolArray object. This is used to define histograms
144 associated with each group in the array.
145 '''
146 # Generate the n-dimensional array
147 from AthenaMonitoringKernel.GenericMonitoringTool import GenericMonitoringArray
148 array = GenericMonitoringArray(self.flags, baseName, dimensions)
149
150 acc = getDQTHistSvc(self.flags)
151 self.resobj.merge(acc)
152
153 pathToSet = self.flags.DQ.FileKey+('/%s' % topPath if topPath else '')
154 if self.flags.Output.HISTFileName:
155 pathToSet = '/' + pathToSet
156 array.broadcast('HistPath',pathToSet)
157 array.broadcast('UseCache',True)
158 convention = 'ONLINE' if self.flags.Common.isOnline else 'OFFLINE'
159 array.broadcast('convention', convention)
160 array.broadcast('defaultDuration',defaultDuration)
161 if alg is not None:
162 alg.GMTools += array.toolList()
163 return array
164
165 def result(self):
166 '''
167 Finalize the creation of the set of monitoring algorithms.
168
169 Returns:
170 resobj -- a ComponentAccumulator
171 '''
172 return self.resobj
173
174
175def getDQTHistSvc(flags):
176 '''
177 This function creates a THistSvc - used for the new-style job configuration
178
179 Returns:
180 (result, histsvc) -- a tuple of (ComponentAccumulator, THistSvc Configurable object)
181 '''
182 result = ComponentAccumulator()
183 histsvc = CompFactory.THistSvc()
184 if flags.Output.HISTFileName:
185 histsvc.Output += ["%s DATAFILE='%s' OPT='RECREATE'" % (flags.DQ.FileKey,
186 flags.Output.HISTFileName)]
187 result.addService(histsvc)
188 return result
ClassName: AthSequencer.
addGroup(self, alg, name, topPath='', defaultDuration='run')
addAlgorithm(self, algClassOrObj, name=None, addFilterTools=[], addToSubSequence=True, *args, **kwargs)
addArray(self, dimensions, alg, baseName, topPath='', defaultDuration='run')
Definition merge.py:1