ATLAS Offline Software
TrigCompositeUtilsRoot.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 // See similar workaround the lack of CLID in standalone releases in TrigComposite_v1.h
7 
11 
13 
14 #include <format>
15 #include <unordered_set>
16 
17 static const SG::AuxElement::Accessor< std::vector<TrigCompositeUtils::DecisionID> > readWriteAccessor("decisions");
18 static const SG::AuxElement::ConstAccessor< std::vector<TrigCompositeUtils::DecisionID> > readOnlyAccessor("decisions");
19 
20 
21 
22 namespace TrigCompositeUtils {
23 
24  ANA_MSG_SOURCE (msgFindLink, "TrigCompositeUtils.findLink")
26 
27 
28  SG::WriteHandle<DecisionContainer> createAndStore( const SG::WriteHandleKey<DecisionContainer>& key, const EventContext& ctx ) {
30  auto data = std::make_unique<DecisionContainer>() ;
31  auto aux = std::make_unique<DecisionAuxContainer>() ;
32  data->setStore( aux.get() );
33  handle.record( std::move( data ), std::move( aux ) ).ignore();
34  return handle;
35  }
36 
38  auto data = std::make_unique<DecisionContainer>() ;
39  auto aux = std::make_unique<DecisionAuxContainer>() ;
40  data->setStore( aux.get() );
41  handle.record( std::move( data ), std::move( aux ) ).ignore();
42  }
43 
44  Decision* newDecisionIn ( DecisionContainer* dc, const std::string& name) {
45  Decision * x = new Decision;
46  dc->push_back( x );
47  if ( ! name.empty() ) {
48  x->setName( name );
49  }
50  return x;
51  }
52 
53  Decision* newDecisionIn ( DecisionContainer* dc, const Decision* dOld, const std::string& name, const EventContext& ctx ) {
54  Decision* dNew = newDecisionIn( dc, name );
55  linkToPrevious(dNew, dOld, ctx); // Sets up link to 'seed' collection, points to dOld
56  return dNew;
57  }
58 
60  std::vector<DecisionID>& decisions = readWriteAccessor( *d );
61  if ( decisions.size() == 0 or decisions.back() != id)
62  decisions.push_back( id );
63  }
64 
65  void decisionIDs( const Decision* d, DecisionIDContainer& destination ) {
66  const std::vector<DecisionID>& decisions = readOnlyAccessor( *d );
67  destination.insert( decisions.begin(), decisions.end() );
68  }
69 
70  const std::vector<DecisionID>& decisionIDs( const Decision* d ) {
71  return readOnlyAccessor( *d );
72  }
73 
74  std::vector<DecisionID>& decisionIDs( Decision* d ) {
75  return readWriteAccessor( *d );
76  }
77 
79  DecisionIDContainer srcIds;
80  decisionIDs( src, srcIds ); // Now stored in a set
81  insertDecisionIDs( srcIds, dest);
82  }
83 
85  DecisionIDContainer collateIDs;
86  // Decision are xAOD objects backed by a std::vector
87  // Here we use a std::set to de-duplicate IDs from src and dest before setting dest
88  decisionIDs( dest, collateIDs ); // Set operation 1. Get from dest
89  collateIDs.insert( src.begin(), src.end() ); // Set operation 2. Get from src
90  std::vector<DecisionID>& vdest = decisionIDs( dest );
91  // Clear and reserve target
92  vdest.clear();
93  vdest.reserve(collateIDs.size());
94  // Copy from set to (ordered) vector
95  vdest.insert( vdest.end(), collateIDs.begin(), collateIDs.end() );
96  }
97 
99  // Re-use above insertDecisionIDs method.
100  // This implicitly performs de-duplication
101  return insertDecisionIDs(dest, dest);
102  }
103 
104  bool allFailed( const Decision* d ) {
105  const std::vector<DecisionID>& decisions = readOnlyAccessor( *d );
106  return decisions.empty();
107  }
108 
110  for ( DecisionID id : readOnlyAccessor( *d ) ) {
111  if ( required.find( id ) != required.end() ) {
112  return true;
113  }
114  }
115  return false;
116  }
117 
118  bool passed( DecisionID id, const DecisionIDContainer& idSet ) {
119  return idSet.find( id ) != idSet.end();
120  }
121 
122 #if !defined(XAOD_STANDALONE) && !defined(XAOD_ANALYSIS) // Full athena
124  const DecisionContainer* container = dynamic_cast<const DecisionContainer*>( d->container() );
125  if( ! container ) {
126  throw std::runtime_error("TrigCompositeUtils::convertToElementLink Using convertToElementLink(d) requires that the Decision d is already in a container");
127  }
128  return ElementLink<DecisionContainer>(*container, d->index(), ctx);
129  }
130 #else // Analysis or Standalone
131  ElementLink<DecisionContainer> decisionToElementLink(const Decision* d, const EventContext&) {
132  const DecisionContainer* container = dynamic_cast<const DecisionContainer*>( d->container() );
133  if( ! container ) {
134  throw std::runtime_error("TrigCompositeUtils::convertToElementLink Using convertToElementLink(d) requires that the Decision d is already in a container");
135  }
136  return ElementLink<DecisionContainer>(*container, d->index());
137  }
138 #endif
139 
140  void linkToPrevious( Decision* d, const std::string& previousCollectionKey, size_t previousIndex ) {
141  ElementLink<DecisionContainer> seed = ElementLink<DecisionContainer>( previousCollectionKey, previousIndex );
142  if (!seed.isValid()) {
143  throw std::runtime_error("TrigCompositeUtils::linkToPrevious Invalid Decision Link key or index provided");
144  } else {
145  d->addObjectCollectionLink(seedString(), seed);
146  }
147  }
148 
149  void linkToPrevious( Decision* d, const Decision* dOld, const EventContext& ctx ) {
150  d->addObjectCollectionLink(seedString(), decisionToElementLink(dOld, ctx));
151  }
152 
153  bool hasLinkToPrevious( const Decision* d ) {
154  return d->hasObjectCollectionLinks( seedString() );
155  }
156 
157  const std::vector<ElementLink<DecisionContainer>> getLinkToPrevious( const Decision* d ) {
158  return d->objectCollectionLinks<DecisionContainer>( seedString() );
159  }
160 
161 
162  bool copyLinks(const Decision* src, Decision* dest) {
163  return dest->copyAllLinksFrom(src);
164  }
165 
166  HLT::Identifier createLegName(const HLT::Identifier& chainIdentifier, size_t counter) {
167  return createLegName( chainIdentifier.name(), counter );
168  }
169 
170  HLT::Identifier createLegName(const std::string& name, size_t counter) {
171  if (!isChainId(name)) {
172  throw std::runtime_error("TrigCompositeUtils::createLegName chainIdentifier '"+name+"' does not start with 'HLT_'");
173  }
174  if (counter > 999) {
175  throw std::runtime_error("TrigCompositeUtils::createLegName Leg counters above 999 are invalid.");
176  }
177  return HLT::Identifier( std::format("leg{:0>3d}_{}", counter, name) );
178  }
179 
181  const std::string& name = legIdentifier.name();
182  if (isChainId(name)){
183  return legIdentifier;
184  } else if (isLegId(name)){
185  return HLT::Identifier(name.substr(7));
186  } else{
187  throw std::runtime_error("TrigCompositeUtils::getIDFromLeg legIdentifier '"+name+"' does not start with 'HLT_' or 'leg' ");
188  }
189  }
190 
191  int32_t getIndexFromLeg(const HLT::Identifier& legIdentifier) {
192  return getIndexFromLeg(legIdentifier.name());
193  }
194 
195  int32_t getIndexFromLeg(const std::string& name) {
196  int32_t id = 0;
197  if (isChainId(name)){
198  // pass
199  } else if (isLegId(name)) {
200  std::from_chars(name.data()+3, name.data()+6, id);
201  } else {
202  throw std::runtime_error("TrigCompositeUtils::getIndexFromLeg legIdentifier '"+name+"' does not start with 'HLT_' or 'leg' ");
203  }
204  return id;
205  }
206 
207  std::pair<std::string, int32_t> getNameAndIndexFromLeg(const std::string& name) {
208  int32_t id = 0;
209  if (isChainId(name)) {
210  return {name, id};
211  } else if (isLegId(name)) {
212  std::from_chars(name.data()+3, name.data()+6, id);
213  return {name.substr(7), id};
214  } else {
215  throw std::runtime_error("TrigCompositeUtils::getIDFromLeg legIdentifier '"+name+"' does not start with 'HLT_' or 'leg' ");
216  }
217  }
218 
219  bool isLegId(const HLT::Identifier& legIdentifier) {
220  return isLegId(legIdentifier.name());
221  }
222 
223  bool isLegId(const std::string& name) {
224  return name.starts_with("leg");
225  }
226 
227  bool isChainId(const HLT::Identifier& chainIdentifier) {
228  return isChainId(chainIdentifier.name());
229  }
230 
231  bool isChainId(const std::string& name) {
232  return name.starts_with("HLT_");
233  }
234 
235 
236  const Decision* find( const Decision* start, const std::function<bool( const Decision* )>& filter ) {
237  if ( filter( start ) ) return start;
238 
239  if ( hasLinkToPrevious(start) ) {
240  const std::vector<ElementLink<DecisionContainer>> seeds = getLinkToPrevious(start);
241  for (const ElementLink<DecisionContainer>& seedEL : seeds) {
242  const Decision* result = find( *seedEL, filter );
243  if (result) return result;
244  }
245  }
246 
247  return nullptr;
248  }
249 
250  bool HasObject::operator()( const Decision* composite ) const {
251  return composite->hasObjectLink( m_name );
252  }
253 
254  bool HasObjectCollection::operator()( const Decision* composite ) const {
255  return composite->hasObjectCollectionLinks( m_name );
256  }
257 
259  return getTerminusNode(*container);
260  }
261 
262  const Decision* getTerminusNode(const DecisionContainer& container) {
263  return getNodeByName(container, summaryPassNodeName());
264  }
265 
267  return getNodeByName(container, summaryPassExpressNodeName());
268  }
269 
270  const Decision* getNodeByName(const DecisionContainer& container, const std::string& nodeName) {
271  const auto it = std::find_if(container.begin(), container.end(), [&nodeName](const Decision* d){return d->name()==nodeName;});
272  if (it==container.end()) {return nullptr;}
273  return *it;
274  }
275 
276  std::vector<const Decision*> getRejectedDecisionNodes([[maybe_unused]] const asg::EventStoreType* eventStore,
277  const EventContext& ctx,
278  const std::string& summaryCollectionKey,
279  const DecisionIDContainer& ids,
280  const std::set<std::string>& keysToIgnore) {
281 
282  // The following list contains all known summary store identifiers where the graph nodes are spread out over O(100s) or O(1000s)
283  // of different SG collections. This is the raw output from running the trigger online.
284  // When dealing with this, we need to query eventStore->keys in every event to obtain the full set of collections to process.
285  static const std::unordered_set<std::string> knownDistributedSummaryStores{
286  "HLTNav_Summary",
287  "_HLTNav_Summary"
288  };
289 
290  // The following list contains all known summary store identifiers where all nodes from the graph have been compactified / condensed
291  // down into a single container. Here we just have to search this one container.
292  static const std::unordered_set<std::string> knownCompactSummaryStores{"HLTNav_Summary_OnlineSlimmed",
293  "HLTNav_Summary_ESDSlimmed",
294  "HLTNav_Summary_AODSlimmed",
295  "HLTNav_Summary_DAODSlimmed",
296  "HLTNav_R2ToR3Summary"
297  };
298 
299  std::vector<std::string> keys; // The SG keys we will be exploring to find rejected decision nodes
300 
301  if (knownDistributedSummaryStores.contains(summaryCollectionKey) or summaryCollectionKey.empty()) {
302 
303  // If we have a distributed store then we need to query SG to find all keys.
304  // This should be a rare case now that we run compactification "online" (i.e. immediately after the trigger has executed)
305 #ifndef XAOD_STANDALONE
306  // The list of containers we need to read can change on a file-by-file basis (it depends on the SMK)
307  // Hence we query SG for all collections rather than maintain a large and ever changing ReadHandleKeyArray
308  eventStore->keys<DecisionContainer>(keys);
309 #else
310  throw std::runtime_error("Cannot obtain rejected HLT features in AnalysisBase when reading from uncompactified navigation containers, run trigger navigation slimming first if you really need this.");
311 #endif
312 
313  } else if (knownCompactSummaryStores.contains(summaryCollectionKey)) {
314 
315  keys.push_back(summaryCollectionKey);
316 
317  } else {
318 
319  using namespace msgRejected;
320  ANA_MSG_WARNING("getRejectedDecisionNodes has not been told about final collection " << summaryCollectionKey << " please update this function. Assuming that it is already compact.");
321  // Safest to assume that this is a compact summary store
322  keys.push_back(summaryCollectionKey);
323 
324  }
325 
326  std::vector<const Decision*> output; // The return vector of identified nodes where one of the chains in 'ids' was rejected
327 
328  // ReadHandleKey to be re-used in the loop to avoid repeated CLID lookups
329  SG::ReadHandleKey<DecisionContainer> containerRHKey("temp");
330  if (!containerRHKey.initialize().isSuccess()) {
331  throw std::runtime_error("Cannot initialize ReadHandleKey for DecisionContainer");
332  }
333 
334  // Loop over each DecisionContainer,
335  for (const std::string& key : keys) {
336  // Get and check this container
337  if ( ! (key.starts_with( "HLTNav_") || key.starts_with("_HLTNav_")) ) {
338  continue; // Only concerned about the decision containers which make up the navigation, they have name prefix of HLTNav (or _HLTNav for transient-only mode)
339  }
340  if (keysToIgnore.contains(key)) {
341  continue; // Have been asked to not explore this SG container
342  }
343 
344  // Create ReadHandle for this key
345  containerRHKey = key;
346  auto containerRH = SG::makeHandle(containerRHKey, ctx);
347  if (!containerRH.isValid()) {
348  throw std::runtime_error("Unable to retrieve " + key + " from event store.");
349  }
350 
351  for (const Decision* d : *containerRH) {
352  if ( not (d->name() == hypoAlgNodeName() or d->name() == comboHypoAlgNodeName()) ) {
353  continue; // Only want Decision objects created by HypoAlgs or ComboHypoAlgs
354  }
355  const std::vector<ElementLink<DecisionContainer>> mySeeds = d->objectCollectionLinks<DecisionContainer>(seedString());
356  if (mySeeds.empty()) {
357  continue;
358  }
359  const bool allSeedsValid = std::all_of(mySeeds.begin(), mySeeds.end(), [](const ElementLink<DecisionContainer>& s) { return s.isValid(); });
360  if (!allSeedsValid) {
361  using namespace msgRejected;
362  ANA_MSG_WARNING("A Decision object in " << key << " has invalid seeds. "
363  << "The trigger navigation information is incomplete. Skipping this Decision object.");
364  continue;
365  }
366 
367  DecisionIDContainer activeChainsIntoThisDecision;
368  decisionIDs(*mySeeds[0], activeChainsIntoThisDecision); // Get list of active chains from the first parent
369  if (mySeeds.size() > 1) {
370  for (size_t i = 1; i < mySeeds.size(); ++i) {
371  // If there are more than one parent, we only want to keep the intersection of all of the seeds
372  DecisionIDContainer moreActiveChains;
373  decisionIDs(*mySeeds[i], moreActiveChains);
375  std::set_intersection(activeChainsIntoThisDecision.begin(), activeChainsIntoThisDecision.end(),
376  moreActiveChains.begin(), moreActiveChains.end(),
377  std::inserter(intersection, intersection.begin()));
378  activeChainsIntoThisDecision = std::move(intersection); // Update the output to only be the intersection and continue to any other seeds
379  }
380  }
381  // We now know what chains were active coming into this Decision (d) from ALL seeds
382  // This is the logic required for each HypoTool to have activated and checked if its chain passes
383  // So the size of activeChainsIntoThisDecision corresponds to the number of HypoTools which will have run
384  // What do we care about? A chain, or all chains?
385  DecisionIDContainer chainsToCheck;
386  if (ids.empty()) { // We care about *all* chains
387  chainsToCheck = activeChainsIntoThisDecision;
388  } else { // We care about specified chains
389  chainsToCheck = ids;
390  }
391  // We have found a rejected decision node *iff* a chainID to check is *not* present here
392  // I.e. the HypoTool for the chain returned a NEGATIVE decision
393  DecisionIDContainer activeChainsPassedByThisDecision;
394  decisionIDs(d, activeChainsPassedByThisDecision);
395  for (const DecisionID checkID : chainsToCheck) {
396  if (not activeChainsPassedByThisDecision.contains(checkID) && // I was REJECTED here ...
397  activeChainsIntoThisDecision.contains(checkID)) { // ... but PASSSED by all my inputs
398  output.push_back(d);
399  break;
400  }
401  }
402  }
403  }
404  return output;
405  }
406 
408  const Decision* comingFrom,
409  NavGraph& navGraph,
410  std::set<const Decision*>& fullyExploredFrom,
411  const DecisionIDContainer& ids,
412  const bool enforceDecisionOnNode) {
413 
414  // Does this Decision satisfy the chain requirement?
415  if (enforceDecisionOnNode && ids.size() != 0 && !isAnyIDPassing(node, ids)) {
416  return; // Stop propagating down this leg. It does not concern the chain with DecisionID = id
417  }
418 
419  // This Decision object is part of this path through the Navigation
420  navGraph.addNode(node, comingFrom);
421 
422 #if TRIGCOMPUTILS_ENABLE_EARLY_EXIT == 1
423  // Note we have to do this check here (after calling addNode) rather than just before calling recursiveGetDecisionsInternal
424  if (fullyExploredFrom.count(node) == 1) {
425  // We have fully explored this branch
426  return;
427  }
428 #endif
429 
430  // Continue to the path(s) by looking at this Decision object's seed(s)
431  if ( hasLinkToPrevious(node) ) {
432  // Do the recursion
434  const Decision* seedDecision = *(seed); // Dereference ElementLink
435  // Sending true as final parameter for enforceDecisionOnStartNode as we are recursing away from the supplied start node
436  recursiveGetDecisionsInternal(seedDecision, node, navGraph, fullyExploredFrom, ids, /*enforceDecisionOnNode*/ true);
437  }
438  }
439 
440  // Have fully explored down from this point
441  fullyExploredFrom.insert(node);
442 
443  return;
444  }
445 
447  NavGraph& navGraph,
448  const DecisionIDContainer& ids,
449  const bool enforceDecisionOnStartNode) {
450 
451  std::set<const Decision*> fullyExploredFrom;
452  // Note: we do not require navGraph to be an empty graph. We can extend it.
453  recursiveGetDecisionsInternal(start, /*comingFrom*/nullptr, navGraph, fullyExploredFrom, ids, enforceDecisionOnStartNode);
454 
455  return;
456  }
457 
458 
460  const bool keepOnlyFinalFeatures,
461  const bool removeEmptySteps,
462  const std::vector<std::string>& nodesToDrop)
463  {
464  std::set<NavGraphNode*> fullyExploredFrom;
465  for (NavGraphNode* finalNode : graph.finalNodes()) {
466  recursiveFlagForThinningInternal(finalNode, /*modeKeep*/true, fullyExploredFrom, keepOnlyFinalFeatures, removeEmptySteps, nodesToDrop);
467  }
468  }
469 
470 
472  bool modeKeep,
473  std::set<NavGraphNode*>& fullyExploredFrom,
474  const bool keepOnlyFinalFeatures,
475  const bool removeEmptySteps,
476  const std::vector<std::string>& nodesToDrop)
477  {
478 
479  // If modeKeep == true, then by default we are KEEPING the nodes as we walk up the navigation (towards L1),
480  // otherwise by default we are THINNING the nodes
481  bool keep = modeKeep;
482 
483  // The calls to node->node() here are going from the transient NavGraphNode
484  // to the underlying const Decision* from the input collection. Cache these in local stack vars for better readability.
485 
486  const Decision* const me = node->node();
487  const Decision* const myFirstParent = (node->seeds().size() ? node->seeds().at(0)->node() : nullptr);
488  const Decision* const myFirstChild = (node->children().size() ? node->children().at(0)->node() : nullptr);
489 
490  // KEEP Section: The following code blocks may override the modeKeep default by setting keep=True for this node.
491 
492  if (keepOnlyFinalFeatures) {
493  // Check if we have reached the first feature
494  if ( modeKeep == true && (me->hasObjectLink(featureString()) || me->hasObjectLink("subfeature")) ) {
495  // Just to be explicit, we keep this node
496  keep = true;
497 
498  // Special BLS case: The bphysics object is attached exceptionally at the ComboHypo.
499  // We want to keep going up one more level in this case to get the Feature node too (we save the 4-vec of the BPhys and both of the muons/electrons)
500  const bool specialBphysCase = (me->name() == comboHypoAlgNodeName());
501 
502  // Special R2->R3 case: We can get steps with dummy features, these feature links point back to the same node.
503  // First check again the feature, with an addition requirement on the feature CLID. Then check if the feature points back to the node.
504  const bool specialR2toR3Case = (me->hasObjectLink(featureString(), ClassID_traits<DecisionContainer>::ID()) && me->object<Decision>(featureString()) == me);
505 
506  // We change the default behaviour to be modeKeep = false (unless we want to explore up one more level for BLS's special case
507  // or to the next feature for the R2->R3 special case) such that by default we start to NOT flag all the parent nodes to be kept
508  if (!specialBphysCase && !specialR2toR3Case) {
509  modeKeep = false;
510  }
511  }
512  }
513 
514  // We always by default keep the initial node from the HLTSeeding, but this may be overridden below by nodesToDrop
515  if (me->name() == hltSeedingNodeName()) {
516  keep = true;
517  }
518 
519  // DROP Section: The following code blocks may override both the current modeKeep default and the above KEEP section by setting keep=False for this node.
520 
521  // Check also against NodesToDrop
522  for (const std::string& toDrop : nodesToDrop) {
523  if (me->name() == toDrop) {
524  keep = false;
525  break;
526  }
527  }
528 
529  // Check against RemoveEmptySteps
530  // The signature we look for here is a InputMaker node connected directly to a ComboHypo node
531  // The key thing to identify is NO intermediate Hypo node
532  // This structure is created in Steps where some chain legs are running reconstruction, but other legs are idle - either due to
533  // menu alignment, or due to the legs being of different length.
534  // For passed chains, there is little point keeping these CH and IM nodes on the idle legs. So we have the option of slimming them here.
535  // First for the ComboHypo ...
536  if (removeEmptySteps && me->name() == comboHypoAlgNodeName() && myFirstParent && myFirstParent->name() == inputMakerNodeName()) {
537  keep = false;
538  }
539  // ... and also for the InputMaker, with flipped logic.
540  if (removeEmptySteps && me->name() == inputMakerNodeName() && myFirstChild && myFirstChild->name() == comboHypoAlgNodeName()) {
541  keep = false;
542  }
543 
544  // Check against RemoveEmptySteps
545  // Check for the R2->R3 empty step case
546  if (removeEmptySteps
547  && me->name() == hypoAlgNodeName()
549  && me->object<Decision>(featureString()) == me)
550  {
551  keep = false;
552  }
553  // ... and also for the InputMaker
554  if (removeEmptySteps
555  && me->name() == inputMakerNodeName()
556  && myFirstChild
557  && myFirstChild->name() == hypoAlgNodeName()
559  && myFirstChild->object<Decision>(featureString()) == myFirstChild)
560  {
561  keep = false;
562  }
563 
564  // APPLICATION Section:
565 
566  if (keep) {
567  node->keep(); // Inform the node that it should NOT be thinned away.
568  }
569 
570  for (NavGraphNode* seed : node->seeds()) {
571 #if TRIGCOMPUTILS_ENABLE_EARLY_EXIT == 1
572  // NOTE: This code block cuts short the recursive graph exploration for any node which has already been fully-explored-from.
573  //
574  // If we are keeping final features, then processing each node exactly once is actually insufficient.
575  // This is because we may reach a node, X, with a feature which is penultimate/generally-non-final for some chain, A,
576  // but then later on we may follow Terminus->SummaryFilter->Hypothesis(X) for some chain, B, where this same
577  // feature from X _is_ the final-feature for chain B. Here we would not process node X again as we have already dealt with it.
578  // But we need to process it again as for chain B, modeKeep==true still and chain B wants to flag the node as keep().
579  //
580  // We only however need to force the exploration while we are in the mode where we are nominally keeping nodes (modeKeep == true).
581  // Once we have switched to dropping nodes by default, we should be OK to once again skip over nodes which we already processed.
582  // The only thing we should be keeping when modeKeep == false is the L1 node, any this is not dependent on path.
583  //
584  // See: ATR-28061
585  bool allowEarlyExit = true;
586  if (keepOnlyFinalFeatures) {
587  allowEarlyExit = (modeKeep == false);
588  }
589  if (allowEarlyExit && fullyExploredFrom.count(seed) == 1) {
590  // We have fully explored this branch
591  continue;
592  }
593 #endif
594  // Recursively call all the way up the graph to the initial nodes from the HLTSeeding
595  recursiveFlagForThinningInternal(seed, modeKeep, fullyExploredFrom, keepOnlyFinalFeatures, removeEmptySteps, nodesToDrop);
596  }
597 
598  // Have fully explored down from this point
599  fullyExploredFrom.insert(node);
600  }
601 
602  // Note: This version of the function recurses through a full navigation graph (initial input: Decision Object)
604  const std::string& linkName,
605  std::vector<sgkey_t>& keyVec,
606  std::vector<uint32_t>& clidVec,
607  std::vector<Decision::index_type>& indexVec,
608  std::vector<const Decision*>& sourceVec,
609  const unsigned int behaviour,
610  std::set<const Decision*>* fullyExploredFrom)
611  {
612  using namespace msgFindLink;
613 
614  // As the append vectors are user-supplied, perform some input validation.
615  if (keyVec.size() != clidVec.size() or clidVec.size() != indexVec.size()) {
616  ANA_MSG_WARNING("In typelessFindLinks, keyVec, clidVec, indexVec must all be the same size. Instead have:"
617  << keyVec.size() << ", " << clidVec.size() << ", " << indexVec.size());
618  return false;
619  }
620 
621  // Locate named links. Both collections of links and individual links are supported.
622  bool found = typelessFindLinksCommonLinkCollection(start, linkName, keyVec, clidVec, indexVec, sourceVec);
623 
624  // Early exit
625  if (found && (behaviour & TrigDefs::lastFeatureOfType)) {
626  return true;
627  }
628  // If not Early Exit, then recurse
630 #if TRIGCOMPUTILS_ENABLE_EARLY_EXIT == 1
631  if (fullyExploredFrom != nullptr) {
632  // We only need to recursively explore back from each node in the graph once.
633  // We can keep a record of nodes which we have already explored, these we can safely skip over.
634  if (fullyExploredFrom->count(*seed) == 1) {
635  continue;
636  }
637  }
638 #endif
639  found |= typelessFindLinks(*seed, linkName, keyVec, clidVec, indexVec, sourceVec, behaviour, fullyExploredFrom);
640  }
641  // Fully explored this node
642  if (fullyExploredFrom != nullptr) {
643  fullyExploredFrom->insert(start);
644  }
645  return found;
646  }
647 
648  // Note: This version of the function recurses through a sub-graph of the full navigation graph (initial input: NavGraphNode)
650  const std::string& linkName,
651  std::vector<sgkey_t>& keyVec,
652  std::vector<uint32_t>& clidVec,
653  std::vector<Decision::index_type>& indexVec,
654  std::vector<const Decision*>& sourceVec,
655  const unsigned int behaviour,
656  std::set<const Decision*>* fullyExploredFrom)
657  {
658  using namespace msgFindLink;
659 
660  // As the append vectors are user-supplied, perform some input validation.
661  if (keyVec.size() != clidVec.size() or clidVec.size() != indexVec.size()) {
662  ANA_MSG_WARNING("In typelessFindLinks, keyVec, clidVec, indexVec must all be the same size. Instead have:"
663  << keyVec.size() << ", " << clidVec.size() << ", " << indexVec.size());
664  return false;
665  }
666 
667  const Decision* start_decisionObject = start->node();
668  // Locate named links. Both collections of links and individual links are supported.
669  bool found = typelessFindLinksCommonLinkCollection(start_decisionObject, linkName, keyVec, clidVec, indexVec, sourceVec);
670 
671  // Early exit
672  if (found && (behaviour & TrigDefs::lastFeatureOfType)) {
673  return true;
674  }
675  // If not Early Exit, then recurse
676  for (const NavGraphNode* seed : start->seeds()) {
677 #if TRIGCOMPUTILS_ENABLE_EARLY_EXIT == 1
678  if (fullyExploredFrom != nullptr) {
679  // We only need to recursively explore back from each node in the graph once.
680  // We can keep a record of nodes which we have already explored, these we can safely skip over.
681  const Decision* seed_decisionObject = seed->node();
682  if (fullyExploredFrom->count(seed_decisionObject) == 1) {
683  continue;
684  }
685  }
686 #endif
687  found |= typelessFindLinks(seed, linkName, keyVec, clidVec, indexVec, sourceVec, behaviour, fullyExploredFrom);
688  }
689  // Fully explored this node
690  if (fullyExploredFrom != nullptr) {
691  fullyExploredFrom->insert(start_decisionObject);
692  }
693  return found;
694  }
695 
696 
698  const std::string& linkName,
699  std::vector<sgkey_t>& keyVec,
700  std::vector<uint32_t>& clidVec,
701  std::vector<Decision::index_type>& indexVec,
702  std::vector<const Decision*>& sourceVec)
703  {
704  bool found = false;
705  std::vector<sgkey_t> tmpKeyVec;
706  std::vector<uint32_t> tmpClidVec;
707  std::vector<Decision::index_type> tmpIndexVec;
708  if (start->hasObjectCollectionLinks(linkName)) {
709  found = start->typelessGetObjectCollectionLinks(linkName, tmpKeyVec, tmpClidVec, tmpIndexVec);
710  }
711  if (start->hasObjectLink(linkName)) {
712  sgkey_t tmpKey{0};
713  uint32_t tmpClid{0};
714  Decision::index_type tmpIndex{0};
715  found |= start->typelessGetObjectLink(linkName, tmpKey, tmpClid, tmpIndex);
716  tmpKeyVec.push_back(tmpKey);
717  tmpClidVec.push_back(tmpClid);
718  tmpIndexVec.push_back(tmpIndex);
719  }
720  // De-duplicate
721  for (size_t tmpi = 0; tmpi < tmpKeyVec.size(); ++tmpi) {
722  bool alreadyAdded = false;
723  const uint32_t tmpKey = tmpKeyVec.at(tmpi);
724  const uint32_t tmpClid = tmpClidVec.at(tmpi);
725  const Decision::index_type tmpIndex = tmpIndexVec.at(tmpi);
726  for (size_t veci = 0; veci < keyVec.size(); ++veci) {
727  if (SG::sgkeyEqual (keyVec.at(veci), tmpKey)
728  and clidVec.at(veci) == tmpClid
729  and indexVec.at(veci) == tmpIndex)
730  {
731  alreadyAdded = true;
732  break;
733  }
734  }
735  if (!alreadyAdded) {
736  keyVec.push_back( tmpKey );
737  clidVec.push_back( tmpClid );
738  indexVec.push_back( tmpIndex );
739  sourceVec.push_back( start );
740  }
741  }
742  return found;
743  }
744 
745 
746 
748  const std::string& linkName,
749  sgkey_t& key,
750  uint32_t& clid,
752  const Decision*& source,
753  const bool suppressMultipleLinksWarning)
754  {
755  using namespace msgFindLink;
756  // We use findLink in cases where there is only one link to be found, or if there are multiple then we
757  // only want the most recent.
758  // Hence we can supply TrigDefs::lastFeatureOfType. /--> parent3(link)
759  // We can still have more then one link found if there is a branch in the navigation. E.g. start --> parent1 --> parent2(link)
760  // If both parent2 and parent3 possessed an admissible ElementLink, then the warning below will trigger, and only one of the
761  // links will be returned (whichever of parent2 or parent3 happened to be the first seed of parent1).
762  std::vector<sgkey_t> keyVec;
763  std::vector<uint32_t> clidVec;
764  std::vector<Decision::index_type> indexVec;
765  std::vector<const Decision*> sourceVec;
766  std::set<const xAOD::TrigComposite*> fullyExploredFrom;
767 
768  const bool result = typelessFindLinks(start, linkName, keyVec, clidVec, indexVec, sourceVec, TrigDefs::lastFeatureOfType, &fullyExploredFrom);
769  if (!result) {
770  return false; // Nothing found
771  }
772 
773  if (keyVec.size() > 1 && !suppressMultipleLinksWarning) {
774  ANA_MSG_WARNING (keyVec.size() << " typeless links found for " << linkName
775  << " returning the first link, consider using findLinks.");
776  }
777  key = keyVec.at(0);
778  clid = clidVec.at(0);
779  index = indexVec.at(0);
780  source = sourceVec.at(0);
781  return true;
782  }
783 
784 
785  bool typelessFindLink(const NavGraph& subGraph,
786  const std::string& linkName,
787  sgkey_t& key,
788  uint32_t& clid,
790  const Decision*& source,
791  const bool suppressMultipleLinksWarning)
792  {
793  using namespace msgFindLink;
794  // Note: This function should be the same as its predecessor, just using a NavGraph to start rather than a Decision*
795  // As a result, it can search from more than one Decision* (the NavGraph may have more than one final node)
796  // but it will still warn if this results in more than one link being located.
797  std::vector<sgkey_t> keyVec;
798  std::vector<uint32_t> clidVec;
799  std::vector<Decision::index_type> indexVec;
800  std::vector<const Decision*> sourceVec;
801  std::set<const Decision*> fullyExploredFrom;
802 
803  bool result = false;
804  for (const NavGraphNode* finalNode : subGraph.finalNodes()) {
805  result |= typelessFindLinks(finalNode, linkName, keyVec, clidVec, indexVec, sourceVec, TrigDefs::lastFeatureOfType, &fullyExploredFrom);
806  }
807 
808  if (!result) {
809  return false; // Nothing found
810  }
811 
812  if (keyVec.size() > 1 && !suppressMultipleLinksWarning) {
813  ANA_MSG_WARNING (keyVec.size() << " typeless links found for " << linkName
814  << " returning the first link, consider using findLinks.");
815  }
816  key = keyVec.at(0);
817  clid = clidVec.at(0);
818  index = indexVec.at(0);
819  source = sourceVec.at(0);
820  return true;
821  }
822 
823 
825  const std::string& chainName,
826  const std::vector<LinkInfo<xAOD::IParticleContainer>>& features,
827  const std::vector<std::size_t>& legMultiplicities,
828  const std::function<bool(const std::vector<LinkInfo<xAOD::IParticleContainer>>&)>& filter)
829  {
831  combinations.reserve(legMultiplicities.size());
832  if (legMultiplicities.size() == 1)
833  combinations.addLeg(legMultiplicities.at(0), features);
834  else
835  for (std::size_t legIdx = 0; legIdx < legMultiplicities.size(); ++legIdx)
836  {
837  // Skip any that will not provide IParticle features
838  if (legMultiplicities[legIdx] == 0)
839  continue;
840  HLT::Identifier legID = createLegName(chainName, legIdx);
841  std::vector<LinkInfo<xAOD::IParticleContainer>> legFeatures;
842  for (const LinkInfo<xAOD::IParticleContainer>& info : features) {
843  if (info.decisions->contains(legID.numeric()))
844  legFeatures.push_back(info);
845  }
846  combinations.addLeg(legMultiplicities.at(legIdx), std::move(legFeatures));
847  }
848  return combinations;
849  }
850 
851 
853  const std::string& chainName,
854  const std::vector<LinkInfo<xAOD::IParticleContainer>>& features,
855  const std::vector<std::size_t>& legMultiplicities,
857  {
858  return buildCombinations(chainName, features, legMultiplicities, getFilter(filter));
859  }
860 
862  const std::string& chainName,
863  const std::vector<LinkInfo<xAOD::IParticleContainer>>& features,
864  const TrigConf::HLTChain *chainInfo,
865  const std::function<bool(const std::vector<LinkInfo<xAOD::IParticleContainer>>&)>& filter)
866  {
867  return buildCombinations(chainName, features, chainInfo->leg_multiplicities(), filter);
868  }
869 
871  const std::string& chainName,
872  const std::vector<LinkInfo<xAOD::IParticleContainer>>& features,
873  const TrigConf::HLTChain *chainInfo,
875  {
876  return buildCombinations(chainName, features, chainInfo, getFilter(filter));
877  }
878 
879 
880  std::string dump( const Decision* tc, const std::function< std::string( const Decision* )>& printerFnc ) {
881  std::string ret;
882  ret += printerFnc( tc );
883  if ( hasLinkToPrevious(tc) ) {
884  const std::vector<ElementLink<DecisionContainer>> seeds = getLinkToPrevious(tc);
885  for (const ElementLink<DecisionContainer>& seedEL : seeds) {
886  ret += " -> " + dump( *seedEL, printerFnc );
887  }
888  }
889  return ret;
890  }
891 
892 }
893 
WriteHandle.h
Handle class for recording to StoreGate.
TrigCompositeUtils::featureString
const std::string & featureString()
Definition: TrigCompositeUtils.h:420
TrigCompositeUtils::buildCombinations
Combinations buildCombinations(const std::string &chainName, const std::vector< LinkInfo< xAOD::IParticleContainer >> &features, const std::vector< std::size_t > &legMultiplicities, const std::function< bool(const std::vector< LinkInfo< xAOD::IParticleContainer >> &)> &filter)
Produce the combinations for a set of features.
Definition: TrigCompositeUtilsRoot.cxx:824
data
char data[hepevt_bytes_allocation_ATLAS]
Definition: HepEvt.cxx:11
TrigCompositeUtils::find
const Decision * find(const Decision *start, const std::function< bool(const Decision *)> &filter)
traverses Decision object links for another Decision object fulfilling the prerequisite specified by ...
Definition: TrigCompositeUtilsRoot.cxx:236
get_generator_info.result
result
Definition: get_generator_info.py:21
TrigCompositeUtils::DecisionID
unsigned int DecisionID
Definition: TrigComposite_v1.h:27
SG
Forward declaration.
Definition: CaloCellPacker_400_500.h:32
TrigCompositeUtils::DecisionContainer
xAOD::TrigCompositeContainer DecisionContainer
Definition: Event/xAOD/xAODTrigger/xAODTrigger/TrigCompositeContainer.h:21
vtune_athena.format
format
Definition: vtune_athena.py:14
TrigCompositeUtils::passed
bool passed(DecisionID id, const DecisionIDContainer &idSet)
checks if required decision ID is in the set of IDs in the container
Definition: TrigCompositeUtilsRoot.cxx:118
TrigCompositeUtils::recursiveGetDecisions
void recursiveGetDecisions(const Decision *start, NavGraph &navGraph, const DecisionIDContainer &ids, const bool enforceDecisionOnStartNode)
Search back in time from "node" and locate all paths back through Decision objects for a given chain.
Definition: TrigCompositeUtilsRoot.cxx:446
HLT::Identifier::numeric
TrigCompositeUtils::DecisionID numeric() const
numeric ID
Definition: TrigCompositeUtils/TrigCompositeUtils/HLTIdentifier.h:41
SG::Accessor
Helper class to provide type-safe access to aux data.
Definition: Control/AthContainers/AthContainers/Accessor.h:68
xAOD::uint32_t
setEventNumber uint32_t
Definition: EventInfo_v1.cxx:127
TrigCompositeUtils::HasObjectCollection::operator()
bool operator()(const Decision *) const
checks if the arg Decision object has link collection of name specified at construction
Definition: TrigCompositeUtilsRoot.cxx:254
WriteCellNoiseToCool.src
src
Definition: WriteCellNoiseToCool.py:513
TrigCompositeUtils::newDecisionIn
Decision * newDecisionIn(DecisionContainer *dc, const std::string &name)
Helper method to create a Decision object, place it in the container and return a pointer to it.
Definition: TrigCompositeUtilsRoot.cxx:44
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:67
index
Definition: index.py:1
hist_file_dump.d
d
Definition: hist_file_dump.py:142
TrigCompositeUtils::NavGraph::finalNodes
const std::vector< NavGraphNode * > & finalNodes() const
Get all final nodes.
Definition: NavGraph.cxx:99
TrigCompositeUtils::summaryPassExpressNodeName
const std::string & summaryPassExpressNodeName()
Definition: TrigCompositeUtils.h:430
TrigCompositeUtils::addDecisionID
void addDecisionID(DecisionID id, Decision *d)
Appends the decision (given as ID) to the decision object.
Definition: TrigCompositeUtilsRoot.cxx:59
mergePhysValFiles.start
start
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:13
TrigCompositeUtils::summaryPassNodeName
const std::string & summaryPassNodeName()
Definition: TrigCompositeUtils.h:429
xAOD::TrigComposite_v1::hasObjectLink
bool hasObjectLink(const std::string &name, const CLID clid=CLID_NULL) const
Check if a link to an object with a given name and type exists. CLID_NULL to not check type.
Definition: TrigComposite_v1.cxx:244
skel.it
it
Definition: skel.GENtoEVGEN.py:407
xAOD::TrigComposite_v1::object
const OBJECT * object(const std::string &name) const
Get a bare pointer with the requested name.
TrigCompositeUtils::typelessFindLinksCommonLinkCollection
bool typelessFindLinksCommonLinkCollection(const Decision *start, const std::string &linkName, std::vector< sgkey_t > &keyVec, std::vector< uint32_t > &clidVec, std::vector< Decision::index_type > &indexVec, std::vector< const Decision * > &sourceVec)
Common functionality shared by both typelessFindLinks interfaces Returns true if at least one link wa...
Definition: TrigCompositeUtilsRoot.cxx:697
TrigCompositeUtils::insertDecisionIDs
void insertDecisionIDs(const Decision *src, Decision *dest)
Appends the decision IDs of src to the dest decision object.
Definition: TrigCompositeUtilsRoot.cxx:78
TrigCompositeUtils::comboHypoAlgNodeName
const std::string & comboHypoAlgNodeName()
Definition: TrigCompositeUtils.h:427
TrigCompositeUtils::NavGraph::addNode
void addNode(const Decision *node, const Decision *comingFrom=nullptr)
Add a new NavGraphNode which shadows the xAOD Decision object "node" from the full navigation graph.
Definition: NavGraph.cxx:73
perfmonmt-printer.dest
dest
Definition: perfmonmt-printer.py:189
SG::ConstAccessor
Helper class to provide constant type-safe access to aux data.
Definition: ConstAccessor.h:55
xAOD::TrigComposite_v1::hasObjectCollectionLinks
bool hasObjectCollectionLinks(const std::string &collectionName, const CLID clid=CLID_NULL) const
Check if links exist to a collection of objects with given name and type. CLID_NULL to not check type...
Definition: TrigComposite_v1.cxx:273
TrigCompositeUtils::recursiveFlagForThinningInternal
void recursiveFlagForThinningInternal(NavGraphNode *node, bool modeKeep, std::set< NavGraphNode * > &fullyExploredFrom, const bool keepOnlyFinalFeatures, const bool removeEmptySteps, const std::vector< std::string > &nodesToDrop)
Used by recursiveFlagForThinning.
Definition: TrigCompositeUtilsRoot.cxx:471
const
bool const RAWDATA *ch2 const
Definition: LArRodBlockPhysicsV0.cxx:560
SG::ReadHandleKey
Property holding a SG store/key/clid from which a ReadHandle is made.
Definition: StoreGate/StoreGate/ReadHandleKey.h:39
TrigConf::HLTChain
HLT chain configuration information.
Definition: TrigConfHLTData/TrigConfHLTData/HLTChain.h:35
x
#define x
TrigCompositeUtils::getNameAndIndexFromLeg
std::pair< std::string, int32_t > getNameAndIndexFromLeg(const std::string &name)
Extract the name and numeric index of a leg identifier.
Definition: TrigCompositeUtilsRoot.cxx:207
TrigCompositeUtils::createAndStore
SG::WriteHandle< DecisionContainer > createAndStore(const SG::WriteHandleKey< DecisionContainer > &key, const EventContext &ctx)
Creates and right away records the DecisionContainer with the key.
Definition: TrigCompositeUtilsRoot.cxx:28
TrigCompositeUtils::HasObject::m_name
std::string m_name
Definition: TrigCompositeUtils.h:295
intersection
std::vector< std::string > intersection(std::vector< std::string > &v1, std::vector< std::string > &v2)
Definition: compareFlatTrees.cxx:25
TrigConf::HLTChain::leg_multiplicities
const std::vector< size_t > & leg_multiplicities() const
Definition: TrigConfHLTData/TrigConfHLTData/HLTChain.h:83
TrigCompositeUtils::HasObjectCollection::m_name
std::string m_name
Definition: TrigCompositeUtils.h:313
covarianceTool.filter
filter
Definition: covarianceTool.py:514
TrigCompositeUtils::HasObject::operator()
bool operator()(const Decision *) const
checks if the arg TC has link of name specified at construction
Definition: TrigCompositeUtilsRoot.cxx:250
SG::makeHandle
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
Definition: ReadCondHandle.h:274
TrigCompositeUtils::FilterType
FilterType
Definition: IPartCombItr.h:22
TrigCompositeUtils::getTerminusNode
const Decision * getTerminusNode(SG::ReadHandle< DecisionContainer > &container)
Definition: TrigCompositeUtilsRoot.cxx:258
TrigCompositeUtils.h
StoreGateSvc
The Athena Transient Store API.
Definition: StoreGateSvc.h:122
lumiFormat.i
int i
Definition: lumiFormat.py:85
ReadCalibFromCool.keep
keep
Definition: ReadCalibFromCool.py:85
TrigCompositeUtils::getLinkToPrevious
const std::vector< ElementLink< DecisionContainer > > getLinkToPrevious(const Decision *d)
returns links to previous decision object 'seed'
Definition: TrigCompositeUtilsRoot.cxx:157
TrigCompositeUtils::typelessFindLinks
bool typelessFindLinks(const Decision *start, const std::string &linkName, std::vector< sgkey_t > &keyVec, std::vector< uint32_t > &clidVec, std::vector< Decision::index_type > &indexVec, std::vector< const Decision * > &sourceVec, const unsigned int behaviour, std::set< const Decision * > *fullyExploredFrom)
search back the TC links for the object of type T linked to the one of TC (recursively) Returns the l...
Definition: TrigCompositeUtilsRoot.cxx:603
TrigCompositeUtils::getExpressTerminusNode
const Decision * getExpressTerminusNode(const DecisionContainer &container)
Returns the express-accept navigation node from a collection or nullptr if missing.
Definition: TrigCompositeUtilsRoot.cxx:266
IParticleContainer.h
ClassID_traits
Default, invalid implementation of ClassID_traits.
Definition: Control/AthenaKernel/AthenaKernel/ClassID_traits.h:37
ANA_MSG_WARNING
#define ANA_MSG_WARNING(xmsg)
Macro printing warning messages.
Definition: Control/AthToolSupport/AsgMessaging/AsgMessaging/MessageCheck.h:292
TrigCompositeUtils::copyLinks
bool copyLinks(const Decision *src, Decision *dest)
copy all links from src to dest TC objects
Definition: TrigCompositeUtilsRoot.cxx:162
TrigCompositeUtils::NavGraph
Structure to hold a transient Directed Acyclic Graph (DAG) structure. NavGraph is populated from,...
Definition: NavGraph.h:111
TrigCompositeUtils::Combinations
Definition: Combinations.h:18
SG::VarHandleKey::initialize
StatusCode initialize(bool used=true)
If this object is used as a property, then this should be called during the initialize phase.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:103
xAOD::TrigComposite_v1
Class used to describe composite objects in the HLT.
Definition: TrigComposite_v1.h:49
DataVector
Derived DataVector<T>.
Definition: DataVector.h:795
HLT::Identifier
Definition: TrigCompositeUtils/TrigCompositeUtils/HLTIdentifier.h:19
TrigCompositeUtils::hltSeedingNodeName
const std::string & hltSeedingNodeName()
Definition: TrigCompositeUtils.h:423
xAOD::decisions
decisions
Definition: TrigComposite_v1.cxx:101
perfmonmt-printer.required
required
Definition: perfmonmt-printer.py:184
TrigCompositeUtils::isChainId
bool isChainId(const HLT::Identifier &chainIdentifier)
Recognise whether the HLT identifier corresponds to a whole chain.
Definition: TrigCompositeUtilsRoot.cxx:227
ANA_MSG_SOURCE
#define ANA_MSG_SOURCE(NAME, TITLE)
the source code part of ANA_MSG_SOURCE
Definition: Control/AthToolSupport/AsgMessaging/AsgMessaging/MessageCheck.h:133
id
SG::auxid_t id
Definition: Control/AthContainers/Root/debug.cxx:239
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
python.subdetectors.mmg.ids
ids
Definition: mmg.py:8
ReadHandle.h
Handle class for reading from StoreGate.
TrigCompositeUtils::Decision
xAOD::TrigComposite Decision
Definition: Event/xAOD/xAODTrigger/xAODTrigger/TrigComposite.h:20
xAOD::TrigComposite_v1::index_type
uint32_t index_type
Definition: TrigComposite_v1.h:53
DataVector::push_back
value_type push_back(value_type pElem)
Add an element to the end of the collection.
checkTriggerxAOD.found
found
Definition: checkTriggerxAOD.py:328
TrigCompositeUtils::seedString
const std::string & seedString()
Definition: TrigCompositeUtils.h:421
TrigCompositeUtils::getFilter
std::function< bool(const std::vector< LinkInfo< xAOD::IParticleContainer >> &)> getFilter(FilterType filter)
Get a lambda corresponding to the specified FilterType enum.
Definition: IPartCombItr.cxx:69
TrigCompositeUtils::createLegName
HLT::Identifier createLegName(const HLT::Identifier &chainIdentifier, size_t counter)
Generate the HLT::Identifier which corresponds to a specific leg of a given chain.
Definition: TrigCompositeUtilsRoot.cxx:166
TrigCompositeUtils::hasLinkToPrevious
bool hasLinkToPrevious(const Decision *d)
checks if there is at least one 'seed' link to previous object
Definition: TrigCompositeUtilsRoot.cxx:153
TrigCompositeUtils::getRejectedDecisionNodes
std::vector< const Decision * > getRejectedDecisionNodes([[maybe_unused]] const asg::EventStoreType *eventStore, const EventContext &ctx, const std::string &summaryCollectionKey, const DecisionIDContainer &ids, const std::set< std::string > &keysToIgnore)
Definition: TrigCompositeUtilsRoot.cxx:276
python.combo.combinations
def combinations(items, n)
Definition: combo.py:84
xAOD::TrigComposite_v1::name
const std::string & name() const
Get a human-readable name for the object.
DataVector::end
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
SG::WriteHandle
Definition: StoreGate/StoreGate/WriteHandle.h:73
TrigCompositeUtils::linkToPrevious
void linkToPrevious(Decision *d, const std::string &previousCollectionKey, size_t previousIndex)
Links to the previous object, location of previous 'seed' decision supplied by hand.
Definition: TrigCompositeUtilsRoot.cxx:140
TrigCompositeUtils::isLegId
bool isLegId(const HLT::Identifier &legIdentifier)
Recognise whether the chain ID is a leg ID.
Definition: TrigCompositeUtilsRoot.cxx:219
TrigCompositeUtils::LinkInfo< xAOD::IParticleContainer >
TrigCompositeUtils::getIndexFromLeg
int32_t getIndexFromLeg(const HLT::Identifier &legIdentifier)
Extract the numeric index of a leg identifier.
Definition: TrigCompositeUtilsRoot.cxx:191
TrigCompositeUtils::DecisionIDContainer
std::set< DecisionID > DecisionIDContainer
Definition: TrigComposite_v1.h:28
SG::WriteHandle::record
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
TrigCompositeUtils::sgkey_t
SG::sgkey_t sgkey_t
Definition: TrigCompositeUtils.h:43
TrigCompositeUtils::NavGraphNode
Transient utility class to represent a node in a graph (m_decisionObject), and a vector of edges (m_f...
Definition: NavGraph.h:20
TrigCompositeUtils::hypoAlgNodeName
const std::string & hypoAlgNodeName()
Definition: TrigCompositeUtils.h:426
python.TriggerAPI.TriggerAPISession.chainName
chainName
Definition: TriggerAPISession.py:426
TrigCompositeUtils::allFailed
bool allFailed(const Decision *d)
return true if there is no positive decision stored
Definition: TrigCompositeUtilsRoot.cxx:104
TrigCompositeUtils::decisionIDs
void decisionIDs(const Decision *d, DecisionIDContainer &destination)
Extracts DecisionIDs stored in the Decision object.
Definition: TrigCompositeUtilsRoot.cxx:65
HLT::Identifier::name
std::string name() const
reports human redable name
Definition: HLTIdentifier.cxx:12
python.SystemOfUnits.s
float s
Definition: SystemOfUnits.py:147
TrigCompositeUtils::recursiveFlagForThinning
void recursiveFlagForThinning(NavGraph &graph, const bool keepOnlyFinalFeatures, const bool removeEmptySteps, const std::vector< std::string > &nodesToDrop)
Used by trigger navigation thinning.
Definition: TrigCompositeUtilsRoot.cxx:459
TrigCompositeUtils::dump
std::string dump(const Decision *tc, const std::function< std::string(const Decision *)> &printerFnc)
Prints the Decision object including the linked seeds @warnign expensive call.
Definition: TrigCompositeUtilsRoot.cxx:880
TrigCompositeUtils
Definition: Event/xAOD/xAODTrigger/xAODTrigger/TrigComposite.h:19
node::node
node(node *n=0, const std::string &d="", TObject *t=0)
Definition: node.h:29
ClassID_traits::ID
static CLID ID()
Definition: Control/AthenaKernel/AthenaKernel/ClassID_traits.h:44
copySelective.source
string source
Definition: copySelective.py:31
TrigCompositeUtils::getNodeByName
const Decision * getNodeByName(const DecisionContainer &container, const std::string &nodeName)
Returns the navigation node with a given name from a collection or nullptr if missing.
Definition: TrigCompositeUtilsRoot.cxx:270
python.Bindings.keys
keys
Definition: Control/AthenaPython/python/Bindings.py:801
TrigCompositeUtils::getIDFromLeg
HLT::Identifier getIDFromLeg(const HLT::Identifier &legIdentifier)
Generate the HLT::Identifier which corresponds to the chain name from the leg name.
Definition: TrigCompositeUtilsRoot.cxx:180
TrigCompositeUtils::uniqueDecisionIDs
void uniqueDecisionIDs(Decision *dest)
Make unique list of decision IDs of dest Decision object.
Definition: TrigCompositeUtilsRoot.cxx:98
test_pyathena.counter
counter
Definition: test_pyathena.py:15
set_intersection
Set * set_intersection(Set *set1, Set *set2)
Perform an intersection of two sets.
TrigCompositeUtils::isAnyIDPassing
bool isAnyIDPassing(const Decision *d, const DecisionIDContainer &required)
Checks if any of the DecisionIDs passed in arg required is availble in Decision object.
Definition: TrigCompositeUtilsRoot.cxx:109
TrigCompositeUtils::inputMakerNodeName
const std::string & inputMakerNodeName()
Definition: TrigCompositeUtils.h:425
python.ParticleTypeUtil.info
def info
Definition: ParticleTypeUtil.py:87
SG::sgkeyEqual
constexpr bool sgkeyEqual(const sgkey_t a, const sgkey_t b)
Compare two sgkeys for equality.
Definition: CxxUtils/CxxUtils/sgkey_t.h:39
node
Definition: node.h:21
DataVector::begin
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
AuxElement.h
Base class for elements of a container that can have aux data.
TrigCompositeUtils::recursiveGetDecisionsInternal
void recursiveGetDecisionsInternal(const Decision *node, const Decision *comingFrom, NavGraph &navGraph, std::set< const Decision * > &fullyExploredFrom, const DecisionIDContainer &ids, const bool enforceDecisionOnNode)
Used by recursiveGetDecisions.
Definition: TrigCompositeUtilsRoot.cxx:407
TrigCompositeUtils::decisionToElementLink
ElementLink< DecisionContainer > decisionToElementLink(const Decision *d, const EventContext &ctx)
Takes a raw pointer to a Decision and returns an ElementLink to the Decision.
Definition: TrigCompositeUtilsRoot.cxx:123
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37
TrigCompositeUtils::typelessFindLink
bool typelessFindLink(const Decision *start, const std::string &linkName, sgkey_t &key, uint32_t &clid, Decision::index_type &index, const Decision *&source, const bool suppressMultipleLinksWarning)
Perform a recursive search for ElementLinks of any time and name 'linkName', starting from Decision o...
Definition: TrigCompositeUtilsRoot.cxx:747