diff --git a/Trigger/TrigAnalysis/TrigDecisionTool/Root/CacheGlobalMemory.cxx b/Trigger/TrigAnalysis/TrigDecisionTool/Root/CacheGlobalMemory.cxx index f2935a0b5587eadad568a37fb437601845aa960c..4b09d09e4e0f14c88fb23c713727a246909aba18 100644 --- a/Trigger/TrigAnalysis/TrigDecisionTool/Root/CacheGlobalMemory.cxx +++ b/Trigger/TrigAnalysis/TrigDecisionTool/Root/CacheGlobalMemory.cxx @@ -60,6 +60,7 @@ Trig::CacheGlobalMemory::CacheGlobalMemory() : {} Trig::CacheGlobalMemory::~CacheGlobalMemory() { + std::lock_guard<std::mutex> lock(m_cgmMutex); delete m_unpacker; @@ -82,6 +83,7 @@ Trig::CacheGlobalMemory::~CacheGlobalMemory() { const Trig::ChainGroup* Trig::CacheGlobalMemory::createChainGroup(const std::vector< std::string >& triggerNames, const std::string& alias) { + std::lock_guard<std::mutex> lock(m_cgmMutex); // create a proper key std::vector< std::string > key=Trig::keyWrap(triggerNames); @@ -112,7 +114,7 @@ void Trig::CacheGlobalMemory::updateChainGroup(Trig::ChainGroup* chainGroup) { void Trig::CacheGlobalMemory::update(const TrigConf::HLTChainList* confChains, const TrigConf::CTPConfig* ctp) { - + std::lock_guard<std::mutex> lock(m_cgmMutex); ATH_MSG_DEBUG( "Updating configuration" ); // store a global reference to the initial answer m_confChains = confChains; @@ -178,33 +180,30 @@ void Trig::CacheGlobalMemory::update(const TrigConf::HLTChainList* confChains, for(auto ch : *m_confChains) { if (( ch->level() == "EF" || ch->level() == "HLT") && ch->streams().size()>0 ) { - ATH_MSG_DEBUG( "Stream: " << ch->chain_name() << " " - << ch->streams().size() ); - for(auto stream : ch->streams()) { - if( msgLvl( MSG::DEBUG ) ) { - msg() << " " << stream->stream(); - } - m_streams[stream->stream()].push_back(ch->chain_name()); - } + ATH_MSG_DEBUG( "Stream: " << ch->chain_name() << " " << ch->streams().size() ); + for(auto stream : ch->streams()) { if( msgLvl( MSG::DEBUG ) ) { - msg() << endmsg; - } + msg() << " " << stream->stream(); + } + m_streams[stream->stream()].push_back(ch->chain_name()); + } + if( msgLvl( MSG::DEBUG ) ) { + msg() << endmsg; + } } if ( ( ch->level() == "EF" || ch->level() == "HLT") && ch->groups().size()>0 ) { - ATH_MSG_DEBUG( "Groups: " << ch->chain_name() - << " " << ch->groups().size() ); - for(auto& group : ch->groups()) { - if( msgLvl( MSG::DEBUG ) ) { - msg() << " " << group; - } - m_groups[group].push_back(ch->chain_name()); + ATH_MSG_DEBUG( "Groups: " << ch->chain_name() << " " << ch->groups().size() ); + for(auto& group : ch->groups()) { + if( msgLvl( MSG::DEBUG ) ) { + msg() << " " << group; } - if( msgLvl( MSG::DEBUG ) ) { - msg() << endmsg; - } + m_groups[group].push_back(ch->chain_name()); + } + if( msgLvl( MSG::DEBUG ) ) { + msg() << endmsg; + } } } - // std::map<std::string, std::vector<std::string> >::iterator mstIt; for (mstIt=m_streams.begin(); mstIt != m_streams.end(); mstIt++) { @@ -212,8 +211,8 @@ void Trig::CacheGlobalMemory::update(const TrigConf::HLTChainList* confChains, std::vector< std::string > key_alias=Trig::keyWrap(Trig::convertStringToVector(alias)); ChGrIt preIt = m_chainGroupsRef.find(key_alias); if ( preIt != m_chainGroupsRef.end()) { - ATH_MSG_INFO( "Replacing predefined, stream based, chain group: " - << alias ); + ATH_MSG_INFO( "Replacing predefined, stream based, chain group: " + << alias ); // cg already exists (from previous config, we need to update it) preIt->second->m_patterns = mstIt->second; updateChainGroup(preIt->second); @@ -227,7 +226,7 @@ void Trig::CacheGlobalMemory::update(const TrigConf::HLTChainList* confChains, std::vector< std::string > key_alias=Trig::keyWrap(Trig::convertStringToVector(alias)); ChGrIt preIt = m_chainGroupsRef.find(key_alias); if (preIt != m_chainGroupsRef.end()) { - ATH_MSG_INFO( "Replacing predefined, config group based, chain " + ATH_MSG_INFO( "Replacing predefined, config group based, chain " << "group: " << alias ); preIt->second->m_patterns = mstIt->second; updateChainGroup(preIt->second); @@ -253,11 +252,11 @@ void Trig::CacheGlobalMemory::update(const TrigConf::HLTChainList* confChains, const HLT::Chain* Trig::CacheGlobalMemory::chain(const std::string& name) const { + std::lock_guard<std::mutex> lock(m_cgmMutex); auto i = m_efchainsByName.find(name); if (i != m_efchainsByName.end()) { return i->second; } - i = m_l2chainsByName.find(name); if ( i != m_l2chainsByName.end() ) { return i->second; @@ -293,6 +292,7 @@ const TrigConf::TriggerItem* Trig::CacheGlobalMemory::config_item(const std::str } float Trig::CacheGlobalMemory::item_prescale(int ctpid) const { + std::lock_guard<std::mutex> lock(m_cgmMutex); // find items in cache if ( m_itemsCache.count(ctpid) == 0 ) { ATH_MSG_ERROR( "item of CTP: " << ctpid @@ -317,6 +317,7 @@ const LVL1CTP::Lvl1Item* Trig::CacheGlobalMemory::item(const std::string& name) } const xAOD::TrigCompositeContainer* Trig::CacheGlobalMemory::expressStreamContainer() const { + std::lock_guard<std::mutex> lock(m_cgmMutex); if(!m_expressStreamContainer){ StatusCode sc = store()->retrieve(m_expressStreamContainer, "HLT_Express_stream_HLT"); if(sc.isFailure()){ @@ -327,7 +328,7 @@ const xAOD::TrigCompositeContainer* Trig::CacheGlobalMemory::expressStreamContai } bool Trig::CacheGlobalMemory::assert_decision() { - + std::lock_guard<std::mutex> lock(m_cgmMutex); ATH_MSG_VERBOSE("asserting decision with unpacker " << m_unpacker); // here we unpack the decision. Note: the navigation will be unpacked only on demand (see navigation()) @@ -389,23 +390,21 @@ bool Trig::CacheGlobalMemory::assert_decision() { } StatusCode Trig::CacheGlobalMemory::unpackDecision() { - ATH_MSG_DEBUG("Unpacking TrigDecision "); ATH_MSG_DEBUG("clearing the delete-end-of-event store"); m_deleteAtEndOfEvent.clear(); bool unpackHLT = ( m_confChains != 0 ); - ATH_CHECK( m_unpacker->unpackDecision( m_itemsByName, m_itemsCache, + ATH_CHECK( m_unpacker->unpackDecision( m_itemsByName, m_itemsCache, m_l2chainsByName, m_l2chainsCache, m_efchainsByName, m_efchainsCache, m_bgCode, unpackHLT ) ); - return StatusCode::SUCCESS; } StatusCode Trig::CacheGlobalMemory::unpackNavigation() { - + std::lock_guard<std::mutex> lock(m_cgmMutex); // Navigation // protect from unpacking in case HLT was not run // (i.e. configuration chains are 0) @@ -422,7 +421,6 @@ StatusCode Trig::CacheGlobalMemory::unpackNavigation() { warningPrinted = true; } } - // Return gracefully: return StatusCode::SUCCESS; } diff --git a/Trigger/TrigAnalysis/TrigDecisionTool/Root/TrigDecisionTool.cxx b/Trigger/TrigAnalysis/TrigDecisionTool/Root/TrigDecisionTool.cxx index fe262391681fdda13dac3c459fc9a7d91ecba8ed..140e78922e4c05e67151496dd4bb35a7a95ad446 100644 --- a/Trigger/TrigAnalysis/TrigDecisionTool/Root/TrigDecisionTool.cxx +++ b/Trigger/TrigAnalysis/TrigDecisionTool/Root/TrigDecisionTool.cxx @@ -102,6 +102,15 @@ StatusCode Trig::TrigDecisionTool::initialize() { TrigDecisionToolCore::initialize().ignore(); + if (m_navigationFormat != "TriggerElement" && m_navigationFormat != "TrigComposite") { + ATH_MSG_ERROR("NavigationFormat property must be one of 'TriggerElement' for Run 1, 2 triggered input or 'TrigComposite' for Run 3+ triggered input"); + return StatusCode::FAILURE; + } + + if (m_navigationFormat == "TrigComposite") { + ATH_CHECK(m_HLTSummaryKeyIn.initialize()); + } + s_instances.push_back(name()); if ( s_instances.size() > 1) { ATH_MSG_WARNING("Several TrigDecisionTool instances" ); @@ -289,4 +298,9 @@ Trig::TrigDecisionTool::isPassedBits( const std::string& chain ) const { return TrigDecisionToolCore::isPassedBits( chain ); } +const std::string& +Trig::TrigDecisionTool::getNavigationFormat() const { + return m_navigationFormat; +} + diff --git a/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/CacheGlobalMemory.h b/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/CacheGlobalMemory.h index e2a8e097d9dd6dd0d413cedf6fe56942ee305d6f..5a7bcd70d800a5322ba3f8c643d9c1dacc7815e9 100644 --- a/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/CacheGlobalMemory.h +++ b/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/CacheGlobalMemory.h @@ -23,6 +23,7 @@ #include<map> #include<unordered_map> #include<string> +#include<mutex> #include "boost/foreach.hpp" #include "TrigConfHLTData/HLTChain.h" @@ -247,6 +248,8 @@ namespace Trig { mutable AnyTypeDeleter m_deleteAtEndOfEvent; + mutable std::mutex m_cgmMutex; //!< Temporary R3 MT protection only against --threads > 1, not against events in flight > 1 + }; diff --git a/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/DecisionAccess.icc b/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/DecisionAccess.icc index 0d0f091f5e8b96e24868616fe84b28b0a4a47c2f..dc01c1d0a1be30e7b4c034f12a05144fac2a886a 100644 --- a/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/DecisionAccess.icc +++ b/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/DecisionAccess.icc @@ -47,6 +47,7 @@ template<class CONTAINER> const std::vector< TrigCompositeUtils::LinkInfo<CONTAINER> > Trig::DecisionAccess::features(const Trig::ChainGroup* group, const unsigned int condition, const bool oneFeaturePerLeg) const { + // const TrigCompositeUtils::DecisionContainer* terminusNode = SG::get(m_HLTSummaryKeyIn/*, context*/); return group->features<CONTAINER>(cgm()->store(), condition, oneFeaturePerLeg); } diff --git a/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/TrigDecisionTool.h b/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/TrigDecisionTool.h index 0b7af32e354d2ba1ecc0236fc26efe109e57bed1..3d1c6570be199ad6ecf4a5cdd219646f72a8bb24 100755 --- a/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/TrigDecisionTool.h +++ b/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/TrigDecisionTool.h @@ -38,6 +38,7 @@ #endif +#include "DecisionHandling/TrigCompositeUtils.h" // interface to implement for offline access (outside AtlasTrigger) #include "TrigDecisionInterface/ITrigDecisionTool.h" @@ -108,6 +109,8 @@ namespace Trig { bool msgLvl(const MSG::Level lvl) const { return Logger::msgLvl(lvl); } + const std::string& getNavigationFormat() const; //!< Note: Temporary + private: bool configKeysMatch(uint32_t smk, uint32_t lvl1psk, uint32_t hltpsk); @@ -128,6 +131,13 @@ namespace Trig { bool m_useAODDecision; std::string m_decisionKey; + /// @name Run 3 properties + /// @{ + Gaudi::Property<std::string> m_navigationFormat{this, "NavigationFormat", "TrigComposite", "Allowed tokens are 'TriggerElement' or 'TrigComposite'"}; //!< Note: Temporary property + + SG::ReadHandleKey<TrigCompositeUtils::DecisionContainer> m_HLTSummaryKeyIn {this, "HLTSummary", "HLTSummary", "HLT summary container Key"}; + /// @} + TrigDecisionTool& operator= (const TrigDecisionTool&); std::map<std::string, std::string> m_publicChainGroups; diff --git a/Trigger/TrigEvent/TrigDecisionInterface/TrigDecisionInterface/Conditions.h b/Trigger/TrigEvent/TrigDecisionInterface/TrigDecisionInterface/Conditions.h index eb9eafce9f159521827390ea114407121457a066..a83093c8cad696eb860aa9d8bf070f25e81d55e4 100644 --- a/Trigger/TrigEvent/TrigDecisionInterface/TrigDecisionInterface/Conditions.h +++ b/Trigger/TrigEvent/TrigDecisionInterface/TrigDecisionInterface/Conditions.h @@ -37,6 +37,7 @@ namespace TrigDefs { // const static unsigned int ignoreIOV = 0x1 << 15; const static unsigned int alsoDeactivateTEs = 0x1 << 16; + const static unsigned int alsoDeactivateTCs = 0x1 << 16; //!< Run3 synonym of alsoDeactivateTEs. const static unsigned int ignoreFDR = 0x1 << 17; // const static unsigned int Physics = requireDecision | enforceLogicalFlow; diff --git a/Trigger/TrigMonitoring/TrigMuonMonitoring/src/MuFastMon.cxx b/Trigger/TrigMonitoring/TrigMuonMonitoring/src/MuFastMon.cxx index b0b03db9d426f0137d044707ed366ae8432c4966..c74714334e4fe7b523cfe0214dcbdfc5eead18ea 100644 --- a/Trigger/TrigMonitoring/TrigMuonMonitoring/src/MuFastMon.cxx +++ b/Trigger/TrigMonitoring/TrigMuonMonitoring/src/MuFastMon.cxx @@ -612,9 +612,19 @@ StatusCode HLTMuonMonTool::fillL2MuonSADQA() // Get mu6 and mu10 chains using TDT // --------------------------------- - Trig::FeatureContainer fc_mu6 = getTDT()->features("HLT_mu6"); - std::vector<Trig::Combination> combs_mu6 = fc_mu6.getCombinations(); - std::vector<Trig::Combination>::const_iterator p_comb_mu6; + std::vector<Trig::Combination> combs_mu6; //!< R2. To be deprecated + using TrigCompositeUtils::LinkInfo; + using TrigCompositeUtils::findLink; + using TrigCompositeUtils::Decision; + std::vector< LinkInfo<xAOD::L2StandAloneMuonContainer> > features_mu6; //!< R3. + if (getTDT()->getNavigationFormat() == "TriggerElement") { + Trig::FeatureContainer fc_mu6 = getTDT()->features("HLT_mu6"); + std::vector<Trig::Combination> combs_mu6 = fc_mu6.getCombinations(); + } else { + features_mu6 = getTDT()->features<xAOD::L2StandAloneMuonContainer>("HLT_mu6", TrigDefs::alsoDeactivateTCs); + // TODO only want to get features from container of name "MuonL2SAInfo" + } + ATH_MSG_DEBUG("isPassed mu6=" << getTDT()->isPassed("HLT_mu6", TrigDefs::Physics)); @@ -792,23 +802,55 @@ StatusCode HLTMuonMonTool::fillL2MuonSADQA() float dRmin_mu6 = 1000; float forIDroi_eta_mu6 = 0; float forIDroi_phi_mu6 = 0; - for(p_comb_mu6=combs_mu6.begin();p_comb_mu6!=combs_mu6.end();++p_comb_mu6) { - std::vector<Trig::Feature<xAOD::L2StandAloneMuonContainer> > fs_MF = - (*p_comb_mu6).get<xAOD::L2StandAloneMuonContainer>("MuonL2SAInfo",TrigDefs::alsoDeactivateTEs); - if(!fs_MF.size()) continue; - const xAOD::L2StandAloneMuonContainer* mf_cont = fs_MF[0]; - float eta_mf = mf_cont->at(0)->eta(); - float phi_mf = mf_cont->at(0)->phi(); - float dR = calc_dR(eta_mf, phi_mf, eta_offl, phi_offl); - if( dR < dRmin_mu6 ) { - dRmin_mu6 = dR; - std::vector<Trig::Feature<TrigRoiDescriptor> > fs_roi = - p_comb_mu6->get<TrigRoiDescriptor>("forID",TrigDefs::alsoDeactivateTEs); - if(!fs_roi.size()) continue; - forIDroi_eta_mu6 = fs_roi.at(0).cptr()->eta(); - forIDroi_phi_mu6 = fs_roi.at(0).cptr()->phi(); - } + + if (getTDT()->getNavigationFormat() == "TriggerElement") { + + std::vector<Trig::Combination>::const_iterator p_comb_mu6; + for(p_comb_mu6=combs_mu6.begin();p_comb_mu6!=combs_mu6.end();++p_comb_mu6) { + std::vector<Trig::Feature<xAOD::L2StandAloneMuonContainer> > fs_MF = + (*p_comb_mu6).get<xAOD::L2StandAloneMuonContainer>("MuonL2SAInfo",TrigDefs::alsoDeactivateTEs); + if(!fs_MF.size()) { + continue; + } + const xAOD::L2StandAloneMuonContainer* mf_cont = fs_MF[0]; + float eta_mf = mf_cont->at(0)->eta(); + float phi_mf = mf_cont->at(0)->phi(); + float dR = calc_dR(eta_mf, phi_mf, eta_offl, phi_offl); + if( dR < dRmin_mu6 ) { + dRmin_mu6 = dR; + std::vector<Trig::Feature<TrigRoiDescriptor> > fs_roi = + p_comb_mu6->get<TrigRoiDescriptor>("forID",TrigDefs::alsoDeactivateTEs); + if(!fs_roi.size()) { + continue; + } + forIDroi_eta_mu6 = fs_roi.at(0).cptr()->eta(); + forIDroi_phi_mu6 = fs_roi.at(0).cptr()->phi(); + } + } + + } else { // getTDT()->getNavigationFormat() == "TrigComposite" + + for(const LinkInfo<xAOD::L2StandAloneMuonContainer>& muLinkInfo : features_mu6) { + ATH_CHECK( muLinkInfo.isValid() ); + const ElementLink<xAOD::L2StandAloneMuonContainer> muEL = muLinkInfo.link; + const Decision* muDecision = muLinkInfo.source; + float eta_mf = (*muEL)->eta(); + float phi_mf = (*muEL)->phi(); + float dR = calc_dR(eta_mf, phi_mf, eta_offl, phi_offl); + if( dR < dRmin_mu6 ) { + dRmin_mu6 = dR; + const LinkInfo<TrigRoiDescriptorCollection> roiLinkInfo = findLink<TrigRoiDescriptorCollection>(muDecision, "initialRoI"); + // TODO - check if the R3 trigger will still create the "forID" ROIDescriptor. + // (SShaw: In Run2 this was a special ROIDescriptor centred on the L2 muon) + ATH_CHECK( roiLinkInfo.isValid() ); + const ElementLink<TrigRoiDescriptorCollection> roiEL = roiLinkInfo.link; + forIDroi_eta_mu6 = (*roiEL)->eta(); + forIDroi_phi_mu6 = (*roiEL)->phi(); + } + } } + + if( dRmin_mu6 < DR_MATCHED ) { float dr = calc_dR(eta_offl,phi_offl,forIDroi_eta_mu6,forIDroi_phi_mu6); float deta = forIDroi_eta_mu6-eta_offl; diff --git a/Trigger/TrigSteer/DecisionHandling/DecisionHandling/TrigCompositeUtils.h b/Trigger/TrigSteer/DecisionHandling/DecisionHandling/TrigCompositeUtils.h index d0e0ed08bc36ebcd08471c279b4b9dab3cebdc15..338bda04603b20266bebf7f5ee68db3067101ba9 100644 --- a/Trigger/TrigSteer/DecisionHandling/DecisionHandling/TrigCompositeUtils.h +++ b/Trigger/TrigSteer/DecisionHandling/DecisionHandling/TrigCompositeUtils.h @@ -210,12 +210,20 @@ namespace TrigCompositeUtils { private: std::string m_name; }; + + /** + * @brief + * @param[in] eventStore + * @param[out] output + * @param[in] id + **/ + StatusCode getRejectedDecisionNodes(EventPtr_t eventStore, std::vector<const Decision*>& output, const DecisionID id = 0) { /** * @brief Search back in time from "start" and locate all linear paths back through Decision objects for a given chain. * @param[in] start The Decision object to start the search from. Typically this will be one of the terminus objects from the HLTSummary (regular or rerun). - * @param[in] id Optional DecisionID of a Chain to trace through the navigation. If omitted, no chain requirement will be applied. * @param[out] linkVector Each entry in the outer vector represents a path through the graph. For each path, a vector of ElementLinks describing the path is returned. + * @param[in] id Optional DecisionID of a Chain to trace through the navigation. If omitted, no chain requirement will be applied. **/ void recursiveGetDecisions( const Decision* start, std::vector<ElementLinkVector<DecisionContainer>>& linkVector, const DecisionID id = 0 ); diff --git a/Trigger/TrigSteer/DecisionHandling/src/TrigCompositeUtils.cxx b/Trigger/TrigSteer/DecisionHandling/src/TrigCompositeUtils.cxx index d83e54bbe65947f99db8cedd23fc278d98360820..06bee82a77c5e94bcfb345605fc8d08e15a152ca 100644 --- a/Trigger/TrigSteer/DecisionHandling/src/TrigCompositeUtils.cxx +++ b/Trigger/TrigSteer/DecisionHandling/src/TrigCompositeUtils.cxx @@ -126,15 +126,15 @@ namespace TrigCompositeUtils { } const ElementLink<DecisionContainer> seedLink = ElementLink<DecisionContainer>(*container, dOld->index(), ctx); - d->addObjectCollectionLink("seed", seedLink); + d->addObjectCollectionLink(seedString(), seedLink); } bool hasLinkToPrevious( const Decision* d ) { - return d->hasObjectCollectionLinks( "seed" ); + return d->hasObjectCollectionLinks( seedString() ); } const ElementLinkVector<DecisionContainer> getLinkToPrevious( const Decision* d ) { - return d->objectCollectionLinks<DecisionContainer>( "seed" ); + return d->objectCollectionLinks<DecisionContainer>( seedString() ); } @@ -166,6 +166,76 @@ namespace TrigCompositeUtils { return composite->hasObjectCollectionLinks( m_name ); } + StatusCode getRejectedDecisionNodes(EventPtr_t eventStore, std::vector<const Decision*>& output, const DecisionID id) { + std::vector<const Decision*> output; + + // Good in the future to have the TDT populate a ReadHandleKeyArray with *ALL* Decision containers in the input files (there will be many, and the list will change often, file by file) + // For now, we are old-fashoned and we ask SG directly on an event-by-event basis. + + std::vector<std::string> keys; + eventStore->keys(static_cast<CLID>( ClassID_traits< DecisionContainer >::ID() ), keys); + + // Loop over each DecisionContainer, only looking for collections produced by HypoAlg + for (const std::string& key : keys) { + if (key.find("Hypo") == std::string::npos) { + continue; + } + // Get and check this container + const DecisionContainer* container = nullptr; + ATH_CHECK( eventStore->retrieve( container, key ) ); + ATH_MSG_DEBUG("Looking for failed Decisions for ChainID " << id << " in HypoCollection " << key); + for (const Decision* d : *container) { + if (!d->hasObjectLink(featureString())) { + ATH_MSG_DEBUG("Decision did not have feature with name:" << featureString() << "?!"); + ATH_MSG_DEBUG(*d); + // TODO add logic for CombiHypo where this is expected + continue; + } + const ElementLinkVector<DecisionContainer> mySeeds = d->objectCollectionLinks<DecisionContainer>(seedString()); + ATH_MSG_DEBUG(" HypoAlg Decision has " << mySeeds.size() << " direct parents"); + if (mySeeds.size() == 0) { + ATH_MSG_WARNING("Got a HypoAlg Decision with no parents - this is a clear sign of a triggr misconfiguration!"); + 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 intersetion 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* [an] 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 id : chainsToCheck) { + if (activeChainsPassedByThisDecision.count(id) == 0) { // I was REJECTED + ATH_MSG_DEBUG("Chain ID " << id << " was rejected here. TrigDefs::alsoDeactivateTCs 'feature' source located."); + output.push_back(d); + break; + } + } + } + } + return StatusCode::SUCCESS; + } void recursiveGetDecisionsInternal(const Decision* start, const size_t location, std::vector<ElementLinkVector<DecisionContainer>>& linkVector, const DecisionID id) { // Does this Decision satisfy the chain requirement? diff --git a/Trigger/TrigValidation/TrigUpgradeTest/share/full_menu.py b/Trigger/TrigValidation/TrigUpgradeTest/share/full_menu.py index d37618b2032dcc623019814888af1c65470a2f83..dceaab603d2b4c7b58e532fd85cb0f2c8be32f5e 100644 --- a/Trigger/TrigValidation/TrigUpgradeTest/share/full_menu.py +++ b/Trigger/TrigValidation/TrigUpgradeTest/share/full_menu.py @@ -68,7 +68,7 @@ if l1decoder: ItemList += [ k[0] for k in TriggerHLTList if 'ESD' in k[1] and "TrigComposite" in k[0] ] ItemList += [ 'xAOD::TrigCompositeAuxContainer#{}Aux.'.format(k[0].split("#")[1]) for k in TriggerHLTList if 'ESD' in k[1] and "TrigComposite" in k[0] ] ItemList += [ "xAOD::EventInfo#EventInfo" ] - + ItemList += [ "xAOD::EventAuxInfo#EventInfoAux." ] ItemList = list(set(ItemList)) else: diff --git a/Trigger/TrigValidation/TrigValAlgs/src/TrigEDMChecker.cxx b/Trigger/TrigValidation/TrigValAlgs/src/TrigEDMChecker.cxx index a7a52847a2aad025c0e45cefcfd825d621b0dc26..247cd232396446d258396906efa7895810f7ebcd 100644 --- a/Trigger/TrigValidation/TrigValAlgs/src/TrigEDMChecker.cxx +++ b/Trigger/TrigValidation/TrigValAlgs/src/TrigEDMChecker.cxx @@ -246,6 +246,7 @@ StatusCode TrigEDMChecker::initialize() { if (m_doTDTCheck) { ATH_CHECK( m_trigDec.retrieve() ); m_trigDec->ExperimentalAndExpertMethods()->enable(); + ATH_MSG_INFO("TDT Executing with navigation format: " << m_trigDec->getNavigationFormat()); } return StatusCode::SUCCESS; @@ -4018,8 +4019,7 @@ StatusCode TrigEDMChecker::dumpTDT() { for (const auto& item : confChains) { bool passed = m_trigDec->isPassed(item, TrigDefs::requireDecision); ATH_MSG_INFO(" HLT Item " << item << " (numeric ID " << TrigConf::HLTUtils::string2hash(item, "Identifier") << ") passed raw? " << passed); - const bool isRunThree = evtStore()->contains<xAOD::TrigCompositeContainer>("HLT_Summary"); - if (isRunThree && passed) { + if (m_trigDec->getNavigationFormat() == "TrigComposite" && passed) { std::vector< LinkInfo<xAOD::IParticleContainer> > features = m_trigDec->features<xAOD::IParticleContainer>(item); ATH_MSG_INFO(" " << item << " IParticle features size: " << features.size()); for (const LinkInfo<xAOD::IParticleContainer>& li : features) {