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
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
217 hltChainName = chainName.rsplit("_L1",1)[0]
218
219
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
225 allChainProperties=[]
226 cparts = hltChainName.split("_")
227 if 'HLT' in hltChainName:
228 cparts.remove('HLT')
229
230
231 genchainDict['eventBuildType'] = getEBPartFromParts( chainName, cparts )
232 if genchainDict['eventBuildType']:
233 cparts.remove( genchainDict['eventBuildType'] )
234
235 hltChainNameShort = '_'.join(cparts)
236
237
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
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
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
288
289
290
291
292 from TriggerMenuMT.HLT.Menu.SignatureDicts import getBasePattern
293 pattern = getBasePattern()
294 mdicts=[]
295 multichainindex=[]
296
297
298
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
322
323
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
347 elif cpart =='acceptedevts':
348 multichainindex.append(hltChainNameShort.index(cpart))
349 buildDict( 'Calib', 'calib')
350 break
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
366
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
382
383 multichainparts.reverse()
384 log.debug('multichainparts after reverse: %s', multichainparts)
385
386
387
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
393
394
395
396
397
398
399 if chainName.count("_L1") > 1:
400 verifyExplicitL1Thresholds(chainName,multichainparts,L1thresholds)
401
402 for chainindex, chainparts in enumerate(multichainparts):
403 chainProperties = {}
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]
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
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
439
440
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
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
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
474 result = deepcopy(SignatureDefaultValues)
475 result.update(chainProperties)
476 chainProperties = result
477
478
479 overlaps = [x for x in parts if x in allDefaults]
480 log.debug("parts that are also in defaults: %s ", overlaps)
481
482
483 if overlaps == ['tracktwoMVA']: overlaps = []
484
485 if overlaps:
486
487
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
491
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
504 if chainProperties['signature']=='Jet':
505
506
507 if chainProperties['bTag'] != '':
508 log.debug('Setting b-jet chain defaults')
509
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
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
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
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
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
559 if chainProperties['extra']:
560
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
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
584
585 assert len(part.split()) == 0, "These parts of the chain name {} are not understood: {}".format(chainpartsNoL1,part)
586
587
588
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
597
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
608 allChainProperties.append(chainProperties)
609
610
611
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
630
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
636 return genchainDict
637
638