3__author__ =
'Javier Montejo'
4__version__=
"$Revision: 2.0 $"
5__doc__=
"Class containing all the information of an HLT chain"
8from TriggerMenuMT.TriggerAPI.TriggerEnums
import TriggerType, TriggerPeriod
9from collections
import Counter
10from AthenaCommon.Logging
import logging
11log = 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:
36 if int(run)<int(start)
or int(run)>int(end):
continue
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()
149 self.
count = int(count)
if count
else 1
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)
285 compdetails = self.
compareTags(
" ".join(self.
details),
" ".join(other.details), 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
400 if int(run)<int(start)
or int(run)>int(end):
continue
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())
614if __name__ ==
"__main__":
isActive(self, livefraction=1e-99)
isInactive(self, livefraction=1e-99)
passType(self, triggerType, additionalTriggerType)
splitAndOrderLegs(self, legs)
getTriggerType(self, legs, l1seed)
__init__(self, name, l1seed, livefraction, activeLB=1, hasRerun=False, activeLBByRun={})
setRunRange(self, start, end, totalLB)
isUnprescaled(self, livefraction=1.0)
isLowerThan(self, other, period=TriggerPeriod.future)
_getLowestUnprescaled(self, triggerType, additionalTriggerType, matchPattern, livefraction=1.0)
_getInactive(self, triggerType, additionalTriggerType, matchPattern, livefraction)
setRunRange(self, start=0, end=999999)
_getActive(self, triggerType, additionalTriggerType, matchPattern, livefraction)
_checkPeriodConsistency(self, triggerType, additionalTriggerType, matchPattern)
_getUnprescaled(self, triggerType, additionalTriggerType, matchPattern, livefraction=1.0)
_getAllHLT(self, triggerType, additionalTriggerType, matchPattern, livefraction)
__init__(self, period=0, customGRL=None, release=None, flags=None)
__init__(self, legname, chainseed, chainname=None)
isLegLowerThan(self, other, is2015, debug=False)
compareTags(self, tag1, tag2, stringSubset=False, debug=False)
parse_legs(cls, name, l1seed, chainname)
compareDetails(self, other, is2015, debug=False)
std::string replace(std::string s, const std::string &s2, const std::string &s3)
void search(TDirectory *td, const std::string &s, std::string cwd, node *n)
recursive directory search for TH1 and TH2 and TProfiles
std::vector< std::string > split(const std::string &s, const std::string &t=":")
bool match(std::string s1, std::string s2)
match the individual directories of two strings