ATLAS Offline Software
TrigNavigationThinningSvc.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3 */
4 
7 #include "getLabel.h"
12 #include "TrigNavigation/Holder.h"
16 #include "GaudiKernel/ThreadLocalContext.h"
17 #include <sstream>
18 #include <iostream>
19 
21 
23 using namespace HLT;
24 
25 /**********************************************************************
26  *
27  * Constructors and destructors
28  *
29  **********************************************************************/
30 
32  ISvcLocator* pSvcLocator )
33  : base_class(name, pSvcLocator),
34  m_trigDecisionTool("Trig::TrigDecisionTool/TrigDecisionTool")
35 {
36  // job option configurable properties
37  declareProperty("TrigDecisionTool", m_trigDecisionTool, "Tool handle to TDT/Navigation.");
38  declareProperty("ChainsRegex", m_chainsRegex="", "Keep only information related to this chains");
39  declareProperty("FeatureInclusionList", m_featureInclusionList, "This features will be kept. This setting overrules the FeatureExclusionList. Only list of types or type#key pairs are supported.");
40  declareProperty("FeatureExclusionList", m_featureExclusionList, "This features will be dropeed. It can be specified as * meaning all, or as a list of typenames, or typename#key pairs.");
41  declareProperty("ReportOperations", m_report=false, "Additional verbosity flag, when enabled the operations on trigger elements are reported (VERBOSE logging level)");
42 
55 
56 
57  std::string possibleActions;
58  for ( auto a: m_actionsMap )
59  possibleActions += a.first +" ";
60  declareProperty("Actions", m_actions, "Operations which need to be done on the navigation"+possibleActions);
61 }
62 
63 
64 /**********************************************************************
65  *
66  * Initialization and Finalization
67  *
68  **********************************************************************/
69 
71 
72  ATH_MSG_DEBUG( "TrigNavigationThinningSvc::initialize()" << name() );
73 
74  m_checkToolDeps = false;
75 
76  // load the required tools
77  if( not m_trigDecisionTool.empty() ) {
78  if ( m_trigDecisionTool.retrieve().isFailure() ) {
79  ATH_MSG_FATAL ( "Unable to retrieve the TrigDecisionTool!" );
80  ATH_MSG_FATAL ( "Please check your job options file" );
81  return StatusCode::FAILURE;
82  }
83  ATH_MSG_INFO ( "Successfully retrived the TrigDecisionTool!" );
84  }
85  else {
86  ATH_MSG_FATAL ( "Could not retrive the TrigDecisionTool as it was not specified!" );
87  return StatusCode::FAILURE;
88  }
89 
90  ATH_MSG_DEBUG ( "Leaving TrigNavigationThinningSvc::Initialize" );
91  // make sure that the inclusions/exclusions are self consistent i.e. they can not be sued at the same time
92  if ( m_featureExclusionList.size() and m_featureInclusionList.size() ) {
93  ATH_MSG_ERROR( "Can't use the features inclusion and exclusion lists at the same time.");
94  return StatusCode::FAILURE;
95  }
96 
99  if ( m_featureKeepSet.size() or m_featureDropSet.size() ) {
100  ATH_MSG_DEBUG("Configured features removeal keep:" << m_featureInclusionList
101  << " drop: " << m_featureExclusionList );
102  } else {
103  if ( find(m_actions.begin(), m_actions.end(), "DropFeatures") != m_actions.end() ) {
104  ATH_MSG_FATAL("Dropping features is demanded but neither inclusion and exclusion lists are set");
105  return StatusCode::FAILURE;
106  }
107  }
108 
109 
110 
111  // verify if all actions are possible
112  for ( auto& action: m_actions) {
113  if ( m_actionsMap.find(action) == m_actionsMap.end()) {
114  ATH_MSG_FATAL("Action not implemented (check for typo) " << action << " possible " << m_actions);
115  return StatusCode::FAILURE;
116  }
117  }
118  return StatusCode::SUCCESS;
119 }
120 
121 
124 {
125  state.destinationNavigation.clear();
126  ATH_MSG_DEBUG ( "Navigation dropped entirely" );
127  return StatusCode::SUCCESS;
128 }
129 
132 {
133  state.destinationNavigation.clear();
134  std::vector<unsigned int> cuts;
135  std::vector<uint32_t> temp;
136  state.navigation.serialize(temp, cuts);
137  state.navigation.reset();
138  state.navigation.prepare();
139  state.navigation.deserialize(temp);
140  ATH_MSG_DEBUG ( "Reloaded the navigation content in TDT (all clients will see reduced navigation content) ..." );
141  return StatusCode::SUCCESS;
142 }
143 
144 
146  std::vector<unsigned int> cuts;
148  ATH_MSG_DEBUG ( "Saved the slimmed navigation" );
149  return StatusCode::SUCCESS;
150 }
151 
154 {
155  state.navigation.reset();
156  state.navigation.prepare();
158  ATH_MSG_DEBUG ( "Restored the original navigation" );
159  return StatusCode::SUCCESS;
160 }
161 
162 
163 
165  ATH_MSG_DEBUG ( "Navigation printout \n" << state.navigation );
166  return StatusCode::SUCCESS;
167 }
168 
170  for ( auto te: state.navigation.getAllTEs() ) {
171  if ( state.navigation.isInitialNode(te)
172  or state.navigation.isRoINode(te)
173  or state.navigation.isTerminalNode(te)
174  or state.tesToProtect.find(te->getId()) != state.tesToProtect.end())
175  continue;
176  // if ( te->getId() == 4032407525 ) m_report = true;
177  CHECK( removeTriggerElement(state, te) );
178  // m_report = false;
179  }
180 
181  return StatusCode::SUCCESS;
182 }
183 
184 
186 {
187  // turn the inclusion and exclusion lists into set of pairs <CLID, SubTypeIndex> of this collections which needs to be dropped
188  // in fact this a bit waste of time that we reclaulate this each time, but, one can imagine slimming events from different runs/configurations
189  // but then we sould have to check some configuration in data (i.e. SMK in the HLTResult, and recompute m_deletedFeatures only if it changes)
190  std::set<std::pair<CLID, uint16_t> > toDelete;
191  std::set<std::pair<CLID, uint16_t> > toRetain;
192 
193  std::lock_guard<std::recursive_mutex> lock(state.navigation.getMutex());
194 
195  const auto& holders = state.navigation.getHolderStorage().getAllHolders<HLTNavDetails::IHolder>();
196  if ( holders.empty() ) { // to prevent issues as in ATR-25282
197  ATH_MSG_ERROR("The navigation does not contain any features. This is likely a configuration problem.");
198  return StatusCode::FAILURE;
199  }
200 
201  for( auto h : holders ) {
202  if(!h) { // check if h is null
203  ATH_MSG_WARNING("holder.second is null pointer; skipping...");
204  continue;
205  }
206  //ATH_MSG_VERBOSE("Checking what to do with "
207  // << h->collectionName()+"#"+h->key());
208  // check if this needs to be kept
209  if ( not m_featureKeepSet.empty() ) {
210  if ( m_featureKeepSet.count(h->collectionName())
211  || m_featureKeepSet.count(h->key()) ) {
212  toRetain.insert(std::make_pair(h->typeClid(), h->subTypeIndex() ));
213  ATH_MSG_DEBUG("will be keeping references associated to: " << h->collectionName()<<"#"<<h->key() << " clid: " << h->typeClid() );
214  }
215  }
216  // check if this needs to be dropped
217  if ( not m_featureDropSet.empty() ) {
218  if ( m_featureDropSet.count(h->collectionName())
219  || m_featureDropSet.count(h->key()) ) {
220  toDelete.insert(std::make_pair(h->typeClid(), h->subTypeIndex() ));
221  ATH_MSG_DEBUG("will be dropping references associated to: " << h->collectionName()<<"#"<<h->key() );
222  }
223  }
224  }
225 
226 
227  if ( not toRetain.empty() )
228  return retainFeatures(state, toRetain);
229  if ( not toDelete.empty() )
230  return removeFeatures(state, toDelete);
231 
232  // now that we've removed them from the tree, we need to remove them from
233  // the navigation structure as well. We do this by finding the holders that
234  // match the deleted labels and removing them.
235  // to be implemented !!!
236 
237  return StatusCode::SUCCESS;
238 }
239 
240 
242  for ( auto te: state.navigation.getAllTEs() ) {
243  if ( state.navigation.isRoINode(te) )
244  CHECK( removeTriggerElement(state, te) );
245  }
246  return StatusCode::SUCCESS;
247 }
248 
250  for ( auto te: state.navigation.getAllTEs() ) {
251  if ( state.navigation.isRoINode(te)
252  and te->getRelated(TriggerElement::seedsRelation).empty() )
253  CHECK( removeTriggerElement(state, te) );
254  }
255  return StatusCode::SUCCESS;
256 }
257 
259  for ( auto te: state.navigation.getAllTEs() ) {
260  if ( te->getFeatureAccessHelpers().empty() )
261  CHECK( removeTriggerElement(state, te) );
262  }
263  return StatusCode::SUCCESS;
264 }
265 
266 
268  if ( m_chainsRegex.empty() ) {
269  return StatusCode::SUCCESS;
270  }
271  // now run over the tree and drop alle TEs except RoIs and intial which are not in the TEs to protect
272  for ( auto te: state.navigation.getAllTEs() ) {
273  if ( state.navigation.isInitialNode(te)
274  or state.navigation.isRoINode(te) ) {
275  continue;
276  }
277  if ( state.tesToProtect.find(te->getId()) == state.tesToProtect.end() ) {
278  CHECK( removeTriggerElement(state, te));
279  }
280  }
281  return StatusCode::SUCCESS;
282 }
283 
284 
285 
288  std::vector<uint32_t>& slimmed_and_serialized) const {
289 
290  ATH_MSG_DEBUG(name() << " is obtaining the TrigNavigationThinningSvc lock in slot " << ctx.slot() << " for event " << ctx.eventID().event_number() );
291  std::lock_guard<std::mutex> lock(TrigNavigationThinningSvcMutex::s_mutex);
292 
293  // grab the navigation
294  auto navAccess = m_trigDecisionTool->ExperimentalAndExpertMethods();
295  // protected by above lock
296  HLT::NavigationCore *cnav ATLAS_THREAD_SAFE = const_cast<HLT::NavigationCore*>(navAccess.getNavigation());
297 
298  if(cnav == 0) {
299  ATH_MSG_WARNING ( "Could not get navigation from Trigger Decision Tool" );
300  ATH_MSG_WARNING ( "Navigation will not be slimmed in this event" );
301  ATH_MSG_DEBUG(name() << " is releasing the TrigNavigationThinningSvc lock");
302  return StatusCode::SUCCESS;
303  }
304 
305  State state (ctx, *cnav, slimmed_and_serialized);
306  CHECK( lateFillConfiguration(state) );
307  {
308  state.originalNavigation.clear();
309  std::vector<uint32_t> cuts;
310  cnav->serialize(state.originalNavigation, cuts);
311  }
312 
313  for ( auto& action: m_actions ) {
314  ATH_MSG_DEBUG("Applying action " << action << " on the navigation ");
315  auto ifunc = m_actionsMap.find (action);
316  if (ifunc != m_actionsMap.end()) {
317  auto function = ifunc->second;
318  CHECK( (this->*function)(state) );
319  }
320  }
321  ATH_MSG_DEBUG(name() << " is releasing the TrigNavigationThinningSvc lock");
322  return StatusCode::SUCCESS;
323 }
324 
325 
326 
328  return StatusCode::SUCCESS;
329 }
330 
331 
332 
335  // remember the configured chain names, as they will be useful later
336  // ??? Originally, this was done once and cached in the tool.
337  // If this takes too long, consider storing it in the detector store.
338  auto chainGroup = m_trigDecisionTool->getChainGroup(m_chainsRegex);
339  ATH_MSG_DEBUG("Will keep information related to this chains" << chainGroup->getListOfTriggers());
340  auto confTEs = chainGroup->getHLTTriggerElements();
341  for ( auto& vec: confTEs) {
342  for ( auto confTEPtr: vec) {
343  state.tesToProtect.insert(confTEPtr->id());
344  }
345  }
346  return StatusCode::SUCCESS;
347 }
348 
350  TriggerElement *te,
351  bool propagateFeatures) const {
352  // refuse to remove the initial node
353  if(state.navigation.isInitialNode(te)) {
354  return StatusCode::SUCCESS;
355  }
356  if ( m_report ) ATH_MSG_VERBOSE("Removing TE of ID: " << te->getId() );
357 
358  // mark the element as transient to prevent it from being serialized
359  te->setTransient();
360 
361 
362  // propagate the features to its children
363  if ( propagateFeatures )
365 
366 
367 
368  if ( m_report ) ATH_MSG_VERBOSE("Removeing TE of ID: " << te->getId() << " removing same RoI relations" );
369  // for those in the same RoI, we need only remove the relationship from ones who are related
370  const std::vector<TriggerElement*>& sameRoI = te->getRelated(TriggerElement::sameRoIRelation);
371 
372  for( auto nodeInRoI : sameRoI ) {
373  if ( m_report ) ATH_MSG_VERBOSE("Removeing TE of ID: " << te->getId() << " bypassing same RoI relation " );
374  // get the relations, and remove the ones that point to te
375  std::vector<TriggerElement*>& relations = nodeInRoI->m_relations[ TriggerElement::sameRoIRelation ];
376  CHECK( removeTriggerElementFromVector (te, relations) );
377  }
378 
379  // for those who te is seededBy, we need to remove the seeds relation, and propagate it down
380  // (if te is not terminal)
381 
382  std::vector<TriggerElement*> seededBy = te->m_relations[TriggerElement::seededByRelation];
383 
384  for(auto seededByNode: seededBy ) {
385 
386  // get the relations and remove the ones that point to te
387  std::vector<TriggerElement*>& relations = seededByNode->m_relations[ TriggerElement::seedsRelation ];
388  CHECK( removeTriggerElementFromVector (te, relations) );
389 
390 
391 
392  // now add all the nodes te seeds onto the node we just removed the seeds relation from
393  if(!state.navigation.isTerminalNode(te))
394  seededByNode->relate( te->m_relations[ TriggerElement::seedsRelation ], TriggerElement::seedsRelation );
395  }
396 
397  // for those who te seeds, we need to remove the seededBy relation, and propagate it up
398  // (if te is not the inital node - hey, you never know!)
399 
400  std::vector<TriggerElement*>& seeds = te->m_relations[TriggerElement::seedsRelation];
401 
402  for( auto seedsNode: seeds ) {
403 
404  // get the relations and remove the ones that point to te
405  std::vector<TriggerElement*>& relations = seedsNode->m_relations[ TriggerElement::seededByRelation ];
406  CHECK ( removeTriggerElementFromVector(te, relations) );
407 
408  // now add all the nodes te seeds onto the node we just removed the seeds relation from
409  if(!state.navigation.isInitialNode(te))
410  seedsNode->relate( te->m_relations[ TriggerElement::seededByRelation ], TriggerElement::seededByRelation );
411  }
412 
413  return StatusCode::SUCCESS;
414 }
415 
416 /**********************************************************************
417  *
418  * Feature Removal
419  *
420  **********************************************************************/
422  const std::set<std::pair<CLID, uint16_t> >& toDelete) const {
423  // we have the following problem:
424  // (a) features are stored as a vector where order can possibly matter
425  // (b) its very time consuming to delete items from the middle of a vector
426  // (c) a large fraction of elements will not have any features deleted
427  //
428  // To handle this, we're going to build an array that keeps track of
429  // whether an element needs be deleted. If none do, nothing gets changed.
430  // If some do, we build a new vector and copy it over. This prevents
431  // the big time sink from deleting elements in the middle of a vector.
432 
433  // another option would be to build a new vector when using inclusion
434  // lists and remove elements when using exclusion lists
435  ATH_MSG_DEBUG("Will remove " << toDelete.size()<< " feature type/key");
436  using namespace HLT;
437  for (auto te: state.navigation.getAllTEs()) {
438  for ( auto& fea: te->getFeatureAccessHelpers() ) {
439  if ( toDelete.find( std::make_pair(fea.getCLID(), fea.getIndex().subTypeIndex()) ) != toDelete.end() )
440  fea.setForget(true); // when we mark this then the serialization of TEs will simpley skip this one, easy, no
441  }
442  }
443  // get back here
444  // get rid of the holders themselves
445  //m_navigation->m_featuresByIndex[ h->typeClid() ].erase( h->subTypeIndex() ); // Erasing an element of the map we're looping over
446  //m_navigation->m_featuresByLabel.at( h->typeClid() ).erase( h->label() ); // Use new C++11 map accessor (does bounds check)
447  // delete holder.second;
448 
449  return StatusCode::SUCCESS;
450 }
451 
452 
454  const std::set<std::pair<CLID, uint16_t> >& toRetain) const {
455  ATH_MSG_DEBUG("Will retain " << toRetain.size()<< " feature type/key");
456  using namespace HLT;
457  for (auto te: state.navigation.getAllTEs()) {
458  for ( auto& fea: te->getFeatureAccessHelpers() ) {
459  if ( toRetain.find( std::make_pair(fea.getCLID(), fea.getIndex().subTypeIndex()) ) == toRetain.end() )
460  fea.setForget(true); // when we mark this then the serialization of TEs will simpley skip this one, easy, no
461  }
462  }
463  return StatusCode::SUCCESS;
464 
465 }
466 
469  TriggerElement *) {
470  ATH_MSG_DEBUG ( "Running the adjustIndicesAfterThinning" );
471 
472  for ( auto te: state.navigation.getAllTEs() ) {
473  size_t featuresCount = std::count_if(te->getFeatureAccessHelpers().begin(),
474  te->getFeatureAccessHelpers().end(),
475  [](const TriggerElement::FeatureAccessHelper& fea){ return fea.forget(); }
476  );
477  if( featuresCount == 0 ) {
478  CHECK( removeTriggerElement( state, te, false ) );
479  }
480  }
481  return StatusCode::SUCCESS;
482 }
483 
484 /**********************************************************************
485  *
486  * Generic Helper Functions
487  *
488  **********************************************************************/
490 
491  if( v.empty())
492  return StatusCode::SUCCESS;
493 
494  std::vector<TriggerElement*>::iterator newend = std::remove( v.begin(), v.end(), te);
495  v.erase(newend, v.end());
496 
497  return StatusCode::SUCCESS;
498 }
499 
501  TriggerElement *te,
502  std::vector<std::string> *inclusionList, std::vector<std::string> *exclusionList) {
503 
504  // if the inclusion list exists, then we use that
505  if(inclusionList && inclusionList->size() > 0) {
506 
507  // check if the trigger element has a feature that is included in the list
508  int onExclusionList = 0;
509  for(std::vector< TriggerElement::FeatureAccessHelper >::const_iterator iter =
510  te->getFeatureAccessHelpers().begin();
511  iter != te->getFeatureAccessHelpers().end(); ++iter) {
512  // grab the label and check if it was found in the inclusion list
513  if(std::find(inclusionList->begin(), inclusionList->end(), SlimmingHelper::getLabel(state.navigation, *iter )) != inclusionList->end())
514  return true;
515  // now find if its in the exclusion list
516  if(exclusionList && std::find(exclusionList->begin(), exclusionList->end(),
517  SlimmingHelper::getLabel( state.navigation, *iter )) != exclusionList->end())
518  onExclusionList = 1;
519  }
520 
521  // if it has a feature on the exclusion list, and none on the inclusion list,
522  // it should be excluded
523  if(onExclusionList)
524  return false;
525 
526  // we've gone through the feature list, and nothing was on the exclusion list,
527  // so we should keep it
528  return true;
529  }
530 
531  // if we get here, then there's no inclusionList, so we need to use the exclusion list
532 
533  // check if it exists - if it doesn't, pass everything
534  if(!exclusionList || exclusionList->size() == 0)
535  return true;
536 
537  for(std::vector< TriggerElement::FeatureAccessHelper >::const_iterator iter =
538  te->getFeatureAccessHelpers().begin();
539  iter != te->getFeatureAccessHelpers().end(); ++iter) {
540  // grab the label and check if it was found in the exclusion list
541  if(std::find(exclusionList->begin(), exclusionList->end(), SlimmingHelper::getLabel(state.navigation, *iter )) != exclusionList->end())
542  return false;
543  }
544 
545  // if we've made it here, its passed the exclusion list and so should be included
546  return true;
547 
548 }
549 
551  TriggerElement *te,
552  std::vector<TriggerElement*> *inclusionList,
553  std::vector<TriggerElement*> *exclusionList) {
554 
555  if(!te)
556  return false;
557 
558  // this function never allows inital nodes or RoI nodes to be removed
559  if( state.navigation.isInitialNode(te) || state.navigation.isRoINode(te) )
560  return true;
561 
562  // if the inclusion list exists, then we use that
563  // If its on the inclusion list, its kept for sure
564  // If its on the exclusion list, its only kept if
565  // its not on the inclusion list.
566  if(inclusionList && inclusionList->size() > 0) {
567 
568  // check if the element is in the list
569  if(std::find_if(inclusionList->begin(), inclusionList->end(),
570  TriggerElementFind(te)) != inclusionList->end())
571  return true;
572  // now, check if its in the exclusion list
573  if(exclusionList && std::find_if(exclusionList->begin(), exclusionList->end(),
574  TriggerElementFind(te)) != exclusionList->end())
575  return false;
576  // if its on neither list, keep it
577  return true;
578  }
579 
580  // if we get here, then there's no inclusionList, so we need to use the exclusion list
581 
582  // check if it exists - if it doesn't, pass everything
583  if(!exclusionList || exclusionList->size() == 0)
584  return true;
585 
586  // check if the te belongs to the exclusion list
587  if(std::find_if(exclusionList->begin(), exclusionList->end(),
588  TriggerElementFind(te)) != exclusionList->end()) {
589  return false;
590  }
591 
592  // if we've made it here, its passed the exclusion list and so should be included
593  return true;
594 
595 }
596 
599 
600  if ( not te )
601  return StatusCode::SUCCESS;
602 
603  const std::vector<TriggerElement::FeatureAccessHelper>& features = te->getFeatureAccessHelpers() ;
604 
605  const std::vector<TriggerElement*> children = te->getRelated(TriggerElement::seedsRelation);
606  for( auto ch: children ) {
607  if ( m_report ) ATH_MSG_VERBOSE("Propagating features to child: " << ch << " " << ch->getId() );
608  // add the parents features to the front of the child features list features list
609  // skip this FEAs which are anyway to be discarded
610  for( auto& fea: features ) {
611  if ( fea.forget() )
612  continue;
613  if ( m_report ){
614  std::stringstream ss;
615  ss << fea;
616  ATH_MSG_VERBOSE("Propagating feature " << ss.str() );
617  }
618  ch->getFeatureAccessHelpers().insert(ch->getFeatureAccessHelpers().begin(), fea );
619  }
620  // te->getFeatureAccessHelpers().insert((*iter)->getFeatureAccessHelpers().begin(), features.begin(), features.end());
621  }
622  return StatusCode::SUCCESS;
623 }
624 
626 
627  // return the id the RoI node
628  if(!te) {
629  m_id = 0;
630  m_RoI = 0;
631  }
632  else {
633  m_id = te->getId();
634 
635  const TriggerElement *mother = te;
636  m_RoI = te;
637  while( mother->getRelated(TriggerElement::seededByRelation).size() > 0 ) {
638  m_RoI = mother;
639  mother = m_RoI->getRelated(TriggerElement::seededByRelation)[0];
640  }
641  }
642 }
643 
645 
646  if(!te)
647  return 0;
648 
649  // if we didn't initialize the RoI, then we can't match
650  if(!m_RoI)
651  return false;
652 
653  // check that the id's match
654  if(te->getId() != m_id)
655  return 0;
656 
657  // Note that we can have elements with the same id as long as they are in difference RoI's
658  // Thus, we must ensure that the RoI's are the same
659 
660  // Find the RoI
661  const TriggerElement *mother = te;
662  const TriggerElement *RoI = te;
663 
664  while( mother->getRelated(TriggerElement::seededByRelation).size() > 0 ) {
665  RoI = mother;
666  mother = RoI->getRelated(TriggerElement::seededByRelation)[0];
667  }
668 
669  // now, RoI equality is defined by all the features that match, where a feature
670  // match is given by a matching CLID, subtypeIndex, and objectIndex
671 
672  const std::vector< TriggerElement::FeatureAccessHelper > firstFeatures = m_RoI->getFeatureAccessHelpers();
673  const std::vector< TriggerElement::FeatureAccessHelper > secondFeatures = m_RoI->getFeatureAccessHelpers();
674 
675  if(firstFeatures.size() != secondFeatures.size())
676  return false;
677 
678  for(unsigned int i = 0; i < firstFeatures.size(); i++) {
679  TriggerElement::FeatureAccessHelper firstFeature = firstFeatures[i];
680  TriggerElement::FeatureAccessHelper secondFeature = secondFeatures[i];
681 
682  if(firstFeature.getCLID() != secondFeature.getCLID())
683  return false;
684  if(firstFeature.getIndex().subTypeIndex() != secondFeature.getIndex().subTypeIndex())
685  return false;
686  if(firstFeature.getIndex().objectsBegin() != secondFeature.getIndex().objectsBegin())
687  return false;
688  if(firstFeature.getIndex().objectsEnd() != secondFeature.getIndex().objectsEnd())
689  return false;
690 
691  }
692 
693  // if we've made it this far, all the features match (what should we do if there
694  // are no features?), so we have found a match!
695 
696  return true;
697 
698 }
699 
700 
701 namespace {
702 
703  static const std::size_t RemovedIdx = SG::ThinningDecisionBase::RemovedIdx;
704  struct IndexRecalculator {
705  IndexRecalculator( const SG::ThinningDecisionBase* dec )
706  : m_dec(dec)
707  {}
708 
709  size_t getNewIndex(size_t oldIndex) {
710  if ( oldIndex >= m_indices.size() ) {
711  expand(oldIndex);
712  }
713  return m_indices[oldIndex];
714  }
715 
716  void expand(size_t maxIndex ) {
717  const size_t checkedSoFar = m_validIndices.size();
718  m_indices.resize(maxIndex+1, RemovedIdx);
719  m_validIndices.resize(maxIndex+1);
720 
721  for ( size_t toScan = checkedSoFar; toScan <= maxIndex; ++ toScan ) {
722  size_t newIndex = m_dec->index(toScan);
723  m_validIndices[toScan] = newIndex;
724  }
725 
726  for ( size_t toScan = checkedSoFar; toScan <= maxIndex; ++toScan ) {
727  m_indices[toScan] = std::count_if(m_validIndices.begin(), m_validIndices.begin()+toScan,
728  [](const size_t x){ return x != RemovedIdx; } );
729  }
730 
731  }
732 
733  std::vector<size_t> m_indices = {0}; // the 0 index will be 0 no mater what is slimmed
734  std::vector<size_t> m_validIndices; // the 0 index will be 0 no mater what is slimmed
735  const SG::ThinningDecisionBase* m_dec;
736  };
737 }
738 
740  const EventContext& ctx = Gaudi::Hive::currentContext();
741  ATH_MSG_DEBUG ( "Running the syncThinning" );
742 
743  std::lock_guard<std::recursive_mutex> lock(state.navigation.getMutex());
744 
745  const auto& holders = state.navigation.getHolderStorage().getAllHolders<HLTNavDetails::IHolder>();
746  if ( holders.empty() ) { // to prevent issues as in ATR-25282
747  ATH_MSG_ERROR("The navigation does not contain any features. This is likely a configuration problem.");
748  return StatusCode::FAILURE;
749  }
750 
751  for(auto holder : holders) {
752  const IProxyDict* ipd = Atlas::getExtendedEventContext(ctx).proxy();
753  if ( not ipd->proxy(holder->containerClid(), holder->label() ) ) {
754  ATH_MSG_DEBUG("Skipping feature missing in the store: " << holder->label());
755  continue;
756  }
757  holder->syncWithSG();
758  const SG::ThinningDecisionBase* dec =
759  SG::getThinningDecision (ctx, holder->label());
760  if ( dec ) {
761  ATH_MSG_DEBUG ( "Thinning occured for this container" << *holder <<", going to ajust the indices" );
762  // ThinningDecisionBase::index method returns the valid new index for unslimmed object and an invalid index ThinningDecisionBase::RemovedIndex for the ones that were removed
763  // The way to calulate new indexes for the ranges describing ROIs (X,Y) is to count the number valid indexes from X to 0 and from Y to 0
764  // This would be quite inefficient so we need to make a vector wiht new indexes
765  // this vector in the end will be of size equal to the original collection and at position X will have new values.
766  // Hoever the difficulty is that we are not able to obtain the size of the collection and we need to build this vector as we meet the indexs during
767  // the scan of TEs.
768  // Since this is quite tricky code it is outsourced to a helper class IndexRecalculator.
769 
770  IndexRecalculator recalculator( dec );
771  // now we need to go over the TEs
772  for ( const auto& te: state.navigation.getAllTEs() ) {
773  for ( auto& fea: te->getFeatureAccessHelpers() ) {
774  if ( fea.getCLID() == holder->typeClid()
775  and fea.getIndex().subTypeIndex() == holder->subTypeIndex() ) {
776  uint32_t begin = fea.getIndex().objectsBegin();
777  uint32_t end = fea.getIndex().objectsEnd();
778  uint32_t newEnd = recalculator.getNewIndex(end);
779  uint32_t newBegin = recalculator.getNewIndex(begin);
780 
782  idx.updateBeginAndEnd(newBegin, newEnd);
783  //ATH_MSG_DEBUG( "Indices changed to " << newBegin << " " << newEnd);
784 
785  }
786  }
787  }
788 
789  } // if thinning occures
790  else {
791  // ATH_MSG_DEBUG("Thinning did not occure on the " << * holder );
792  }
793  } // holder loop
794  return StatusCode::SUCCESS;
795 }
796 
797 
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
HLT::TriggerElement::ObjectIndex
Helper class for conversion from/to int stored in TE and pair of ints used in Navigation Object point...
Definition: TrigNavStructure/TrigNavStructure/TriggerElement.h:75
temp
Definition: JetEventDict.h:21
TrigNavigationThinningSvc::m_actions
std::vector< std::string > m_actions
Definition: TrigNavigationThinningSvc.h:89
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
TrigNavigationThinningSvc::State::tesToProtect
std::set< HLT::te_id_type > tesToProtect
Definition: TrigNavigationThinningSvc.h:86
sendEI_SPB.ch
ch
Definition: sendEI_SPB.py:35
TrigNavigationThinningSvc::lateFillConfiguration
StatusCode lateFillConfiguration(State &state) const
configures at the first event
Definition: TrigNavigationThinningSvc.cxx:334
IProxyDict::proxy
virtual SG::DataProxy * proxy(const CLID &id, const std::string &key) const =0
Get proxy with given id and key.
TrigNavigationThinningSvc::doSlimming
virtual StatusCode doSlimming(const EventContext &, std::vector< uint32_t > &slimmed_and_serialized) const override
Definition: TrigNavigationThinningSvc.cxx:287
PowhegControl_ttHplus_NLO.ss
ss
Definition: PowhegControl_ttHplus_NLO.py:83
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
TrigNavigationThinningSvc::reload
StatusCode reload(State &state) const
Reload the slimmed navigation in TDT so that all clients of current job see the chage.
Definition: TrigNavigationThinningSvc.cxx:131
HLT::TrigNavStructure::isRoINode
static bool isRoINode(const TriggerElement *te)
queries if node is an RoI type one
Definition: TrigNavStructure.cxx:507
TrigNavigationThinningSvc::dropFeatureless
StatusCode dropFeatureless(State &state) const
Removes TEs which have no features (combine wiht squeeze)
Definition: TrigNavigationThinningSvc.cxx:258
xAOD::uint32_t
setEventNumber uint32_t
Definition: EventInfo_v1.cxx:127
SG::ThinningDecisionBase
Hold thinning decisions for one container.
Definition: ThinningDecisionBase.h:39
BeamSpot::mutex
std::mutex mutex
Definition: InDetBeamSpotVertex.cxx:18
TrigNavigationThinningSvc::finalize
virtual StatusCode finalize() override
Definition: TrigNavigationThinningSvc.cxx:327
TrigNavigationThinningSvc::State
Definition: TrigNavigationThinningSvc.h:74
HLT::TrigNavStructure::getMutex
std::recursive_mutex & getMutex()
Definition: TrigNavStructure.h:371
TrigNavigationThinningSvc::retainFeatures
StatusCode retainFeatures(State &state, const std::set< std::pair< CLID, uint16_t > > &toRetain) const
This is a helper function for removeFeatures(HLT::NavigationCore*, ...).
Definition: TrigNavigationThinningSvc.cxx:453
HLT::NavigationCore::deserialize
bool deserialize(const std::vector< uint32_t > &input)
Definition: NavigationCore.cxx:151
TrigNavigationThinningSvc::State::originalNavigation
std::vector< uint32_t > originalNavigation
Definition: TrigNavigationThinningSvc.h:85
PlotCalibFromCool.begin
begin
Definition: PlotCalibFromCool.py:94
HLT::TriggerElement::getId
te_id_type getId() const
reset internals.
Definition: TrigNavStructure/TrigNavStructure/TriggerElement.h:43
HLT::TriggerElement::FeatureAccessHelper::getCLID
class_id_type getCLID() const
Class ID of object.
Definition: TrigNavStructure/TrigNavStructure/TriggerElement.h:208
HLT::TrigNavStructure::isTerminalNode
static bool isTerminalNode(const TriggerElement *te)
queries if node is terminal (no more TriggerElement are seeded by it)
Definition: TrigNavStructure.cxx:517
vec
std::vector< size_t > vec
Definition: CombinationsGeneratorTest.cxx:12
ThinningDecisionBase.h
Hold thinning decisions for one container.
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
ChainGroup.h
x
#define x
IProxyDict
A proxy dictionary.
Definition: AthenaKernel/AthenaKernel/IProxyDict.h:51
ATLAS_THREAD_SAFE
std::mutex TrigNavigationThinningSvcMutex::s_mutex ATLAS_THREAD_SAFE
Definition: TrigNavigationThinningSvc.cxx:20
TrigNavigationThinningSvc::save
StatusCode save(State &state) const
Save the result of the slimming in the doSlimming argument (vector<uint32_t>)
Definition: TrigNavigationThinningSvc.cxx:145
TrigNavigationThinningSvc::toBeIncluded
bool toBeIncluded(State &state, HLT::TriggerElement *te, std::vector< std::string > *inclusionList, std::vector< std::string > *exclusionList)
Returns true if the TriggerElement should be included in the navigation tree and false if it should n...
Definition: TrigNavigationThinningSvc.cxx:500
HLT::NavigationCore::reset
virtual void reset(bool inFinalize=false)
resets all the navigation, goes to the factory and asks to withdraw all produced objects
Definition: NavigationCore.cxx:281
HLT::TriggerElement::setTransient
void setTransient(bool t=true)
Definition: TrigNavStructure/TrigNavStructure/TriggerElement.h:59
TrigNavigationThinningSvc::m_chainsRegex
std::string m_chainsRegex
Definition: TrigNavigationThinningSvc.h:92
TrigNavigationThinningSvc::TriggerElementFind::TriggerElementFind
TriggerElementFind(const HLT::TriggerElement *te)
Definition: TrigNavigationThinningSvc.cxx:625
HLT::NavigationCore::prepare
virtual void prepare()
prepapres the navigation for next event
Definition: NavigationCore.cxx:335
mergePhysValFiles.end
end
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:93
HLT::TriggerElement::getRelated
const std::vector< TriggerElement * > & getRelated(Relation rel) const
returns reference to the likns to other TriggerElements related by relation r
Definition: TrigNavStructure/TrigNavStructure/TriggerElement.h:127
TriggerElement.h
Atlas::getExtendedEventContext
const ExtendedEventContext & getExtendedEventContext(const EventContext &ctx)
Retrieve an extended context from a context object.
Definition: ExtendedEventContext.cxx:32
PixelModuleFeMask_create_db.remove
string remove
Definition: PixelModuleFeMask_create_db.py:83
HLT::NavigationCore
The NavigationCore class, adds on top of the TrigNavStructure the EDM read-only handling.
Definition: NavigationCore.h:96
HLT::TriggerElement::ObjectIndex::subTypeIndex
sub_index_type subTypeIndex() const
to get collection index
Definition: TrigNavStructure/Root/TriggerElement.cxx:247
HLT::TriggerElement::ObjectIndex::objectsBegin
index_type objectsBegin() const
to get object number in th ecollection
Definition: TrigNavStructure/Root/TriggerElement.cxx:256
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
HLT
It used to be useful piece of code for replacing actual SG with other store of similar functionality ...
Definition: HLTResultReader.h:26
lumiFormat.i
int i
Definition: lumiFormat.py:92
TrigNavigationThinningSvc::print
StatusCode print(State &state) const
Definition: TrigNavigationThinningSvc.cxx:164
TrigNavigationThinningSvc::State::navigation
HLT::NavigationCore & navigation
Definition: TrigNavigationThinningSvc.h:83
TrigNavigationThinningSvcMutex::s_mutex
static std::mutex s_mutex
Definition: TrigNavigationThinningSvcMutex.h:19
h
TrigNavigationThinningSvc::removeFeatures
StatusCode removeFeatures(State &state, const std::set< std::pair< CLID, uint16_t > > &doDelete) const
This is a helper function for removeFeatures(HLT::NavigationCore*, ...).
Definition: TrigNavigationThinningSvc.cxx:421
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
HLT::TriggerElement
TriggerElement is the basic ingreedient of the interface between HLT algorithms and the navigation It...
Definition: TrigNavStructure/TrigNavStructure/TriggerElement.h:27
TrigNavigationThinningSvc::State::destinationNavigation
std::vector< uint32_t > & destinationNavigation
Definition: TrigNavigationThinningSvc.h:84
Holder.h
plotBeamSpotVert.cuts
string cuts
Definition: plotBeamSpotVert.py:93
getThinningCache.h
Helpers to retrieve the current thinning cache from the event context.
TrigNavigationThinningSvc::removeTriggerElement
StatusCode removeTriggerElement(State &state, HLT::TriggerElement *te, bool propagateFeatures=true) const
Removes the passed trigger element from the navigation structure by removing all references to it in ...
Definition: TrigNavigationThinningSvc.cxx:349
TrigNavigationThinningSvc::TriggerElementFind
Used to compare pointers of TriggerElements.
Definition: TrigNavigationThinningSvc.h:196
HLT::TrigNavStructure::getHolderStorage
TrigHolderStructure & getHolderStorage()
Definition: TrigNavStructure.h:370
Navigation.h
CHECK
#define CHECK(...)
Evaluate an expression and check for errors.
Definition: Control/AthenaKernel/AthenaKernel/errorcheck.h:422
SG::ThinningDecisionBase::RemovedIdx
static const std::size_t RemovedIdx
Flag used to show that an index has been thinned away.
Definition: ThinningDecisionBase.h:42
HLT::TrigNavTools::SlimmingHelper
Definition: getLabel.h:34
TrigNavigationThinningSvc::dropRoIs
StatusCode dropRoIs(State &state) const
Removes RoI nodes, rather aggressive option, should be use as one of last actions as it makes impossi...
Definition: TrigNavigationThinningSvc.cxx:241
TrigNavigationThinningSvc::syncThinning
StatusCode syncThinning(State &state) const
reset indexes in the after the thinning
Definition: TrigNavigationThinningSvc.cxx:739
HLT::TriggerElement::m_relations
std::map< Relation, std::vector< TriggerElement * > > m_relations
relations holder (features outside)
Definition: TrigNavStructure/TrigNavStructure/TriggerElement.h:143
TrigNavigationThinningSvc::dropFeatures
StatusCode dropFeatures(State &state) const
Removes references to features from the navigation structure.
Definition: TrigNavigationThinningSvc.cxx:185
CxxUtils::set
constexpr std::enable_if_t< is_bitmask_v< E >, E & > set(E &lhs, E rhs)
Convenience function to set bits in a class enum bitmask.
Definition: bitmask.h:224
TrigNavigationThinningSvc::squeeze
StatusCode squeeze(State &state) const
Remove intermediate TEs leaving very flat structure with event node, rois and terminals.
Definition: TrigNavigationThinningSvc.cxx:169
TrigNavigationThinningSvc::m_report
bool m_report
TE operations verbosity flag.
Definition: TrigNavigationThinningSvc.h:95
SG::getThinningDecision
const SG::ThinningDecisionBase * getThinningDecision(const EventContext &ctx, const std::string &key)
Retrieve the current thinning decision for key.
Definition: getThinningCache.cxx:83
TrigNavigationThinningSvc::TriggerElementFind::operator()
bool operator()(const HLT::TriggerElement *te)
Definition: TrigNavigationThinningSvc.cxx:644
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
ConfigUtils.getLabel
def getLabel(flags, key)
Definition: ConfigUtils.py:189
getLabel.h
Helper function to get a label for a feature.
HLTTriggerElement.h
TrigNavigationThinningSvc::removeFeaturelessTriggerElements
StatusCode removeFeaturelessTriggerElements(State &state, HLT::TriggerElement *te=0)
Removes all trigger elements with no features from the navigation structure.
Definition: TrigNavigationThinningSvc.cxx:468
HLT::NavigationCore::serialize
virtual bool serialize(std::vector< uint32_t > &output) const
method serizlizes the navigation structure The structure is serrizlized in following order ....
Definition: NavigationCore.cxx:81
TrigNavigationThinningSvc::restore
StatusCode restore(State &state) const
Restore the original navigation structure.
Definition: TrigNavigationThinningSvc.cxx:153
python.PyAthena.v
v
Definition: PyAthena.py:157
HLT::TrigNavStructure::getAllTEs
std::vector< TriggerElement * > & getAllTEs()
access needed by slimming tools.
Definition: TrigNavStructure.cxx:376
TrigNavigationThinningSvc::m_featureKeepSet
std::set< std::string > m_featureKeepSet
computed from above
Definition: TrigNavigationThinningSvc.h:70
HLT::TrigNavStructure::isInitialNode
static bool isInitialNode(const TriggerElement *te)
queries if node is an initial one
Definition: TrigNavStructure.cxx:501
PyPoolBrowser.expand
expand
Definition: PyPoolBrowser.py:128
a
TList * a
Definition: liststreamerinfos.cxx:10
HLT::TriggerElement::ObjectIndex::objectsEnd
index_type objectsEnd() const
to get object number in th ecollection
Definition: TrigNavStructure/Root/TriggerElement.cxx:260
HLT::TriggerElement::FeatureAccessHelper::getIndex
const ObjectIndex & getIndex() const
index in the external ojects array
Definition: TrigNavStructure/TrigNavStructure/TriggerElement.h:209
TrigNavigationThinningSvc::propagateFeaturesToChildren
StatusCode propagateFeaturesToChildren(const HLT::TriggerElement *te) const
Propagates the features on given TE to its children.
Definition: TrigNavigationThinningSvc.cxx:598
HLT::TriggerElement::FeatureAccessHelper
the FeatureAccessHelper is a class used to keep track of features attached to this TE.
Definition: TrigNavStructure/TrigNavStructure/TriggerElement.h:192
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
HLTNavDetails::IHolder
Definition: Holder.h:58
python.CaloScaleNoiseConfig.action
action
Definition: CaloScaleNoiseConfig.py:77
TrigNavigationThinningSvc::drop
StatusCode drop(State &state) const
clear the result of the slimming in the doSliming argument (vector<uint32_t>) Makes no sense to combi...
Definition: TrigNavigationThinningSvc.cxx:123
LArNewCalib_DelayDump_OFC_Cali.idx
idx
Definition: LArNewCalib_DelayDump_OFC_Cali.py:69
TrigNavigationThinningSvc::TrigNavigationThinningSvc
TrigNavigationThinningSvc(const std::string &name, ISvcLocator *pSvcLocator)
Definition: TrigNavigationThinningSvc.cxx:31
python.DecayParser.children
children
Definition: DecayParser.py:32
declareProperty
#define declareProperty(n, p, h)
Definition: BaseFakeBkgTool.cxx:15
TrigNavigationThinningSvc::dropEmptyRoIs
StatusCode dropEmptyRoIs(State &state) const
Removes RoI nodes, which do not seed anything.
Definition: TrigNavigationThinningSvc.cxx:249
TrigNavigationThinningSvc::removeTriggerElementFromVector
StatusCode removeTriggerElementFromVector(HLT::TriggerElement *te, std::vector< HLT::TriggerElement * > &v) const
Removes all instances of the supplied TriggerElement from the supplied vector.
Definition: TrigNavigationThinningSvc.cxx:489
HLT::TriggerElement::getFeatureAccessHelpers
const std::vector< FeatureAccessHelper > & getFeatureAccessHelpers() const
returns all features which ara attached to this TE
Definition: TrigNavStructure/TrigNavStructure/TriggerElement.h:238
TrigNavigationThinningSvc::m_featureExclusionList
std::vector< std::string > m_featureExclusionList
Definition: TrigNavigationThinningSvc.h:69
HLT::TrigHolderStructure::getAllHolders
std::vector< HolderType * > getAllHolders() const
Definition: TrigHolderStructure.h:40
TrigNavigationThinningSvc.h
TrigNavigationThinningSvc::m_trigDecisionTool
ToolHandle< Trig::TrigDecisionTool > m_trigDecisionTool
Definition: TrigNavigationThinningSvc.h:66
checker_macros.h
Define macros for attributes used to control the static checker.
TrigNavigationThinningSvc::initialize
virtual StatusCode initialize() override
Definition: TrigNavigationThinningSvc.cxx:70
TrigNavigationThinningSvc::m_featureInclusionList
std::vector< std::string > m_featureInclusionList
Definition: TrigNavigationThinningSvc.h:68
TrigNavigationThinningSvc::m_actionsMap
std::map< std::string, Action > m_actionsMap
Definition: TrigNavigationThinningSvc.h:91
TrigNavigationThinningSvc::dropChains
StatusCode dropChains(State &state) const
remove info not related to the specified chains
Definition: TrigNavigationThinningSvc.cxx:267
TrigNavigationThinningSvc::m_featureDropSet
std::set< std::string > m_featureDropSet
computed from above
Definition: TrigNavigationThinningSvc.h:71
TrigNavigationThinningSvcMutex.h