ATLAS Offline Software
TriggerInfo.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
2 
3 __author__ = 'Javier Montejo'
4 __version__="$Revision: 2.0 $"
5 __doc__="Class containing all the information of an HLT chain"
6 
7 import re
8 from TriggerMenuMT.TriggerAPI.TriggerEnums import TriggerType, TriggerPeriod
9 from collections import Counter
10 import six
11 from AthenaCommon.Logging import logging
12 log = logging.getLogger(__name__)
13 
15  ''' Object containing all the HLT information related to a given period.
16  Stores a list of TriggerChain objects and the functions to skim them
17  '''
18  def __init__(self,period=0, customGRL=None, release=None, flags=None):
19  self.triggerChains = []
20  self.period = period
21  self.totalLB = 0
22  self.totalLBByRun = {}
23 
24  if not period and not customGRL: return
25  from .TriggerDataAccess import getHLTlist
26  HLTlist, self.totalLB, self.totalLBByRun = getHLTlist(period, customGRL, release, flags)
27  for hlt, l1, livefraction, activeLB, hasRerun, activeLBByRun in HLTlist:
28  self.triggerChains.append( TriggerChain(hlt, l1, livefraction, activeLB, hasRerun, activeLBByRun))
29 
30  def setRunRange(self,start=0,end=999999):
31  if not self.totalLBByRun:
32  # empty dict means either loaded from trigger menu or from old json
33  totalLB = self.totalLB
34  else:
35  totalLB = 0
36  for run,efflb in self.totalLBByRun.items():
37  if int(run)<int(start) or int(run)>int(end): continue
38  totalLB += efflb
39  for tc in self.triggerChains:
40  tc.setRunRange(start,end,totalLB)
41 
42  def __str__(self):
43  return f"<TriggerMenuMT.TriggerAPI.TriggerInfo.TriggerInfo object with {len(self.triggerChains)} triggerChains, period={self.period}, totalLB={self.totalLB}>"
44 
45  def toJSON(self):
46  return dict(period= TriggerPeriod.toName(self.period), totalLB=self.totalLB,triggerChains=self.triggerChains,totalLBByRun=self.totalLBByRun)
47 
48  @classmethod
49  def merge(cls,listofTI):
50  from copy import deepcopy
51  mergedTI = TriggerInfo()
52  mergedHLTmap = {}
53  for ti in listofTI:
54  mergedTI.period |= ti.period
55  mergedTI.totalLB += ti.totalLB
56  for run,lb in ti.totalLBByRun.items():
57  if run not in mergedTI.totalLBByRun: mergedTI.totalLBByRun[run] = 0
58  mergedTI.totalLBByRun[run] += lb
59  for tc in ti.triggerChains:
60  if tc.name not in mergedHLTmap: mergedHLTmap[tc.name] = deepcopy(tc)
61  else: mergedHLTmap[tc.name].activeLB += tc.activeLB
62  # copy activeLBByRun values too
63  for run,lb in tc.activeLBByRun.items():
64  if run not in mergedHLTmap[tc.name].activeLBByRun: mergedHLTmap[tc.name].activeLBByRun = 0
65  mergedHLTmap[tc.name].activeLBByRun += lb
66  for tc in six.itervalues (mergedHLTmap):
67  tc.livefraction = tc.activeLB/float(mergedTI.totalLB)
68  mergedTI.triggerChains = list(mergedHLTmap.values())
69  return mergedTI
70 
71 
72  @classmethod
73  def testCustomGRL(cls, grl):
74  from TriggerMenuMT.TriggerAPI.TriggerPeriodData import TriggerPeriodData
75  return TriggerPeriodData.testCustomGRL(grl)
76 
77  def reparse(self):
78  self.triggerChains = [ TriggerChain(t.name, t.l1seed, t.livefraction, t.activeLB) for t in self.triggerChains ]
79 
80  def _getUnprescaled(self,triggerType, additionalTriggerType, matchPattern, livefraction=1.0):
81  return [x.name for x in self.triggerChains if x.isUnprescaled(livefraction) and x.passType(triggerType, additionalTriggerType) and re.search(matchPattern, x.name)]
82 
83  def _getLowestUnprescaled(self,triggerType, additionalTriggerType, matchPattern, livefraction=1.0):
84  chainList = [ x for x in self.triggerChains if x.isUnprescaled(livefraction) and x.passType(triggerType, additionalTriggerType) and re.search(matchPattern, x.name)]
85  typeMap = {}
86  for chain in chainList:
87  if chain.triggerType not in typeMap:
88  typeMap[chain.triggerType] = [chain]
89  continue
90  append = False
91  for other in typeMap[chain.triggerType][:]:
92  comp = chain.isLowerThan(other,self.period)
93  if comp == 0:
94  append = False
95  break
96  append = True
97  if comp == 1: typeMap[chain.triggerType].remove(other)
98  if append:
99  typeMap[chain.triggerType].append(chain)
100  return [x.name for t in six.itervalues (typeMap) for x in t ]
101 
102 
103  def _getAllHLT(self,triggerType, additionalTriggerType, matchPattern, livefraction):
104  return {x.name: x.livefraction for x in self.triggerChains if x.passType(triggerType, additionalTriggerType) and re.search(matchPattern, x.name) and x.isUnprescaled(livefraction)}
105 
106  def _getActive(self,triggerType, additionalTriggerType, matchPattern, livefraction):
107  return [x.name for x in self.triggerChains if x.isActive(livefraction) and x.passType(triggerType, additionalTriggerType) and re.search(matchPattern, x.name)]
108  def _getInactive(self,triggerType, additionalTriggerType, matchPattern, livefraction):
109  return [x.name for x in self.triggerChains if x.isInactive(livefraction) and x.passType(triggerType, additionalTriggerType) and re.search(matchPattern, x.name)]
110 
111  def _checkPeriodConsistency(self,triggerType, additionalTriggerType, matchPattern):
112  inconsistent = set()
113  for i in range(len(self.triggerChains)):
114  probe1 = self.triggerChains[i]
115  if not (probe1.passType(triggerType, additionalTriggerType) and re.search(matchPattern, probe1.name)): continue
116  for j in range(i+1,len(self.triggerChains)):
117  probe2 = self.triggerChains[j]
118  if not (probe2.passType(triggerType, additionalTriggerType) and re.search(matchPattern, probe2.name)): continue
119  if probe1.isUnprescaled() and not probe2.isUnprescaled() and probe1.isLowerThan(probe2,self.period)==1:
120  log.error(f"Found {probe2.name} that is tighter than Primary {probe1.name}")
121  inconsistent.add(probe2.name)
122  if probe2.isUnprescaled() and not probe1.isUnprescaled() and probe2.isLowerThan(probe1,self.period)==1:
123  log.error(f"Found {probe1.name} that is tighter than Primary {probe2.name}")
124  inconsistent.add(probe1.name)
125 
126  return inconsistent
127 
128 
130  types = ('e','j','mu','tau','xe','g','ht')
131  uctTypes = ('isotrk', 'fslrt', 'dedxtrk', 'hitdvjet', 'fsvsi', 'distrk', 'dispjet', 'dispvtx') # unconventional tracking types
132  legpattern = re.compile('([0-9]*)(%s)([0-9]+)(noL1)?' % '|'.join(types+uctTypes))
133  detailpattern = re.compile(r'(?:-?\d+)|(?:[^0-9 -]+)') #split into text-only vs number-only
134  bjetpattern = re.compile('bmv|bhmv|btight|bmedium|bloose|bld1|bgn1|bgn2|bdl1')
135  bphyspattern = re.compile('b[A-Z]')
136  exoticspattern = re.compile('llp|LLP|muvtx|hiptrt|LATE|NOMATCH|distrk|hitdvjet')
137  afppattern = re.compile('afp|AFP')
138 
139  def __init__(self,legname, chainseed, chainname=None):
140  self.legname = legname
141  self.l1seed = ""
142  details = []
143  chainseed= chainseed.replace("L1_","")
144  blocks = legname.split("_L1")
145 
146  for token in blocks[0].split("_"):
147  m = self.legpattern.match(token)
148  if m:
149  count,legtype,thr,noL1 = m.groups()
150  self.count = int(count) if count else 1
151  self.thr = int(thr)
152  if legtype == 'e':
153  if self.count > 1: self.legtype = TriggerType.el_multi
154  else: self.legtype = TriggerType.el_single
155  elif legtype == 'mu':
156  if self.count > 1: self.legtype = TriggerType.mu_multi
157  else: self.legtype = TriggerType.mu_single
158  elif legtype == 'j':
159  if self.count > 1: self.legtype = TriggerType.j_multi
160  else: self.legtype = TriggerType.j_single
161  elif legtype == 'tau':
162  if self.count > 1: self.legtype = TriggerType.tau_multi
163  else: self.legtype = TriggerType.tau_single
164  elif legtype == 'g':
165  if self.count > 1: self.legtype = TriggerType.g_multi
166  else: self.legtype = TriggerType.g_single
167  elif legtype == 'xe':
168  self.legtype = TriggerType.xe
169  elif legtype == 'ht':
170  self.legtype = TriggerType.ht
171  elif legtype in self.uctTypes:
172  self.legtype = TriggerType.exotics
173  # all these leg types are actually distinct, so include legtype in the detail list too
174  details.append(legtype)
175  else:
176  log.info("Unknown trigger type: %s",legtype)
177  if noL1: details.append(noL1)
178  else:
179  if self.bjetpattern.match(token):
180  if self.legtype == TriggerType.j_single: self.legtype = TriggerType.bj_single
181  if self.legtype == TriggerType.j_multi: self.legtype = TriggerType.bj_multi
182  if self.bphyspattern.match(token):
183  self.legtype = TriggerType.mu_bphys
184  if self.exoticspattern.search(token):
185  self.legtype = TriggerType.exotics
186  if self.afppattern.search(token):
187  self.legtype = TriggerType.afp
188  details.append(token)
189 
190  for l1seed in blocks[1:]:
191  if self.exoticspattern.search(l1seed):
192  self.legtype = TriggerType.exotics
193  if self.afppattern.search(l1seed):
194  self.legtype = TriggerType.afp
195  if l1seed == chainseed: continue
196  else:
197  assert self.l1seed=="", (self.l1seed, chainseed, chainname, blocks[1:])
198  self.l1seed = l1seed
199  if not self.l1seed: self.l1seed = chainseed
200  self.details = tuple(details)
201 
202  def __eq__(self,other):
203  return (self.l1seed == other.l1seed and self.count == other.count and self.thr == other.thr and self.legtype == other.legtype and self.details == other.details)
204 
205  def __hash__(self):
206  return hash((self.l1seed,self.count,self.thr,self.legtype,self.details))
207 
208  def __repr__(self):
209  return "{0} l1seed={1} count={2} thr={3} details={4} legtype={5}".format(self.legname,self.l1seed,self.count,self.thr,self.details,TriggerType.toStr(self.legtype))
210 
211  def isLegLowerThan(self, other, is2015, debug=False):
212  ''' Returns -9 if none of them is lower than the other (e.g. different met flavour).
213  Returns -1 if identical
214  Returns 0 if other is lower than self.
215  Returns 1 if self is lower than other.
216  '''
217  if debug:
218  log.info("DEBUG LEGS --------")
219  log.info(f"{self.legname} {other.legname}")
220  log.info(f"{self.legtype} {other.legtype}")
221  log.info(f"{self.l1seed} {other.l1seed}")
222  log.info(f"{self.details} {other.details}")
223  log.info(f"{self.thr} {other.thr}")
224  log.info(self.compareDetails(other, is2015, debug=True))
225  log.info(self.details == other.details)
226  log.info("DEBUG LEGS END --------")
227 
228  if self.legtype != other.legtype: return -9
229  if self.compareDetails(other, is2015) == -1:
230  if self.thr < other.thr: return 1
231  if self.thr > other.thr: return 0
232  else: return -1
233 
234  if self.compareDetails(other, is2015) == 1 and self.thr <= other.thr: return 1
235  if self.compareDetails(other, is2015) == 0 and other.thr <= self.thr: return 0
236  return -9
237 
238  def compareDetails(self, other, is2015, debug=False):
239  ''' Returns -9 if none of them is lower than the other (e.g. different met flavour).
240  Returns -1 if identical
241  Returns 0 if other is lower than self.
242  Returns 1 if self is lower than other.
243  '''
244  from copy import deepcopy
245 
246  if debug: log.info(f"compareDetails: {len(self.details)} {len(other.details)} {(self.l1seed == other.l1seed)} {(self.details == other.details)}")
247  if len(self.details) != len(other.details):
248  if not is2015 and any([x.startswith("noL1") for x in self.details]):
249  cloneself = deepcopy(self)
250  cloneself.details = [ x for x in self.details if not x.startswith("noL1")]
251  compno = cloneself.compareDetails(other,is2015,debug)
252  if compno ==1 or compno == -1:
253  return 1
254  if not is2015 and any([x.startswith("noL1") for x in other.details]):
255  cloneother = deepcopy(other)
256  cloneother.details = [ x for x in other.details if not x.startswith("noL1")]
257  compno = self.compareDetails(cloneother,is2015,debug)
258  if compno ==0 or compno == -1:
259  return 0
260  if not is2015 and any([x.startswith("nod0") for x in self.details]):
261  cloneself = deepcopy(self)
262  cloneself.details = [ x for x in self.details if not x.startswith("nod0")]
263  compno = cloneself.compareDetails(other,is2015,debug)
264  if compno ==1 or compno == -1:
265  return 1
266  if not is2015 and any([x.startswith("nod0") for x in other.details]):
267  cloneother = deepcopy(other)
268  cloneother.details = [ x for x in other.details if not x.startswith("nod0")]
269  compno = self.compareDetails(cloneother,is2015,debug)
270  if compno ==0 or compno == -1:
271  return 0
272  if any([x.startswith("cut") for x in self.details]):
273  cloneself = deepcopy(self)
274  cloneself.details = [ x for x in self.details if not x.startswith("cut")]
275  compno = cloneself.compareDetails(other,is2015,debug)
276  if compno ==0 or compno == -1:
277  return 0
278  if any([x.startswith("cut") for x in other.details]):
279  cloneother = deepcopy(other)
280  cloneother.details = [ x for x in other.details if not x.startswith("cut")]
281  compno = self.compareDetails(cloneother,is2015,debug)
282  if compno ==1 or compno == -1:
283  return 1
284  return -9
285  compl1seed = self.compareTags(self.l1seed, other.l1seed, stringSubset=True, debug=debug)
286  compdetails = self.compareTags(" ".join(self.details), " ".join(other.details), debug=debug )
287  if self.l1seed == other.l1seed:
288  if self.details == other.details: return -1
289  if debug: log.info(f"compareTags 1: {compdetails}")
290  return compdetails
291 
292  if self.details == other.details:
293  if debug: log.info(f"compareTags 2: {compl1seed}")
294  return compl1seed
295 
296  if compl1seed == compdetails:
297  return compl1seed
298  return -9
299 
300  def compareTags(self, tag1, tag2, stringSubset=False,debug=False):
301  def mycomp(x,y):
302  ''' Return -9 for different strings,
303  -1 for identical strings/nums,
304  0/1 for high/low numbers or string subsets
305  '''
306  try:
307  x,y = int(x), int(y)
308  if x < y: return 1
309  elif x > y: return 0
310  else: return -1
311  except ValueError:
312  if x==y: return -1
313  if x == y.replace("vloose","loose"): return 0
314  if x == y.replace("vloose","loose").replace("loose","medium"): return 0
315  if x == y.replace("vloose","loose").replace("loose","medium").replace("medium","tight"): return 0
316  if y == x.replace("vloose","loose"): return 1
317  if y == x.replace("vloose","loose").replace("loose","medium"): return 1
318  if y == x.replace("vloose","loose").replace("loose","medium").replace("medium","tight"): return 1
319  l1ThresholdLevels = ["L","M","T"]
320  if x in l1ThresholdLevels and y in l1ThresholdLevels:
321  if l1ThresholdLevels.index(x) > l1ThresholdLevels.index(y): return 0
322  return 1 # don't need to check for equality, that was done above
323  if stringSubset:
324  if x in y: return 1
325  if y in x: return 0
326  return -9
327 
328  if tag1 == tag2: return -1
329  #lower mv2 and deltaR/deltaZ/deltaPhi values are tighter, put a minus sign to trick it
330  inverseCuts = ("mv2c","dr","dz","dphi","dl1d","dl1r","gn1","gn2")
331  for cut in inverseCuts:
332  tag1 = tag1.replace(cut,cut+"-")
333  tag2 = tag2.replace(cut,cut+"-")
334  #only make a statement on the numerical values, with everything else identical
335  reself = self.detailpattern.findall(tag1)
336  reother = self.detailpattern.findall(tag2)
337 
338  if len(reself) != len(reother): return -9
339  thecomp = [mycomp(a,b) for a,b in zip(reself,reother)]
340  if debug: log.info(f"thecomp: {thecomp} {reself} {reother}")
341  if any([x == -9 for x in thecomp]): return -9
342  if all([x !=0 for x in thecomp]) and any([x == 1 for x in thecomp]): return 1
343  if all([x !=1 for x in thecomp]) and any([x == 0 for x in thecomp]): return 0
344  return -9
345 
346  @classmethod
347  def parse_legs(cls,name,l1seed,chainname):
348  legsname = []
349  name = name.replace("HLT_","")
350  for token in name.split("_"):
351  m = cls.legpattern.match(token)
352  if m:
353  legsname.append(token)
354  elif legsname:
355  legsname[-1] += "_"+token
356  else: #first token doesn't match
357  #log.info("parse_legs: Problem parsing",name)
358  return []
359  return [TriggerLeg(l,l1seed,chainname) for l in legsname]
360 
362  l1types = ('EM','J','MU','TAU','XE','XS','HT','eEM','eTAU','jJ','jTAU','jXE','gXEJWOJ','gJ','gLJ','jEM')
363  l1pattern = re.compile('([0-9]*)(%s)([0-9]+)' % '|'.join(l1types))
364 
365  def __init__(self,name,l1seed,livefraction,activeLB=1,hasRerun=False, activeLBByRun={}):
366  self.name = name
367  self.l1seed = l1seed
368  tmplegs = TriggerLeg.parse_legs(name,l1seed,name)
369  self.legs = self.splitAndOrderLegs(tmplegs)
370  self.livefraction = livefraction
371  self.activeLB = activeLB
372  self.hasRerun = hasRerun
373  self.activeLBByRun = activeLBByRun
374  self.triggerType = self.getTriggerType(self.legs, l1seed)
375 
376  def setRunRange(self,start,end,totalLB):
377  """
378  This method is called by the owning TriggerInfo method to adjust the livefractions and activeLB
379  to only the given runs
380  :param start:
381  :param end:
382  :param totalLB:
383  :return:
384  """
385  if not self.activeLBByRun:
386  # empty dict means either loaded from trigger menu or from old json
387  return
388  self.activeLB = 0
389  for run,efflb in self.activeLBByRun.items():
390  if int(run)<int(start) or int(run)>int(end): continue
391  self.activeLB += efflb
392  self.livefraction = self.activeLB/totalLB
393  pass
394 
395  def toJSON(self):
396  return dict(name=self.name, l1seed=self.l1seed, livefraction=self.livefraction, activeLB=self.activeLB, hasRerun=self.hasRerun,activeLBByRun=self.activeLBByRun)
397 
398  def splitAndOrderLegs(self, legs):
399  from copy import deepcopy
400  newLegs = []
401  for triggerType in TriggerType:
402  for l in legs:
403  if not l.legtype == triggerType: continue
404  for i in range(l.count): #split into N single legs
405  tmp = deepcopy(l)
406  tmp.count = 1
407  if tmp.legtype & TriggerType.el_multi:
408  tmp.legtype |= TriggerType.el_single
409  tmp.legtype &= ~TriggerType.el_multi
410  elif tmp.legtype & TriggerType.mu_multi:
411  tmp.legtype |= TriggerType.mu_single
412  tmp.legtype &= ~TriggerType.mu_multi
413  elif tmp.legtype & TriggerType.tau_multi:
414  tmp.legtype |= TriggerType.tau_single
415  tmp.legtype &= ~TriggerType.tau_multi
416  elif tmp.legtype & TriggerType.j_multi:
417  tmp.legtype |= TriggerType.j_single
418  tmp.legtype &= ~TriggerType.j_multi
419  elif tmp.legtype & TriggerType.bj_multi:
420  tmp.legtype |= TriggerType.bj_single
421  tmp.legtype &= ~TriggerType.bj_multi
422  elif tmp.legtype & TriggerType.g_multi:
423  tmp.legtype |= TriggerType.g_single
424  tmp.legtype &= ~TriggerType.g_multi
425  newLegs.append(tmp)
426  return newLegs
427 
428 
429  # def getChainGroupTriggerType(self):
430  # """
431  # :return: triggerType determined by chainGroup information
432  # """
433  # mtype = TriggerType.UNDEFINED
434  #
435  # # decide trigger type on chainGroup's "RATE:" group if present
436  # for group in self.chainGroups:
437  # if not group.startswith("RATE:"): continue
438  # rateGroup = group[5:] # strip prefix
439  # if rateGroup=="SingleElectron": mtype |= TriggerType.el_single
440  # elif rateGroup=="SingleMuon": mtype |= TriggerType.mu_single
441  # elif rateGroup=="MultiElectron": mtype |= TriggerType.el_multi
442  # elif rateGroup=="MultiMuon": mtype |= TriggerType.mu_multi
443  # elif rateGroup=="SinglePhoton": mtype |= TriggerType.g_single
444  # elif rateGroup=="MultiPhoton": mtype |= TriggerType.g_multi
445  # elif rateGroup=="SingleJet": mtype |= TriggerType.j_single
446  # elif rateGroup=="MultiJet": mtype |= TriggerType.j_multi
447  # elif rateGroup=="SingleBJet": mtype |= TriggerType.bj_single
448  # elif rateGroup=="MultiBJet": mtype |= TriggerType.bj_multi
449  # elif rateGroup=="SingleTau": mtype |= TriggerType.tau_single
450  # elif rateGroup=="MultiTau": mtype |= TriggerType.tau_multi
451  # else:
452  # if "Bphysics" in rateGroup: mtype |= TriggerType.mu_bphys
453  # if "MET" in rateGroup: mtype |= TriggerType.xe
454  # if "Muon" in rateGroup: mtype |= TriggerType.mu
455  # if "Electron" in rateGroup: mtype |= TriggerType.el
456  # if "Bjet" in rateGroup: mtype |= TriggerType.bj
457  # if "Jet" in rateGroup: mtype |= TriggerType.j
458  # if "Tau" in rateGroup: mtype |= TriggerType.tau
459  #
460  # return mtype
461 
462  def getTriggerType(self, legs, l1seed):
463  mtype = TriggerType.UNDEFINED
464 
465  for l in legs:
466  if mtype & TriggerType.el and l.legtype & TriggerType.el:
467  mtype |= TriggerType.el_multi
468  mtype &= ~TriggerType.el_single
469  elif mtype & TriggerType.mu and l.legtype & TriggerType.mu:
470  mtype |= TriggerType.mu_multi
471  mtype &= ~TriggerType.mu_single
472  elif mtype & TriggerType.tau and l.legtype & TriggerType.tau:
473  mtype |= TriggerType.tau_multi
474  mtype &= ~TriggerType.tau_single
475  elif mtype & TriggerType.j and l.legtype & TriggerType.j:
476  mtype |= TriggerType.j_multi
477  mtype &= ~TriggerType.j_single
478  elif mtype & TriggerType.bj and l.legtype & TriggerType.bj:
479  mtype |= TriggerType.bj_multi
480  mtype &= ~TriggerType.bj_single
481  elif mtype & TriggerType.g and l.legtype & TriggerType.g:
482  mtype |= TriggerType.g_multi
483  mtype &= ~TriggerType.g_single
484  elif l.legtype & TriggerType.mu_bphys:
485  mtype |= TriggerType.mu_bphys
486  mtype &= ~(TriggerType.mu_single | TriggerType.mu_multi)
487  elif l.legtype & TriggerType.exotics:
488  mtype |= TriggerType.exotics
489  elif l.legtype & TriggerType.afp:
490  mtype = TriggerType.afp #on purpose not OR-ed
491  else:
492  mtype |= l.legtype
493 
494  l1seed= l1seed.replace("L1_","")
495  if mtype & TriggerType.exotics or mtype & TriggerType.afp:
496  return mtype
497  for token in l1seed.split("_"):
498  m = self.l1pattern.match(token)
499  if m:
500  count,legtype,thr = m.groups()
501  count = int(count) if count else 1
502  if 'EM' in legtype or 'TAU' in legtype:
503  pass
504  elif 'MU' in legtype:
505  if not mtype & TriggerType.mu_bphys:
506  if count > 1: mtype |= TriggerType.mu_multi
507  elif not mtype & TriggerType.mu_multi: mtype |= TriggerType.mu_single
508  elif 'J' in legtype:
509  if not mtype & TriggerType.bj and not mtype & TriggerType.j and not mtype & TriggerType.tau and not mtype & TriggerType.ht:
510  if count > 1: mtype |= TriggerType.j_multi
511  elif not mtype & TriggerType.j_multi: mtype |= TriggerType.j_single
512  elif 'XE' in legtype or 'XS' in legtype:
513  mtype |= TriggerType.xe
514  elif 'HT' in legtype:
515  mtype |= TriggerType.ht
516  else:
517  log.info("Unknown trigger type:",(legtype, mtype, token, self.name))
518  return mtype
519 
520  def isActive(self, livefraction=1e-99):
521  return self.livefraction > livefraction or self.hasRerun
522  def isInactive(self, livefraction=1e-99):
523  return not self.isActive(livefraction)
524 
525  def isUnprescaled(self, livefraction=1.0):
526  return self.livefraction >= livefraction
527 
528  def getType(self):
529  return self.triggerType
530 
531  def passType(self, triggerType, additionalTriggerType):
532  if self.triggerType == TriggerType.UNDEFINED: return False
533  if self.triggerType == TriggerType.ALL: return True
534  match = (self.triggerType & triggerType)
535  if not match: return False
536  tmpType = self.triggerType & ~triggerType
537 
538  try:
539  for t in additionalTriggerType:
540  match = (tmpType & t)
541  if not match: return False
542  tmpType = tmpType & ~t
543  except TypeError: #Not iterable
544  if additionalTriggerType!=TriggerType.UNDEFINED:
545  match = (tmpType & additionalTriggerType)
546  if not match: return False
547  tmpType = tmpType & ~additionalTriggerType
548 
549  return tmpType == TriggerType.UNDEFINED #After matches nothing remains
550 
551  def __repr__(self):
552  return repr({"name":self.name, "legs":self.legs, "triggerType":TriggerType.toStr(self.triggerType), "livefraction":self.livefraction, "activeLB":self.activeLB})
553 
554  def isSubsetOf(self, other):
555  ''' Returns -1 if none of them is a strict subset of the other
556  Returns 0 if the legs in other are a subset of self.
557  Returns 1 if the legs in self are a subset of other.
558  '''
559  if not self.legs or not other.legs: return -1 #problems with AFP
560  selfcounter = Counter(self.legs)
561  othercounter = Counter(other.legs)
562  for leg, count in selfcounter.items():
563  if leg not in othercounter or count > othercounter[leg]: break
564  else: return 1
565  for leg, count in othercounter.items():
566  if leg not in selfcounter or count > selfcounter[leg]: break
567  else: return 0
568  return -1
569 
570  def isLowerThan(self, other,period=TriggerPeriod.future):
571  ''' Returns -1 if none of them is lower than the other (e.g. asymmetric dilepton).
572  Returns 0 if other is lower than self.
573  Returns 1 if self is lower than other.
574  '''
575  is2015 = period & TriggerPeriod.y2015 and not TriggerPeriod.isRunNumber(period)
576  is2015 |= period <= 284484 and TriggerPeriod.isRunNumber(period)
577  if self.triggerType != other.triggerType: return -1
578  if len(self.legs) != len(other.legs): return -1
579  comp = -1
580  debug = False
581  #if re.search("HLT_j55_gsc75_bmv2c1040_split_3j55_gsc75_boffperf_split", self.name): debug = True
582  if debug: log.info("DEBUG:",self.name,other.name)
583  for selfleg, otherleg in zip(self.legs, other.legs):
584  legcomp = selfleg.isLegLowerThan(otherleg, is2015, debug)
585  if debug: log.info("DEBUG LEG return:", legcomp)
586  if legcomp == -9: return -1
587  elif legcomp == -1: continue
588  elif legcomp == 0 and comp == 1: return -1
589  elif legcomp == 1 and comp == 0: return -1
590  elif legcomp == 0 : comp = 0
591  elif legcomp == 1 : comp = 1
592  if debug: log.info("DEBUG FINAL:",comp)
593  return comp
594 
595 
596 def test():
597  a = TriggerChain("HLT_j50_gsc65_bmv2c1040_split_3j50_gsc65_boffperf_split", "L1J100",1)
598  log.info(a)
599  log.info(bin(a.getType()))
600  log.info(a.passType(TriggerType.j_multi, TriggerType.UNDEFINED))
601  log.info(a.passType(TriggerType.j_multi | TriggerType.bj_single, TriggerType.UNDEFINED))
602  log.info(a.isUnprescaled())
603 
604 if __name__ == "__main__":
605  import sys
606  sys.exit(test())
replace
std::string replace(std::string s, const std::string &s2, const std::string &s3)
Definition: hcg.cxx:307
python.TriggerAPI.TriggerInfo.TriggerChain.isLowerThan
def isLowerThan(self, other, period=TriggerPeriod.future)
Definition: TriggerInfo.py:570
python.TriggerAPI.TriggerInfo.TriggerLeg.bphyspattern
bphyspattern
Definition: TriggerInfo.py:135
python.TriggerAPI.TriggerInfo.TriggerInfo._getUnprescaled
def _getUnprescaled(self, triggerType, additionalTriggerType, matchPattern, livefraction=1.0)
Definition: TriggerInfo.py:80
python.TriggerAPI.TriggerInfo.TriggerChain.activeLB
activeLB
Definition: TriggerInfo.py:371
python.TriggerAPI.TriggerInfo.TriggerChain.isInactive
def isInactive(self, livefraction=1e-99)
Definition: TriggerInfo.py:522
python.TriggerAPI.TriggerInfo.TriggerLeg
Definition: TriggerInfo.py:129
python.TriggerAPI.TriggerInfo.TriggerLeg.count
count
Definition: TriggerInfo.py:150
vtune_athena.format
format
Definition: vtune_athena.py:14
python.TriggerAPI.TriggerInfo.TriggerChain.hasRerun
hasRerun
Definition: TriggerInfo.py:372
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
python.TriggerAPI.TriggerInfo.TriggerChain.legs
legs
Definition: TriggerInfo.py:369
python.TriggerAPI.TriggerInfo.TriggerChain.livefraction
livefraction
Definition: TriggerInfo.py:370
python.TriggerAPI.TriggerInfo.TriggerChain.passType
def passType(self, triggerType, additionalTriggerType)
Definition: TriggerInfo.py:531
python.TriggerAPI.TriggerInfo.TriggerLeg.__eq__
def __eq__(self, other)
Definition: TriggerInfo.py:202
bin
Definition: BinsDiffFromStripMedian.h:43
python.TriggerAPI.TriggerInfo.TriggerChain.toJSON
def toJSON(self)
Definition: TriggerInfo.py:395
python.TriggerAPI.TriggerInfo.TriggerLeg.uctTypes
uctTypes
Definition: TriggerInfo.py:131
python.TriggerAPI.TriggerInfo.TriggerChain.name
name
Definition: TriggerInfo.py:366
python.TriggerAPI.TriggerInfo.TriggerInfo._getAllHLT
def _getAllHLT(self, triggerType, additionalTriggerType, matchPattern, livefraction)
Definition: TriggerInfo.py:103
python.TriggerAPI.TriggerInfo.TriggerChain.isActive
def isActive(self, livefraction=1e-99)
Definition: TriggerInfo.py:520
python.TriggerAPI.TriggerInfo.TriggerChain.setRunRange
def setRunRange(self, start, end, totalLB)
Definition: TriggerInfo.py:376
python.TriggerAPI.TriggerInfo.TriggerChain.isSubsetOf
def isSubsetOf(self, other)
Definition: TriggerInfo.py:554
python.TriggerAPI.TriggerInfo.TriggerInfo._getActive
def _getActive(self, triggerType, additionalTriggerType, matchPattern, livefraction)
Definition: TriggerInfo.py:106
python.TriggerAPI.TriggerInfo.TriggerLeg.__init__
def __init__(self, legname, chainseed, chainname=None)
Definition: TriggerInfo.py:139
dumpHVPathFromNtuple.append
bool append
Definition: dumpHVPathFromNtuple.py:91
python.TriggerAPI.TriggerInfo.TriggerChain.getType
def getType(self)
Definition: TriggerInfo.py:528
search
void search(TDirectory *td, const std::string &s, std::string cwd, node *n)
recursive directory search for TH1 and TH2 and TProfiles
Definition: hcg.cxx:738
python.TriggerAPI.TriggerInfo.TriggerLeg.__repr__
def __repr__(self)
Definition: TriggerInfo.py:208
python.TriggerAPI.TriggerInfo.TriggerInfo.triggerChains
triggerChains
Definition: TriggerInfo.py:19
python.TriggerAPI.TriggerInfo.TriggerChain.getTriggerType
def getTriggerType(self, legs, l1seed)
Definition: TriggerInfo.py:462
python.TriggerAPI.TriggerInfo.TriggerInfo.reparse
def reparse(self)
Definition: TriggerInfo.py:77
python.TriggerAPI.TriggerInfo.TriggerChain.activeLBByRun
activeLBByRun
Definition: TriggerInfo.py:373
python.TriggerAPI.TriggerInfo.TriggerLeg.__hash__
def __hash__(self)
Definition: TriggerInfo.py:205
python.TriggerAPI.TriggerInfo.TriggerInfo.toJSON
def toJSON(self)
Definition: TriggerInfo.py:45
python.TriggerAPI.TriggerInfo.TriggerChain.isUnprescaled
def isUnprescaled(self, livefraction=1.0)
Definition: TriggerInfo.py:525
PixelModuleFeMask_create_db.remove
string remove
Definition: PixelModuleFeMask_create_db.py:83
python.TriggerAPI.TriggerInfo.TriggerChain.splitAndOrderLegs
def splitAndOrderLegs(self, legs)
Definition: TriggerInfo.py:398
python.TriggerAPI.TriggerInfo.TriggerLeg.parse_legs
def parse_legs(cls, name, l1seed, chainname)
Definition: TriggerInfo.py:347
python.TriggerAPI.TriggerInfo.TriggerLeg.l1seed
l1seed
Definition: TriggerInfo.py:141
python.TriggerAPI.TriggerInfo.TriggerLeg.compareDetails
def compareDetails(self, other, is2015, debug=False)
Definition: TriggerInfo.py:238
python.TriggerAPI.TriggerInfo.TriggerInfo.period
period
Definition: TriggerInfo.py:20
python.TriggerAPI.TriggerInfo.TriggerChain.l1seed
l1seed
Definition: TriggerInfo.py:367
plotBeamSpotVxVal.range
range
Definition: plotBeamSpotVxVal.py:195
PyAthena::repr
std::string repr(PyObject *o)
returns the string representation of a python object equivalent of calling repr(o) in python
Definition: PyAthenaUtils.cxx:106
histSizes.list
def list(name, path='/')
Definition: histSizes.py:38
python.TriggerAPI.TriggerInfo.TriggerLeg.compareTags
def compareTags(self, tag1, tag2, stringSubset=False, debug=False)
Definition: TriggerInfo.py:300
python.TriggerAPI.TriggerInfo.TriggerInfo.totalLBByRun
totalLBByRun
Definition: TriggerInfo.py:22
python.TriggerAPI.TriggerInfo.TriggerInfo._getInactive
def _getInactive(self, triggerType, additionalTriggerType, matchPattern, livefraction)
Definition: TriggerInfo.py:108
python.TriggerAPI.TriggerInfo.TriggerInfo.totalLB
totalLB
Definition: TriggerInfo.py:21
CxxUtils::set
constexpr std::enable_if_t< is_bitmask_v< E >, E & > set(E &lhs, E rhs)
Convenience function to set bits in a class enum bitmask.
Definition: bitmask.h:224
TCS::join
std::string join(const std::vector< std::string > &v, const char c=',')
Definition: Trigger/TrigT1/L1Topo/L1TopoCommon/Root/StringUtils.cxx:10
python.TriggerAPI.TriggerInfo.test
def test()
Definition: TriggerInfo.py:596
TrigJetMonitorAlgorithm.items
items
Definition: TrigJetMonitorAlgorithm.py:79
python.TriggerAPI.TriggerInfo.TriggerChain
Definition: TriggerInfo.py:361
python.TriggerAPI.TriggerInfo.TriggerLeg.legpattern
legpattern
Definition: TriggerInfo.py:132
python.TriggerAPI.TriggerInfo.TriggerInfo._checkPeriodConsistency
def _checkPeriodConsistency(self, triggerType, additionalTriggerType, matchPattern)
Definition: TriggerInfo.py:111
Cut::all
@ all
Definition: SUSYToolsAlg.cxx:64
python.TriggerAPI.TriggerInfo.TriggerLeg.legname
legname
Definition: TriggerInfo.py:140
python.TriggerAPI.TriggerInfo.TriggerLeg.detailpattern
detailpattern
Definition: TriggerInfo.py:133
CaloCondBlobAlgs_fillNoiseFromASCII.hash
dictionary hash
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:109
python.TriggerAPI.TriggerInfo.TriggerInfo._getLowestUnprescaled
def _getLowestUnprescaled(self, triggerType, additionalTriggerType, matchPattern, livefraction=1.0)
Definition: TriggerInfo.py:83
python.TriggerAPI.TriggerInfo.TriggerLeg.afppattern
afppattern
Definition: TriggerInfo.py:137
python.TriggerAPI.TriggerInfo.TriggerInfo.testCustomGRL
def testCustomGRL(cls, grl)
Definition: TriggerInfo.py:73
python.TriggerAPI.TriggerInfo.TriggerLeg.thr
thr
Definition: TriggerInfo.py:151
python.TriggerAPI.TriggerInfo.TriggerInfo.__init__
def __init__(self, period=0, customGRL=None, release=None, flags=None)
Definition: TriggerInfo.py:18
python.TriggerAPI.TriggerInfo.TriggerLeg.isLegLowerThan
def isLegLowerThan(self, other, is2015, debug=False)
Definition: TriggerInfo.py:211
python.TriggerAPI.TriggerInfo.TriggerChain.__repr__
def __repr__(self)
Definition: TriggerInfo.py:551
python.TriggerAPI.TriggerInfo.TriggerInfo.merge
def merge(cls, listofTI)
Definition: TriggerInfo.py:49
python.TriggerAPI.TriggerInfo.TriggerLeg.details
details
Definition: TriggerInfo.py:200
python.TriggerAPI.TriggerDataAccess.getHLTlist
def getHLTlist(period, customGRL, release, flags=None)
Definition: TriggerDataAccess.py:368
python.TriggerAPI.TriggerInfo.TriggerChain.triggerType
triggerType
Definition: TriggerInfo.py:374
python.TriggerAPI.TriggerInfo.TriggerLeg.bjetpattern
bjetpattern
Definition: TriggerInfo.py:134
python.TriggerAPI.TriggerInfo.TriggerChain.__init__
def __init__(self, name, l1seed, livefraction, activeLB=1, hasRerun=False, activeLBByRun={})
Definition: TriggerInfo.py:365
readCCLHist.float
float
Definition: readCCLHist.py:83
python.TriggerAPI.TriggerInfo.TriggerInfo
Definition: TriggerInfo.py:14
Trk::split
@ split
Definition: LayerMaterialProperties.h:38
python.TriggerAPI.TriggerInfo.TriggerInfo.__str__
def __str__(self)
Definition: TriggerInfo.py:42
python.TriggerAPI.TriggerInfo.TriggerLeg.exoticspattern
exoticspattern
Definition: TriggerInfo.py:136
match
bool match(std::string s1, std::string s2)
match the individual directories of two strings
Definition: hcg.cxx:356
python.TriggerAPI.TriggerInfo.TriggerInfo.setRunRange
def setRunRange(self, start=0, end=999999)
Definition: TriggerInfo.py:30
python.TriggerAPI.TriggerInfo.TriggerChain.l1pattern
l1pattern
Definition: TriggerInfo.py:363
python.TriggerAPI.TriggerInfo.TriggerLeg.legtype
legtype
Definition: TriggerInfo.py:153