From c75e9332e2c5f88a6ab56a25fb58c498469640ad Mon Sep 17 00:00:00 2001 From: Tim Martin <tim.martin@cern.ch> Date: Fri, 4 Sep 2020 16:12:25 +0000 Subject: [PATCH] Make TrigDecisionTool compile under AnalysisBase --- Projects/AnalysisBase/package_filters.txt | 6 +- .../TrigDecisionTool/CMakeLists.txt | 12 +- .../Root/CacheGlobalMemory.cxx | 27 +- .../Root/DecisionObjectHandleStandalone.cxx | 3 + .../TrigDecisionTool/Root/ExpertMethods.cxx | 39 +- .../Root/TrigDecisionTool.cxx | 44 ++- .../Root/TrigDecisionToolCore.cxx | 27 +- .../TrigDecisionTool/CacheGlobalMemory.h | 20 +- .../TrigDecisionTool/DecisionAccess.h | 11 +- .../DecisionObjectHandleStandalone.h | 2 +- .../TrigDecisionTool/DecisionUnpackerAthena.h | 7 +- .../DecisionUnpackerStandalone.h | 2 +- .../TrigDecisionTool/ExpertMethods.h | 18 +- .../TrigDecisionTool/TrigDecisionTool.h | 37 +- .../TrigDecisionTool/TrigDecisionToolCore.h | 8 +- .../src/DecisionUnpackerAthena.cxx | 2 + .../TrigDecisionEvent/TrigDecision.h | 2 +- .../TrigSteeringEvent/CMakeLists.txt | 2 +- .../TrigSteeringEvent/GenericResult.h | 2 +- .../TrigSteeringEvent/HLTResult.h | 8 +- .../TrigSteeringEvent/Lvl1Result.h | 3 +- .../TrigSteeringEvent/src/HLTResult.cxx | 1 - .../TrigCompositeUtils/CMakeLists.txt | 9 +- .../{src => Root}/NavGraph.cxx | 0 .../Root/TrigCompositeUtils.cxx | 369 +++++++++++++++++- .../TrigCompositeUtils/TrigCompositeUtils.h | 8 + .../src/TrigCompositeUtils.cxx | 356 ----------------- 27 files changed, 585 insertions(+), 440 deletions(-) rename Trigger/TrigSteer/TrigCompositeUtils/{src => Root}/NavGraph.cxx (100%) delete mode 100644 Trigger/TrigSteer/TrigCompositeUtils/src/TrigCompositeUtils.cxx diff --git a/Projects/AnalysisBase/package_filters.txt b/Projects/AnalysisBase/package_filters.txt index ac7fa92925a..e1865aa1233 100644 --- a/Projects/AnalysisBase/package_filters.txt +++ b/Projects/AnalysisBase/package_filters.txt @@ -121,9 +121,9 @@ + Tools/PathResolver + Trigger/TrigAnalysis/TrigAnalysisInterfaces + Trigger/TrigAnalysis/TrigBunchCrossingTool -#+ Trigger/TrigAnalysis/TrigDecisionTool -#+ Trigger/TrigAnalysis/TrigTauAnalysis/TrigTauMatching -#+ Trigger/TrigAnalysis/TriggerMatchingTool ++ Trigger/TrigAnalysis/TrigDecisionTool ++ Trigger/TrigAnalysis/TrigTauAnalysis/TrigTauMatching ++ Trigger/TrigAnalysis/TriggerMatchingTool + Trigger/TrigConfiguration/TrigConfBase + Trigger/TrigConfiguration/TrigConfHLTData + Trigger/TrigConfiguration/TrigConfHLTUtils diff --git a/Trigger/TrigAnalysis/TrigDecisionTool/CMakeLists.txt b/Trigger/TrigAnalysis/TrigDecisionTool/CMakeLists.txt index 3462185aecb..d4206f18c50 100644 --- a/Trigger/TrigAnalysis/TrigDecisionTool/CMakeLists.txt +++ b/Trigger/TrigAnalysis/TrigDecisionTool/CMakeLists.txt @@ -15,8 +15,10 @@ if( XAOD_STANDALONE ) INCLUDE_DIRS ${Boost_INCLUDE_DIRS} PRIVATE_INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} LINK_LIBRARIES ${Boost_LIBRARIES} AsgTools xAODBase xAODTrigger - TrigConfHLTData TrigConfL1Data TrigNavStructure TrigRoiConversionLib TrigConfInterfaces - PRIVATE_LINK_LIBRARIES ${ROOT_LIBRARIES} TrigSteeringEvent ) + TrigConfHLTData TrigConfL1Data TrigNavStructure TrigRoiConversionLib + TrigConfInterfaces TrigDecisionInterface AsgDataHandlesLib + TrigCompositeUtilsLib + PRIVATE_LINK_LIBRARIES ${ROOT_LIBRARIES} TrigSteeringEvent ) else() if( XAOD_ANALYSIS ) atlas_add_library( TrigDecisionToolLib @@ -26,8 +28,9 @@ else() PRIVATE_INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} LINK_LIBRARIES ${Boost_LIBRARIES} AsgTools EventInfo xAODBase xAODTrigger GaudiKernel TrigConfHLTData TrigConfL1Data - TrigNavStructure StoreGateLib TrigRoiConversionLib TrigCompositeUtilsLib TrigConfInterfaces - PRIVATE_LINK_LIBRARIES ${ROOT_LIBRARIES} AthenaBaseComps + TrigNavStructure StoreGateLib TrigRoiConversionLib TrigCompositeUtilsLib + TrigConfInterfaces TrigDecisionEvent TrigDecisionInterface + PRIVATE_LINK_LIBRARIES ${ROOT_LIBRARIES} AthenaBaseComps AsgDataHandlesLib TrigSteeringEvent AthenaKernel ) else() atlas_add_library( TrigDecisionToolLib @@ -40,6 +43,7 @@ else() TrigConfL1Data TrigDecisionEvent TrigMuonEvent TrigNavStructure TrigStorageDefinitions StoreGateLib TrigNavigationLib TrigRoiConversionLib TrigCompositeUtilsLib TrigConfInterfaces + TrigDecisionInterface AsgDataHandlesLib PRIVATE_LINK_LIBRARIES ${ROOT_LIBRARIES} AthenaBaseComps TrigSteeringEvent AthenaKernel ) endif() diff --git a/Trigger/TrigAnalysis/TrigDecisionTool/Root/CacheGlobalMemory.cxx b/Trigger/TrigAnalysis/TrigDecisionTool/Root/CacheGlobalMemory.cxx index 8f598bb1513..223dbd2c8ae 100644 --- a/Trigger/TrigAnalysis/TrigDecisionTool/Root/CacheGlobalMemory.cxx +++ b/Trigger/TrigAnalysis/TrigDecisionTool/Root/CacheGlobalMemory.cxx @@ -24,6 +24,8 @@ #include "TrigConfHLTData/HLTSignature.h" #include "TrigNavStructure/TriggerElement.h" +#include "AsgDataHandles/ReadHandle.h" + #include "TrigSteeringEvent/Lvl1Item.h" #include "TrigDecisionTool/CacheGlobalMemory.h" @@ -55,8 +57,10 @@ Trig::CacheGlobalMemory::CacheGlobalMemory() : m_confChains(nullptr), m_expressStreamContainer(nullptr), m_decisionKeyPtr(nullptr), +#if !defined(XAOD_STANDALONE) && !defined(XAOD_ANALYSIS) // Full Athena m_oldDecisionKeyPtr(nullptr), m_oldEventInfoKeyPtr(nullptr), +#endif m_navigationKeyPtr(nullptr), m_bgCode(0) {} @@ -334,9 +338,12 @@ bool Trig::CacheGlobalMemory::assert_decision() { // here we unpack the decision. Note: the navigation will be unpacked only on demand (see navigation()) bool contains_xAOD_decision = false; + +#if !defined(XAOD_STANDALONE) && !defined(XAOD_ANALYSIS) // Full Athena bool is_l1result_configured = false; bool contains_decision = false; bool contains_old_event_info = false; +#endif if(!m_unpacker){ ATH_MSG_INFO("decision not set on first (?) assert. deciding how to unpack"); @@ -352,7 +359,7 @@ bool Trig::CacheGlobalMemory::assert_decision() { contains_xAOD_decision = decisionReadHandle.isValid(); } -#ifndef XAOD_ANALYSIS +#if !defined(XAOD_STANDALONE) && !defined(XAOD_ANALYSIS) // Full Athena if (!m_oldDecisionKeyPtr->empty()) { SG::ReadHandle<TrigDec::TrigDecision> oldDecisionReadHandle = SG::makeHandle(*m_oldDecisionKeyPtr, context); @@ -391,12 +398,9 @@ bool Trig::CacheGlobalMemory::assert_decision() { }//if(!m_unpacker) if(!m_unpacker){ - ATH_MSG_ERROR("No source of Trigger Decision in file. " - << "(Looked for xAOD::TrigDecision? " - << (m_decisionKeyPtr->empty() ? "NO" : "YES") - << ", has xAOD::TrigDecision? " - << (contains_xAOD_decision ? "YES" : "NO") - << ". Looked for old TrigDec::TrigDecision? " + std::stringstream extra; +#if !defined(XAOD_STANDALONE) && !defined(XAOD_ANALYSIS) // Full Athena + extra << ". Looked for old TrigDec::TrigDecision? " << (m_oldDecisionKeyPtr->empty() ? "NO" : "YES") << ", has TrigDec::TrigDecision? " << (contains_decision ? "YES" : "NO") @@ -405,7 +409,14 @@ bool Trig::CacheGlobalMemory::assert_decision() { << ". Looked for old EventInfo? " << (m_oldEventInfoKeyPtr->empty() ? "NO" : "YES") << ", has old EventInto? " - << (contains_old_event_info ? "YES" : "NO") + << (contains_old_event_info ? "YES" : "NO"); +#endif + ATH_MSG_ERROR("No source of Trigger Decision in file. " + << "(Looked for xAOD::TrigDecision? " + << (m_decisionKeyPtr->empty() ? "NO" : "YES") + << ", has xAOD::TrigDecision? " + << (contains_xAOD_decision ? "YES" : "NO") + << extra.str() << ". Check UseRun1DecisionFormat and UseOldEventInfoDecisionFormat flags if reading pre-xAOD or BS input)."); throw std::runtime_error("Trig::CacheGlobalMemory::assert_decision(): No source of Trigger Decision in file."); } diff --git a/Trigger/TrigAnalysis/TrigDecisionTool/Root/DecisionObjectHandleStandalone.cxx b/Trigger/TrigAnalysis/TrigDecisionTool/Root/DecisionObjectHandleStandalone.cxx index 6a37ccb3d74..ad8b848c91e 100644 --- a/Trigger/TrigAnalysis/TrigDecisionTool/Root/DecisionObjectHandleStandalone.cxx +++ b/Trigger/TrigAnalysis/TrigDecisionTool/Root/DecisionObjectHandleStandalone.cxx @@ -7,6 +7,9 @@ // Local include(s): #include "TrigDecisionTool/DecisionObjectHandleStandalone.h" +#include "AsgTools/CurrentContext.h" +#include "AsgDataHandles/ReadHandle.h" + // Include for the event store type: #ifdef XAOD_STANDALONE # include "AsgTools/SgTEvent.h" diff --git a/Trigger/TrigAnalysis/TrigDecisionTool/Root/ExpertMethods.cxx b/Trigger/TrigAnalysis/TrigDecisionTool/Root/ExpertMethods.cxx index 64052d3495c..20b6e5d0fcd 100644 --- a/Trigger/TrigAnalysis/TrigDecisionTool/Root/ExpertMethods.cxx +++ b/Trigger/TrigAnalysis/TrigDecisionTool/Root/ExpertMethods.cxx @@ -23,6 +23,8 @@ #include "TrigNavigation/AccessProxy.h" #endif +#include "AsgDataHandles/ReadHandle.h" + #include "TrigSteeringEvent/Chain.h" #include "TrigConfHLTData/HLTSignature.h" #include "TrigConfHLTData/HLTTriggerElement.h" @@ -33,12 +35,25 @@ #include "xAODTrigger/TrigDecision.h" + +#if !defined(XAOD_STANDALONE) && !defined(XAOD_ANALYSIS) // Full Athena + Trig::ExpertMethods::ExpertMethods(SG::SlotSpecificObj<Trig::CacheGlobalMemory>* cgm) : m_cacheGlobalMemory(cgm), m_useExperimentalAndExpertMethods(false) { } +#else // Analysis or Standalone + +Trig::ExpertMethods::ExpertMethods(Trig::CacheGlobalMemory* cgm) + : m_cacheGlobalMemory(cgm), + m_useExperimentalAndExpertMethods(false) +{ +} + +#endif + Trig::ExpertMethods::~ExpertMethods() {} bool Trig::ExpertMethods::checkExperimentalAndExpertMethods() const { @@ -76,30 +91,42 @@ const LVL1CTP::Lvl1Item* Trig::ExpertMethods::getItemDetails(const std::string& return cgm()->item(chain); } -#if !defined(XAOD_STANDALONE) && !defined(XAOD_ANALYSIS) +#if !defined(XAOD_STANDALONE) && !defined(XAOD_ANALYSIS) // Full Athena + const HLT::NavigationCore* Trig::ExpertMethods::getNavigation() const { if (!(checkExperimentalAndExpertMethods())) return 0; return dynamic_cast<const HLT::NavigationCore*>(cgm()->navigation()); } -#else + +Trig::CacheGlobalMemory* Trig::ExpertMethods::cgm(bool onlyConfig) const { + if ( ! onlyConfig ) { + if ( !const_cast<Trig::CacheGlobalMemory*>(m_cacheGlobalMemory->get())->assert_decision() ) { + ATH_MSG_WARNING("TDT has not ben able to unpack trigger decision"); + } + } + return m_cacheGlobalMemory->get(); +} + +#else // Analysis or Standalone + const HLT::TrigNavStructure* Trig::ExpertMethods::getNavigation() const { if (!(checkExperimentalAndExpertMethods())) return 0; return cgm()->navigation(); } -#endif - Trig::CacheGlobalMemory* Trig::ExpertMethods::cgm(bool onlyConfig) const { if ( ! onlyConfig ) { - if ( !const_cast<Trig::CacheGlobalMemory*>(m_cacheGlobalMemory->get())->assert_decision() ) { + if ( !const_cast<Trig::CacheGlobalMemory*>(m_cacheGlobalMemory)->assert_decision() ) { ATH_MSG_WARNING("TDT has not ben able to unpack trigger decision"); } } - return m_cacheGlobalMemory->get(); + return m_cacheGlobalMemory; } +#endif + diff --git a/Trigger/TrigAnalysis/TrigDecisionTool/Root/TrigDecisionTool.cxx b/Trigger/TrigAnalysis/TrigDecisionTool/Root/TrigDecisionTool.cxx index d1b00685ed2..932d4278c11 100644 --- a/Trigger/TrigAnalysis/TrigDecisionTool/Root/TrigDecisionTool.cxx +++ b/Trigger/TrigAnalysis/TrigDecisionTool/Root/TrigDecisionTool.cxx @@ -34,9 +34,9 @@ static std::vector<std::string> s_instances; Trig::TrigDecisionTool::TrigDecisionTool(const std::string& name) : - asg::AsgMetadataTool(name), + asg::AsgMetadataTool(name) #ifndef XAOD_STANDALONE - AthMessaging( Athena::getMessageSvc(), name) + ,AthMessaging( Athena::getMessageSvc(), name) #endif #ifndef XAOD_ANALYSIS ,m_fullNavigation("HLT::Navigation/Navigation", this) @@ -95,8 +95,12 @@ Trig::TrigDecisionTool::initialize() { return StatusCode::FAILURE; } + +#if !defined(XAOD_STANDALONE) && !defined(XAOD_ANALYSIS) // Full athena ATH_CHECK(m_oldDecisionKey.initialize( m_useRun1DecisionFormat ) ); ATH_CHECK(m_oldEventInfoKey.initialize( m_useOldEventInfoDecisionFormat ) ); +#endif + ATH_CHECK(m_HLTSummaryKeyIn.initialize(m_navigationFormat == "TrigComposite")); ATH_CHECK(m_navigationKey.initialize(m_navigationFormat == "TriggerElement")); ATH_CHECK(m_decisionKey.initialize()); @@ -170,13 +174,28 @@ Trig::TrigDecisionTool::initialize() { return StatusCode::SUCCESS; } +std::vector<uint32_t>* Trig::TrigDecisionTool::getKeys() { +#if !defined(XAOD_STANDALONE) && !defined(XAOD_ANALYSIS) // Full athena + return m_configKeysCache.get(); +#else // Analysis or Standalone + return &m_configKeysCache; +#endif +} + + + StatusCode Trig::TrigDecisionTool::beginEvent() { CacheGlobalMemory* cgmPtr = cgm(); cgmPtr->setDecisionKeyPtr( &m_decisionKey ); - cgmPtr->setOldDecisionKeyPtr( &m_oldDecisionKey ); cgmPtr->setNavigationKeyPtr( &m_navigationKey ); + + size_t slot = 0; +#if !defined(XAOD_STANDALONE) && !defined(XAOD_ANALYSIS) // Full athena + cgmPtr->setOldDecisionKeyPtr( &m_oldDecisionKey ); cgmPtr->setOldEventInfoKeyPtr( &m_oldEventInfoKey ); + slot = Gaudi::Hive::currentContext().slot(); +#endif //invalidate handle so that we read a new decision object if(cgm()->unpacker()){ @@ -200,21 +219,19 @@ StatusCode Trig::TrigDecisionTool::beginEvent() { if(!keysMatch){ - ATH_MSG_INFO("Tool: updating config in slot " - << Gaudi::Hive::currentContext().slot() + ATH_MSG_INFO("Tool: updating config in slot " << slot << " with SMK: " << m_configTool->masterKey() << " and L1PSK: " << m_configTool->lvl1PrescaleKey() << " and HLTPSK: " << m_configTool->hltPrescaleKey()); - std::vector<uint32_t>* keys = m_configKeysCache.get(); + std::vector<uint32_t>* keys = getKeys(); keys->resize(3); keys->at(0) = m_configTool->masterKey(); keys->at(1) = m_configTool->lvl1PrescaleKey(); keys->at(2) = m_configTool->hltPrescaleKey(); configurationUpdate( m_configTool->chainList(), m_configTool->ctpConfig() ); } else{ - ATH_MSG_VERBOSE("Tool: Cached Trigger configuration keys match for this event in slot " - << Gaudi::Hive::currentContext().slot()); + ATH_MSG_VERBOSE("Tool: Cached Trigger configuration keys match for this event in slot " << slot); } #ifndef XAOD_ANALYSIS } @@ -231,21 +248,20 @@ StatusCode Trig::TrigDecisionTool::beginEvent() { if(!keysMatch){ - ATH_MSG_INFO("Svc: updating config in slot " - << Gaudi::Hive::currentContext().slot() + ATH_MSG_INFO("Svc: updating config in slot " << slot << " with SMK: " << m_configSvc->masterKey() << " and L1PSK: " << m_configSvc->lvl1PrescaleKey() << " and HLTPSK: " << m_configSvc->hltPrescaleKey()); - std::vector<uint32_t>* keys = m_configKeysCache.get(); + std::vector<uint32_t>* keys = getKeys(); keys->resize(3); keys->at(0) = m_configSvc->masterKey(); keys->at(1) = m_configSvc->lvl1PrescaleKey(); keys->at(2) = m_configSvc->hltPrescaleKey(); configurationUpdate( m_configSvc->chainList(), m_configSvc->ctpConfig() ); }else{ - ATH_MSG_VERBOSE("Svc: Cached Trigger configuration keys match for this event in slot " - << Gaudi::Hive::currentContext().slot()); } + ATH_MSG_VERBOSE("Svc: Cached Trigger configuration keys match for this event in slot " << slot); + } } #endif @@ -263,7 +279,7 @@ StatusCode Trig::TrigDecisionTool::beginInputFile() { } bool Trig::TrigDecisionTool::configKeysMatch(uint32_t smk, uint32_t lvl1psk, uint32_t hltpsk){ - std::vector<uint32_t>* keys = m_configKeysCache.get(); // Slot-specific object. + std::vector<uint32_t>* keys = getKeys(); // Slot-specific object in full athena. if (keys->size() != 3) { return false; } diff --git a/Trigger/TrigAnalysis/TrigDecisionTool/Root/TrigDecisionToolCore.cxx b/Trigger/TrigAnalysis/TrigDecisionTool/Root/TrigDecisionToolCore.cxx index 89ec36fb4e9..e703f253edb 100644 --- a/Trigger/TrigAnalysis/TrigDecisionTool/Root/TrigDecisionToolCore.cxx +++ b/Trigger/TrigAnalysis/TrigDecisionTool/Root/TrigDecisionToolCore.cxx @@ -19,22 +19,41 @@ #include "TrigDecisionTool/TrigDecisionToolCore.h" + +#if !defined(XAOD_STANDALONE) && !defined(XAOD_ANALYSIS) // Full Athena + Trig::TrigDecisionToolCore::TrigDecisionToolCore() { SG::SlotSpecificObj<Trig::CacheGlobalMemory>* ptr = &m_cacheGlobalMemory; m_expertMethods=new ExpertMethods(ptr); } -Trig::TrigDecisionToolCore::~TrigDecisionToolCore() { - delete m_expertMethods; -} - Trig::CacheGlobalMemory* Trig::TrigDecisionToolCore::cgm() const { const Trig::CacheGlobalMemory* ptr = m_cacheGlobalMemory.get(); // A consiquence of placing the cache in a slot-specific wrapper return const_cast<Trig::CacheGlobalMemory*>(ptr); } +#else // Analysis or Standalone + +Trig::TrigDecisionToolCore::TrigDecisionToolCore() +{ + Trig::CacheGlobalMemory* ptr = &m_cacheGlobalMemory; + m_expertMethods=new ExpertMethods(ptr); +} + +Trig::CacheGlobalMemory* Trig::TrigDecisionToolCore::cgm() const { + return const_cast<Trig::CacheGlobalMemory*>(&m_cacheGlobalMemory); +} + +#endif + + +Trig::TrigDecisionToolCore::~TrigDecisionToolCore() { + delete m_expertMethods; +} + + StatusCode Trig::TrigDecisionToolCore::initialize() { ChainGroupInitialize(); return StatusCode::SUCCESS; diff --git a/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/CacheGlobalMemory.h b/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/CacheGlobalMemory.h index 81215f7310b..cca01aa534e 100644 --- a/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/CacheGlobalMemory.h +++ b/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/CacheGlobalMemory.h @@ -32,18 +32,21 @@ #include "TrigConfL1Data/CTPConfig.h" #include "TrigSteeringEvent/Chain.h" -#include "TrigDecisionEvent/TrigDecision.h" #include "TrigDecisionTool/IDecisionUnpacker.h" #include "TrigDecisionTool/Logger.h" #include "AsgTools/AsgMessaging.h" -#include "StoreGate/ReadHandleKey.h" +#include "AsgDataHandles/ReadHandleKey.h" #include "xAODTrigger/TrigCompositeContainer.h" #include "xAODTrigger/TrigDecision.h" #include "xAODTrigger/TrigNavigation.h" + +#ifndef XAOD_STANDALONE #include "EventInfo/EventInfo.h" +#include "TrigDecisionEvent/TrigDecision.h" +#endif namespace HLT { class Chain; @@ -104,9 +107,9 @@ namespace Trig { const HLT::TrigNavStructure* navigation() const { //!< gives back pointer to navigation object (unpacking if necessary) if(!m_unpacker->unpacked_navigation()){ - if(const_cast<CacheGlobalMemory*>(this)->unpackNavigation().isFailure()){ - ATH_MSG_WARNING("unpack Navigation failed"); - } + if(const_cast<CacheGlobalMemory*>(this)->unpackNavigation().isFailure()){ + ATH_MSG_WARNING("unpack Navigation failed"); + } } return m_navigation; } @@ -142,8 +145,11 @@ namespace Trig { void setDecisionKeyPtr(SG::ReadHandleKey<xAOD::TrigDecision>* k) { m_decisionKeyPtr = k; } void setNavigationKeyPtr(SG::ReadHandleKey<xAOD::TrigNavigation>* k) { m_navigationKeyPtr = k; } + +#if !defined(XAOD_STANDALONE) && !defined(XAOD_ANALYSIS) // Full Athena void setOldDecisionKeyPtr(SG::ReadHandleKey<TrigDec::TrigDecision>* k) { m_oldDecisionKeyPtr = k; } void setOldEventInfoKeyPtr(SG::ReadHandleKey<EventInfo>* k) { m_oldEventInfoKeyPtr = k; } +#endif SG::ReadHandleKey<xAOD::TrigDecision>* xAODTrigDecisionKey() { return m_decisionKeyPtr; } @@ -211,8 +217,12 @@ namespace Trig { mutable const xAOD::TrigCompositeContainer* m_expressStreamContainer; SG::ReadHandleKey<xAOD::TrigDecision>* m_decisionKeyPtr; //!< Parent TDT's read handle key + +#if !defined(XAOD_STANDALONE) && !defined(XAOD_ANALYSIS) // Full Athena SG::ReadHandleKey<TrigDec::TrigDecision>* m_oldDecisionKeyPtr; //!< Parent TDT's read handle key SG::ReadHandleKey<EventInfo>* m_oldEventInfoKeyPtr; //!< Parent TDT's read handle key +#endif + SG::ReadHandleKey<xAOD::TrigNavigation>* m_navigationKeyPtr; //!< Parent TDT's read handle key typedef std::unordered_map<std::string, const TrigConf::HLTChain*> ChainHashMap_t; diff --git a/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/DecisionAccess.h b/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/DecisionAccess.h index eb22260dde7..20b09dbecfb 100644 --- a/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/DecisionAccess.h +++ b/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/DecisionAccess.h @@ -33,6 +33,8 @@ #include "TrigCompositeUtils/TrigCompositeUtils.h" +#include "AsgDataHandles/ReadHandle.h" + namespace HLT { class Chain; } @@ -111,6 +113,7 @@ namespace Trig { /// @name Run 3 functions /// @{ + /** * @brief Runs 3+. Returns all features related to given chain group * @param[in] group Chain group to return features for. @@ -155,7 +158,7 @@ namespace Trig { **/ template<class CONTAINER, class FEATURE_CONTAINER> std::pair< typename CONTAINER::const_iterator, typename CONTAINER::const_iterator > - associateToEventView(SG::ReadHandle<CONTAINER>& inViewContainer, + associateToEventView(typename SG::ReadHandle<CONTAINER>& inViewContainer, const TrigCompositeUtils::LinkInfo<FEATURE_CONTAINER> linkInfo, const std::string& roiName = TrigCompositeUtils::roiString()) const; @@ -169,7 +172,7 @@ namespace Trig { **/ template<class CONTAINER> std::pair< typename CONTAINER::const_iterator, typename CONTAINER::const_iterator > - associateToEventView(SG::ReadHandle<CONTAINER>& inViewContainer, + associateToEventView(typename SG::ReadHandle<CONTAINER>& inViewContainer, const TrigCompositeUtils::Decision* decisionObject, const std::string& roiName = TrigCompositeUtils::roiString()) const; @@ -182,7 +185,7 @@ namespace Trig { **/ template<class CONTAINER> std::pair< typename CONTAINER::const_iterator, typename CONTAINER::const_iterator > - associateToEventView(SG::ReadHandle<CONTAINER>& inViewContainer, + associateToEventView(typename SG::ReadHandle<CONTAINER>& inViewContainer, const ElementLink<TrigRoiDescriptorCollection>& matchROI) const; /** @@ -200,7 +203,7 @@ namespace Trig { **/ template<class CONTAINER> std::pair< typename CONTAINER::const_iterator, typename CONTAINER::const_iterator > - associateToEventView(SG::ReadHandle<CONTAINER>& inViewContainer, + associateToEventView(typename SG::ReadHandle<CONTAINER>& inViewContainer, const uint32_t matchIndex, const uint32_t matchKey = 0, const bool isFullscan = false) const; diff --git a/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/DecisionObjectHandleStandalone.h b/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/DecisionObjectHandleStandalone.h index 05c79a9f7fd..09b72d0f690 100644 --- a/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/DecisionObjectHandleStandalone.h +++ b/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/DecisionObjectHandleStandalone.h @@ -22,7 +22,7 @@ #include "TrigDecisionTool/DecisionObjectHandle.h" #include "TrigDecisionTool/EventPtrDef.h" -#include "StoreGate/ReadHandleKey.h" +#include "AsgDataHandles/ReadHandleKey.h" namespace Trig { diff --git a/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/DecisionUnpackerAthena.h b/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/DecisionUnpackerAthena.h index f3d3b3b746c..bf9e0054424 100644 --- a/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/DecisionUnpackerAthena.h +++ b/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/DecisionUnpackerAthena.h @@ -14,13 +14,16 @@ #include "TrigDecisionTool/Logger.h" #include "AsgTools/AsgMessaging.h" -#include "StoreGate/ReadHandleKey.h" +#include "AsgDataHandles/ReadHandleKey.h" -#include "TrigDecisionEvent/TrigDecision.h" class StoreGateSvc; +namespace TrigDec { + class TrigDecision; +} + namespace HLT { class TrigNavStructure; } diff --git a/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/DecisionUnpackerStandalone.h b/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/DecisionUnpackerStandalone.h index f4784403510..08f81638859 100644 --- a/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/DecisionUnpackerStandalone.h +++ b/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/DecisionUnpackerStandalone.h @@ -24,7 +24,7 @@ #include "xAODTrigger/TrigDecision.h" #include "xAODTrigger/TrigNavigation.h" -#include "StoreGate/ReadHandleKey.h" +#include "AsgDataHandles/ReadHandleKey.h" // Forward declaration(s): namespace HLT { diff --git a/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/ExpertMethods.h b/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/ExpertMethods.h index 71878fb3965..2e78e09266f 100644 --- a/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/ExpertMethods.h +++ b/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/ExpertMethods.h @@ -30,10 +30,10 @@ #include "TrigDecisionTool/Logger.h" -#include "AthenaKernel/SlotSpecificObj.h" #if !defined(XAOD_STANDALONE) && !defined(XAOD_ANALYSIS) #include "TrigNavigation/NavigationCore.h" +#include "AthenaKernel/SlotSpecificObj.h" #endif namespace HLT { @@ -53,7 +53,12 @@ namespace Trig { class ExpertMethods : public virtual Logger { public: +#if !defined(XAOD_STANDALONE) && !defined(XAOD_ANALYSIS) ExpertMethods(SG::SlotSpecificObj<Trig::CacheGlobalMemory>* m_cacheGlobalMemory); +#else + ExpertMethods(Trig::CacheGlobalMemory* m_cacheGlobalMemory); +#endif + virtual ~ExpertMethods(); /** @@ -92,9 +97,9 @@ namespace Trig { /** * @brief return HLT::NavigationCore **/ -#if !defined(XAOD_STANDALONE) && !defined(XAOD_ANALYSIS) +#if !defined(XAOD_STANDALONE) && !defined(XAOD_ANALYSIS) // Full Athena const HLT::NavigationCore* getNavigation() const; -#else +#else // Analysis or Standalone const HLT::TrigNavStructure* getNavigation() const; #endif @@ -106,7 +111,12 @@ namespace Trig { private: - SG::SlotSpecificObj<Trig::CacheGlobalMemory>* m_cacheGlobalMemory; +#if !defined(XAOD_STANDALONE) && !defined(XAOD_ANALYSIS) // Full Athena + SG::SlotSpecificObj<Trig::CacheGlobalMemory>* m_cacheGlobalMemory; +#else // Analysis or Standalone + Trig::CacheGlobalMemory* m_cacheGlobalMemory; +#endif + Trig::CacheGlobalMemory* cgm(bool onlyConfig=false) const; bool m_useExperimentalAndExpertMethods; diff --git a/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/TrigDecisionTool.h b/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/TrigDecisionTool.h index 6316ea07216..ff65a864512 100755 --- a/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/TrigDecisionTool.h +++ b/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/TrigDecisionTool.h @@ -22,11 +22,12 @@ #include "AsgTools/AsgMetadataTool.h" #include "AsgTools/ToolHandle.h" +#include "AsgTools/PropertyWrapper.h" #include "TrigConfInterfaces/ITrigConfigTool.h" #ifndef XAOD_STANDALONE #include "AthenaBaseComps/AthMessaging.h" - +#include "EventInfo/EventInfo.h" #ifndef XAOD_ANALYSIS #include "TrigNavigation/Navigation.h" @@ -46,7 +47,6 @@ #include "xAODTrigger/TrigDecision.h" #include "xAODTrigger/TrigNavigation.h" -#include "EventInfo/EventInfo.h" // base classes #include "TrigDecisionTool/TrigDecisionToolCore.h" @@ -119,7 +119,8 @@ namespace Trig { private: bool configKeysMatch(uint32_t smk, uint32_t lvl1psk, uint32_t hltpsk); - SG::SlotSpecificObj< std::vector<uint32_t> > m_configKeysCache; //!< cache for config keys. only update CacheGlobalMemory when these change + + std::vector<uint32_t>* getKeys(); ToolHandle<TrigConf::ITrigConfigTool> m_configTool{this, "ConfigTool", "TrigConf::xAODConfigTool"}; //!< trigger configuration service handle @@ -127,25 +128,33 @@ namespace Trig { #if !defined(XAOD_STANDALONE) && !defined(XAOD_ANALYSIS) ServiceHandle<TrigConf::ITrigConfigSvc> m_configSvc{this, "TrigConfigSvc", ""}; //!< trigger configuration service handle ToolHandle<HLT::Navigation> m_fullNavigation; - #endif - HLT::TrigNavStructure* m_navigation; - - Gaudi::Property<bool> m_acceptMultipleInstance{this, "AcceptMultipleInstance", false}; - SG::ReadHandleKey<xAOD::TrigNavigation> m_navigationKey {this, "NavigationKey", "TrigNavigation", - "Storegate key of Run1, Run2 Trig Navigation"}; - - SG::ReadHandleKey<TrigDec::TrigDecision> m_oldDecisionKey {this, "OldTrigDecisionKey", "TrigDecision", - "Storegate key of old pre-xAOD Decision object"}; + Gaudi::Property<bool> m_useOldEventInfoDecisionFormat {this, "UseOldEventInfoDecisionFormat", false, + "For use when reading old BS with trigger decision information available in the EventInfo"}; SG::ReadHandleKey<EventInfo> m_oldEventInfoKey {this, "OldEventInfoKey", "EventInfo", "Storegate key of old pre-xAOD EventInfo object"}; + SG::ReadHandleKey<TrigDec::TrigDecision> m_oldDecisionKey {this, "OldTrigDecisionKey", "TrigDecision", + "Storegate key of old pre-xAOD Decision object"}; + Gaudi::Property<bool> m_useRun1DecisionFormat {this, "UseAODDecision", false, "For use when reading old ESD/AOD with only a TrigDec::TrigDecision and no xAOD::TrigDecision"}; - Gaudi::Property<bool> m_useOldEventInfoDecisionFormat {this, "UseOldEventInfoDecisionFormat", false, - "For use when reading old BS with trigger decision information available in the EventInfo"}; + SG::SlotSpecificObj< std::vector<uint32_t> > m_configKeysCache; //!< cache for config keys. only update CacheGlobalMemory when these change + + #else // Analysis or standalone + + std::vector<uint32_t> m_configKeysCache; //!< cache for config keys. only update CacheGlobalMemory when these change + + #endif + + HLT::TrigNavStructure* m_navigation; + + Gaudi::Property<bool> m_acceptMultipleInstance{this, "AcceptMultipleInstance", false}; + + SG::ReadHandleKey<xAOD::TrigNavigation> m_navigationKey {this, "NavigationKey", "TrigNavigation", + "Storegate key of Run1, Run2 Trig Navigation"}; /// @name Run 3 properties /// @{ diff --git a/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/TrigDecisionToolCore.h b/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/TrigDecisionToolCore.h index 7fb149ed732..1bc0d47cd52 100644 --- a/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/TrigDecisionToolCore.h +++ b/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/TrigDecisionToolCore.h @@ -62,7 +62,13 @@ namespace Trig { private: - SG::SlotSpecificObj<Trig::CacheGlobalMemory> m_cacheGlobalMemory; + +#if !defined(XAOD_STANDALONE) && !defined(XAOD_ANALYSIS) // Full Athena + SG::SlotSpecificObj<Trig::CacheGlobalMemory> m_cacheGlobalMemory; +#else // Analysis or Standalone + Trig::CacheGlobalMemory m_cacheGlobalMemory; +#endif + Trig::ExpertMethods* m_expertMethods; TrigDecisionToolCore (const TrigDecisionToolCore&); TrigDecisionToolCore& operator= (const TrigDecisionToolCore&); diff --git a/Trigger/TrigAnalysis/TrigDecisionTool/src/DecisionUnpackerAthena.cxx b/Trigger/TrigAnalysis/TrigDecisionTool/src/DecisionUnpackerAthena.cxx index 7ff8b090b3d..36f0fc0660d 100644 --- a/Trigger/TrigAnalysis/TrigDecisionTool/src/DecisionUnpackerAthena.cxx +++ b/Trigger/TrigAnalysis/TrigDecisionTool/src/DecisionUnpackerAthena.cxx @@ -14,6 +14,8 @@ #include "TrigDecisionTool/DecisionUnpackerAthena.h" #include "TrigDecisionTool/DecisionObjectHandleAthena.h" #include "TrigNavigation/NavigationCore.h" +#include "TrigDecisionEvent/TrigDecision.h" + namespace Trig { DecisionUnpackerAthena::DecisionUnpackerAthena(SG::ReadHandleKey<TrigDec::TrigDecision>* olddeckey) : m_handle(new DecisionObjectHandleAthena(olddeckey)){ diff --git a/Trigger/TrigEvent/TrigDecisionEvent/TrigDecisionEvent/TrigDecision.h b/Trigger/TrigEvent/TrigDecisionEvent/TrigDecisionEvent/TrigDecision.h index ce5f9b9ab1b..f2191f60068 100755 --- a/Trigger/TrigEvent/TrigDecisionEvent/TrigDecisionEvent/TrigDecision.h +++ b/Trigger/TrigEvent/TrigDecisionEvent/TrigDecisionEvent/TrigDecision.h @@ -29,7 +29,7 @@ #include "TrigSteeringEvent/Lvl1Result.h" #include "TrigSteeringEvent/HLTResult.h" -#include "AthenaKernel/CLASS_DEF.h" +#include "xAODCore/CLASS_DEF.h" #include <string> #include <stdint.h> diff --git a/Trigger/TrigEvent/TrigSteeringEvent/CMakeLists.txt b/Trigger/TrigEvent/TrigSteeringEvent/CMakeLists.txt index cb0a27f8fa8..fbfdd079e27 100644 --- a/Trigger/TrigEvent/TrigSteeringEvent/CMakeLists.txt +++ b/Trigger/TrigEvent/TrigSteeringEvent/CMakeLists.txt @@ -81,7 +81,7 @@ atlas_add_test( TrigPassBits_test LINK_LIBRARIES TrigSteeringEvent POST_EXEC_SCRIPT nopost.sh ) -if( NOT XAOD_STANDALONE ) +if( NOT XAOD_STANDALONE AND NOT XAOD_ANALYSIS ) atlas_add_test( Operators_test SOURCES test/Operators_test.cxx LINK_LIBRARIES AthenaKernel GaudiKernel TrigSteeringEvent diff --git a/Trigger/TrigEvent/TrigSteeringEvent/TrigSteeringEvent/GenericResult.h b/Trigger/TrigEvent/TrigSteeringEvent/TrigSteeringEvent/GenericResult.h index 7ee2c098d5b..0a40be1ddca 100644 --- a/Trigger/TrigEvent/TrigSteeringEvent/TrigSteeringEvent/GenericResult.h +++ b/Trigger/TrigEvent/TrigSteeringEvent/TrigSteeringEvent/GenericResult.h @@ -16,7 +16,7 @@ */ #include <stdint.h> -#include "AthenaKernel/CLASS_DEF.h" +#include "xAODCore/CLASS_DEF.h" class GenericResult { public: diff --git a/Trigger/TrigEvent/TrigSteeringEvent/TrigSteeringEvent/HLTResult.h b/Trigger/TrigEvent/TrigSteeringEvent/TrigSteeringEvent/HLTResult.h index 1af1bc3a6e9..7e0860b64b8 100644 --- a/Trigger/TrigEvent/TrigSteeringEvent/TrigSteeringEvent/HLTResult.h +++ b/Trigger/TrigEvent/TrigSteeringEvent/TrigSteeringEvent/HLTResult.h @@ -19,8 +19,14 @@ #include <stdint.h> #include "TrigSteeringEvent/Enums.h" #include "TrigSteeringEvent/GenericResult.h" + +#ifdef XAOD_STANDALONE +#include "xAODCore/ClassID_traits.h" +#else #include "AthenaKernel/IClassIDSvc.h" -#include "AthenaKernel/CLASS_DEF.h" +#endif + +#include "xAODCore/CLASS_DEF.h" #include "CxxUtils/checker_macros.h" /**************************************************************************************** diff --git a/Trigger/TrigEvent/TrigSteeringEvent/TrigSteeringEvent/Lvl1Result.h b/Trigger/TrigEvent/TrigSteeringEvent/TrigSteeringEvent/Lvl1Result.h index 53ae0e6c79f..39533970fe2 100644 --- a/Trigger/TrigEvent/TrigSteeringEvent/TrigSteeringEvent/Lvl1Result.h +++ b/Trigger/TrigEvent/TrigSteeringEvent/TrigSteeringEvent/Lvl1Result.h @@ -23,7 +23,7 @@ #define TRIGSTEERINGEVENT_Lvl1Result_H #include <stdint.h> -#include "AthenaKernel/CLASS_DEF.h" +#include "xAODCore/CLASS_DEF.h" #include "TrigSteeringEvent/Lvl1Item.h" namespace LVL1CTP { @@ -77,6 +77,7 @@ namespace LVL1CTP { } // end of namespace + CLASS_DEF( LVL1CTP::Lvl1Result, 21091893, 1) #endif diff --git a/Trigger/TrigEvent/TrigSteeringEvent/src/HLTResult.cxx b/Trigger/TrigEvent/TrigSteeringEvent/src/HLTResult.cxx index 08fe8e47f67..eca55294878 100644 --- a/Trigger/TrigEvent/TrigSteeringEvent/src/HLTResult.cxx +++ b/Trigger/TrigEvent/TrigSteeringEvent/src/HLTResult.cxx @@ -5,7 +5,6 @@ #include "TrigSteeringEvent/HLTResult.h" #include "TrigSteeringEvent/HLTExtraData.h" -#include "AthenaKernel/CLASS_DEF.h" #include <cassert> #include <algorithm> #include <numeric> diff --git a/Trigger/TrigSteer/TrigCompositeUtils/CMakeLists.txt b/Trigger/TrigSteer/TrigCompositeUtils/CMakeLists.txt index 8788fd23e45..889df3253c3 100644 --- a/Trigger/TrigSteer/TrigCompositeUtils/CMakeLists.txt +++ b/Trigger/TrigSteer/TrigCompositeUtils/CMakeLists.txt @@ -4,19 +4,16 @@ atlas_subdir( TrigCompositeUtils ) # Set up the (non-)standalone compilation. -set( extra_srcs ) set( extra_libs ) if( NOT XAOD_STANDALONE ) - set( extra_srcs src/*.cxx ) - set( extra_libs GaudiKernel AthenaKernel AthLinks StoreGateLib AthContainers - xAODTrigger ) + set( extra_libs GaudiKernel AthenaKernel AthLinks StoreGateLib AthContainers ) endif() # Add the package's dual use library. atlas_add_library( TrigCompositeUtilsLib - TrigCompositeUtils/*.h TrigCompositeUtils/*.icc Root/*.cxx ${extra_srcs} + TrigCompositeUtils/*.h TrigCompositeUtils/*.icc Root/*.cxx PUBLIC_HEADERS TrigCompositeUtils - LINK_LIBRARIES TrigConfHLTUtilsLib CxxUtils AsgMessagingLib AsgDataHandlesLib TrigDecisionInterface xAODTrigger ${extra_libs} ) + LINK_LIBRARIES TrigConfHLTUtilsLib CxxUtils AsgMessagingLib AsgDataHandlesLib AsgTools TrigDecisionInterface xAODBase xAODTrigger ${extra_libs} ) # Install files from the package. atlas_install_python_modules( python/*.py POST_BUILD_CMD ${ATLAS_FLAKE8} ) diff --git a/Trigger/TrigSteer/TrigCompositeUtils/src/NavGraph.cxx b/Trigger/TrigSteer/TrigCompositeUtils/Root/NavGraph.cxx similarity index 100% rename from Trigger/TrigSteer/TrigCompositeUtils/src/NavGraph.cxx rename to Trigger/TrigSteer/TrigCompositeUtils/Root/NavGraph.cxx diff --git a/Trigger/TrigSteer/TrigCompositeUtils/Root/TrigCompositeUtils.cxx b/Trigger/TrigSteer/TrigCompositeUtils/Root/TrigCompositeUtils.cxx index 2275e2e1ba2..f050f42c4e7 100644 --- a/Trigger/TrigSteer/TrigCompositeUtils/Root/TrigCompositeUtils.cxx +++ b/Trigger/TrigSteer/TrigCompositeUtils/Root/TrigCompositeUtils.cxx @@ -2,9 +2,376 @@ Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ +// See similar workaround the lack of CLID in standalone releases in TrigComposite_v1.h +#include "xAODBase/IParticleContainer.h" +#ifdef XAOD_STANDALONE +#include "xAODCore/CLASS_DEF.h" +CLASS_DEF( xAOD::IParticleContainer, 1241842700, 1 ) +#endif // XAOD_STANDALONE + +#include "AsgDataHandles/WriteHandle.h" +#include "AsgDataHandles/ReadHandle.h" +#include "AthContainers/AuxElement.h" + #include "TrigCompositeUtils/TrigCompositeUtils.h" -namespace TrigCompositeUtils { +#include <unordered_map> +#include <regex> +#include <iomanip> // std::setfill + +static const SG::AuxElement::Accessor< std::vector<TrigCompositeUtils::DecisionID> > readWriteAccessor("decisions"); +static const SG::AuxElement::ConstAccessor< std::vector<TrigCompositeUtils::DecisionID> > readOnlyAccessor("decisions"); + +namespace TrigCompositeUtils { ANA_MSG_SOURCE (msgFindLink, "TrigCompositeUtils.findLink") + ANA_MSG_SOURCE (msgRejected, "TrigCompositeUtils.getRejectedDecisionNodes") + + + SG::WriteHandle<DecisionContainer> createAndStore( const SG::WriteHandleKey<DecisionContainer>& key, const EventContext& ctx ) { + SG::WriteHandle<DecisionContainer> handle( key, ctx ); + auto data = std::make_unique<DecisionContainer>() ; + auto aux = std::make_unique<DecisionAuxContainer>() ; + data->setStore( aux.get() ); + handle.record( std::move( data ), std::move( aux ) ).ignore(); + return handle; + } + + void createAndStore( SG::WriteHandle<DecisionContainer>& handle ) { + auto data = std::make_unique<DecisionContainer>() ; + auto aux = std::make_unique<DecisionAuxContainer>() ; + data->setStore( aux.get() ); + handle.record( std::move( data ), std::move( aux ) ).ignore(); + } + + Decision* newDecisionIn ( DecisionContainer* dc, const std::string& name) { + Decision * x = new Decision; + dc->push_back( x ); + if ( ! name.empty() ) { + x->setName( name ); + } + return x; + } + + Decision* newDecisionIn ( DecisionContainer* dc, const Decision* dOld, const std::string& name, const EventContext& ctx ) { + Decision* dNew = newDecisionIn( dc, name ); + linkToPrevious(dNew, dOld, ctx); // Sets up link to 'seed' collection, points to dOld + return dNew; + } + + void addDecisionID( DecisionID id, Decision* d ) { + std::vector<DecisionID>& decisions = readWriteAccessor( *d ); + if ( decisions.size() == 0 or decisions.back() != id) + decisions.push_back( id ); + } + + void decisionIDs( const Decision* d, DecisionIDContainer& destination ) { + const std::vector<DecisionID>& decisions = readOnlyAccessor( *d ); + destination.insert( decisions.begin(), decisions.end() ); + } + + const std::vector<DecisionID>& decisionIDs( const Decision* d ) { + return readOnlyAccessor( *d ); + } + + std::vector<DecisionID>& decisionIDs( Decision* d ) { + return readWriteAccessor( *d ); + } + + void insertDecisionIDs(const Decision* src, Decision* dest ){ + DecisionIDContainer srcIds; + decisionIDs( src, srcIds ); // Now stored in a set + insertDecisionIDs( srcIds, dest); + } + + void insertDecisionIDs( const DecisionIDContainer& src, Decision* dest ) { + DecisionIDContainer collateIDs; + // Decision are xAOD objects backed by a std::vector + // Here we use a std::set to de-duplicate IDs from src and dest before setting dest + decisionIDs( dest, collateIDs ); // Set operation 1. Get from dest + collateIDs.insert( src.begin(), src.end() ); // Set operation 2. Get from src + decisionIDs( dest ).clear(); // Clear target + // Copy from set to (ordered) vector + decisionIDs( dest ).insert( decisionIDs(dest).end(), collateIDs.begin(), collateIDs.end() ); + } + + void uniqueDecisionIDs(Decision* dest) { + // Re-use above insertDecisionIDs method. + // This implicitly performs de-duplication + return insertDecisionIDs(dest, dest); + } + + bool allFailed( const Decision* d ) { + const std::vector<DecisionID>& decisions = readOnlyAccessor( *d ); + return decisions.empty(); + } + + bool isAnyIDPassing( const Decision* d, const DecisionIDContainer& required ) { + for ( DecisionID id : readOnlyAccessor( *d ) ) { + if ( required.count( id ) > 0 ) { + return true; + } + } + return false; + } + + bool passed( DecisionID id, const DecisionIDContainer& idSet ) { + return idSet.count( id ) != 0; + } + +#if !defined(XAOD_STANDALONE) && !defined(XAOD_ANALYSIS) // Full athena + ElementLink<DecisionContainer> decisionToElementLink(const Decision* d, const EventContext& ctx) { + const DecisionContainer* container = dynamic_cast<const DecisionContainer*>( d->container() ); + if( ! container ) { + throw std::runtime_error("TrigCompositeUtils::convertToElementLink Using convertToElementLink(d) requires that the Decision d is already in a container"); + } + return ElementLink<DecisionContainer>(*container, d->index(), ctx); + } +#else // Analysis or Standalone + ElementLink<DecisionContainer> decisionToElementLink(const Decision* d, const EventContext&) { + const DecisionContainer* container = dynamic_cast<const DecisionContainer*>( d->container() ); + if( ! container ) { + throw std::runtime_error("TrigCompositeUtils::convertToElementLink Using convertToElementLink(d) requires that the Decision d is already in a container"); + } + return ElementLink<DecisionContainer>(*container, d->index()); + } +#endif + + void linkToPrevious( Decision* d, const std::string& previousCollectionKey, size_t previousIndex ) { + ElementLink<DecisionContainer> seed = ElementLink<DecisionContainer>( previousCollectionKey, previousIndex ); + if (!seed.isValid()) { + throw std::runtime_error("TrigCompositeUtils::linkToPrevious Invalid Decision Link key or index provided"); + } else { + d->addObjectCollectionLink("seed", seed); + } + } + + void linkToPrevious( Decision* d, const Decision* dOld, const EventContext& ctx ) { + d->addObjectCollectionLink(seedString(), decisionToElementLink(dOld, ctx)); + } + + bool hasLinkToPrevious( const Decision* d ) { + return d->hasObjectCollectionLinks( seedString() ); + } + + const ElementLinkVector<DecisionContainer> getLinkToPrevious( const Decision* d ) { + return d->objectCollectionLinks<DecisionContainer>( seedString() ); + } + + + bool copyLinks(const Decision* src, Decision* dest) { + return dest->copyAllLinksFrom(src); + } + + + HLT::Identifier createLegName(const HLT::Identifier& chainIdentifier, size_t counter) { + if (chainIdentifier.name().substr(0,4) != "HLT_") { + throw std::runtime_error("TrigCompositeUtils::createLegName chainIdentifier '"+chainIdentifier.name()+"' does not start 'HLT_'"); + } + if (counter > 999) { + throw std::runtime_error("TrigCompositeUtils::createLegName Leg counters above 999 are invalid."); + } + std::stringstream legStringStream; + legStringStream << "leg" << std::setfill('0') << std::setw(3) << counter << "_" << chainIdentifier.name(); + return HLT::Identifier( legStringStream.str() ); + } + + + HLT::Identifier getIDFromLeg(const HLT::Identifier& legIdentifier) { + if (legIdentifier.name().find("HLT_",0)==0 ){ + return legIdentifier; + } else if (isLegId(legIdentifier)){ + return HLT::Identifier(legIdentifier.name().substr(7)); + } else{ + throw std::runtime_error("TrigCompositeUtils::getIDFromLeg legIdentifier '"+legIdentifier.name()+"' does not start with 'HLT_' or 'leg' "); + } + } + + + bool isLegId(const HLT::Identifier& legIdentifier) { + return (legIdentifier.name().find("leg",0)==0); + } + + + const Decision* find( const Decision* start, const std::function<bool( const Decision* )>& filter ) { + if ( filter( start ) ) return start; + + if ( hasLinkToPrevious(start) ) { + const ElementLinkVector<DecisionContainer> seeds = getLinkToPrevious(start); + for (const ElementLink<DecisionContainer>& seedEL : seeds) { + const Decision* result = find( *seedEL, filter ); + if (result) return result; + } + } + + return nullptr; + } + + bool HasObject::operator()( const Decision* composite ) const { + return composite->hasObjectLink( m_name ); + } + + bool HasObjectCollection::operator()( const Decision* composite ) const { + return composite->hasObjectCollectionLinks( m_name ); + } + + std::vector<const Decision*> getRejectedDecisionNodes(asg::EventStoreType* eventStore, const DecisionID id) { + std::vector<const Decision*> output; + // The list of containers we need to read can change on a file-by-file basis (it depends on the SMK) + // Hence we query SG for all collections rather than maintain a large and ever changing ReadHandleKeyArray + + std::vector<std::string> keys; + // TODO TODO TODO NEED TO REPLACE THIS WITH A STANDALONE-FRIENDLY VERSION +#ifndef XAOD_STANDALONE + eventStore->keys(static_cast<CLID>( ClassID_traits< DecisionContainer >::ID() ), keys); +#else + throw std::runtime_error("Cannot yet obtain rejected HLT features in AnalysisBase"); +#endif + + // Loop over each DecisionContainer, + for (const std::string& key : keys) { + // Get and check this container + if ( key.find("HLTNav") != 0 ) { + continue; // Only concerned about the decision containers which make up the navigation, they have name prefix of HLTNav + } + if ( key == "HLTNav_Summary" ) { + continue; // This is where accepted paths start. We are looking for rejected ones + } + const DecisionContainer* container = nullptr; + if ( eventStore->retrieve( container, key ).isFailure() ) { + throw std::runtime_error("Unable to retrieve " + key + " from event store."); + } + for (const Decision* d : *container) { + if (!d->hasObjectLink(featureString())) { + // TODO add logic for ComboHypo where this is expected + continue; // Only want Decision objects created by HypoAlgs + } + const ElementLinkVector<DecisionContainer> mySeeds = d->objectCollectionLinks<DecisionContainer>(seedString()); + if (mySeeds.size() == 0) { + continue; + } + const bool allSeedsValid = std::all_of(mySeeds.begin(), mySeeds.end(), [](const ElementLink<DecisionContainer>& s) { return s.isValid(); }); + if (!allSeedsValid) { + using namespace msgRejected; + ANA_MSG_WARNING("A Decision object in " << key << " has invalid seeds. " + << "The trigger navigation information is incomplete. Skipping this Decision object."); + continue; + } + DecisionIDContainer activeChainsIntoThisDecision; + decisionIDs(*(mySeeds.at(0)), activeChainsIntoThisDecision); // Get list of active chains from the first parent + if (mySeeds.size() > 1) { + for (size_t i = 1; i < mySeeds.size(); ++i) { + // If there are more than one parent, we only want to keep the intersection of all of the seeds + DecisionIDContainer moreActiveChains; + decisionIDs(*(mySeeds.at(i)), moreActiveChains); + DecisionIDContainer intersection; + std::set_intersection(activeChainsIntoThisDecision.begin(), activeChainsIntoThisDecision.end(), + moreActiveChains.begin(), moreActiveChains.end(), + std::inserter(intersection, intersection.begin())); + activeChainsIntoThisDecision = intersection; // Update the output to only be the intersection and continue to any other seeds + } + } + // We now know what chains were active coming into this Decision (d) from ALL seeds + // This is the logic required for each HypoTool to have activated and checked if its chain passes + // So the size of activeChainsIntoThisDecision corresponds to the number of HypoTools which will have run + // What do we care about? A chain, or all chains? + DecisionIDContainer chainsToCheck; + if (id == 0) { // We care about *all* chains + chainsToCheck = activeChainsIntoThisDecision; + } else { // We care about *one* chain + chainsToCheck.insert(id); + } + // We have found a rejected decision node *iff* a chainID to check is *not* present here + // I.e. the HypoTool for the chain returned a NEGATIVE decision + DecisionIDContainer activeChainsPassedByThisDecision; + decisionIDs(d, activeChainsPassedByThisDecision); + for (const DecisionID checkID : chainsToCheck) { + if (activeChainsPassedByThisDecision.count(checkID) == 0 && // I was REJECTED here ... + activeChainsIntoThisDecision.count(checkID) == 1) { // ... but PASSSED by all my inputs + output.push_back(d); + break; + } + } + } + } + return output; + } + + void recursiveGetDecisionsInternal(const Decision* node, + const Decision* comingFrom, + NavGraph& navGraph, + const DecisionID id, + const bool enforceDecisionOnNode) { + + // Does this Decision satisfy the chain requirement? + DecisionIDContainer idSet = {id}; + if (enforceDecisionOnNode && id != 0 && !isAnyIDPassing(node, idSet)) { + return; // Stop propagating down this leg. It does not concern the chain with DecisionID = id + } + + // This Decision object is part of this path through the Navigation + navGraph.addNode(node, comingFrom); + + // Continue to the path(s) by looking at this Decision object's seed(s) + if ( hasLinkToPrevious(node) ) { + // Do the recursion + for ( ElementLink<DecisionContainer> seed : getLinkToPrevious(node)) { + const Decision* seedDecision = *(seed); // Dereference ElementLink + // Sending true as final parameter for enforceDecisionOnStartNode as we are recursing away from the supplied start node + recursiveGetDecisionsInternal(seedDecision, node, navGraph, id, /*enforceDecisionOnNode*/ true); + } + } + return; + } + + void recursiveGetDecisions(const Decision* start, + NavGraph& navGraph, + const DecisionID id, + const bool enforceDecisionOnStartNode) { + + // Note: we do not require navGraph to be an empty graph. We can extend it. + recursiveGetDecisionsInternal(start, /*comingFrom*/nullptr, navGraph, id, enforceDecisionOnStartNode); + + return; + } + + + std::string dump( const Decision* tc, std::function< std::string( const Decision* )> printerFnc ) { + std::string ret; + ret += printerFnc( tc ); + if ( hasLinkToPrevious(tc) ) { + const ElementLinkVector<DecisionContainer> seeds = getLinkToPrevious(tc); + for (const ElementLink<DecisionContainer>& seedEL : seeds) { + ret += " -> " + dump( *seedEL, printerFnc ); + } + } + return ret; + } + + + const std::string& initialRoIString() { + return Decision::s_initialRoIString; + } + + const std::string& initialRecRoIString() { + return Decision::s_initialRecRoIString; + } + + const std::string& roiString() { + return Decision::s_roiString; + } + + const std::string& viewString() { + return Decision::s_viewString; + } + + const std::string& featureString() { + return Decision::s_featureString; + } + + const std::string& seedString() { + return Decision::s_seedString; + } + } + diff --git a/Trigger/TrigSteer/TrigCompositeUtils/TrigCompositeUtils/TrigCompositeUtils.h b/Trigger/TrigSteer/TrigCompositeUtils/TrigCompositeUtils/TrigCompositeUtils.h index a5eaf77bd2d..40862643bb3 100644 --- a/Trigger/TrigSteer/TrigCompositeUtils/TrigCompositeUtils/TrigCompositeUtils.h +++ b/Trigger/TrigSteer/TrigCompositeUtils/TrigCompositeUtils/TrigCompositeUtils.h @@ -18,6 +18,12 @@ #include "AsgTools/CurrentContext.h" #include "AsgTools/EventStoreType.h" #include "AsgMessaging/MsgStream.h" +#include "AsgMessaging/MessageCheck.h" + + +#ifdef XAOD_STANDALONE +#include "AsgTools/SgTEvent.h" +#endif #include "AthContainers/AuxElement.h" #include "xAODTrigger/TrigCompositeContainer.h" @@ -30,6 +36,8 @@ namespace TrigCompositeUtils { + ANA_MSG_HEADER (msgRejected) + /// alias types, for readability and to simplify future evolution typedef SG::WriteHandle<DecisionContainer> DecisionWriteHandle; diff --git a/Trigger/TrigSteer/TrigCompositeUtils/src/TrigCompositeUtils.cxx b/Trigger/TrigSteer/TrigCompositeUtils/src/TrigCompositeUtils.cxx deleted file mode 100644 index e570baed736..00000000000 --- a/Trigger/TrigSteer/TrigCompositeUtils/src/TrigCompositeUtils.cxx +++ /dev/null @@ -1,356 +0,0 @@ -/* - Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration -*/ - -#include "StoreGate/WriteHandle.h" -#include "StoreGate/ReadHandle.h" -#include "AthContainers/AuxElement.h" -#include "GaudiKernel/EventContext.h" -#include "GaudiKernel/GaudiException.h" - -#include "StoreGate/WriteHandle.h" -#include "TrigCompositeUtils/TrigCompositeUtils.h" - -#include <unordered_map> -#include <regex> - -static const SG::AuxElement::Accessor< std::vector<TrigCompositeUtils::DecisionID> > readWriteAccessor("decisions"); -static const SG::AuxElement::ConstAccessor< std::vector<TrigCompositeUtils::DecisionID> > readOnlyAccessor("decisions"); - -namespace TrigCompositeUtils { - - SG::WriteHandle<DecisionContainer> createAndStore( const SG::WriteHandleKey<DecisionContainer>& key, const EventContext& ctx ) { - SG::WriteHandle<DecisionContainer> handle( key, ctx ); - auto data = std::make_unique<DecisionContainer>() ; - auto aux = std::make_unique<DecisionAuxContainer>() ; - data->setStore( aux.get() ); - handle.record( std::move( data ), std::move( aux ) ).ignore(); - return handle; - } - - void createAndStore( SG::WriteHandle<DecisionContainer>& handle ) { - auto data = std::make_unique<DecisionContainer>() ; - auto aux = std::make_unique<DecisionAuxContainer>() ; - data->setStore( aux.get() ); - handle.record( std::move( data ), std::move( aux ) ).ignore(); - } - - Decision* newDecisionIn ( DecisionContainer* dc, const std::string& name) { - Decision * x = new Decision; - dc->push_back( x ); - if ( ! name.empty() ) { - x->setName( name ); - } - return x; - } - - Decision* newDecisionIn ( DecisionContainer* dc, const Decision* dOld, const std::string& name, const EventContext& ctx ) { - Decision* dNew = newDecisionIn( dc, name ); - linkToPrevious(dNew, dOld, ctx); // Sets up link to 'seed' collection, points to dOld - return dNew; - } - - void addDecisionID( DecisionID id, Decision* d ) { - std::vector<DecisionID>& decisions = readWriteAccessor( *d ); - if ( decisions.size() == 0 or decisions.back() != id) - decisions.push_back( id ); - } - - void decisionIDs( const Decision* d, DecisionIDContainer& destination ) { - const std::vector<DecisionID>& decisions = readOnlyAccessor( *d ); - destination.insert( decisions.begin(), decisions.end() ); - } - - const std::vector<DecisionID>& decisionIDs( const Decision* d ) { - return readOnlyAccessor( *d ); - } - - std::vector<DecisionID>& decisionIDs( Decision* d ) { - return readWriteAccessor( *d ); - } - - void insertDecisionIDs(const Decision* src, Decision* dest ){ - DecisionIDContainer srcIds; - decisionIDs( src, srcIds ); // Now stored in a set - insertDecisionIDs( srcIds, dest); - } - - void insertDecisionIDs( const DecisionIDContainer& src, Decision* dest ) { - DecisionIDContainer collateIDs; - // Decision are xAOD objects backed by a std::vector - // Here we use a std::set to de-duplicate IDs from src and dest before setting dest - decisionIDs( dest, collateIDs ); // Set operation 1. Get from dest - collateIDs.insert( src.begin(), src.end() ); // Set operation 2. Get from src - decisionIDs( dest ).clear(); // Clear target - // Copy from set to (ordered) vector - decisionIDs( dest ).insert( decisionIDs(dest).end(), collateIDs.begin(), collateIDs.end() ); - } - - void uniqueDecisionIDs(Decision* dest) { - // Re-use above insertDecisionIDs method. - // This implicitly performs de-duplication - return insertDecisionIDs(dest, dest); - } - - bool allFailed( const Decision* d ) { - const std::vector<DecisionID>& decisions = readOnlyAccessor( *d ); - return decisions.empty(); - } - - bool isAnyIDPassing( const Decision* d, const DecisionIDContainer& required ) { - for ( DecisionID id : readOnlyAccessor( *d ) ) { - if ( required.count( id ) > 0 ) { - return true; - } - } - return false; - } - - bool passed( DecisionID id, const DecisionIDContainer& idSet ) { - return idSet.count( id ) != 0; - } - - ElementLink<DecisionContainer> decisionToElementLink(const Decision* d, const EventContext& ctx) { - const DecisionContainer* container = dynamic_cast<const DecisionContainer*>( d->container() ); - if( ! container ) { - throw GaudiException("Using convertToElementLink(d) requires that the Decision d is already in a container", - "TrigCompositeUtils::convertToElementLink", StatusCode::FAILURE); - } - return ElementLink<DecisionContainer>(*container, d->index(), ctx); - } - - void linkToPrevious( Decision* d, const std::string& previousCollectionKey, size_t previousIndex ) { - ElementLink<DecisionContainer> seed = ElementLink<DecisionContainer>( previousCollectionKey, previousIndex ); - if (!seed.isValid()) { - throw GaudiException("Invalid Decision Link key or index provided", "TrigCompositeUtils::linkToPrevious", StatusCode::FAILURE); - } else { - d->addObjectCollectionLink("seed", seed); - } - } - - void linkToPrevious( Decision* d, const Decision* dOld, const EventContext& ctx ) { - d->addObjectCollectionLink(seedString(), decisionToElementLink(dOld, ctx)); - } - - bool hasLinkToPrevious( const Decision* d ) { - return d->hasObjectCollectionLinks( seedString() ); - } - - const ElementLinkVector<DecisionContainer> getLinkToPrevious( const Decision* d ) { - return d->objectCollectionLinks<DecisionContainer>( seedString() ); - } - - - bool copyLinks(const Decision* src, Decision* dest) { - return dest->copyAllLinksFrom(src); - } - - - HLT::Identifier createLegName(const HLT::Identifier& chainIdentifier, size_t counter) { - if (chainIdentifier.name().substr(0,4) != "HLT_") { - throw GaudiException("chainIdentifier '"+chainIdentifier.name()+"' does not start 'HLT_'", - "TrigCompositeUtils::createLegName", StatusCode::FAILURE); - } - if (counter > 999) { - throw GaudiException("Leg counters above 999 are invalid.", "TrigCompositeUtils::createLegName", StatusCode::FAILURE); - } - std::stringstream legStringStream; - legStringStream << "leg" << std::setfill('0') << std::setw(3) << counter << "_" << chainIdentifier.name(); - return HLT::Identifier( legStringStream.str() ); - } - - - HLT::Identifier getIDFromLeg(const HLT::Identifier& legIdentifier) { - if (legIdentifier.name().find("HLT_",0)==0 ){ - return legIdentifier; - } else if (isLegId(legIdentifier)){ - return HLT::Identifier(legIdentifier.name().substr(7)); - } else{ - throw GaudiException("legIdentifier '"+legIdentifier.name()+"' does not start with 'HLT_' or 'leg' ", - "TrigCompositeUtils::getIDFromLeg", StatusCode::FAILURE); - } - } - - - bool isLegId(const HLT::Identifier& legIdentifier) { - return (legIdentifier.name().find("leg",0)==0); - } - - - const Decision* find( const Decision* start, const std::function<bool( const Decision* )>& filter ) { - if ( filter( start ) ) return start; - - if ( hasLinkToPrevious(start) ) { - const ElementLinkVector<DecisionContainer> seeds = getLinkToPrevious(start); - for (const ElementLink<DecisionContainer>& seedEL : seeds) { - const Decision* result = find( *seedEL, filter ); - if (result) return result; - } - } - - return nullptr; - } - - bool HasObject::operator()( const Decision* composite ) const { - return composite->hasObjectLink( m_name ); - } - - bool HasObjectCollection::operator()( const Decision* composite ) const { - return composite->hasObjectCollectionLinks( m_name ); - } - - std::vector<const Decision*> getRejectedDecisionNodes(StoreGateSvc* eventStore, const DecisionID id) { - std::vector<const Decision*> output; - // The list of containers we need to read can change on a file-by-file basis (it depends on the SMK) - // Hence we query SG for all collections rather than maintain a large and ever changing ReadHandleKeyArray - - std::vector<std::string> keys; - eventStore->keys(static_cast<CLID>( ClassID_traits< DecisionContainer >::ID() ), keys); - - // Loop over each DecisionContainer, - for (const std::string& key : keys) { - // Get and check this container - if ( key.find("HLTNav") != 0 ) { - continue; // Only concerned about the decision containers which make up the navigation, they have name prefix of HLTNav - } - if ( key == "HLTNav_Summary" ) { - continue; // This is where accepted paths start. We are looking for rejected ones - } - const DecisionContainer* container = nullptr; - if ( eventStore->retrieve( container, key ).isFailure() ) { - throw std::runtime_error("Unable to retrieve " + key + " from event store."); - } - for (const Decision* d : *container) { - if (!d->hasObjectLink(featureString())) { - // TODO add logic for ComboHypo where this is expected - continue; // Only want Decision objects created by HypoAlgs - } - const ElementLinkVector<DecisionContainer> mySeeds = d->objectCollectionLinks<DecisionContainer>(seedString()); - if (mySeeds.size() == 0) { - continue; - } - const bool allSeedsValid = std::all_of(mySeeds.begin(), mySeeds.end(), [](const ElementLink<DecisionContainer>& s) { return s.isValid(); }); - if (!allSeedsValid) { - MsgStream(Athena::getMessageSvc(), "TrigCompositeUtils::getRejectedDecisionNodes") << MSG::WARNING - << "A Decision object in " << key << " has invalid seeds. " - << "The trigger navigation information is incomplete. Skipping this Decision object." << endmsg; - continue; - } - DecisionIDContainer activeChainsIntoThisDecision; - decisionIDs(*(mySeeds.at(0)), activeChainsIntoThisDecision); // Get list of active chains from the first parent - if (mySeeds.size() > 1) { - for (size_t i = 1; i < mySeeds.size(); ++i) { - // If there are more than one parent, we only want to keep the intersection of all of the seeds - DecisionIDContainer moreActiveChains; - decisionIDs(*(mySeeds.at(i)), moreActiveChains); - DecisionIDContainer intersection; - std::set_intersection(activeChainsIntoThisDecision.begin(), activeChainsIntoThisDecision.end(), - moreActiveChains.begin(), moreActiveChains.end(), - std::inserter(intersection, intersection.begin())); - activeChainsIntoThisDecision = intersection; // Update the output to only be the intersection and continue to any other seeds - } - } - // We now know what chains were active coming into this Decision (d) from ALL seeds - // This is the logic required for each HypoTool to have activated and checked if its chain passes - // So the size of activeChainsIntoThisDecision corresponds to the number of HypoTools which will have run - // What do we care about? A chain, or all chains? - DecisionIDContainer chainsToCheck; - if (id == 0) { // We care about *all* chains - chainsToCheck = activeChainsIntoThisDecision; - } else { // We care about *one* chain - chainsToCheck.insert(id); - } - // We have found a rejected decision node *iff* a chainID to check is *not* present here - // I.e. the HypoTool for the chain returned a NEGATIVE decision - DecisionIDContainer activeChainsPassedByThisDecision; - decisionIDs(d, activeChainsPassedByThisDecision); - for (const DecisionID checkID : chainsToCheck) { - if (activeChainsPassedByThisDecision.count(checkID) == 0 && // I was REJECTED here ... - activeChainsIntoThisDecision.count(checkID) == 1) { // ... but PASSSED by all my inputs - output.push_back(d); - break; - } - } - } - } - return output; - } - - void recursiveGetDecisionsInternal(const Decision* node, - const Decision* comingFrom, - NavGraph& navGraph, - const DecisionID id, - const bool enforceDecisionOnNode) { - - // Does this Decision satisfy the chain requirement? - DecisionIDContainer idSet = {id}; - if (enforceDecisionOnNode && id != 0 && !isAnyIDPassing(node, idSet)) { - return; // Stop propagating down this leg. It does not concern the chain with DecisionID = id - } - - // This Decision object is part of this path through the Navigation - navGraph.addNode(node, comingFrom); - - // Continue to the path(s) by looking at this Decision object's seed(s) - if ( hasLinkToPrevious(node) ) { - // Do the recursion - for ( ElementLink<DecisionContainer> seed : getLinkToPrevious(node)) { - const Decision* seedDecision = *(seed); // Dereference ElementLink - // Sending true as final parameter for enforceDecisionOnStartNode as we are recursing away from the supplied start node - recursiveGetDecisionsInternal(seedDecision, node, navGraph, id, /*enforceDecisionOnNode*/ true); - } - } - return; - } - - void recursiveGetDecisions(const Decision* start, - NavGraph& navGraph, - const DecisionID id, - const bool enforceDecisionOnStartNode) { - - // Note: we do not require navGraph to be an empty graph. We can extend it. - recursiveGetDecisionsInternal(start, /*comingFrom*/nullptr, navGraph, id, enforceDecisionOnStartNode); - - return; - } - - - std::string dump( const Decision* tc, std::function< std::string( const Decision* )> printerFnc ) { - std::string ret; - ret += printerFnc( tc ); - if ( hasLinkToPrevious(tc) ) { - const ElementLinkVector<DecisionContainer> seeds = getLinkToPrevious(tc); - for (const ElementLink<DecisionContainer>& seedEL : seeds) { - ret += " -> " + dump( *seedEL, printerFnc ); - } - } - return ret; - } - - - const std::string& initialRoIString() { - return Decision::s_initialRoIString; - } - - const std::string& initialRecRoIString() { - return Decision::s_initialRecRoIString; - } - - const std::string& roiString() { - return Decision::s_roiString; - } - - const std::string& viewString() { - return Decision::s_viewString; - } - - const std::string& featureString() { - return Decision::s_featureString; - } - - const std::string& seedString() { - return Decision::s_seedString; - } - -} - -- GitLab