ATLAS Offline Software
TrigJetMonitorAlgorithm.py
Go to the documentation of this file.
1 #
2 # Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 #
4 
5 '''@file MTMonitoring.py
6 @authors P-A. Delsart, Jona Bossio
7 @date 03/04/2020
8 @brief Python configuration for the Run III Trigger Jet Monitoring
9 '''
10 
11 from AthenaCommon.Logging import logging
12 logger = logging.getLogger(__name__)
13 
14 from TrigDecisionTool.TrigDecisionToolConfig import getRun3NavigationContainerFromInput
15 
16 import math
17 import re
18 import copy
19 
20 
21 
24 
25 copySuffix = "copied" # suffix for jet containters that are duplicated for monitoring
26 
27 
30 
31 OfflineJetCollections = dict()
32 
33 OfflineJetCollections['pp'] = {
34  'AntiKt4EMTopoJets' : { 'MatchTo' : 'AntiKt4EMPFlowJets' },
35  'AntiKt4EMPFlowJets' : { 'MatchTo' : 'NONE' },
36  #'AntiKt10LCTopoTrimmedPtFrac5SmallR20Jets' : { 'MatchTo' : 'NONE' }, # Remove until ATR-25800 is fixed
37 }
38 
39 OfflineJetCollections['HI'] = {
40  'AntiKt4HIJets' : { 'MatchTo' : 'AntiKt4HIJets' },
41 }
42 
43 
46 
47 # The MatchedTo list must be either empty of length 2, and contain the names of an offline collection
48 # and an HLT collection. These names can be the empty string.
49 
50 # the strings in L1JetCollections are jet container names.
51 L1JetCollections = dict()
52 
53 match_smallRL1_OfflineJets_List = ['AntiKt4EMPFlowJets', 'HLT_AntiKt4EMPFlowJets_subresjesgscIS_ftf']
54 # temporarily modified to use small-R offline jet in turn-on to fix tier0 jet mon crash ATR-25800!! - throws exception if < 2 jet collections provided
55 match_largeRL1_OfflineJets_List = ['AntiKt4EMPFlowJets', 'HLT_AntiKt10EMPFlowCSSKSoftDropBeta100Zcut10Jets_jes_ftf']
56 match_HIL1_OfflineJets_List = ['AntiKt4HIJets', 'HLT_AntiKt4HIJets']
57 
58 L1JetCollections['pp'] = {
59  'L1_jFexSRJetRoI': {'MatchTo': match_smallRL1_OfflineJets_List},
60  'L1_gFexSRJetRoI': {'MatchTo': match_smallRL1_OfflineJets_List},
61  'L1_gFexLRJetRoI': {'MatchTo': match_largeRL1_OfflineJets_List},
62 }
63 
64 L1JetCollections['HI'] = {
65  'L1_jFexSRJetRoI': {'MatchTo': match_HIL1_OfflineJets_List},
66  'L1_gFexSRJetRoI': {'MatchTo': match_HIL1_OfflineJets_List},
67 }
68 
69 for case in L1JetCollections.keys():
70  try:
71  items = L1JetCollections[case].items()
72  except (AttributeError, TypeError):
73  raise RuntimeError('L1JetCollections for %s is not a mapping type'%case)
74 
75  for k, d in items:
76  try:
77  d_items = d.items()
78  except (AttributeError, TypeError):
79  raise RuntimeError('L1JetCollections value for %s is not a mapping type'%case)
80 
81  if 'MatchTo' not in d:
82  errmsg = 'L1Collections entry %s has no (possibly empty) MatchType list' % (
83  str(k))
84  raise RuntimeError(errmsg)
85 
86 # Now seeing new L1 containers of differing types. These types
87 # are explicit in the C++ JetMatcher algorithm, and correspond
88 # top different attributes of that algorithm.
89 #
90 # l1Coll2MatcherKey supplies the python name of
91 # C++ component attribute.
92 
93 l1Coll2MatcherKey = {
94  'L1_jFexSRJetRoI': 'L1jFexSRJetRoIContainerName',
95  'L1_gFexSRJetRoI': 'L1gFexJetRoIContainerName',
96  'L1_gFexLRJetRoI': 'L1gFexJetRoIContainerName',
97 }
98 
99 for case in L1JetCollections.keys():
100  for k, d in L1JetCollections[case].items():
101  if d['MatchTo']: # exists by previous checks. check if empty.
102  if k not in l1Coll2MatcherKey:
103  errmsg = 'Match(es) to an L1 container requested entry '\
104  '%s but no C++ MatcherAlg attribute name provided' % (str(k),)
105  raise RuntimeError(errmsg)
106 
107 
108 # the values of Chain2L1JetCollDict are keys of L1JetCollections.
109 # the keys of Chain2L1JetCollDict are used to select events before histograms are filled
110 
111 Chain2L1JetCollDict = dict()
112 
113 Chain2L1JetCollDict['pp'] = { # set L1 jet collection name for L1 jet chains
114 
115  'L1_jJ40': ['L1_jFexSRJetRoI'],
116  'L1_jJ50': ['L1_jFexSRJetRoI'],
117  'L1_jJ160': ['L1_jFexSRJetRoI'],
118  'L1_jJ85p0ETA21_3jJ40p0ETA25': ['L1_jFexSRJetRoI'],
119  'L1_3jJ70p0ETA23': ['L1_jFexSRJetRoI'],
120  'L1_4jJ40': ['L1_jFexSRJetRoI'],
121 
122 
123  'L1_gJ20p0ETA25': ['L1_gFexSRJetRoI'],
124  'L1_gJ50p0ETA25': ['L1_gFexSRJetRoI'],
125  'L1_gJ100p0ETA25': ['L1_gFexSRJetRoI'],
126  'L1_gJ400p0ETA25': ['L1_gFexSRJetRoI'],
127 
128  'L1_gLJ80p0ETA25': ['L1_gFexLRJetRoI'],
129  'L1_gLJ100p0ETA25': ['L1_gFexLRJetRoI'],
130  'L1_gLJ140p0ETA25': ['L1_gFexLRJetRoI'],
131  'L1_gLJ160p0ETA25': ['L1_gFexLRJetRoI'],
132 
133  'L1_SC111-CjJ40': ['L1_jFexSRJetRoI'],
134  'L1_HT190-jJ40s5pETA21': ['L1_jFexSRJetRoI'],
135 }
136 
137 Chain2L1JetCollDict['HI'] = {
138 
139  'L1_jJ40': ['L1_jFexSRJetRoI'],
140  'L1_jJ55': ['L1_jFexSRJetRoI'],
141  'L1_jJ80': ['L1_jFexSRJetRoI'],
142 
143  'L1_jJ40p30ETA49': ['L1_jFexSRJetRoI'],
144 }
145 
146 
149 
150 # List of HLT jet collections (stating
151 # which should be matched and to which offline jet collection
152 
153 JetCollections = dict()
154 
155 JetCollections['pp'] = {
156  'HLT_AntiKt4EMTopoJets_subjesIS' : { 'MatchTo' : 'AntiKt4EMPFlowJets'}, # default small-R EM
157  'HLT_AntiKt4EMTopoJets_subjesIS_fastftag' : { 'MatchTo' : 'NONE'}, # small-R EM jets with RoI tracking & fast flavour tagging
158  'HLT_AntiKt4EMTopoJets_subresjesgscIS_ftf' : { 'MatchTo' : 'AntiKt4EMPFlowJets'}, # a4 calo jet w/ FTF
159  'HLT_AntiKt4EMTopoJets_subjesgscIS_ftf' : { 'MatchTo' : 'AntiKt4EMPFlowJets'}, # a4 calo jet w/ calo+track GSC, reconstructed by MET
160  'HLT_AntiKt4EMPFlowJets_subjesgscIS_ftf' : { 'MatchTo' : 'AntiKt4EMPFlowJets'}, # a4 pflow w/ calo+track GSC, reconstructed by MET
161  'HLT_AntiKt4EMPFlowJets_subresjesgscIS_ftf' : { 'MatchTo' : 'AntiKt4EMPFlowJets'}, # a4 pflow w/ residual + calo+track GSC
162  'HLT_AntiKt4EMPFlowJets_nojcalib_ftf' : { 'MatchTo' : 'NONE'}, # a4 pflow nojcalib
163  'HLT_AntiKt10EMTopoRCJets_subjesIS' : { 'MatchTo' : 'NONE'}, # a10r
164  'HLT_AntiKt10LCTopoJets_subjes' : { 'MatchTo' : 'NONE'}, # a10
165  'HLT_AntiKt10LCTopoTrimmedPtFrac4SmallR20Jets_jes' : { 'MatchTo' : 'NONE'}, # a10t
166  'HLT_AntiKt10EMPFlowCSSKSoftDropBeta100Zcut10Jets_nojcalib_ftf' : { 'MatchTo' : 'NONE'}, # a10sd pflow cssk nojcalib
167  'HLT_AntiKt10EMPFlowCSSKSoftDropBeta100Zcut10Jets_jes_ftf' : { 'MatchTo' : 'NONE'}, # a10sd pflow cssk jes
168 }
169 
170 JetCollections['HI'] = {
171  'HLT_AntiKt4HIJets' : {'MatchTo': 'AntiKt4HIJets'},
172  'HLT_AntiKt4EMPFlowJets_jes_ftf' : {'MatchTo': 'AntiKt4HIJets'},
173 }
174 
175 
176 def getChains2Monitor(inputFlags, monMode):
177 
178  Chains2Monitor = dict()
179  from TrigConfigSvc.TriggerConfigAccess import getHLTMonitoringAccess
180  monAccess = getHLTMonitoringAccess(inputFlags)
181 
182  # set HLT jet collection, reference chain and offline jet collection
183  # for turn-on curves
184  ListOfMonChains = monAccess.monitoredChains(signatures="jetMon", monLevels = ["shifter","t0"])
185 
186  default_dict = {"HLTColl": "NONE", "RefChain": "NONE" ,"OfflineColl": "NONE"}
187  Chains2Monitor[monMode] = dict((chain, default_dict.copy()) for chain in ListOfMonChains)
188 
189  if monMode == 'HI':
190  for chainName in Chains2Monitor['HI']:
191  if '_ion_' in chainName:
192  Chains2Monitor['HI'][chainName]["HLTColl"] = "HLT_AntiKt4HIJets"
193  Chains2Monitor['HI'][chainName]["OfflineColl"] = "AntiKt4HIJets"
194  else:
195  Chains2Monitor['HI'][chainName]["HLTColl"] = "HLT_AntiKt4EMPFlowJets_jes_ftf"
196  Chains2Monitor['HI'][chainName]["OfflineColl"] = "AntiKt4EMPFlowJets"
197 
198  # only HLT_noalg get efficiency curves by default, so...
199  # these are additional hard-coded chains for efficiency monitoring
200  #Standard HI chains (obsolete for O+O)
201  if Chains2Monitor['HI'].get('HLT_j60_ion_L1jJ40'): Chains2Monitor['HI']['HLT_j60_ion_L1jJ40'].update({"RefChain": "HLT_noalg_L1jTE50", "OfflineColl": "AntiKt4HIJets"})
202  if Chains2Monitor['HI'].get('HLT_j75_ion_L1jJ55'): Chains2Monitor['HI']['HLT_j75_ion_L1jJ55'].update({"RefChain": "HLT_noalg_L1jTE50", "OfflineColl": "AntiKt4HIJets"})
203  if Chains2Monitor['HI'].get('HLT_j85_ion_L1jJ55'): Chains2Monitor['HI']['HLT_j85_ion_L1jJ55'].update({"RefChain": "HLT_noalg_L1jTE50", "OfflineColl": "AntiKt4HIJets"})
204  if Chains2Monitor['HI'].get('HLT_j150_ion_L1jJ80'): Chains2Monitor['HI']['HLT_j150_ion_L1jJ80'].update({"RefChain": "HLT_noalg_L1jTE50", "OfflineColl": "AntiKt4HIJets"})
205  if Chains2Monitor['HI'].get('HLT_j200_ion_L1jJ80'): Chains2Monitor['HI']['HLT_j200_ion_L1jJ80'].update({"RefChain": "HLT_noalg_L1jTE50", "OfflineColl": "AntiKt4HIJets"})
206 
207  if Chains2Monitor['HI'].get('HLT_j50f_ion_L1jJ40p30ETA49'): Chains2Monitor['HI']['HLT_j50f_ion_L1jJ40p30ETA49'].update({"RefChain": "HLT_noalg_L1jTE50", "OfflineColl": "AntiKt4HIJets"})
208  if Chains2Monitor['HI'].get('HLT_j60f_ion_L1jJ40p30ETA49'): Chains2Monitor['HI']['HLT_j60f_ion_L1jJ40p30ETA49'].update({"RefChain": "HLT_noalg_L1jTE50", "OfflineColl": "AntiKt4HIJets"})
209 
210  elif monMode == "pp":
211  # logic to define HLTColl, RefChain, OfflineColl
212  for chainName in Chains2Monitor['pp']:
213  Chains2Monitor['pp'][chainName]["HLTColl"] = "HLT_AntiKt4EMTopoJets_subjesIS"
214  if '_pf_' in chainName and 'a10' not in chainName:
215  Chains2Monitor['pp'][chainName]["HLTColl"] = "HLT_AntiKt4EMPFlowJets_subresjesgscIS_ftf"
216  Chains2Monitor['pp'][chainName]["OfflineColl"] = "AntiKt4EMPFlowJets"
217  elif 'a10' in chainName:
218  if 'a10t' in chainName: Chains2Monitor['pp'][chainName]["HLTColl"] = "HLT_AntiKt10LCTopoTrimmedPtFrac4SmallR20Jets_jes"
219  elif 'sd_cssk_pf' in chainName: Chains2Monitor['pp'][chainName]["HLTColl"] = "HLT_AntiKt10EMPFlowCSSKSoftDropBeta100Zcut10Jets_jes_ftf"
220  elif 'a10r' in chainName: Chains2Monitor['pp'][chainName]["HLTColl"] = "HLT_AntiKt10EMTopoRCJets_subjesIS"
221  else: Chains2Monitor['pp'][chainName]["HLTColl"] = "HLT_AntiKt10LCTopoJets_subjes"
222  elif '_noalg_' in chainName:
223  Chains2Monitor['pp'][chainName]["RefChain"] = "HLT_j45_pf_ftf_preselj20_L1jJ40" # temporarily modify to using small-R jet in turn-on for both small and large-R jets to fix tier0 jet mon crash ATR-25800!!
224  Chains2Monitor['pp'][chainName]["OfflineColl"] = "AntiKt4EMPFlowJets"
225  if 'gLJ' in chainName: Chains2Monitor['pp'][chainName]["HLTColl"] = "HLT_AntiKt10EMPFlowCSSKSoftDropBeta100Zcut10Jets_jes_ftf"
226  else: continue
227 
228 
229  if Chains2Monitor['pp'].get('HLT_j420_L1jJ160'): Chains2Monitor['pp']['HLT_j420_L1jJ160'].update({"RefChain": "HLT_j85_L1jJ50", "OfflineColl": "AntiKt4EMPFlowJets"})
230  if Chains2Monitor['pp'].get('HLT_3j200_L1jJ160'): Chains2Monitor['pp']['HLT_3j200_L1jJ160'].update({"RefChain": "HLT_j85_L1jJ50", "OfflineColl": "AntiKt4EMPFlowJets"})
231  if Chains2Monitor['pp'].get('HLT_4j120_L13jJ90'): Chains2Monitor['pp']['HLT_4j120_L13jJ90'].update({"RefChain": "HLT_j85_L1jJ50", "OfflineColl": "AntiKt4EMPFlowJets"})
232  if Chains2Monitor['pp'].get('HLT_5j80_pf_ftf_presel5j50_L14jJ40'): Chains2Monitor['pp']['HLT_5j80_pf_ftf_presel5j50_L14jJ40'].update({"RefChain": "HLT_j45_pf_ftf_preselj20_L1jJ40", "OfflineColl": "AntiKt4EMPFlowJets"})
233  if Chains2Monitor['pp'].get('HLT_j400_pf_ftf_L1jJ160'): Chains2Monitor['pp']['HLT_j400_pf_ftf_L1jJ160'].update({"RefChain": "HLT_j85_pf_ftf_preselj50_L1jJ50", "OfflineColl": "AntiKt4EMPFlowJets"})
234  if Chains2Monitor['pp'].get('HLT_j400_pf_ftf_preselj225_L1jJ160'): Chains2Monitor['pp']['HLT_j400_pf_ftf_preselj225_L1jJ160'].update({"RefChain": "HLT_j85_pf_ftf_preselj50_L1jJ50", "OfflineColl": "AntiKt4EMPFlowJets"})
235 
236  else:
237  errmsg = 'Returned empty Chains2Monitor due to invalid monMode'
238  raise RuntimeError(errmsg)
239  return Chains2Monitor
240 
241 
244 
245 def getEtaRange(chain):
246  etaMin,etaMax = 0,2.5 # central jets by default
247 
248  if 'eta490_j' in chain: #workaround for the UPC (ultra-peripheral) trigger chains
249  etaMin,etaMax = 0,4.9
250  elif 'eta' in chain:
251  etaParts = chain.split('eta')
252  etaMinTemp = etaParts[0].split('_')
253  etaMin = etaMinTemp[len(etaMinTemp)-1]
254  etaMin = int(etaMin)/10
255  etaMax = etaParts[1].split('_')[0]
256  etaMax = int(etaMax)/10
257 
258  # Check for 2-3 digit number before f_ for forward triggers
259  if re.search(r'\d{2,3}f_', chain): #workaround for the HLT forward triggers with 2-3 digit numbers
260  etaMin,etaMax = 3.2,4.9
261 
262  if 'a_' in chain: #new full eta range triggers
263  etaMin,etaMax = 0,4.9
264 
265  return etaMin,etaMax
266 
267 def getBinningFromThreshold(chain,varname):
268  #default binning if nothing below applies
269  xbins, xmin, xmax = 160,0.,800000.
270  #pt and et binning based on threshold
271  if varname == "pt" or varname == "et":
272  if 'noalg' in chain:
273  if 'jJ500' in chain or 'J400' in chain: return 160,xmin,800000
274  else: return 100,xmin,500000 # good enough for L1 jJ40 & jJ100
275  else:
276  #threshold = int(chain.split("_")[1].split('j')[1])
277  threshold = int(re.search(r'\d+',chain.split("_")[1].split('j')[1]).group())
278  if threshold < 50:
279  return 40, 0., 100000.
280  if threshold < 120:
281  return 36, 20000., 200000.
282 
283  xbins = 40
284  xmin = 50000.+100000.*(int(threshold/100)-1) #example: threshold = 330 -> 250 to 450; threshold = 420 -> 350 to 550
285  if threshold % 100 == 0: #gives enough low bins if threshold is an exact divider of 100 GeV such as 3j200
286  xmin = 1000.*(threshold - 100.)
287  xmax = xmin + 200000.
288  if "a10" in chain: # efficiency curve broader for large-R jets
289  xmin = xmin - 50000.
290  xmax = xmax + 50000.
291  if "pf" in chain:
292  xmax = xmax + 50000. # needed to include efficiency plateau for large-R PFlow chains
293  if "smc" in chain:
294  xmax = xmax + 50000. # efficiency plateau even higher for a10 pdf smc chains due to imperfect calibration
295  #mass binning for large-R smc chains
296  elif varname == "m":
297  xbins, xmin, xmax = 35, 30000., 100000.
298  return xbins, xmin, xmax
299 
300 def getHTBinning(chain,binwidth):
301  parts = chain.split('HT')
302  threshold = parts[1].split('_')[0]
303  if 'XX' in threshold:
304  threshold = threshold.split('XX')[0]
305  xmin = int(0.9 * int(threshold)) # xmin to make the threshold visible
306  xmax = xmin + 500
307  xbins = int((xmax-xmin)/binwidth)-1
308  return xbins, xmin, xmax
309 
310 # Add fast flavour-tag monitoring.
311 # Adds a 20 GeV jet pT cut to avoid FPE WARNINGS from jets below min jet pT for RoI track association
312 def addFlavourTagVariables(conf, network_prefix, flavs="cub"):
313  cutname='pt20'
314  fillerTools = []
315  for f in flavs:
316  xvar = f"{network_prefix}_p{f}"
317  varname = f"ftag_p{f}"
318  fillerTools += [HistoSpec(varname, xvar=xvar, bins=(70, -0.2, 1.2), title=f"{varname};{varname};;Entries")]
319  fastDipsSelectSpec = SelectSpec(f"{network_prefix}_{cutname}", '20<pt:GeV&|eta|<3.2', path='NoTriggerSelection/'+cutname, FillerTools=fillerTools)
320  conf.appendHistos(fastDipsSelectSpec)
321 
322 
325 from JetMonitoring.JetMonitoringConfig import JetMonAlgSpec, HistoSpec, EventHistoSpec, SelectSpec, ToolSpec #VarSpec can be added to define specific/custom variables
326 from AthenaConfiguration.ComponentFactory import CompFactory
327 
328 # All offline jet collections
329 ExtraOfflineHists = [
330  "EMFrac",
331  "HECFrac",
332  "Jvt",
333  "JVFCorr",
334  "JvtRpt",
335  "NumTrkPt1000[0]",
336  "TrackWidthPt1000[0]",
337  "SumPtTrkPt500[0]",
338 ]
339 
340 # All online small-R jet collections
341 ExtraSmallROnlineHists = [
342  HistoSpec('et:GeV;eta', (100,0,750, 50,-5,5) , title='#eta vs E_{T};E_{T} [GeV];#eta;Entries'),
343  "EMFrac",
344  "HECFrac",
345  "DetectorEta",
346  "ActiveArea",
347  "EM3Frac",
348  "Tile0Frac",
349  "LooseBad",
350 ]
351 
352 # All online large-R jet collections
353 ExtraLargeROnlineHists = [
354 ]
355 
356 ExtraOnlineNJetHists = [
357  "njets",
358 ]
359 
360 # Kinematics at different scales for offline and small-R online jet collections
361 OfflineScaleMomenta = [ "ConstitScale", "EMScale", "PileupScale", "EtaJESScale"]
362 OnlineScaleMomenta = [ "ConstitScale" ]
363 for var in [ "pt", "eta", "m" ]:
364  for offlinescale in OfflineScaleMomenta:
365  ExtraOfflineHists.append("Jet"+offlinescale+"Momentum_"+var)
366  for onlinescale in OnlineScaleMomenta:
367  ExtraSmallROnlineHists.append("Jet"+onlinescale+"Momentum_"+var)
368 
369 OnlineScaleMomenta.append("") #Adding this for convenience in the jet matching loop below
370 OfflineScaleMomenta.append("")
371 
372 
373 def getJetCopyAlg(injets,outjets):
374  '''
375  Schedules JetCopier tool to make a shallow copy of
376  the original offline/HLT jet container, for the JetMatcherAlg to decorate.
377  This prevents our jet monitoring from decorating
378  the original jet containers, which may end up being
379  persistified in AOD/ESD (ATLASRECTS-7168,ATR-27980,ATR-26076)
380  '''
381  jcopy = CompFactory.JetCopier(
382  "copier",
383  InputJets = injets,
384  DecorDeps=[],
385  ShallowCopy=True,
386  ShallowIO=True)
387 
388  jprovider = CompFactory.JetRecAlg(
389  "jetalg_copy_"+outjets,
390  Provider = jcopy,
391  Modifiers = [],
392  OutputContainer = outjets,
393  MonTool = None)
394 
395  return jprovider
396 
397 def getL1JetCopyAlg(injets,outjets):
398  '''
399  Schedules L1JetCopyAlgorithm to make a shallow copy of
400  the original L1 jet container, for the JetMatcherAlg to decorate.
401  This prevents our jet monitoring from decorating
402  the original jet containers, which may end up being
403  persistified in AOD/ESD (ATLASRECTS-7168,ATR-27980,ATR-26076).
404  The L1JetCopyAlgorithm is a templated class (e.g. L1JetCopyAlgorithm<JTM_JetRoIContainer>).
405  The python class name is what is generated by Athena during build time.
406  The template types are defined in JTMContainers.h.
407  '''
408  jcopy_alg = None
409  jcopy_alg_name = "l1jetcopy_alg_"+injets
410  if injets == "L1_jFexSRJetRoI":
411  jcopy_alg = CompFactory.L1JetCopyAlgorithm_JTM_jFexSRJetRoIContainer_(jcopy_alg_name)
412  elif injets in ["L1_gFexSRJetRoI", "L1_gFexLRJetRoI"]:
413  jcopy_alg = CompFactory.L1JetCopyAlgorithm_JTM_gFexJetRoIContainer_(jcopy_alg_name)
414  else:
415  raise ValueError(f"L1 jet container {injets} not recognised")
416  jcopy_alg.JetInContainerName = injets
417  jcopy_alg.JetOutContainerName = outjets
418 
419  return jcopy_alg
420 
421 def TrigJetMonConfig(inputFlags):
422 
423  from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
424  cfg = ComponentAccumulator()
425 
426  monMode = 'pp'
427  if inputFlags.Reco.EnableHI: monMode = 'HI'
428 
429  Chains2Monitor = getChains2Monitor(inputFlags, monMode)
430 
431  # Protections
432  # Add missing jet collections to JetCollections dict
433  # (this can happen if a given chain uses a jet collection that is not listed in JetCollections)
434  # TODO: make more general
435  for chain,chaindict in Chains2Monitor[monMode].items():
436  if chaindict['HLTColl'] not in JetCollections[case]: # chain will not be monitored unless HLT collection is present in JetCollections
437  JetCollections[case][chaindict['HLTColl']] = {'MatchTo': 'NONE'}
438 
439  # Match HLT jets to offline jets
440  CopiedJetCollections = copy.deepcopy(JetCollections)
441  for hltColl,collDict in JetCollections[monMode].items():
442  if collDict['MatchTo'] != 'NONE':
443  copiedhltColl = f'{hltColl}_{copySuffix}'
444  CopiedJetCollections[monMode][copiedhltColl] = CopiedJetCollections[monMode].pop(hltColl)
445  jetcopyalg = getJetCopyAlg(hltColl,copiedhltColl)
446  jetcopyalg.ExtraInputs.add(('xAOD::TrigCompositeContainer',
447  'StoreGateSvc+%s' % getRun3NavigationContainerFromInput(inputFlags)))
448  cfg.addEventAlgo(jetcopyalg)
449  for jetcalibscale in OnlineScaleMomenta:
450  scalestring = "_"+jetcalibscale if jetcalibscale != "" else ""
451  name = 'Matching_{}{}_{}'.format(hltColl,scalestring,collDict['MatchTo'])
452  alg = CompFactory.JetMatcherAlg(name,
453  JetContainerName1=copiedhltColl,
454  JetContainerName2=collDict['MatchTo'],
455  JetCalibScale=jetcalibscale)
456 
457  alg.ExtraInputs.add(('xAOD::TrigCompositeContainer',
458  'StoreGateSvc+%s' % getRun3NavigationContainerFromInput(inputFlags)))
459  cfg.addEventAlgo(alg)
460 
461  # Match offline to offline jets
462  CopiedOfflineJetCollections = copy.deepcopy(OfflineJetCollections)
463  for offjetColl,collDict in OfflineJetCollections[monMode].items():
464  if collDict['MatchTo'] != 'NONE':
465  copiedjetcoll = f'{offjetColl}_{copySuffix}'
466  CopiedOfflineJetCollections[monMode][copiedjetcoll] = CopiedOfflineJetCollections[monMode].pop(offjetColl)
467  jetcopyalg = getJetCopyAlg(offjetColl,copiedjetcoll)
468  cfg.addEventAlgo(jetcopyalg)
469  for jetcalibscale in OfflineScaleMomenta:
470  scalestring = "_"+jetcalibscale if jetcalibscale != "" else ""
471  name = 'Matching_{}{}_{}'.format(offjetColl,scalestring,collDict['MatchTo'])
472  alg = CompFactory.JetMatcherAlg(name,
473  JetContainerName1=copiedjetcoll,
474  JetContainerName2=collDict['MatchTo'],
475  JetCalibScale=jetcalibscale)
476 
477  alg.ExtraInputs.add(('xAOD::TrigCompositeContainer',
478  'StoreGateSvc+%s' % getRun3NavigationContainerFromInput(inputFlags)))
479  cfg.addEventAlgo(alg)
480 
481  # Make copy of every L1 jet collection
482  # Then match L1 to offline as well as HLT jets
483  CopiedL1JetCollections = copy.deepcopy(L1JetCollections)
484  for l1jetColl,collDict in L1JetCollections[monMode].items():
485  copiedl1jetColl = f'{l1jetColl}_{copySuffix}'
486  CopiedL1JetCollections[monMode][copiedl1jetColl] = CopiedL1JetCollections[monMode].pop(l1jetColl)
487  l1jetcopyalg = getL1JetCopyAlg(l1jetColl,copiedl1jetColl)
488  l1jetcopyalg.ExtraInputs.add(('xAOD::TrigCompositeContainer',
489  'StoreGateSvc+%s' % getRun3NavigationContainerFromInput(inputFlags)))
490  cfg.addEventAlgo(l1jetcopyalg)
491  for matchjetcoll in collDict['MatchTo']:
492 
493  kwds = {'name': 'Matching_{}_{}'.format(l1jetColl,matchjetcoll),
494  l1Coll2MatcherKey[l1jetColl]: copiedl1jetColl,
495  'JetContainerName2': matchjetcoll,
496  'MatchL1': True
497  }
498 
499  alg = CompFactory.JetMatcherAlg(**kwds)
500  alg.ExtraInputs.add(('xAOD::TrigCompositeContainer',
501  'StoreGateSvc+%s' % getRun3NavigationContainerFromInput(inputFlags)))
502  cfg.addEventAlgo(alg)
503 
504  # The following class will make a sequence, configure algorithms, and link
505  # them to GenericMonitoringTools
506  from AthenaMonitoring import AthMonitorCfgHelper
507  helper = AthMonitorCfgHelper(inputFlags,'TrigJetMonitorAlgorithm')
508  # Configure filter tools
509  from AthenaMonitoring.EventFlagFilterToolConfig import EventFlagFilterToolCfg
510  from AthenaMonitoring.BadLBFilterToolConfig import LArBadLBFilterToolCfg
511  # Loop over L1 jet collections
512  for jetcoll in CopiedL1JetCollections[monMode]:
513  l1jetconf = l1JetMonitoringConfig(inputFlags,jetcoll,CopiedL1JetCollections,monMode,'',True)
514  alg=l1jetconf.toAlg(helper)
515  alg.FilterTools = [ EventFlagFilterToolCfg(inputFlags),helper.resobj.popToolsAndMerge(LArBadLBFilterToolCfg(inputFlags))]
516 
517  # Loop over L1 jet chains
518  for chain,jetcolls in Chain2L1JetCollDict[monMode].items():
519  for jetcoll in jetcolls:
520  l1chainconf = l1JetMonitoringConfig(inputFlags,jetcoll,L1JetCollections,monMode,chain)
521  alg=l1chainconf.toAlg(helper)
522  alg.FilterTools = [ EventFlagFilterToolCfg(inputFlags),helper.resobj.popToolsAndMerge(LArBadLBFilterToolCfg(inputFlags))]
523 
524  # Loop over offline jet collections
525  for jetcoll in CopiedOfflineJetCollections[monMode]:
526  offlineMonitorConf = jetMonitoringConfig(inputFlags,jetcoll,CopiedOfflineJetCollections,monMode)
527  alg=offlineMonitorConf.toAlg(helper)
528  alg.FilterTools = [ EventFlagFilterToolCfg(inputFlags),helper.resobj.popToolsAndMerge(LArBadLBFilterToolCfg(inputFlags))]
529 
530  # Loop over HLT jet collections
531  for jetcoll in CopiedJetCollections[monMode]:
532  monitorConf = jetMonitoringConfig(inputFlags,jetcoll,CopiedJetCollections,monMode)
533  # then we turn the full specification into properly configured algorithm and tools.
534  # we use the method 'toAlg()' defined for the specialized dictionnary 'JetMonAlgSpec'
535  monitorConf.toAlg(helper)
536 
537  # Loop over HLT jet chains
538  for chain,chainDict in Chains2Monitor[monMode].items():
539  jetcoll = chainDict['HLTColl']
540  # kinematic plots
541  # only use passing jets
542  # skip for noalg chains
543  if 'noalg' not in chain:
544  chainMonitorConfT = jetChainMonitoringConfig(inputFlags,jetcoll,chain,True)
545  alg=chainMonitorConfT.toAlg(helper)
546  alg.FilterTools = [ EventFlagFilterToolCfg(inputFlags),helper.resobj.popToolsAndMerge(LArBadLBFilterToolCfg(inputFlags))]
547  # all jets
548  chainMonitorConfF = jetChainMonitoringConfig(inputFlags,jetcoll,chain,False)
549  alg=chainMonitorConfF.toAlg(helper)
550  alg.FilterTools = [ EventFlagFilterToolCfg(inputFlags),helper.resobj.popToolsAndMerge(LArBadLBFilterToolCfg(inputFlags))]
551  # efficiency plots
552  if chainDict['RefChain'] != 'NONE' and chainDict['OfflineColl'] != 'NONE':
553  effMonitorConf = jetEfficiencyMonitoringConfig(inputFlags,jetcoll,chainDict['OfflineColl'],chain,chainDict['RefChain'])
554  effMonitorConf.toAlg(helper)
555 
556  cfg.merge(helper.result())
557  return cfg
558 
559 
560 # Basic selection of histograms common for online and offline jets
561 def basicJetMonAlgSpec(jetcoll,isOnline):
562  # we use a specialized dictionnary (JetMonAlgSpec) which will be translated into the final C++ tool
563  path = 'NoTriggerSelection' if isOnline else 'standardHistos/'
564  minNjetBin = 1 if isOnline else 0
565 
566  TopLevelDir = 'HLT/JetMon/'
567  TopLevelDir += 'Online/' if isOnline else 'Offline/'
568 
569  jetcollFolder = jetcoll
570  jetcollFolder=jetcoll.replace(f"_{copySuffix}","")
571  Conf = JetMonAlgSpec(jetcoll+"Mon",JetContainerName = jetcoll, defaultPath = path, topLevelDir=TopLevelDir, bottomLevelDir=jetcollFolder, failureOnMissingContainer=False)
572 
573  # Now start filling the histo spec list
574  Conf.appendHistos(
575 
576  #See knownHistos in JetStandardHistoSpecs.py for the list of standard specification.
577  #or we can directly add our custom histo specification in the form of a HistoSpec:
578  #the basic call is : HistoSpec( variable, histobins, title='histotile;xtitle,ytitle')
579 
580  #Say we want a 2nd 'pt' plot but with a different binning than in the standard spec.
581  #WARNING : we can not re-use the same spec name in a given JetMonitoringAlg !!!
582  #so we give a new name AND we specify the actual variable with the argument 'xvar'
583  #(the ':GeV' means the variable is to be set at GeV scale)
584  #HistoSpec( 'lowpt', (100,0,150) , title='p_{T};p_{T} [GeV];', xvar='pt:GeV'),
585  #An equivalent solution would have been to clone the existing spec like in :
586  #knownHistos.pt.clone('lowpt',bins= (100,0,200) ),
587 
588  #2D histos are usually refered to by concatenating vars with a ';' as in 'varx;vary'
589  #if the 'vax;vary' alias doesn't exist in knownHistos but 'varx' and 'vary'
590  #do exist, then a spec fot 'vax;vary' will be automatically generated.
591 
592 
593  #Jet multiplicity histograms can be added by using an EventHistoSpec
594  #Their specifications (pT cut, ET cut, eta cuts) must be defined in the knownEventVar dictionary within JetStandardHistoSpecs.py
595  #The following line is an example for a jet multiplicity histogram with ET>40 GeV, 1.0<|eta|<2.0, and binning of (10,0,10):
596  #EventHistoSpec('njetsEt40Eta1_2', (10,0,10), title='NJetsEt40Eta1_2;NJetsEt40Eta1_2;Entries' ),
597 
598  #To select on multiple variables simultaneously, simply combine the selection strings via &
599  #Example below to select on ET > 100 GeV and |eta| > 3.2:
600  #SelectSpec( 'ETeta', '100<et:GeV&|eta|<3.2', path, FillerTools = ["pt","et","m","eta"] )
601 
602  #TProfile2D : just use 3 variables. For now the sytem will automatically
603  #interpret it as a TProfile2D (the 3rd variable being profiled)
604  #"phi;eta;e", --> Average Energy vs pt and eta
605 
606  #another possible selections : only sub-leading jets and highJVF
607  #SelectSpec( 'subleading',
608  # '', # no selection on variables
609  # SelectedIndex=1, # force 2nd (sub-leading) jet (we would set 0 for leading jets)
610  # path='standardHistos', # force the path where the histos are saved in the final ROOT file
611  # FillerTools = [
612  # "pt",
613  # "m",
614  # ] ),
615  #SelectSpec( 'highJVF',
616  # '0.3<JVF[0]', # JVF is a vector<float> for each jets. Here we cut on the 0th entry of this vector
617  # FillerTools = [
618  # "pt",
619  # ] ),
620 
621  #1D histos
622  "pt",
623  "m",
624  "eta",
625  "phi",
626  "e",
627  "et",
628 
629  #2D histos
630  "pt;m", # mass vs pt
631  "eta;phi", # phi vs eta
632  "eta;e", # energy vs eta
633  "phi;e", # energy vs phi
634 
635  #Event selection
636  SelectSpec( 'central', '|eta|<3.2', path, FillerTools = ["pt","et","m"] ),
637  SelectSpec( 'forward', '3.2<|eta|', path, FillerTools = ["pt","et","m"] ),
638  SelectSpec( 'lowmu', 'avgMu<30', path, isEventVariable=True, FillerTools = ["pt","et","m","phi","eta"]),
639  SelectSpec( 'highmu', '30<avgMu', path, isEventVariable=True, FillerTools = ["pt","et","m","phi","eta"]),
640 
641  EventHistoSpec('njets', (25,minNjetBin,25), title='NJets;NJets;Entries' ),
642  EventHistoSpec('njetsPt20', (25,minNjetBin,25), title='NJetsPt20;NJetsPt20;Entries' ),
643  EventHistoSpec('njetsPt50', (25,minNjetBin,25), title='NJetsPt50;NJetsPt50;Entries' ),
644 
645  )
646 
647  return Conf
648 
649 # Basic selection of histograms common for heavy ion online and offline jets
650 def basicHIJetMonAlgSpec(jetcoll,isOnline):
651  # we use a specialized dictionnary (JetMonAlgSpec) which will be translated into the final C++ tool
652  path = 'NoTriggerSelection' if isOnline else 'standardHistos/'
653 
654  TopLevelDir = 'HLT/JetMon/'
655  TopLevelDir += 'Online/' if isOnline else 'Offline/'
656 
657  jetcollFolder = jetcoll
658  jetcollFolder=jetcoll.replace(f"_{copySuffix}","")
659  Conf = JetMonAlgSpec(jetcoll+"Mon",JetContainerName = jetcoll, defaultPath = path, topLevelDir=TopLevelDir, bottomLevelDir=jetcollFolder, failureOnMissingContainer=False)
660 
661  # Now start filling the histo spec list
662  Conf.appendHistos(
663 
664  #See knownHistos in JetStandardHistoSpecs.py for the list of standard specification.
665  #or we can directly add our custom histo specification in the form of a HistoSpec:
666  #the basic call is : HistoSpec( variable, histobins, title='histotile;xtitle,ytitle')
667 
668  #Say we want a 2nd 'pt' plot but with a different binning than in the standard spec.
669  #WARNING : we can not re-use the same spec name in a given JetMonitoringAlg !!!
670  #so we give a new name AND we specify the actual variable with the argument 'xvar'
671  #(the ':GeV' means the variable is to be set at GeV scale)
672  #HistoSpec( 'lowpt', (100,0,150) , title='p_{T};p_{T} [GeV];', xvar='pt:GeV'),
673  #An equivalent solution would have been to clone the existing spec like in :
674  #knownHistos.pt.clone('lowpt',bins= (100,0,200) ),
675 
676  #2D histos are usually refered to by concatenating vars with a ';' as in 'varx;vary'
677  #if the 'vax;vary' alias doesn't exist in knownHistos but 'varx' and 'vary'
678  #do exist, then a spec fot 'vax;vary' will be automatically generated.
679 
680  #Jet multiplicity histograms can be added by using an EventHistoSpec
681  #Their specifications (pT cut, ET cut, eta cuts) must be defined in the knownEventVar dictionary within JetStandardHistoSpecs.py
682  #The following line is an example for a jet multiplicity histogram with ET>40 GeV, 1.0<|eta|<2.0, and binning of (10,0,10):
683  #EventHistoSpec('njetsEt40Eta1_2', (10,0,10), title='NJetsEt40Eta1_2;NJetsEt40Eta1_2;Entries' ),
684 
685  #To select on multiple variables simultaneously, simply combine the selection strings via &
686  #Example below to select on ET > 100 GeV and |eta| > 3.2:
687  #SelectSpec( 'ETeta', '100<et:GeV&|eta|<3.2', path, FillerTools = ["pt","et","m","eta"] )
688 
689  #TProfile2D : just use 3 variables. For now the sytem will automatically
690  #interpret it as a TProfile2D (the 3rd variable being profiled)
691  #"phi;eta;e", --> Average Energy vs pt and eta
692 
693  #another possible selections : only sub-leading jets and highJVF
694  #SelectSpec( 'subleading',
695  # '', # no selection on variables
696  # SelectedIndex=1, # force 2nd (sub-leading) jet (we would set 0 for leading jets)
697  # path='standardHistos', # force the path where the histos are saved in the final ROOT file
698  # FillerTools = [
699  # "pt",
700  # "m",
701  # ] ),
702  #SelectSpec( 'highJVF',
703  # '0.3<JVF[0]', # JVF is a vector<float> for each jets. Here we cut on the 0th entry of this vector
704  # FillerTools = [
705  # "pt",
706  # ] ),
707 
708  #1D histos
709  "pt",
710  "m",
711  "eta",
712  "phi",
713  "et",
714 
715  #2D histos
716  "eta;phi", # phi vs eta
717  HistoSpec( 'pt:GeV;m:GeV', (100,0,400, 100,0,400) , title='p_{T} vs mass;p_{T} [GeV];m [GeV];Entries'),
718  HistoSpec( 'eta;et:GeV', (100,-5,5, 100,0,400) , title='#eta vs e_{T};#eta;E_{T} [GeV];Entries'),
719  HistoSpec( 'phi;et:GeV', (60,-math.pi,math.pi, 100,0,400) , title='#phi vs E_{T};#phi;E_{T} [GeV];Entries'),
720 
721  #Event selection
722  SelectSpec( 'central', '|eta|<3.2', path, FillerTools = ["pt","et","m"] ),
723  SelectSpec( 'forward', '3.2<|eta|', path, FillerTools = ["pt","et","m"] ),
724  SelectSpec( 'pt60', '60<pt:GeV', path, FillerTools = ["m","phi","eta","eta;phi"]),
725 
726  )
727 
728  return Conf
729 
730 def jetMonitoringConfig(inputFlags,jetcoll,jetCollDict,monMode):
731  '''Function to configures some algorithms in the monitoring system.'''
732 
733  isOnline = True if 'HLT' in jetcoll else False
734 
735  if monMode == 'HI': # Heavy ion jet monitoring histos
736  conf = basicHIJetMonAlgSpec(jetcoll,isOnline)
737  else:
738  conf = basicJetMonAlgSpec(jetcoll,isOnline)
739 
740  jetCollMonDetails = jetCollDict[monMode][jetcoll]
741 
742  # Declare a configuration dictionnary for a JetContainer
743  if isOnline:
744  if 'AntiKt4' in jetcoll or 'a4tcem' in jetcoll:
745  if monMode == 'pp': #Use extra histos for pp only
746  for hist in ExtraSmallROnlineHists: conf.appendHistos(hist)
747  if 'ftf' in jetcoll: # dedicated histograms for FTF chains
748  conf.appendHistos("Jvt")
749  conf.appendHistos("JVFCorr")
750  conf.appendHistos("JvtRpt")
751  conf.appendHistos("SumPtTrkPt500[0]")
752  conf.appendHistos("NumTrkPt1000[0]")
753  conf.appendHistos("TrackWidthPt1000[0]")
754  if 'PF' in jetcoll: # dedicated histograms for online PFlow jets
755  conf.appendHistos("SumPtChargedPFOPt500[0]")
756  conf.appendHistos("fCharged")
757  if "subresjesgscIS" in jetcoll:
758  addFlavourTagVariables(conf,"fastDIPS20211215")
759  addFlavourTagVariables(conf,"GN120230331")
760  addFlavourTagVariables(conf,"tlaGN220240122")
761  if 'fastftag' in jetcoll:
762  addFlavourTagVariables(conf,"fastDips")
763  addFlavourTagVariables(conf, "fastGN120230327")
764  addFlavourTagVariables(conf,"fastGN220240122")
765  addFlavourTagVariables(conf,"fastGNTau20240216", flavs=["tau", "u"])
766  if 'EMTopo' in jetcoll: #dedicated histograms for online EMTopo jets
767  conf.appendHistos("Timing")
768  else:
769  for hist in ExtraLargeROnlineHists: conf.appendHistos(hist)
770  # Add matched jets plots
771  if jetCollMonDetails['MatchTo'] != 'NONE':
772  def defineHistoForHLTJetMatch(conf, parentAlg, monhelper , path):
773  # create a monitoring group with the histo path starting from the parentAlg
774  group = monhelper.addGroup(parentAlg, conf.Group, conf.topLevelDir+'/'+conf.bottomLevelDir+'/NoTriggerSelection/')
775  # define the histograms
776  for histname in [ 'ptdiff', 'energydiff', 'massdiff' ]: #defines which variable difference will be plotted
777  group.defineHistogram(histname,title=histname, type="TH1F",
778  path='MatchedJets_{}'.format(jetCollMonDetails['MatchTo']),
779  xbins=100 , xmin=-100000., xmax=100000. ,)
780 
781  for histname in [ 'ptresp', 'energyresp', 'massresp' ]:
782  group.defineHistogram(histname,title=histname, type="TH1F",
783  path='MatchedJets_{}'.format(jetCollMonDetails['MatchTo']),
784  xbins=100 , xmin=-2., xmax=2. ,)
785 
786  group.defineHistogram('ptresp,ptref;ptresp_vs_ptRef',title='ptresponse vs ptRef', type="TH2F",
787  path='MatchedJets_{}'.format(jetCollMonDetails['MatchTo']),
788  xbins=10 , xmin=-2., xmax=2., ybins=10, ymin=0., ymax=500000.,)
789 
790  group.defineHistogram('ptresp,etaref;ptresp_vs_etaRef',title='ptresponse vs etaRef', type="TH2F",
791  path='MatchedJets_{}'.format(jetCollMonDetails['MatchTo']),
792  xbins=10 , xmin=-2., xmax=2., ybins=10, ymin=-5., ymax=5.,)
793 
794  group.defineHistogram('ptref,ptresp;ptRef_vs_ptresp',title='ptRef vs ptresponse', type="TH2F",
795  path='MatchedJets_{}'.format(jetCollMonDetails['MatchTo']),
796  xbins=100 , xmin=0., xmax=400000., ybins=80, ymin=-2., ymax=2.,)
797 
798  group.defineHistogram('etaref,ptresp;etaRef_vs_ptresp',title='etaRef vs ptresponse', type="TH2F",
799  path='MatchedJets_{}'.format(jetCollMonDetails['MatchTo']),
800  xbins=100 , xmin=-5., xmax=5., ybins=80, ymin=-2., ymax=2.,)
801 
802  matchedJetColl = jetCollMonDetails['MatchTo']
803 
804  # we can get specific calibration scales by adding e.g. '_EtaJESScale' to the strings
805  jetmatchKey = '{}.matched_{}'.format(jetcoll,matchedJetColl)
806  jetptdiffKey = '{}.ptdiff_{}'.format(jetcoll,matchedJetColl)
807  jetenergydiffKey = '{}.energydiff_{}'.format(jetcoll,matchedJetColl)
808  jetmassdiffKey = '{}.massdiff_{}'.format(jetcoll,matchedJetColl)
809  jetptrespKey = '{}.ptresp_{}'.format(jetcoll,matchedJetColl)
810  jetenergyrespKey = '{}.energyresp_{}'.format(jetcoll,matchedJetColl)
811  jetmassrespKey = '{}.massresp_{}'.format(jetcoll,matchedJetColl)
812  jetptrefKey = '{}.ptRef_{}'.format(jetcoll,matchedJetColl)
813  jetetarefKey = '{}.etaRef_{}'.format(jetcoll,matchedJetColl)
814  name = 'jetMatched_{}_{}'.format(jetcoll,matchedJetColl)
815  conf.appendHistos(ToolSpec('JetHistoMatchedFiller', name,
816  JetMatchedKey=jetmatchKey, JetPtDiffKey=jetptdiffKey,
817  JetEnergyDiffKey=jetenergydiffKey,
818  JetMassDiffKey=jetmassdiffKey, JetPtRespKey=jetptrespKey,
819  JetEnergyRespKey=jetenergyrespKey, JetMassRespKey=jetmassrespKey,
820  JetPtRefKey=jetptrefKey,JetEtaRefKey=jetetarefKey,
821  defineHistoFunc=defineHistoForHLTJetMatch,Group='matchedJets_'+jetcoll)
822  )
823  else: # offline
824  for hist in ExtraOfflineHists: conf.appendHistos(hist)
825  if 'AntiKt4' in jetcoll and monMode=="pp":
826  conf.appendHistos(SelectSpec('LooseBadFailedJets', 'LooseBad',
827  InverseJetSel=True,
828  FillerTools = ["pt",
829  "phi",
830  "eta"])) #cleaning variables not applicable for large-R collections
831 
832  if 'PF' in jetcoll: # dedicated histograms for offline PFlow jets
833  conf.appendHistos("SumPtChargedPFOPt500[0]")
834  conf.appendHistos("fCharged")
835  elif 'EMTopo' in jetcoll:
836  conf.appendHistos("Timing")
837  if jetCollMonDetails['MatchTo'] != 'NONE':
838  def defineHistoForOfflineJetMatch(conf, parentAlg, monhelper , path):
839  # create a monitoring group with the histo path starting from the parentAlg
840  group = monhelper.addGroup(parentAlg, conf.Group, conf.topLevelDir+'/'+conf.bottomLevelDir+'/standardHistos/')
841  # define the histograms
842  for histname in [ 'ptdiff', 'energydiff', 'massdiff' ]: #defines which variable difference will be plotted
843  group.defineHistogram(histname,title=histname, type="TH1F",
844  path='MatchedJets_{}'.format(jetCollMonDetails['MatchTo']),
845  xbins=100 , xmin=-100000., xmax=100000. ,)
846 
847  for histname in [ 'ptresp', 'energyresp', 'massresp' ]:
848  group.defineHistogram(histname,title=histname, type="TH1F",
849  path='MatchedJets_{}'.format(jetCollMonDetails['MatchTo']),
850  xbins=100 , xmin=-2., xmax=2. ,)
851 
852  group.defineHistogram('ptresp,ptref;ptresp_vs_ptRef',title='ptresp vs ptRef', type="TH2F",
853  path='MatchedJets_{}'.format(jetCollMonDetails['MatchTo']),
854  xbins=10 , xmin=-2., xmax=2., ybins=10, ymin=0., ymax=500000.,)
855 
856  group.defineHistogram('ptresp,etaref;ptresp_vs_etaRef',title='ptresp vs etaRef', type="TH2F",
857  path='MatchedJets_{}'.format(jetCollMonDetails['MatchTo']),
858  xbins=10 , xmin=-2., xmax=2., ybins=10, ymin=-5., ymax=5.,)
859 
860  group.defineHistogram('ptref,ptresp;ptRef_vs_ptresp',title='ptRef vs ptresponse', type="TH2F",
861  path='MatchedJets_{}'.format(jetCollMonDetails['MatchTo']),
862  xbins=100 , xmin=0., xmax=400000., ybins=80, ymin=-2., ymax=2.,)
863 
864  group.defineHistogram('etaref,ptresp;etaRef_vs_ptresp',title='etaRef vs ptresponse', type="TH2F",
865  path='MatchedJets_{}'.format(jetCollMonDetails['MatchTo']),
866  xbins=100 , xmin=-5., xmax=5., ybins=80, ymin=-2., ymax=2.,)
867 
868  matchedJetColl = jetCollMonDetails['MatchTo']
869  jetmatchKey = '{}.matched_{}'.format(jetcoll,matchedJetColl)
870  jetptdiffKey = '{}.ptdiff_{}'.format(jetcoll,matchedJetColl)
871  jetenergydiffKey = '{}.energydiff_{}'.format(jetcoll,matchedJetColl)
872  jetmassdiffKey = '{}.massdiff_{}'.format(jetcoll,matchedJetColl)
873  jetptrespKey = '{}.ptresp_{}'.format(jetcoll,matchedJetColl)
874  jetenergyrespKey = '{}.energyresp_{}'.format(jetcoll,matchedJetColl)
875  jetmassrespKey = '{}.massresp_{}'.format(jetcoll,matchedJetColl)
876  jetptrefKey = '{}.ptRef_{}'.format(jetcoll,matchedJetColl)
877  jetetarefKey = '{}.etaRef_{}'.format(jetcoll,matchedJetColl)
878  name = 'jetMatched_{}_{}'.format(jetcoll,matchedJetColl)
879  conf.appendHistos(ToolSpec('JetHistoMatchedFiller',name,
880  JetMatchedKey=jetmatchKey, JetPtDiffKey=jetptdiffKey,
881  JetEnergyDiffKey=jetenergydiffKey,
882  JetMassDiffKey=jetmassdiffKey, JetPtRespKey=jetptrespKey,
883  JetEnergyRespKey=jetenergyrespKey,
884  JetMassRespKey=jetmassrespKey,
885  JetPtRefKey=jetptrefKey, JetEtaRefKey=jetetarefKey,
886  defineHistoFunc=defineHistoForOfflineJetMatch,Group='matchedJets_'+jetcoll)
887  )
888 
889  return conf
890 
891 def l1JetMonitoringConfig(inputFlags,jetColl, jetDict, monMode,chain='',matched=False):
892 
893  from TrigJetMonitoring.L1JetMonitoringConfig import L1JetMonAlg
894  name = jetColl if chain=='' else jetColl+'_'+chain
895 
896  jetCollKey = jetColl
897  jetColl = jetColl.replace(f"_{copySuffix}","")
898 
899  if not jetDict[monMode][jetCollKey]['MatchTo']:
900  conf = L1JetMonAlg(name,jetColl,jetCollKey,chain)
901  else:
902  assert len(jetDict[monMode][jetCollKey]['MatchTo']) == 2
903 
904  conf = L1JetMonAlg(name,jetColl,jetCollKey,chain,
905  matched,jetDict[monMode][jetCollKey]['MatchTo'][0],
906  jetDict[monMode][jetCollKey]['MatchTo'][1])
907 
908  return conf
909 
910 def jetChainMonitoringConfig(inputFlags,jetcoll,chain,onlyUsePassingJets=True):
911  '''Function to configures some algorithms in the monitoring system.'''
912 
913  jetcollFolder = jetcoll
914  chainFolder = chain
915 
916  #if not athenaMT:
917  # onlyUsePassingJets = False #does not work for legacy samples yet
918  jetMonAlgSpecName = chain+"TrigMon"
919  if not onlyUsePassingJets:
920  chainFolder = chainFolder + "/ExpertHistos"
921  jetMonAlgSpecName = jetMonAlgSpecName + "_ExpertHistos"
922 
923  # Define helper functions to automatize ET & eta selection strings for NJet histograms of chains
924  def getThreshold(parts):
925  return parts[1].split('_')[0]
926 
927  def getEtaRangeString(chain):
928  etaMin, etaMax = 0, 32
929  if 'eta490_j' in chain: #workaround for the upc chains
930  etaMin, etaMax = 0, 49
931  elif 'eta' in chain:
932  etaParts = chain.split('eta')
933  etaMinTemp = etaParts[0].split('_')
934  etaMin = etaMinTemp[len(etaMinTemp)-1]
935  etaMax = etaParts[1].split('_')[0]
936  if int(etaMin) > 0 : etaMin = str(int(int(etaMin)/10))
937  if int(etaMax) > 0 : etaMax = str(int(int(etaMax)/10))
938  if 'f_ion' in chain:
939  etaMin, etaMax = 32, 49
940  return 'Eta{}_{}'.format(etaMin,etaMax)
941 
942  def getNjetHistName(chain):
943  NjetHistName = 'NONE'
944  parts = chain.split('j')
945  # check if it is a multi-threshold multijet chain or a single-threshold multijet chain
946  multiplicity = parts[0].split('_')[1] # for single-threshold multijet chains
947  if (chain.count('_j')-chain.count('_jes')) > 1 or multiplicity != '':
948  NjetHistName = 'njetsEt{}{}'.format(getThreshold(parts),getEtaRangeString(chain))
949  return NjetHistName
950 
951 
952  trigConf = JetMonAlgSpec( # the usual JetMonAlgSpec
953  jetMonAlgSpecName,
954  JetContainerName = jetcoll,
955  TriggerChain = chain,
956  defaultPath = chainFolder,
957  topLevelDir="HLT/JetMon/Online/",
958  bottomLevelDir=jetcollFolder,
959  failureOnMissingContainer=True,
960  onlyPassingJets=onlyUsePassingJets,
961  isExpressStreamJob=inputFlags.Common.doExpressProcessing,
962  )
963 
964  trigConf.appendHistos(
965  "pt",
966  "m",
967  "eta",
968  "et",
969  "phi",
970  )
971  for hist in ExtraOnlineNJetHists: trigConf.appendHistos(EventHistoSpec(hist, (20,0,25), title=hist+';'+hist+';Entries'))
972  # Add NjetEt and NjetPt histograms for simple scenarios
973  if 'ht' not in chain and 'HT' not in chain and 'dijet' not in chain and 'DIJET' not in chain and 'fbdj' not in chain and 'noalg' not in chain:
974  NjetHistName = getNjetHistName(chain)
975  from JetMonitoring.JetStandardHistoSpecs import knownEventVar
976  if knownEventVar.get(NjetHistName,None) is not None and NjetHistName not in ExtraOnlineNJetHists: #avoids duplication warnings for some chains
977  trigConf.appendHistos(
978  EventHistoSpec(NjetHistName, (25,0,25), title=NjetHistName+';'+NjetHistName+';Entries' ),
979  )
980  NjetHistName = NjetHistName.replace('Et','Pt')
981  if knownEventVar.get(NjetHistName,None) is not None and NjetHistName not in ExtraOnlineNJetHists:
982  trigConf.appendHistos(
983  EventHistoSpec(NjetHistName, (25,0,25), title=NjetHistName+';'+NjetHistName+';Entries' ),
984  )
985  if 'ftf' in chain and 'a10' not in chain: # track-based JVT variables for FTF chains
986  trigConf.appendHistos("Jvt")
987  trigConf.appendHistos("JVFCorr")
988  trigConf.appendHistos("JvtRpt")
989 
990  if 'ht' in chain or 'HT' in chain:
991  def defineHistoForHTChain(conf, parentAlg, monhelper , path):
992  # create a monitoring group with the histo path starting from the parentAlg
993  group = monhelper.addGroup(parentAlg, conf.Group, conf.topLevelDir+jetcollFolder+'/')
994  # define the histograms
995  xbins, xmin, xmax = getHTBinning(chain,25) # bin width in GeV
996  group.defineHistogram("jetHT;HT",title="Jet HT;H_{T} [GeV];Entries", type="TH1F", path=chainFolder, xbins=xbins , xmin=xmin, xmax=xmax ,)
997  trigConf.appendHistos(ToolSpec('JetHistoHTFiller','JetHistoHTFiller_'+chain,MinPt=30.,MaxEta=3.2,FailureOnMissingContainer=False,
998  defineHistoFunc=defineHistoForHTChain,Group='jetHT_'+jetcoll))
999 
1000  return trigConf
1001 
1002 def jetEfficiencyMonitoringConfig(inputFlags,onlinejetcoll,offlinejetcoll,chain,refChain):
1003  '''Function to configures some algorithms in the monitoring system.'''
1004 
1005  jetcollFolder = onlinejetcoll
1006  chainFolder = chain
1007 
1008  # We schedule a new JetAlg which will be acting only when a TriggerChain fired (using the TriggerChain from the base classes).
1009  # We'll plot 1 histo build by a dedicated JetHistoTriggEfficiency tool.
1010  # So we'll have to explicitely give a specification via the generic dicionnary 'ToolSpec'
1011  # This implies defining a little function which declares to the monitoring framework which variables to histogram and how.
1012  # this is done here.
1013  def defineHistoForJetTrigg(conf, parentAlg, monhelper , path):
1014  # create a monitoring group with the histo path starting from the parentAlg
1015  group = monhelper.addGroup(parentAlg, conf.Group, conf.topLevelDir+jetcollFolder+'/')
1016  # define the histogram, give them individual names so they don't overwrite each other
1017  append = "offlineCut_"+conf.name.split("_")[-1] if "offlineCut" in conf.name else "noOfflineCut"
1018  histname = "trigEff_vs_"+conf.Var.Name+"_"+append
1019  xbins, xmin, xmax = getBinningFromThreshold(chain,conf.Var.Name)
1020  group.defineHistogram('trigPassed,jetVar;'+histname, title=histname, type="TEfficiency",
1021  path=chainFolder,
1022  xbins=xbins , xmin=xmin, xmax=xmax,)
1023 
1024  # Get jet index and eta selection for offline jets
1025  validchain = chain.replace('noalg','j0')
1026  parts = validchain.split('j')
1027  multiplicity = parts[0].split('_')[1]
1028  if multiplicity != '': index = int(multiplicity) - 1 # single-threhold multijet chains
1029  else: index = 0 # single-jet chain
1030  etaMin,etaMax = getEtaRange(chain)
1031 
1032  from JetMonitoring.JetMonitoringConfig import retrieveVarToolConf
1033  trigConf = JetMonAlgSpec( # the usual JetMonAlgSpec
1034  chain+"TrigEffMon",
1035  JetContainerName = offlinejetcoll,
1036  TriggerChain = refChain, # reference chain
1037  defaultPath = chainFolder,
1038  topLevelDir = "HLT/JetMon/Online/",
1039  bottomLevelDir = jetcollFolder,
1040  failureOnMissingContainer = True,
1041  onlyPassingJets = False,
1042  )
1043  trigConf.appendHistos(
1044  SelectSpec( 'eff', '{}<|eta|<{}'.format(etaMin,etaMax), chainFolder, SelectedIndex=index, FillerTools = [
1045  # we pass directly the ToolSpec
1046  ToolSpec('JetHistoTriggEfficiency', chain,
1047  # below we pass the Properties of this JetHistoTriggEfficiency tool :
1048  Group='jetTrigGroup_'+chain,
1049  Var=retrieveVarToolConf("pt"), # In this context we can not just pass a str alias to describe a histo variable
1050  # so we use retrieveVarToolConf("pt") which returns a full specification for the "pt" histo variable.
1051  ProbeTrigChain=chain,defineHistoFunc=defineHistoForJetTrigg),
1052  ] ),
1053  )
1054 
1055  if 'smc' in chain:
1056  trigConf.appendHistos(
1057  SelectSpec( 'm50', '50<m:GeV&{}<|eta|<{}'.format(etaMin,etaMax), chainFolder, SelectedIndex=index, FillerTools = [
1058  ToolSpec('JetHistoTriggEfficiency', chain+'_offlineCut_m50',
1059  Group='jetTrigGroup_'+chain+'_m50',
1060  Var=retrieveVarToolConf("pt"), # In this context we can not just pass a str alias to describe a histo variable
1061  ProbeTrigChain=chain,defineHistoFunc=defineHistoForJetTrigg
1062  ),
1063  ] ),
1064  SelectSpec( 'et500', '500<et:GeV&{}<|eta|<{}'.format(etaMin,etaMax), chainFolder, SelectedIndex=index, FillerTools = [
1065  ToolSpec('JetHistoTriggEfficiency', chain+'_offlineCut_et500',
1066  Group='jetTrigGroup_'+chain+'_et500',
1067  Var=retrieveVarToolConf("m"), # In this context we can not just pass a str alias to describe a histo variable
1068  SortJets=True,
1069  ProbeTrigChain=chain,defineHistoFunc=defineHistoForJetTrigg
1070  ),
1071  ] ),
1072  )
1073 
1074  return trigConf
1075 
1076 if __name__=='__main__':
1077 
1078  import sys,argparse
1079 
1080  # Read arguments
1081  parser = argparse.ArgumentParser()
1082  parser.add_argument('--runTruthReco', action='store_true', dest='runTruthReco', default=False)
1083  parser.add_argument('--genOfflineR10PF', action='store_true', dest='genOfflineR10PF', default=False)
1084  parser.add_argument('--printDetailedConfig', action='store_true', dest='printDetailedConfig', default=False)
1085  parser.add_argument('--input', action='store', dest='inputFile')
1086  args = parser.parse_args()
1087  RunTruth = args.runTruthReco
1088  GenOfflineR10PF = args.genOfflineR10PF
1089  PrintDetailedConfig = args.printDetailedConfig
1090 
1091  # Input file
1092  if args.inputFile is not None: inputFile = args.inputFile
1093  else:
1094  logger.error('ERROR: No input file provided, exiting')
1095  sys.exit(0)
1096 
1097  # Setup logs
1098  from AthenaCommon.Logging import log
1099  from AthenaCommon.Constants import INFO #,DEBUG
1100  log.setLevel(INFO)
1101 
1102  # Set the Athena configuration flags
1103  from AthenaConfiguration.AllConfigFlags import initConfigFlags
1105  flags.Input.Files = [inputFile]
1106  flags.Input.isMC = True
1107  flags.Output.HISTFileName = 'AthenaMTMonitorOutput.root'
1108  flags.lock()
1109 
1110  monMode = 'pp'
1111  if flags.Reco.EnableHI: monMode = 'HI'
1112 
1113  Chains2Monitor = getChains2Monitor(flags, monMode)
1114 
1115  # Protections
1116  # Add missing jet collections to JetCollections dict
1117  # (this can happen if a given chain uses a jet collection that is not listed in JetCollections)
1118  # TODO: make more general
1119  for chain,chaindict in Chains2Monitor[monMode].items():
1120  if chaindict['HLTColl'] not in JetCollections[case]: # chain will not be monitored unless HLT collection is present in JetCollections
1121  JetCollections[case][chaindict['HLTColl']] = {'MatchTo': 'NONE'}
1122 
1123  # Initialize configuration object, add accumulator, merge, and run.
1124  from AthenaConfiguration.MainServicesConfig import MainServicesCfg
1125  from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg
1126  cfg = MainServicesCfg(flags)
1127 
1128  # Define the output list
1129  outputlist = ["xAOD::EventInfo#*","xAOD::VertexContainer#*","xAOD::JetContainer#AntiKt4*Jets","xAOD::JetAuxContainer#AntiKt4*JetsAux.-PseudoJet","xAOD::JetContainer#HLT_*","xAOD::JetAuxContainer#HLT_*Aux.-PseudoJet","xAOD::ShallowAuxContainer#HLT_*Aux.-PseudoJet"]
1130  # Reconstruct small-R truth jets
1131  if RunTruth:
1132  from JetRecConfig.StandardSmallRJets import AntiKt4Truth # import the standard definitions
1133  # Add the components from our jet reconstruction job
1134  from JetRecConfig.JetRecConfig import JetRecCfg
1135  comp = JetRecCfg(AntiKt4Truth,flags)
1136  cfg.merge(comp)
1137  # add jets to the output list
1138  key = "{0}Jets".format(AntiKt4Truth.basename)
1139  outputlist += ["xAOD::JetContainer#"+key,"xAOD::JetAuxContainer#"+key+"Aux.-PseudoJet"]
1140 
1141  # Reconstruct offline large-R PFlow CSSK+SD jets
1142  if GenOfflineR10PF:
1143  from JetRecConfig.JetDefinition import JetConstitSeq, JetDefinition, xAODType
1144  EMPFlowCSSK = JetConstitSeq("EMPFlowCSSK", xAODType.ParticleFlow, ["CorrectPFO","CS","SK","CHS"], "JetETMissParticleFlowObjects", "CSSKParticleFlowObjects", label="EMPFlowCSSK")
1145  AntiKt10EMPFlowCSSK = JetDefinition("AntiKt",1.0,EMPFlowCSSK,ptmin=2e3,)
1146  AntiKt10EMPFlowCSSK.modifiers = ["ConstitFourMom","Sort","Filter:2000"]
1147  from JetRecConfig.JetGrooming import JetSoftDrop
1148  from JetRecConfig.StandardLargeRJets import standardrecomods,substrmods
1149  AntiKt10EMPFlowCSSKSoftDrop = JetSoftDrop(AntiKt10EMPFlowCSSK,modifiers=standardrecomods+substrmods,ZCut=0.1,Beta=1.0) # standard SoftDrop
1150  # Add the components from our jet reconstruction job
1151  from JetRecConfig.JetRecConfig import JetRecCfg
1152  comp = JetRecCfg(AntiKt10EMPFlowCSSKSoftDrop,flags)
1153  cfg.merge(comp)
1154  # add jets to the output list
1155  key = "{0}Jets".format(AntiKt10EMPFlowCSSKSoftDrop.basename)
1156  outputlist += ["xAOD::JetContainer#"+key,"xAOD::JetAuxContainer#"+key+"Aux.-PseudoJet"]
1157 
1158  # Write new jet collections to AOD
1159  if RunTruth or GenOfflineR10PF:
1160  # Get the output stream components
1161  from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg
1162  cfg.merge(OutputStreamCfg(flags,"xAOD",ItemList=outputlist))
1163 
1164  cfg.merge(PoolReadCfg(flags))
1165 
1166  # The following class will make a sequence, configure algorithms, and link
1167  # them to GenericMonitoringTools
1168  from AthenaMonitoring import AthMonitorCfgHelper
1169  helper = AthMonitorCfgHelper(flags,'TrigJetMonitorAlgorithm')
1170  cfg.merge(helper.result()) # merge it to add the sequence needed to add matchers
1171 
1172  # Match HLT jets to offline jets
1173  for hltColl,collDict in JetCollections[monMode].items():
1174  if collDict['MatchTo'] != 'NONE':
1175  for jetcalibscale in OnlineScaleMomenta:
1176  scalestring = "_"+jetcalibscale if jetcalibscale != "" else ""
1177  name = 'Matching_{}{}_{}'.format(hltColl,scalestring,collDict['MatchTo'])
1178  alg = CompFactory.JetMatcherAlg(name, JetContainerName1=hltColl,JetContainerName2=collDict['MatchTo'],JetCalibScale=jetcalibscale)
1179  alg.ExtraInputs.add(('xAOD::TrigCompositeContainer','StoreGateSvc+%s' % getRun3NavigationContainerFromInput(flags)))
1180  cfg.addEventAlgo(alg,sequenceName='AthMonSeq_TrigJetMonitorAlgorithm') # Add matchers to monitoring alg sequence
1181 
1182  # Match offline to offline jets
1183  for offjetColl,collDict in OfflineJetCollections[monMode].items():
1184  if collDict['MatchTo'] != 'NONE':
1185  for jetcalibscale in OfflineScaleMomenta:
1186  scalestring = "_"+jetcalibscale if jetcalibscale != "" else ""
1187  name = 'Matching_{}{}_{}'.format(offjetColl,scalestring,collDict['MatchTo'])
1188  alg = CompFactory.JetMatcherAlg(name, JetContainerName1=offjetColl,JetContainerName2=collDict['MatchTo'],JetCalibScale=jetcalibscale)
1189  alg.ExtraInputs.add(('xAOD::TrigCompositeContainer','StoreGateSvc+%s' % getRun3NavigationContainerFromInput(flags)))
1190  cfg.addEventAlgo(alg,sequenceName='AthMonSeq_TrigJetMonitorAlgorithm')
1191 
1192  # Match L1 to offline as well as HLT jets
1193  for l1jetColl,collDict in L1JetCollections[monMode].items():
1194  for matchjetcoll in collDict['MatchTo']:
1195  if matchjetcoll != 'NONE':
1196  name = 'Matching_{}_{}'.format(l1jetColl,matchjetcoll)
1197  alg = CompFactory.JetMatcherAlg(name, L1JetContainerName1=l1jetColl,JetContainerName2=matchjetcoll,MatchL1=True)
1198  alg.ExtraInputs.add(('xAOD::TrigCompositeContainer','StoreGateSvc+%s' % getRun3NavigationContainerFromInput(flags)))
1199  cfg.addEventAlgo(alg,sequenceName='AthMonSeq_TrigJetMonitorAlgorithm')
1200 
1201  # Loop over L1 jet collectoins
1202  for jetcoll in L1JetCollections[monMode]:
1203  l1jetconf = l1JetMonitoringConfig(flags,jetcoll,L1JetCollections,monMode,'',True)
1204  l1jetconf.toAlg(helper)
1205 
1206  # Loop over L1 jet chains
1207  for chain,jetcoll in Chain2L1JetCollDict[monMode].items():
1208  l1chainconf = l1JetMonitoringConfig(flags,jetcoll,L1JetCollections,monMode,chain)
1209  l1chainconf.toAlg(helper)
1210 
1211  # Loop over offline jet collections
1212  for jetcoll in OfflineJetCollections[monMode]:
1213  offlineMonitorConf = jetMonitoringConfig(flags,jetcoll,OfflineJetCollections,monMode)
1214  offlineMonitorConf.toAlg(helper)
1215 
1216  # Loop over HLT jet collections
1217  for jetcoll in JetCollections[monMode]:
1218  monitorConf = jetMonitoringConfig(flags,jetcoll,JetCollections,monMode)
1219  # then we turn the full specification into properly configured algorithm and tools.
1220  # we use the method 'toAlg()' defined for the specialized dictionnary 'JetMonAlgSpec'
1221  monitorConf.toAlg(helper)
1222 
1223  # Loop over HLT jet chains
1224  for chain,chainDict in Chains2Monitor[monMode].items():
1225  jetcoll = chainDict['HLTColl']
1226  # kinematic plots
1227  # only passing jets
1228  # skip for noalg chains
1229  if 'noalg' not in chain:
1230  chainMonitorConfT = jetChainMonitoringConfig(flags,jetcoll,chain,True)
1231  chainMonitorConfT.toAlg(helper)
1232  # all jets
1233  chainMonitorConfF = jetChainMonitoringConfig(flags,jetcoll,chain,False)
1234  chainMonitorConfF.toAlg(helper)
1235  # efficiency plots
1236  if chainDict['RefChain'] != 'NONE' and chainDict['OfflineColl'] != 'NONE':
1237  effMonitorConf = jetEfficiencyMonitoringConfig(flags, jetcoll,
1238  chainDict['OfflineColl'], chain,
1239  chainDict['RefChain'])
1240  effMonitorConf.toAlg(helper)
1241 
1242  cfg.merge(helper.result())
1243 
1244  # Print config
1245  cfg.printConfig(withDetails=PrintDetailedConfig)
1246 
1247  cfg.run()
python.OutputStreamConfig.OutputStreamCfg
def OutputStreamCfg(flags, streamName, ItemList=None, MetadataItemList=None, disableEventTag=False, trigNavThinningSvc=None, takeItemsFromInput=False, extendProvenanceRecord=True, keepProvenanceTagsRegEx=None, AcceptAlgs=None, HelperTools=None)
Definition: OutputStreamConfig.py:13
TrigJetMonitorAlgorithm.getEtaRange
def getEtaRange(chain)
Helpful functions.
Definition: TrigJetMonitorAlgorithm.py:245
TrigJetMonitorAlgorithm.getJetCopyAlg
def getJetCopyAlg(injets, outjets)
Definition: TrigJetMonitorAlgorithm.py:373
python.JetAnalysisCommon.ComponentAccumulator
ComponentAccumulator
Definition: JetAnalysisCommon.py:302
vtune_athena.format
format
Definition: vtune_athena.py:14
python.TriggerConfigAccess.getHLTMonitoringAccess
HLTMonitoringAccess getHLTMonitoringAccess(flags=None)
Definition: TriggerConfigAccess.py:256
TrigJetMonitorAlgorithm.getHTBinning
def getHTBinning(chain, binwidth)
Definition: TrigJetMonitorAlgorithm.py:300
TrigJetMonitorAlgorithm.jetChainMonitoringConfig
def jetChainMonitoringConfig(inputFlags, jetcoll, chain, onlyUsePassingJets=True)
Definition: TrigJetMonitorAlgorithm.py:910
TrigJetMonitorAlgorithm.getChains2Monitor
def getChains2Monitor(inputFlags, monMode)
Definition: TrigJetMonitorAlgorithm.py:176
TrigJetMonitorAlgorithm.l1JetMonitoringConfig
def l1JetMonitoringConfig(inputFlags, jetColl, jetDict, monMode, chain='', matched=False)
Definition: TrigJetMonitorAlgorithm.py:891
TrigJetMonitorAlgorithm.TrigJetMonConfig
def TrigJetMonConfig(inputFlags)
Definition: TrigJetMonitorAlgorithm.py:421
TrigJetMonitorAlgorithm.jetMonitoringConfig
def jetMonitoringConfig(inputFlags, jetcoll, jetCollDict, monMode)
Definition: TrigJetMonitorAlgorithm.py:730
TrigJetMonitorAlgorithm.getBinningFromThreshold
def getBinningFromThreshold(chain, varname)
Definition: TrigJetMonitorAlgorithm.py:267
TrigJetMonitorAlgorithm.addFlavourTagVariables
def addFlavourTagVariables(conf, network_prefix, flavs="cub")
Definition: TrigJetMonitorAlgorithm.py:312
JetMonitoringConfig.retrieveVarToolConf
def retrieveVarToolConf(alias)
Definition: JetMonitoringConfig.py:584
python.BadLBFilterToolConfig.LArBadLBFilterToolCfg
def LArBadLBFilterToolCfg(inputFlags, origDbTag=None)
Definition: BadLBFilterToolConfig.py:100
python.TrigDecisionToolConfig.getRun3NavigationContainerFromInput
def getRun3NavigationContainerFromInput(flags)
Definition: TrigDecisionToolConfig.py:63
TrigJetMonitorAlgorithm.jetEfficiencyMonitoringConfig
def jetEfficiencyMonitoringConfig(inputFlags, onlinejetcoll, offlinejetcoll, chain, refChain)
Definition: TrigJetMonitorAlgorithm.py:1002
python.JetRecConfig.JetRecCfg
def JetRecCfg(flags, jetdef, returnConfiguredDef=False)
Top level functions returning ComponentAccumulator out of JetDefinition.
Definition: JetRecConfig.py:36
python.MainServicesConfig.MainServicesCfg
def MainServicesCfg(flags, LoopMgr='AthenaEventLoopMgr')
Definition: MainServicesConfig.py:310
Constants
some useful constants -------------------------------------------------—
TrigJetMonitorAlgorithm.items
items
Definition: TrigJetMonitorAlgorithm.py:71
TrigJetMonitorAlgorithm.basicJetMonAlgSpec
def basicJetMonAlgSpec(jetcoll, isOnline)
Definition: TrigJetMonitorAlgorithm.py:561
CaloLCW_tf.group
group
Definition: CaloLCW_tf.py:28
python.CaloAddPedShiftConfig.int
int
Definition: CaloAddPedShiftConfig.py:45
python.AllConfigFlags.initConfigFlags
def initConfigFlags()
Definition: AllConfigFlags.py:19
python.EventFlagFilterToolConfig.EventFlagFilterToolCfg
def EventFlagFilterToolCfg(flags, name="EventFlagFilter", doLAr=True, doTile=True, doSCT=True, doCore=True, alwaysReturnTrue=False)
Definition: EventFlagFilterToolConfig.py:5
get
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition: hcg.cxx:127
getThreshold
CP::CorrectionCode getThreshold(Int_t &threshold, const std::string &trigger)
Definition: MuonTriggerSFRootCoreTest.cxx:48
str
Definition: BTagTrackIpAccessor.cxx:11
TrigJetMonitorAlgorithm.basicHIJetMonAlgSpec
def basicHIJetMonAlgSpec(jetcoll, isOnline)
Definition: TrigJetMonitorAlgorithm.py:650
python.PoolReadConfig.PoolReadCfg
def PoolReadCfg(flags)
Definition: PoolReadConfig.py:71
Trk::split
@ split
Definition: LayerMaterialProperties.h:38
TrigJetMonitorAlgorithm.getL1JetCopyAlg
def getL1JetCopyAlg(injets, outjets)
Definition: TrigJetMonitorAlgorithm.py:397