2 Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
5 #include "AsgDataHandles/ReadHandle.h"
6 #include "AsgDataHandles/ReadHandleKey.h"
8 template<class CONTAINER>
9 std::vector< TrigCompositeUtils::LinkInfo<CONTAINER> > Trig::ChainGroup::features(const asg::EventStoreType* eventStore,
10 const SG::ReadHandleKey<TrigCompositeUtils::DecisionContainer>& HLTSummaryKeyIn,
11 unsigned int condition, const std::string& containerSGKey,
12 const unsigned int featureCollectionMode, const std::string& navElementLinkKey,
13 const int restrictToLegIndex) const {
15 const EventContext& ctx = Gaudi::Hive::currentContext();
17 bool errState = false;
18 if ( condition != TrigDefs::Physics && condition != TrigDefs::includeFailedDecisions ) {
19 ATH_MSG_ERROR("features may only be called with: "
20 "TrigDefs::Physics - features from the legs of the chain(s) which passed the trigger. "
21 "TrigDefs::includeFailedDecisions - all features from the chain(s) irrespective of pass/fail of each Step.");
25 if ( featureCollectionMode != TrigDefs::lastFeatureOfType && featureCollectionMode != TrigDefs::allFeaturesOfType ) {
26 ATH_MSG_ERROR("featureCollectionMode may only be called with: "
27 "TrigDefs::lastFeatureOfType - stop exploring each route through the navigation once a feature matching all requirements is found. "
28 "TrigDefs::allFeaturesOfType - always fully explore each route throught the navigation graph and collect all matching features.");
32 // TODO when we decide what happens to CacheGlobalMemory - this needs to be updated to use a ReadHandle
33 SG::ReadHandle<TrigCompositeUtils::DecisionContainer> navigationSummaryRH = SG::ReadHandle(HLTSummaryKeyIn, ctx);
34 if (!navigationSummaryRH.isValid()) {
35 ATH_MSG_ERROR("Unable to read Run 3 trigger navigation from " << HLTSummaryKeyIn.key() << ". Cannot retrieve features.");
39 // We always want to search from the passed raw terminus node to find features for passed chains.
40 const TrigCompositeUtils::Decision* terminusNode = nullptr;
42 terminusNode = TrigCompositeUtils::getTerminusNode(navigationSummaryRH);
43 if (terminusNode == nullptr) {
44 ATH_MSG_ERROR("Unable to locate HLTPassRaw element of " << HLTSummaryKeyIn.key()
45 << ", collection contains " << navigationSummaryRH->size() << " nodes." );
51 ATH_MSG_ERROR("Encountered one or more errors in Trig::ChainGroup::features. Returning empty vector.");
52 return std::vector< TrigCompositeUtils::LinkInfo<CONTAINER> >();
55 // The sub-graph from which we will extract features
56 TrigCompositeUtils::NavGraph navGraph;
58 // Collect the set of chains (and chain legs) which we are fetching
59 // Perform the fetches using the full set of IDs for each chain (include all legs)
60 TrigCompositeUtils::DecisionIDContainer allRequestedChainIDs;
61 for (const TrigConf::HLTChain* ch : m_confChains) {
63 TrigCompositeUtils::DecisionIDContainer thisChainIDs;
64 HLT::Identifier chainID("");
66 const HLT::Chain* fchain = cgm_assert().chain(*ch);
68 chainID = HLT::Identifier( fchain->getChainName() );
69 const std::vector<size_t> legMultiplicites = fchain->getLegMultiplicities();
70 allRequestedChainIDs.insert( chainID.numeric() );
71 thisChainIDs.insert( chainID.numeric() );
72 if (legMultiplicites.size() == 0) {
73 ATH_MSG_ERROR("chain " << chainID << " has invalid configuration, no multiplicity data.");
74 } else if (legMultiplicites.size() > 1) {
75 if (restrictToLegIndex >= (int)legMultiplicites.size()) {
76 ATH_MSG_WARNING("Requested features from leg index " << restrictToLegIndex << " for chain " << chainID <<
77 " but this chain only has " << legMultiplicites.size() << " legs");
79 // For multi-leg chains, the DecisionIDs are handled per leg.
80 // We don't care here exactly how many objects are required per leg, just that there are two-or-more legs
81 for (size_t legNumeral = 0; legNumeral < legMultiplicites.size(); ++legNumeral) {
82 // If restrictToLegIndex is -1 then we are NOT filtering on legs, we return features over all legs.
83 if (restrictToLegIndex != -1 and restrictToLegIndex != (int)legNumeral) {
86 HLT::Identifier legID = TrigCompositeUtils::createLegName(chainID, legNumeral);
87 allRequestedChainIDs.insert( legID.numeric() );
88 thisChainIDs.insert( legID.numeric() );
91 ATH_MSG_DEBUG("Adding navigation data for chain " << chainID << " with " << legMultiplicites.size() << " leg(s)." );
92 if (msg().level() <= MSG::VERBOSE) {
93 for (const TrigCompositeUtils::DecisionID printID : thisChainIDs) {
94 ATH_MSG_VERBOSE(" -- Collecting for chain or chain-leg: " << HLT::Identifier(printID));
98 ATH_MSG_ERROR("Cannot access configuration for one of the ChainGroup's chains");
102 // Obtain navigation routes for objects which pass
103 // Final parameter TRUE as the chain passed (has its ID in terminusNode)
104 TrigCompositeUtils::recursiveGetDecisions(terminusNode, navGraph, thisChainIDs, true);
106 ATH_MSG_DEBUG("Added all passed navigation data for chain " << chainID
107 << ", total nodes:" << navGraph.nodes() << " total edges:" << navGraph.edges() << " final nodes:" << navGraph.finalNodes().size());
109 // Obtain navigation routes for objects which fail
110 if (condition == TrigDefs::includeFailedDecisions) {
111 std::vector<const TrigCompositeUtils::Decision*> rejectedDecisionNodes =
112 TrigCompositeUtils::getRejectedDecisionNodes(eventStore, HLTSummaryKeyIn.key(), thisChainIDs);
114 ATH_MSG_DEBUG("Chain " << chainID << " has " << rejectedDecisionNodes.size()
115 << " dangling nodes in the graph from objects which were rejected.");
117 for (const TrigCompositeUtils::Decision* rejectedNode : rejectedDecisionNodes) {
118 // Final parameter FALSE as the chain failed here (its ID was removed from rejectedNode)
119 TrigCompositeUtils::recursiveGetDecisions(rejectedNode, navGraph, thisChainIDs, false);
122 ATH_MSG_DEBUG("Added all failed navigation data for chain " << chainID
123 << ", total nodes:" << navGraph.nodes() << " total edges:" << navGraph.edges() << " final nodes:" << navGraph.finalNodes().size());
128 ATH_MSG_DEBUG("Finished adding nodes to sub-graph. "
129 << "Total nodes:" << navGraph.nodes() << " total edges:" << navGraph.edges() << " final nodes:" << navGraph.finalNodes().size());
130 if (msg().level() <= MSG::DEBUG && navGraph.finalNodes().size()) {
131 for (const TrigCompositeUtils::NavGraphNode* n : navGraph.finalNodes()) {
132 ATH_MSG_DEBUG(" Final node:" << TrigCompositeUtils::decisionToElementLink(n->node()).dataID() << " #" << n->node()->index());
136 if (navGraph.edges() == 0) {
137 ATH_MSG_DEBUG("No navigation path data found for this chain group of " << names().size() << " chains. "
138 << "Total nodes:" << navGraph.nodes() << " total edges:" << navGraph.edges() << " final nodes:" << navGraph.finalNodes().size());
141 if (msg().level() <= MSG::VERBOSE) {
142 navGraph.printAllPaths(msg(), MSG::VERBOSE);
145 const bool lastFeatureOfTypeFlag = (featureCollectionMode == TrigDefs::lastFeatureOfType);
147 std::vector<TrigCompositeUtils::LinkInfo<CONTAINER>> returnVector =
148 TrigCompositeUtils::recursiveGetFeaturesOfType<CONTAINER>(navGraph, containerSGKey, lastFeatureOfTypeFlag, navElementLinkKey, allRequestedChainIDs);
151 for (const TrigCompositeUtils::LinkInfo<CONTAINER>& linkInfo : returnVector) {
152 if (not linkInfo.link.isValid()) {
157 ATH_MSG_WARNING(invalid << " of " << returnVector.size() << " returned features have invalid element links. Check the Trigger EDM. "
158 << "Request was for features of type " << ClassID_traits<CONTAINER>::typeName());