Loading [MathJax]/extensions/tex2jax.js
ATLAS Offline Software
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
JetEfficiencyMonitorAlgorithm.py
Go to the documentation of this file.
1 #
2 # Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 #
5  '''Function to configure LVL1 JetEfficiency algorithm in the monitoring system.'''
6 
7  # get the component factory - used for getting the algorithms
8  from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
9  from AthenaConfiguration.ComponentFactory import CompFactory
10  from TrigConfigSvc.TriggerConfigAccess import getL1MenuAccess
11  result = ComponentAccumulator()
12  l1menu = getL1MenuAccess(flags)
13 
14 
15  from AthenaConfiguration.Enums import Format
16 
18  if flags.Input.Format is Format.POOL and not flags.Input.isMC and not any(["AOD" in a for a in flags.Input.ProcessingTags]):
19  from JetRecConfig.JetRecConfig import JetRecCfg
20  from JetRecConfig.StandardSmallRJets import AntiKt4EMPFlow
21  result.merge( JetRecCfg(flags,AntiKt4EMPFlow) )
22 
23  from eflowRec.PFCfg import PFGlobalFlowElementLinkingCfg
24  if flags.DQ.Environment == "AOD":
25  result.merge(PFGlobalFlowElementLinkingCfg(flags, useMuonTopoClusters=True))
26  else:
27  result.merge(PFGlobalFlowElementLinkingCfg(flags))
28  from eflowRec.PFCfg import PFGlobalFlowElementLinkingCfg
29  result.merge(PFGlobalFlowElementLinkingCfg(flags))
30  from METReconstruction.METAssociatorCfg import METAssociatorCfg
31  result.merge(METAssociatorCfg(flags, 'AntiKt4EMPFlow'))
32  from METUtilities.METMakerConfig import getMETMakerAlg
33  metCA=ComponentAccumulator()
34  metCA.addEventAlgo(getMETMakerAlg('AntiKt4EMPFlow'))
35  result.merge(metCA)
36 
37 
38  # make the athena monitoring helper
39  from TrigT1CaloMonitoring.LVL1CaloMonitoringConfig import L1CaloMonitorCfgHelper
40  helper = L1CaloMonitorCfgHelper(flags,CompFactory.JetEfficiencyMonitorAlgorithm,'JetEfficiencyMonAlg')
41  groupName = 'JetEfficiencyMonitor' # the monitoring group name is also used for the package name
42  JetEfficiencyMonAlg = helper.alg
43  JetEfficiencyMonAlg.PackageName = groupName
44 
45 
46 
50 
51  # We can choose if we want to use pass before prescale, or not when defining our trigger efficiency
52  # generally only want to use pass before prescale when considering the efficiency of a trigger for
53  # internal evaluation of how triggers are behaving
54  # the prescaling is an important feature of real utility if a
55  passedb4Prescale = True
56  JetEfficiencyMonAlg.PassedBeforePrescale = passedb4Prescale
57 
58 
62 
63  #define the various reference triggers
64  hltRandom_reference_triggers = ['HLT_j0_perf_L1RD0_FILLED', 'HLT_j0_perf_pf_ftf_L1RD0_FILLED']
65  JetEfficiencyMonAlg.HLTRandomReferenceTriggers = hltRandom_reference_triggers
66 
67  muon_reference_triggers = ["L1_MU14FCH", "L1_MU18VFCH", "L1_MU8F_TAU20IM", "L1_2MU8F", "L1_MU8VF_2MU5VF", "L1_3MU3VF", "L1_MU5VF_3MU3VF", "L1_4MU3V", "L1_2MU5VF_3MU3V", "L1_RD0_FILLED"]
68  JetEfficiencyMonAlg.MuonReferenceTriggers = muon_reference_triggers
69 
70  JetEfficiencyMonAlg.BootstrapReferenceTrigger='L1_J15'
71 
72  trigPath = 'Developer/JetEfficiency/'
73  ExpertTrigPath = 'Expert/Efficiency/'
74  distributionPath = 'Distributions/'
75  noRefPath = 'NoReferenceTrigger/'
76  muonRefPath = 'MuonReferenceTrigger/'
77  randomRefPath = 'RandomHLTReferenceTrigger/'
78  bsRefPath = 'BootstrapReferenceTrigger/'
79  GeV = 1000
80 
81  # add monitoring algorithm to group, with group name and main directory
82  single_triggers = []
83  LR_triggers = []
84 
85  gfex_SR_triggers = ['L1_gJ20p0ETA25', 'L1_gJ50p0ETA25', 'L1_gJ100p0ETA25', 'L1_gJ400p0ETA25']
86  gfex_LR_triggers = ['L1_gLJ80p0ETA25', 'L1_gLJ100p0ETA25', 'L1_gLJ140p0ETA25', 'L1_gLJ160p0ETA25']
87 
88  jfex_SR_triggers = ['L1_jJ30','L1_jJ40','L1_jJ50', 'L1_jJ60', 'L1_jJ80','L1_jJ90', 'L1_jJ125','L1_jJ140','L1_jJ160', 'L1_jJ180']
89  jfex_LR_triggers = ['L1_SC111-CjJ40']
90 
91 
92  all_SR_singletriggers = single_triggers + gfex_SR_triggers + jfex_SR_triggers
93  all_LR_singletriggers = LR_triggers + gfex_LR_triggers + jfex_LR_triggers
94 
95  # if the trigger isnt included in the menu, then we dont actually want to fill anything into the histograms (it looks weird)
96  JetEfficiencyMonAlg.SmallRadiusJetTriggers_phase1 = [trigger for trigger in all_SR_singletriggers if trigger in l1menu]
97  JetEfficiencyMonAlg.LargeRadiusJetTriggers_phase1 = [trigger for trigger in all_LR_singletriggers if trigger in l1menu]
98  # if a trigger isnt in the menu, but its a gfex trigger so we can emulate the efficiemcy using the gFEX TOBs
99  JetEfficiencyMonAlg.SmallRadiusJetTriggers_gFEX = [trigger for trigger in gfex_SR_triggers if trigger not in l1menu]
100  JetEfficiencyMonAlg.LargeRadiusJetTriggers_gFEX = [trigger for trigger in gfex_LR_triggers if trigger not in l1menu]
101 
102  # if there are no gFEX triggers in our list that aren't present in the menu, then we don't need to even look at them, so lets just not open them
103  if len(JetEfficiencyMonAlg.SmallRadiusJetTriggers_gFEX ) == 0: JetEfficiencyMonAlg.mygFexSRJetRoIContainer = ""
104  if len(JetEfficiencyMonAlg.LargeRadiusJetTriggers_gFEX ) == 0: JetEfficiencyMonAlg.mygFexLRJetRoIContainer = ""
105 
106 
107  reference_paths = {"Muon" : muonRefPath, "RandomHLT": randomRefPath, "No": noRefPath, "Bootstrap": bsRefPath}
108  references = ["Muon", "No", "Bootstrap"] #"RandomHLT"
109 
110  # if we want to make the eta efficiencies, can add in SReta and LReta
111  sr_props = ["SRpt"] #SReta
112  lr_props = ["LRpt"] #LReta
113  trigger_group_list = {"gfex_SR_triggers" : gfex_SR_triggers,
114  "gfex_LR_triggers" : gfex_LR_triggers,
115  "jfex_SR_triggers" : jfex_SR_triggers,
116  "jfex_LR_triggers" : jfex_LR_triggers }
117  properties_per_trigger_group = {"gfex_SR_triggers" : sr_props, "jfex_SR_triggers" : sr_props,
118  "gfex_LR_triggers" : lr_props, "jfex_LR_triggers" : lr_props }
119  pathadd_per_trigger_group = {"gfex_SR_triggers" : "gFEX/", "jfex_SR_triggers" : "jFEX/",
120  "gfex_LR_triggers" : "gFEX/", "jfex_LR_triggers" : "jFEX/" }
121  trigger_groups = list(trigger_group_list.keys())
122 
123  xlabel_for_prop = { "SRpt" :'pT [MeV]', "SReta" : '#eta', "LRpt" :'pT [MeV]', "LReta" : '#eta'}
124  nbins = {"SRpt": 220, "SReta" :32, "LRpt": 220, "LReta" :32}
125  binmin = {"SRpt": -50, "SReta" :-3.3, "LRpt": -50, "LReta" :-3.3}
126  binmax = {"SRpt": 1800*GeV, "SReta" :3.3, "LRpt": 1800*GeV, "LReta" :3.3}
127 
128 
129  plotDistrubutions = False
130  if plotDistrubutions:
131  helper.defineHistogram('raw_pt',title='pT for all leading offline jets (with no trigger requirments);PT [MeV];Events', fillGroup=groupName, path=trigPath + distributionPath, xbins=nbins["SRpt"], xmin=binmin["SRpt"], xmax=binmax["SRpt"])
132 
133  helper.defineHistogram('raw_eta', title='Eta Distribution for all leading offline jets (with no trigger requirments);#eta; Count', fillGroup=groupName, path=trigPath + distributionPath, xbins=nbins["SReta"], xmin=binmin["SReta"], xmax=binmax["SReta"])
134 
135 
136  for tgroup in trigger_groups: #iterate through the trigger groups (gFEX SR & LR, jFEX SR & LR)
137  for t in trigger_group_list[tgroup]: #iterate through the triggers within subgroups
138  #add algorithm that flags if the efficiency is not reaching 100%
139  # assemble thresholdConfig dict
140  thresholdConfig = {"Plateau":plateau_dict.get(t,[0.99,0.95])}
141  thresholdConfig["Threshold"] = get_or_estimate_thresholds(t)
142  xMaxConfig = min(thresholdConfig["Threshold"][1]*2.5, binmax["SRpt"]) #set the x maximum of the fit to be 6 times the upper limit, to help the fit work better
143  # if t in threshold_dict: thresholdConfig["Threshold"] = threshold_dict[t]
144  helper.defineDQAlgorithm("JetEfficiency_"+t,
145  hanConfig={"libname":"libdqm_algorithms.so","name":"Simple_fermi_Fit_TEff", "xmax":xMaxConfig, "ImproveFit":1}, # this line is always the same
146  thresholdConfig=thresholdConfig
147  )
148  for p in properties_per_trigger_group[tgroup]:
149  for r in references: #iteratate through the refernce trigger options
150 
151  # if trigger not included in the menu, then lets modify the hist title to make that clear!
152  if t in l1menu: eff_plot_title = t+';'+xlabel_for_prop[p]+'; Efficiency '
153  elif t not in l1menu and t in (gfex_SR_triggers + gfex_LR_triggers): eff_plot_title = t+' Emulated;'+xlabel_for_prop[p]+'; Efficiency '
154  else: eff_plot_title = t+' NOT in Menu;'+xlabel_for_prop[p]+'; Efficiency '
155 
156  #Using the muon reference trigger selection, as our least biased trigger selection inside the web displkay. Others still exist in the HIST file for now
157  if r == "Muon" and p in ["SRpt", "LRpt"]:
158  helper.defineHistogram(f"bool_{r}_{t}, val_{p};{p}_{t}", type='TEfficiency', title=eff_plot_title, fillGroup=groupName, path=ExpertTrigPath + pathadd_per_trigger_group[tgroup]+ reference_paths[r], xbins=nbins[p], xmin=binmin[p], xmax=binmax[p], hanConfig={"algorithm":"JetEfficiency_"+t}, opt='kAlwaysCreate')
159  else:
160  helper.defineHistogram(f"bool_{r}_{t}, val_{p};{p}_{t}", type='TEfficiency', title=eff_plot_title, fillGroup=groupName, path=trigPath + pathadd_per_trigger_group[tgroup]+ reference_paths[r], xbins=nbins[p], xmin=binmin[p], xmax=binmax[p], opt='kAlwaysCreate')
161 
162 
163 
164  acc = helper.result()
165  result.merge(acc)
166  print("flags.DQ.Environment = " + flags.DQ.Environment )
167  return result
168 
169 def get_closest_threshold(trigger_value, extracted_values, lower_bounds, upper_bounds):
170  """
171  Finds and returns the threshold values of the closest existing trigger.
172  """
173  import numpy as np
174  closest_index = np.abs(extracted_values - trigger_value).argmin()
175  return [lower_bounds[closest_index], upper_bounds[closest_index]]
176 
177 def estimate_thresold(trigger_name):
178  """
179  Estimates the DQ monitoring threshold range for a given trigger name based on given threshold_dict,
180  treating jet types (gJ, gLJ, jJ, and jLJ) as separate for extrapolation.
181  If interpolation fails, it returns the closest existing trigger values.
182  """
183  import re
184  import numpy as np
185  # Extract the numeric portion and type from the trigger name
186  match = re.search(r'(gJ|gLJ|jJ|jLJ)(\d+)', trigger_name)
187  if not match:
188  return None
189 
190  trigger_type, trigger_value = match.groups()
191  trigger_value = int(trigger_value)
192 
193  # Gather existing numeric values and their thresholds for the same type
194  extracted_values = []
195  lower_bounds = []
196  upper_bounds = []
197 
198  for key, (low, high) in threshold_dict.items():
199  key_match = re.search(r'(gJ|gLJ|jJ|jLJ)(\d+)', key)
200  if key_match and key_match.group(1) == trigger_type:
201  extracted_values.append(int(key_match.group(2)))
202  lower_bounds.append(low)
203  upper_bounds.append(high)
204 
205  if not extracted_values:
206  return None # No matching trigger types found
207 
208  extracted_values = np.array(extracted_values)
209  lower_bounds = np.array(lower_bounds)
210  upper_bounds = np.array(upper_bounds)
211 
212  # Try interpolation/extrapolation
213  lower_pred = np.interp(trigger_value, extracted_values, lower_bounds, left=lower_bounds[0], right=lower_bounds[-1])
214  upper_pred = np.interp(trigger_value, extracted_values, upper_bounds, left=upper_bounds[0], right=upper_bounds[-1])
215 
216  return [lower_pred, upper_pred]
217 
218 def get_or_estimate_thresholds(trigger_name):
219  """
220  Returns the threshold from threshold_dict if it exists.
221  Otherwise, predicts the thresholds using estimate_thresold.
222  """
223  if trigger_name in threshold_dict:
224  return threshold_dict[trigger_name] # Return stored values if available
225  else:
226  print("WARNING, trigger " + trigger_name + " doesn't have predifined thresholds for DQ Algorithm. Estimating thresholds with a fit, or using thresholds from closest exisiting trigger.")
227  print("Please add thresholds to the threshold_dict for trigger " + trigger_name)
228  print(estimate_thresold(trigger_name))
229  return estimate_thresold(trigger_name) # Predict or use closest match
230 
231 
232 plateau_dict = {} #in case there are low stats for some of the triggers, we could modify the threshold ranges for some triggers
233 threshold_dict = {"L1_gJ20p0ETA25" : [55e3, 75e3], #hits 50% at 50 for a good run, 100% around 75
234  "L1_gJ50p0ETA25" : [110e3, 180e3], #hits 50% at 109 for a good run, 100% around 180
235  "L1_gJ100p0ETA25" : [195e3, 3000e3],#hits 50% at 185 for a good run, 100% around 300
236  "L1_gJ400p0ETA25" : [620e3, 900e3],#hits 50% at 611 for a good run, 100% around 900
237  "L1_gLJ80p0ETA25" : [125e3, 200e3],#hits 50% at 113 for a good run, 100% around 200
238  "L1_gLJ100p0ETA25" : [150e3, 240e3],#hits 50% at 137 for a good run, 100% around 240
239  "L1_gLJ140p0ETA25" : [210e3, 315e3],#hits 50% at 197 for a good run, 100% around 315
240  "L1_gLJ160p0ETA25" : [240e3, 260e3],#hits 50% at 225 for a good run, 100% around 350
241  "L1_jJ30" : [50e3, 85e3],#hits 50% at 46 for a good run, 100% around 85
242  "L1_jJ40" : [55e3, 90e3],#hits 50% at 47 for a good run, 100% around 90
243  "L1_jJ50" : [60e3, 100e3],#hits 50% at 53 for a good run, 100% around 100
244  "L1_jJ60" : [90e3, 130e3],#hits 50% at 85 for a good run, 100% around 130
245  "L1_jJ80" : [90e3, 155e3],#hits 50% at 86 for a good run, 100% around 155
246  "L1_jJ90" : [110e3, 185e3],#hits 50% at 105 for a good run, 100% around 185
247  "L1_jJ125" : [145e3, 230e3],#hits 50% at 140 for a good run, 100% around 230
248  "L1_jJ140" : [160e3, 225e3],#hits 50% at 150 for a good run, 100% around 255
249  "L1_jJ160" : [180e3, 260e3],#hits 50% at 170 for a good run, 100% around 260
250  "L1_jJ180" : [235e3, 320e3],#hits 50% at 223 for a good run, 100% around 320
251  "L1_SC111-CjJ40": [195e3, 300e3],#hits 50% at 190 for a good run, 100% around 300
252 }
253 
254 
255 if __name__=='__main__':
256  # set debug level for whole job
257  from AthenaCommon.Logging import log
258  from AthenaCommon.Constants import INFO #DEBUG
259  log.setLevel(INFO)
260 
261  # set input file and config options
262  from AthenaConfiguration.AllConfigFlags import initConfigFlags
263  flags = initConfigFlags()
264 
265  import glob
266 
267  inputs = glob.glob('/eos/atlas/atlastier0/rucio/data18_13TeV/physics_Main/00354311/data18_13TeV.00354311.physics_Main.recon.ESD.f1129/data18_13TeV.00354311.physics_Main.recon.ESD.f1129._lb0013._SFO-8._0001.1')
268 
269 
270  flags.Input.Files = inputs
271  flags.Output.HISTFileName = 'ExampleMonitorOutput_LVL1.root'
272 
273  flags.lock()
274 
275  flags.dump() # print all the configs
276 
277  from AthenaConfiguration.MainServicesConfig import MainServicesCfg
278  from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg
279  cfg = MainServicesCfg(flags)
280  cfg.merge(PoolReadCfg(flags))
281 
282  JetEfficiencyMonitorCfg = JetEfficiencyMonitoringConfig(flags)
283  cfg.merge(JetEfficiencyMonitorCfg)
284 
285 
286  # message level for algorithm
287  JetEfficiencyMonitorCfg.getEventAlgo('JetEfficiencyMonAlg').OutputLevel = 1 # 1/2 INFO/DEBUG
288  # options - print all
python.JetAnalysisCommon.ComponentAccumulator
ComponentAccumulator
Definition: JetAnalysisCommon.py:302
min
constexpr double min()
Definition: ap_fixedTest.cxx:26
METMakerConfig.getMETMakerAlg
def getMETMakerAlg(suffix, jetSelection="Tier0", jetColl="")
Definition: METMakerConfig.py:60
JetEfficiencyMonitorAlgorithm.get_or_estimate_thresholds
def get_or_estimate_thresholds(trigger_name)
Definition: JetEfficiencyMonitorAlgorithm.py:218
JetEfficiencyMonitorAlgorithm.estimate_thresold
def estimate_thresold(trigger_name)
Definition: JetEfficiencyMonitorAlgorithm.py:177
METAssociatorCfg
Definition: METAssociatorCfg.py:1
python.TriggerConfigAccess.getL1MenuAccess
L1MenuAccess getL1MenuAccess(flags=None)
Definition: TriggerConfigAccess.py:129
python.LArMinBiasAlgConfig.int
int
Definition: LArMinBiasAlgConfig.py:59
python.JetRecConfig.JetRecCfg
def JetRecCfg(flags, jetdef, returnConfiguredDef=False)
Top level functions returning ComponentAccumulator out of JetDefinition.
Definition: JetRecConfig.py:36
JetEfficiencyMonitorAlgorithm.get_closest_threshold
def get_closest_threshold(trigger_value, extracted_values, lower_bounds, upper_bounds)
Definition: JetEfficiencyMonitorAlgorithm.py:169
python.MainServicesConfig.MainServicesCfg
def MainServicesCfg(flags, LoopMgr='AthenaEventLoopMgr')
Definition: MainServicesConfig.py:260
Constants
some useful constants -------------------------------------------------—
histSizes.list
def list(name, path='/')
Definition: histSizes.py:38
print
void print(char *figname, TCanvas *c1)
Definition: TRTCalib_StrawStatusPlots.cxx:25
python.AllConfigFlags.initConfigFlags
def initConfigFlags()
Definition: AllConfigFlags.py:19
python.PoolReadConfig.PoolReadCfg
def PoolReadCfg(flags)
Definition: PoolReadConfig.py:69
JetEfficiencyMonitorAlgorithm.JetEfficiencyMonitoringConfig
def JetEfficiencyMonitoringConfig(flags)
Definition: JetEfficiencyMonitorAlgorithm.py:4
PFCfg.PFGlobalFlowElementLinkingCfg
def PFGlobalFlowElementLinkingCfg(inputFlags, **kwargs)
Definition: PFCfg.py:472