3 __author__ =
'Javier Montejo'
4 __version__=
"$Revision: 2.0 $"
5 __doc__=
"Class containing all the information of an HLT chain"
8 from TriggerMenuMT.TriggerAPI.TriggerEnums
import TriggerType, TriggerPeriod
9 from collections
import Counter
10 from AthenaCommon.Logging
import logging
11 log = logging.getLogger(__name__)
14 ''' Object containing all the HLT information related to a given period.
15 Stores a list of TriggerChain objects and the functions to skim them
17 def __init__(self,period=0, customGRL=None, release=None, flags=None):
23 if not period
and not customGRL:
return
24 from .TriggerDataAccess
import getHLTlist
26 for hlt, l1, livefraction, activeLB, hasRerun, activeLBByRun
in HLTlist:
39 tc.setRunRange(start,end,totalLB)
42 return f
"<TriggerMenuMT.TriggerAPI.TriggerInfo.TriggerInfo object with {len(self.triggerChains)} triggerChains, period={self.period}, totalLB={self.totalLB}>"
49 from copy
import deepcopy
53 mergedTI.period |= ti.period
54 mergedTI.totalLB += ti.totalLB
55 for run,lb
in ti.totalLBByRun.items():
56 if run
not in mergedTI.totalLBByRun: mergedTI.totalLBByRun[run] = 0
57 mergedTI.totalLBByRun[run] += lb
58 for tc
in ti.triggerChains:
59 if tc.name
not in mergedHLTmap: mergedHLTmap[tc.name] = deepcopy(tc)
60 else: mergedHLTmap[tc.name].activeLB += tc.activeLB
62 for run,lb
in tc.activeLBByRun.items():
63 if run
not in mergedHLTmap[tc.name].activeLBByRun: mergedHLTmap[tc.name].activeLBByRun = 0
64 mergedHLTmap[tc.name].activeLBByRun += lb
65 for tc
in mergedHLTmap.values():
66 tc.livefraction = tc.activeLB/
float(mergedTI.totalLB)
67 mergedTI.triggerChains =
list(mergedHLTmap.values())
73 from TriggerMenuMT.TriggerAPI.TriggerPeriodData
import TriggerPeriodData
74 return TriggerPeriodData.testCustomGRL(grl)
79 def _getUnprescaled(self,triggerType, additionalTriggerType, matchPattern, livefraction=1.0):
80 return [x.name
for x
in self.
triggerChains if x.isUnprescaled(livefraction)
and x.passType(triggerType, additionalTriggerType)
and re.search(matchPattern, x.name)]
83 chainList = [ x
for x
in self.
triggerChains if x.isUnprescaled(livefraction)
and x.passType(triggerType, additionalTriggerType)
and re.search(matchPattern, x.name)]
85 for chain
in chainList:
86 if chain.triggerType
not in typeMap:
87 typeMap[chain.triggerType] = [chain]
90 for other
in typeMap[chain.triggerType][:]:
91 comp = chain.isLowerThan(other,self.
period)
96 if comp == 1: typeMap[chain.triggerType].
remove(other)
98 typeMap[chain.triggerType].
append(chain)
99 return [x.name
for t
in typeMap.values()
for x
in t ]
102 def _getAllHLT(self,triggerType, additionalTriggerType, matchPattern, livefraction):
103 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 def _getActive(self,triggerType, additionalTriggerType, matchPattern, livefraction):
106 return [x.name
for x
in self.
triggerChains if x.isActive(livefraction)
and x.passType(triggerType, additionalTriggerType)
and re.search(matchPattern, x.name)]
107 def _getInactive(self,triggerType, additionalTriggerType, matchPattern, livefraction):
108 return [x.name
for x
in self.
triggerChains if x.isInactive(livefraction)
and x.passType(triggerType, additionalTriggerType)
and re.search(matchPattern, x.name)]
114 if not (probe1.passType(triggerType, additionalTriggerType)
and re.search(matchPattern, probe1.name)):
continue
117 if not (probe2.passType(triggerType, additionalTriggerType)
and re.search(matchPattern, probe2.name)):
continue
118 if probe1.isUnprescaled()
and not probe2.isUnprescaled()
and probe1.isLowerThan(probe2,self.
period)==1:
119 log.error(f
"Found {probe2.name} that is tighter than Primary {probe1.name}")
120 inconsistent.add(probe2.name)
121 if probe2.isUnprescaled()
and not probe1.isUnprescaled()
and probe2.isLowerThan(probe1,self.
period)==1:
122 log.error(f
"Found {probe1.name} that is tighter than Primary {probe2.name}")
123 inconsistent.add(probe1.name)
129 types = (
'e',
'j',
'mu',
'tau',
'xe',
'g',
'ht')
130 uctTypes = (
'isotrk',
'fslrt',
'dedxtrk',
'hitdvjet',
'fsvsi',
'distrk',
'dispjet',
'dispvtx')
131 legpattern = re.compile(
'([0-9]*)(%s)([0-9]+)(noL1)?' %
'|'.
join(types+uctTypes))
132 detailpattern = re.compile(
r'(?:-?\d+)|(?:[^0-9 -]+)')
133 bjetpattern = re.compile(
'bmv|bhmv|btight|bmedium|bloose|bld1|bgn1|bgn2|bdl1')
134 bphyspattern = re.compile(
'b[A-Z]')
135 exoticspattern = re.compile(
'llp|LLP|muvtx|hiptrt|LATE|NOMATCH|distrk|hitdvjet')
136 afppattern = re.compile(
'afp|AFP')
138 def __init__(self,legname, chainseed, chainname=None):
142 chainseed= chainseed.replace(
"L1_",
"")
143 blocks = legname.split(
"_L1")
145 for token
in blocks[0].
split(
"_"):
148 count,legtype,thr,noL1 = m.groups()
153 else: self.
legtype = TriggerType.el_single
154 elif legtype ==
'mu':
156 else: self.
legtype = TriggerType.mu_single
159 else: self.
legtype = TriggerType.j_single
160 elif legtype ==
'tau':
162 else: self.
legtype = TriggerType.tau_single
165 else: self.
legtype = TriggerType.g_single
166 elif legtype ==
'xe':
168 elif legtype ==
'ht':
171 self.
legtype = TriggerType.exotics
173 details.append(legtype)
175 log.info(
"Unknown trigger type: %s",legtype)
176 if noL1: details.append(noL1)
179 if self.
legtype == TriggerType.j_single: self.
legtype = TriggerType.bj_single
180 if self.
legtype == TriggerType.j_multi: self.
legtype = TriggerType.bj_multi
182 self.
legtype = TriggerType.mu_bphys
184 self.
legtype = TriggerType.exotics
187 details.append(token)
189 for l1seed
in blocks[1:]:
191 self.
legtype = TriggerType.exotics
194 if l1seed == chainseed:
continue
196 assert self.
l1seed==
"", (self.
l1seed, chainseed, chainname, blocks[1:])
202 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)
211 ''' Returns -9 if none of them is lower than the other (e.g. different met flavour).
212 Returns -1 if identical
213 Returns 0 if other is lower than self.
214 Returns 1 if self is lower than other.
217 log.info(
"DEBUG LEGS --------")
218 log.info(f
"{self.legname} {other.legname}")
219 log.info(f
"{self.legtype} {other.legtype}")
220 log.info(f
"{self.l1seed} {other.l1seed}")
221 log.info(f
"{self.details} {other.details}")
222 log.info(f
"{self.thr} {other.thr}")
224 log.info(self.
details == other.details)
225 log.info(
"DEBUG LEGS END --------")
227 if self.
legtype != other.legtype:
return -9
229 if self.
thr < other.thr:
return 1
230 if self.
thr > other.thr:
return 0
238 ''' Returns -9 if none of them is lower than the other (e.g. different met flavour).
239 Returns -1 if identical
240 Returns 0 if other is lower than self.
241 Returns 1 if self is lower than other.
243 from copy
import deepcopy
245 if debug: log.info(f
"compareDetails: {len(self.details)} {len(other.details)} {(self.l1seed == other.l1seed)} {(self.details == other.details)}")
246 if len(self.
details) != len(other.details):
247 if not is2015
and any([x.startswith(
"noL1")
for x
in self.
details]):
248 cloneself = deepcopy(self)
249 cloneself.details = [ x
for x
in self.
details if not x.startswith(
"noL1")]
250 compno = cloneself.compareDetails(other,is2015,debug)
251 if compno ==1
or compno == -1:
253 if not is2015
and any([x.startswith(
"noL1")
for x
in other.details]):
254 cloneother = deepcopy(other)
255 cloneother.details = [ x
for x
in other.details
if not x.startswith(
"noL1")]
257 if compno ==0
or compno == -1:
259 if not is2015
and any([x.startswith(
"nod0")
for x
in self.
details]):
260 cloneself = deepcopy(self)
261 cloneself.details = [ x
for x
in self.
details if not x.startswith(
"nod0")]
262 compno = cloneself.compareDetails(other,is2015,debug)
263 if compno ==1
or compno == -1:
265 if not is2015
and any([x.startswith(
"nod0")
for x
in other.details]):
266 cloneother = deepcopy(other)
267 cloneother.details = [ x
for x
in other.details
if not x.startswith(
"nod0")]
269 if compno ==0
or compno == -1:
271 if any([x.startswith(
"cut")
for x
in self.
details]):
272 cloneself = deepcopy(self)
273 cloneself.details = [ x
for x
in self.
details if not x.startswith(
"cut")]
274 compno = cloneself.compareDetails(other,is2015,debug)
275 if compno ==0
or compno == -1:
277 if any([x.startswith(
"cut")
for x
in other.details]):
278 cloneother = deepcopy(other)
279 cloneother.details = [ x
for x
in other.details
if not x.startswith(
"cut")]
281 if compno ==1
or compno == -1:
284 compl1seed = self.
compareTags(self.
l1seed, other.l1seed, stringSubset=
True, debug=debug)
286 if self.
l1seed == other.l1seed:
287 if self.
details == other.details:
return -1
288 if debug: log.info(f
"compareTags 1: {compdetails}")
291 if self.
details == other.details:
292 if debug: log.info(f
"compareTags 2: {compl1seed}")
295 if compl1seed == compdetails:
299 def compareTags(self, tag1, tag2, stringSubset=False,debug=False):
301 ''' Return -9 for different strings,
302 -1 for identical strings/nums,
303 0/1 for high/low numbers or string subsets
312 if x == y.replace(
"vloose",
"loose"):
return 0
313 if x == y.replace(
"vloose",
"loose").
replace(
"loose",
"medium"):
return 0
314 if x == y.replace(
"vloose",
"loose").
replace(
"loose",
"medium").
replace(
"medium",
"tight"):
return 0
315 if y == x.replace(
"vloose",
"loose"):
return 1
316 if y == x.replace(
"vloose",
"loose").
replace(
"loose",
"medium"):
return 1
317 if y == x.replace(
"vloose",
"loose").
replace(
"loose",
"medium").
replace(
"medium",
"tight"):
return 1
318 l1ThresholdLevels = [
"L",
"M",
"T"]
319 if x
in l1ThresholdLevels
and y
in l1ThresholdLevels:
320 if l1ThresholdLevels.index(x) > l1ThresholdLevels.index(y):
return 0
327 if tag1 == tag2:
return -1
329 inverseCuts = (
"mv2c",
"dr",
"dz",
"dphi",
"dl1d",
"dl1r",
"gn1",
"gn2")
330 for cut
in inverseCuts:
331 tag1 = tag1.replace(cut,cut+
"-")
332 tag2 = tag2.replace(cut,cut+
"-")
334 extra_inverseCuts = (
"b",
"emf",
"bgtwo",
"gntau",
"uht1tau")
337 for s
in tag.split(
" "):
339 if len(l)
and l[0]==
'presel':
340 for i,s
in enumerate(l):
341 for cut
in extra_inverseCuts:
342 if s==cut: l[i+1] =
"-" + l[i+1]
345 reself = findall(tag1)
346 reother = findall(tag2)
348 if len(reself) != len(reother):
return -9
349 thecomp = [mycomp(a,b)
for a,b
in zip(reself,reother)]
350 if debug: log.info(f
"thecomp: {thecomp} {reself} {reother}")
351 if any([x == -9
for x
in thecomp]):
return -9
352 if all([x !=0
for x
in thecomp])
and any([x == 1
for x
in thecomp]):
return 1
353 if all([x !=1
for x
in thecomp])
and any([x == 0
for x
in thecomp]):
return 0
359 name = name.replace(
"HLT_",
"")
360 for token
in name.split(
"_"):
363 legsname.append(token)
365 legsname[-1] +=
"_"+token
369 return [
TriggerLeg(l,l1seed,chainname)
for l
in legsname]
372 l1types = (
'EM',
'J',
'MU',
'TAU',
'XE',
'XS',
'HT',
'eEM',
'eTAU',
'jJ',
'jTAU',
'jXE',
'gXEJWOJ',
'gJ',
'gLJ',
'jEM')
373 l1pattern = re.compile(
'([0-9]*)(%s)([0-9]+)' %
'|'.
join(l1types))
375 def __init__(self,name,l1seed,livefraction,activeLB=1,hasRerun=False, activeLBByRun={}):
378 tmplegs = TriggerLeg.parse_legs(name,l1seed,name)
388 This method is called by the owning TriggerInfo method to adjust the livefractions and activeLB
389 to only the given runs
409 from copy
import deepcopy
411 for triggerType
in TriggerType:
413 if not l.legtype == triggerType:
continue
414 for i
in range(l.count):
417 if tmp.legtype & TriggerType.el_multi:
418 tmp.legtype |= TriggerType.el_single
419 tmp.legtype &= ~TriggerType.el_multi
420 elif tmp.legtype & TriggerType.mu_multi:
421 tmp.legtype |= TriggerType.mu_single
422 tmp.legtype &= ~TriggerType.mu_multi
423 elif tmp.legtype & TriggerType.tau_multi:
424 tmp.legtype |= TriggerType.tau_single
425 tmp.legtype &= ~TriggerType.tau_multi
426 elif tmp.legtype & TriggerType.j_multi:
427 tmp.legtype |= TriggerType.j_single
428 tmp.legtype &= ~TriggerType.j_multi
429 elif tmp.legtype & TriggerType.bj_multi:
430 tmp.legtype |= TriggerType.bj_single
431 tmp.legtype &= ~TriggerType.bj_multi
432 elif tmp.legtype & TriggerType.g_multi:
433 tmp.legtype |= TriggerType.g_single
434 tmp.legtype &= ~TriggerType.g_multi
473 mtype = TriggerType.UNDEFINED
476 if mtype & TriggerType.el
and l.legtype & TriggerType.el:
477 mtype |= TriggerType.el_multi
478 mtype &= ~TriggerType.el_single
479 elif mtype & TriggerType.mu
and l.legtype & TriggerType.mu:
480 mtype |= TriggerType.mu_multi
481 mtype &= ~TriggerType.mu_single
482 elif mtype & TriggerType.tau
and l.legtype & TriggerType.tau:
483 mtype |= TriggerType.tau_multi
484 mtype &= ~TriggerType.tau_single
485 elif mtype & TriggerType.j
and l.legtype & TriggerType.j:
486 mtype |= TriggerType.j_multi
487 mtype &= ~TriggerType.j_single
488 elif mtype & TriggerType.bj
and l.legtype & TriggerType.bj:
489 mtype |= TriggerType.bj_multi
490 mtype &= ~TriggerType.bj_single
491 elif mtype & TriggerType.g
and l.legtype & TriggerType.g:
492 mtype |= TriggerType.g_multi
493 mtype &= ~TriggerType.g_single
494 elif l.legtype & TriggerType.mu_bphys:
495 mtype |= TriggerType.mu_bphys
496 mtype &= ~(TriggerType.mu_single | TriggerType.mu_multi)
497 elif l.legtype & TriggerType.exotics:
498 mtype |= TriggerType.exotics
499 elif l.legtype & TriggerType.afp:
500 mtype = TriggerType.afp
504 l1seed= l1seed.replace(
"L1_",
"")
505 if mtype & TriggerType.exotics
or mtype & TriggerType.afp:
507 for token
in l1seed.split(
"_"):
510 count,legtype,thr = m.groups()
511 count =
int(count)
if count
else 1
512 if 'EM' in legtype
or 'TAU' in legtype:
514 elif 'MU' in legtype:
515 if not mtype & TriggerType.mu_bphys:
516 if count > 1: mtype |= TriggerType.mu_multi
517 elif not mtype & TriggerType.mu_multi: mtype |= TriggerType.mu_single
519 if not mtype & TriggerType.bj
and not mtype & TriggerType.j
and not mtype & TriggerType.tau
and not mtype & TriggerType.ht:
520 if count > 1: mtype |= TriggerType.j_multi
521 elif not mtype & TriggerType.j_multi: mtype |= TriggerType.j_single
522 elif 'XE' in legtype
or 'XS' in legtype:
523 mtype |= TriggerType.xe
524 elif 'HT' in legtype:
525 mtype |= TriggerType.ht
527 log.info(
"Unknown trigger type: %s %s %s %s", legtype, mtype, token, self.
name)
533 return not self.
isActive(livefraction)
541 def passType(self, triggerType, additionalTriggerType):
542 if self.
triggerType == TriggerType.UNDEFINED:
return False
543 if self.
triggerType == TriggerType.ALL:
return True
545 if not match:
return False
549 for t
in additionalTriggerType:
550 match = (tmpType & t)
551 if not match:
return False
552 tmpType = tmpType & ~t
554 if additionalTriggerType!=TriggerType.UNDEFINED:
555 match = (tmpType & additionalTriggerType)
556 if not match:
return False
557 tmpType = tmpType & ~additionalTriggerType
559 return tmpType == TriggerType.UNDEFINED
565 ''' Returns -1 if none of them is a strict subset of the other
566 Returns 0 if the legs in other are a subset of self.
567 Returns 1 if the legs in self are a subset of other.
569 if not self.
legs or not other.legs:
return -1
570 selfcounter = Counter(self.
legs)
571 othercounter = Counter(other.legs)
572 for leg, count
in selfcounter.items():
573 if leg
not in othercounter
or count > othercounter[leg]:
break
575 for leg, count
in othercounter.items():
576 if leg
not in selfcounter
or count > selfcounter[leg]:
break
581 ''' Returns -1 if none of them is lower than the other (e.g. asymmetric dilepton).
582 Returns 0 if other is lower than self.
583 Returns 1 if self is lower than other.
585 is2015 = period & TriggerPeriod.y2015
and not TriggerPeriod.isRunNumber(period)
586 is2015 |= period <= 284484
and TriggerPeriod.isRunNumber(period)
587 if self.
triggerType != other.triggerType:
return -1
588 if len(self.
legs) != len(other.legs):
return -1
592 if debug: log.info(
"DEBUG: %s %s",self.
name,other.name)
593 for selfleg, otherleg
in zip(self.
legs, other.legs):
594 legcomp = selfleg.isLegLowerThan(otherleg, is2015, debug)
595 if debug: log.info(
"DEBUG LEG return: %s", legcomp)
596 if legcomp == -9:
return -1
597 elif legcomp == -1:
continue
598 elif legcomp == 0
and comp == 1:
return -1
599 elif legcomp == 1
and comp == 0:
return -1
600 elif legcomp == 0 : comp = 0
601 elif legcomp == 1 : comp = 1
602 if debug: log.info(
"DEBUG FINAL: %s",comp)
607 a =
TriggerChain(
"HLT_j50_gsc65_bmv2c1040_split_3j50_gsc65_boffperf_split",
"L1J100",1)
609 log.info(
bin(a.getType()))
610 log.info(a.passType(TriggerType.j_multi, TriggerType.UNDEFINED))
611 log.info(a.passType(TriggerType.j_multi | TriggerType.bj_single, TriggerType.UNDEFINED))
612 log.info(a.isUnprescaled())
614 if __name__ ==
"__main__":