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