diff --git a/Event/xAOD/xAODTrigger/Root/TrigComposite_v1.cxx b/Event/xAOD/xAODTrigger/Root/TrigComposite_v1.cxx index b9c293d6a2cfeb8a51ebbfd648ca4cf2b7b2291f..3d916bee953856ab315ffaf8a2ed195525ac06d1 100644 --- a/Event/xAOD/xAODTrigger/Root/TrigComposite_v1.cxx +++ b/Event/xAOD/xAODTrigger/Root/TrigComposite_v1.cxx @@ -199,8 +199,8 @@ namespace xAOD { bool TrigComposite_v1::hasObjectLinkExact(const std::string& name, const uint32_t key, const uint16_t index, const uint32_t clid) const { for (size_t i = 0; i < this->linkColNames().size(); ++i) { if (this->linkColNames().at(i) != name) continue; - if (this->linkColKeys().at(i) != key) continue; - if (this->linkColIndices().at(i) != index) continue; + if (this->linkColKeysNoRemap().at(i) != key) continue; + if (this->linkColIndicesNoRemap().at(i) != index) continue; if (this->linkColClids().at(i) != clid) continue; return true; } @@ -214,13 +214,39 @@ namespace xAOD { AUXSTORE_OBJECT_GETTER( TrigComposite_v1, std::vector< std::string >, linkColNames ) - AUXSTORE_OBJECT_GETTER( TrigComposite_v1, std::vector< uint32_t >, - linkColKeys ) - AUXSTORE_OBJECT_GETTER( TrigComposite_v1, std::vector< uint16_t >, - linkColIndices ) AUXSTORE_OBJECT_GETTER( TrigComposite_v1, std::vector< uint32_t >, linkColClids ) + const std::vector< uint32_t >& TrigComposite_v1::linkColKeys() const { + if (isRemapped()) { + static const Accessor< std::vector< uint32_t > > acc_remap( "remap_linkColKeys" ); + return acc_remap( *this ); + } + static const Accessor< std::vector< uint32_t > > acc_builtin( "linkColKeys" ); + return acc_builtin( *this ); + } + + const std::vector< uint16_t >& TrigComposite_v1::linkColIndices() const { + if (isRemapped()) { + static const Accessor< std::vector< uint16_t > > acc_remap( "remap_linkColIndices" ); + return acc_remap( *this ); + } + static const Accessor< std::vector< uint16_t > > acc_builtin( "linkColIndices" ); + return acc_builtin( *this ); + } + + const std::vector< uint32_t >& TrigComposite_v1::linkColKeysNoRemap() const { + static const Accessor< std::vector< uint32_t > > acc( "linkColKeys" ); + return acc( *this ); + } + + const std::vector< uint16_t >& TrigComposite_v1::linkColIndicesNoRemap() const { + static const Accessor< std::vector< uint16_t > > acc( "linkColIndices" ); + return acc( *this ); + } + + //////// + std::vector< std::string >& TrigComposite_v1::linkColNamesNC() { static const Accessor< std::vector< std::string > > acc( "linkColNames" ); @@ -314,18 +340,35 @@ namespace xAOD { } } + bool TrigComposite_v1::isRemapped() const { + static const Accessor< std::vector< uint32_t > > key_remap( "remap_linkColKeys" ); + static const Accessor< std::vector< uint16_t > > index_remap( "remap_linkColIndices" ); + size_t nDecorations = 0; + if (key_remap.isAvailable( *this )) ++nDecorations; + if (index_remap.isAvailable( *this )) ++nDecorations; + if (nDecorations == 1) { + throw std::runtime_error("TrigComposite_v1::isRemapped Only one of the 'remap_linkColKeys' and 'remap_linkColIndices' " + "decorations were found on this object. This should never happen, a remapped element link must have both of these collections."); + } + return static_cast<bool>(nDecorations); //0=Fasle, 2=True + } + + // ///////////////////////////////////////////////////////////////////////////// std::ostream& operator<<(std::ostream& os, const xAOD::TrigComposite_v1& tc) { os << "TrigComposite_v1 name:'" << tc.name() << "'" << std::endl; - os << " N Lnks:" << tc.linkColNames().size(); + const bool isRemapped = tc.isRemapped(); + os << " N Links:" << tc.linkColNames().size() << ", isRemapped:" << (isRemapped ? "YES" : "NO"); for (size_t i=0; i<tc.linkColNames().size(); ++i){ if (!i) os << std::endl; os << " Link Name:" << tc.linkColNames()[i]; os << ", Key:" << tc.linkColKeys()[i]; + if (isRemapped) os << ", OldKey:" << tc.linkColKeysNoRemap()[i]; os << ", Index:" << tc.linkColIndices()[i]; + if (isRemapped) os << ", OldIndex:" << tc.linkColIndicesNoRemap()[i]; os << ", CLID:" << tc.linkColClids()[i]; if (i != tc.linkColNames().size() - 1) os << std::endl; } diff --git a/Event/xAOD/xAODTrigger/xAODTrigger/versions/TrigComposite_v1.h b/Event/xAOD/xAODTrigger/xAODTrigger/versions/TrigComposite_v1.h index 54420895b95664410a65a3bd6d1467a063052713..434ec8485befeb1818bfa321b228765e412de1ca 100644 --- a/Event/xAOD/xAODTrigger/xAODTrigger/versions/TrigComposite_v1.h +++ b/Event/xAOD/xAODTrigger/xAODTrigger/versions/TrigComposite_v1.h @@ -166,13 +166,22 @@ namespace xAOD { /// Raw access to the persistent link names const std::vector< std::string >& linkColNames() const; - /// Raw access to the persistent link labels + /// Raw access to the persistent link labels. Will use remapped data, if available. const std::vector< uint32_t >& linkColKeys() const; - /// Raw access to the persistent link indices + /// Raw access to the persistent link indices. Will use remapped data, if available. const std::vector< uint16_t >& linkColIndices() const; /// Raw access to the persistent link CLIDs const std::vector< uint32_t >& linkColClids() const; + /// Information on if linkColKeys() and linkColIndices() are able to access remapped link data + /// Remapping happens at the end of HLT execution when EDM objects are copied out of their per-EventView + /// containers and into the global Trigger EDM containers. + bool isRemapped() const; + + /// Raw access to the persistent link labels. Will not attempt to access remapped link data. + const std::vector< uint32_t >& linkColKeysNoRemap() const; + /// Raw access to the persistent link indices. Will not attempt to access remapped link data. + const std::vector< uint16_t >& linkColIndicesNoRemap() const; /// @} diff --git a/Event/xAOD/xAODTrigger/xAODTrigger/versions/TrigComposite_v1.icc b/Event/xAOD/xAODTrigger/xAODTrigger/versions/TrigComposite_v1.icc index 3af13d04d63d733e37aa2339404b2a4af3c724ff..6c3bf8b4c6de0712f02818843b4768e7e4c4d1b0 100644 --- a/Event/xAOD/xAODTrigger/xAODTrigger/versions/TrigComposite_v1.icc +++ b/Event/xAOD/xAODTrigger/xAODTrigger/versions/TrigComposite_v1.icc @@ -119,9 +119,16 @@ namespace xAOD { for( size_t i = 0; i < names.size(); ++i ) { if( names[ i ] != name ) continue; checkTypes< CONTAINER >(linkColClids()[ i ], name); - // Construct the link: - return ElementLink< CONTAINER >( linkColKeys()[ i ], - linkColIndices()[ i ] ); + // Construct the link. Try to remap, if remap collections are available: + ElementLink< CONTAINER > linkTryRemap( linkColKeys()[ i ], + linkColIndices()[ i ] ); + if (linkTryRemap.isValid()) { + return linkTryRemap; + } + + // Try again, without remapping + return ElementLink< CONTAINER >( linkColKeysNoRemap()[ i ], + linkColIndicesNoRemap()[ i ] ); } // We didn't find the link. :-( @@ -145,13 +152,19 @@ namespace xAOD { // Check that it is of the right type: checkTypes< DataVector< OBJECT > >(linkColClids()[ i ], name); // Create a temporary ElementLink: - ElementLink< DataVector< OBJECT > > link( linkColKeys()[ i ], - linkColIndices()[ i ] ); - if( ! link.isValid() ) { - return 0; + ElementLink< DataVector< OBJECT > > linkTryRemap( linkColKeys()[ i ], + linkColIndices()[ i ] ); + if( linkTryRemap.isValid() ) { + return *linkTryRemap; + } + + // This time forbid remapping + ElementLink< DataVector< OBJECT > > link( linkColKeysNoRemap()[ i ], + linkColIndicesNoRemap()[ i ] ); + + if( link.isValid() ) { + return *link; } - // Get the pointer: - return *link; } // There was an internal error. :-( diff --git a/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/ChainGroup.h b/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/ChainGroup.h index 176351abd4feae4f7ac0d62c3c78ee12efa81702..f2b6c8ecffa77837ee73916fb3b99eb76e68809c 100644 --- a/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/ChainGroup.h +++ b/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/ChainGroup.h @@ -121,10 +121,12 @@ namespace Trig { * @param[in] eventStore Event store pointer. To migrate to readHandles with the rest of the TDT soon * @param[in] condition Condition requirement. Only physics currently supported. * @param[in] oneFeaturePerLeg If true, only collects the final feature from each object which passed the event for the Chain Group. - * @return ElementLinkVector with one entry per located feature for the ChainGroup's chain(s) + * @return Vector of LinkInfo, where each entry wraps an ElementLink to the feature, and the Decision object it came from. **/ template<class CONTAINER> - const ElementLinkVector<CONTAINER> features(EventPtr_t eventStore, unsigned int condition = TrigDefs::Physics, const bool oneFeaturePerLeg = true) const; + const std::vector< TrigCompositeUtils::LinkInfo<CONTAINER> > features(EventPtr_t eventStore, + unsigned int condition = TrigDefs::Physics, + const bool oneFeaturePerLeg = true) const; // const std::vector< std::string >& patterns() const {return m_patterns;} diff --git a/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/ChainGroup.icc b/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/ChainGroup.icc index 67f865230b0dad2619902e22fb01d41eb27d371a..b5f2841f4d3baf7e921350e87be3c44c9e8bb04d 100644 --- a/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/ChainGroup.icc +++ b/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/ChainGroup.icc @@ -1,56 +1,64 @@ -template<class CONTAINER> -const ElementLinkVector<CONTAINER> Trig::ChainGroup::features(EventPtr_t eventStore, unsigned int condition, const bool oneFeaturePerLeg) const { - - // Proper adherence to the condition bits in Run 3 is to follow. - - bool errState = false; - if ( !(condition & TrigDefs::Physics) ) { - ATH_MSG_ERROR("Only TrigDefs::Physics is currently supported for Run 3 feature retrieval"); - errState = true; - } - if ( condition & TrigDefs::allowResurrectedDecision ) { - ATH_MSG_ERROR("TrigDefs::allowResurrectedDecision is not yet supported for feature retrieval for Run 3"); - errState = true; - } - - // TODO when we decide what happens to CacheGlobalMemory - this needs to be updated to use a ReadHandle - const TrigCompositeUtils::DecisionContainer* navigationSummaryContainer = nullptr; - if (eventStore->retrieve(navigationSummaryContainer, "HLTSummary").isFailure() || navigationSummaryContainer == nullptr) { - ATH_MSG_ERROR("Unable to read Run 3 trigger navigation. Cannot retrieve features."); - errState = true; - } - - // We just support Physics decision for now - const TrigCompositeUtils::Decision* terminusNode = nullptr; - - if (!errState) { - for (const TrigCompositeUtils::Decision* decision : *navigationSummaryContainer) { - if (decision->name() == "HLTPassRaw") { - terminusNode = decision; - break; - } - } - if (terminusNode == nullptr) { - ATH_MSG_ERROR("Unable to locate HLTPassRaw element of HLTSummary"); - errState = true; - } - } - - if (errState) { - return ElementLinkVector<CONTAINER>(); - } - - // For each chain, collect Navigation information - std::vector< ElementLinkVector<TrigCompositeUtils::DecisionContainer> > allLinearNavigationPaths; - - // Loop over HLT chains - std::set<const TrigConf::HLTChain*>::const_iterator chIt; - for (chIt=conf_chain_begin(); chIt != conf_chain_end(); ++chIt) { - const HLT::Chain* fchain = cgm()->chain(**chIt); - if (fchain) { - TrigCompositeUtils::recursiveGetDecisions(terminusNode, allLinearNavigationPaths, fchain->getChainHashId()); - } - } - - return TrigCompositeUtils::getFeaturesOfType<CONTAINER>(allLinearNavigationPaths, oneFeaturePerLeg); -} +template<class CONTAINER> +const std::vector< TrigCompositeUtils::LinkInfo<CONTAINER> > Trig::ChainGroup::features(EventPtr_t eventStore, + unsigned int condition, const bool oneFeaturePerLeg) const { + + // Proper adherence to the condition bits in Run 3 is to follow. + bool errState = false; + if ( !(condition & TrigDefs::Physics) ) { + ATH_MSG_ERROR("Only TrigDefs::Physics is currently supported for Run 3 feature retrieval"); + errState = true; + } + if ( condition & TrigDefs::allowResurrectedDecision ) { + ATH_MSG_ERROR("TrigDefs::allowResurrectedDecision is not yet supported for feature retrieval for Run 3"); + errState = true; + } + + // TODO when we decide what happens to CacheGlobalMemory - this needs to be updated to use a ReadHandle + const TrigCompositeUtils::DecisionContainer* navigationSummaryContainer = nullptr; + if (eventStore->retrieve(navigationSummaryContainer, "HLTSummary").isFailure() || navigationSummaryContainer == nullptr) { + ATH_MSG_ERROR("Unable to read Run 3 trigger navigation. Cannot retrieve features."); + errState = true; + } + + // We just support Physics decision for now + const TrigCompositeUtils::Decision* terminusNode = nullptr; + + if (!errState) { + for (const TrigCompositeUtils::Decision* decision : *navigationSummaryContainer) { + if (decision->name() == "HLTPassRaw") { + terminusNode = decision; + break; + } + } + if (terminusNode == nullptr) { + ATH_MSG_ERROR("Unable to locate HLTPassRaw element of HLTSummary"); + errState = true; + } + } + + if (errState) { + ATH_MSG_ERROR("Encountered one or more errors in Trig::ChainGroup::features. Returning empty vector."); + return std::vector< TrigCompositeUtils::LinkInfo<CONTAINER> >(); + } + + // For each chain, collect Navigation information + std::vector< ElementLinkVector<TrigCompositeUtils::DecisionContainer> > allLinearNavigationPaths; + + // Loop over HLT chains + std::set<const TrigConf::HLTChain*>::const_iterator chIt; + for (chIt=conf_chain_begin(); chIt != conf_chain_end(); ++chIt) { + const HLT::Chain* fchain = cgm()->chain(**chIt); + if (fchain) { + TrigCompositeUtils::recursiveGetDecisions(terminusNode, allLinearNavigationPaths, fchain->getChainHashId()); + ATH_MSG_DEBUG("Added all navigation paths for chain " << fchain->getChainName() << ", total paths:" << allLinearNavigationPaths.size()); + } else { + ATH_MSG_ERROR("Cannot access configuration for one of the ChainGroup's chains"); + } + } + + if (allLinearNavigationPaths.size() == 0) { + ATH_MSG_WARNING("No navigation paths found for this chain group of " << names().size() << " chains."); + } + + return TrigCompositeUtils::getFeaturesOfType<CONTAINER>(allLinearNavigationPaths, oneFeaturePerLeg); +} diff --git a/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/DecisionAccess.h b/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/DecisionAccess.h index fb2e7d9001d9252e13b11af400fbeafbd9dc5ed0..f69d411b4a4bbc8b6643cad2a70bb55e3692a4e0 100644 --- a/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/DecisionAccess.h +++ b/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/DecisionAccess.h @@ -107,17 +107,27 @@ namespace Trig { /** * @brief Runs 3+. Returns all features related to given chain group + * @param[in] group Chain group to return features for. + * @param[in] condition Condition bits which the chain group must satisfy. + * @param[in] oneFeaturePerLeg If true, only collects the final feature from each object which passed the event for the Chain Group. + * @return Vector of LinkInfo, where each entry wraps an ElementLink to the feature, and the Decision object it came from. **/ template<class CONTAINER> - const ElementLinkVector<CONTAINER> features(const Trig::ChainGroup* group, - unsigned int condition = TrigDefs::Physics) const; + const std::vector< TrigCompositeUtils::LinkInfo<CONTAINER> > features(const Trig::ChainGroup* group, + const unsigned int condition = TrigDefs::Physics, + const bool oneFeaturePerLeg = true) const; /** * @brief Runs 3+. Returns features related to given chain + * @param[in] group Chain group to return features for. + * @param[in] condition Condition bits which the chain group must satisfy. + * @param[in] oneFeaturePerLeg If true, only collects the final feature from each object which passed the event for the Chain Group. + * @return Vector of LinkInfo, where each entry wraps an ElementLink to the feature, and the Decision object it came from. **/ template<class CONTAINER> - const ElementLinkVector<CONTAINER> features(const std::string& chainName = "HLT_.*", - unsigned int condition = TrigDefs::Physics) const; + const std::vector< TrigCompositeUtils::LinkInfo<CONTAINER> > features(const std::string& chainName = "HLT_.*", + const unsigned int condition = TrigDefs::Physics, + const bool oneFeaturePerLeg = true) const; /** * @brief gives back feature matching (by seeding relation) diff --git a/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/DecisionAccess.icc b/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/DecisionAccess.icc index 7071fca4c1bcf341e3182e777f5d5b506f818f1b..0d0f091f5e8b96e24868616fe84b28b0a4a47c2f 100644 --- a/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/DecisionAccess.icc +++ b/Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/DecisionAccess.icc @@ -1,57 +1,59 @@ -#if defined(ASGTOOL_ATHENA) && !defined(XAOD_ANALYSIS) - -template<class T> -const Trig::Feature<T> Trig::DecisionAccess::ancestor(const HLT::TriggerElement* te, std::string label) const { - Trig::Feature<T> f; - std::vector<Trig::Feature<T> > data; - FeatureAccessImpl::collect<T>(te, data, label, TrigDefs::alsoDeactivateTEs, "", const_cast<HLT::TrigNavStructure*>(cgm()->navigation())); - - BOOST_FOREACH( Feature<T>& f, data ) { - if ( f.owned() ) { - cgm()->deleteAtTheEndOfEvent( const_cast<T*>( f.cptr() ) ); - } - } - - if (data.size() == 1) - f = data[0]; - return f; -} - - -template<class T> -const std::vector<Trig::Feature<T> > Trig::DecisionAccess::ancestors(const HLT::TriggerElement* te, std::string label, unsigned int condition, const std::string& teName) const { - std::vector<Trig::Feature<T> > data; - FeatureAccessImpl::collect<T>(te, data, label, condition, teName, const_cast<HLT::TrigNavStructure*>(cgm()->navigation())); - BOOST_FOREACH( Feature<T>& f, data ) { - if ( f.owned() ) { - cgm()->deleteAtTheEndOfEvent(const_cast<T*>( f.cptr() )); - } - } - return data; -} -#else -template<class T> -const Trig::Feature<T> Trig::DecisionAccess::ancestor(const HLT::TriggerElement* /*te*/, std::string /*label*/) const { - ATH_MSG_WARNING("DecisionAccess::ancestor not implemented in Standalone mode, since it needs compile-time type information. Returning empty Feature"); - return Trig::Feature<T>(); -} -template<class T> -const std::vector<Trig::Feature<T> > Trig::DecisionAccess::ancestors(const HLT::TriggerElement* /*te*/, std::string /*label*/, unsigned int /*condition*/, const std::string& /*teName*/) const { - ATH_MSG_WARNING("DecisionAccess::ancestor not implemented in Standalone mode, since it needs compile-time type information. Returning empty vector"); - return std::vector<Trig::Feature<T> >(); -} - -#endif // ASGTOOL_ATHENA - -template<class CONTAINER> -const ElementLinkVector<CONTAINER> Trig::DecisionAccess::features(const Trig::ChainGroup* group, - unsigned int condition) const { - return group->features<CONTAINER>(cgm()->store(), condition, /*one feature per leg*/ true); -} - -template<class CONTAINER> -const ElementLinkVector<CONTAINER> Trig::DecisionAccess::features(const std::string& chainName, - unsigned int condition) const { - const Trig::ChainGroup *g = cgm()->createChainGroup(Trig::convertStringToVector(chainName)); - return features<CONTAINER>(g,condition); -} \ No newline at end of file +#if defined(ASGTOOL_ATHENA) && !defined(XAOD_ANALYSIS) + +template<class T> +const Trig::Feature<T> Trig::DecisionAccess::ancestor(const HLT::TriggerElement* te, std::string label) const { + Trig::Feature<T> f; + std::vector<Trig::Feature<T> > data; + FeatureAccessImpl::collect<T>(te, data, label, TrigDefs::alsoDeactivateTEs, "", const_cast<HLT::TrigNavStructure*>(cgm()->navigation())); + + BOOST_FOREACH( Feature<T>& f, data ) { + if ( f.owned() ) { + cgm()->deleteAtTheEndOfEvent( const_cast<T*>( f.cptr() ) ); + } + } + + if (data.size() == 1) + f = data[0]; + return f; +} + + +template<class T> +const std::vector<Trig::Feature<T> > Trig::DecisionAccess::ancestors(const HLT::TriggerElement* te, std::string label, unsigned int condition, const std::string& teName) const { + std::vector<Trig::Feature<T> > data; + FeatureAccessImpl::collect<T>(te, data, label, condition, teName, const_cast<HLT::TrigNavStructure*>(cgm()->navigation())); + BOOST_FOREACH( Feature<T>& f, data ) { + if ( f.owned() ) { + cgm()->deleteAtTheEndOfEvent(const_cast<T*>( f.cptr() )); + } + } + return data; +} +#else +template<class T> +const Trig::Feature<T> Trig::DecisionAccess::ancestor(const HLT::TriggerElement* /*te*/, std::string /*label*/) const { + ATH_MSG_WARNING("DecisionAccess::ancestor not implemented in Standalone mode, since it needs compile-time type information. Returning empty Feature"); + return Trig::Feature<T>(); +} +template<class T> +const std::vector<Trig::Feature<T> > Trig::DecisionAccess::ancestors(const HLT::TriggerElement* /*te*/, std::string /*label*/, unsigned int /*condition*/, const std::string& /*teName*/) const { + ATH_MSG_WARNING("DecisionAccess::ancestor not implemented in Standalone mode, since it needs compile-time type information. Returning empty vector"); + return std::vector<Trig::Feature<T> >(); +} + +#endif // ASGTOOL_ATHENA + +template<class CONTAINER> +const std::vector< TrigCompositeUtils::LinkInfo<CONTAINER> > Trig::DecisionAccess::features(const Trig::ChainGroup* group, + const unsigned int condition, + const bool oneFeaturePerLeg) const { + return group->features<CONTAINER>(cgm()->store(), condition, oneFeaturePerLeg); +} + +template<class CONTAINER> +const std::vector< TrigCompositeUtils::LinkInfo<CONTAINER> > Trig::DecisionAccess::features(const std::string& chainName, + const unsigned int condition, + const bool oneFeaturePerLeg) const { + const Trig::ChainGroup *g = cgm()->createChainGroup(Trig::convertStringToVector(chainName)); + return features<CONTAINER>(g,condition,oneFeaturePerLeg); +} diff --git a/Trigger/TrigConfiguration/TrigConfigSvc/src/HLTConfigSvc.cxx b/Trigger/TrigConfiguration/TrigConfigSvc/src/HLTConfigSvc.cxx index c734a5a6d790e2bba3dd533f3dd171ff658ea191..d67a53b5fcda1e7bd7322eb089f1a92b654884b6 100644 --- a/Trigger/TrigConfiguration/TrigConfigSvc/src/HLTConfigSvc.cxx +++ b/Trigger/TrigConfiguration/TrigConfigSvc/src/HLTConfigSvc.cxx @@ -146,6 +146,35 @@ HLTConfigSvc::initialize() { dummyChains["HLT_e3_etcut"] = "L1_EM3"; dummyChains["HLT_e5_etcut"] = "L1_EM3"; dummyChains["HLT_e7_etcut"] = "L1_EM7"; + // for menu test + dummyChains["HLT_2mu4_bBmumu_L12MU4"] = "L1_2MU4"; + dummyChains["HLT_2mu4_bJpsimumu_L12MU4"] = "L1_2MU4"; + dummyChains["HLT_2mu4_bUpsimumu_L12MU4"] = "L1_2MU4"; + dummyChains["HLT_2mu6"] = "L1_2MU6"; + dummyChains["HLT_2mu6Comb"] = "L1_2MU6"; + dummyChains["HLT_2mu6_bJpsimumu_L12MU6"] = "L1_2MU6"; + dummyChains["HLT_3j200"] = "L1_J50"; + dummyChains["HLT_5j70_0eta240"] = "L1_J50"; + dummyChains["HLT_e3_etcut1step"] = "L1_EM3"; + dummyChains["HLT_e3_etcut_mu6"] = "L1_EM8I_MU10"; + dummyChains["HLT_g5_etcut"] = "L1_EM3"; + dummyChains["HLT_j0_vbenfSEP30etSEP34mass35SEP50fbet20"] = "L1_RD0_FILLED"; + dummyChains["HLT_j225_gsc420_boffperf_split20"] = "L1_J100"; + dummyChains["HLT_j260_320eta490"] = "L1_J100"; + dummyChains["HLT_j420"] = "L1_J100"; + dummyChains["HLT_j45"] = "L1_J20"; + dummyChains["HLT_j460_a10_lcw_subjes"] = "L1_J100"; + dummyChains["HLT_j460_a10r"] = "L1_J100"; + dummyChains["HLT_j85"] = "L1_J20"; + dummyChains["HLT_mu20_ivar"] = "L1_MU20"; + dummyChains["HLT_mu6"] = "L1_MU6"; + dummyChains["HLT_mu6Comb"] = "L1_MU6"; + dummyChains["HLT_mu6fast"] = "L1_MU6"; + dummyChains["HLT_mu6msonly"] = "L1_MU6"; + dummyChains["HLT_mu6nol1"] = "L1_MU6"; + dummyChains["HLT_xe30_L1XE10"] = "L1_XE20"; + dummyChains["HLT_xe65_L1XE50"] = "L1_XE20"; + m_HLTFrame.setMergedHLT( m_setMergedHLT ); for (const auto& mapPair : dummyChains) { const std::string& chainName = mapPair.first; diff --git a/Trigger/TrigSteer/DecisionHandling/DecisionHandling/TrigCompositeUtils.h b/Trigger/TrigSteer/DecisionHandling/DecisionHandling/TrigCompositeUtils.h index 28032b4f2e981d1ee23c7ddbfe7a1596ef36382a..d0e0ed08bc36ebcd08471c279b4b9dab3cebdc15 100644 --- a/Trigger/TrigSteer/DecisionHandling/DecisionHandling/TrigCompositeUtils.h +++ b/Trigger/TrigSteer/DecisionHandling/DecisionHandling/TrigCompositeUtils.h @@ -225,15 +225,6 @@ namespace TrigCompositeUtils { **/ void recursiveGetDecisionsInternal( const Decision* start, const size_t location, std::vector<ElementLinkVector<DecisionContainer>>& linkVector, const DecisionID id = 0); - /** - * @brief Extract features from the supplied linkVector (obtained through recursiveGetDecisions). - * @param[in] linkVector Vector of paths through the navigation which are to be considered. - * @param[oneFeaturePerLeg] oneFeaturePerLeg If True, stops at the first feature (of the correct type) found per path through the navigation. - * @return Typed vector of element links to all features found on the supplied linkVector. - **/ - template<class CONTAINER> - ElementLinkVector<CONTAINER> getFeaturesOfType( const std::vector<ElementLinkVector<DecisionContainer>>& linkVector, const bool oneFeaturePerLeg = true ); - /** * @brief Helper to keep the TC & object it has linked together (for convenience) **/ @@ -256,6 +247,15 @@ namespace TrigCompositeUtils { ElementLink<T> link; }; + /** + * @brief Extract features from the supplied linkVector (obtained through recursiveGetDecisions). + * @param[in] linkVector Vector of paths through the navigation which are to be considered. + * @param[oneFeaturePerLeg] oneFeaturePerLeg If True, stops at the first feature (of the correct type) found per path through the navigation. + * @return Typed vector of LinkInfo. Each LinkInfo wraps an ElementLink to a feature and a pointer to the feature's Decision object in the navigation. + **/ + template<class CONTAINER> + const std::vector< LinkInfo<CONTAINER> > getFeaturesOfType( const std::vector<ElementLinkVector<DecisionContainer>>& linkVector, const bool oneFeaturePerLeg = true ); + /** * @brief search back the TC links for the object of type T linked to the one of TC (recursively) * @arg start the TC from where the link back is to be looked for diff --git a/Trigger/TrigSteer/DecisionHandling/DecisionHandling/TrigCompositeUtils.icc b/Trigger/TrigSteer/DecisionHandling/DecisionHandling/TrigCompositeUtils.icc index 784b207047d608b9d7110e7eaa600ce9ab0ced36..549323c16767eb914c716bf48f658d3199408ba4 100644 --- a/Trigger/TrigSteer/DecisionHandling/DecisionHandling/TrigCompositeUtils.icc +++ b/Trigger/TrigSteer/DecisionHandling/DecisionHandling/TrigCompositeUtils.icc @@ -60,20 +60,20 @@ namespace TrigCompositeUtils { } template<class CONTAINER> - ElementLinkVector<CONTAINER> getFeaturesOfType(const std::vector<ElementLinkVector<DecisionContainer>>& linkVector, const bool oneFeaturePerLeg) { - ElementLinkVector<CONTAINER> features; + const std::vector< LinkInfo<CONTAINER> > getFeaturesOfType(const std::vector<ElementLinkVector<DecisionContainer>>& linkVector, const bool oneFeaturePerLeg) { + std::vector< LinkInfo<CONTAINER> > features; // For each unique path through the navigation for a given chain for (const ElementLinkVector<DecisionContainer>& decisionPath : linkVector) { // For each step along this path, starting at the terminus and working back towards L1 for (const ElementLink<DecisionContainer>& decisionLink : decisionPath) { const Decision* decision = (*decisionLink); - if (decision->hasObjectLink("feature", ClassID_traits< CONTAINER >::ID())) { + if (decision->hasObjectLink(featureString(), ClassID_traits< CONTAINER >::ID())) { // This try block protects against ExcCLIDMismatch throws from // features which do not derive from IParticle, when an IParticle interface is requested. try { - const ElementLink<CONTAINER> featureLink = decision->objectLink<CONTAINER>("feature"); - features.push_back( featureLink ); + const ElementLink<CONTAINER> featureLink = decision->objectLink<CONTAINER>( featureString() ); + features.push_back( LinkInfo<CONTAINER>(decision, featureLink) ); if (oneFeaturePerLeg) { break; } diff --git a/Trigger/TrigSteer/DecisionHandling/share/TrigCompositeUtils_test.ref b/Trigger/TrigSteer/DecisionHandling/share/TrigCompositeUtils_test.ref index 7592d0dbb9c221812978d81293782199efd62d61..bee27322b7d9e515ba226410f7ff0a38f7965adf 100644 --- a/Trigger/TrigSteer/DecisionHandling/share/TrigCompositeUtils_test.ref +++ b/Trigger/TrigSteer/DecisionHandling/share/TrigCompositeUtils_test.ref @@ -35,26 +35,26 @@ xAOD::TrigComposite_v1::setObjectLink ERROR link is not valid New decision d3b with name & context d3b: TrigComposite_v1 name:'d3b' - N Lnks:1 + N Links:1, isRemapped:NO Link Name:testlink, Key:1042135810, Index:1, CLID:1333228823 el2 1042135810 1 d3: TrigComposite_v1 name:'' - N Lnks:1 + N Links:1, isRemapped:NO Link Name:seed__COLL, Key:1042135810, Index:1, CLID:1333228823 N Decisions:2 95, 99, d4: TrigComposite_v1 name:'' - N Lnks:1 + N Links:1, isRemapped:NO Link Name:seed__COLL, Key:1042135810, Index:1, CLID:1333228823 el: key 1042135810 index 1 create d5 set link d5: TrigComposite_v1 name:'d5' - N Lnks:1 + N Links:1, isRemapped:NO Link Name:feature, Key:1042135810, Index:1, CLID:1333228823 create d6 d6: TrigComposite_v1 name:'d6' - N Lnks:1 + N Links:1, isRemapped:NO Link Name:seed__COLL, Key:1042135810, Index:5, CLID:1333228823 get d5 feature link get d6 feature link diff --git a/Trigger/TrigSteer/DecisionHandling/share/TrigTraversal_test.ref b/Trigger/TrigSteer/DecisionHandling/share/TrigTraversal_test.ref index bb1a91f9ff5119b6a124f65487875477af718712..ea15ceb53b591dff3e2c78aac9bc21988ffe78cd 100644 --- a/Trigger/TrigSteer/DecisionHandling/share/TrigTraversal_test.ref +++ b/Trigger/TrigSteer/DecisionHandling/share/TrigTraversal_test.ref @@ -7,24 +7,25 @@ ApplicationMgr Ready Context: s: 0 e: 0 Current context: s: 0 e: 0 1 paths for HLT_mufast_chain - Path 0[HLTPassRaw -> END_MU_H_1__MU1 -> MU_H_1__MU1 F(20) -> MU_IM_1__MU1 -> MU_F_1__MU1 -> MU1] -1 paths for HLT_mu_chain - Path 0[HLTPassRaw -> END_MU_H_2__MU1 -> MU_H_2__MU1 F(21) -> MU_IM_2__MU1 -> MU_F_2__MU1 -> MU_H_1__MU1 F(20) -> MU_IM_1__MU1 -> MU_F_1__MU1 -> MU1] + Path 0[HLTPassRaw -> MU_H_1__MU1 F(20) -> MU_IM_1__MU1 -> MU_F_1__MU1 -> MU1] +2 paths for HLT_mu_chain + Path 0[HLTPassRaw -> MU_H_1__MU1 F(20) -> MU_IM_1__MU1 -> MU_F_1__MU1 -> MU1] + Path 1[HLTPassRaw -> MU_H_2__MU1 F(21) -> MU_IM_2__MU1 -> MU_F_2__MU1 -> MU_H_1__MU1 F(20) -> MU_IM_1__MU1 -> MU_F_1__MU1 -> MU1] 2 paths for HLT_mu_em_chain - Path 0[HLTPassRaw -> END_MUEM_CH_2__MU1 -> MUEM_CH_2__MU1 -> MUEM_H_2__MU1 F(21) -> MUEM_IM_2__MU1 -> MUEM_F_2__MU1 -> MUEM_CH_1__MU1 -> MUEM_H_1__MU1 F(20) -> MUEM_IM_1__MU1 -> MUEM_F_1__MU1 -> MU1] - Path 1[HLTPassRaw -> END_MUEM_CH_2__EM0 -> MUEM_CH_2__EM0 -> MUEM_H_2__EM0 F(31) -> MUEM_IM_2__EM0 -> MUEM_F_2__EM0 -> MUEM_CH_1__EM0 -> MUEM_H_1__EM0 F(30) -> MUEM_IM_1__EM0 -> MUEM_F_1__EM0 -> EM0] + Path 0[HLTPassRaw -> MUEM_CH_2__MU1 -> MUEM_H_2__MU1 F(21) -> MUEM_IM_2__MU1 -> MUEM_F_2__MU1 -> MUEM_CH_1__MU1 -> MUEM_H_1__MU1 F(20) -> MUEM_IM_1__MU1 -> MUEM_F_1__MU1 -> MU1] + Path 1[HLTPassRaw -> MUEM_CH_2__EM0 -> MUEM_H_2__EM0 F(31) -> MUEM_IM_2__EM0 -> MUEM_F_2__EM0 -> MUEM_CH_1__EM0 -> MUEM_H_1__EM0 F(30) -> MUEM_IM_1__EM0 -> MUEM_F_1__EM0 -> EM0] 1 paths for HLT_em_chain - Path 0[HLTPassRaw -> END_EM_H_2__EM0 -> EM_H_2__EM0 F(31) -> EM_IM_2__EM0 -> EM_F_2__EM0 -> EM_H_1__EM0 F(30) -> EM_IM_1__EM0 -> EM_F_1__EM0 -> EM0] + Path 0[HLTPassRaw -> EM_H_2__EM0 F(31) -> EM_IM_2__EM0 -> EM_F_2__EM0 -> EM_H_1__EM0 F(30) -> EM_IM_1__EM0 -> EM_F_1__EM0 -> EM0] 5 paths for All - Path 0[HLTPassRaw -> END_MU_H_1__MU1 -> MU_H_1__MU1 F(20) -> MU_IM_1__MU1 -> MU_F_1__MU1 -> MU1] - Path 1[HLTPassRaw -> END_MU_H_2__MU1 -> MU_H_2__MU1 F(21) -> MU_IM_2__MU1 -> MU_F_2__MU1 -> MU_H_1__MU1 F(20) -> MU_IM_1__MU1 -> MU_F_1__MU1 -> MU1] - Path 2[HLTPassRaw -> END_MUEM_CH_2__MU1 -> MUEM_CH_2__MU1 -> MUEM_H_2__MU1 F(21) -> MUEM_IM_2__MU1 -> MUEM_F_2__MU1 -> MUEM_CH_1__MU1 -> MUEM_H_1__MU1 F(20) -> MUEM_IM_1__MU1 -> MUEM_F_1__MU1 -> MU1] - Path 3[HLTPassRaw -> END_EM_H_2__EM0 -> EM_H_2__EM0 F(31) -> EM_IM_2__EM0 -> EM_F_2__EM0 -> EM_H_1__EM0 F(30) -> EM_IM_1__EM0 -> EM_F_1__EM0 -> EM0] - Path 4[HLTPassRaw -> END_MUEM_CH_2__EM0 -> MUEM_CH_2__EM0 -> MUEM_H_2__EM0 F(31) -> MUEM_IM_2__EM0 -> MUEM_F_2__EM0 -> MUEM_CH_1__EM0 -> MUEM_H_1__EM0 F(30) -> MUEM_IM_1__EM0 -> MUEM_F_1__EM0 -> EM0] + Path 0[HLTPassRaw -> MU_H_1__MU1 F(20) -> MU_IM_1__MU1 -> MU_F_1__MU1 -> MU1] + Path 1[HLTPassRaw -> MU_H_2__MU1 F(21) -> MU_IM_2__MU1 -> MU_F_2__MU1 -> MU_H_1__MU1 F(20) -> MU_IM_1__MU1 -> MU_F_1__MU1 -> MU1] + Path 2[HLTPassRaw -> MUEM_CH_2__MU1 -> MUEM_H_2__MU1 F(21) -> MUEM_IM_2__MU1 -> MUEM_F_2__MU1 -> MUEM_CH_1__MU1 -> MUEM_H_1__MU1 F(20) -> MUEM_IM_1__MU1 -> MUEM_F_1__MU1 -> MU1] + Path 3[HLTPassRaw -> EM_H_2__EM0 F(31) -> EM_IM_2__EM0 -> EM_F_2__EM0 -> EM_H_1__EM0 F(30) -> EM_IM_1__EM0 -> EM_F_1__EM0 -> EM0] + Path 4[HLTPassRaw -> MUEM_CH_2__EM0 -> MUEM_H_2__EM0 F(31) -> MUEM_IM_2__EM0 -> MUEM_F_2__EM0 -> MUEM_CH_1__EM0 -> MUEM_H_1__EM0 F(30) -> MUEM_IM_1__EM0 -> MUEM_F_1__EM0 -> EM0] [All features] HLT_mufast_chain features size:1 Feature 0:20, -[All features] HLT_mu_chain features size:2 - Feature 0:21, Feature 1:20, +[All features] HLT_mu_chain features size:3 + Feature 0:20, Feature 1:21, Feature 2:20, [All features] HLT_mu_em_chain features size:4 Feature 0:21, Feature 1:20, Feature 2:31, Feature 3:30, [All features] HLT_em_chain features size:2 @@ -33,8 +34,8 @@ Current context: s: 0 e: 0 Feature 0:20, Feature 1:21, Feature 2:20, Feature 3:21, Feature 4:20, Feature 5:31, Feature 6:30, Feature 7:31, Feature 8:30, [Final feature] HLT_mufast_chain features size:1 Feature 0:20, -[Final feature] HLT_mu_chain features size:1 - Feature 0:21, +[Final feature] HLT_mu_chain features size:2 + Feature 0:20, Feature 1:21, [Final feature] HLT_mu_em_chain features size:2 Feature 0:21, Feature 1:31, [Final feature] HLT_em_chain features size:1 diff --git a/Trigger/TrigSteer/DecisionHandling/src/TrigCompositeUtils.cxx b/Trigger/TrigSteer/DecisionHandling/src/TrigCompositeUtils.cxx index ffd4959b554d5b743547b929bd9319488b5d900d..d83e54bbe65947f99db8cedd23fc278d98360820 100644 --- a/Trigger/TrigSteer/DecisionHandling/src/TrigCompositeUtils.cxx +++ b/Trigger/TrigSteer/DecisionHandling/src/TrigCompositeUtils.cxx @@ -169,12 +169,9 @@ namespace TrigCompositeUtils { void recursiveGetDecisionsInternal(const Decision* start, const size_t location, std::vector<ElementLinkVector<DecisionContainer>>& linkVector, const DecisionID id) { // Does this Decision satisfy the chain requirement? - // Don't check this for HLTPassRaw or HLTRerun. These inital nodes have empty sets - if (start->name() != "HLTPassRaw" && start->name() != "HLTRerun") { - DecisionIDContainer idSet = {id}; - if (id != 0 && !isAnyIDPassing(start, idSet)) { - return; // Stop propagating down this leg. It does not concern the chain with DecisionID = id - } + DecisionIDContainer idSet = {id}; + if (id != 0 && !isAnyIDPassing(start, idSet)) { + return; // Stop propagating down this leg. It does not concern the chain with DecisionID = id } // This Decision object is part of this linear path through the Navigation @@ -211,7 +208,7 @@ namespace TrigCompositeUtils { } void recursiveGetDecisions(const Decision* start, std::vector<ElementLinkVector<DecisionContainer>>& linkVector, const DecisionID id) { - // Note: we do not require recursiveGetDecisions to be an empty vector. We can append to it. + // Note: we do not require linkVector to be an empty vector. We can append to it. linkVector.push_back( ElementLinkVector<DecisionContainer>() ); // Our starting point const size_t startingElement = linkVector.size() - 1; recursiveGetDecisionsInternal(start, startingElement, linkVector, id); diff --git a/Trigger/TrigSteer/DecisionHandling/test/TrigTraversal_test.cxx b/Trigger/TrigSteer/DecisionHandling/test/TrigTraversal_test.cxx index bf9b0841d146486933d01edf9aae2fd371e4709a..edecd00b0bee1ae79a0cf987cf591f3e86079fe8 100644 --- a/Trigger/TrigSteer/DecisionHandling/test/TrigTraversal_test.cxx +++ b/Trigger/TrigSteer/DecisionHandling/test/TrigTraversal_test.cxx @@ -28,7 +28,7 @@ using TrigCompositeUtils::DecisionContainer; void printPaths(const std::vector<ElementLinkVector<DecisionContainer>>& paths, const std::string& name); template<class CONTAINER> -void printFeatures(const ElementLinkVector<CONTAINER>& featureContainer, const std::string& name); +void printFeatures(const std::vector< TrigCompositeUtils::LinkInfo<CONTAINER> >& featureContainer, const std::string& name); /// @brief Test to check traversal functions of a graph of interconnect TrigComposite objects /// @@ -205,12 +205,23 @@ int main ATLAS_NOT_THREAD_SAFE () { MU_H_1__MU1->setObjectLink<xAOD::MuonContainer>("feature", rec_1__mu1_link); addDecisionID(HLT_mufast_chain, MU_H_1__MU1); addDecisionID(HLT_mu_chain, MU_H_1__MU1); - // HLT_mufast_chain passes the event - Decision* END_MU_H_1__MU1 = newDecisionIn(decisionContainerPtr, "END_MU_H_1__MU1"); - linkToPrevious(END_MU_H_1__MU1, MU_H_1__MU1); - addDecisionID(HLT_mufast_chain, END_MU_H_1__MU1); - linkToPrevious(END, END_MU_H_1__MU1); + addDecisionID(HLT_mufast_chain, END); + linkToPrevious(END, MU_H_1__MU1); + + /// !!! + /// !!! + /// !!! When finding the first feature for the HLT_mu_chain, the navigation is here given two entry points into the graph, + /// !!! the correct one (MU_H_2__MU1) and an incorrect one (MU_H_1__MU1) due to HLT_mufast_chain also passing this event + /// !!! at this earlier Step. + /// !!! + /// !!! The feature access is currently "dumb", it doesn't know what should be the final step for each chain. Hence here + /// !!! it will return both the Step1 muon and the Step2 muon when asked for the first feature down each leg for HLT_mu_chain, + /// !!! Rather than just the Step2 muon. + /// !!! + /// !!! This will be corrected later, once the Trigger Decision Tool has access to more menu reflection information. + /// !!! + /// !!! Decision* MU_F_2__MU1 = newDecisionIn(decisionContainerPtr, "MU_F_2__MU1"); linkToPrevious(MU_F_2__MU1, MU_H_1__MU1); @@ -224,12 +235,9 @@ int main ATLAS_NOT_THREAD_SAFE () { linkToPrevious(MU_H_2__MU1, MU_IM_2__MU1); MU_H_2__MU1->setObjectLink<xAOD::MuonContainer>("feature", rec_2__mu1_link); addDecisionID(HLT_mu_chain, MU_H_2__MU1); - // HLT_mu_chain passes the event - Decision* END_MU_H_2__MU1 = newDecisionIn(decisionContainerPtr, "END_MU_H_2__MU1"); - linkToPrevious(END_MU_H_2__MU1, MU_H_2__MU1); - addDecisionID(HLT_mu_chain, END_MU_H_2__MU1); - linkToPrevious(END, END_MU_H_2__MU1); + addDecisionID(HLT_mu_chain, END); + linkToPrevious(END, MU_H_2__MU1); } /// @@ -272,12 +280,10 @@ int main ATLAS_NOT_THREAD_SAFE () { Decision* MUEM_CH_2__MU1 = newDecisionIn(decisionContainerPtr, "MUEM_CH_2__MU1"); linkToPrevious(MUEM_CH_2__MU1, MUEM_H_2__MU1); addDecisionID(HLT_mu_em_chain, MUEM_CH_2__MU1); - // HLT_mu_em_chain passes the event - Decision* END_MUEM_CH_2__MU1 = newDecisionIn(decisionContainerPtr, "END_MUEM_CH_2__MU1"); - linkToPrevious(END_MUEM_CH_2__MU1, MUEM_CH_2__MU1); - addDecisionID(HLT_mu_em_chain, END_MUEM_CH_2__MU1); - linkToPrevious(END, END_MUEM_CH_2__MU1); + addDecisionID(HLT_mu_em_chain, END); + linkToPrevious(END, MUEM_CH_2__MU1); + } /// @@ -312,12 +318,9 @@ int main ATLAS_NOT_THREAD_SAFE () { linkToPrevious(EM_H_2__EM0, EM_IM_2__EM0); EM_H_2__EM0->setObjectLink<xAOD::ElectronContainer>("feature", rec_2__em0_link); addDecisionID(HLT_em_chain, EM_H_2__EM0); - // HLT_em_chain passes the event - Decision* END_EM_H_2__EM0 = newDecisionIn(decisionContainerPtr, "END_EM_H_2__EM0"); - linkToPrevious(END_EM_H_2__EM0, EM_H_2__EM0); - addDecisionID(HLT_em_chain, END_EM_H_2__EM0); - linkToPrevious(END, END_EM_H_2__EM0); + linkToPrevious(END, EM_H_2__EM0); + addDecisionID(HLT_em_chain, END); } /// @@ -360,12 +363,9 @@ int main ATLAS_NOT_THREAD_SAFE () { Decision* MUEM_CH_2__EM0 = newDecisionIn(decisionContainerPtr, "MUEM_CH_2__EM0"); linkToPrevious(MUEM_CH_2__EM0, MUEM_H_2__EM0); addDecisionID(HLT_mu_em_chain, MUEM_CH_2__EM0); - // HLT_mu_em_chain passes the event - Decision* END_MUEM_CH_2__EM0 = newDecisionIn(decisionContainerPtr, "END_MUEM_CH_2__EM0"); - linkToPrevious(END_MUEM_CH_2__EM0, MUEM_CH_2__EM0); - addDecisionID(HLT_mu_em_chain, END_MUEM_CH_2__EM0); - linkToPrevious(END, END_MUEM_CH_2__EM0); + addDecisionID(HLT_mu_em_chain, END); + linkToPrevious(END, MUEM_CH_2__EM0); } // Test the graph @@ -388,11 +388,11 @@ int main ATLAS_NOT_THREAD_SAFE () { printPaths(paths_HLT_em_chain, "HLT_em_chain"); printPaths(paths_HLT_all, "All"); - ElementLinkVector<xAOD::IParticleContainer> features_all_HLT_mufast_chain = getFeaturesOfType<xAOD::IParticleContainer>(paths_HLT_mufast_chain, false); - ElementLinkVector<xAOD::IParticleContainer> features_all_HLT_mu_chain = getFeaturesOfType<xAOD::IParticleContainer>(paths_HLT_mu_chain, false); - ElementLinkVector<xAOD::IParticleContainer> features_all_HLT_mu_em_chain = getFeaturesOfType<xAOD::IParticleContainer>(paths_HLT_mu_em_chain, false); - ElementLinkVector<xAOD::IParticleContainer> features_all_HLT_em_chain = getFeaturesOfType<xAOD::IParticleContainer>(paths_HLT_em_chain, false); - ElementLinkVector<xAOD::IParticleContainer> features_all_HLT_all = getFeaturesOfType<xAOD::IParticleContainer>(paths_HLT_all, false); + std::vector< LinkInfo<xAOD::IParticleContainer> > features_all_HLT_mufast_chain = getFeaturesOfType<xAOD::IParticleContainer>(paths_HLT_mufast_chain, false); + std::vector< LinkInfo<xAOD::IParticleContainer> > features_all_HLT_mu_chain = getFeaturesOfType<xAOD::IParticleContainer>(paths_HLT_mu_chain, false); + std::vector< LinkInfo<xAOD::IParticleContainer> > features_all_HLT_mu_em_chain = getFeaturesOfType<xAOD::IParticleContainer>(paths_HLT_mu_em_chain, false); + std::vector< LinkInfo<xAOD::IParticleContainer> > features_all_HLT_em_chain = getFeaturesOfType<xAOD::IParticleContainer>(paths_HLT_em_chain, false); + std::vector< LinkInfo<xAOD::IParticleContainer> > features_all_HLT_all = getFeaturesOfType<xAOD::IParticleContainer>(paths_HLT_all, false); printFeatures(features_all_HLT_mufast_chain, "[All features] HLT_mufast_chain"); printFeatures(features_all_HLT_mu_chain, "[All features] HLT_mu_chain"); @@ -400,11 +400,11 @@ int main ATLAS_NOT_THREAD_SAFE () { printFeatures(features_all_HLT_em_chain, "[All features] HLT_em_chain"); printFeatures(features_all_HLT_all, "[All features] All chains"); - ElementLinkVector<xAOD::IParticleContainer> features_final_HLT_mufast_chain = getFeaturesOfType<xAOD::IParticleContainer>(paths_HLT_mufast_chain, true); - ElementLinkVector<xAOD::IParticleContainer> features_final_HLT_mu_chain = getFeaturesOfType<xAOD::IParticleContainer>(paths_HLT_mu_chain, true); - ElementLinkVector<xAOD::IParticleContainer> features_final_HLT_mu_em_chain = getFeaturesOfType<xAOD::IParticleContainer>(paths_HLT_mu_em_chain, true); - ElementLinkVector<xAOD::IParticleContainer> features_final_HLT_em_chain = getFeaturesOfType<xAOD::IParticleContainer>(paths_HLT_em_chain, true); - ElementLinkVector<xAOD::IParticleContainer> features_final_HLT_all = getFeaturesOfType<xAOD::IParticleContainer>(paths_HLT_all, true); + std::vector< LinkInfo<xAOD::IParticleContainer> > features_final_HLT_mufast_chain = getFeaturesOfType<xAOD::IParticleContainer>(paths_HLT_mufast_chain, true); + std::vector< LinkInfo<xAOD::IParticleContainer> > features_final_HLT_mu_chain = getFeaturesOfType<xAOD::IParticleContainer>(paths_HLT_mu_chain, true); + std::vector< LinkInfo<xAOD::IParticleContainer> > features_final_HLT_mu_em_chain = getFeaturesOfType<xAOD::IParticleContainer>(paths_HLT_mu_em_chain, true); + std::vector< LinkInfo<xAOD::IParticleContainer> > features_final_HLT_em_chain = getFeaturesOfType<xAOD::IParticleContainer>(paths_HLT_em_chain, true); + std::vector< LinkInfo<xAOD::IParticleContainer> > features_final_HLT_all = getFeaturesOfType<xAOD::IParticleContainer>(paths_HLT_all, true); printFeatures(features_final_HLT_mufast_chain, "[Final feature] HLT_mufast_chain"); printFeatures(features_final_HLT_mu_chain, "[Final feature] HLT_mu_chain"); @@ -413,8 +413,8 @@ int main ATLAS_NOT_THREAD_SAFE () { printFeatures(features_final_HLT_all, "[Final feature] All chains"); // Check typed retrieval too - ElementLinkVector<xAOD::MuonContainer> features_final_mu = getFeaturesOfType<xAOD::MuonContainer>(paths_HLT_mu_em_chain); - ElementLinkVector<xAOD::ElectronContainer> features_final_em = getFeaturesOfType<xAOD::ElectronContainer>(paths_HLT_mu_em_chain); + std::vector< LinkInfo<xAOD::MuonContainer> > features_final_mu = getFeaturesOfType<xAOD::MuonContainer>(paths_HLT_mu_em_chain); + std::vector< LinkInfo<xAOD::ElectronContainer> > features_final_em = getFeaturesOfType<xAOD::ElectronContainer>(paths_HLT_mu_em_chain); printFeatures(features_final_mu, "[Explicit Final Muon Features] HLT_mu_em_chain"); printFeatures(features_final_em, "[Explicit Final Electron Features] HLT_mu_em_chain"); @@ -427,11 +427,11 @@ int main ATLAS_NOT_THREAD_SAFE () { } template<class CONTAINER> -void printFeatures(const ElementLinkVector<CONTAINER>& featureContainer, const std::string& name) { +void printFeatures(const std::vector< TrigCompositeUtils::LinkInfo<CONTAINER> >& featureContainer, const std::string& name) { std::cout << name << " features size:" << featureContainer.size() << std::endl; size_t count = 0; - for (ElementLink<CONTAINER> featureLink : featureContainer) { - std::cout << " Feature " << count++ << ":" << (*featureLink)->pt() << ","; + for (const TrigCompositeUtils::LinkInfo<CONTAINER>& featureLinkInfo : featureContainer) { + std::cout << " Feature " << count++ << ":" << (*featureLinkInfo.link)->pt() << ","; } std::cout << std::endl; } diff --git a/Trigger/TrigSteer/TrigOutputHandling/src/DecisionSummaryMakerAlg.cxx b/Trigger/TrigSteer/TrigOutputHandling/src/DecisionSummaryMakerAlg.cxx index 122b4fcb734e1d53bba86bbd9c3ffcbc71d92095..e3f91b0a20e9b7b1fa9eb0c523609b65de666d2c 100644 --- a/Trigger/TrigSteer/TrigOutputHandling/src/DecisionSummaryMakerAlg.cxx +++ b/Trigger/TrigSteer/TrigOutputHandling/src/DecisionSummaryMakerAlg.cxx @@ -76,16 +76,17 @@ StatusCode DecisionSummaryMakerAlg::execute(const EventContext& context) const { continue; } - // Copy decisions set into passRawOutput's persistent vector - decisionIDs(passRawOutput).insert( decisionIDs(passRawOutput).end(), - passingFinalIDs.begin(), passingFinalIDs.end() ); - - if (msgLvl(MSG::DEBUG)) { - allPassingFinalIDs.insert( passingFinalIDs.begin(), passingFinalIDs.end() ); - } + // Accumulate and de-duplicate passed IDs for which this hypo was the Chain's final step + allPassingFinalIDs.insert( passingFinalIDs.begin(), passingFinalIDs.end() ); + // Create seed links for the navigation to follow + linkToPrevious(passRawOutput, decisionObject, context); } } + // Copy decisions set into passRawOutput's persistent vector + decisionIDs(passRawOutput).insert( decisionIDs(passRawOutput).end(), + allPassingFinalIDs.begin(), allPassingFinalIDs.end() ); + if (msgLvl(MSG::DEBUG)) { ATH_MSG_DEBUG( "Number of positive decisions " << allPassingFinalIDs.size() << " passing chains"); for ( auto d: allPassingFinalIDs ) { diff --git a/Trigger/TrigSteer/TrigOutputHandling/src/HLTEDMCreator.cxx b/Trigger/TrigSteer/TrigOutputHandling/src/HLTEDMCreator.cxx index e3237abefebfa56706ae26df4113501909ed9dbb..30b5de790b6c8104bbd5baa414fc4670434bb9df 100644 --- a/Trigger/TrigSteer/TrigOutputHandling/src/HLTEDMCreator.cxx +++ b/Trigger/TrigSteer/TrigOutputHandling/src/HLTEDMCreator.cxx @@ -10,8 +10,8 @@ #include "StoreGate/WriteDecorHandle.h" HLTEDMCreator::HLTEDMCreator( const std::string& type, - const std::string& name, - const IInterface* parent ) + const std::string& name, + const IInterface* parent ) : base_class( type, name, parent ) {} template<typename T> @@ -65,12 +65,16 @@ StatusCode HLTEDMCreator::initialize() #undef INIT #undef INIT_XAOD - if ( m_fixLinks ) { - for ( auto writeHandleKey: m_TrigCompositeContainer ) { - m_remapLinkCollKeys.emplace_back( writeHandleKey.key()+".remap_linkCollKeys" ); - m_remapLinkColIndices.emplace_back( writeHandleKey.key()+".remap_linkCollIndices" ); + if ( m_fixLinks.size() > 0 ) { + for ( const auto& writeHandleKey: m_TrigCompositeContainer ) { + const bool doFixLinks = std::any_of(m_fixLinks.begin(), m_fixLinks.end(), [&](const std::string& s) { return s == writeHandleKey.key(); } ); + if (doFixLinks) { + // This writeHandleKey is being included in the element link remapping + m_remapLinkColKeys.emplace_back( writeHandleKey.key()+".remap_linkColKeys" ); + m_remapLinkColIndices.emplace_back( writeHandleKey.key()+".remap_linkColIndices" ); + } } - ATH_CHECK( m_remapLinkCollKeys.initialize() ) ; + ATH_CHECK( m_remapLinkColKeys.initialize() ) ; ATH_CHECK( m_remapLinkColIndices.initialize() ); } @@ -106,7 +110,7 @@ struct xAODGenerator { template<typename T> StatusCode HLTEDMCreator::noMerge( ViewContainer const&, const SG::ReadHandleKey<T>&, - EventContext const&, T & ) const { + EventContext const&, T & ) const { // if we are called it means views merging is requested but Type T does not support it (i.e. missing copy c'tor) return StatusCode::FAILURE; @@ -114,7 +118,7 @@ StatusCode HLTEDMCreator::noMerge( ViewContainer const&, const SG::ReadHandleKe template<typename T> StatusCode HLTEDMCreator::viewsMerge( ViewContainer const& views, const SG::ReadHandleKey<T>& inViewKey, - EventContext const& context, T & output ) const { + EventContext const& context, T & output ) const { typedef typename T::base_value_type type_in_container; StoreGateSvc* sg = evtStore().operator->(); // why the get() method is returing a null ptr is a puzzle, we have to use this ugly call to operator instead of it @@ -128,68 +132,75 @@ StatusCode HLTEDMCreator::viewsMerge( ViewContainer const& views, const SG::Rea StatusCode HLTEDMCreator::fixLinks( const ConstHandlesGroup< xAOD::TrigCompositeContainer >& handles ) const { - // Make a list of the collections we're going to mess with - // std::set< std::string > remappedCollections; - // for ( auto writeHandleKey : handles.out ) { - // remappedCollections.insert( writeHandleKey.key() ); - // } - static const SG::AuxElement::ConstAccessor< std::vector< uint32_t > > keyAccessor( "linkColKeys" ); - static const SG::AuxElement::ConstAccessor< std::vector< uint16_t > > offsetAccessor( "linkColIndices" ); + static const SG::AuxElement::ConstAccessor< std::vector< uint16_t > > indexAccessor( "linkColIndices" ); ATH_MSG_DEBUG("Fixing links called for " << handles.out.size() << " object(s)"); // Do the remapping - int index = -1; + int writeHandleArrayIndex = -1; for ( auto writeHandleKey : handles.out ) { - index++; - ATH_MSG_DEBUG("Fixing links: see if collection is there: " << writeHandleKey.key() << " index " << index); + ++writeHandleArrayIndex; + // Check if we are re-mapping this handle + const bool doFixLinks = std::any_of(m_fixLinks.begin(), m_fixLinks.end(), [&](const std::string& s) { return s == writeHandleKey.key(); } ); + if ( not doFixLinks ) { + ATH_MSG_DEBUG("Not requested to fix TrigComposite ElementLinks for " << writeHandleKey.key()); + continue; + } + + ATH_MSG_DEBUG("Fixing links: see if collection is there: " << writeHandleKey.key() << ", write hand array index: " << writeHandleArrayIndex); SG::ReadHandle<xAOD::TrigCompositeContainer> readHandle( writeHandleKey.key() ); if ( not readHandle.isValid() ) { // object missing, ok, may be early rejection continue; } - ATH_MSG_DEBUG("Fixing links: collection is there: " << writeHandleKey.key() ); - ATH_MSG_DEBUG("Adding decorations: " << m_remapLinkCollKeys.at( index ).key() << " and " << m_remapLinkColIndices.at( index ).key() ); + ATH_MSG_DEBUG("Fixing links: collection exists: " << writeHandleKey.key() << " with size " << readHandle->size() << " Decision objects" ); + ATH_MSG_DEBUG("Adding decorations: " << m_remapLinkColKeys.at( writeHandleArrayIndex ).key() << " and " << m_remapLinkColIndices.at( writeHandleArrayIndex ).key() ); - SG::WriteDecorHandle<xAOD::TrigCompositeContainer, std::vector<uint32_t> > keyDecor( m_remapLinkCollKeys.at( index ) ); - SG::WriteDecorHandle<xAOD::TrigCompositeContainer, std::vector<uint16_t> > offsetDecor( m_remapLinkColIndices.at( index ) ); + SG::WriteDecorHandle<xAOD::TrigCompositeContainer, std::vector<uint32_t> > keyDecor( m_remapLinkColKeys.at( writeHandleArrayIndex ) ); + SG::WriteDecorHandle<xAOD::TrigCompositeContainer, std::vector<uint16_t> > indexDecor( m_remapLinkColIndices.at( writeHandleArrayIndex ) ); - // Examine each input TC + int decisionObjectIndex = -1; for ( auto inputDecision : *( readHandle.cptr() ) ) { + ++decisionObjectIndex; - // Retrieve the link information for remapping std::vector< uint32_t > remappedKeys = keyAccessor( *inputDecision ); - std::vector< uint16_t > remappedOffsets = offsetAccessor( *inputDecision ); + std::vector< uint16_t > remappedIndexes = indexAccessor( *inputDecision ); // Search the linked collections for remapping - unsigned int const collectionTotal = inputDecision->linkColNames().size(); - for ( unsigned int collectionIndex = 0; collectionIndex < collectionTotal; ++collectionIndex ) { - - // Load identifiers - std::string const collectionName = inputDecision->linkColNames()[ collectionIndex ]; - uint32_t const collectionKey = inputDecision->linkColKeys()[ collectionIndex ]; - std::string const keyString = *( evtStore()->keyToString( collectionKey ) ); - uint16_t const collectionOffset = inputDecision->linkColIndices()[ collectionIndex ]; - - // Check for remapping in a merge - uint32_t newKey = 0; - size_t newOffset = 0; - bool isRemapped = evtStore()->tryELRemap( collectionKey, collectionOffset, newKey, newOffset); - if ( isRemapped ) { - - ATH_MSG_DEBUG( "Remap link from " << *( evtStore()->keyToString( collectionKey ) ) << " to " << *( evtStore()->keyToString( newKey ) ) ); - remappedKeys[ collectionIndex ] = newKey; - remappedOffsets[ collectionIndex ] = newOffset; - } - + size_t const collectionTotal = inputDecision->linkColNames().size(); + ATH_MSG_DEBUG("Decision object #" << decisionObjectIndex << " has " << collectionTotal << " links"); + for ( size_t elementLinkIndex = 0; elementLinkIndex < collectionTotal; ++elementLinkIndex ) { + + // Load ElementLink identifiers (except for CLID) + std::string const collectionName = inputDecision->linkColNames().at(elementLinkIndex); + uint32_t const collectionKey = remappedKeys.at(elementLinkIndex); //Note: This is the existing before-remap key + std::string const keyString = *( evtStore()->keyToString( collectionKey ) ); + uint16_t const collectionIndex = remappedIndexes.at(elementLinkIndex); //Note: This is the existing before-remap index + + // Check for remapping in a merge + uint32_t newKey = 0; + size_t newIndex = 0; + bool isRemapped = evtStore()->tryELRemap( collectionKey, collectionIndex, newKey, newIndex); + if ( isRemapped ) { + + ATH_MSG_DEBUG( "Remap link [" << collectionName <<"] from " << keyString << " to " << *( evtStore()->keyToString( newKey ) ) << ", from index " << collectionIndex << " to index " << newIndex ); + remappedKeys[ elementLinkIndex ] = newKey; + remappedIndexes[ elementLinkIndex ] = newIndex; + + } else { + + ATH_MSG_DEBUG( "StoreGate did not remap link [" << collectionName << "] from " << keyString << " index " << collectionIndex ); + + } + } // Save the remaps keyDecor( *inputDecision ) = remappedKeys; - offsetDecor( *inputDecision ) = remappedOffsets; + indexDecor( *inputDecision ) = remappedIndexes; } } @@ -203,33 +214,33 @@ StatusCode HLTEDMCreator::createIfMissing( const EventContext& context, const Co for ( auto writeHandleKey : handles.out ) { SG::ReadHandle<T> readHandle( writeHandleKey.key() ); - + if ( readHandle.isValid() ) { ATH_MSG_DEBUG( "The " << writeHandleKey.key() << " already present" ); - } else { + } else { ATH_MSG_DEBUG( "The " << writeHandleKey.key() << " was absent, creating it" ); generator.create(); if ( handles.views.size() != 0 ) { - ATH_MSG_DEBUG("Will be trying to merge from " << handles.views.size() << " view containers into that output"); - auto viewCollKeyIter = handles.views.begin(); - auto inViewCollKeyIter = handles.in.begin(); - - for ( ; viewCollKeyIter != handles.views.end(); ++viewCollKeyIter, ++inViewCollKeyIter ) { - // get the views handle - - auto viewsHandle = SG::makeHandle( *viewCollKeyIter, context ); - if ( viewsHandle.isValid() ) { - ATH_MSG_DEBUG("Will be merging from " << viewsHandle->size() << " views " << viewCollKeyIter->key() << " view container using key " << inViewCollKeyIter->key() ); - CHECK( (this->*merger)( *viewsHandle, *inViewCollKeyIter , context, *generator.data.get() ) ); - } else { - ATH_MSG_DEBUG("Views " << viewCollKeyIter->key() << " are missing"); - } - } + ATH_MSG_DEBUG("Will be trying to merge from " << handles.views.size() << " view containers into that output"); + auto viewCollKeyIter = handles.views.begin(); + auto inViewCollKeyIter = handles.in.begin(); + + for ( ; viewCollKeyIter != handles.views.end(); ++viewCollKeyIter, ++inViewCollKeyIter ) { + // get the views handle + + auto viewsHandle = SG::makeHandle( *viewCollKeyIter, context ); + if ( viewsHandle.isValid() ) { + ATH_MSG_DEBUG("Will be merging from " << viewsHandle->size() << " views " << viewCollKeyIter->key() << " view container using key " << inViewCollKeyIter->key() ); + CHECK( (this->*merger)( *viewsHandle, *inViewCollKeyIter , context, *generator.data.get() ) ); + } else { + ATH_MSG_DEBUG("Views " << viewCollKeyIter->key() << " are missing"); + } + } } auto writeHandle = SG::makeHandle( writeHandleKey, context ); CHECK( generator.record( writeHandle ) ); - } + } } return StatusCode::SUCCESS; } @@ -237,12 +248,13 @@ StatusCode HLTEDMCreator::createIfMissing( const EventContext& context, const Co StatusCode HLTEDMCreator::createOutput(const EventContext& context) const { + ATH_MSG_DEBUG("Confirming / Creating this tool's output"); if ( m_dumpSGBefore ) ATH_MSG_DEBUG( evtStore()->dump() ); #define CREATE(__TYPE) \ - { \ - plainGenerator<__TYPE> generator; \ + { \ + plainGenerator<__TYPE> generator; \ CHECK( createIfMissing<__TYPE>( context, ConstHandlesGroup<__TYPE>( m_##__TYPE, m_##__TYPE##InViews, m_##__TYPE##Views ), generator, &HLTEDMCreator::noMerge<__TYPE> ) ); \ } @@ -257,7 +269,7 @@ StatusCode HLTEDMCreator::createOutput(const EventContext& context) const { } -#define CREATE_XAOD_NO_MERGE(__TYPE, __STORE_TYPE) \ +#define CREATE_XAOD_NO_MERGE(__TYPE, __STORE_TYPE) \ { \ xAODGenerator<xAOD::__TYPE, xAOD::__STORE_TYPE> generator; \ CHECK( createIfMissing<xAOD::__TYPE>( context, ConstHandlesGroup<xAOD::__TYPE>( m_##__TYPE, m_##__TYPE##InViews, m_##__TYPE##Views ), generator, &HLTEDMCreator::noMerge<xAOD::__TYPE> ) ); \ @@ -279,7 +291,7 @@ StatusCode HLTEDMCreator::createOutput(const EventContext& context) const { CREATE_XAOD( CaloClusterContainer, CaloClusterAuxContainer ); // After view collections are merged, need to update collection links - if ( m_fixLinks ) { + if ( m_fixLinks.size() > 0 ) { ATH_CHECK( fixLinks( ConstHandlesGroup<xAOD::TrigCompositeContainer>( m_TrigCompositeContainer, m_TrigCompositeContainerInViews, m_TrigCompositeContainerViews ) ) ); } diff --git a/Trigger/TrigSteer/TrigOutputHandling/src/HLTEDMCreator.h b/Trigger/TrigSteer/TrigOutputHandling/src/HLTEDMCreator.h index 09e0c9ab702d3cfa434b9acfcbbbb12e2c6ca8db..0acdd10f7edd36a0234d26357e7d2e65475461ef 100644 --- a/Trigger/TrigSteer/TrigOutputHandling/src/HLTEDMCreator.h +++ b/Trigger/TrigSteer/TrigOutputHandling/src/HLTEDMCreator.h @@ -75,9 +75,9 @@ class HLTEDMCreator: public extends<AthAlgTool, IHLTOutputTool> { private: HLTEDMCreator(); - Gaudi::Property<bool> m_fixLinks{ this, "FixLinks", false, "Fix links that may be pointing objects in views"}; - SG::WriteDecorHandleKeyArray<xAOD::TrigCompositeContainer, std::vector<uint32_t> > m_remapLinkCollKeys{ this, "DoNotSet_RemapLinkCollKeys", {}, "Do not set, it is configured accordingly to FixLinks & TC output property"}; - SG::WriteDecorHandleKeyArray<xAOD::TrigCompositeContainer, std::vector<uint16_t> > m_remapLinkColIndices{ this, "DoNotSet_RemapLinkCollIndices", {}, "Do not set, it is configured accordingly to FixLinks & TC output property"}; + Gaudi::Property<std::vector<std::string>> m_fixLinks{ this, "FixLinks", {}, "Which keys of the TrigCompositeContainer WriteHandleKeyArray might need to have their (e.g. feature) element links re-mapped outside of views"}; + SG::WriteDecorHandleKeyArray<xAOD::TrigCompositeContainer, std::vector<uint32_t> > m_remapLinkColKeys{ this, "DoNotSet_RemapLinkColKeys", {}, "Do not set, it is configured accordingly to FixLinks & TC output property"}; + SG::WriteDecorHandleKeyArray<xAOD::TrigCompositeContainer, std::vector<uint16_t> > m_remapLinkColIndices{ this, "DoNotSet_RemapLinkColIndices", {}, "Do not set, it is configured accordingly to FixLinks & TC output property"}; Gaudi::Property<bool> m_dumpSGBefore{ this, "dumpSGBefore", false, "Dump SG content before the merging"}; // for debugging Gaudi::Property<bool> m_dumpSGAfter { this, "dumpSGAfter", false, "Dump SG content after the merging"}; diff --git a/Trigger/TrigValidation/TrigUpgradeTest/share/full_menu.py b/Trigger/TrigValidation/TrigUpgradeTest/share/full_menu.py index c878ea1781440c17cf68a4faf844a9e31a92d552..bbaf5295faa100bc2c6e56b97dcb1d3c352d8896 100644 --- a/Trigger/TrigValidation/TrigUpgradeTest/share/full_menu.py +++ b/Trigger/TrigValidation/TrigUpgradeTest/share/full_menu.py @@ -2,6 +2,9 @@ # Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration # +from AthenaCommon.Logging import logging +__log = logging.getLogger('full_menu') + # import flags from RecExConfig.RecFlags import rec rec.doESD=True @@ -270,8 +273,8 @@ for a in AthSequencer("HLTAllSteps").getChildren(): # this part uses parts from the NewJO configuration, it is very hacky for the moment from TriggerJobOpts.TriggerConfig import collectHypos, collectFilters, collectDecisionObjects, triggerOutputStreamCfg -hypos = collectHypos(topSequence) -filters = collectFilters(topSequence) +hypos = collectHypos(AthSequencer("HLTAllSteps")) +filters = collectFilters(AthSequencer("HLTAllSteps")) # try to find L1Decoder from AthenaCommon.CFElements import findAlgorithm,findSubSequence @@ -281,7 +284,8 @@ if not l1decoder: if l1decoder: decObj = collectDecisionObjects( hypos, filters, l1decoder ) - print decObj + __log.debug("Decision Objects to export to ESD [hack method - should be replaced with triggerRunCfg()]") + __log.debug(decObj) from TrigEDMConfig.TriggerEDMRun3 import TriggerHLTList ItemList = [ 'xAOD::TrigCompositeContainer#{}'.format(d) for d in decObj ] diff --git a/Trigger/TrigValidation/TrigValAlgs/src/TrigEDMChecker.cxx b/Trigger/TrigValidation/TrigValAlgs/src/TrigEDMChecker.cxx index 51e75508b14633e75b5ca0b289ad14fed36238b5..bb371fdab6106a83c52d468ab8a98825d7d2c6ee 100644 --- a/Trigger/TrigValidation/TrigValAlgs/src/TrigEDMChecker.cxx +++ b/Trigger/TrigValidation/TrigValAlgs/src/TrigEDMChecker.cxx @@ -55,8 +55,6 @@ #include "tauEvent/TauJetContainer.h" #include "tauEvent/TauJet.h" -#include "xAODEventInfo/EventInfo.h" - #include "xAODMuon/MuonContainer.h" #include "MuonCombinedToolInterfaces/IMuonPrintingTool.h" @@ -99,6 +97,8 @@ #include "TrigT1Interfaces/RecEmTauRoI.h" + + #include "AthViews/ViewHelper.h" #include "AthViews/View.h" @@ -559,12 +559,8 @@ StatusCode TrigEDMChecker::execute() { if (m_doDumpAll || m_doDumpTrigCompsiteNavigation) { std::string trigCompositeSteering; ATH_CHECK(TrigCompositeNavigationToDot(trigCompositeSteering)); - const xAOD::EventInfo* evtInfo = nullptr; - if (evtStore()->contains<xAOD::EventInfo>("EventInfo")) { - ATH_CHECK( evtStore()->retrieve(evtInfo) ); - } - static int eventStatic = 0; // Might not always have EventInfo (early testing of Run-3 software) - const std::string evtNumber = (evtInfo == nullptr ? std::to_string(eventStatic++) : std::to_string(evtInfo->eventNumber())); + const EventContext& context = Gaudi::Hive::currentContext(); + const std::string evtNumber = std::to_string(context.eventID().event_number()); std::ofstream ofile(std::string("NavigationGraph_" + evtNumber + ".dot").c_str()); ofile << trigCompositeSteering; } @@ -4015,17 +4011,24 @@ StatusCode TrigEDMChecker::dumpxAODVertex() { } StatusCode TrigEDMChecker::dumpTDT() { + using namespace TrigCompositeUtils; // LinkInfo ATH_MSG_INFO( "REGTEST ==========START of TDT DUMP===========" ); // Note: This minimal TDT dumper is for use during run-3 dev std::vector<std::string> confChains = m_trigDec->getListOfTriggers("HLT_.*"); for (const auto& item : confChains) { bool passed = m_trigDec->isPassed(item, TrigDefs::requireDecision); - ATH_MSG_INFO(" HLT Item " << item << " passed raw? " << passed); - // TODO Enable this section after !22102 is merged - // if (passed) { - // ElementLinkVector<IParticleContainer> features = m_trigDec->features<IParticleContainer>(item); - // ATH_MSG_INFO(" " << item << " features size: " << features.size()); - // } + ATH_MSG_INFO(" HLT Item " << item << " (numeric ID " << TrigConf::HLTUtils::string2hash(item, "Identifier") << ") passed raw? " << passed); + if (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) { + if (!li.isValid()) { + ATH_MSG_WARNING(" Unable to access feature - link invalid."); + } else { + ATH_MSG_INFO(" IParticle Feature pt:" << (*li.link)->pt() << " eta:" << (*li.link)->eta() << " phi:" << (*li.link)->phi()); + } + } + } } ATH_MSG_INFO( "REGTEST ==========END of TDT DUMP===========" ); return StatusCode::SUCCESS; @@ -4099,6 +4102,25 @@ StatusCode TrigEDMChecker::checkTrigCompositeElementLink(const xAOD::TrigComposi if (!elementLink.isValid()) ATH_MSG_WARNING(" Invalid element link to View, link name:'" << name << "'"); else ATH_MSG_DEBUG(" Dereferenced link '" << name << "' to View:'" << *elementLink); + } else if (name == "feature") { + + if (clid == ClassID_traits< xAOD::TrigEMClusterContainer >::ID()) { + + const ElementLink<xAOD::TrigEMClusterContainer> elementLink = tc->objectLink<xAOD::TrigEMClusterContainer>(name); + if (!elementLink.isValid()) ATH_MSG_WARNING(" Invalid element link to xAOD::TrigEMClusterContainer 'feature'"); + else ATH_MSG_DEBUG(" Dereferenced xAOD::TrigEMClusterContainer link 'feature', Energy:" << (*elementLink)->energy()); + + } else { + + try { + const ElementLink<xAOD::IParticleContainer> elementLink = tc->objectLink<xAOD::IParticleContainer>(name); + if (!elementLink.isValid()) ATH_MSG_WARNING(" Invalid element link to 'feature'"); + else ATH_MSG_DEBUG(" Dereferenced IParticle link 'feature', pt:" << (*elementLink)->pt() << " eta:" << (*elementLink)->eta() << " phi:" << (*elementLink)->phi()); + } catch(std::runtime_error& e) { + ATH_MSG_WARNING(" Cannot dereference 'feature' as IParticle: '" << e.what() << "'"); + } + + } } else { ATH_MSG_DEBUG(" Ignoring link to '" << name << "' with link CLID " << clid); @@ -4162,7 +4184,7 @@ StatusCode TrigEDMChecker::TrigCompositeNavigationToDot(std::string& returnValue const uint32_t selfIndex = selfEL.index(); ss << " \"" << selfKey << "_" << selfIndex << "\" [label=\"Container=" << typeNameTC; if (tc->name() != "") ss << "\\nName=" << tc->name(); - ss << "\\nKey=" << key << "\\nIndex=" << selfIndex; + ss << "\\nKey=" << key << "\\nIndex=" << selfIndex << " linksRemapped=" << (tc->isRemapped() ? "Y" : "N"); const std::vector<DecisionID> decisions = tc->decisions(); if (decisions.size() > 0) { ss << "\\nPass="; diff --git a/Trigger/TriggerCommon/TriggerJobOpts/python/TriggerConfig.py b/Trigger/TriggerCommon/TriggerJobOpts/python/TriggerConfig.py index 7b0b71ea61921e9c4b35fb2a10178a020ee2be5c..793eabb90c10c7073023f494d6e6bdf297300d50 100644 --- a/Trigger/TriggerCommon/TriggerJobOpts/python/TriggerConfig.py +++ b/Trigger/TriggerCommon/TriggerJobOpts/python/TriggerConfig.py @@ -72,6 +72,8 @@ def collectFilters( steps ): for stepSeq in steps.getChildren(): if "filter" in stepSeq.name(): filters[stepSeq.name()] = stepSeq.getChildren() + __log.info("Found Filters in Step {} : {}".format(stepSeq.name(), stepSeq.getChildren())) + return filters @@ -80,12 +82,12 @@ def collectDecisionObjects( hypos, filters, l1decoder ): Returns the set of all decision objects of HLT """ decisionObjects = set() - __log.info("Collecting decision obejcts from L1 decoder instance") + __log.info("Collecting decision objects from L1 decoder instance") decisionObjects.update([ d.Decisions for d in l1decoder.roiUnpackers ]) decisionObjects.update([ d.Decisions for d in l1decoder.rerunRoiUnpackers ]) - __log.info("Collecting decision obejcts from hypos") + __log.info("Collecting decision objects from hypos") __log.info(hypos) for step, stepHypos in hypos.iteritems(): for hypoAlg in stepHypos: @@ -97,7 +99,7 @@ def collectDecisionObjects( hypos, filters, l1decoder ): decisionObjects.add( hypoAlg.HypoInputDecisions ) decisionObjects.add( hypoAlg.HypoOutputDecisions ) - __log.info("Collecting decision obejcts from filters") + __log.info("Collecting decision objects from filters") for step, stepFilters in filters.iteritems(): for filt in stepFilters: decisionObjects.update( filt.Input ) @@ -108,7 +110,7 @@ def collectDecisionObjects( hypos, filters, l1decoder ): def triggerSummaryCfg(flags, hypos): """ - Configures an algorithm(s) that should be run after the slection process + Configures an algorithm(s) that should be run after the section process Returns: ca, algorithm """ acc = ComponentAccumulator() @@ -169,7 +171,7 @@ def triggerMonitoringCfg(flags, hypos, filters, l1Decoder): def triggerOutputStreamCfg( flags, decObj, outputType ): """ Configure output stream according to the menu setup (decision objects) - and TrigEDMCOnfig + and TrigEDMConfig """ from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg itemsToRecord = [] @@ -185,10 +187,10 @@ def triggerOutputStreamCfg( flags, decObj, outputType ): itemsToRecord.extend( [ el[0] for el in EDMCollectionsToRecord ] ) # summary objects - __log.debug( outputType + " trigger content "+str( itemsToRecord ) ) + __log.info( outputType + " trigger content "+str( itemsToRecord ) ) acc = OutputStreamCfg( flags, outputType, ItemList=itemsToRecord ) streamAlg = acc.getEventAlgo("OutputStream"+outputType) - streamAlg.ExtraInputs = [("xAOD::TrigCompositeContainer", "HLTSummary")] + streamAlg.ExtraInputs = [("xAOD::TrigCompositeContainer", "HLTSummary")] # OutputStream has a data dependency on HLTSummary return acc @@ -268,13 +270,37 @@ def triggerMergeViewsAndAddMissingEDMCfg( edmSet, hypos, viewMakers, decObj ): continue producer = producer[0] - tool.TrigCompositeContainer = producer.InputMakerOutputDecisions - tool.FixLinks = True + # NOTE: The below loop is going to find the HypoAlg which consume this output, and collate these HypoAlg's output + # It might be nicer to instead split up the GapFiller below to have a different GapFiller for Hypos and for Filters + # Then we could go back to having FixLinks be a boolean, rather than specifying a sub-set of the write handles + # attached to the TrigCompositeContainer parameter. + + # We have a InputMaker with configured outputs, we need to identify all HypoAlg which consume these inputs. + # These HypoAlg all need to have their output element link collections remapped via FixLinks + TCHypoOutputCollections = list() + for step, stepHypos in hypos.iteritems(): + for hypoAlg in stepHypos: + if isinstance( hypoAlg.HypoInputDecisions, list): # Support multiple inputs and outputs to this HypoAlg + counter = -1 + for inputDecision in hypoAlg.HypoInputDecisions: + ++counter + if inputDecision in producer.InputMakerOutputDecisions: + TCHypoOutputCollections.append(hypoAlg.HypoOutputDecisions[counter]) + else: # Normal case - consume one input, produce one output + if hypoAlg.HypoInputDecisions in producer.InputMakerOutputDecisions: + TCHypoOutputCollections.append(hypoAlg.HypoOutputDecisions) + tool.FixLinks = TCHypoOutputCollections + + # We need to register in storegate these Hypo outputs, but also the InputMaker outputs as well so we add them to the list here too + TCOutputCollections = TCHypoOutputCollections[:] # copy the list + TCOutputCollections.extend(producer.InputMakerOutputDecisions) + tool.TrigCompositeContainer = TCOutputCollections + tool.dumpSGBefore = False + tool.dumpSGAfter = False alg.OutputTools += [ tool ] - + tool = HLTEDMCreator( "GapFiller" ) if len(edmSet) != 0: - tool = HLTEDMCreator( "GapFiller" ) from collections import defaultdict groupedByType = defaultdict( list ) @@ -291,13 +317,14 @@ def triggerMergeViewsAndAddMissingEDMCfg( edmSet, hypos, viewMakers, decObj ): propName = collType.split(":")[-1] if hasattr( tool, propName ): setattr( tool, propName, collNameList ) + __log.info("GapFiller will create EDM collection type '{}' for '{}'".format( collType, collNameList )) else: - __log.info("The {} is not going to be added if missing".format( collType )) + __log.info("EDM collections of type {} are not going to be added to StoreGate, if not created by the HLT".format( collType )) + # append all decision objects + __log.debug("The GapFiller is ensuring the creation of all the decision object collections: '{}'".format( decObj ) ) + tool.TrigCompositeContainer += list(decObj) + alg.OutputTools += [tool] - # append all decision objects - tool.TrigCompositeContainer += list(decObj) - alg.OutputTools += [tool] - return alg @@ -365,10 +392,12 @@ def triggerRunCfg( flags, menu=None ): edmSet = [] if flags.Output.ESDFileName != "": + __log.debug( "Setting up trigger EDM output for ESD" ) acc.merge( triggerOutputStreamCfg( flags, decObj, "ESD" ) ) edmSet.append('ESD') if flags.Output.AODFileName != "": + __log.debug( "Setting up trigger EDM output for AOD" ) acc.merge( triggerOutputStreamCfg( flags, decObj, "AOD" ) ) edmSet.append('AOD') @@ -378,6 +407,7 @@ def triggerRunCfg( flags, menu=None ): # configure actual streams if flags.Trigger.writeBS: + __log.debug( "Setting up trigger output for ByteStream" ) acc.merge( triggerBSOutputCfg( flags, decObj ) ) return acc