3 from functools 
import lru_cache
 
    4 from collections 
import defaultdict
 
    6 from GaudiKernel.DataHandle 
import DataHandle
 
    7 from AthenaCommon.Logging 
import logging
 
    8 log = logging.getLogger(
'TrigEDMConfig')
 
   10 @lru_cache(maxsize=
None)
 
   12    """Determine Trigger EDM version based on the input ByteStream file. 
   14    Run-3 EDM is indicated by HLT ROD version > 1.0. For Run 1 and 2 the 
   15    HLT ROD version was 0.0 and the run number is used to disambiguate between them. 
   18    boundary_run12 = 230000
 
   19    boundary_run23 = 368000
 
   22    from libpyeformat_helper 
import SubDetector
 
   23    bs = eformat.istream(filename)
 
   29        if robf.rob_source_id().subdetector_id()==SubDetector.TDAQ_HLT:
 
   30            rodVersionM = robf.rod_minor_version() >> 8
 
   31            rodVersionL = robf.rod_minor_version() & 0xFF
 
   32            log.debug(
"HLT ROD minor version from input file is %d.%d", rodVersionM, rodVersionL)
 
   36    if rodVersionM 
is None or rodVersionL 
is None:
 
   37        log.warning(
"Cannot determine HLT ROD version from input file, falling back to run-number-based decision")
 
   39    elif rodVersionM >= 1:
 
   40        log.info(
"Determined EDMVersion to be 3, because running on BS file with HLT ROD version %d.%d",
 
   41                  rodVersionM, rodVersionL)
 
   45    runNumber = bs[0].run_no()
 
   46    log.debug(
"Read run number %s", runNumber)
 
   48    if not runNumber 
or runNumber <= 0:
 
   49        log.warning(
"Cannot determine EDM version because run number %s is invalid. ", runNumber)
 
   51    elif runNumber < boundary_run12:
 
   53        log.info(
"Determined EDMVersion to be 1 based on BS file run number (runNumber < %d)",
 
   56    elif runNumber < boundary_run23:
 
   58        log.info(
"Determined EDMVersion to be 2 based on BS file run number (%d < runNumber < %d)",
 
   59                  boundary_run12, boundary_run23)
 
   63        log.info(
"Determined EDMVersion to be 3 based on BS file run number (runNumber > %d)",
 
   70     Convert EDM dictionary in the format: 
   71         {'type1': ['key1','key2'], 'type2': ['key3']} 
   72     to a flat list in the format: 
   73         ['type1#key1', 'type1#key2', 'type2#key3'] 
   75     return [ f
"{type}#{name}" for type, names 
in edmDict.items() 
for name 
in names ]
 
   80     Convert EDM list in the format: 
   81         ['type1#key1', 'type1#key2', 'type2#key3'] 
   82     to a dictionary in the format: 
   83         {'type1': ['key1','key2'], 'type2': ['key3']} 
   85     edmDict = defaultdict(list)
 
   86     for typeName 
in edmList:
 
   87         edmType, edmKey = typeName.split(
'#')
 
   88         edmDict[edmType].
append(edmKey)
 
   94     Build OutputStream ItemList from all WriteHandles in a list of components (configurables), 
   95     for example a list of AlgTools. The output is in flat list format: 
   96         ['type1#key1', 'type1#key2', 'type2#key3'] 
   99     def getWriteHandles(comp):
 
  100         properties = [getattr(comp,propName) 
for propName 
in comp.getDefaultProperties().
keys()]
 
  101         return [prop 
for prop 
in properties 
if isinstance(prop,DataHandle) 
and prop.mode()==
'W']
 
  103     def formatItem(containerType, containerKey):
 
  104         auxType = containerType.replace(
'Container',
'AuxContainer')
 
  105         return [f
'{containerType}#{containerKey}',
 
  106                 f
'{auxType}#{containerKey}Aux.-']
 
  108     def containerTypedef(containerType):
 
  109         if containerType.startswith(
'xAOD::') 
and containerType.endswith(
'Container'):
 
  112         m = re.match(
r'DataVector<xAOD::(\w+)_v[0-9]+,', containerType)
 
  113         if m 
and len(m.groups()) > 0:
 
  114             return f
'xAOD::{m.group(1)}Container' 
  115         raise RuntimeError(f
'Failed to convert type {containerType} into a container typedef')
 
  117     def itemListFromConfigurable(comp):
 
  119         for handle 
in getWriteHandles(comp):
 
  120             sgKey = handle.Path.replace(
'StoreGateSvc+',
'')
 
  123             items += formatItem(containerTypedef(handle.Type), handle.Path)
 
  127     for comp 
in configurables:
 
  128         itemList += itemListFromConfigurable(comp)