ATLAS Offline Software
Loading...
Searching...
No Matches
ChainGroup.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5/**********************************************************************************
6 * @Project: TrigDecisionTool
7 * @Package: TrigDecisionTool
8 * @Class : ChainGroup
9 *
10 * @brief simple container to hold trigger chains
11 *
12 * @author Michael Begel <michael.begel@cern.ch> - Brookhaven National Laboratory
13 * @author Alexander Mann <mann@cern.ch> - University of Goettingen
14 *
15 ***********************************************************************************/
16
17
18#include "CxxUtils/bitmask.h"
30
34#include <limits>
35#include <regex>
36#include <ranges>
37
38
39using namespace std;
40
41Trig::ChainGroup::ChainGroup(const std::vector< std::string >& triggerNames,
43 :
44 m_patterns(triggerNames),
45 m_cgm(parent)
46{}
47
49 std::vector< std::string > v;
50 v.resize(patterns().size()+rhs.patterns().size());
51 merge(patterns().begin(), patterns().end(),
52 rhs.patterns().begin(), rhs.patterns().end(),
53 v.begin());
54 return *(cgm().createChainGroup(v));
55}
56
57
61
63 return !(*this==rhs);
64}
65
66void Trig::ChainGroup::addAlias(const std::string& alias) {
67 cgm().createChainGroup(patterns(),alias);
68}
69
71 // thread-safe because assert_decision is locked
72 auto nonconst_cgm ATLAS_THREAD_SAFE = const_cast<Trig::CacheGlobalMemory*>(&cgm());
73 nonconst_cgm->assert_decision();
74
75 return cgm();
76}
77
78bool Trig::ChainGroup::HLTResult(const std::string& chain, unsigned int condition) const {
79 bool chainRESULT = false;
80 if (chain.empty()) return chainRESULT;
81 const HLT::Chain* fchain=cgm_assert().chain(chain);
82 if (fchain==nullptr) return chainRESULT;
83
84
85 bool RAW = fchain->chainPassedRaw();
86 const bool PASSTHROUGH = fchain->isPassedThrough();
87 const bool PRESCALED = fchain->isPrescaled();
88 const bool RESURRECTED = fchain->isResurrected();
89
90 // Resurrection overwrites the value in RAW but sets the RESURRECTED flag
91 // we should therefore fix RAW appropriately
92 if (~condition & TrigDefs::allowResurrectedDecision) {
93 if (RESURRECTED) {
94 RAW=false;
95 }
96 }
97 //
98 // Do we accept the result?
99 //
100 if (condition & TrigDefs::passedThrough) {
101 if (PASSTHROUGH) {chainRESULT=true;}
102 }
103 if (condition & TrigDefs::requireDecision) {
104 if (RAW && !PRESCALED) {chainRESULT=true;}
105 if ( condition & TrigDefs::allowResurrectedDecision ) { // prescaling does not matter for RR (it runs in fact because of that
106 if (RAW) {chainRESULT=true;}
107 }
108
109 }
110 // respects resurrection -- is this the appropriate behavior???
111 if (condition & TrigDefs::eventAccepted) {
112 if ( (RAW && !PRESCALED) || PASSTHROUGH) {chainRESULT=true;}
113 }
114 ATH_MSG_DEBUG("ChainGroup::HLTResult Counter = " << std::setw(4) << fchain->getChainCounter()
115 << " name = " << fchain->getChainName()
116 << " level = " << fchain->getConfigChain()->level()
117 << " success (raw) = " << fchain->chainPassedRaw()
118 << " pass-through = " << fchain->isPassedThrough()
119 << " prescaled = " << fchain->isPrescaled()
120 << " rerun = " << fchain->isResurrected()
121 << " lastActiveStep = " << fchain->getChainStep()
122 << " name = " << std::setw(35) << fchain->getChainName()
123 << " result = " << chainRESULT);
124
125 return chainRESULT;
126}
127
128// this logic fails for passthrough especially with enforceLogicalFlow!!!!
129bool Trig::ChainGroup::L1Result(const std::string& item, unsigned int condition) const {
130 bool r = false;
131 if (item.empty()) return r;
132 if (item.find(',')!=std::string::npos) {
133 for(const std::string& thisItem : convertStringToVector(item)) {
134 if(L1Result(thisItem,condition)) return true;
135 }
136 return false;
137 }
138 const LVL1CTP::Lvl1Item* fitem=cgm_assert().item(item);
139 if (fitem==nullptr) {
140 return r;
141 }
142 ATH_MSG_DEBUG(" success (raw) = " << fitem->isPassedBeforePrescale()
143 << " prescaled = " << fitem->isPrescaled()
144 << " vetoed = " << fitem->isVeto()
145 << " name = " << std::setw(35) << fitem->name());
146
147 r = fitem->isPassedAfterVeto();
148
150 r = fitem->isPassedBeforePrescale();
151
152 //if (condition & TrigDefs::eventAccepted)
153 // r = fitem->isPassedAfterVeto();
154 //else
155 // r = fitem->isPassedBeforePrescale();
156 return r;
157}
158
159
160std::string Trig::ChainGroup::getLowerName(const std::string& name) const {
161 if ( name.empty() )
162 return name;
163 const TrigConf::HLTChain* cchain = cgm().config_chain(name);
164 if (cchain==nullptr){
165 ATH_MSG_WARNING(" Lower chain name used by: " << name << " is not in the configuration ");
166 return "BAD NAME";
167 }
168 return cchain->lower_chain_name();
169}
170
171// Helper to get decision of a single chain (private)
172bool Trig::ChainGroup::isPassed(const TrigConf::HLTChain& chain, unsigned int condition) const
173{
174 bool result = HLTResult(chain.chain_name(),condition);
175 if (result && (condition & TrigDefs::enforceLogicalFlow)) {
176 // enforceLogicalFlow
177 if (chain.has_l2() && chain.level()=="EF") {
178 const std::string& nexttwo = getLowerName(chain.chain_name());
179 result = result && HLTResult(nexttwo,condition);
180 result = result && L1Result(getLowerName(nexttwo),condition);
181
182 } else if (chain.level()=="L2") {
183 result = result && L1Result(getLowerName(chain.chain_name()),condition);
184
185 } else if (chain.level()=="HLT" || chain.level()=="EF"){ // && !chain.has_l2() - implied
186 result = result && L1Result(getLowerName(chain.chain_name()),condition);
187
188 } else {
189
190 ATH_MSG_ERROR("Unknown chain level " << chain.level() << " cannot do 'enforceLogicalFlow'");
191 }
192
193 }
194
195 return result;
196}
197
198std::vector<bool> Trig::ChainGroup::isPassedForEach(unsigned int condition) const
199{
200 std::vector<bool> result;
201 result.reserve(m_confChains.size() + m_confItems.size());
202
203 for (const TrigConf::HLTChain* ch : m_confChains) {
204 result.push_back( isPassed(*ch, condition) );
205 }
206 for (const TrigConf::TriggerItem* item : m_confItems) {
207 result.push_back( L1Result(item->name(), condition) );
208 }
209
210 return result;
211}
212
213bool Trig::ChainGroup::isPassed(unsigned int condition) const
214{
215 if (condition & TrigDefs::Express_passed) {
216 ATH_MSG_ERROR("Incorrect use of Express_passed bit. Please use isPassedBits() and test for TrigDefs::Express_passed in the returned bit-map.");
217 }
218
219 // True if any HLT or L1 item passed
220 return ( std::any_of(m_confChains.cbegin(), m_confChains.cend(),
221 [&](const TrigConf::HLTChain* ch) {return isPassed(*ch, condition);}) ||
222 std::any_of(m_confItems.cbegin(), m_confItems.cend(),
223 [&](const TrigConf::TriggerItem* item) {return L1Result(item->name(), condition);}) );
224}
225
226unsigned int Trig::ChainGroup::HLTBits(const std::string& chain, const std::string& level, const TrigCompositeUtils::DecisionIDContainer& passExpress) const {
227 unsigned int chainRESULT = 0;
228 if (chain.empty()) return chainRESULT;
229 const HLT::Chain* fchain = cgm_assert().chain(chain);
230 if (fchain==nullptr) return chainRESULT;
231 if (level=="L2") {
232 if (fchain->chainPassedRaw()) chainRESULT = chainRESULT | TrigDefs::L2_passedRaw;
233 if (fchain->isPassedThrough()) chainRESULT = chainRESULT | TrigDefs::L2_passThrough;
234 if (fchain->isPrescaled()) chainRESULT = chainRESULT | TrigDefs::L2_prescaled;
235 if (fchain->isResurrected()) chainRESULT = chainRESULT | TrigDefs::L2_resurrected;
236 } else {//L2EF merged use same EF bits
237 if (fchain->chainPassedRaw()) chainRESULT = chainRESULT | TrigDefs::EF_passedRaw;
238 if (fchain->isPassedThrough()) chainRESULT = chainRESULT | TrigDefs::EF_passThrough;
239 if (fchain->isPrescaled()) chainRESULT = chainRESULT | TrigDefs::EF_prescaled;
240 if (fchain->isResurrected()) chainRESULT = chainRESULT | TrigDefs::EF_resurrected;
241
242 if (passExpress.count( HLT::Identifier(chain).numeric() ) == 1) {
243 chainRESULT = chainRESULT | TrigDefs::Express_passed;
244 }
245 }
246 return chainRESULT;
247}
248
249unsigned int Trig::ChainGroup::L1Bits(const std::string& item) const {
250 unsigned int r = 0;
251 if (item.empty()) return r;
252 if (item.find(',')!=std::string::npos) {
253 for(const std::string& item : convertStringToVector(item)) {
254 r |= L1Bits(item);
255 }
256 return r;
257 }
258 const LVL1CTP::Lvl1Item* fitem = cgm_assert().item(item);
259 if (fitem==nullptr) return r;
263 return r;
264}
265
266std::vector<unsigned int> Trig::ChainGroup::isPassedBitsForEach() const
267{
268 // This is for the express decision (R3 only), we read this directly from the navigation (not from bits)
269 const SG::ReadHandleKey<TrigCompositeUtils::DecisionContainer>* navRHK = cgm().getRun3NavigationKeyPtr();
271 if (navRHK && !navRHK->empty()) {
272 SG::ReadHandle<TrigCompositeUtils::DecisionContainer> navRH(*navRHK); // No good way to pass in the context here?
273 if (navRH.isValid()) {
275 if (expressTerminusNode) {
276 TrigCompositeUtils::decisionIDs(expressTerminusNode, passExpress);
277 }
278 }
279 }
280
281 std::vector<unsigned int> all;
282 all.reserve(m_confChains.size() + m_confItems.size());
283
284 for ( const TrigConf::HLTChain* ch : m_confChains ) {
285
286 unsigned int RESULT = HLTBits(ch->chain_name(), ch->level(), passExpress);
287
288 if (ch->has_l2() && ch->level()=="EF") {
289 const std::string& nexttwo = getLowerName(ch->chain_name());
290 RESULT = RESULT | HLTBits(nexttwo,"L2", passExpress);
291 RESULT = RESULT | L1Bits(getLowerName(nexttwo));
292
293 } else if (ch->level()=="L2") {
294 RESULT = RESULT | L1Bits(getLowerName(ch->chain_name()));
295
296 } else if (ch->level()=="HLT" || ch->level()=="EF") { // && !ch->has_l2() - implied
297 RESULT = RESULT | L1Bits(getLowerName(ch->chain_name()));
298
299 } else {
300 ATH_MSG_ERROR("Unknown chain level " << ch->level() << " cannot look at lower level results to compute isPassedBitsForEach");
301 }
302
303 all.push_back(RESULT);
304 }
305
306 for ( const TrigConf::TriggerItem* item : m_confItems ) {
307 all.push_back( L1Bits(item->name()) );
308 }
309
310 return all;
311}
312
314{
315 const std::vector<unsigned int> all = isPassedBitsForEach();
316 unsigned int result = 0;
317 for (unsigned int r : all) {
318 result = result | r;
319 }
320 return result;
321}
322
324 HLT::ErrorCode errorCode = HLT::OK;
325 for ( const TrigConf::HLTChain* ch : m_confChains ) {
326 const HLT::Chain* fchain = cgm_assert().chain(ch->chain_name());
327 if (fchain==nullptr) continue;
328 HLT::ErrorCode ec = fchain->getErrorCode();
329 errorCode = errorCode > ec ? errorCode : ec;
330 }
331 return errorCode;
332}
333
334float Trig::ChainGroup::HLTPrescale(const std::string& chain, unsigned int /*condition*/) const {
335 if (chain=="") return 0.;
336
337 const TrigConf::HLTChain* fchain=cgm().config_chain(chain);
338 if (fchain==0) { // this is error condition, we always need configuration of the chains in the chaon group!
339 ATH_MSG_WARNING("Configuration for the chain: " << chain << " not known");
340 return std::numeric_limits<float>::quiet_NaN();
341 }
342 float chainRESULT = fchain->prescale();
343
344 if (chainRESULT < 1)
345 chainRESULT = 0.;
346
347 return chainRESULT;
348}
349
350
351bool Trig::ChainGroup::isCorrelatedL1items(const std::string& item) const {
352 if( (item == "L1_MU20,L1_MU21") || (item == "L1_MU21,L1_MU20") ) return true;
353 return false;
354}
355
356float Trig::ChainGroup::correlatedL1Prescale(const std::string& item) const {
357 if( (item == "L1_MU20,L1_MU21") || (item == "L1_MU21,L1_MU20") ) {
358 //see discussion in ATR-16612
359 auto l1mu20 = cgm().config_item("L1_MU20");
360 if (l1mu20==nullptr) {
361 ATH_MSG_WARNING("Configuration for the item L1_MU20 not known");
362 return std::numeric_limits<float>::quiet_NaN();
363 }
364 float l1mu20ps = cgm().item_prescale(l1mu20->ctpId());
365
366 auto l1mu21 = cgm().config_item("L1_MU21");
367 if (l1mu21==nullptr) {
368 ATH_MSG_WARNING("Configuration for the item L1_MU21 not known");
369 return std::numeric_limits<float>::quiet_NaN();
370 }
371 float l1mu21ps = cgm().item_prescale(l1mu21->ctpId());
372
373 if( (l1mu20ps < 1.0) && (l1mu21ps < 1.0) ) return 0.0;
374 if( (l1mu20ps < 1.0) ) return l1mu21ps;
375 if( (l1mu21ps < 1.0) ) return l1mu20ps;
376 if(l1mu20ps == 1.0) return 1.0;
377 return 0.0;
378 }
379 return 0.0;
380}
381
382float Trig::ChainGroup::L1Prescale(const std::string& item, unsigned int /*condition*/) const {
383 if (item.empty()) return 0;
384
385 if(item.find(',')==std::string::npos) {
386 const TrigConf::TriggerItem* fitem=cgm().config_item(item);
387 if (fitem==nullptr) {
388 ATH_MSG_WARNING("Configuration for the item: " << item << " not known");
389 return std::numeric_limits<float>::quiet_NaN();
390 }
391 // now we can;t access the prescale value because this information doe not come togehther as in HLT
392 // we need to go to the cache of L1 items and get it from there
393 float itemprescale = cgm().item_prescale(fitem->ctpId());
394 if ( itemprescale < 1) itemprescale = 0;
395 return itemprescale;
396 } else if(isCorrelatedL1items(item)) {
397 return correlatedL1Prescale(item);
398 } else {
399 float minprescale=0;
400 for(const std::string& item : convertStringToVector(item)) {
401
402 const TrigConf::TriggerItem* fitem=cgm().config_item(item);
403 if (fitem==nullptr) {
404 ATH_MSG_WARNING("Configuration for the item: " << item << " not known");
405 return std::numeric_limits<float>::quiet_NaN();
406 }
407 float itemprescale = cgm().item_prescale(fitem->ctpId());
408 if ( itemprescale < 1) itemprescale = 0;
409 minprescale = (minprescale&&(minprescale<itemprescale)?minprescale:itemprescale); // takes min, except the first time
410 }
411 return minprescale;
412 }
413}
414
415float Trig::ChainGroup::getPrescale(unsigned int condition) const {
416 if ( condition != TrigDefs::Physics )
417 return 0.0;
418 return m_prescale;
419}
420
421float Trig::ChainGroup::calculatePrescale(unsigned int condition)
422{
423 bool singleTrigger = (m_confChains.size()+m_confItems.size()==1);
424
425 for ( const TrigConf::HLTChain* ch : m_confChains ) {
426
427 const std::string& hltChainName = ch->chain_name();
428 float chainRESULT = HLTPrescale(hltChainName,condition);
429
430 if (condition & TrigDefs::enforceLogicalFlow) {
431 // enforceLogicalFlow
432 if (ch->has_l2() && ch->level()=="EF") {
433 const std::string& hltChainNameL2 = getLowerName(hltChainName);
434 const std::string& l1ItemName = getLowerName(hltChainNameL2);
435 chainRESULT *= HLTPrescale(hltChainNameL2,condition);
436 chainRESULT *= L1Prescale(l1ItemName,condition);
437 if(l1ItemName.find(',')!=std::string::npos) singleTrigger=false;
438
439 } else if (ch->level()=="L2") {
440 const std::string& l1ItemName = getLowerName(hltChainName);
441 chainRESULT *= L1Prescale(l1ItemName,condition);
442 if(l1ItemName.find(',')!=std::string::npos) singleTrigger=false;
443
444 } else if (ch->level()=="HLT" || ch->level()=="EF") { // && !ch->has_l2() - implied
445 const std::string& l1ItemName = getLowerName(hltChainName);
446 chainRESULT *= L1Prescale(l1ItemName,condition);
447 if(l1ItemName.find(',')!=std::string::npos and !isCorrelatedL1items(l1ItemName) ) singleTrigger=false;
448 }
449 }
450
451 if (singleTrigger) return chainRESULT; // for a single trigger we are done
452
453 const bool UNPRESCALED = (fabs(chainRESULT-1.0)<1e-5);
454
455 if (UNPRESCALED) return 1.0; // any unprescaled trigger and we are done too
456 }
457
458
459 for ( const TrigConf::TriggerItem* item : m_confItems ) {
460 const std::string& l1ItemName = item->name();
461 const float itemRESULT = L1Prescale(l1ItemName, condition);
462 if(l1ItemName.find(',')!=std::string::npos) singleTrigger=false;
463
464 if (singleTrigger) return itemRESULT; // for a single trigger we are done
465
466 const bool UNPRESCALED = (itemRESULT==1);
467
468 if (UNPRESCALED) return 1.0; // any unprescaled trigger and we are done too
469 }
470
471 return 0.0; // multiple triggers and all are prescaled
472}
473
474
475std::vector< std::string > Trig::ChainGroup::getListOfTriggers() const {
476 return m_names;
477}
478
479
480std::vector< std::string > Trig::ChainGroup::getListOfStreams() const {
481 std::set< std::string > streams;
482 for ( const TrigConf::HLTChain* ch : m_confChains ) {
483 for ( const TrigConf::HLTStreamTag* s : ch->streams() ) {
484 streams.insert(s->stream());
485 }
486 }
487 return {streams.begin(), streams.end()};
488}
489
490//
491// Groups
492//
493
494vector<string>
496
497 vector< string > v;
498
499 for( const TrigConf::HLTChain* ch : m_confChains )
500 v.assign( ch->groups().begin(), ch->groups().end() );
501
502 return v;
503}
504
505//
506// Signatures
507//
508
509std::vector< std::string > Trig::ChainGroup::getListOfSignatures() const {
510 std::set< std::string > sig;
511 for ( const TrigConf::HLTChain* ch : m_confChains ) {
512 for ( const TrigConf::HLTSignature* s : ch->signatureList() ) {
513 sig.insert(s->label());
514 }
515 }
516 return {sig.begin(), sig.end()};
517}
518
519
520//
521// Return level 1 thresholds
522//
523
524vector<string>
526
527 set<string> s; // using a set makes the items in the result vector unique
528 std::stack<const TrigConf::TriggerItemNode*> nodes;
530
531 for( const TrigConf::TriggerItem* item : m_confItems ) {
532 nodes.push( item->topNode() );
533 while (!nodes.empty()) {
534 node = nodes.top(); nodes.pop();
535 if (node == NULL)
536 continue;
537 if (node->isThreshold()) {
538 if (node->triggerThreshold()) {
539 // available if thresholds have been read in
540 if (!node->triggerThreshold()->name().empty())
541 s.insert(node->triggerThreshold()->name());
542 } else if (!node->thresholdName().empty()) {
543 // fall back solution
544 s.insert(node->thresholdName());
545 }
546 } else {
547 for(TrigConf::TriggerItemNode* childnode : node->children()) {
548 nodes.push(childnode);
549 }
550 }
551 }
552 // I am not using (*it)->topNode()->getAllThresholds() here, because it returns nothing when only ItemDef (and not the thresholds themselves) are defined
553 }
554
555 return {s.begin(), s.end()};
556}
557
558
559//
560// Trigger Elements
561//
562
563std::vector< std::vector< std::string > > Trig::ChainGroup::getListOfTriggerElements() const {
564
565 std::set< std::vector< std::string > > tes;
566 std::vector< std::string > t;
567
568 for( const TrigConf::HLTChain* ch : m_confChains ) {
569 for ( const TrigConf::HLTSignature* s : ch->signatureList() ) {
570 t.clear();
571 for ( const TrigConf::HLTTriggerElement* te : s->outputTEs() ) {
572 t.push_back( te->name());
573 }
574 tes.insert(t);
575 }
576 }
577 return {tes.begin(), tes.end()};
578}
579
580
581//
582// get vector of vector with all Trigger Elements
583//
584
585std::vector< std::vector< TrigConf::HLTTriggerElement* > > Trig::ChainGroup::getHLTTriggerElements() const {
586
587 std::set< std::vector< TrigConf::HLTTriggerElement* > > tes;
588
589 for( const TrigConf::HLTChain* ch : m_confChains ) {
590 for ( const TrigConf::HLTSignature* s : ch->signatureList() ) {
591 tes.insert(s->outputTEs());
592 }
593 }
594 return {tes.begin(), tes.end()};
595}
596
597
598void
600 const TrigConf::ItemContainer* confItems,
601 TrigDefs::Group prop) {
602
603 m_confChains.clear();
604 m_confItems.clear();
605 m_names.clear();
606
607 // protect against genConf failure
608 if (!(confChains && confItems) ) return;
609
611
612 for(const std::string& pat : m_patterns) {
613 // find chains matching pattern
614 std::regex compiled(pat);
615
616 for(TrigConf::HLTChain* ch : *confChains) {
617 if ( std::regex_match(ch->chain_name().c_str(), compiled) ) {
618 m_confChains.push_back(ch);
619 }
620 }
621
622 for(TrigConf::TriggerItem* item : *confItems) {
623 if ( std::regex_match(item->name().c_str(), compiled) ) {
624 m_confItems.push_back(item);
625 }
626 }
627 }
628
629 } else { // Do not parse as regex
630
631 for(const std::string& what : m_patterns) {
632
633 bool found_it = false;
634
635 for(TrigConf::HLTChain* ch : *confChains) {
636 if (ch->chain_name() == what) {
637 m_confChains.push_back(ch);
638 found_it = true;
639 break;
640 }
641 }
642
643 if (found_it) {
644 continue;
645 }
646
647 for(TrigConf::TriggerItem* item : *confItems) {
648 if (item->name() == what) {
649 m_confItems.push_back(item);
650 found_it = true;
651 break;
652 }
653 }
654
655 if (found_it) {
656 continue;
657 }
658
659 ATH_MSG_WARNING("Explicitly requested '" << what << "' be added to a ChainGroup"
660 << " but this item or chain could not be found in the menu");
661 }
662
663 } // parseAsRegex
664
665 // Cache the names of all triggers
666 m_names.reserve(m_confChains.size() + m_confItems.size());
667 for (const TrigConf::HLTChain* ch : m_confChains) m_names.push_back(ch->chain_name());
668 for (const TrigConf::TriggerItem* item : m_confItems) m_names.push_back(item->name());
669
671}
672
674// features
675
677 using namespace HLT;
678 using namespace Trig;
679
680 bool allActive(const std::vector<TriggerElement*>& tes) {
681 for(TriggerElement* te : tes){
682 if (te->getActiveState() == false)
683 return false;
684 }
685 return true;
686 }
687
688
689
690 void collectCombinations( const TrigConf::HLTChain* conf, const CacheGlobalMemory& cgm, FeatureContainer& fc, unsigned int condition ){
691 // go over the steps of the chain and collecte TEs combinations for each of the chain step (signature)
692 bool last_step=true;
693 const TrigConf::HLTSignature* previous_sig(0);
694 for(const TrigConf::HLTSignature* sig : std::views::reverse(conf->signatureList())) {
695 // chain without signatures
696 if (!sig) break;
697
698 // the signatures size changes from step to step, this needs custom treatement and the iteration eeds to be stoped here
699 if ( previous_sig && previous_sig->outputTEs().size() != sig->outputTEs().size() )
700 break;
701 previous_sig = sig;
702
703 std::vector<std::vector<HLT::TriggerElement*> > tes(sig->outputTEs().size()); // preallocate
704 size_t idx = 0;
705 for(const TrigConf::HLTTriggerElement* confte : sig->outputTEs() ) {
706
707 // here the condition enters; if we take only accepted objects we need to pick only the active TEs
708 cgm.navigation()->getAllOfType(confte->id(), tes[idx], condition & TrigDefs::Physics );
709 idx++;
710 }
711 HLT::ComboIterator combination(tes, cgm.navigation());
712
713 // build the combinations, sometimes a huge list
714 while (combination.isValid()) {
715 // very very tricky, if all TEs in the combination are active then it means they were already picked up by previous combinations
716 // but we can not do this for the last chain step, (we woudl be unable to pick objects whcih made trigger passing)
717 //std::cerr << "emitting new combination last_step: "<< last_step << std::endl;
718 if (!allActive(*combination) || last_step) {
719 fc.addWithChecking(Combination(*combination, &cgm));
720 }
721 ++combination;
722 }
723
724 if ( condition & TrigDefs::Physics ) // here again athe condition calls for the loop breaking
725 break;
726 else
727 last_step = false; // and go deeper
728 }
729 }
730}// eof namespace
731
732const Trig::FeatureContainer
733Trig::ChainGroup::features(unsigned int condition) const {
734 using namespace ChainGroup_impl;
736
737 // this loop only applies to L2 and EF chain groups
738 for (const TrigConf::HLTChain* ch : m_confChains) {
739 const HLT::Chain* fchain = cgm_assert().chain(*ch);
740 if (fchain) {
741 collectCombinations(fchain->getConfigChain(), cgm_assert(), f, condition);
742 }
743 }
744
745 // this part only applies to L1 chain groups
746 std::vector< std::vector< HLT::TriggerElement*> > tes;
747 std::vector< std::vector< HLT::TriggerElement*> >::iterator tesit;
748
749 for(const TrigConf::TriggerItem* item : m_confItems) {
750
751 std::set< std::string > threshold_names;
752 std::stack<const TrigConf::TriggerItemNode*> nodes;
753
754 nodes.push( item->topNode() );
755
756 // collect unique list (= set) of threshold names for this item
757 while (!nodes.empty()) {
758 const TrigConf::TriggerItemNode* node = nodes.top();
759 nodes.pop();
760 if (node == nullptr)
761 continue;
762 if (node->isThreshold()) {
763 if (node->triggerThreshold()) {
764 // available if thresholds have been read in
765 if (!node->triggerThreshold()->name().empty())
766 threshold_names.insert(node->triggerThreshold()->name());
767 } else if (!node->thresholdName().empty()) {
768 // fall back solution
769 threshold_names.insert(node->thresholdName());
770 }
771 }
772 for(TrigConf::TriggerItemNode* childnode : node->children()) {
773 nodes.push(childnode);
774 }
775 }
776
777 // collect corresponding TEs and add them using appendFeatures()
778 tes.clear();
779 tes.resize(threshold_names.size());
780 tesit = tes.begin();
781 std::set< std::string >::iterator setstrit;
782
783 for (setstrit = threshold_names.begin(); setstrit != threshold_names.end(); ++setstrit, ++tesit) {
784 cgm_assert().navigation()->getAllOfType(TrigConf::HLTUtils::string2hash(*setstrit), *tesit, true);
785 }
786
787 appendFeatures(tes, f);
788 }
789
790 ATH_MSG_DEBUG("features: features container size: "<< f.getCombinations().size());
791 return f;
792}
793
794
795void Trig::ChainGroup::appendFeatures(std::vector< std::vector< HLT::TriggerElement*> >& tes, Trig::FeatureContainer& fc) const {
796
797 // appends (combinations of) TriggerElements to FeatureContainer
798 if (tes.empty()) // ComboIterator::isValid would return true in this case
799 return;
800
801 HLT::ComboIterator combination(tes, cgm_assert().navigation());
802 while (combination.isValid()) {
803 fc.addWithChecking(Combination(*combination, &cgm_assert()));
804
805 ATH_MSG_VERBOSE(" adding combination" << Combination(*combination, &cgm_assert()));
806
807 ++combination;
808 }
809}
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_VERBOSE(x,...)
size_t size() const
Number of registered mappings.
Helpers for treating a class enum as a bitmask.
This class represents one chain of signatures, i.e.
Definition Chain.h:61
const TrigConf::HLTChain * getConfigChain() const
get underlying ConfigChain
Definition Chain.h:75
HLT::ErrorCode getErrorCode() const
return this Chain's most severe error code (from execution)
Definition Chain.h:99
unsigned int getChainCounter() const
return the unique identifier of this Chain (uint)
Definition Chain.h:90
int getChainStep() const
return the current step of execution
Definition Chain.h:100
bool isPassedThrough() const
is chain passed through ?
Definition Chain.h:82
bool isPrescaled() const
is chain prescaled ?
Definition Chain.h:83
const std::string & getChainName() const
return the Chain name (string)
Definition Chain.h:91
bool isResurrected() const
is chain resurrected ?
Definition Chain.h:84
bool chainPassedRaw() const
Definition Chain.h:78
Iterator used to loop over multi-particle combinations.
bool isValid() const
Validity check for the iterator.
TrigCompositeUtils::DecisionID numeric() const
numeric ID
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.
TriggerElement is the basic ingreedient of the interface between HLT algorithms and the navigation It...
bool isPassedAfterPrescale() const
Definition Lvl1Item.h:45
bool isPassedBeforePrescale() const
Definition Lvl1Item.h:44
const std::string & name() const
Definition Lvl1Item.h:41
bool isPassedAfterVeto() const
Definition Lvl1Item.h:46
bool isPrescaled() const
Definition Lvl1Item.h:50
bool isVeto() const
Definition Lvl1Item.h:51
Property holding a SG store/key/clid from which a ReadHandle is made.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
bool empty() const
Test if the key is blank.
list of all HLT chains in a trigger menu
HLT chain configuration information.
const std::string & lower_chain_name() const
HLT signature configuration information.
std::vector< HLTTriggerElement * > & outputTEs()
accessor to the list of trigger elements
HLT stream configuration information.
HLT trigger element configuration information.
static HLTHash string2hash(std::string_view, const std::string &category=s_defaultCategory)
hash function translating TE names into identifiers
bool assert_decision() const
checks if new event arrived with the decision Need to use before any call to CacheGlobalMemory.
const HLT::TrigNavStructure * navigation() const
float correlatedL1Prescale(const std::string &item) const
const std::vector< std::string > & patterns() const
Definition ChainGroup.h:155
std::vector< std::string > getListOfStreams() const
std::vector< std::string > getListOfThresholds() const
const Trig::CacheGlobalMemory & cgm() const
Definition ChainGroup.h:193
const FeatureContainer features(unsigned int condition=TrigDefs::Physics) const
returns all features related to given chain group of HLT chains or L1 items Note: This does not yet w...
std::vector< std::string > getListOfGroups() const
HLT::ErrorCode error() const
returns most severe error in the chains composing that chain group for L1 it is just OK If there is s...
unsigned int isPassedBits() const
returns bits (OR ed) of the chain group Meaning of the returned bits can be understood by using masks...
std::vector< bool > isPassedForEach(unsigned int condition=TrigDefs::Physics) const
return vector with isPassed decision for each chain
bool isCorrelatedL1items(const std::string &item) const
ChainGroup(const std::vector< std::string > &triggerNames, Trig::CacheGlobalMemory &parent)
void addAlias(const std::string &alias)
adds alias (sort understandabel name) to the group
std::vector< std::string > m_names
names of trigger derived from patterns & current configuration
Definition ChainGroup.h:190
void update(const TrigConf::HLTChainList *confChains, const TrigConf::ItemContainer *confItems, TrigDefs::Group prop=TrigDefs::Group::Default)
float HLTPrescale(const std::string &chain, unsigned int condition) const
float getPrescale(unsigned int condition=TrigDefs::Physics) const
returns prescale factor for chain group with single chain in returns real prescale factor for real ch...
const Trig::ChainGroup & operator+(const Trig::ChainGroup &rhs)
bool L1Result(const std::string &item, unsigned int condition) const
unsigned int L1Bits(const std::string &item) const
bool operator!=(const Trig::ChainGroup &rhs)
float calculatePrescale(unsigned int condition=TrigDefs::Physics)
std::vector< const TrigConf::HLTChain * > m_confChains
Definition ChainGroup.h:183
unsigned int HLTBits(const std::string &chain, const std::string &level, const TrigCompositeUtils::DecisionIDContainer &passExpress) const
const std::vector< std::string > & names() const
names of triggers within chain group
Definition ChainGroup.h:168
std::vector< std::vector< std::string > > getListOfTriggerElements() const
std::vector< std::string > m_patterns
patterns with which the CG was constructed
Definition ChainGroup.h:181
bool isPassed(unsigned int condition=TrigDefs::Physics) const
tells if chain group passed
Trig::CacheGlobalMemory & m_cgm
Definition ChainGroup.h:188
void appendFeatures(std::vector< std::vector< HLT::TriggerElement * > > &tes, FeatureContainer &fc) const
float L1Prescale(const std::string &item, unsigned int condition) const
std::vector< unsigned int > isPassedBitsForEach() const
return result of isPassedBits for each chain in the group
const Trig::CacheGlobalMemory & cgm_assert() const
bool operator==(const Trig::ChainGroup &rhs)
std::vector< std::string > getListOfSignatures() const
std::string getLowerName(const std::string &EFname) const
std::vector< std::vector< TrigConf::HLTTriggerElement * > > getHLTTriggerElements() const
bool HLTResult(const std::string &chain, unsigned int condition) const
std::vector< const TrigConf::TriggerItem * > m_confItems
Definition ChainGroup.h:184
std::vector< std::string > getListOfTriggers() const
is a connector between chains and object It store single combination of trigger elements.
void addWithChecking(const Combination &newComb)
add new combination to the container checking for overlap
Definition node.h:24
void name(const std::string &n)
Definition node.h:40
int r
Definition globals.cxx:22
std::vector< std::string > patterns
Definition listroot.cxx:187
void collectCombinations(const TrigConf::HLTChain *conf, const CacheGlobalMemory &cgm, FeatureContainer &fc, unsigned int condition)
bool allActive(const std::vector< TriggerElement * > &tes)
constexpr std::enable_if_t< is_bitmask_v< E >, bool > test(E lhs, E rhs)
Convenience function to test bits in a class enum bitmask.
Definition bitmask.h:270
It used to be useful piece of code for replacing actual SG with other store of similar functionality ...
static const ErrorCode OK(Action::CONTINUE)
xAOD::TrigComposite Decision
const Decision * getExpressTerminusNode(const DecisionContainer &container)
Returns the express-accept navigation node from a collection or nullptr if missing.
std::set< DecisionID > DecisionIDContainer
void decisionIDs(const Decision *d, DecisionIDContainer &destination)
Extracts DecisionIDs stored in the Decision object.
boost::multi_index::multi_index_container< TriggerItem *, boost::multi_index::indexed_by< boost::multi_index::random_access<>, boost::multi_index::ordered_unique< boost::multi_index::identity< TriggerItem > >, boost::multi_index::ordered_unique< boost::multi_index::tag< tag_ctpid >, boost::multi_index::const_mem_fun< TriggerItem, int, &TriggerItem::ctpId > >, boost::multi_index::hashed_unique< boost::multi_index::tag< tag_name_hash >, boost::multi_index::const_mem_fun< TrigConfData, const std::string &, &TrigConfData::name > > > > ItemContainer
Definition Menu.h:39
Group
Properties of a chain group.
@ NoRegex
Do not use regular expressions.
The common trigger namespace for trigger analysis tools.
std::vector< std::string > convertStringToVector(std::string_view triggerNames)
makes a split of list of chains into the vector of chains
std::vector< std::string > keyWrap(const std::vector< std::string > &triggerNames)
normalizes the list of triggers (patterns) by sorting and uniquing them
Definition merge.py:1
STL namespace.