ATLAS Offline Software
Loading...
Searching...
No Matches
TrigTauMonitoringConfig.py
Go to the documentation of this file.
1# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
2
3from AthenaConfiguration.ComponentFactory import CompFactory
4from AthenaMonitoring.DQConfigFlags import DQDataType
5
6import functools
7
9 # Configuration flags
10 # Can be accessed in the --preExec with e.g.:
11 # --preExec 'from TrigTauMonitoring.TrigTauMonitoringConfig import TrigTauMonAlgBuilder; TrigTauMonAlgBuilder.do_total_efficiency=True'
12 # But be careful! Changing settings in this way will affect all instances of the TrigTauMonitoring (although you should normally have only 1)
13
14 #=============================================
15 # Monitoring modules
16 #=============================================
17 do_single_tau = True
18 do_L1 = True
19 do_ditau = True
20 do_boosted_ditau = True
21 do_tag_and_probe = True
22 do_truth = True # Truth monitoring will only be used when running on MC data
23
24 #=============================================
25 # Configuration
26 #=============================================
27 do_total_efficiency = False # Enable total efficiency plots (HLT vs Offline, without the L1 matching as in the normal HLT Efficiency plots)
28
29 require_offline_taus = True # Require at least 1 offline good-quality tau (regardless of p_T) on ALL events (except in the Truth monitoring).
30 # This will bias the background events variable distributions of online objects, but will better represent the signal events (the events included in the efficiency numerators)
31
32 do_duplicate_var_plots_without_offline_taus = True # Duplicate variable distribution plots without the requirement of at least 1 offline good-quality tau (regardless of p_T) on ALL events (except in the Truth monitoring).
33 do_duplicate_with_offline_gntau = True # Duplicate all plots with offline GNTaus (except in the Truth monitoring).
34
35 #=============================================
36 # TauID monitoring
37 #=============================================
38 hlt_tauid_scores = {
39 'tracktwoMVA': {
40 'GNTauDev1': ('GNTauDev1_Score', 'GNTauDev1_ScoreSigTrans'),
41 'GNTau': ('GNTau_Score', 'GNTau_ScoreSigTrans'),
42 'DeepSet': ('RNNJetScore', 'RNNJetScoreSigTrans'),
43 },
44 'tracktwoLLP': {
45 'RNNLLP': ('RNNJetScore', 'RNNJetScoreSigTrans'),
46 },
47 'trackLRT': {
48 'RNNLLP': ('RNNJetScore', 'RNNJetScoreSigTrans'),
49 },
50
51 # Archive:
52 'tracktwoMVABDT': { 'RNN': ('RNNJetScore', 'RNNJetScoreSigTrans') }, # Deprecated
53 }
54
55 offline_tauid_scores = {
56 'RNN': ('RNNJetScore', 'RNNJetScoreSigTrans'),
57 'GNTau': ('GNTauScore_v0prune', 'GNTauScoreSigTrans_v0prune'),
58 }
59 offline_taujets = 'TauJets'
60 offline_GNTau_WP = ''
61
62 #=============================================
63 # Setup for L1Calo monitoring
64 #=============================================
65 do_alternative_eTAU_monitoring = False # Run the L1 monitoring again, for the Alt (heuristic) eTAU simulation
66
67 def __init__(self, helper):
68 from AthenaCommon.Logging import logging
69 self.logger = logging.getLogger('TrigTauMonAlgBuilder')
70
71 self.base_path = 'HLT/TauMon'
72 self.helper = helper
73
74 # Threshold information for all Phase 1 items
75 self.L1_Phase1_thresholds = {} # E_T cuts
76 self.L1_Phase1_threshold_mappings = {} # thresholdMappings bit masks
77
78 # Monitoring algorithms, and lists of items to monitor (will be filled on configure())
80 self.mon_alg_single = None
82
84 self.mon_alg_ditau = None
86
90
94
96 self.mon_alg_truth = None
98
99 self.activate_L1 = self.do_L1
100 self.mon_alg_L1 = None
101 self.L1_items = []
102
103 self.configureMode()
104
105
106 def configureMode(self):
107 self.is_mc = False
108
109 self.data_type = self.helper.flags.DQ.DataType
110 self.logger.debug('Configuring for %s', self.data_type)
111
112 if self.data_type is DQDataType.MC:
113 self.is_mc = True
114 self.logger.debug('Enabling Truth monitoring')
115 else:
116 self.activate_truth = False
117 self.logger.debug('Using default monitoring configuration for collisions')
118
119 if self.helper.flags.DQ.Environment == "tier0":
121 # We don't have any configuration specific for Cosmics or HI (the HLT Tau Monitoring is disabled for this one)
122 # If we did, we could specify it here
123
124
125 def configure(self):
126 # First load and classify the list of triggers
127 self.configureTriggers()
128
129 # Now create, configure, and book the histograms for all the individual algorithms
130 self.logger.info('Creating the Tau monitoring algorithms...')
131
132 if self.activate_single_tau:
134
135 if self.activate_ditau:
137
140
143
144 if self.activate_truth:
146
147 if self.activate_L1:
149
150 @functools.cached_property
152 import ROOT
153 m = ROOT.std.map[ROOT.std.string, ROOT.float]()
154 for item, thr in self.L1_Phase1_thresholds.items():
155 m[item] = thr
156 return m
157
158 @functools.cached_property
160 import ROOT
161 m = ROOT.std.map[ROOT.std.string, ROOT.uint64_t]()
162 for item, thr in self.L1_Phase1_threshold_mappings.items():
163 m[item] = thr
164 return m
165
166 @functools.lru_cache(maxsize=1000)
167 def getTriggerInfo(self, trigger: str, use_thresholds=True):
168 from TrigTauMonitoring.TrigTauInfo import TrigTauInfo
169 if use_thresholds:
171 else:
172 return TrigTauInfo(trigger)
173
174
176 self.logger.info('Configuring triggers')
177
178 from TrigConfigSvc.TriggerConfigAccess import getL1MenuAccess, getHLTMenuAccess, getHLTMonitoringAccess
179 # The L1 and HLT menus should always be available
180 L1_menu = getL1MenuAccess(self.helper.flags)
181 HLT_menu = getHLTMenuAccess(self.helper.flags)
182
183 # Try to load the monitoring groups
184 HLT_monitoring = getHLTMonitoringAccess(self.helper.flags)
185 all_items = HLT_monitoring.monitoredChains(signatures='tauMon', monLevels=['shifter', 't0', 'val'])
186 # If the mon groups are not available, fallback to the hard-coded trigger monitoring list
187 if not all_items:
188 from TrigTauMonitoring.ManualChains import monitored_chains
189 self.logger.info('Could not find any monitored tau chains in the HLTMonitoring information. Will use the available items from the fallback trigger list')
190 all_items = monitored_chains
191
192 # Classify HLT trigger chains:
193 for trigger in all_items:
194 # Skip items not included in the menu. This is needed if e.g. using the fallback list on new files without Legacy triggers, or old files
195 # without PhI triggers. Also some old SMKs have broken HLTMonitoring DB links, with chains that are not in the Trigger Menu
196 if trigger not in HLT_menu: continue
197
198 info = self.getTriggerInfo(trigger, use_thresholds=False)
199
200 if self.activate_single_tau and info.isHLTSingleTau():
201 self.HLT_single_items.append(trigger)
202 elif self.activate_ditau and info.isHLTDiTau():
203 self.HLT_ditau_items.append(trigger)
204 elif self.activate_boosted_ditau and info.isHLTBoostedDiTau():
205 self.HLT_boosted_ditau_items.append(trigger)
206 elif self.activate_tag_and_probe and info.isHLTTandP():
207 self.HLT_tag_and_probe_items.append(trigger)
208
209 if len(info.getL1TauItems()):
210 for l1_tau_item in map(str, info.getL1TauItems()): # The objects are of type std::string by default, and 'in' doesn't work properly on them
211 is_phase_1 = 'eTAU' in l1_tau_item or 'jTAU' in l1_tau_item or 'cTAU' in l1_tau_item
212 if is_phase_1 and l1_tau_item not in self.L1_Phase1_thresholds:
213 # We have only one threshold entry, because we don't use eta-dependent thresholds for Phase 1 TAU items:
214 self.L1_Phase1_thresholds[l1_tau_item] = float(L1_menu.thresholds()[l1_tau_item]['thrValues'][0]['value'])
215
216 self.L1_Phase1_threshold_mappings[l1_tau_item] = 1 << int(L1_menu.thresholds()[l1_tau_item]['mapping']) # thresholdPatterns property mask
217
218 if self.activate_L1 and f'L1{l1_tau_item}' not in self.L1_items:
219 self.L1_items.append(f'L1{l1_tau_item}')
220
221 if self.activate_single_tau:
223 self.logger.info(f'Configuring HLT single-tau monitored chains: {self.HLT_single_items}')
224 if not self.HLT_single_items:
225 self.logger.warning('Empty trigger list, disabling the single-tau monitoring')
226 self.activate_single_tau = False
227
228 if self.activate_ditau:
229 self.HLT_ditau_items.sort()
230 self.logger.info(f'Configuring HLT di-tau monitored chains: {self.HLT_ditau_items}')
231 if not self.HLT_ditau_items:
232 self.logger.warning('Empty trigger list, disabling the di-tau monitoring')
233 self.activate_ditau = False
234
237 self.logger.info(f'Configuring HLT Boosted di-tau monitored chains: {self.HLT_boosted_ditau_items}')
238 if not self.HLT_boosted_ditau_items:
239 self.logger.warning('Empty trigger list, disabling the boosted di-tau monitoring')
240 self.activate_boosted_ditau = False
241
244 self.logger.info(f'Configuring HLT Tag and Probe tau monitored chains: {self.HLT_tag_and_probe_items}')
245 if not self.HLT_tag_and_probe_items:
246 self.logger.warning('Empty trigger list, disabling the tag and probe monitoring')
247 self.activate_tag_and_probe = False
248
249 if self.activate_truth:
250 # We add all chains to the Truth monitoring
252 self.logger.info(f'Configuring HLT truth tau monitored chains: {self.HLT_truth_items}')
253 if not self.HLT_truth_items:
254 self.logger.warning('Empty trigger list, disabling the truth tau monitoring')
255 self.activate_truth = False
256
257 if self.activate_L1:
258 self.L1_items.sort()
259 self.logger.info(f'Configuring L1 tau monitored items: {self.L1_items}')
260 if not self.L1_items:
261 self.logger.warning('Empty trigger list, disabling the L1 tau monitoring')
262 self.activate_L1 = False
263
264
265 def _configureAlgorithm(self, algorithm_factory, name):
266 self.logger.info(f'Creating the monitoring algorithm: {name}')
267 mon_alg = self.helper.addAlgorithm(algorithm_factory, name)
268 mon_alg.L1Phase1Thresholds = self.L1_Phase1_thresholds
269 mon_alg.L1Phase1ThresholdPatterns = self.L1_Phase1_threshold_mappings
270 mon_alg.OfflineTauJetKey = self.offline_taujets
271 mon_alg.OfflineGNTauDecorKey = self.offline_GNTau_WP
272 return mon_alg
273
274
276 self.mon_alg_single = self._configureAlgorithm(CompFactory.TrigTauMonitorSingleAlgorithm, 'TrigTauMonAlgSingle')
277 self.mon_alg_single.TriggerList = self.HLT_single_items
278 self.mon_alg_single.DoTotalEfficiency = self.do_total_efficiency
279 self.mon_alg_single.RequireOfflineTaus = self.require_offline_taus
280 self.mon_alg_single.HLTTauIDScores = self.hlt_tauid_scores
281 self.mon_alg_single.OfflineTauIDScores = self.offline_tauid_scores
282
283 self.logger.info(' |- Booking all histograms')
284 for trigger in self.HLT_single_items:
285 # Efficiencies
286 for p in ('1P', '3P'):
287 self.bookHLTEffHistograms(self.mon_alg_single, self.base_path, trigger, n_prong=p)
288
289 # Online distributions
290 for p in ('0P', '1P', 'MP'):
291 self.bookBasicVars(self.mon_alg_single, self.base_path, trigger, n_prong=p, online=True)
292 self.bookIDScores(self.mon_alg_single, self.base_path, trigger, n_prong=p, online=True)
293 self.bookIDInputScalar(self.mon_alg_single, self.base_path, trigger, n_prong=p, online=True)
294 self.bookIDInputTrack(self.mon_alg_single, self.base_path, trigger, online=True)
295 self.bookIDInputCluster(self.mon_alg_single, self.base_path, trigger, online=True)
296
297 # Offline distributions
298 for p in ('1P', '3P'):
299 self.bookBasicVars(self.mon_alg_single, self.base_path, trigger, p, online=False)
300 self.bookIDScores(self.mon_alg_single, self.base_path, trigger, p, online=False)
301 self.bookIDInputScalar(self.mon_alg_single, self.base_path, trigger, n_prong=p, online=False)
302 self.bookIDInputTrack(self.mon_alg_single, self.base_path, trigger, online=False)
303 self.bookIDInputCluster(self.mon_alg_single, self.base_path, trigger, online=False)
304
306 self.mon_alg_single_no_offline = self._configureAlgorithm(CompFactory.TrigTauMonitorSingleAlgorithm, 'TrigTauMonAlgSingleNoOffline')
307 self.mon_alg_single_no_offline.TriggerList = self.HLT_single_items
308 self.mon_alg_single_no_offline.RequireOfflineTaus = False
309 self.mon_alg_single_no_offline.DoOfflineTausDistributions = False
310 self.mon_alg_single_no_offline.DoEfficiencyPlots = False
311 self.mon_alg_single_no_offline.HLTTauIDScores = self.hlt_tauid_scores
312
313 self.logger.info(' |- Booking all histograms')
314 path = f'{self.base_path}/OnlineOnlyVars'
315 for trigger in self.HLT_single_items:
316 for p in ('0P', '1P', 'MP'):
317 self.bookBasicVars(self.mon_alg_single_no_offline, path, trigger, n_prong=p, online=True)
318 self.bookIDScores(self.mon_alg_single_no_offline, path, trigger, n_prong=p, online=True)
319 self.bookIDInputScalar(self.mon_alg_single_no_offline, path, trigger, n_prong=p, online=True)
320 self.bookIDInputTrack(self.mon_alg_single_no_offline, path, trigger, online=True)
321 self.bookIDInputCluster(self.mon_alg_single_no_offline, path, trigger, online=True)
322
324 self.mon_alg_single_gntau = self._configureAlgorithm(CompFactory.TrigTauMonitorSingleAlgorithm, 'TrigTauMonAlgSingleGNTau')
325 self.mon_alg_single_gntau.TriggerList = self.HLT_single_items
326 self.mon_alg_single_gntau.DoTotalEfficiency = self.do_total_efficiency
327 self.mon_alg_single_gntau.RequireOfflineTaus = self.require_offline_taus
328 self.mon_alg_single_gntau.HLTTauIDScores = self.hlt_tauid_scores
329 self.mon_alg_single_gntau.OfflineTauIDScores = self.offline_tauid_scores
330 self.mon_alg_single_gntau.OfflineTauID = 2
331
332 self.logger.info(' |- Booking all histograms')
333 path = f'{self.base_path}/OfflineGNTau'
334 for trigger in self.HLT_single_items:
335 # Efficiencies
336 for p in ('1P', '3P'):
337 self.bookHLTEffHistograms(self.mon_alg_single_gntau, path, trigger, n_prong=p)
338
339 # Online distributions
340 for p in ('0P', '1P', 'MP'):
341 self.bookBasicVars(self.mon_alg_single_gntau, path, trigger, n_prong=p, online=True)
342 self.bookIDScores(self.mon_alg_single_gntau, path, trigger, n_prong=p, online=True)
343 self.bookIDInputScalar(self.mon_alg_single_gntau, path, trigger, n_prong=p, online=True)
344 self.bookIDInputTrack(self.mon_alg_single_gntau, path, trigger, online=True)
345 self.bookIDInputCluster(self.mon_alg_single_gntau, path, trigger, online=True)
346
347 # Offline distributions
348 for p in ('1P', '3P'):
349 self.bookBasicVars(self.mon_alg_single_gntau, path, trigger, p, online=False)
350 self.bookIDScores(self.mon_alg_single_gntau, path, trigger, p, online=False)
351 self.bookIDInputScalar(self.mon_alg_single_gntau, path, trigger, n_prong=p, online=False)
352 self.bookIDInputTrack(self.mon_alg_single_gntau, path, trigger, online=False)
353 self.bookIDInputCluster(self.mon_alg_single_gntau, path, trigger, online=False)
354
355
356
358 self.mon_alg_ditau = self._configureAlgorithm(CompFactory.TrigTauMonitorDiTauAlgorithm, 'TrigTauMonAlgDiTau')
359 self.mon_alg_ditau.TriggerList = self.HLT_ditau_items
360 self.mon_alg_ditau.DoTotalEfficiency = self.do_total_efficiency
361 self.mon_alg_ditau.RequireOfflineTaus = self.require_offline_taus
362
363 self.logger.info(' |- Booking all histograms')
364 for trigger in self.HLT_ditau_items:
365 self.bookDiTauHLTEffHistograms(self.mon_alg_ditau, self.base_path, trigger)
366 self.bookDiTauVars(self.mon_alg_ditau, self.base_path, trigger)
367
368
370 self.mon_alg_ditau_gntau = self._configureAlgorithm(CompFactory.TrigTauMonitorDiTauAlgorithm, 'TrigTauMonAlgDiTauGNTau')
371 self.mon_alg_ditau_gntau.TriggerList = self.HLT_ditau_items
372 self.mon_alg_ditau_gntau.DoTotalEfficiency = self.do_total_efficiency
373 self.mon_alg_ditau_gntau.RequireOfflineTaus = self.require_offline_taus
374 self.mon_alg_ditau_gntau.OfflineTauID = 2
375
376 self.logger.info(' |- Booking all histograms')
377 path = f'{self.base_path}/OfflineGNTau'
378 for trigger in self.HLT_ditau_items:
379 self.bookDiTauHLTEffHistograms(self.mon_alg_ditau_gntau, path, trigger)
380 self.bookDiTauVars(self.mon_alg_ditau_gntau, path, trigger)
381
383 self.mon_alg_boosted_ditau = self._configureAlgorithm(CompFactory.TrigTauMonitorBoostedDiTauAlgorithm, 'TrigTauMonAlgBoostedDiTau')
384 self.mon_alg_boosted_ditau.TriggerList = self.HLT_boosted_ditau_items
385
386 self.logger.info(' |- Booking all histograms')
387 for trigger in self.HLT_boosted_ditau_items:
389
391 self.mon_alg_tag_and_probe = self._configureAlgorithm(CompFactory.TrigTauMonitorTandPAlgorithm, 'TrigTauMonAlgTandP')
392 self.mon_alg_tag_and_probe.TriggerList = self.HLT_tag_and_probe_items
393 self.mon_alg_tag_and_probe.RequireOfflineTaus = self.require_offline_taus
394
395 self.logger.info(' |- Booking all histograms')
396 for trigger in self.HLT_tag_and_probe_items:
398 self.bookTAndPVars(self.mon_alg_tag_and_probe, self.base_path, trigger)
399
400
402 self.mon_alg_tag_and_probe_gntau = self._configureAlgorithm(CompFactory.TrigTauMonitorTandPAlgorithm, 'TrigTauMonAlgTandPGNTau')
404 self.mon_alg_tag_and_probe_gntau.RequireOfflineTaus = self.require_offline_taus
405
406 self.logger.info(' |- Booking all histograms')
407 path = f'{self.base_path}/OfflineGNTau'
408 for trigger in self.HLT_tag_and_probe_items:
410 self.bookTAndPVars(self.mon_alg_tag_and_probe_gntau, path, trigger)
411
412
414 self.mon_alg_truth = self._configureAlgorithm(CompFactory.TrigTauMonitorTruthAlgorithm, 'TrigTauMonAlgTruth')
415 self.mon_alg_truth.TriggerList = self.HLT_truth_items
416
417 self.logger.info(' |- Booking all histograms')
418 for trigger in self.HLT_truth_items:
419 for p in ('1P', '3P'):
420 self.bookTruthEfficiency(self.mon_alg_truth, self.base_path, trigger, n_prong=p)
421 self.bookTruthVars(self.mon_alg_truth, self.base_path, trigger, n_prong=p)
422
423
425 has_xtob_etau_rois = 'L1_eTauxRoI' in self.helper.flags.Input.Collections or self.helper.flags.DQ.Environment == "tier0"
426
427 self.mon_alg_L1 = self._configureAlgorithm(CompFactory.TrigTauMonitorL1Algorithm, 'TrigTauMonAlgL1')
428 self.mon_alg_L1.TriggerList = self.L1_items
429 self.mon_alg_L1.RequireOfflineTaus = self.require_offline_taus
430 if not has_xtob_etau_rois:
431 self.logger.info(' |- No L1_eTauxRoI container is available: e/cTAU BDT scores will be set to 0')
432 self.mon_alg_L1.Phase1L1eTauxRoIKey = ''
433
434 self.logger.info(' |- Booking all histograms')
435 for trigger in self.L1_items:
436 for p in ('1P', '3P'):
437 self.bookL1EffHistograms(self.mon_alg_L1, self.base_path, trigger, n_prong=p)
438 self.bookL1Vars(self.mon_alg_L1, self.base_path, trigger)
439
441 self.mon_alg_L1_no_offline = self._configureAlgorithm(CompFactory.TrigTauMonitorL1Algorithm, 'TrigTauMonAlgL1NoOffline')
442 self.mon_alg_L1_no_offline.TriggerList = self.L1_items
443 self.mon_alg_L1_no_offline.RequireOfflineTaus = False
444 self.mon_alg_L1_no_offline.DoEfficiencyPlots = False
445 if not has_xtob_etau_rois:
446 self.logger.info(' |- No L1_eTauxRoI container is available: e/cTAU BDT scores will be set to 0')
447 self.mon_alg_L1_no_offline.Phase1L1eTauxRoIKey = ''
448
449 self.logger.info(' |- Booking all histograms')
450 path = f'{self.base_path}/OnlineOnlyVars'
451 for trigger in self.L1_items:
452 self.bookL1Vars(self.mon_alg_L1_no_offline, path, trigger)
453
455 self.mon_alg_L1_alt = self._configureAlgorithm(CompFactory.TrigTauMonitorL1Algorithm, 'TrigTauMonAlgL1eTAUAlt')
456 self.mon_alg_L1_alt.Phase1L1eTauRoIKey = 'L1_eTauRoIAltSim' # Use alternative RoIs (with heuristic eTAU algorithm simulation)
457 self.mon_alg_L1_alt.SelectL1ByETOnly = True # We don't have threshold patterns for the Alt RoIs, so we match by ET only
458 self.mon_alg_L1_alt.RequireOfflineTaus = False
459 self.mon_alg_L1_alt.Phase1L1eTauxRoIKey = ''
460
461 l1_items = [item for item in self.L1_items if 'eTAU' in item and not self.getTriggerInfo(item).isL1TauIsolated()] # Only non-isolated eTAU items
462 self.mon_alg_L1_alt.TriggerList = l1_items
463
464 self.logger.info(' |- Booking all histograms')
465 path = f'{self.base_path}/L1eTAUAlt'
466 for trigger in l1_items:
467 for p in ('1P', '3P'):
468 self.bookL1EffHistograms(self.mon_alg_L1_alt, path, trigger, n_prong=p)
469 self.bookL1Vars(self.mon_alg_L1_alt, path, trigger)
470
472 self.mon_alg_L1_gntau = self._configureAlgorithm(CompFactory.TrigTauMonitorL1Algorithm, 'TrigTauMonAlgL1GNTau')
473 self.mon_alg_L1_gntau.TriggerList = self.L1_items
474 self.mon_alg_L1_gntau.RequireOfflineTaus = self.require_offline_taus
475 if not has_xtob_etau_rois:
476 self.logger.info(' |- No L1_eTauxRoI container is available: e/cTAU BDT scores will be set to 0')
477 self.mon_alg_L1_gntau.Phase1L1eTauxRoIKey = ''
478
479 self.logger.info(' |- Booking all histograms')
480 path = f'{self.base_path}/OfflineGNTau'
481 for trigger in self.L1_items:
482 for p in ('1P', '3P'):
483 self.bookL1EffHistograms(self.mon_alg_L1_gntau, path, trigger, n_prong=p)
484 self.bookL1Vars(self.mon_alg_L1_gntau, path, trigger)
485
486
487 def bookHLTEffHistograms(self, mon_alg, base_path, trigger, n_prong):
488 mon_group_name = f'{trigger}_HLT_Efficiency_{n_prong}'
489 mon_group_path = f'{base_path}/HLT_Efficiency/{trigger}/HLT_Efficiency_{n_prong}'
490 mon_group = self.helper.addGroup(mon_alg, mon_group_name, mon_group_path)
491
492 def defineEachStepHistograms(xvariable, xlabel, xbins, xmin, xmax, eff='HLT', high_pt=False, coarse=False):
493 pass_flag = f'{eff}_pass'
494 sfx = ''
495
496 if high_pt:
497 pass_flag += '_highPt'
498 sfx += '_highPt'
499 xlabel += ' (p_{T} > p_{T}^{thr} + 20 GeV)'
500 elif coarse: sfx = '_coarse'
501
502 mon_group.defineHistogram(f'{pass_flag},{xvariable};Eff{eff}_{xvariable}{sfx}_wrt_Offline',
503 title=f'{eff} Efficiency {trigger} {n_prong}; {xlabel}; Efficiency',
504 type='TEfficiency', xbins=xbins, xmin=xmin, xmax=xmax, opt='kAlwaysCreate')
505
506 coarse_binning = self.getCustomPtBinning(trigger)
507
508 eff_list = ['HLT'] + (['Total'] if self.do_total_efficiency else [])
509 for eff in eff_list:
510 defineEachStepHistograms('tauPt', 'p_{T} [GeV]', 60, 0.0, 300., eff)
511 defineEachStepHistograms('tauPt', 'p_{T} [GeV]', coarse_binning, coarse_binning[0], coarse_binning[-1], eff, coarse=True)
512 defineEachStepHistograms('tauEta', '#eta', 13, -2.6, 2.6, eff)
513 defineEachStepHistograms('tauPhi', '#phi', 16, -3.2, 3.2, eff)
514 defineEachStepHistograms('tauEta', '#eta', 13, -2.6, 2.6, eff, high_pt=True)
515 defineEachStepHistograms('tauPhi', '#phi', 16, -3.2, 3.2, eff, high_pt=True)
516 defineEachStepHistograms('averageMu', '#LT#mu#GT', 10, 0, 80, eff)
517
518 # Save quantities in TTree for offline analysis
519 mon_group.defineTree('tauPt,tauEta,tauPhi,averageMu,HLT_pass;HLTEffTree',
520 treedef='tauPt/F:tauEta/F:tauPhi/F:averageMu/F:HLT_pass/I')
521
522
523 def bookIDInputScalar(self, mon_alg, base_path, trigger, n_prong, online):
524 type_str = 'HLT' if online else 'Offline'
525 mon_group_name = f'{trigger}_ID_{type_str}_InputScalar_{n_prong}'
526 mon_group_path = f'{base_path}/TauIDVars/InputScalar_{n_prong}/{trigger}/{type_str}'
527 mon_group = self.helper.addGroup(mon_alg, mon_group_name, mon_group_path)
528
529 mon_group.defineHistogram('centFrac', title=f'Centrality Fraction ({n_prong}); centFrac; Events', xbins=50, xmin=-0.05, xmax=1.2, opt='kAlwaysCreate')
530 mon_group.defineHistogram('etOverPtLeadTrk', title=f'etOverPtLeadTrk log ({n_prong}); etOverPtLeadTrk_log; Events', xbins=60, xmin=-3, xmax=3, opt='kAlwaysCreate')
531 mon_group.defineHistogram('dRmax', title=f'max dR of associated tracks ({n_prong}); dRmax; Events', xbins=50, xmin=-0.1, xmax=0.3, opt='kAlwaysCreate')
532 mon_group.defineHistogram('absipSigLeadTrk', title=f'AbsIpSigLeadTrk ({n_prong}); absipSigLeadTrk; Events', xbins=25, xmin=0.0, xmax=20.0, opt='kAlwaysCreate')
533 mon_group.defineHistogram('sumPtTrkFrac', title=f'SumPtTrkFrac ({n_prong}); SumPtTrkFrac; Events', xbins=50, xmin=-0.5, xmax=1.1, opt='kAlwaysCreate')
534 mon_group.defineHistogram('emPOverTrkSysP', title=f'EMPOverTrkSysP log ({n_prong}); EMPOverTrkSysP_log; Events', xbins=50, xmin=-5, xmax=3, opt='kAlwaysCreate')
535 mon_group.defineHistogram('ptRatioEflowApprox', title=f'ptRatioEflowApprox ({n_prong}); ptRatioEflowApprox; Events', xbins=50, xmin=0.0, xmax=2.0, opt='kAlwaysCreate')
536 mon_group.defineHistogram('mEflowApprox', title=f'mEflowApprox log ({n_prong}); mEflowApprox_log; Events', xbins=50, xmin=0, xmax=5, opt='kAlwaysCreate')
537 mon_group.defineHistogram('ptDetectorAxis', title=f'ptDetectorAxis log ({n_prong}); ptDetectorAxis_log; Events', xbins=50, xmin=0, xmax=5, opt='kAlwaysCreate')
538 if n_prong == 'MP' or n_prong == '3P':
539 mon_group.defineHistogram('massTrkSys', title=f'massTrkSys log ({n_prong}); massTrkSys_log; Events', xbins=50, xmin=0, xmax=3, opt='kAlwaysCreate')
540 mon_group.defineHistogram('trFlightPathSig', title=f'trFlightPathSig ({n_prong}); trFlightPathSig; Events', xbins=100, xmin=-20, xmax=40, opt='kAlwaysCreate')
541
542
543 def bookIDInputTrack(self, mon_alg, base_path, trigger, online):
544 type_str = 'HLT' if online else 'Offline'
545 mon_group_name = f'{trigger}_ID_{type_str}_InputTrack'
546 mon_group_path = f'{base_path}/TauIDVars/InputTrack/{trigger}/{type_str}'
547 mon_group = self.helper.addGroup(mon_alg, mon_group_name, mon_group_path)
548
549 mon_group.defineHistogram('n_track', title='Number of tracks; N_{track}; Events', xbins=15, xmin=0, xmax=15, opt='kAlwaysCreate')
550 mon_group.defineHistogram('track_pt_log', title='track_pt_log; track_pt_log; Events', xbins=20, xmin=2, xmax=7, opt='kAlwaysCreate')
551 mon_group.defineHistogram('track_pt_jetseed_log', title='track_pt_jetseed_log; track_pt_jetseed_log; Events', xbins=50, xmin=2, xmax=7, opt='kAlwaysCreate')
552 mon_group.defineHistogram('track_eta', title='Track #eta; #eta; Events', xbins=26, xmin=-2.6, xmax=2.6, opt='kAlwaysCreate')
553 mon_group.defineHistogram('track_phi', title='Track #phi; #phi; Events', xbins=16, xmin=-3.2, xmax=3.2, opt='kAlwaysCreate')
554 mon_group.defineHistogram('track_dEta', title='Track #Delta#eta; #Delta#eta; Events', xbins=100, xmin=-0.5, xmax=0.5, opt='kAlwaysCreate')
555 mon_group.defineHistogram('track_dPhi', title='Track #Delta#phi; #Delta#phi; Events', xbins=100, xmin=-0.5, xmax=0.5, opt='kAlwaysCreate')
556 mon_group.defineHistogram('track_d0_abs_log', title='track_d0_abs_log; track_d0_abs_log; Events', xbins=50, xmin=-7, xmax=2, opt='kAlwaysCreate')
557 mon_group.defineHistogram('track_z0sinthetaTJVA_abs_log', title='track_z0sinthetaTJVA_abs_log; track_z0sinthetaTJVA_abs_log; Events', xbins=50, xmin=-10, xmax=4, opt='kAlwaysCreate')
558 mon_group.defineHistogram('track_nIBLHitsAndExp', title='track_nIBLHitsAndExp; track_nIBLHitsAndExp; Events', xbins=3, xmin=0, xmax=3, opt='kAlwaysCreate')
559 mon_group.defineHistogram('track_nPixelHitsPlusDeadSensors', title='track_nPixelHitsPlusDeadSensors; track_nPixelHitsPlusDeadSensors; Events', xbins=11, xmin=0, xmax=11, opt='kAlwaysCreate')
560 mon_group.defineHistogram('track_nSCTHitsPlusDeadSensors', title='track_nSCTHitsPlusDeadSensors; track_nSCTHitsPlusDeadSensors; Events', xbins=20, xmin=0, xmax=20, opt='kAlwaysCreate')
561 mon_group.defineHistogram('track_eta,track_phi', type='TH2F', title='Track #eta vs #phi; #eta; #phi', xbins=26, xmin=-2.6, xmax=2.6, ybins=16, ymin=-3.2, ymax=3.2, opt='kAlwaysCreate')
562 mon_group.defineHistogram('track_dEta,track_dPhi', type='TH2F', title='Track #Delta#eta vs #Delta#phi; #Delta#eta; #Delta#phi', xbins=100, xmin=-0.5, xmax=0.5, ybins=100, ymin=-0.5, ymax=0.5, opt='kAlwaysCreate')
563
564
565 def bookIDInputCluster(self, mon_alg, base_path, trigger, online):
566 type_str = 'HLT' if online else 'Offline'
567 mon_group_name = f'{trigger}_ID_{type_str}_InputCluster'
568 mon_group_path = f'{base_path}/TauIDVars/InputCluster/{trigger}/{type_str}'
569 mon_group = self.helper.addGroup(mon_alg, mon_group_name, mon_group_path)
570
571 mon_group.defineHistogram('n_cluster', title='Number of clusters; N_{cluster}; Events', xbins=30, xmin=0, xmax=30, opt='kAlwaysCreate')
572 mon_group.defineHistogram('cluster_et_log', title='cluster_et_log; cluster_et_log; Events', xbins=30, xmin=0, xmax=6, opt='kAlwaysCreate')
573 mon_group.defineHistogram('cluster_pt_jetseed_log', title='cluster_pt_jetseed_log; cluster_pt_jetseed_log; Events', xbins=50, xmin=2, xmax=7, opt='kAlwaysCreate')
574 mon_group.defineHistogram('cluster_eta', title='Cluster #eta; #eta; Events', xbins=26, xmin=-2.6, xmax=2.6, opt='kAlwaysCreate')
575 mon_group.defineHistogram('cluster_phi', title='Cluster #phi; #phi; Events', xbins=16, xmin=-3.2, xmax=3.2, opt='kAlwaysCreate')
576 mon_group.defineHistogram('cluster_dEta', title='Cluster #Delta#eta; #Delta#eta; Events', xbins=100, xmin=-0.5, xmax=0.5, opt='kAlwaysCreate')
577 mon_group.defineHistogram('cluster_dPhi', title='Cluster #Delta#phi; #Delta#phi; Events', xbins=100, xmin=-0.5, xmax=0.5, opt='kAlwaysCreate')
578 mon_group.defineHistogram('cluster_SECOND_R_log10', title='cluster_SECOND_R_log10; cluster_SECOND_R_log10; Events', xbins=50, xmin=-3, xmax=7, opt='kAlwaysCreate')
579 mon_group.defineHistogram('cluster_SECOND_LAMBDA_log10', title='cluster_SECOND_LAMBDA_log10; cluster_SECOND_LAMBDA_log10; Events', xbins=50, xmin=-3, xmax=7, opt='kAlwaysCreate')
580 mon_group.defineHistogram('cluster_CENTER_LAMBDA_log10', title='cluster_CENTER_LAMBDA_log10; cluster_CENTER_LAMBDA_log10; Events', xbins=50, xmin=-2, xmax=5, opt='kAlwaysCreate')
581 mon_group.defineHistogram('cluster_eta,cluster_phi', type='TH2F', title='Cluster #eta vs #phi; #eta; #phi', xbins=26, xmin=-2.6, xmax=2.6, ybins=16, ymin=-3.2, ymax=3.2, opt='kAlwaysCreate')
582 mon_group.defineHistogram('cluster_dEta,cluster_dPhi', type='TH2F', title='Cluster #Delta#eta vs #Delta#phi; #Delta#eta; #Delta#phi', xbins=100, xmin=-0.5, xmax=0.5, ybins=100, ymin=-0.5, ymax=0.5, opt='kAlwaysCreate')
583
584
585 def bookIDScores(self, mon_alg, base_path, trigger, n_prong, online):
586 info = self.getTriggerInfo(trigger)
587 store_all = info.getHLTTauID() in ['idperf', 'perf']
588
589 if online:
590 if info.getHLTTauType() not in self.hlt_tauid_scores: return
591 variables = {
592 tau_id: p
593 for tau_id, p in self.hlt_tauid_scores[info.getHLTTauType()].items()
594 if tau_id == info.getHLTTauID() or store_all
595 }
596 else:
597 variables = self.offline_tauid_scores
598
599 type_str = 'HLT' if online else 'Offline'
600 mon_group_name = f'{trigger}_{type_str}_IDScores_{n_prong}'
601 mon_group_path = f'{base_path}/basicVars/{trigger}/{type_str}_{n_prong}'
602 mon_group = self.helper.addGroup(mon_alg, mon_group_name, mon_group_path)
603
604 for tau_id, (score, score_sig_trans) in variables.items():
605 if online and tau_id in ['RNN', 'DeepSet', 'RNNLLP', 'GNTau', 'GNTauDev1'] or not online and tau_id in ['RNN']: xbins, xmax = 20, 1
606 else: xbins, xmax = 100, 7
607
608 mon_group.defineHistogram(f'{tau_id}_TauIDScore', title=f'{type_str} {tau_id} TauID score; TauID score; Events', xbins=xbins, xmin=0, xmax=xmax, opt='kAlwaysCreate')
609 mon_group.defineHistogram(f'{tau_id}_TauIDScoreSigTrans', title=f'{type_str} {tau_id} TauID score sig. transformed; TauID score sig. transformed; Events', xbins=xbins, xmin=0, xmax=1, opt='kAlwaysCreate')
610
611
612 def bookBasicVars(self, mon_alg, base_path, trigger, n_prong, online):
613 type_str = 'HLT' if online else 'Offline'
614 mon_group_name = f'{trigger}_{type_str}_basicVars_{n_prong}'
615 mon_group_path = f'{base_path}/basicVars/{trigger}/{type_str}_{n_prong}'
616 mon_group = self.helper.addGroup(mon_alg, mon_group_name, mon_group_path)
617
618 binning = self.getCustomPtBinning(trigger, fine=True)
619
620 mon_group.defineHistogram('Pt', title=f'{type_str} p_{{T}}; p_{{T}} [GeV]; Events', xbins=binning, opt='kAlwaysCreate')
621 mon_group.defineHistogram('Eta', title=f'{type_str} #eta; #eta; Events', xbins=26, xmin=-2.6, xmax=2.6, opt='kAlwaysCreate')
622 mon_group.defineHistogram('Phi', title=f'{type_str} #phi; #phi; Events', xbins=16, xmin=-3.2, xmax=3.2, opt='kAlwaysCreate')
623 mon_group.defineHistogram('nTrack', title=f'{type_str} Number of tracks; N_{{track}}; Events', xbins=10, xmin=0, xmax=10, opt='kAlwaysCreate')
624 mon_group.defineHistogram('Eta,Phi', type='TH2F', title=f'{type_str} #eta vs #phi; #eta; #phi', xbins=26, xmin=-2.6, xmax=2.6, ybins=16, ymin=-3.2, ymax=3.2, opt='kAlwaysCreate')
625 mon_group.defineHistogram('Pt,Phi', type='TH2F', title=f'{type_str} p_{{T}} vs #phi; p_{{T}} [GeV]; #phi', xbins=binning, ybins=16, ymin=-3.2, ymax=3.2, opt='kAlwaysCreate')
626 mon_group.defineHistogram('Pt,Eta', type='TH2F', title=f'{type_str} p_{{T}} vs #eta; p_{{T}} [GeV]; #eta', xbins=binning, ybins=26, ymin=-2.6, ymax=2.6, opt='kAlwaysCreate')
627 mon_group.defineHistogram('nIsoTrack', title=f'{type_str} Number of isolation tracks; N_{{track}}^{{iso}}; Events', xbins=10, xmin=0, xmax=10, opt='kAlwaysCreate')
628 mon_group.defineHistogram('averageMu', title=f'{type_str} Average #mu; #LT#mu$GT; Events', xbins=20, xmin=0, xmax=80, opt='kAlwaysCreate')
629 mon_group.defineHistogram('TauVertexX', title=f'{type_str} Tau Vertex X; x [mm]; Events', xbins=100, xmin=-1, xmax=1, opt='kAlwaysCreate')
630 mon_group.defineHistogram('TauVertexY', title=f'{type_str} Tau Vertex Y; y [mm]; Events', xbins=100, xmin=-2, xmax=0, opt='kAlwaysCreate')
631 mon_group.defineHistogram('TauVertexZ', title=f'{type_str} Tau Vertex Z; z [mm]; Events', xbins=120, xmin=-120, xmax=120, opt='kAlwaysCreate')
632
633
634 def bookDiTauHLTEffHistograms(self, mon_alg, base_path, trigger):
635 mon_group_name = f'{trigger}_DiTauHLT_Efficiency'
636 mon_group_path = f'{base_path}/DiTauHLT_Efficiency/{trigger}/DiTauHLT_Efficiency'
637 mon_group = self.helper.addGroup(mon_alg, mon_group_name, mon_group_path)
638
639 def defineEachStepHistograms(xvariable, xlabel, xbins, xmin, xmax, eff='HLT', high_pt=False):
640 pass_flag = f'{eff}_pass'
641 sfx = ''
642
643 if high_pt:
644 pass_flag += '_highPt'
645 sfx += '_highPt'
646 xlabel += ' (p_{T}^{1,2} > p_{T}^{thr 1,2} + 20 GeV)'
647
648 mon_group.defineHistogram(f'{pass_flag},{xvariable};EffDiTau{eff}_{xvariable}{sfx}_wrt_Offline',
649 title=f'DiTau {eff} Efficiency {trigger};{xlabel};Efficiency',
650 type='TEfficiency', xbins=xbins, xmin=xmin, xmax=xmax, opt='kAlwaysCreate')
651
652 eff_list = ['HLT'] + (['Total'] if self.do_total_efficiency else [])
653 for eff in eff_list:
654 defineEachStepHistograms('dR', '#Delta R(#tau,#tau)', 20, 0, 4, eff)
655 defineEachStepHistograms('dEta', '#Delta#eta(#tau,#tau)', 20, 0, 4, eff)
656 defineEachStepHistograms('dPhi', '#Delta#phi(#tau,#tau)', 8, -3.2, 3.2, eff)
657
658 defineEachStepHistograms('dR', '#Delta R(#tau,#tau)', 20, 0, 4, eff, high_pt=True)
659 defineEachStepHistograms('dEta', '#Delta#eta(#tau,#tau)', 20, 0, 4, eff, high_pt=True)
660 defineEachStepHistograms('dPhi', '#Delta#phi(#tau,#tau)', 8, -3.2, 3.2, eff, high_pt=True)
661 defineEachStepHistograms('averageMu', '#LT#mu#GT', 10, 0, 80, eff)
662
663 # Save quantities in TTree for offline analysis
664 mon_group.defineTree('dR,dEta,dPhi,averageMu,HLT_pass;DiTauHLTEffTree',
665 treedef='dR/F:dEta/F:dPhi/F:averageMu/F:HLT_pass/I')
666
667
668 def bookDiTauVars(self, mon_alg, base_path, trigger):
669 mon_group_name = f'{trigger}_DiTauVars'
670 mon_group_path = f'{base_path}/DiTauVars/{trigger}'
671 mon_group = self.helper.addGroup(mon_alg, mon_group_name, mon_group_path)
672
673 mon_group.defineHistogram('leadHLTEt,subleadHLTEt', type='TH2F', title='p_{T}^{lead} vs p_{T}^{sublead}; p_{T}^{lead} [GeV]; p_{T}^{sublead} [GeV]',
674 xbins=50, xmin=0, xmax=250, ybins=50, ymin=0, ymax=250, opt='kAlwaysCreate')
675 mon_group.defineHistogram('leadHLTEta,subleadHLTEta', type='TH2F', title='#eta_{lead} vs #eta_{sublead}; #eta_{lead}; #eta_{sublead}',
676 xbins=26, xmin=-2.6, xmax=2.6, ybins=26, ymin=-2.6, ymax=2.6, opt='kAlwaysCreate')
677 mon_group.defineHistogram('leadHLTPhi,subleadHLTPhi', type='TH2F', title='#phi_{lead} vs #phi_{sublead}; #phi_{lead}; #phi_{sublead}',
678 xbins=16, xmin=-3.2, xmax=3.2, ybins=16, ymin=-3.2, ymax=3.2, opt='kAlwaysCreate')
679 mon_group.defineHistogram('dR', title='#Delta R(#tau,#tau); #Delta R(#tau,#tau); Events', xbins=40, xmin=0, xmax=4, opt='kAlwaysCreate')
680 mon_group.defineHistogram('dEta', title='#Delta#eta(#tau,#tau); #Delta#eta(#tau,#tau); Events', xbins=40, xmin=0, xmax=4, opt='kAlwaysCreate')
681 mon_group.defineHistogram('dPhi', title='#Delta#phi(#tau,#tau); #Delta#phi(#tau,#tau); Events', xbins=16, xmin=-3.2, xmax=3.2, opt='kAlwaysCreate')
682
683 mon_group.defineHistogram('Pt', title='p_{T}(#tau,#tau); p_{T} [GeV]; Events', xbins=50, xmin=0, xmax=250, opt='kAlwaysCreate')
684 mon_group.defineHistogram('Eta', title='#eta(#tau,#tau); #eta(#tau,#tau); Events', xbins=26, xmin=-2.6, xmax=2.6, opt='kAlwaysCreate')
685 mon_group.defineHistogram('Phi', title='#phi(#tau,#tau); #phi(#tau,#tau); Events', xbins=16, xmin=-3.2, xmax=3.2, opt='kAlwaysCreate')
686 mon_group.defineHistogram('M', title='m(#tau,#tau); m_{#tau,#tau}; Events', xbins=50, xmin=0, xmax=250, opt='kAlwaysCreate')
687 mon_group.defineHistogram('dPt', title='#Delta p_{T}(#tau, #tau); p_{T} [GeV]; Events', xbins=20, xmin=0, xmax=200, opt='kAlwaysCreate')
688
689 mon_group.defineTree('leadHLTEt,subleadHLTEt,leadHLTEta,subleadHLTEta,leadHLTPhi,subleadHLTPhi,dR,dEta,dPhi,Pt,Eta,Phi,M,dPt;DiTauVarsTree',
690 treedef='leadHLTEt/F:subleadHLTEt/F:leadHLTEta/F:subleadHLTEta/F:leadHLTPhi/F:subleadHLTPhi/F:dR/F:dEta/F:dPhi/F:Pt/F:Eta/F:Phi/F:M/F:dPt/F')
691
692# def bookBoostedDiTauHLTEffHistograms(self, mon_alg, base_path, trigger):
693 # mon_group_name = f'{trigger}_BoostedDiTauHLT_Efficiency'
694 # mon_group_path = f'{base_path}/BoostedDiTauHLT_Efficiency/{trigger}
695 # mon_group = self.helper.addGroup(mon_alg, mon_group_name, mon_group_path)
696
697
698 def bookBoostedDiTauVars(self, mon_alg, base_path, trigger):
699 mon_group_name = f'{trigger}_BoostedDiTauVars'
700 mon_group_path = f'{base_path}/BoostedDiTauVars/{trigger}'
701 mon_group = self.helper.addGroup(mon_alg, mon_group_name, mon_group_path)
702
703 mon_group.defineHistogram('omni_score', title='omni_score; omni_score; Events', xbins=50, xmin=0, xmax=1, opt='kAlwaysCreate')
704 mon_group.defineHistogram('R_tracks_lead', title='R_tracks_lead; R_tracks_lead; Events', xbins=50, xmin=0, xmax=0.2, opt='kAlwaysCreate')
705 mon_group.defineHistogram('R_tracks_subl', title='R_tracks_subl; R_tracks_subl; Events', xbins=50, xmin=0, xmax=0.2, opt='kAlwaysCreate')
706 mon_group.defineHistogram('f_core_lead', title='f_core_lead; f_core_lead; Events', xbins=50, xmin=0, xmax=1, opt='kAlwaysCreate')
707 mon_group.defineHistogram('f_core_subl', title='f_core_subl; f_core_subl; Events', xbins=50, xmin=0, xmax=1, opt='kAlwaysCreate')
708 mon_group.defineHistogram('n_track', title='Number of tracks; n_tracks; Events', xbins=51, xmin=-0.5, xmax=50.5, opt='kAlwaysCreate')
709 mon_group.defineHistogram('n_tracks_lead', title='Number of Lead tracks; n_tracks_lead; Events', xbins=11, xmin=-0.5, xmax=10.5, opt='kAlwaysCreate')
710 mon_group.defineHistogram('n_tracks_subl', title='Number of Sub-Lead tracks; n_tracks_subl; Events', xbins=11, xmin=-0.5, xmax=10.5, opt='kAlwaysCreate')
711 mon_group.defineHistogram('Pt', title='p_{T}(#tau,#tau); p_{T} [GeV]; Events', xbins=50, xmin=160, xmax=1300, opt='kAlwaysCreate')
712 mon_group.defineHistogram('Eta', title='#eta(#tau,#tau); #eta(#tau,#tau); Events', xbins=26, xmin=-2.6, xmax=2.6, opt='kAlwaysCreate')
713 mon_group.defineHistogram('Phi', title='#phi(#tau,#tau); #phi(#tau,#tau); Events', xbins=16, xmin=-3.2, xmax=3.2, opt='kAlwaysCreate')
714 mon_group.defineHistogram('M', title='m(#tau,#tau); m_{#tau,#tau}; Events', xbins=50, xmin=0, xmax=250, opt='kAlwaysCreate')
715
716 def bookTAndPHLTEffHistograms(self, mon_alg, base_path, trigger):
717 mon_group_name = f'{trigger}_TAndPHLT_Efficiency'
718 mon_group_path = f'{base_path}/TAndPHLT_Efficiency/{trigger}/TAndPHLT_Efficiency'
719 mon_group = self.helper.addGroup(mon_alg, mon_group_name, mon_group_path)
720
721 def defineEachStepHistograms(xvariable, xlabel, xbins, xmin, xmax, high_pt=False, coarse=False):
722 pass_flag = 'HLT_pass'
723 sfx = ''
724
725 if high_pt:
726 pass_flag += '_highPt'
727 sfx += '_highPt'
728 xlabel += ' (p_{T}^{#tau} > p_{T}^{#tau thr} + 20 GeV)'
729 elif coarse:
730 sfx += '_coarse'
731
732 mon_group.defineHistogram(f'{pass_flag},{xvariable};EffTAndPHLT_{xvariable}{sfx}_wrt_Offline',
733 title=f'TAndP HLT Efficiency {trigger}; {xlabel}; Efficiency',
734 type='TEfficiency', xbins=xbins, xmin=xmin, xmax=xmax, opt='kAlwaysCreate')
735
736 coarse_binning = self.getCustomPtBinning(trigger)
737
738 defineEachStepHistograms('tauPt', 'p_{T}^{#tau} [GeV]', 60, 0.0, 300)
739 defineEachStepHistograms('tauPt', 'p_{T}^{#tau} [GeV]', coarse_binning, coarse_binning[0], coarse_binning[-1], coarse=True)
740 defineEachStepHistograms('tauEta', '#eta_{#tau}', 13, -2.6, 2.6)
741 defineEachStepHistograms('tauPhi', '#phi_{#tau}', 16, -3.2, 3.2)
742 defineEachStepHistograms('tauEta', '#eta_{#tau}', 13, -2.6, 2.6, high_pt=True)
743 defineEachStepHistograms('tauPhi', '#phi_{#tau}', 16, -3.2, 3.2, high_pt=True)
744 defineEachStepHistograms('dR', '#Delta R(#tau,lep)', 20, 0, 4)
745 defineEachStepHistograms('dEta', '#Delta#eta(#tau,lep)', 20, 0,4)
746 defineEachStepHistograms('dPhi', '#Delta#phi(#tau,lep)', 8, -3.2, 3.2)
747 defineEachStepHistograms('averageMu', '#LT#mu#GT', 10, 0, 80)
748
749 # Save quantities in TTree for offline analysis
750 mon_group.defineTree('tauPt,tauEta,tauPhi,dR,dEta,dPhi,averageMu,HLT_pass;TAndPHLTEffTree',
751 treedef='tauPt/F:tauEta/F:tauPhi/F:dR/F:dEta/F:dPhi/F:averageMu/F:HLT_pass/I')
752
753
754 def bookTAndPVars(self, mon_alg, base_path, trigger):
755 mon_group_name = f'{trigger}_TAndPVars'
756 mon_group_path = f'{base_path}/TAndPVars/{trigger}'
757 mon_group = self.helper.addGroup(mon_alg, mon_group_name, mon_group_path)
758
759 mon_group.defineHistogram('dR', title='#Delta R(#tau,lep); #Delta R(#tau,lep); Events', xbins=40, xmin=0, xmax=4, opt='kAlwaysCreate')
760 mon_group.defineHistogram('dEta', title='#Delta#eta(#tau,lep); #Delta#eta(#tau,lep); Events', xbins=40, xmin=0, xmax=4, opt='kAlwaysCreate')
761 mon_group.defineHistogram('dPhi', title='#Delta#phi(#tau,lep); #Delta#phi(#tau,lep); Events', xbins=16, xmin=-3.2, xmax=3.2, opt='kAlwaysCreate')
762
763 mon_group.defineHistogram('Pt', title='p_{T}(#tau,lep); p_{T} [GeV]; Events', xbins=50, xmin=0, xmax=250, opt='kAlwaysCreate')
764 mon_group.defineHistogram('Eta', title='#eta(#tau,lep); #eta; Events', xbins=26, xmin=-2.6, xmax=2.6, opt='kAlwaysCreate')
765 mon_group.defineHistogram('Phi', title='#phi(#tau,lep); #phi; Events', xbins=16, xmin=-3.2, xmax=3.2, opt='kAlwaysCreate')
766 mon_group.defineHistogram('M', title='m(#tau,lep); m_{#tau,lep}; Events', xbins=50, xmin=0, xmax=250, opt='kAlwaysCreate')
767 mon_group.defineHistogram('dPt', title='#Delta p_{T}(#tau,lep); p_{T} [GeV]; Events', xbins=20, xmin=0, xmax=200, opt='kAlwaysCreate')
768
769
770 def bookTruthEfficiency(self, mon_alg, base_path, trigger, n_prong):
771 mon_group_name = f'{trigger}_Truth_Efficiency_{n_prong}'
772 mon_group_path = f'{base_path}/Truth_Efficiency/{trigger}/Truth_Efficiency_{n_prong}'
773 mon_group = self.helper.addGroup(mon_alg, mon_group_name, mon_group_path)
774
775 info = self.getTriggerInfo(trigger)
776
777 def defineEachStepHistograms(xvariable, xlabel, xbins, xmin, xmax, high_pt=False, coarse=False):
778 pass_flag = 'HLT_pass'
779 sfx = ''
780
781 if high_pt:
782 pass_flag += '_highPt'
783 sfx += '_highPt'
784 if info.isHLTDiTau():
785 xlabel += ' (p_{T}^{#tau} > p_{T}^{#tau min thr} + 20 GeV)'
786 else:
787 xlabel += ' (p_{T}^{#tau} > p_{T}^{#tau thr} + 20 GeV)'
788 elif coarse:
789 sfx += '_coarse'
790
791 mon_group.defineHistogram(f'{pass_flag},{xvariable};EffHLT_{xvariable}{sfx}_wrt_Truth',
792 title=f'HLT Efficiency {trigger} {n_prong}; {xlabel}; Efficiency',
793 type='TEfficiency', xbins=xbins, xmin=xmin, xmax=xmax)
794
795 coarse_binning = self.getCustomPtBinning(trigger)
796
797 defineEachStepHistograms('pt_vis', 'p_{T, vis} [GeV]', 60, 0.0, 300)
798 if info.isHLTSingleTau() or info.isHLTTandP(): defineEachStepHistograms('pt_vis', 'p_{T, vis} [GeV]', coarse_binning, coarse_binning[0], coarse_binning[-1], coarse=True)
799 defineEachStepHistograms('eta_vis', '#eta_{vis}', 13, -2.6, 2.6)
800 defineEachStepHistograms('phi_vis', '#phi_{vis}', 16, -3.2, 3.2)
801 defineEachStepHistograms('eta_vis', '#eta_{vis}', 13, -2.6, 2.6, high_pt=True)
802 defineEachStepHistograms('phi_vis', '#phi_{vis}', 16, -3.2, 3.2, high_pt=True)
803
804
805 def bookTruthVars(self, mon_alg, base_path, trigger, n_prong):
806 mon_group_name = f'{trigger}_TruthVars_{n_prong}'
807 mon_group_path = f'{base_path}/TruthVars/{trigger}/TruthVars_{n_prong}'
808 mon_group = self.helper.addGroup(mon_alg, mon_group_name, mon_group_path)
809
810 mon_group.defineHistogram('pt_vis,PtRatio', title='p_{T} ratio vs p_{T, vis}; p_{T, vis} [GeV]; (p_{T}^{reco} - p_{T, vis}^{truth})/p_{T, vis}^{truth}', type='TProfile', xbins=21, xmin=20, xmax=250)
811 mon_group.defineHistogram('eta_vis,PtRatio', title='p_{T} ratio vs #eta_{vis}; #eta_{vis}; (p_{T}^{reco} - p_{T, vis}^{truth})/p_{T, vis}^{truth}', type='TProfile', xbins=21, xmin=-3, xmax=3)
812 mon_group.defineHistogram('phi_vis,PtRatio', title='p_{T} ratio vs #phi_{vis}; #phi_{vis}; (p_{T}^{reco} - p_{T, vis}^{truth})/p_{T, vis}^{truth}', type='TProfile', xbins=21, xmin=-3, xmax=3)
813
814 mon_group.defineHistogram('pt_vis', title='p_{T, vis}; p_{T, vis}; Events', xbins=50, xmin=0, xmax=250)
815 mon_group.defineHistogram('eta_vis', title='#eta_{vis}; #eta_{vis}; Events', xbins=26, xmin=-2.6, xmax=2.6)
816 mon_group.defineHistogram('phi_vis', title='#phi_{vis}; #phi_{vis}; Events', xbins=16, xmin=-3.2, xmax=3.2)
817
818
819 def bookL1EffHistograms(self, mon_alg, base_path, trigger, n_prong):
820 mon_group_name = f'{trigger}_L1_Efficiency_{n_prong}'
821 mon_group_path = f'{base_path}/L1_Efficiency/{trigger}/L1_Efficiency_{n_prong}'
822 mon_group = self.helper.addGroup(mon_alg, mon_group_name, mon_group_path)
823
824 def defineEachStepHistograms(xvariable, xlabel, xbins, xmin, xmax, high_pt=False, coarse=False):
825 pass_flag = 'L1_pass'
826 sfx = ''
827
828 if high_pt:
829 pass_flag += '_highPt'
830 sfx += '_highPt'
831 xlabel += ' (p_{T}^{#tau} > p_{T}^{#tau thr} + 20 GeV)'
832 elif coarse:
833 sfx += '_coarse'
834
835 mon_group.defineHistogram(f'{pass_flag},{xvariable};EffL1_{xvariable}{sfx}_wrt_Offline',
836 title=f'L1 Efficiency {trigger} {n_prong}; {xlabel}; Efficiency',
837 type='TEfficiency', xbins=xbins, xmin=xmin, xmax=xmax, opt='kAlwaysCreate')
838
839 coarse_binning = self.getCustomPtBinning(trigger)
840
841 defineEachStepHistograms('tauPt', 'p_{T} [GeV]', 60, 0, 300)
842 defineEachStepHistograms('tauPt', 'p_{T} [GeV]', coarse_binning, coarse_binning[0], coarse_binning[-1], coarse=True)
843 defineEachStepHistograms('tauEta', '#eta', 13, -2.6, 2.6)
844 defineEachStepHistograms('tauPhi', '#phi', 16, -3.2, 3.2)
845 defineEachStepHistograms('tauEta', '#eta', 13, -2.6, 2.6, high_pt=True)
846 defineEachStepHistograms('tauPhi', '#phi', 16, -3.2, 3.2, high_pt=True)
847 defineEachStepHistograms('averageMu', '#LT#mu#GT', 10, 0, 80)
848
849
850 def bookL1Vars(self, mon_alg, base_path, trigger):
851 mon_group_name = f'{trigger}_L1Vars'
852 mon_group_path = f'{base_path}/L1Vars/{trigger}'
853 mon_group = self.helper.addGroup(mon_alg, mon_group_name, mon_group_path)
854
855 mon_group.defineHistogram('L1RoIEt,L1RoIEta', type='TH2F', title='L1 RoI E_{T} vs #eta; E_{T} [GeV]; #eta',
856 xbins=60, xmin=0, xmax=300,
857 ybins=60, ymin=-2.6, ymax=2.6, opt='kAlwaysCreate')
858 mon_group.defineHistogram('L1RoIEt,L1RoIPhi', type='TH2F', title='L1 RoI E_{T} vs #phi; E_{T} [GeV]; #phi',
859 xbins=60, xmin=0, xmax=300,
860 ybins=60, ymin=-3.2, ymax=3.2, opt='kAlwaysCreate')
861 mon_group.defineHistogram('L1RoIEta,L1RoIPhi', type='TH2F', title='L1 RoI #eta vs #phi; #eta; #phi',
862 xbins=60, xmin=-2.6, xmax=2.6,
863 ybins=60, ymin=-3.2, ymax=3.2, opt='kAlwaysCreate')
864 mon_group.defineHistogram('L1RoIEta', title='L1 RoI #eta; #eta; RoIs', xbins=60, xmin=-2.6, xmax=2.6, opt='kAlwaysCreate')
865 mon_group.defineHistogram('L1RoIPhi', title='L1 RoI #phi; #phi; RoIs', xbins=60, xmin=-3.2, xmax=3.2, opt='kAlwaysCreate')
866 mon_group.defineHistogram('L1RoIEt', title='L1 RoI E_{T}; E_{T} [GeV]; RoIs', xbins=60, xmin=0, xmax=300, opt='kAlwaysCreate')
867
868 if 'eTAU' in trigger:
869 mon_group.defineHistogram('L1eFexRoIRCore', title='L1 eTAU RoI rCore Isolation; rCore Isolation; RoIs', xbins=250, xmin=0, xmax=1, opt='kAlwaysCreate')
870 mon_group.defineHistogram('L1eFexRoIRHad' , title='L1 eTAU RoI rHad Isolation; rHad Isolation; RoIs', xbins=250, xmin=0, xmax=1, opt='kAlwaysCreate')
871 mon_group.defineHistogram('L1eFexRoIBDTScore' , title='L1 eTAU RoI BDT score; BDT Score; RoIs', xbins=128, xmin=512, xmax=1024, opt='kAlwaysCreate')
872
873 elif 'cTAU' in trigger:
874 mon_group.defineHistogram('L1eFexRoIRCore', title='L1 eTAU RoI rCore Isolation; eTAU rCore Isolation; RoIs', xbins=250, xmin=0, xmax=1, opt='kAlwaysCreate')
875 mon_group.defineHistogram('L1eFexRoIRHad', title='L1 eTAU RoI rHad Isolation; eTAU rHad Isolation; RoIs', xbins=250, xmin=0, xmax=1, opt='kAlwaysCreate')
876 mon_group.defineHistogram('L1cTauRoITopoMatch', title='L1Topo match between eTAU and jTAU RoI; Match; RoIs', xbins=2, xmin=0, xmax=2, opt='kAlwaysCreate')
877 mon_group.defineHistogram('L1jFexRoIIso', title='L1 jTAU RoI Isolation; E_{T}^{jTAU Iso} [GeV]; RoIs', xbins=25, xmin=0, xmax=50, opt='kAlwaysCreate')
878 mon_group.defineHistogram('L1cTauMatchedRoIIso', title='L1 cTAU Isolation score; E_{T}^{jTAU Iso}/E_{T}^{eTAU}; RoIs', xbins=50, xmin=0, xmax=5, opt='kAlwaysCreate')
879 mon_group.defineHistogram('L1RoIcTauMatchedEtRatio', title='Et ratio between matched eTAU and jTAU RoIs; E_{T}^{jTAU}/E_{T}^{eTAU}; RoIs', xbins=40, xmin=0, xmax=4, opt='kAlwaysCreate')
880 mon_group.defineHistogram('L1eFexRoIBDTScore' , title='L1 eTAU RoI BDT score; BDT Score; RoIs', xbins=128, xmin=512, xmax=1024, opt='kAlwaysCreate')
881
882 elif 'jTAU' in trigger:
883 mon_group.defineHistogram('L1jFexRoIIso', title='L1 jTAU RoI Isolation; jTAU Isolation [GeV]; N RoI', xbins=25, xmin=0, xmax=50, opt='kAlwaysCreate')
884
885 def getCustomPtBinning(self, trigger, fine=False):
886 info = self.getTriggerInfo(trigger)
887
888 def getList(ranges, others=[250]):
889 ret = set(others + [500]) # The upper end of the x-axis will always be 500
890 for jump, interval in ranges.items():
891 ret.update(range(interval[0], interval[1], jump), interval)
892 return sorted(list(ret))
893
894 if info.isL1TauOnly():
895 thr = info.getL1TauThreshold()
896
897 if thr <= 8: return getList({5:(0, 30), 50:(50, 150)})
898 elif thr <= 12: return getList({5:(0, 30), 50:(50, 150)})
899 elif thr <= 20: return getList({5:(5, 40), 10:(40, 70), 50:(100, 150)})
900 elif thr <= 30: return getList({5:(15, 50), 10:(50, 70), 50:(100, 150)})
901 elif thr <= 35: return getList({5:(20, 55), 10:(60, 80), 50:(100, 150)})
902 elif thr <= 40: return getList({5:(25, 60), 10:(60, 80), 50:(100, 150)})
903 elif thr <= 60: return getList({5:(45, 80), 10:(80, 100), 50:(100, 150)})
904 elif thr <= 100: return getList({5:(85, 120), 10:(120, 140), 20:(140, 180), 50:(200, 250)})
905 else: return getList({50:(0, 200)})
906
907 else: # HLT triggers
908 thr = info.getHLTTauThreshold()
909
910 if fine:
911 if thr == 0: return getList({5:(0, 80), 10:(80, 120), 20:(120, 160), 40:(160, 240), 60:(240, 420)}, [])
912 elif thr <= 20: return getList({5:(15, 80), 10:(80, 120), 20:(120, 160), 40:(160, 240), 60:(240, 420)}, [])
913 elif thr <= 25: return getList({5:(20, 80), 10:(80, 120), 20:(120, 160), 40:(160, 240), 60:(240, 420)}, [])
914 elif thr <= 30: return getList({5:(25, 80), 10:(80, 120), 20:(120, 160), 40:(160, 240), 60:(240, 420)}, [])
915 elif thr <= 35: return getList({5:(30, 80), 10:(80, 120), 20:(120, 160), 40:(160, 240), 60:(240, 420)}, [])
916 elif thr <= 60: return getList({5:(55, 80), 10:(80, 120), 20:(120, 160), 40:(160, 240), 60:(240, 420)}, [])
917 elif thr <= 80: return getList({5:(75, 80), 10:(80, 120), 20:(120, 160), 40:(160, 240), 60:(240, 420)}, [])
918 elif thr <= 160: return getList({5:(155, 160), 40:(160, 240), 60:(240, 420)}, [])
919 elif thr <= 180: return getList({5:(175, 180), 40:(180, 260), 60:(260, 380)}, [])
920 else: return getList({5:(195, 200), 40:(200, 240), 60:(240, 420)}, [])
921
922 else:
923 if thr == 0:
924 if info.getL1TauItems(): return self.getCustomPtBinning(f'L1{info.getL1TauItem()}')
925 else: return getList({5:(0, 30), 50:(50, 150)})
926 elif thr <= 20: return getList({5:(10, 40), 10:(40, 60), 20:(60, 80)}, [150, 250])
927 elif thr <= 25: return getList({5:(15, 40), 10:(40, 60), 20:(60, 80)}, [150, 250])
928 elif thr <= 30: return getList({5:(20, 50), 10:(50, 60), 20:(60, 80)}, [150, 250])
929 elif thr <= 35: return getList({5:(25, 50), 10:(50, 60), 20:(60, 80)}, [150, 250])
930 elif thr <= 60: return getList({5:(50, 70), 10:(70, 80)}, [110, 150, 250])
931 elif thr <= 80: return getList({5:(70, 90)}, [110, 150, 250])
932 elif thr <= 160: return getList({5:(150, 170), 10:(170, 180), 20:(180, 200)}, [240, 300])
933 elif thr <= 180: return getList({5:(170, 180), 10:(180, 200)}, [240, 300])
934 else: return getList({5:(190, 200), 10:(200, 210)}, [240, 300])
const bool debug
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
STL class.
bookIDInputScalar(self, mon_alg, base_path, trigger, n_prong, online)
getTriggerInfo(self, str trigger, use_thresholds=True)
bookBasicVars(self, mon_alg, base_path, trigger, n_prong, online)
bookTruthEfficiency(self, mon_alg, base_path, trigger, n_prong)
bookIDInputTrack(self, mon_alg, base_path, trigger, online)
bookIDInputCluster(self, mon_alg, base_path, trigger, online)
bookIDScores(self, mon_alg, base_path, trigger, n_prong, online)
bookTruthVars(self, mon_alg, base_path, trigger, n_prong)
bookL1EffHistograms(self, mon_alg, base_path, trigger, n_prong)
bookHLTEffHistograms(self, mon_alg, base_path, trigger, n_prong)
STL class.