ATLAS Offline Software
Loading...
Searching...
No Matches
DictFromChainName Namespace Reference

Functions

 getOverallL1item (flags, chainName)
 getL1item (flags, chainName)
 getAllThresholdsFromItem (item)
 getUniqueThresholdsFromItem (item)
 getEBPartFromParts (chainName, chainParts)
 getChainThresholdFromName (chainParts, signature)
 getChainMultFromDict (chainDict)
 verifyExplicitL1Thresholds (chainname, chainparts, L1thresholds)
 unifyJetRecoParts (chainParts)
 analyseChainName (chainName, L1thresholds, L1item)
 flattenChainGroups (A)
 checkChainStream (myStream)
 dictFromChainName (flags, chainInfo)
 main ()

Variables

str __author__ = 'Catrin Bernius'
str __version__ = ""
str __doc__ = "Decoding of chain name into a dictionary"
 log = logging.getLogger( __name__ )
 matchL1 = re.compile('L1([a-zA-Z0-9]+)(_.*)?')

Detailed Description

Class to obtain the chain configuration dictionary from the short or long name

Authors of original code in TriggerMenu: Joerg Stelzer, Moritz Backes, Catrin Bernius

Function Documentation

◆ analyseChainName()

DictFromChainName.analyseChainName ( chainName,
L1thresholds,
L1item )
Function to obtain the chain configuration dictionary from the short name by parsing its
components and finding the corresponding properties which are defined in SignatureDicts.
The naming convention is defined in https://twiki.cern.ch/twiki/bin/view/Atlas/TriggerNamingRun2
and https://twiki.cern.ch/twiki/bin/view/Atlas/TriggerNamingRun3

Definition at line 201 of file DictFromChainName.py.

201def analyseChainName(chainName, L1thresholds, L1item):
202 """
203 Function to obtain the chain configuration dictionary from the short name by parsing its
204 components and finding the corresponding properties which are defined in SignatureDicts.
205 The naming convention is defined in https://twiki.cern.ch/twiki/bin/view/Atlas/TriggerNamingRun2
206 and https://twiki.cern.ch/twiki/bin/view/Atlas/TriggerNamingRun3
207 """
208
209 # ---- dictionary with all chain properties ----
210 from TriggerMenuMT.HLT.Menu.SignatureDicts import ChainDictTemplate
211 from TriggerMenuMT.HLT.Menu.SignatureDicts import getSignatureInformation
212 from TriggerMenuMT.HLT.Jet.JetRecoCommon import etaRangeAbbrev
213 genchainDict = deepcopy(ChainDictTemplate)
214 genchainDict['chainName'] = chainName
215
216 # ---- remove the L1 item from the name ----
217 hltChainName = chainName.rsplit("_L1",1)[0]
218
219 # ---- check for HLT_HLT in name ---
220 if 'HLT_HLT' in hltChainName:
221 log.error("%s is incorrect, please fix the HLT_HLT part", hltChainName)
222 raise RuntimeError("[analyseChainName] chain name contains HLT_HLT, please fix in corresponding menu where this chain is included")
223
224 # ---- specific chain part information ----
225 allChainProperties=[]
226 cparts = hltChainName.split("_")
227 if 'HLT' in hltChainName:
228 cparts.remove('HLT')
229
230 # ---- handle EB directive ----
231 genchainDict['eventBuildType'] = getEBPartFromParts( chainName, cparts )
232 if genchainDict['eventBuildType']:
233 cparts.remove( genchainDict['eventBuildType'] )
234
235 hltChainNameShort = '_'.join(cparts)
236
237 # ---- identify the topo algorithm and add to genchainDict -----
238 from TriggerMenuMT.HLT.Menu.SignatureDicts import AllowedTopos, AllowedTopos_comb, AllowedTopos_Bphysics_topoVariant, AllowedTopos_Bphysics_topoExtra
239 topo = ''
240 topos=[]
241 extraComboHypos = []
242 bphys_topoVariant=[]
243 bphys_topoExtra = []
244 bphysTopos = False
245 toposIndexed={}
246 topoindex = -5
247 for cindex, cpart in enumerate(cparts):
248 #should make this if...elif...?
249 if cpart in AllowedTopos:
250 log.debug('" %s" is in this part of the name %s -> topo alg', AllowedTopos, cpart)
251 topo = cpart
252 topoindex = cindex
253 toposIndexed.update({topo : topoindex})
254 hltChainNameShort=hltChainNameShort.replace('_'+cpart, '')
255 topos.append(topo)
256 elif cpart in AllowedTopos_Bphysics_topoVariant:
257 log.debug('[analyseChainName] chain part %s is a BLS topo variant, adding to bphys_topoVariant', cpart)
258 bphys_topoVariant.append(cpart)
259 toposIndexed.update({cpart : cindex})
260 bphysTopos = True
261 elif cpart in AllowedTopos_Bphysics_topoExtra:
262 log.debug('[analyseChainName] chain part %s is a BLS extra topo hypo, adding to bphys_topoExtra', cpart)
263 bphys_topoExtra.append(cpart)
264 toposIndexed.update({cpart : cindex})
265 bphysTopos = True
266 else:
267 log.debug('[analyseChainName] chain part %s is not a general topo, BLS extra or variant topo hypo, checking comb topos next', cpart)
268 if cpart in AllowedTopos_comb:
269 log.debug('[analyseChainName] chain part %s is a combined topo hypo, adding to extraComboHypo', cpart)
270 toposIndexed.update({cpart : cindex})
271 extraComboHypos.append(cpart)
272
273 genchainDict['topo'] = topos
274 genchainDict['extraComboHypos'] = extraComboHypos
275
276 if bphysTopos is True:
277 genchainDict['topoVariant'] = bphys_topoVariant
278 genchainDict['topoExtra'] = bphys_topoExtra
279
280 # remove the parts that have been already identified
281 for t, i in enumerate(toposIndexed):
282 if (t in cparts):
283 log.debug('topo %s with index %s is going to be deleted from chain parts', t, i)
284 del cparts[i]
285
286
287 # ---- Find the signature defining patterns ----
288 # ---- and write them out in dictionary ----
289 # ---- expected format: <Multiplicity(int)><TriggerType(str)>
290 # <Threshold(int)><isolation,...(str|str+int)> ----
291 # EXCEPT FOR CHAINS ...
292 from TriggerMenuMT.HLT.Menu.SignatureDicts import getBasePattern
293 pattern = getBasePattern()
294 mdicts=[]
295 multichainindex=[]
296
297
298 # ---- obtain dictionary parts for signature defining patterns ----
299 from TriggerMenuMT.HLT.Menu.SignatureDicts import getSignatureNameFromToken, AllowedCosmicChainIdentifiers, \
300 AllowedCalibChainIdentifiers, AllowedMonitorChainIdentifiers, AllowedBeamspotChainIdentifiers
301
302 from TriggerMenuMT.HLT.Config.Utility.MenuAlignmentTools import get_alignment_group_from_pattern as getAlignmentGroupFromPattern
303
304 def buildDict(signature, sigToken ):
305 groupdict = {'signature': signature, 'threshold': '', 'multiplicity': '',
306 'trigType': sigToken, 'extra': ''}
307 mdicts.append( groupdict )
308
309 for cpart in cparts:
310
311 log.debug("Looping over chain part: %s", cpart)
312 m = pattern.match(cpart)
313
314 if m:
315 log.debug("Pattern found in this string: %s", cpart)
316 groupdict = m.groupdict()
317
318 multiChainIndices = [i for i in range(len(hltChainNameShort)) if ( hltChainNameShort.startswith(cpart, i) ) ]
319 log.debug("MultiChainIndices: %s", multiChainIndices)
320 for theMultiChainIndex in multiChainIndices:
321 # this check is necessary for the bjet chains, example: j45_bloose_3j45
322 # j45 would be found in [0, 13], and 3j45 in [12]
323 # so need to make sure the multiplicities are considered here!
324 if (theMultiChainIndex != 0) & (hltChainNameShort[theMultiChainIndex-1] != '_'):
325 continue
326
327 if theMultiChainIndex not in multichainindex:
328 multichainindex.append(theMultiChainIndex)
329
330 log.debug("HLTChainName: %s", hltChainName)
331 log.debug("HLTChainNameShort: %s", hltChainNameShort)
332 log.debug("cpart: %s", cpart)
333 log.debug("groupdict: %s", groupdict)
334 log.debug("multichainindex: %s", multichainindex)
335
336 sName = getSignatureNameFromToken(cpart)
337
338 groupdict['signature'] = sName
339 log.debug("groupdict['signature']: %s",groupdict['signature'])
340
341 mdicts.append(groupdict)
342
343 elif cpart =='noalg':
344 multichainindex.append(hltChainNameShort.index(cpart))
345 buildDict( 'Streaming', 'streamer')
346 break # stop loop here so that further parts like noalg_idmon are discarded, this allows have copies with different output streams and prescales. Caveat: all noalg chains go into the Streaming slice
347 elif cpart =='acceptedevts':
348 multichainindex.append(hltChainNameShort.index(cpart))
349 buildDict( 'Calib', 'calib')
350 break # stop loop here so that further parts like acceptedevts_larnoiseburst are discarded. They are only used to define different prescales
351 else:
352 for chainCategory in [(['mb'], 'MinBias', 'mb'),
353 (['hi'], 'HeavyIon', 'mb'),
354 (AllowedCosmicChainIdentifiers, 'Cosmic', 'cosmic'),
355 (AllowedCalibChainIdentifiers, 'Calib', 'calib'),
356 (AllowedMonitorChainIdentifiers, 'Monitor', 'calib'),
357 (AllowedBeamspotChainIdentifiers, 'Beamspot', 'beamspot'),
358 (['eb'], 'EnhancedBias', 'eb')]:
359 if cpart in chainCategory[0]:
360 log.debug('Doing chain type %s', chainCategory[1])
361 multichainindex.append(hltChainNameShort.index(cpart))
362 buildDict(chainCategory[1], chainCategory[2])
363
364
365 # If multiple parts exist, split the string and analyse each
366 # part depending on the signature it belongs to
367 multichainparts=[]
368 multichainindex = sorted(multichainindex, key=int)
369 cN = deepcopy(hltChainNameShort)
370 for i in reversed(multichainindex):
371 if i!=0:
372 log.debug('Appending to multichainparts (i!=0): %s', hltChainNameShort[i:len(cN)])
373
374 multichainparts.append(hltChainNameShort[i:len(cN)])
375 cN = cN[0:i-1]
376 else:
377 log.debug('Appending to multichainparts: %s', hltChainNameShort[i:len(cN)])
378 multichainparts.append(cN)
379 log.debug("multichainparts: %s",multichainparts)
380
381 # build the chainProperties dictionary for each part of the chain
382 # add it to a allChainProperties
383 multichainparts.reverse()
384 log.debug('multichainparts after reverse: %s', multichainparts)
385
386 # verify if the L1 setup is consistent with the chain
387 # sizes of seeds matter
388 if len(L1thresholds) != 0:
389 assert len(L1thresholds) == len(multichainparts), 'ERROR IN CHAIN {} definition, l1 thresholds specified {} have different length than chain parts {}'\
390 .format(chainName, str(L1thresholds), str(multichainparts) )
391
392 # tmp removed this check since the L1seeds depend on sym or asym cases
393 # if len(L1thresholds) == 0:
394 # getAllThresholdsFromItem, getUniqueThresholdsFromItem
395 # assert len( getAllThresholdsFromItem( L1item )) == len(multichainparts), 'ERROR IN CHAIN {} definition, l1 thresholds extracted from the L1 item name {} have different length than chain parts {}, set L1 thresholds ChainProp'\
396 # .format( chainName, str( getAllThresholdsFromItem( L1item ) ), str(multichainparts))
397
398 # check the case when _L1 appears more than once in the name
399 if chainName.count("_L1") > 1:
400 verifyExplicitL1Thresholds(chainName,multichainparts,L1thresholds)
401
402 for chainindex, chainparts in enumerate(multichainparts):
403 chainProperties = {} #will contain properties for one part of chain if multiple parts
404 chainpartsNoL1 = chainparts.rsplit('_L1',1)[0] if 'L1' in chainparts else chainparts
405
406 if len(L1thresholds) != 0:
407 chainProperties['L1threshold'] = L1thresholds[chainindex]
408 else:
409 __th = getAllThresholdsFromItem ( L1item )
410 assert chainindex < len(__th), "In defintion of the chain {chainName} there is not enough thresholds to be used, index: {chainindex} >= number of thresholds, thresholds are: {__th}"
411 chainProperties['L1threshold'] = __th[chainindex] #replced getUniqueThresholdsFromItem
412
413 parts=chainpartsNoL1.split('_')
414 log.debug("[analyseChainName] chain parts w/o L1 are %s", parts)
415 if None in parts:
416 log.error("[analyseChainName] chainpartsNoL1 -> parts: %s -> %s", chainpartsNoL1, parts)
417 raise Exception("[analyseChainName] parts contains None, please identify how this is happening")
418 parts=list(filter(None,parts))
419 log.debug("[analyseChainName] chainpartsNoL1 %s, parts %s", chainpartsNoL1, parts)
420
421 # --- check for duplicate strings in chain part name ---
422 duplicateParts = ([item for item, count in collections.Counter(parts).items() if count > 1])
423 log.debug("[analyseChainName] chainpartsNoL1 %s contains duplicate strings %s", chainpartsNoL1, duplicateParts)
424 if duplicateParts:
425 log.error("[analyseChainName] chain %s has duplicate strings %s, please fix!!", chainName, duplicateParts)
426 raise RuntimeError("[analyseChainName] Check the chain name, there are duplicate configurations: %s", duplicateParts)
427
428 chainProperties['trigType']=mdicts[chainindex]['trigType']
429 if 'extra' in chainProperties:
430 raise RuntimeError("[analyseChainName] Overwrote 'extra' value, only one supported!")
431 else:
432 chainProperties['extra']=mdicts[chainindex]['extra']
433 multiplicity = mdicts[chainindex]['multiplicity'] if not mdicts[chainindex]['multiplicity'] == '' else '1'
434 chainProperties['multiplicity'] = multiplicity
435 chainProperties['threshold']=mdicts[chainindex]['threshold']
436 chainProperties['signature']=mdicts[chainindex]['signature']
437
438 # if we have a L1 topo in a multi-chain then we want to remove it from the chain name
439 # but only if it's the same as the L1item_main; otherwise it belongs to chain part and we q
440 # have to keep it in the name
441 chainProperties['chainPartName'] = chainparts
442 if ('-' in L1item) and (len(multichainparts) > 1):
443 chainProperties['chainPartName'] = chainpartsNoL1
444
445 if len(multichainparts) > 1 and L1item.count("_") > 1 :
446 chainProperties['chainPartName'] = chainpartsNoL1
447
448 log.debug('[analyseChainname] Chainparts: %s', chainparts)
449 if (chainProperties['signature'] != 'Cosmic') \
450 & (chainProperties['signature'] != 'Calib')\
451 & (chainProperties['signature'] != 'Streaming') \
452 & (chainProperties['signature'] != 'Beamspot') \
453 & (chainProperties['signature'] != 'Monitor') :
454 parts.pop(0)
455
456
457 #---- Check if topo is a bphysics topo -> change signature ----
458 from TriggerMenuMT.HLT.Menu.SignatureDicts import AllAllowedTopos_Bphysics
459 for t in genchainDict['topo']:
460 if (t in AllAllowedTopos_Bphysics):
461 chainProperties['signature'] = 'Bphysics'
462 if "tnpInfo" in chainProperties.keys() and chainProperties['tnpInfo'] != "":
463 chainProperties['alignmentGroup'] = getAlignmentGroupFromPattern('Bphysics',chainProperties['tnpInfo'])
464 else:
465 chainProperties['alignmentGroup'] = getAlignmentGroupFromPattern('Bphysics',chainProperties['extra'])
466
467 # ---- import the relevant dictionaries for each part of the chain ----
468 SignatureDefaultValues, allowedSignaturePropertiesAndValues = getSignatureInformation(chainProperties['signature'])
469 log.debug('SignatureDefaultValues: %s', SignatureDefaultValues)
470 allDefaults = list(SignatureDefaultValues.values())
471 log.debug('All default values in a list')
472
473 # ---- update chain properties with default properties ----
474 result = deepcopy(SignatureDefaultValues)
475 result.update(chainProperties)
476 chainProperties = result
477
478 # ---- check that all parts to be matched are not specified as defaults already ----
479 overlaps = [x for x in parts if x in allDefaults]
480 log.debug("parts that are also in defaults: %s ", overlaps)
481
482 # Suppress the warning until we fully decomission the old DeepSet tau triggers in a couple of months
483 if overlaps == ['tracktwoMVA']: overlaps = []
484
485 if overlaps:
486 #log.error("[analyseChainName] The following string(s) is/are already defined as defaults, please remove: %s", overlaps)
487 #raise RuntimeError("[analyseChainname] Default config appearing in chain name, please remove: %s", overlaps)
488 log.warning("[analyseChainName] The following chainpart %s contains the string(s) %s which is/are already defined as defaults, please remove!", chainparts, overlaps)
489
490 # ---- check remaining parts for complete matches in allowedPropertiesAndValues Dict ----
491 # ---- unmatched = list of tokens that are not found in the allowed values as a whole ----
492 matchedparts = []
493 log.debug("[analyseChainname] parts to match are %s", parts)
494 for pindex, part in enumerate(parts):
495 for prop, allowedValues in allowedSignaturePropertiesAndValues.items():
496 if part in allowedValues:
497 if type(chainProperties[prop]) is list:
498 chainProperties[prop] += [part]
499 else:
500 chainProperties[prop] = part
501 matchedparts.append(part)
502
503 # Jet-specific operations
504 if chainProperties['signature']=='Jet':
505
506 # ----- at this point we can figure out if the chain is a bJet chain and update defaults accordingly
507 if chainProperties['bTag'] != '':
508 log.debug('Setting b-jet chain defaults')
509 # b-jet chain, so we now use the bJet defaults if they have not already been overriden
510 bJetDefaultValues, allowedbJetPropertiesAndValues = getSignatureInformation('Bjet')
511 for prop, value in bJetDefaultValues.items():
512 propSet=False
513 for value in allowedbJetPropertiesAndValues[prop]:
514 if value in matchedparts:
515 propSet=True
516 break
517
518 # if the property was not set already, then set if according to the b-jet defaults
519 if propSet is False:
520 log.debug('Changing %s from %s to %s', prop, str(chainProperties[prop]), str(bJetDefaultValues[prop]))
521 chainProperties[prop] = bJetDefaultValues[prop]
522
523
524 if chainProperties['ditauTag'] != '':
525 log.debug('Setting Ditau chain defaults')
526 # boosted ditau chain, so we now use the ditau defaults if they have not already been overriden
527 ditauJetDefaultValues, allowedDitauJetPropertiesAndValues = getSignatureInformation('Ditau')
528 for prop, value in ditauJetDefaultValues.items():
529 propSet=False
530 for value in allowedDitauJetPropertiesAndValues[prop]:
531 if value in matchedparts:
532 propSet=True
533 break
534
535 # if the property was not set already, then set if according to the ditau defaults
536 if propSet is False:
537 log.debug('Changing %s from %s to %s', prop, str(chainProperties[prop]), str(ditauJetDefaultValues[prop]))
538 chainProperties[prop] = ditauJetDefaultValues[prop]
539
540
541 if chainProperties['signature'] == 'Jet' and chainProperties['beamspotChain'] != '':
542 log.debug('Setting beamspot chain defaults')
543 BeamspotDefaultValues, allowedBeamspotPropertiesAndValues = getSignatureInformation('Beamspot_Jet')
544
545 for prop, value in BeamspotDefaultValues.items():
546 propSet=False
547 for value in allowedBeamspotPropertiesAndValues[prop]:
548 if value in matchedparts:
549 propSet=True
550 break
551
552 # if the property was not set already, then set if according to the b-jet defaults
553 if propSet is False:
554 log.debug('Changing %s from %s to %s', prop, str(chainProperties[prop]), str(BeamspotDefaultValues[prop]))
555 chainProperties[prop] = BeamspotDefaultValues[prop]
556
557
558 # Substitute after b-jet defaults have been set otherwise they will be overridden
559 if chainProperties['extra']:
560 # Atypical handling here: jets translate the 1 char suffix to an eta range
561 try:
562 etarange = etaRangeAbbrev[chainProperties['extra']]
563 chainProperties['etaRange'] = etarange
564 except KeyError:
565 raise RuntimeError(f"Invalid jet 'extra' value {chainProperties['extra']} in {chainProperties['chainPartName']}. Only [a,c,f] allowed")
566
567 # ---- checking the parts that haven't been matched yet ----
568 log.debug("matched parts %s", matchedparts)
569 leftoverparts = set(parts)-set(matchedparts)
570 log.debug('leftoverparts %s', leftoverparts)
571 for pindex, part in enumerate(leftoverparts):
572 for prop, allowedValues in allowedSignaturePropertiesAndValues.items():
573 if prop in chainProperties.keys():
574 continue
575 for aV in allowedValues:
576 if (aV in part):
577 if (chainProperties['signature'] in ['Egamma', 'Muon'] )& (prop in ['trkInfo','hypoInfo']):
578 chainProperties[prop] = part
579 part = part.replace(part,'')
580 else:
581 chainProperties[prop] = aV
582 part = part.replace(aV,'')
583 break # done with allowed values for that property
584
585 assert len(part.split()) == 0, "These parts of the chain name {} are not understood: {}".format(chainpartsNoL1,part)
586
587
588 # ---- remove properties that aren't allowed in the chain properties for a given siganture ----
589 forbiddenProperties = set(chainProperties.keys()) - set(allowedSignaturePropertiesAndValues.keys())
590 log.debug('chainProperties: %s', sorted(set(chainProperties.keys())))
591 log.debug('allowedSignaturePropertiesAndValues: %s', sorted(set(allowedSignaturePropertiesAndValues.keys())))
592 for fb in forbiddenProperties:
593 forbiddenValue = chainProperties.pop(fb)
594 assert forbiddenValue == '', "Property {} not allowed for signature '{}', but specified '{}'".format (fb, chainProperties['signature'], forbiddenValue)
595
596 # ---- set the alignment group here, once we have fully worked out the properties ----
597 # ---- this is for the benefit of the probe leg in T&P chains ----
598
599 if any(x in chainName for x in ('larnoiseburst', 'idcalib', 'metcalo', 'mettrk')):
600 chainProperties['alignmentGroup'] = 'JetMET'
601 else:
602 if 'tnpInfo' in chainProperties.keys() and chainProperties['tnpInfo'] != "":
603 chainProperties['alignmentGroup'] = getAlignmentGroupFromPattern(mdicts[chainindex]['signature'],chainProperties['tnpInfo'])
604 else:
605 chainProperties['alignmentGroup'] = getAlignmentGroupFromPattern(mdicts[chainindex]['signature'],chainProperties['extra'])
606
607 # ---- the info of the general and the specific chain parts dict ----
608 allChainProperties.append(chainProperties)
609
610 # ---- depending on if signatures are different in this chain, break up the chainProperties dictionary ----
611 # ---- finally also taking care of the signature key ----
612 genchainDict['chainParts'] = allChainProperties
613 for cPart in allChainProperties:
614 if cPart['signature'] == 'Jet' and cPart['bTag'] != '':
615 cPart['signature'] = 'Bjet'
616 if 'tnpInfo' in cPart.keys() and cPart['tnpInfo'] != "":
617 cPart['alignmentGroup'] = getAlignmentGroupFromPattern('Bjet', cPart['tnpInfo'])
618 else:
619 cPart['alignmentGroup'] = getAlignmentGroupFromPattern('Bjet', cPart['extra'])
620 if cPart['signature'] == 'Jet' and cPart['ditauTag'] != '':
621 cPart['signature'] = 'Tau'
622 if 'tnpInfo' in cPart.keys() and cPart['tnpInfo'] != "":
623 cPart['alignmentGroup'] = getAlignmentGroupFromPattern('Tau', cPart['tnpInfo'])
624 else:
625 cPart['alignmentGroup'] = getAlignmentGroupFromPattern('Tau', cPart['extra'])
626 genchainDict['signatures'] += [cPart['signature']]
627 genchainDict['alignmentGroups'] += [cPart['alignmentGroup']]
628
629 # Postprocess chains with multiple jet chainParts
630 # to set them consistently from only one specification
631 if len(genchainDict['chainParts'])>1:
632 if 'Jet' in genchainDict['signatures'] or 'Bjet' in genchainDict['signatures']:
633 genchainDict['chainParts'] = unifyJetRecoParts(genchainDict['chainParts'])
634
635 #genchainDict['signature'] = allChainProperties[0]['signature']
636 return genchainDict
637
638
STL class.

◆ checkChainStream()

DictFromChainName.checkChainStream ( myStream)

Definition at line 646 of file DictFromChainName.py.

646def checkChainStream(myStream):
647 if len(myStream) == 1:
648 if myStream[0] == 'express':
649 return False
650 return True
651

◆ dictFromChainName()

DictFromChainName.dictFromChainName ( flags,
chainInfo )
Transforms ChainProp into the ChainDict

The logic:
---- Loop over all chains (keys) in dictionary ----
---- Then complete the dict with other info    ----
Default input format will be a ChainProp object:
ChainProp(name: str, groups: list[str], l1SeedThresholds: list[str] = [], stream: list[str] = ['Main'], 
            monGroups: list[str] = [], mergingStrategy: str = 'auto', mergingOrder: list[str] = [], mergingOffset: int = -1),
but for nwo plain chain name is also supported

Definition at line 652 of file DictFromChainName.py.

652def dictFromChainName(flags, chainInfo):
653 """
654 Transforms ChainProp into the ChainDict
655
656 The logic:
657 ---- Loop over all chains (keys) in dictionary ----
658 ---- Then complete the dict with other info ----
659 Default input format will be a ChainProp object:
660 ChainProp(name: str, groups: list[str], l1SeedThresholds: list[str] = [], stream: list[str] = ['Main'],
661 monGroups: list[str] = [], mergingStrategy: str = 'auto', mergingOrder: list[str] = [], mergingOffset: int = -1),
662 but for nwo plain chain name is also supported
663 """
664
665 # these if/elif/else statements are due to temporary development
666 if type(chainInfo) is str:
667 chainName = chainInfo
668 l1Thresholds = []
669 stream = ''
670 groups = []
671 mergingStrategy = 'parallel'
672 mergingOffset = -1
673 mergingOrder = []
674 monGroups = []
675
676 elif 'ChainProp' in str(type(chainInfo)):
677 #this is how we define chains in the menu - the normal behaviour of this function
678 chainName = chainInfo.name
679 l1Thresholds = chainInfo.l1SeedThresholds
680 stream = chainInfo.stream
681 groups = flattenChainGroups(chainInfo.groups)
682 mergingStrategy = chainInfo.mergingStrategy
683 mergingOffset = chainInfo.mergingOffset
684 mergingOrder = chainInfo.mergingOrder
685 monGroups = chainInfo.monGroups
686
687 else:
688 raise RuntimeError("Format of chainInfo passed to genChainDict not known")
689
690 #check here the content of the stream
691 if not checkChainStream(stream):
692 raise RuntimeError("Chain {}, format of chainInfo:stream {} is not valid".format(chainName, stream))
693
694 L1item = getL1item(flags, chainName)
695
696 log.debug("Analysing chain with name: %s", chainName)
697 chainDict = analyseChainName(chainName, l1Thresholds, L1item)
698 log.debug('ChainProperties: %s', chainDict)
699
700 for chainPart in chainDict['chainParts']:
701 # fill the sigFolder and subSigs folder
702 for sf in chainPart['sigFolder']:
703 if sf in chainDict['sigDicts']:
704 chainDict['sigDicts'][sf].extend(chainPart['subSigs'])
705 else:
706 chainDict['sigDicts'].update({sf:chainPart['subSigs']})
707 if sf == 'Bjet' or 'Ditau' in chainPart['subSigs']:
708 if 'Jet' not in chainDict['sigDicts']:
709 chainDict['sigDicts'].update({'Jet':['Jet']})
710
711
712 thisSignature = chainPart['signature']
713 thisSubSigs = chainPart['subSigs']
714 thisAlignGroup = chainPart['alignmentGroup']
715 thisExtra = chainPart['extra']
716 thisL1 = chainPart['L1threshold']
717 thisChainPartName = chainPart['chainPartName']
718
719 if thisSignature in ['Muon','Bphysics']:
720 if 'MuonnoL1' in thisAlignGroup or 'lateMu' in thisExtra:
721 if 'FSNOSEED' not in thisL1:
722 log.error("Muon noL1 and lateMu chain should be seeded from FSNOSEED. Check %s seeded from %s (defined L1: %s), signature %s",chainDict['chainName'],thisL1,l1Thresholds,thisSignature)
723 else:
724 if 'MU' not in thisL1:
725 log.error("Standard muon and Bphysics chain should be seeded from L1_MU. Check %s seeded from %s (defined L1: %s), signature %s",chainDict['chainName'],thisL1,l1Thresholds,thisSignature)
726 #incorrectL1=True
727
728 if thisSignature in ['Electron','Photon'] and not ('UPC' in stream): # don't apply for HI UPC chains
729 if 'EM' not in thisL1 and 'BKee' not in thisL1 and 'All' not in thisL1:
730 log.error("Standard egamma chains should be seeded from L1_EM. Check %s seeded from %s (defined L1: %s), signature %s",chainDict['chainName'],thisL1,l1Thresholds,thisSignature)
731 #incorrectL1=True
732
733 if thisSignature in ['Tau'] and 'Ditau' not in thisSubSigs:
734 if 'TAU' not in thisL1:
735 log.error("Standard tau chains should be seeded from L1_TAU. Check %s seeded from %s (defined L1: %s), signature %s",chainDict['chainName'],thisL1,l1Thresholds,thisSignature)
736 #incorrectL1=True
737
738 if thisSignature in ['Jet','Bjet','MET','UnconventionalTracking'] or (thisSignature =='Tau' and 'Ditau' in thisSubSigs):
739 if 'FSNOSEED' not in thisL1:
740 log.error("Jet, b-jet, MET and Tau:Ditau chains should be seeded from FSNOSEED. Check %s seeded from %s (defined L1: %s), signature %s",chainDict['chainName'],thisL1,l1Thresholds,thisSignature)
741 #incorrectL1=True
742
743 if thisChainPartName in ['noalg']:
744 # All streamers should be unseeded except RoI-based PEB streamers which need a real RoI for PEB
745 if 'FSNOSEED' not in thisL1 and not isRoIBasedPEB(chainDict['eventBuildType']):
746 log.error("noalg chains should be seeded from FSNOSEED. Check %s seeded from %s (defined L1: %s), signature %s",chainDict['chainName'],thisL1,l1Thresholds,thisSignature)
747 #incorrectL1=True
748
749# if incorrectL1 is True:
750# raise Exception("You are using incorrect L1 seed, please check for ERROR messages...")
751
752
753 log.debug('Parts: signature %s, align %s, extra %s, L1 %s', thisSignature, thisAlignGroup, thisExtra, thisL1)
754
755
756
757 # setting the L1 item
758 chainDict['L1item'] = L1item
759 chainDict['stream'] = stream
760 chainDict['groups'] = groups
761 chainDict['mergingStrategy'] = mergingStrategy
762 chainDict['mergingOffset'] = mergingOffset
763 chainDict['mergingOrder'] = mergingOrder
764 chainDict['monGroups'] = monGroups
765 chainDict['chainNameHash'] = string2hash(chainDict['chainName'])
766
767
768 allChainMultiplicities = getChainMultFromDict(chainDict)
769 chainDict['chainMultiplicities'] = allChainMultiplicities
770 log.debug('Setting chain multiplicities: %s ', allChainMultiplicities)
771
772
776
777 return chainDict
778

◆ flattenChainGroups()

DictFromChainName.flattenChainGroups ( A)

Definition at line 639 of file DictFromChainName.py.

639def flattenChainGroups(A):
640 rt = []
641 for i in A:
642 if isinstance(i,list): rt.extend(flattenChainGroups(i))
643 else: rt.append(i)
644 return rt
645

◆ getAllThresholdsFromItem()

DictFromChainName.getAllThresholdsFromItem ( item)
Breaks the item name into parts separated by the _ and from each element extract the threshold name

Fails when used on topo items or ill formatted items
Examples: L1_MU4 returns [MU4]
L1_2MU4 returns [MU4, MU4]
L1_MU4_MU6 returns [MU4, MU6]

Definition at line 58 of file DictFromChainName.py.

58def getAllThresholdsFromItem(item):
59 """
60 Breaks the item name into parts separated by the _ and from each element extract the threshold name
61
62 Fails when used on topo items or ill formatted items
63 Examples: L1_MU4 returns [MU4]
64 L1_2MU4 returns [MU4, MU4]
65 L1_MU4_MU6 returns [MU4, MU6]
66 """
67 assert item.startswith("L1_"), "The L1 item {} name does not start with L1".format( item )
68 assert "-" not in item, "The {} is Topo item and can not be parsed".format( item )
69
70 multThressholds = item.split("_")[1:] # skips the L1_
71 thresholds = []
72 for mt in multThressholds:
73 assert mt[0] != '1', 'Issue while parsing {}, multiplicity of 1, should not be configured, if multiplicity greater than 9 is needed then support for it needs to be added'.format( mt )
74 if mt[0] in '23456789': # first letter is a number == multiplicity, multiplicity 1 is not specified
75 thresholds.extend( int(mt[0])*[mt[1:]] )
76 else:
77 thresholds.append( mt ) # no muliplicity prefix
78 return thresholds
79

◆ getChainMultFromDict()

DictFromChainName.getChainMultFromDict ( chainDict)
Look for all multiplicities stored in chains

Definition at line 129 of file DictFromChainName.py.

129def getChainMultFromDict(chainDict):
130 """
131 Look for all multiplicities stored in chains
132 """
133 allMultis = []
134
135 for cpart in chainDict['chainParts']:
136 if cpart['multiplicity'] != '':
137 allMultis.append( int(cpart['multiplicity']))
138 return allMultis
139
140
141# For certain chains, we need to include the L1 seed threshold
142# in the leg name for disambiguation.
143# This checks that the explicit threshold matches the threshold list
144# In this case, the seed thresholds cannot be inferred from the L1 name

◆ getChainThresholdFromName()

DictFromChainName.getChainThresholdFromName ( chainParts,
signature )
Decode threshold value from the chain name

Definition at line 106 of file DictFromChainName.py.

106def getChainThresholdFromName(chainParts, signature):
107 """
108 Decode threshold value from the chain name
109 """
110
111 from TriggerMenuMT.HLT.Menu.SignatureDicts import getBasePattern
112 pattern = getBasePattern()
113 trigType = []
114 thresholdToPass = 0
115
116 allThresh = []
117 for cpart in chainParts:
118 m = pattern.match( cpart )
119 if m:
120 log.debug("In getChainThresholdFromName: Pattern found in this string: %s", cpart)
121 groupdict = m.groupdict()
122 allThresh.append(groupdict['threshold'])
123 trigType.append(groupdict['trigType'])
124 if signature == groupdict['trigType']:
125 thresholdToPass = groupdict['threshold']
126 break
127 return thresholdToPass
128

◆ getEBPartFromParts()

DictFromChainName.getEBPartFromParts ( chainName,
chainParts )
If EB identifier is in the name, return it.

Checks if there is only one identifier

Definition at line 91 of file DictFromChainName.py.

91def getEBPartFromParts( chainName, chainParts ):
92 """
93 If EB identifier is in the name, return it.
94
95 Checks if there is only one identifier
96 """
97 # ---- event building identifier ----
98 from TriggerMenuMT.HLT.Menu.EventBuildingInfo import getAllEventBuildingIdentifiers
99 eventBuildTypes = set( getAllEventBuildingIdentifiers() ).intersection( chainParts )
100 assert len(eventBuildTypes) <= 1, 'Chain {} has more than one Event Building identifier: {}, that is not supported'.format( chainName, eventBuildTypes)
101 if eventBuildTypes:
102 return eventBuildTypes.pop()
103 return ''
104
105
std::vector< std::string > intersection(std::vector< std::string > &v1, std::vector< std::string > &v2)

◆ getL1item()

DictFromChainName.getL1item ( flags,
chainName )

Definition at line 54 of file DictFromChainName.py.

54def getL1item(flags, chainName):
55 mainL1 = getOverallL1item(flags, chainName)
56 return mainL1
57

◆ getOverallL1item()

DictFromChainName.getOverallL1item ( flags,
chainName )
Extracts the L1 seed from the chain name, checks for issue in naming, if found, fails

In simple case the L1 items is just the last part of the name, after the _L1...
There are though more complicated names like ...._L1...._L1..._L1... in such cases the L1 seed item is the last one

Definition at line 24 of file DictFromChainName.py.

24def getOverallL1item(flags, chainName):
25 """
26 Extracts the L1 seed from the chain name, checks for issue in naming, if found, fails
27
28 In simple case the L1 items is just the last part of the name, after the _L1...
29 There are though more complicated names like ...._L1...._L1..._L1... in such cases the L1 seed item is the last one
30 """
31 assert '_L1' in chainName, 'ERROR IN CHAIN {}, missing L1 seed at the end i.e. _L1...' .format(chainName)
32
33 from TriggerMenuMT.HLT.Menu.L1Seeds import valid_multiseeds, getSpecificL1Seeds
34 from TrigConfigSvc.TriggerConfigAccess import getL1MenuAccess
35
36 # this assumes that the last string of a chain name is the overall L1 item
37 cNameParts = chainName.rsplit("_L1",1)
38 l1seed = 'L1_' + cNameParts[-1]
39 # For reference, remapping of L1seeds lived originally in LVL1MenuConfig/LVL1Menu/L1Seeds.py
40 # L1 collections can be read out from there in case they are needed again
41 if l1seed == 'L1_All':
42 return ''
43 if l1seed == 'L1_test': #Multiseeded chains are build like this
44 return 'L1_EM24VHI,L1_MU20'
45 if l1seed in valid_multiseeds:
46 # For these item seed specifications we need to derive the precise list of item names from the L1Menu.
47 lvl1access = getL1MenuAccess(flags)
48 itemsDict = lvl1access.items(includeKeys = ['name','ctpid','triggerType'])
49 l1seedlist = getSpecificL1Seeds(l1seed, itemsDict, flags.Trigger.triggerMenuSetup)
50 return l1seedlist
51
52 return l1seed
53

◆ getUniqueThresholdsFromItem()

DictFromChainName.getUniqueThresholdsFromItem ( item)
As above but eliminates repeated thresholds

Definition at line 80 of file DictFromChainName.py.

80def getUniqueThresholdsFromItem(item):
81 """
82 As above but eliminates repeated thresholds
83 """
84 allThreshold = getAllThresholdsFromItem(item)
85 s = set()
86 def _(t):
87 s.add(t)
88 return t
89 return [ _(t) for t in allThreshold if t not in s ]
90

◆ main()

DictFromChainName.main ( )

Definition at line 779 of file DictFromChainName.py.

779def main():
780
781 from AthenaConfiguration.AllConfigFlags import initConfigFlags
782 flags = initConfigFlags()
783
784 parser = flags.getArgumentParser()
785 parser.add_argument(
786 'chain',
787 type=str,
788 help='Chain name to be parsed into chain dictionary')
789 parser.add_argument(
790 '-t', '--thresholds',
791 nargs='+',
792 help='L1 thresholds, needed for multileg or fullscan chains')
793 args = flags.fillFromArgs(parser=parser)
794 flags.lock()
795
796 if args.thresholds:
797 from TriggerMenuMT.HLT.Config.Utility.ChainDefInMenu import ChainProp
798 cd = dictFromChainName(flags, ChainProp(args.chain,l1SeedThresholds=args.thresholds,groups=[]))
799 else:
800 cd = dictFromChainName(flags, args.chain)
801
802 from pprint import pprint
803 pprint(cd)
804
805 import json
806 with open(f'{args.chain}.dict.json','w') as f:
807 json.dump(cd, f, indent=2)
808
809 return 0
810
int main()
Definition hello.cxx:18

◆ unifyJetRecoParts()

DictFromChainName.unifyJetRecoParts ( chainParts)

Definition at line 164 of file DictFromChainName.py.

164def unifyJetRecoParts(chainParts):
165 from TriggerMenuMT.HLT.Menu.SignatureDicts import getSignatureInformation, JetRecoKeys
166
167 """
168 Postprocess the jet chainParts to set all the reco config consistently
169 For formatting reasons, we extract these from the last jet chainPart
170 then propagate to all jet chainParts.
171 Any inconsistencies in non-default options are considered a malformed chain
172 Technically we can't tell if the default was explicitly set, though.
173 """
174
175 jetDefaults, _ = getSignatureInformation('Jet')
176 # Extract the jet chainParts, and get the reco specs from the last one
177 _jetRecoKeys = JetRecoKeys
178 jetChainParts = [cPart for cPart in chainParts if cPart['signature'] in ['Jet','Bjet']]
179 jetRecoDict = {k:jetChainParts[-1][k] for k in _jetRecoKeys}
180
181 # Check consistency of the preceding jet parts
182 for p in jetChainParts[:-1]:
183 for k in _jetRecoKeys:
184 # Assume that keys are all defined
185 if p[k] != jetDefaults[k]: # OK if the spec is default
186 log.error('Inconsistent jet reco setting for %s in chainPart %s', k, p['chainPartName'])
187 log.error('Jet chainParts: %s', jetChainParts)
188 raise RuntimeError('Jet reco should be specified only in the last jet chainPart')
189
190 # Substitute the reco settings consistently and return
191 newChainParts = []
192 for cPart in chainParts:
193 newCPart = deepcopy(cPart)
194 if newCPart['signature'] in ['Jet','Bjet']:
195 for k in _jetRecoKeys:
196 newCPart[k] = jetRecoDict[k]
197 newChainParts.append(newCPart)
198
199 return newChainParts
200

◆ verifyExplicitL1Thresholds()

DictFromChainName.verifyExplicitL1Thresholds ( chainname,
chainparts,
L1thresholds )

Definition at line 146 of file DictFromChainName.py.

146def verifyExplicitL1Thresholds(chainname,chainparts,L1thresholds):
147 assert len(L1thresholds)>0, f'L1 thresholds cannot be inferred from L1 name for chain {chainname} with explicit L1 seed thresholds'
148
149 log.debug('Verifying explicit L1 thresholds for %s, received L1thresholds %s',chainname,L1thresholds)
150
151 counter = 0
152 for part, threshold in zip(chainparts,L1thresholds):
153 if '_L1' in part:
154 matches = matchL1.findall(part)
155 assert len(matches)==1, f"Inappropriate number of L1 thresholds {matches} in chain part '{part}'"
156 thisL1, remainder = matches[0] # list of tuples
157 assert remainder == '', f"Explicit L1 threshold should be last element in chain part {part}"
158 log.verbose(' ChainPart %s has explicit L1 threshold %s',part,thisL1)
159 assert 'PROBE' not in thisL1, f"Omit 'PROBE' from explicit L1 threshold '{thisL1}'"
160 assert thisL1 == threshold.replace('PROBE',''), f"Explicit L1 threshold for chainpart '{thisL1}' does not match threshold '{threshold}' from list"
161 counter += 1
162 assert counter>0, f"Did not find explicit L1 seeds in chain parts for {chainname}!"
163

Variable Documentation

◆ __author__

str DictFromChainName.__author__ = 'Catrin Bernius'
private

Definition at line 10 of file DictFromChainName.py.

◆ __doc__

str DictFromChainName.__doc__ = "Decoding of chain name into a dictionary"
private

Definition at line 12 of file DictFromChainName.py.

◆ __version__

str DictFromChainName.__version__ = ""
private

Definition at line 11 of file DictFromChainName.py.

◆ log

DictFromChainName.log = logging.getLogger( __name__ )

Definition at line 22 of file DictFromChainName.py.

◆ matchL1

DictFromChainName.matchL1 = re.compile('L1([a-zA-Z0-9]+)(_.*)?')

Definition at line 145 of file DictFromChainName.py.