ATLAS Offline Software
Loading...
Searching...
No Matches
TrigNavStructure.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#include <sstream>
6#include <iostream>
7#include <algorithm>
8#include <iterator> // need it for advance
9
12
13//#define MLOG(x) if (m_log->level()<=MSG::x+m_msgLvlOffset) *m_log << (m_msgLvlOffset+MSG::x)
14//#define MLOG(x) if (m_log->level()<=MSG::x) *m_log << MSG::x
15
16using namespace HLT;
17
18template<typename T>
19std::ostream& operator<<( std::ostream& s, const std::vector<T>& v)
20{
21 s<< "[";for(auto i:v){s << i << ", ";} s << "]";
22 return s;
23}
24
25std::string TrigNavStructure::m_unspecifiedLabel = "";
26const TriggerElement* TrigNavStructure::m_unspecifiedTE = 0;
27std::recursive_mutex TrigNavStructure::s_rmutex;
28
29
31 for (auto& factory : m_factory) factory.reset();
32}
33
34/*****************************************************************************
35 *
36 * METHODS FOR NAVIGATION BUILDING
37 *
38 *****************************************************************************/
40 std::lock_guard<std::recursive_mutex> lock(getMutex());
42
43 if ( factory.empty() )
44 factory.produce(0);
45 return factory.listOfProduced().front();
46}
47
49 std::lock_guard<std::recursive_mutex> lock(getMutex());
50 const TriggerElementFactory& factory = getFactory();
51
52 if ( not factory.empty() )
53 return factory.listOfProduced().front();
54 return 0;
55}
56
57
59 std::lock_guard<std::recursive_mutex> lock(getMutex());
61
62 if ( isInitialNode(initial) ) {
63 TriggerElement* te = factory.produce(0);
64
65 // build seeds, seeededBy relations
67 initial->relate( te, TriggerElement::seedsRelation );
68 return te;
69 }
70 return 0;
71}
72
73const std::vector<TriggerElement*>& TrigNavStructure::getRoINodes( const TriggerElement* somenode ) {
75}
76
77
78// delegates all work to the more generic method
80 std::vector<TriggerElement*> list;
81 list.push_back(seednode);
82 return addNode(list, id);
83}
84
85TriggerElement* TrigNavStructure::addNode( std::vector<TriggerElement* >& seeds, unsigned int id, bool ghost, bool nofwd ) {
86 std::lock_guard<std::recursive_mutex> lock(getMutex());
88
89 TriggerElement* te = factory.produce(id, ghost, nofwd);
90
91
92 std::vector<TriggerElement* >::iterator it;
93 for ( it = seeds.begin(); it != seeds.end(); ++it ) {
94 // relate to it
95 TriggerElement* seednode = *it;
98 // add previous Features
99 te->getPreviousFeatures().insert(te->getPreviousFeatures().end(),
100 seednode->getPreviousFeatures().begin(),
101 seednode->getPreviousFeatures().end());
102
103 // copy RoI relations
104 if ( isRoINode(seednode) ) {
107 } else {
108 std::vector<TriggerElement*>::const_iterator itbegin = seednode->getRelated( TriggerElement::sameRoIRelation ).begin();
109 std::vector<TriggerElement*>::const_iterator itend = seednode->getRelated( TriggerElement::sameRoIRelation ).end();
110
111 for ( ; itbegin != itend; ++itbegin ) {
113 (*itbegin)->relate( te, TriggerElement::sameRoIRelation );
114 }
115 }
116 }
117 return te;
118}
119
120const std::vector<TriggerElement*>& TrigNavStructure::getDirectPredecessors(const TriggerElement* te) {
122}
123
124const std::vector<TriggerElement*>& TrigNavStructure::getDirectSuccessors(const TriggerElement* te) {
126}
127
128
130 if ( te->getId() == id )
131 return te;
132 std::vector<TriggerElement*>::const_iterator it;
133 const TriggerElement* found(0);
134 for ( it = TrigNavStructure::getDirectSuccessors(te).begin() ; it != TrigNavStructure::getDirectSuccessors(te).end() ; ++it ) {
135 found = getSuccessor(*it, id);
136 if (found)
137 break;
138 }
139 return found;
140}
141
142
143
144
145/*****************************************************************************
146 *
147 * PRETTY PRINTING
148 *
149 *****************************************************************************/
150
151
152void TrigNavStructure::printASCIIArt (std::string& str, const TriggerElement* te, int offset) const {
153 using namespace std;
154 const TriggerElement* initialNode = getInitialNode();
155 if ( initialNode == 0 )
156 return;
157
158 std::lock_guard<std::recursive_mutex> lock(getMutex());
159 const TriggerElementFactory& factory = getFactory();
160
161
162 if ( !te )
163 te = initialNode;
164
165 if ( te == initialNode ) {
166 // loop over all TEs which are not seeded by anything but are not initial nodes
167 const std::vector< TriggerElement* >& allTEs = factory.listOfProduced();
168 std::vector< TriggerElement* >::const_iterator allIt;
169 for (allIt = allTEs.begin(); allIt != allTEs.end(); ++allIt) {
170 if ((*allIt)->getRelated(TriggerElement::seededByRelation).size() == 0 && *allIt != getInitialNode() )
171 printASCIIArt(str, *allIt);
172 }
173 }
174
176 // pretty print
177 for ( int i=0; i < offset; i++ ) {
178 ss << "| ";
179 //cout << " ";
180 }
181 ss << "\\_";
182
183 ss << "id:" << dec << te->getId() << ";"
184 << "active:" <<(te->getActiveState() ? "1" : "0" ) << ";"
185 << "error:" <<(te->getErrorState() ? "1" : "0" ) << ";"
186 << "ptr:" << hex << te << ";"
187 << "#seeds:" << dec << te->getRelated(TriggerElement::seedsRelation).size() << ",";
188 // add all ptrs
189 std::vector<TriggerElement*>::const_iterator seedIt;
190 for ( seedIt = getDirectSuccessors(te).begin(); seedIt != getDirectSuccessors(te).end(); ++seedIt ) {
191 ss << *seedIt <<" ";
192 }
193
194 ss << "#seededBy:" << dec << te->getRelated(TriggerElement::seededByRelation).size() << ";"
195 << "#RoI:" << dec << te->getRelated(TriggerElement::sameRoIRelation).size() << ";"
196 << "#features:" << te->getFeatureAccessHelpers().size() << ";";
197 for ( auto& fea: te->getFeatureAccessHelpers() ) {
198 ss << fea;
199 }
200 ss << std::endl;
202 std::string str2;
203 str2 = ss.str();
204 str += str2;
205
206 if ( ! isTerminalNode(te) ) {
207 std::vector < TriggerElement* >::const_iterator it = te->getRelated( TriggerElement::seedsRelation ).begin();
208 std::vector < TriggerElement* >::const_iterator itEnd = te->getRelated( TriggerElement::seedsRelation ).end();
209 for ( ; it != itEnd; ++it ) {
210 std::string str2;
211 printASCIIArt(str, *it, offset+1);
212 str += str2;
213 }
214 }
215}
216
217bool TrigNavStructure::serializeTEs( std::vector<uint32_t>& output ) const {
218 std::lock_guard<std::recursive_mutex> lock(getMutex());
219 const TriggerElementFactory& factory = getFactory();
220
222
223 const std::vector<TriggerElement*>& fullList = factory.listOfProduced();
224 std::vector<TriggerElement*> all;
225 all.reserve(fullList.size());
226
227 for(std::vector<TriggerElement*>::const_iterator iter = fullList.begin(); iter != fullList.end(); ++iter) {
228 if(! (*iter)->transient() ) {
229 all.push_back( *iter );
230 }
231 }
232
233 // reserve space (in order to be efficient it should not be resized any more, this can be studied probably later to find optimum)
234 output.reserve(10*all.size());
235
236 // SERIALZE NAVIGATION STRUCTURE
237 // size (measured in elements)
238 output.push_back(all.size());
239
240 // helper keys
241 std::map<TriggerElement*, uint16_t> keys;
242
243 const TriggerElement* previous = 0;
244 std::vector<TriggerElement*>::const_iterator it;
245 uint16_t indexForTe = 0;
246 for ( it = all.begin(); it != all.end(); ++it ) {
247 // first we stream pointer as it (this is already an unique key for this TE)
248 // output.push_back((unsigned int)(*it));
249 (*it)->serialize(output, keys, previous);
250 previous = *it;
251 keys[*it] = indexForTe;
252 indexForTe++;
253 }
254
255 return true;
256}
257
258/*****************************************************************************
259 *
260 * DESERIALIZATION
261 *
262 *****************************************************************************/
263
264bool TrigNavStructure::deserializeTEs(std::vector<uint32_t>::const_iterator& start, unsigned int totalSize) {
265 std::lock_guard<std::recursive_mutex> lock(getMutex());
267
268 factory.reset();
269
270 std::vector<uint32_t>::const_iterator& inputIt = start;
271 const size_t payloadSize = *inputIt++;
272
273 if ( totalSize < payloadSize ) { // not all TEs were recorded
274 std::cerr << "size of the navigation payload smaller than the one required to save TEs. " << totalSize << " < " << payloadSize << std::endl;
275 return false;
276 }
277
278
279 const unsigned int size = *inputIt++; // size in terms of number of TEs
280 TriggerElement* previous = 0;
281 std::map<uint16_t, TriggerElement* > keys;
282
283 for ( unsigned int i = 0; i < size; ++i ) {
284 // create new TE
285 TriggerElement* te = factory.produce(TriggerElement::enquireId(inputIt)); //
286 te->deserialize(inputIt, keys, previous);
287 previous = te;
288 // keys table for deserialization of other TEs
289 keys[i] = te;
290 }
291
292 if ( not factory.empty() ) {
293 // rebuild sameRoI relations (this can't be done by TEs deserialization)
294 TriggerElement* initialNode = getInitialNode();
295 std::vector<TriggerElement*>::const_iterator roiTEit;
296 for ( roiTEit = getDirectSuccessors(initialNode).begin();
297 roiTEit != getDirectSuccessors(initialNode).end(); ++roiTEit ) {
298 fillSameRoIRelation((*roiTEit), (*roiTEit));
299 }
300 } // else this is empty structure, but this shoudl not bother us as it is may well be valid case
301
302 return true;
303}
304
305
306
308 if ( ! isRoINode(te) ) {
311 }
312 if ( isTerminalNode(te) )
313 return;
314 else { // traverse all sub nodes
315 std::vector<TriggerElement*>::const_iterator it;
316 for ( it = getDirectSuccessors(te).begin(); it != getDirectSuccessors(te).end(); ++it ) {
317 fillSameRoIRelation(roi, *it);
318 }
319 }
320}
321
322/*****************************************************************************
323 *
324 * QUERIES
325 *
326 *****************************************************************************/
327
328void TrigNavStructure::getAllRoIThresholdTEs( std::vector< TriggerElement* >& output ) const
329{
330 const TriggerElement* initNode = getInitialNode();
331 // get first layer of TEs representing the RoIs themselves (not the thresholds!)
332 const std::vector<TriggerElement*>& rois = getDirectSuccessors(initNode);
333 for ( const TriggerElement* roi_te : rois ) {
334 // get threshold-like TEs:
335 const std::vector<TriggerElement*>& tes = getDirectSuccessors( roi_te );
336 for (TriggerElement* te : tes) {
337 output.push_back( te );
338 }
339 }
340}
341
343 std::vector< TriggerElement* >& output,
344 const bool activeOnly) const {
345 std::lock_guard<std::recursive_mutex> lock(getMutex());
346 const TriggerElementFactory& factory = getFactory();
347
348 if ( not factory.listOfProduced(id).empty() ) {
349 std::back_insert_iterator<std::vector<TriggerElement*> > outputIt( output );
350
351 // 2 cases: only active ones, and all
352 // one can consider sorting the TEs according to the activation status and then assume that collection is sorted
353 // the same functor can be used as in copy_if
354 if (activeOnly)
355 remove_copy_if ( factory.listOfProduced(id).begin(), factory.listOfProduced(id).end(), outputIt, isNotActive );
356 else
357 copy ( factory.listOfProduced(id).begin(), factory.listOfProduced(id).end(), outputIt );
358 }
359}
360
361void TrigNavStructure::getAll ( std::vector< TriggerElement* >& output, const bool activeOnly) const {
362 std::lock_guard<std::recursive_mutex> lock(getMutex());
363 const TriggerElementFactory& factory = getFactory();
364
365 if ( not factory.listOfProduced().empty() ) {
366 std::back_insert_iterator<std::vector<TriggerElement*> > outputIt( output );
367 if (activeOnly)
368 remove_copy_if ( factory.listOfProduced().begin(), factory.listOfProduced().end(), outputIt, isNotActive );
369 else
370 copy ( factory.listOfProduced().begin(), factory.listOfProduced().end(), outputIt );
371 }
372}
373
374std::vector<TriggerElement*>& TrigNavStructure::getAllTEs() {
375 std::lock_guard<std::recursive_mutex> lock(getMutex());
377
378 return factory.listOfProduced();
379}
380
381const std::vector<TriggerElement*>& TrigNavStructure::getAllTEs() const {
382 std::lock_guard<std::recursive_mutex> lock(getMutex());
383 const TriggerElementFactory& factory = getFactory();
384
385 return factory.listOfProduced();
386}
387
388unsigned int TrigNavStructure::countAllOfType( const te_id_type id, const bool activeOnly ) const {
389 std::lock_guard<std::recursive_mutex> lock(getMutex());
390 const TriggerElementFactory& factory = getFactory();
391
392 if ( activeOnly )
393 return factory.listOfProduced(id).size()
394 - count_if(factory.listOfProduced(id).begin(), factory.listOfProduced(id).end(), isNotActive);
395 //else
396 return factory.listOfProduced(id).size();
397}
398
399
400// need to deal with comples TopoTEs
401// algorithm is realying on navigation i.e. does not check anything like
402// RoIDescriptor etc. only just navigation nodes
403// it packs all the RoINodes in to one vector does sort on it and the unique STL algos
404// if size of temp vector is unchanged (all were unique) the there are no common RoIs
405// Since this method is prepared to get RoI nodes one can use it for checking if the
406// given TE is originating from given RoI, assume noone wil lquery it with initialNode
407//
408// in future on can revise this algorithm depending on usecases
409// if most cases the NON Topo TEs will be chcked (only one RoI for each) then this can be simplified
410// if RoI nodes will not be used here then security checks fro that can be abandonned)
411// however this algo is N log(N) in current shape
412
413
415 std::vector<const TriggerElement*> vecRoINodes;
416
417 if ( isRoINode(te1) ) {
418 vecRoINodes.push_back(te1);
419 } else {
420 std::back_insert_iterator<std::vector<const TriggerElement*> > outputIt( vecRoINodes );
422 }
423 if ( isRoINode(te2) ) {
424 vecRoINodes.push_back(te2);
425 } else {
426 std::back_insert_iterator<std::vector<const TriggerElement*> > outputIt( vecRoINodes );
428 }
429 // sort (by pointers, it is OK do not be scared)
430 sort(vecRoINodes.begin(), vecRoINodes.end());
431
432 std::vector<const TriggerElement*>::const_iterator it;
433 it = adjacent_find(vecRoINodes.begin(), vecRoINodes.end());
434
435 if ( it == vecRoINodes.end() )
436 return false;
437
438 return true;
439}
440
441
443 return ! haveCommonRoI(te1, te2);
444}
445
446
448 std::vector<TriggerElement*> vecRoINodes1 = getRoINodes(te1);
449 std::vector<TriggerElement*> vecRoINodes2 = getRoINodes(te2);
450 sort(vecRoINodes1.begin(), vecRoINodes1.end());
451 sort(vecRoINodes2.begin(), vecRoINodes2.end());
452 return vecRoINodes1 == vecRoINodes2;
453}
454
455
456// similar to haveCommonRoI but other relation is queried
457// and is simpler (no RoI special case)
458
460 std::vector<const TriggerElement*> vecRoINodes;
461 std::back_insert_iterator<std::vector<const TriggerElement*> > outputIt( vecRoINodes );
462
464 te1->getRelated(TriggerElement::seededByRelation).end(), outputIt);
465
467 te2->getRelated(TriggerElement::seededByRelation).end(), outputIt);
468
469 // sort (by pointers, it is OK do not be scared) & uniq
470 sort(vecRoINodes.begin(), vecRoINodes.end());
471
472 std::vector<const TriggerElement*>::iterator it;
473 it = adjacent_find(vecRoINodes.begin(), vecRoINodes.end());
474 if ( it == vecRoINodes.end() ) // after uniquing we still are
475 return false;
476 return true;
477}
478
480 return ! haveCommonSeed(te1, te2);
481}
482
484 return te1->getId() < te2->getId();
485}
486
488 return te1->getId() > te2->getId();
489}
490
491bool TrigNavStructure::hasIdFromTheSet ( const TriggerElement* te, std::vector<unsigned int> ids ) {
492 if ( find(ids.begin(), ids.end(), te->getId()) != ids.end() )
493 return true;
494 return false;
495}
496
497
498
500 if ( te->getRelated(TriggerElement::seededByRelation).empty() and te->getId() == 0 )
501 return true;
502 return false;
503}
504
506 if ( te->getRelated( TriggerElement::seededByRelation ).empty() ) // this s initial node
507 return false;
508
509 TriggerElement* whoSeedsMe = *(te->getRelated( TriggerElement::seededByRelation ).begin());
510 if ( isInitialNode(whoSeedsMe) )
511 return true;
512 return false;
513}
514
516 if ( te->getRelated( TriggerElement::seedsRelation ).empty() )
517 return true;
518 return false;
519}
520
521
522
523
525 using namespace std;
526 if ( te1->getId() != te2->getId() ) {
527 return false; // distinc Id
528 }
529
530 if ( ( isTerminalNode(te1) && isTerminalNode(te2) ) )
531 return true; // no more checks needs to be done
532 else if ( isTerminalNode(te1) || isTerminalNode(te2) )
533 return false; // one of both is terminal while another is not (case when both are terminal is covered above)
534
535 // continue subchecks otherwise (both nonterminal)
536
537 // folow seeds otherwise
539 return false;
540
541 std::vector<TriggerElement*>::const_iterator seededByTe1 = te1->getRelated(TriggerElement::seedsRelation).begin();
542 std::vector<TriggerElement*>::const_iterator seededByTe2 = te2->getRelated(TriggerElement::seedsRelation).begin();
543
544 for ( ; seededByTe1 != te1->getRelated(TriggerElement::seedsRelation).end(); ++seededByTe1, ++seededByTe2 ) {
545 if (isCompatibleTree(*seededByTe1, *seededByTe2) == false) // grrr,wrrr recursive call here
546 return false;
547 }
548 // there I should probably check as well the Features attached to the TEs
549
550 return true;
551}
552
553
554
556 std::lock_guard<std::recursive_mutex> lock(getMutex());
558 const TriggerElementFactory& oldFactory = nav->getFactory();
559
560
561 // basic checks first
562 if ( oldFactory.listOfProduced().size() > factory.listOfProduced().size() )
563 return false;
564
565 std::vector< TriggerElement* >::const_iterator old = oldFactory.listOfProduced().begin();
566 std::vector< TriggerElement* >::iterator me = factory.listOfProduced().begin();
567 // int i = 0;
568 do {
569 (*me)->setActiveState((*old)->getActiveState());
570 ++me;
571 ++old;
572 } while ( old != oldFactory.listOfProduced().end() );
573 return true;
574}
575
576
577
578
579
580bool TrigNavStructure::combine(std::vector<unsigned int>& types,
581 std::vector<std::vector<TriggerElement*> >& output,
582 unsigned int maxResults, bool onlyActive)
583{
584 // It should be empty anyways, but just in case...
585 output.clear();
586
587 std::vector< std::vector<TriggerElement*> > input;
588 std::vector< std::vector<std::pair<unsigned int, unsigned int> > > newIdxs;
589
590 for (std::vector<unsigned int>::iterator type = types.begin();
591 type != types.end(); ++type) {
592 // Use the previous iteration's output as the input for this one
593 std::vector< std::vector<TriggerElement*> > input = output;
594 std::vector< std::vector<std::pair<unsigned int, unsigned int> > > currentIdxs = newIdxs;
595
596 // Remove the old n-tuples
597 output.clear();
598 newIdxs.clear();
599 // Re-populate output with the (n+1)-tuples. If error return false immediately...
600 if (not addOneLevel(input, currentIdxs, *type, output, newIdxs,
601 maxResults, onlyActive)) return false;
602 }
603
604 return true;
605}
606
607
608bool TrigNavStructure::addOneLevel(std::vector< std::vector<TriggerElement*> >& currentCombs,
609 std::vector< std::vector<std::pair<unsigned int, unsigned int> > >& currentIdxs,
610 unsigned int type,
611 std::vector<std::vector<TriggerElement*> >& newCombs,
612 std::vector< std::vector<std::pair<unsigned int, unsigned int> > >& newIdxs,
613 unsigned int maxResults, bool onlyActive)
614{
615 // Get the list of TEs of the desired type from the event
616 std::vector<TriggerElement*> newTEs;
617 getAllOfType(type, newTEs, onlyActive);
618
619 if (currentCombs.size() == 0) {
620
621
622 for (unsigned int j = 0; j < newTEs.size(); j++) {
623
624 std::vector<TriggerElement*> cbs;
625 cbs.push_back(newTEs[j]);
626 newCombs.push_back(std::move(cbs));
627
628 // Do the same for the auxiliary data
629 std::vector<std::pair<unsigned int, unsigned int> > ti;
630 ti.emplace_back(type, j);
631 newIdxs.push_back(std::move(ti));
632 }
633 return 1;
634 }
635
636 // Loop over existing combinations, adding the newTEs one by one
637 for (unsigned int i = 0; i < currentCombs.size(); i++) {
638
639 // Get the current combinations
640 std::vector<TriggerElement*>& comb = currentCombs[i];
641
642 // Get the auxiliary data that stores the type and index of each TE.
643 // "index" is the index of the TE in the vector of TEs returned by getallOfType - it
644 // is assumed to stay the same between calls of addOneLevel within the same combine() call
645 std::vector<std::pair<unsigned int, unsigned int> >& ti = currentIdxs[i];
646
647 // The auxiliary data is used to avoid double-counting: we make sure that if multiple
648 // TEs of the same type appear in the n-tuple, they are always such that
649 // their indices in the getAllOfType vector increases with position in the n-tuple.
650 // I.E if we have TEs (e0, m1, e1, e2) and e0, e1 and e2 are of the same type,
651 // we only take the combination such that e0 comes before e1 and e1 before e2 in
652 // the getAllOfType vector of "e".
653
654 // To implement this, go through the auxiliary data first and get the index
655 // of the last TE of the current type that is already in the ntuple:
656 int first = 0;
657
658 for (unsigned int j = comb.size(); j > 0; j--)
659 if (ti[j - 1].first == type) {
660 first = ti[j - 1].second;
661 break;
662 }
663
664 // Now instead of considering all the TEs in newTEs, only loop over those with
665 // index > first.
666
667 for (unsigned int j = first + 1; j < newTEs.size(); j++) {
668
669 TriggerElement* te = newTEs[j];
670
671 // Continue if the TE overlaps with any of the TEs in the existing combination
672 if (overlaps(te, comb)) continue;
673
674 // Add the new TE to the current combination
675 comb.push_back(te);
676
677 // Add the current combination to the list for the next level
678 newCombs.push_back(comb);
679
680 // Restore the current combination for the next iteration
681 comb.pop_back();
682
683 // Do the same for the auxiliary data
684 ti.push_back(std::pair<unsigned int, unsigned int>(type, j));
685 newIdxs.push_back(ti);
686 ti.pop_back();
687
688 // If the limit is exceeded, return immediately.
689 if (maxResults > 0 && newCombs.size() >= maxResults) {
690 return true;
691 }
692 }
693 }
694
695 return true;
696}
697
698bool TrigNavStructure::overlaps(const TriggerElement* te1, const std::vector<TriggerElement*>& teVec) const {
699 for (std::vector<TriggerElement*>::const_iterator te2 = teVec.begin(); te2 != teVec.end(); ++te2)
700 if (overlaps(te1, *te2)) return true;
701
702 return false;
703}
704
705bool TrigNavStructure::overlaps(const TriggerElement* te1, const TriggerElement* te2) const {
706 if (te1 == te2) return true;
707 if (haveCommonRoI(te1, te2)) return true;
708
709 return false;
710}
711
712bool TrigNavStructure::getTopologicallySpannedBy( const TriggerElement* te, const std::vector<unsigned int>& types,
713 std::vector<const TriggerElement*>& children, const bool activeOnly ) const {
714 if ( getDirectPredecessors(te).size() != types.size() ) {
715 return false;
716 }
717
718 for ( unsigned i = 0 ; i < types.size(); ++i ) {
719 const TriggerElement* child = getSuccessor( getDirectPredecessors(te)[i], types[i]);
720 if(child!=0) {
721 if(activeOnly && !child->getActiveState()) {
722 children.clear();
723 return true;
724 }
725 children.push_back(child);
726 } else {
727 children.clear();
728 return true;
729 }
730 }
731 return true;
732}
733
735{
736 unsigned int n_features = 0;
737 // push back all featureAccessHelpers from source to destiny TE
738 for ( std::vector< TriggerElement::FeatureAccessHelper >::const_iterator it = sourceTE->getFeatureAccessHelpers().begin();
739 it != sourceTE->getFeatureAccessHelpers().end(); ++it ) {
740 destTE->addFeature(*it);
741 n_features++;
742 }
743 return n_features;
744
745}
746
747
748
749/*****************************************************************************
750 *
751 * very important RESET
752 *
753 *****************************************************************************/
754void TrigNavStructure::reset(bool inFinalize) {
755 std::lock_guard<std::recursive_mutex> lock(getMutex());
756 if (inFinalize) {
757 for (auto& factory : m_factory) factory.reset();
758 for (auto& holder : m_holderstorage) holder.reset();
759 } else {
760 getFactory().reset();
762 }
763}
764
765
767 std::lock_guard<std::recursive_mutex> lock(getMutex());
768 const TrigHolderStructure& holderstorage = getHolderStorage();
769
770 return holderstorage.getSubTypeIndex(clid,sti_or_label);
771}
772
773std::string TrigNavStructure::label(class_id_type clid, const index_or_label_type& sti_or_label) const {
774 std::lock_guard<std::recursive_mutex> lock(getMutex());
775 const TrigHolderStructure& holderstorage = getHolderStorage();
776
777 return holderstorage.getLabel(clid,sti_or_label);
778}
779
780
782
783
785 bool single = true; bool recursively = false;
786 bool status = getFeatureAccessors(te, clid,index_or_label,single,features,recursively);
787
788 if(status && !features.empty()){
789 return features.front();
790 }
791 return TriggerElement::FeatureAccessHelper(); // not found
792}
793
794
796 const index_or_label_type& index_or_label, const TriggerElement*& sourceTE) const {
797
799 bool single = true; bool recursively = true;
800 bool status = getFeatureAccessors(startTE, clid,index_or_label,single,features,recursively,sourceTE);
801
802 if(status && !features.empty()){
803 return features.front();
804 }
805 return TriggerElement::FeatureAccessHelper(); // not found
806}
807
809 const index_or_label_type& index_or_label,
810 bool only_single_feature,
812 const TriggerElement*& source,
813 std::string& sourcelabel ) const {
814
815 // ATH_MSG_VERBOSE("getFeatureAccessorsSingleTE: looking for:" << (only_single_feature ? "one object" : "many objects" ) << " of CLID: " << clid
816 // << " label: \"" << label << "\"" << " starting from TE: " << te->getId());
817
818 int size = te->getFeatureAccessHelpers().size();
819
820 // loop the feature access helper in order depending of type of request (i.e. if single featyure needed then loop from back, if all then loop from the front)
821 for ( int it = ( only_single_feature ? size-1 : 0 ); it != (only_single_feature ? -1 : size ); only_single_feature ? it--: it++ ) {
822 auto& fea = te->getFeatureAccessHelpers().at(it);
823 //ATH_MSG_VERBOSE("getFeatureAccessors: in a loop over FeatureAccessHelpers got ObjectIndex " << fea);
824
825 if(matchFeature(fea,clid,index_or_label)){
826 sourcelabel = label(clid,fea.getIndex().subTypeIndex());
827 source = te;
828 features.push_back(fea);
829
830 // ATH_MSG_DEBUG("getFeatureAccessors: matching feature found in te: " << *te << " index: " << fea);
831 // now the ending (depends on the "single" flag)
832 if ( only_single_feature )
833 break;
834 }
835 } // end of loop over feature access helpers of this TE
836
837 return true;
838}
839
841 const index_or_label_type& index_or_label,
842 bool only_single_feature,
844 bool travel_backward_recursively,
845 const TriggerElement*& source,
846 std::string& sourcelabel ) const {
847
848 bool singleTEstatus = getFeatureAccessorsSingleTE(te,clid,index_or_label,only_single_feature,features,source,sourcelabel);
849
850 if(!singleTEstatus){
851 // MLOG(WARNING) << "getFeatureAccessorsSingleTE() returned false" << endmsg;
852 }
853
854
855
856 if ( ! travel_backward_recursively ) {
857 return true;
858 }
859
860 // stop digging deeper if this is an RoI node already
861 if ( isRoINode(te) ) {
862 return true;
863 }
864
865 // return if a feature(s) is/are found
866 if ( ! features.empty() ) {
867 return true;
868 }
869
870 // recurse deeper
871 bool recursion_status = true;
872 for( TriggerElement* predecessor: getDirectPredecessors(te) ) {
873
874 TriggerElement::FeatureVec features_in_branch;
875
876 recursion_status = recursion_status && getFeatureAccessors( predecessor, clid, index_or_label,
877 only_single_feature, features_in_branch,
878 travel_backward_recursively,
879 source, sourcelabel);
880 features.insert(features.end(), features_in_branch.begin(), features_in_branch.end());
881 }
882
883 if ( only_single_feature && ( features.size() > 1 || recursion_status == false) ) {
884 // MLOG(DEBUG) << "getFeatureAccessors: looking for object of CLID: " << clid
885 // << " label: \"" << label << "\"" << " found several objects matching criteria while can only return back one, this is ambiguous" << endmsg;
886
887 if ( getDirectPredecessors(te).size() > 1 ) // mark bifurcation point as to where one can start again
888 source = te;
889
890 return false;
891 }
892 return true;
893}
894
895
897 //we always require the CLID to match
898 if(fea.getCLID() != clid) return false;
899
900 if(index_or_label.index() == 0){
901 //subtype index case: if argument is invalid_sub_index we always match, else require exact match
902 auto index = std::get<sub_index_type>(index_or_label) ;
903 return (index == invalid_sub_index || index == fea.getIndex().subTypeIndex());
904 }
905
906 if(index_or_label.index() == 1){
907 //label case: if argument is "" we always match, else require exact match (via)
908 auto label = std::get<std::string>(index_or_label);
909 if(label.empty()){
910 return true;
911 }
912 label = (label == "!") ? "" : label;
913 auto sub = subType(clid,label);
914 if(sub == invalid_sub_index) return false;
915 return matchFeature(fea,clid,sub);
916 }
917 return false;
918}
919
920
922 std::lock_guard<std::recursive_mutex> lock(getMutex());
923 const TrigHolderStructure& holderstorage = getHolderStorage();
924
925 return holderstorage.getHolderForFeature(fea);
926}
static Double_t fs
static Double_t ss
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
static unsigned int totalSize(const MultiDimArray< T, N > &ht)
static const std::vector< std::string > types
std::string getLabel(class_id_type clid, const index_or_label_type &stiOrLabel) const
HolderType * getHolderForFeature(const TriggerElement::FeatureAccessHelper &fea) const
sub_index_type getSubTypeIndex(class_id_type clid, const index_or_label_type &stiOrLabel) const
static bool haveCommonSeed(const TriggerElement *te1, const TriggerElement *te2)
checks that there is any common predecessor of two TriggerElements
unsigned int countAllOfType(const te_id_type id, const bool activeOnly=true) const
The query counting a collection of all TriggerElement of a given type.
bool overlaps(const TriggerElement *t1, const TriggerElement *t2) const
Check overlap between trigger elements (pointer equality or RoI overlap)
static bool isCompatibleTree(const TriggerElement *te1, const TriggerElement *te2)
check compatibility of 2 navigation structures
static bool haveDistinctRoI(const TriggerElement *te1, const TriggerElement *te2)
inversion of haveCommonRoI
static bool haveAllCommonRoIs(const HLT::TriggerElement *te1, const HLT::TriggerElement *te2)
bool matchFeature(const TriggerElement::FeatureAccessHelper &fea, class_id_type clid, const index_or_label_type &index_or_label) const
void getAllRoIThresholdTEs(std::vector< TriggerElement * > &output) const
The query returns a vector of all TriggerElements that represent a LVL1 RoI threshold.
SG::SlotSpecificObj< TriggerElementFactory > m_factory
factory of trigger elements (one per processing slot)
static bool isInitialNode(const TriggerElement *te)
queries if node is an initial one
virtual void reset(bool inFinalize=false)
resets all the navigation, goes to the factory and asks to withdraw all produced objects
void printASCIIArt(std::string &str, const TriggerElement *te=0, int offset=0) const
pretty printing of the navigational structure (heavy)
static std::recursive_mutex s_rmutex
TriggerElement::FeatureAccessHelper getFeature(const TriggerElement *te, class_id_type clid, const index_or_label_type &index_or_label) const
typeless feature access metod
bool addOneLevel(std::vector< std::vector< TriggerElement * > > &currentCombs, std::vector< std::vector< std::pair< unsigned int, unsigned int > > > &currentIdxs, unsigned int type, std::vector< std::vector< TriggerElement * > > &newCombs, std::vector< std::vector< std::pair< unsigned int, unsigned int > > > &newIdxs, unsigned int maxResults=1000, bool onlyActive=1)
Helper method for "combine": add one "level" of multiplicity to the results.
bool propagateDeactivation(const TrigNavStructure *nav)
propagates deactivation of TE state This finction should be used after Trigger is rerurn on L2 and th...
sub_index_type subType(class_id_type clid, const index_or_label_type &sti_or_label) const
static const TriggerElement * getSuccessor(const TriggerElement *te, unsigned int id)
returns successor of given type beeing seeded from this TE
const BaseHolder * getHolder(const TriggerElement::FeatureAccessHelper &fea) const
bool serializeTEs(std::vector< uint32_t > &output) const
method serizlizes the navigation structure
std::vector< TriggerElement * > & getAllTEs()
access needed by slimming tools.
void getAllOfType(const te_id_type id, std::vector< TriggerElement * > &output, const bool activeOnly=true) const
The query returning a collection of all TriggerElements if name is given.
virtual bool getFeatureAccessors(const TriggerElement *te, class_id_type clid, const index_or_label_type &index_or_label, bool only_single_feature, TriggerElement::FeatureVec &features, bool travel_backward_recursively, const TriggerElement *&source=m_unspecifiedTE, std::string &sourcelabel=m_unspecifiedLabel) const
TriggerElement * addNode(TriggerElement *seed, unsigned int id)
adds nodes seeded form the one given as an argument,
static bool haveCommonRoI(const TriggerElement *te1, const TriggerElement *te2)
does this 2 share RoI
TriggerElement * addRoINode(TriggerElement *initial)
gets RoI node (attached to initial)
void fillSameRoIRelation(TriggerElement *roi, TriggerElement *te)
rebuilds the sameRoIRelation between trigger elements (used internally by deserialize)
bool getTopologicallySpannedBy(const TriggerElement *te, const std::vector< unsigned int > &types, std::vector< const TriggerElement * > &children, const bool activeOnly=true) const
gets the TEs whose predecessors were used to built a given topological TE
bool combine(std::vector< unsigned int > &types, std::vector< std::vector< TriggerElement * > > &output, unsigned int maxResults=1000, bool onlyActive=true)
For Algorithms: return all the possible n-tuples of TE* objects (te0, te1..., ten)
static bool hasIdFromTheSet(const TriggerElement *te, std::vector< unsigned int > ids)
simple helper
SG::SlotSpecificObj< TrigHolderStructure > m_holderstorage
structure for feature holders (one per processing slot)
unsigned int copyAllFeatures(const TriggerElement *sourceTE, TriggerElement *destTE)
gets all features from the sourceTE and copies a reference (FeatureAccessHelper) to the destTE
bool deserializeTEs(std::vector< uint32_t >::const_iterator &start, unsigned int totalSize)
static bool isNotActive(const TriggerElement *te)
helper for the STL
static bool decreasingOrderByTEId(const TriggerElement *te1, const TriggerElement *te2)
void getAll(std::vector< TriggerElement * > &output, const bool activeOnly=true) const
The query returning a collection of all TriggerElements.
virtual bool getFeatureAccessorsSingleTE(const TriggerElement *te, class_id_type clid, const index_or_label_type &index_or_label, bool only_single_feature, TriggerElement::FeatureVec &features, const TriggerElement *&source, std::string &sourcelabel) const
TriggerElement * getInitialNode()
gets initial node, if node is not there then it is created on fly
TriggerElementFactory & getFactory()
static bool increasingOrderByTEId(const TriggerElement *te1, const TriggerElement *te2)
for sorting TriggerElements according to their id
static const std::vector< TriggerElement * > & getRoINodes(const TriggerElement *somenode)
gets all RoI type nodes seeding indirectly this TriggerElement
TriggerElement::FeatureAccessHelper getFeatureRecursively(const TriggerElement *startTE, class_id_type clid, const index_or_label_type &index_or_label, const TriggerElement *&sourceTE) const
recursive search for features the function is similar to the above butif th features is not found at ...
static const std::vector< TriggerElement * > & getDirectPredecessors(const TriggerElement *te)
returns list of direct predecessors (nodes seeding me)
static bool haveDistinctSeed(const TriggerElement *te1, const TriggerElement *te2)
inversion of haveCommonSeed
static bool isTerminalNode(const TriggerElement *te)
queries if node is terminal (no more TriggerElement are seeded by it)
static const std::vector< TriggerElement * > & getDirectSuccessors(const TriggerElement *te)
returns list of direct predecessors (nodes I seed)
std::recursive_mutex & getMutex()
static bool isRoINode(const TriggerElement *te)
queries if node is an RoI type one
TrigHolderStructure & getHolderStorage()
std::string label(class_id_type clid, const index_or_label_type &sti_or_label) const
The factory of TriggerElements Creation in controlled way.
const std::vector< TriggerElement * > & listOfProduced() const
TriggerElement * produce(unsigned int id, bool ghost=false, bool nofwd=false)
the FeatureAccessHelper is a class used to keep track of features attached to this TE.
const ObjectIndex & getIndex() const
index in the external ojects array
sub_index_type subTypeIndex() const
to get collection index
TriggerElement is the basic ingreedient of the interface between HLT algorithms and the navigation It...
static unsigned int enquireId(std::vector< uint32_t >::const_iterator &inputIt)
@ sameRoIRelation
equilateral relation of all TEs rooted in one RoI
const std::vector< TriggerElement * > & getRelated(Relation rel) const
returns reference to the likns to other TriggerElements related by relation r
bool getActiveState() const
get state of the TriggerElement
const std::vector< FeatureAccessHelper > & getFeatureAccessHelpers() const
returns all features which ara attached to this TE
void addFeature(class_id_type clid, const ObjectIndex &index, bool forget=false)
add helper for new feature
const std::vector< FeatureAccessHelper > & getPreviousFeatures() const
void deserialize(std::vector< uint32_t >::const_iterator &inputIt, const std::map< uint16_t, TriggerElement * > &keys, const TriggerElement *previous)
deserialization
void relate(TriggerElement *te, Relation r)
reates given TE to other TE
STL class.
std::string find(const std::string &s)
return a remapped string
Definition hcg.cxx:138
It used to be useful piece of code for replacing actual SG with other store of similar functionality ...
const FeatureContainerInit< FEATURE, CONTAINER > RegisterFeatureContainerTypes< FEATURE, CONTAINER >::s
std::variant< sub_index_type, std::string > index_or_label_type
static const index_type invalid_sub_index
MsgStream & operator<<(MsgStream &m, const Navigation &nav)
Definition index.py:1
STL namespace.