ATLAS Offline Software
ChainGroup.icc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #include "AsgDataHandles/ReadHandle.h"
6 #include "AsgDataHandles/ReadHandleKey.h"
7 
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 {
14 
15  const EventContext& ctx = Gaudi::Hive::currentContext();
16 
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.");
22  errState = true;
23  }
24 
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.");
29  errState = true;
30  }
31 
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.");
36  errState = true;
37  }
38 
39  // We always want to search from the passed raw terminus node to find features for passed chains.
40  const TrigCompositeUtils::Decision* terminusNode = nullptr;
41  if (!errState) {
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." );
46  errState = true;
47  }
48  }
49 
50  if (errState) {
51  ATH_MSG_ERROR("Encountered one or more errors in Trig::ChainGroup::features. Returning empty vector.");
52  return std::vector< TrigCompositeUtils::LinkInfo<CONTAINER> >();
53  }
54 
55  // The sub-graph from which we will extract features
56  TrigCompositeUtils::NavGraph navGraph;
57 
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) {
62 
63  TrigCompositeUtils::DecisionIDContainer thisChainIDs;
64  HLT::Identifier chainID("");
65 
66  const HLT::Chain* fchain = cgm_assert().chain(*ch);
67  if (fchain) {
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");
78  }
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) {
84  continue;
85  }
86  HLT::Identifier legID = TrigCompositeUtils::createLegName(chainID, legNumeral);
87  allRequestedChainIDs.insert( legID.numeric() );
88  thisChainIDs.insert( legID.numeric() );
89  }
90  }
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));
95  }
96  }
97  } else {
98  ATH_MSG_ERROR("Cannot access configuration for one of the ChainGroup's chains");
99  continue;
100  }
101 
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, ctx, thisChainIDs, true);
105 
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());
108 
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);
113 
114  ATH_MSG_DEBUG("Chain " << chainID << " has " << rejectedDecisionNodes.size()
115  << " dangling nodes in the graph from objects which were rejected.");
116 
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, ctx, thisChainIDs, false);
120  }
121 
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());
124  }
125 
126  }
127 
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());
133  }
134  }
135 
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());
139  }
140 
141  if (msg().level() <= MSG::VERBOSE) {
142  navGraph.printAllPaths(msg(), MSG::VERBOSE);
143  }
144 
145  const bool lastFeatureOfTypeFlag = (featureCollectionMode == TrigDefs::lastFeatureOfType);
146 
147  std::vector<TrigCompositeUtils::LinkInfo<CONTAINER>> returnVector =
148  TrigCompositeUtils::recursiveGetFeaturesOfType<CONTAINER>(navGraph, containerSGKey, lastFeatureOfTypeFlag, navElementLinkKey, allRequestedChainIDs);
149 
150  size_t invalid = 0;
151  for (const TrigCompositeUtils::LinkInfo<CONTAINER>& linkInfo : returnVector) {
152  if (not linkInfo.link.isValid()) {
153  ++invalid;
154  }
155  }
156  if (invalid) {
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());
159  }
160 
161  return returnVector;
162 }
163 
164