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
11 from AthenaCommon.Logging
import logging
12 log = logging.getLogger(__name__)
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
18 def __init__(self,period=0, customGRL=None, release=None, flags=None):
24 if not period
and not customGRL:
return
25 from .TriggerDataAccess
import getHLTlist
27 for hlt, l1, livefraction, activeLB, hasRerun, activeLBByRun
in HLTlist:
40 tc.setRunRange(start,end,totalLB)
43 return f
"<TriggerMenuMT.TriggerAPI.TriggerInfo.TriggerInfo object with {len(self.triggerChains)} triggerChains, period={self.period}, totalLB={self.totalLB}>"
50 from copy
import deepcopy
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
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())
74 from TriggerMenuMT.TriggerAPI.TriggerPeriodData
import TriggerPeriodData
75 return TriggerPeriodData.testCustomGRL(grl)
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)]
84 chainList = [ x
for x
in self.
triggerChains if x.isUnprescaled(livefraction)
and x.passType(triggerType, additionalTriggerType)
and re.search(matchPattern, x.name)]
86 for chain
in chainList:
87 if chain.triggerType
not in typeMap:
88 typeMap[chain.triggerType] = [chain]
91 for other
in typeMap[chain.triggerType][:]:
92 comp = chain.isLowerThan(other,self.
period)
97 if comp == 1: typeMap[chain.triggerType].
remove(other)
99 typeMap[chain.triggerType].
append(chain)
100 return [x.name
for t
in six.itervalues (typeMap)
for x
in t ]
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)}
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)]
115 if not (probe1.passType(triggerType, additionalTriggerType)
and re.search(matchPattern, probe1.name)):
continue
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)
130 types = (
'e',
'j',
'mu',
'tau',
'xe',
'g',
'ht')
131 uctTypes = (
'isotrk',
'fslrt',
'dedxtrk',
'hitdvjet',
'fsvsi',
'distrk',
'dispjet',
'dispvtx')
132 legpattern = re.compile(
'([0-9]*)(%s)([0-9]+)(noL1)?' %
'|'.
join(types+uctTypes))
133 detailpattern = re.compile(
r'(?:-?\d+)|(?:[^0-9 -]+)')
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')
139 def __init__(self,legname, chainseed, chainname=None):
143 chainseed= chainseed.replace(
"L1_",
"")
144 blocks = legname.split(
"_L1")
146 for token
in blocks[0].
split(
"_"):
149 count,legtype,thr,noL1 = m.groups()
154 else: self.
legtype = TriggerType.el_single
155 elif legtype ==
'mu':
157 else: self.
legtype = TriggerType.mu_single
160 else: self.
legtype = TriggerType.j_single
161 elif legtype ==
'tau':
163 else: self.
legtype = TriggerType.tau_single
166 else: self.
legtype = TriggerType.g_single
167 elif legtype ==
'xe':
169 elif legtype ==
'ht':
172 self.
legtype = TriggerType.exotics
174 details.append(legtype)
176 log.info(
"Unknown trigger type: %s",legtype)
177 if noL1: details.append(noL1)
180 if self.
legtype == TriggerType.j_single: self.
legtype = TriggerType.bj_single
181 if self.
legtype == TriggerType.j_multi: self.
legtype = TriggerType.bj_multi
183 self.
legtype = TriggerType.mu_bphys
185 self.
legtype = TriggerType.exotics
188 details.append(token)
190 for l1seed
in blocks[1:]:
192 self.
legtype = TriggerType.exotics
195 if l1seed == chainseed:
continue
197 assert self.
l1seed==
"", (self.
l1seed, chainseed, chainname, blocks[1:])
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)
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.
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}")
225 log.info(self.
details == other.details)
226 log.info(
"DEBUG LEGS END --------")
228 if self.
legtype != other.legtype:
return -9
230 if self.
thr < other.thr:
return 1
231 if self.
thr > other.thr:
return 0
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.
244 from copy
import deepcopy
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:
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")]
258 if compno ==0
or compno == -1:
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:
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")]
270 if compno ==0
or compno == -1:
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:
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")]
282 if compno ==1
or compno == -1:
285 compl1seed = self.
compareTags(self.
l1seed, other.l1seed, stringSubset=
True, 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}")
292 if self.
details == other.details:
293 if debug: log.info(f
"compareTags 2: {compl1seed}")
296 if compl1seed == compdetails:
300 def compareTags(self, tag1, tag2, stringSubset=False,debug=False):
302 ''' Return -9 for different strings,
303 -1 for identical strings/nums,
304 0/1 for high/low numbers or string subsets
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
328 if tag1 == tag2:
return -1
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+
"-")
335 extra_inverseCuts = (
"b",
"emf",
"bgtwo",
"gntau")
338 for s
in tag.split(
" "):
340 if len(l)
and l[0]==
'presel':
341 for i,s
in enumerate(l):
342 for cut
in extra_inverseCuts:
343 if s==cut: l[i+1] =
"-" + l[i+1]
346 reself = findall(tag1)
347 reother = findall(tag2)
349 if len(reself) != len(reother):
return -9
350 thecomp = [mycomp(a,b)
for a,b
in zip(reself,reother)]
351 if debug: log.info(f
"thecomp: {thecomp} {reself} {reother}")
352 if any([x == -9
for x
in thecomp]):
return -9
353 if all([x !=0
for x
in thecomp])
and any([x == 1
for x
in thecomp]):
return 1
354 if all([x !=1
for x
in thecomp])
and any([x == 0
for x
in thecomp]):
return 0
360 name = name.replace(
"HLT_",
"")
361 for token
in name.split(
"_"):
364 legsname.append(token)
366 legsname[-1] +=
"_"+token
370 return [
TriggerLeg(l,l1seed,chainname)
for l
in legsname]
373 l1types = (
'EM',
'J',
'MU',
'TAU',
'XE',
'XS',
'HT',
'eEM',
'eTAU',
'jJ',
'jTAU',
'jXE',
'gXEJWOJ',
'gJ',
'gLJ',
'jEM')
374 l1pattern = re.compile(
'([0-9]*)(%s)([0-9]+)' %
'|'.
join(l1types))
376 def __init__(self,name,l1seed,livefraction,activeLB=1,hasRerun=False, activeLBByRun={}):
379 tmplegs = TriggerLeg.parse_legs(name,l1seed,name)
389 This method is called by the owning TriggerInfo method to adjust the livefractions and activeLB
390 to only the given runs
410 from copy
import deepcopy
412 for triggerType
in TriggerType:
414 if not l.legtype == triggerType:
continue
415 for i
in range(l.count):
418 if tmp.legtype & TriggerType.el_multi:
419 tmp.legtype |= TriggerType.el_single
420 tmp.legtype &= ~TriggerType.el_multi
421 elif tmp.legtype & TriggerType.mu_multi:
422 tmp.legtype |= TriggerType.mu_single
423 tmp.legtype &= ~TriggerType.mu_multi
424 elif tmp.legtype & TriggerType.tau_multi:
425 tmp.legtype |= TriggerType.tau_single
426 tmp.legtype &= ~TriggerType.tau_multi
427 elif tmp.legtype & TriggerType.j_multi:
428 tmp.legtype |= TriggerType.j_single
429 tmp.legtype &= ~TriggerType.j_multi
430 elif tmp.legtype & TriggerType.bj_multi:
431 tmp.legtype |= TriggerType.bj_single
432 tmp.legtype &= ~TriggerType.bj_multi
433 elif tmp.legtype & TriggerType.g_multi:
434 tmp.legtype |= TriggerType.g_single
435 tmp.legtype &= ~TriggerType.g_multi
474 mtype = TriggerType.UNDEFINED
477 if mtype & TriggerType.el
and l.legtype & TriggerType.el:
478 mtype |= TriggerType.el_multi
479 mtype &= ~TriggerType.el_single
480 elif mtype & TriggerType.mu
and l.legtype & TriggerType.mu:
481 mtype |= TriggerType.mu_multi
482 mtype &= ~TriggerType.mu_single
483 elif mtype & TriggerType.tau
and l.legtype & TriggerType.tau:
484 mtype |= TriggerType.tau_multi
485 mtype &= ~TriggerType.tau_single
486 elif mtype & TriggerType.j
and l.legtype & TriggerType.j:
487 mtype |= TriggerType.j_multi
488 mtype &= ~TriggerType.j_single
489 elif mtype & TriggerType.bj
and l.legtype & TriggerType.bj:
490 mtype |= TriggerType.bj_multi
491 mtype &= ~TriggerType.bj_single
492 elif mtype & TriggerType.g
and l.legtype & TriggerType.g:
493 mtype |= TriggerType.g_multi
494 mtype &= ~TriggerType.g_single
495 elif l.legtype & TriggerType.mu_bphys:
496 mtype |= TriggerType.mu_bphys
497 mtype &= ~(TriggerType.mu_single | TriggerType.mu_multi)
498 elif l.legtype & TriggerType.exotics:
499 mtype |= TriggerType.exotics
500 elif l.legtype & TriggerType.afp:
501 mtype = TriggerType.afp
505 l1seed= l1seed.replace(
"L1_",
"")
506 if mtype & TriggerType.exotics
or mtype & TriggerType.afp:
508 for token
in l1seed.split(
"_"):
511 count,legtype,thr = m.groups()
512 count =
int(count)
if count
else 1
513 if 'EM' in legtype
or 'TAU' in legtype:
515 elif 'MU' in legtype:
516 if not mtype & TriggerType.mu_bphys:
517 if count > 1: mtype |= TriggerType.mu_multi
518 elif not mtype & TriggerType.mu_multi: mtype |= TriggerType.mu_single
520 if not mtype & TriggerType.bj
and not mtype & TriggerType.j
and not mtype & TriggerType.tau
and not mtype & TriggerType.ht:
521 if count > 1: mtype |= TriggerType.j_multi
522 elif not mtype & TriggerType.j_multi: mtype |= TriggerType.j_single
523 elif 'XE' in legtype
or 'XS' in legtype:
524 mtype |= TriggerType.xe
525 elif 'HT' in legtype:
526 mtype |= TriggerType.ht
528 log.info(
"Unknown trigger type:",(legtype, mtype, token, self.
name))
534 return not self.
isActive(livefraction)
542 def passType(self, triggerType, additionalTriggerType):
543 if self.
triggerType == TriggerType.UNDEFINED:
return False
544 if self.
triggerType == TriggerType.ALL:
return True
546 if not match:
return False
550 for t
in additionalTriggerType:
551 match = (tmpType & t)
552 if not match:
return False
553 tmpType = tmpType & ~t
555 if additionalTriggerType!=TriggerType.UNDEFINED:
556 match = (tmpType & additionalTriggerType)
557 if not match:
return False
558 tmpType = tmpType & ~additionalTriggerType
560 return tmpType == TriggerType.UNDEFINED
566 ''' Returns -1 if none of them is a strict subset of the other
567 Returns 0 if the legs in other are a subset of self.
568 Returns 1 if the legs in self are a subset of other.
570 if not self.
legs or not other.legs:
return -1
571 selfcounter = Counter(self.
legs)
572 othercounter = Counter(other.legs)
573 for leg, count
in selfcounter.items():
574 if leg
not in othercounter
or count > othercounter[leg]:
break
576 for leg, count
in othercounter.items():
577 if leg
not in selfcounter
or count > selfcounter[leg]:
break
582 ''' Returns -1 if none of them is lower than the other (e.g. asymmetric dilepton).
583 Returns 0 if other is lower than self.
584 Returns 1 if self is lower than other.
586 is2015 = period & TriggerPeriod.y2015
and not TriggerPeriod.isRunNumber(period)
587 is2015 |= period <= 284484
and TriggerPeriod.isRunNumber(period)
588 if self.
triggerType != other.triggerType:
return -1
589 if len(self.
legs) != len(other.legs):
return -1
593 if debug: log.info(
"DEBUG:",self.
name,other.name)
594 for selfleg, otherleg
in zip(self.
legs, other.legs):
595 legcomp = selfleg.isLegLowerThan(otherleg, is2015, debug)
596 if debug: log.info(
"DEBUG LEG return:", legcomp)
597 if legcomp == -9:
return -1
598 elif legcomp == -1:
continue
599 elif legcomp == 0
and comp == 1:
return -1
600 elif legcomp == 1
and comp == 0:
return -1
601 elif legcomp == 0 : comp = 0
602 elif legcomp == 1 : comp = 1
603 if debug: log.info(
"DEBUG FINAL:",comp)
608 a =
TriggerChain(
"HLT_j50_gsc65_bmv2c1040_split_3j50_gsc65_boffperf_split",
"L1J100",1)
610 log.info(
bin(a.getType()))
611 log.info(a.passType(TriggerType.j_multi, TriggerType.UNDEFINED))
612 log.info(a.passType(TriggerType.j_multi | TriggerType.bj_single, TriggerType.UNDEFINED))
613 log.info(a.isUnprescaled())
615 if __name__ ==
"__main__":