diff --git a/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/python/MTCalibPebConfig.py b/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/python/MTCalibPebConfig.py index 72de33222c81676d30d0dfe52e5fd40bf2eb39b0..76366c4fe9d7e58deb4d9de09202d673fc92061b 100644 --- a/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/python/MTCalibPebConfig.py +++ b/HLT/Trigger/TrigControl/TrigExamples/TrigExPartialEB/python/MTCalibPebConfig.py @@ -314,34 +314,44 @@ def make_hlt_seq(num_chains, concurrent=False): def write_dummy_menu_json(chains, chain_to_streams): import json + from collections import OrderedDict as odict from TrigConfHLTData.HLTUtils import string2hash menu_name = 'MTCalibPeb' - menu_dict = { - 'name': menu_name, - 'chains': [] - } + menu_dict = odict([ ("filetype", "hltmenu"), ("name", menu_name), ("chains", odict()), ("streams", odict()), ("sequencers", odict()) ]) counter = 0 for chain in chains: - chain_dict = {} - - # Relevant attributes - chain_dict['counter'] = counter - chain_dict['name'] = chain - chain_dict['streams'] = chain_to_streams[chain] - chain_dict['nameHash'] = string2hash(chain) - - # Other attributes not used in MTCalibPeb - chain_dict['groups'] = [] - chain_dict['l1item'] = '' - chain_dict['l1thresholds'] = [] + # Prepare information for stream list and fill separate dictionary + chain_streams = [] + for stream in chain_to_streams[chain]: + stream_name = stream['name'] + chain_streams.append(stream_name) + # If not already listed, add stream details to stream dictionary + if stream_name not in menu_dict["streams"]: + menu_dict["streams"][stream_name] = odict([ + ("name", stream_name), + ("type", stream['type']), + ("obeyLB", stream['obeyLB']), + ("forceFullEventBuilding", stream['forceFullEventBuilding']) + ]) + + # Attributes not filled are not used in MTCalibPeb + menu_dict["chains"][chain] = odict([ + ("counter", counter), + ("name", chain), + ("nameHash", string2hash(chain)), + ("l1item", ''), + ("l1thresholds", []), + ("groups", []), + ("streams", chain_streams), + ("sequencers", [] ) + ]) - menu_dict['chains'].append(chain_dict) counter += 1 file_name = 'HLTMenu_{:s}.json'.format(menu_name) log.info('Writing trigger menu to %s', file_name) with open(file_name, 'w') as json_file: - json.dump(menu_dict, json_file, indent=4, sort_keys=True) + json.dump(menu_dict, json_file, indent=4, sort_keys=False) return file_name diff --git a/Trigger/TrigConfiguration/TrigConfData/TrigConfData/HLTChain.h b/Trigger/TrigConfiguration/TrigConfData/TrigConfData/HLTChain.h index f95829c949b35c9300cebc905149d6f0540e79ba..c0755dda26977142d5039171db0747cffa54edd4 100644 --- a/Trigger/TrigConfiguration/TrigConfData/TrigConfData/HLTChain.h +++ b/Trigger/TrigConfiguration/TrigConfData/TrigConfData/HLTChain.h @@ -50,7 +50,7 @@ namespace TrigConf { std::vector<std::string> l1thresholds() const; /** Accessor to the connected output streams */ - std::vector<DataStructure> streams() const; + std::vector<std::string> streams() const; /** Accessor to the groups this chain belongs to */ std::vector<std::string> groups() const; diff --git a/Trigger/TrigConfiguration/TrigConfData/TrigConfData/HLTMenu.h b/Trigger/TrigConfiguration/TrigConfData/TrigConfData/HLTMenu.h index 887766cf8f4e595cbead29c167856fac6a89c307..ec445700604467987e1761a969b8a29d916c70b9 100644 --- a/Trigger/TrigConfiguration/TrigConfData/TrigConfData/HLTMenu.h +++ b/Trigger/TrigConfiguration/TrigConfData/TrigConfData/HLTMenu.h @@ -54,6 +54,9 @@ namespace TrigConf { */ const_iterator end() const; + /** Accessor to the connected output streams */ + std::vector<DataStructure> streams() const; + /** print overview of L1 Menu */ void printMenu(bool full = false) const; diff --git a/Trigger/TrigConfiguration/TrigConfData/src/HLTChain.cxx b/Trigger/TrigConfiguration/TrigConfData/src/HLTChain.cxx index 261e3f443081a066a3b7695b1aa598e10adb6357..0a072f3e40e12b3ae0cd2bcb7d0b305ade89b5ed 100644 --- a/Trigger/TrigConfiguration/TrigConfData/src/HLTChain.cxx +++ b/Trigger/TrigConfiguration/TrigConfData/src/HLTChain.cxx @@ -66,19 +66,22 @@ TrigConf::Chain::l1thresholds() const } -std::vector<TrigConf::DataStructure> +std::vector<std::string> TrigConf::Chain::streams() const { - std::vector<DataStructure> strlist; - const auto & streams = data().get_child("streams"); - strlist.reserve(streams.size()); - for( auto & strData : streams ) - strlist.emplace_back( strData.second ); - + std::vector<std::string> strlist; + const auto & streams = getList("streams"); + if( !streams.empty() ) { + strlist.reserve(streams.size()); + for( auto & stream : streams ) { + strlist.emplace_back( stream.getValue<std::string>() ); + } + } return strlist; } + std::vector<std::string> TrigConf::Chain::groups() const { diff --git a/Trigger/TrigConfiguration/TrigConfData/src/HLTMenu.cxx b/Trigger/TrigConfiguration/TrigConfData/src/HLTMenu.cxx index 8c81eddb00127f21f769700662cb831c69a6f44a..817ae1ee6f82ee2f446207aec8c2111c06297532 100644 --- a/Trigger/TrigConfiguration/TrigConfData/src/HLTMenu.cxx +++ b/Trigger/TrigConfiguration/TrigConfData/src/HLTMenu.cxx @@ -60,11 +60,25 @@ TrigConf::HLTMenu::end() const } +std::vector<TrigConf::DataStructure> +TrigConf::HLTMenu::streams() const +{ + std::vector<DataStructure> strlist; + const auto & streams = data().get_child("streams"); + strlist.reserve(streams.size()); + + for( auto & strData : streams ) + strlist.emplace_back( strData.second ); + + return strlist; +} + void TrigConf::HLTMenu::printMenu(bool full) const { cout << "HLT menu '" << name() << "'" << endl; + cout << "Streams: " << data().get_child("streams").size() << endl; cout << "Chains: " << size() << endl; if(full) { int c(0); diff --git a/Trigger/TrigConfiguration/TrigConfIO/python/HLTTriggerConfigAccess.py b/Trigger/TrigConfiguration/TrigConfIO/python/HLTTriggerConfigAccess.py index 8aff51fee8b64ba8351c1ff7eb60bb63d6d67ed2..daed3c4457ba57bd2fb9ecd7e39fc028cd0b99cc 100644 --- a/Trigger/TrigConfiguration/TrigConfIO/python/HLTTriggerConfigAccess.py +++ b/Trigger/TrigConfiguration/TrigConfIO/python/HLTTriggerConfigAccess.py @@ -25,12 +25,16 @@ class HLTMenuAccess(TriggerConfigAccess): def chains(self): return iter(self) + def streams(self): + return self["streams"] + def sequencers(self): return self["sequencers"] def printSummary(self): print("HLT menu %s" % self.name()) print("Number of chains: %i" % len(self) ) + print("Number of streams: %i" % len(self.streams()) ) print("Number of sequencers: %i" % len(self.sequencers()) ) diff --git a/Trigger/TrigConfiguration/TrigConfIO/utils/TestTriggerMenuAccess.cxx b/Trigger/TrigConfiguration/TrigConfIO/utils/TestTriggerMenuAccess.cxx index 76b6c13bc1b2ec2cc5852c869c8e41d3f4b2f1f3..39cb2b5992ee628fa7bc2550cdaaa030e51da945 100644 --- a/Trigger/TrigConfiguration/TrigConfIO/utils/TestTriggerMenuAccess.cxx +++ b/Trigger/TrigConfiguration/TrigConfIO/utils/TestTriggerMenuAccess.cxx @@ -274,11 +274,15 @@ bool testHLTMenu(const string & filename) { printComma = true; } cout << endl; - cout << "streams:" << endl; + cout << "streams:" << endl << " "; + printComma = false; for( auto & s : ch.streams() ) { - cout << " " << s["type"] << "_" << s["name"] - << (s["obeyLB"]=="yes" ? " (obeys LB" : " (does not obey LB") << " and has prescale " << s["prescale"] << ")" << endl; + if (printComma) + cout << ", "; + cout << s; + printComma = true; } + cout << endl; cout << "and groups:" << endl << " "; printComma = false; for( auto & g : ch.groups() ) { @@ -290,6 +294,16 @@ bool testHLTMenu(const string & filename) { cout << endl; if(--np==0) break; } + vector<TrigConf::DataStructure> streams = hltmenu.streams(); + cout << "Menu has " << streams.size() << " streams, going to print the first 3." << endl; + np = 3; + for( auto & s : streams ) { + cout << " " << s["type"] << "_" << s["name"] + << (s["obeyLB"]=="true" ? " (obeys LB" : " (does not obey LB") << ")" + << (s["forceFullEventBuilding"]=="true" ? " (forces FullEventBuilding" : " (does not force FullEventBuilding") << ")" + << endl; + if(--np==0) break; + } return true; } diff --git a/Trigger/TrigConfiguration/TrigConfigSvc/python/TrigConfigSvcCfg.py b/Trigger/TrigConfiguration/TrigConfigSvc/python/TrigConfigSvcCfg.py index 0b892f7f501f1a457873dc765ed3323d92cb15d9..a1603a63f1b97239d88cebfcb802a0834be482f6 100644 --- a/Trigger/TrigConfiguration/TrigConfigSvc/python/TrigConfigSvcCfg.py +++ b/Trigger/TrigConfiguration/TrigConfigSvc/python/TrigConfigSvcCfg.py @@ -98,18 +98,17 @@ def createHLTPrescalesFileFromMenu( flags=None ): log = logging.getLogger('TrigConfigSvcCfg') menuFN = getHLTMenuFileName( flags ) with open(menuFN,'r') as fh: - data = json.load(fh) + data = json.load(fh, object_pairs_hook = odict) pso = odict() pso['filetype'] = 'hltprescale' pso['name'] = data['name'] pso['prescales'] = odict() ps = pso['prescales'] - for ch in data['chains']: - chName = ch['name'] - ps[chName] = odict([ - ("name", chName), - ("counter", ch['counter']), - ("hash", ch['nameHash']), + for name, chain in data['chains'].items(): + ps[name] = odict([ + ("name", name), + ("counter", chain['counter']), + ("hash", chain['nameHash']), ("prescale", 1), ("enabled", 1) ]) diff --git a/Trigger/TrigMonitoring/TrigSteerMonitor/src/TrigSignatureMoniMT.cxx b/Trigger/TrigMonitoring/TrigSteerMonitor/src/TrigSignatureMoniMT.cxx index c2531161d548be0c3472097f10fc9ab38650abb6..3e8d5c063653c546bf03a78b016b701ad891fee5 100644 --- a/Trigger/TrigMonitoring/TrigSteerMonitor/src/TrigSignatureMoniMT.cxx +++ b/Trigger/TrigMonitoring/TrigSteerMonitor/src/TrigSignatureMoniMT.cxx @@ -52,8 +52,8 @@ StatusCode TrigSignatureMoniMT::start() { } } - for ( const auto& stream : chain.streams() ){ - m_streamToChainMap[stream.getAttribute("name")].insert( HLT::Identifier(chain.name()) ); + for ( const std::string& stream : chain.streams() ){ + m_streamToChainMap[stream].insert( HLT::Identifier(chain.name()) ); } if( gotL1Menu && !chain.l1item().empty() ) { diff --git a/Trigger/TrigSteer/TrigOutputHandling/src/StreamTagMakerTool.cxx b/Trigger/TrigSteer/TrigOutputHandling/src/StreamTagMakerTool.cxx index 3c5211163a921f8a0d5ab118c2a63b66e2fe8f8a..5cf723383e05f6c55cb4a159126cb2ed34890030 100644 --- a/Trigger/TrigSteer/TrigOutputHandling/src/StreamTagMakerTool.cxx +++ b/Trigger/TrigSteer/TrigOutputHandling/src/StreamTagMakerTool.cxx @@ -36,32 +36,46 @@ StatusCode StreamTagMakerTool::initialize() { } ATH_MSG_INFO("Configuring from HLTMenu from DetStore with " << hltMenu->size() << " chains"); + + std::vector<TrigConf::DataStructure> allStreams = hltMenu->streams(); + ATH_MSG_INFO("Menu has " << allStreams.size() << " streams defined"); + std::map<std::string, StreamTagInfo> streamDictionary; + ATH_MSG_DEBUG("StreamTags [Name,type,obeyLB,forceFullEventBuilding]:"); + for (const TrigConf::DataStructure& stream : allStreams) { + try { + std::string stream_name = stream.getAttribute("name"); + std::string stream_type = stream.getAttribute("type"); + std::string_view obeyLB = stream.getAttribute("obeyLB"); + std::string_view fullEventBuild = stream.getAttribute("forceFullEventBuilding"); + StreamTagInfo streamTag = { + stream_name, + stream_type, + obeyLB == "true", + fullEventBuild == "true" + }; + ATH_MSG_DEBUG("-- " << streamTag); + streamDictionary.insert(std::pair<std::string, StreamTagInfo>(stream.getAttribute("name"),streamTag)); + } catch (const std::exception& ex) { + ATH_MSG_ERROR("Failure reading stream tag configuration from JSON: " << ex.what()); + return StatusCode::FAILURE; + } + } + for (const TrigConf::Chain & chain : *hltMenu) { - std::vector<TrigConf::DataStructure> streams = chain.streams(); + std::vector<std::string> streams = chain.streams(); if (streams.empty()) { ATH_MSG_ERROR("Chain " << chain.name() << " has no streams assigned"); return StatusCode::FAILURE; } ATH_MSG_DEBUG("Chain " << chain.name() << " is assigned to " << streams.size() << " streams"); m_mapping[ HLT::Identifier( chain.name() ) ] = {}; - for (const TrigConf::DataStructure& stream : streams) { - try { - std::string stream_name = stream.getAttribute("name"); - std::string stream_type = stream.getAttribute("type"); - std::string_view obeyLB = stream.getAttribute("obeyLB"); - std::string_view fullEventBuild = stream.getAttribute("forceFullEventBuilding"); - StreamTagInfo streamTag = { - stream_name, - stream_type, - obeyLB == "true", - fullEventBuild == "true" - }; - m_mapping[ HLT::Identifier(chain.name()).numeric() ].push_back(streamTag); - ATH_MSG_DEBUG("-- " << stream_type << "_" << stream_name - << " (obeyLB=" << obeyLB << ", forceFullEventBuilding=" << fullEventBuild << ")"); - } catch (const std::exception& ex) { - ATH_MSG_ERROR("Failure reading stream tag configuration from JSON: " << ex.what()); - return StatusCode::FAILURE; + for (const std::string& stream : streams) { + ATH_MSG_DEBUG("-- " << stream); + if (const auto streamIt = streamDictionary.find(stream); streamIt != streamDictionary.end()) { + m_mapping[ HLT::Identifier(chain.name()).numeric() ].push_back(streamIt->second); + }else{ + ATH_MSG_ERROR("Failure reading stream tag configuration for stream: " << stream); + return StatusCode::FAILURE; } } } diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/HLTMenuJSON.py b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/HLTMenuJSON.py index 2b42306e92f30bbe059d3f905d58d0f0cb3c2b03..8e34146f6d1dff33b35141a03cb2fe0c9eaad2fd 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/HLTMenuJSON.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/HLTMenuConfig/Menu/HLTMenuJSON.py @@ -74,47 +74,61 @@ def __getSequencerAlgs(stepsData): def __generateJSON( chainDicts, chainConfigs, HLTAllSteps, menuName, fileName ): """ Generates JSON given the ChainProps and sequences """ - menuDict = odict([ ("filetype", "hltmenu"), ("name", menuName), ("chains", []), ("sequencers", odict()) ]) + # Menu dictionary that is used to create the JSON content + menuDict = odict([ ("filetype", "hltmenu"), ("name", menuName), ("chains", odict()), ("streams", odict()), ("sequencers", odict()) ]) - # List of steps data + # List of steps data for sequencers stepsData = __getStepsDataFromAlgSequence(HLTAllSteps) from TriggerMenuMT.HLTMenuConfig.Menu import StreamInfo for chain in chainDicts: - streamDicts = [] - streamTags = StreamInfo.getStreamTags(chain["stream"]) - for streamTag in streamTags: - streamDicts.append({"name": streamTag.name(), - "type": streamTag.type(), - "obeyLB": streamTag.obeysLumiBlock(), - "forceFullEventBuilding": streamTag.forceFullEventBuilding()}) - + # Prepare information for stream list and fill separate dictionary + chainStreamTags = [] + for streamName in chain["stream"]: + streamTag = StreamInfo.getStreamTag(streamName) + # Stream needs to have been defined in StreamInfo.py otherwise is not added to JSON + if streamTag is None: + __log.error('Stream %s does not have StreamTags defined excluding from JSON', streamName) + continue + # Add stream to the chain + chainStreamTags.append(streamName) + # If not already listed, add stream details to stream dictionary + if streamName not in menuDict["streams"]: + menuDict["streams"][streamName] = odict([ + ("name", streamName), + ("type", streamTag.type()), + ("obeyLB", streamTag.obeysLumiBlock()), + ("forceFullEventBuilding", streamTag.forceFullEventBuilding()) + ]) + + # Find L1 Threshold information for current chain l1Thresholds = [] [ l1Thresholds.append(p['L1threshold']) for p in chain['chainParts'] ] - chainDict = odict([ + # Now have all information to write the chain to the menu dictionary + chainName = chain["chainName"] + menuDict["chains"][chainName] = odict([ ("counter", chain["chainCounter"]), - ("name", chain["chainName"]), + ("name", chainName), ("nameHash", chain["chainNameHash"]), ("l1item", chain["L1item"]), ("l1thresholds", l1Thresholds), ("groups", chain["groups"]), - ("streams", streamDicts), - ("sequencers", __getChainSequencers(stepsData, chain["chainName"]) ) + ("streams", chainStreamTags), + ("sequencers", __getChainSequencers(stepsData, chainName) ) ]) - menuDict["chains"].append( chainDict ) - # All algorithms executed by a given Sequencer menuDict["sequencers"].update( __getSequencerAlgs(stepsData) ) - __log.info( "Writing trigger menu to %s", fileName ) + # Menu dictionary now completed, write to JSON + __log.info( "Writing HLT Menu JSON to %s", fileName ) with open( fileName, 'w' ) as fp: json.dump( menuDict, fp, indent=4, sort_keys=False ) def generateJSON(): - __log.info("Generating HLT JSON config in the rec-ex-common job") + __log.info("Generating HLT Menu JSON in the rec-ex-common job") from TriggerJobOpts.TriggerFlags import TriggerFlags from TriggerMenuMT.HLTMenuConfig.Menu.TriggerConfigHLT import TriggerConfigHLT from AthenaCommon.AlgSequence import AlgSequence @@ -127,7 +141,7 @@ def generateJSON(): getHLTMenuFileName() ) def generateJSON_newJO( chainDicts, chainConfigs, HLTAllSteps ): - __log.info("Generating HLT JSON config in the new JO") + __log.info("Generating HLT Menu JSON in the new JO") from AthenaConfiguration.AllConfigFlags import ConfigFlags return __generateJSON( chainDicts, diff --git a/Trigger/TriggerCommon/TriggerMenuMT/python/menu_config_tests.py b/Trigger/TriggerCommon/TriggerMenuMT/python/menu_config_tests.py index 2ae3d786e0f94666a437e5a31332ee85f136c0b9..b744da8dbc666d61ddbb921767d136d3ab705998 100644 --- a/Trigger/TriggerCommon/TriggerMenuMT/python/menu_config_tests.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/python/menu_config_tests.py @@ -34,7 +34,7 @@ class UniqueChainNames(MenuVerification): description="Chain names are unique") def run(self, config): - names = [chain["name"] for chain in config["chains"]] + names = [chain["name"] for chain in config["chains"].values()] counts = Counter(names) self.failures = [chain for chain, count in counts.items() if count > 1] @@ -47,7 +47,7 @@ class ConsecutiveChainCounters(MenuVerification): def run(self, config): counters = [chain["counter"] for chain - in config["chains"]] + in config["chains"].values()] prev_counter = 0 for count in counters: if count != prev_counter + 1: @@ -80,7 +80,7 @@ class StructuredChainNames(MenuVerification): def run(self, config): if self._trigger_level == TriggerLevel.HLT: - names = [chain["name"] for chain in config["chains"]] + names = [chain["name"] for chain in config["chains"].values()] self.failures = [n for n in names if not self._name_matches_hlt_convention(n)] elif self._trigger_level == TriggerLevel.L1: diff --git a/Trigger/TriggerCommon/TriggerMenuMT/scripts/verify_menu_config.py b/Trigger/TriggerCommon/TriggerMenuMT/scripts/verify_menu_config.py index 91a79a1ce3e2d89895f312990891c3641b7af5dd..37ab9b7d5830801767943cb9406e421379ee79e1 100755 --- a/Trigger/TriggerCommon/TriggerMenuMT/scripts/verify_menu_config.py +++ b/Trigger/TriggerCommon/TriggerMenuMT/scripts/verify_menu_config.py @@ -14,6 +14,7 @@ import os import sys import argparse +from collections import OrderedDict as odict from AthenaCommon.Logging import logging from TriggerMenuMT.menu_config_tests import TriggerLevel, menu_tests @@ -44,7 +45,7 @@ def load_and_verify(file_path, trigger_level): log.error("'{}' is not a JSON file".format(file_path)) else: with open(file_path, "r") as config_file: - config = json.load(config_file) + config = json.load(config_file, object_pairs_hook = odict) return verify(config, trigger_level) @@ -104,7 +105,7 @@ if __name__ == "__main__": for failed_test in result["failures"]: log.error("'{}' failed for: {}".format( failed_test.description, - ", ".join(failed_test.failures))) + ", ".join([str(i) for i in failed_test.failures]))) if result["failures"]: any_failures = True