ATLAS Offline Software
Loading...
Searching...
No Matches
NavigationTesterAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include <GaudiKernel/StatusCode.h>
6#include <set>
7#include <algorithm>
8#include <iterator>
10#include "NavigationTesterAlg.h"
11#include "SpecialCases.h"
12
13
14// anonymous namespace for convenience functions
15namespace {
16 std::set<std::set<const xAOD::IParticle *>> vectorToSet(
17 const std::vector<std::vector<const xAOD::IParticle *>>& vec)
18 {
19 std::set<std::set<const xAOD::IParticle *>> ret;
20 for (const std::vector<const xAOD::IParticle *> &combination : vec)
21 ret.emplace(combination.begin(), combination.end());
22 return ret;
23 }
24
25}
26
27namespace xAOD {
28 std::ostream &operator<<(std::ostream &os, const xAOD::IParticle *p)
29 {
30 return os << "["
31 << "type = " << p->type() << ", "
32 << "pt = " << p->pt() << ", "
33 << "eta = " << p->eta() << ", "
34 << "phi = " << p->phi() << ", "
35 << "ptr = " << reinterpret_cast<const void*>(p)
36 << "]";
37
38 }
39}
40
41namespace std {
42 // Define printing operators for the set and IParticle pointers
43 template <typename T>
44 std::ostream &operator<<(std::ostream &os, const std::set<T> &s)
45 {
46 os << "{";
47 for (auto itr = s.begin(); itr != s.end(); ++itr)
48 {
49 if (itr != s.begin())
50 os << ", ";
51 os << *itr;
52 }
53 return os << "}";
54 }
55}
56
57namespace Trig {
58
59 NavigationTesterAlg::NavigationTesterAlg(const std::string &name, ISvcLocator *pSvcLocator) :
60 AthReentrantAlgorithm(name, pSvcLocator)
61 {}
62
64 {
65 ATH_CHECK(m_tdt.retrieve());
66 ATH_CHECK(m_tdtRun2.retrieve());
67 ATH_CHECK(m_tdtRun3.retrieve());
68 ATH_CHECK(m_toolRun2.retrieve());
69 ATH_CHECK(m_toolRun3.retrieve());
70
71 if (m_chains.size() == 0)
72 ATH_MSG_WARNING("No chains provided, algorithm will be no-op");
73 return StatusCode::SUCCESS;
74 }
75
76 StatusCode NavigationTesterAlg::execute(const EventContext &) const
77 {
78 for (const std::string &chain : m_chains)
79 {
80 const bool chainPassed = m_tdt->isPassed(chain, TrigDefs::Physics | TrigDefs::allowResurrectedDecision);
81 ATH_MSG_DEBUG("Begin testing chain " << chain << (chainPassed ? " and will dive into details as the chain passed " : " but will not do anything as the chain did not pass"));
82 if (!chainPassed) continue;
83
84 // explicitely excluded chains
85 bool isExcluded = false;
86 for (const auto& excludedChain : SpecialCases::excludedChains) {
87 if (chain == excludedChain) {
88 isExcluded = true;
89 break; // Break out of the exclusion check loop
90 }
91 }
92
93 if (isExcluded) {
94 continue; // Skip the current iteration of the main loop
95 }
96
97 // We assume that the navigation is ultimately a set of element links
98 // We're comparing two types of navigation but they should both point to the same
99 // objects.
100 // We don't care about the order of the combinations, or the order within the
101 // combinations, we just care that they are the same. Therefore, we can convert the
102 // vectors to sets and just look at the differences between them
103 CombinationsVector vecCombinationsRun2;
104 ATH_MSG_DEBUG("###### checking features of CHAIN " << chain);
105 ATH_CHECK(m_toolRun2->retrieveParticles(vecCombinationsRun2, chain));
106 auto combsRun2 = vectorToSet(vecCombinationsRun2);
107 ATH_MSG_DEBUG("Run 2 size " << combsRun2.size());
108 // if Run 2 size is 0 we discard any further testing
109 if (combsRun2.size() == 0)
110 {
111 ATH_MSG_DEBUG("Chain " << chain << " testing discarded due to detected Run 2 size == 0");
112 continue;
113 }
114 for (auto& c : combsRun2 ) {
115 ATH_MSG_DEBUG(c);
116 }
117 CombinationsVector vecCombinationsRun3;
118 ATH_CHECK(m_toolRun3->retrieveParticles(vecCombinationsRun3, chain));
119 auto combsRun3 = vectorToSet(vecCombinationsRun3);
120 ATH_MSG_DEBUG("Run 3 size " << combsRun3.size());
121
122 if (combinationsEmpty(vecCombinationsRun2) and combinationsEmpty(vecCombinationsRun3)) {
123 ATH_MSG_DEBUG("Both, Run2 and Run3 combinations are effectively empty");
124 continue;
125 }
126
127
128 for (auto& c : combsRun3 ) {
129 ATH_MSG_DEBUG(c);
130 }
131 if ( std::regex_match(chain, SpecialCases::gammaXeChain) ) {
133 } else {
135 ATH_CHECK(verifyCombinationsSize(vecCombinationsRun2, vecCombinationsRun3, chain));
136 }
137 if ( m_verifyCombinations ) {
138 ATH_CHECK(verifyCombinationsContent(combsRun2, combsRun3, chain));
139 }
140 }
141
142 ATH_MSG_DEBUG("Verified chain " << chain);
143 }
144 return StatusCode::SUCCESS;
145 }
146
147 StatusCode NavigationTesterAlg::verifyFlatContent(const std::string& chain) const {
148 const auto &run3 = m_tdtRun3->features<xAOD::IParticleContainer>(chain);
149 std::set<const xAOD::IParticle*> particlesRun3;
150 for ( auto l: run3) {
151 if ( l.link.isValid() )
152 particlesRun3.insert(*(l.link));
153 }
154
155 CombinationsVector vecCombinationsRun2;
156 ATH_CHECK(m_toolRun2->retrieveParticles(vecCombinationsRun2, chain));
157 std::set<const xAOD::IParticle*> particlesRun2;
158 for ( auto& comb: vecCombinationsRun2) {
159 for ( auto el: comb) {
160 particlesRun2.insert(el);
161 }
162 }
163
164 for ( auto f2: particlesRun2 ) {
165 bool found=false;
166 for ( auto f3: particlesRun3 ) {
167 ATH_MSG_DEBUG("Serial set of features " << f3 );
168 if ( f2 == f3)
169 found = true;
170 }
171 if ( not found ) {
172 ATH_MSG_ERROR("Missing feature in Run 3 that is present in Run 2 " << f2 << " chain " << chain << " enable DEBUG to see more details" );
173 if ( m_failOnDifference ) {
174 return StatusCode::FAILURE;
175 }
176 }
177 }
178 return StatusCode::SUCCESS;
179 }
180
181
182 StatusCode NavigationTesterAlg::verifyCombinationsSize(const CombinationsVector& run2, const CombinationsVector& run3, const std::string& chain) const {
183 if (run2.size() > run3.size()) { // in Run3 we do not use decision per RoI but per object. For single RoI there is more than one object we will have more combinations in Run3
184 ATH_MSG_WARNING("Issue in combination sizes for chain " << chain
185 << " using Run 2 navigation " << run2.size()
186 << " Run 3 navigation " << run3.size());
187 ATH_MSG_WARNING("Mismatched sizes of combinations for chain " << chain << " (enable WARNING messages for more details), this may be a false positive if chain is incorrectly decoded");
188 if ( m_failOnDifference ) {
189 return StatusCode::FAILURE;
190 }
191 }
192 return StatusCode::SUCCESS;
193 }
194
195 StatusCode NavigationTesterAlg::verifyCombinationsContent(const CombinationsSet& run2, const CombinationsSet& run3, const std::string& chain) const {
196 // compare combinations
197
198 using xAODParticle = const xAOD::IParticle;
199
200 auto isSubsetPresent = [](const std::set<xAODParticle*>& subset, const CombinationsSet& run2) {
201 for (const auto& setInRun2 : run2) {
202 // Manual check for all particles in subset
203 bool allFound = true;
204 for (auto particle : subset) {
205 if (setInRun2.find(particle) == setInRun2.end()) {
206 allFound = false;
207 break; // If any particle is not found, no need to check further
208 }
209 }
210 if (allFound) return true; // Found all particles in this subset of Run2
211 }
212 return false; // Did not find the subset
213 };
214
215
216 auto isAnySubsetPresent = [&isSubsetPresent](const CombinationsSet& run3, const CombinationsSet& run2) {
217 for (const auto& subset : run3) {
218 if (isSubsetPresent(subset, run2)) {
219 return true; // At least one subset from Run3 is found in Run2
220 }
221 }
222 return false; // No subset from Run3 was found in Run2
223 };
224
225 bool result { false };
226 // hack for "HLT_e26_lhmedium_nod0_mu8noL1" case
227 // hack for "HLT_e24_lhmedium_L1EM20VHI_mu8noL1" type case
228 // hack for "HLT_mu11_2mu4noL1_nscan03_L1MU11_2MU6" type case
229 if ( std::regex_match(chain, SpecialCases::specialEchain) or
230 std::regex_match(chain, SpecialCases::specialElMuChain) or
231 std::regex_match(chain, SpecialCases::mu2MunoL1Special) ) {
232 result = isAnySubsetPresent(run3, run2);
233 } else {
234 // now subset checked on a level of objects, instead of group of objects
235 result = isAnySubsetPresent(run2, run3);
236 }
237
238 if (run2 != run3)
239 {
240 ATH_MSG_WARNING("Difference in combinations between Run2 and Run3 format for chain: " << chain << " parsed multiplicities " << ChainNameParser::multiplicities(chain));
241 ATH_MSG_WARNING("Run2 combs: " << run2);
242 ATH_MSG_WARNING("Run3 combs: " << run3);
243 }
244
245 if (not result) // previous not isSubset, loosened condition
246 {
247 ATH_MSG_WARNING("NOT PASSED: failed, Run2 objects are not within a subset of Run3 objects for chain: " << chain << " parsed multiplicities " << ChainNameParser::multiplicities(chain));
248 ATH_MSG_WARNING("Run2 combs: " << run2);
249 ATH_MSG_WARNING("Run3 combs: " << run3);
250 if ( m_failOnDifference ) {
251 return StatusCode::FAILURE;
252 }
253 }
254
255 return StatusCode::SUCCESS;
256 }
257
259 size_t counter = 0;
260 for ( const std::vector<const xAOD::IParticle*>& outerc: combs )
261 counter += outerc.size();
262 return counter == 0;
263 }
264
265} //> end namespace Trig
266
267
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
std::vector< size_t > vec
An algorithm that can be simultaneously executed in multiple threads.
StatusCode verifyFlatContent(const std::string &chain) const
PublicToolHandle< Trig::TrigDecisionTool > m_tdtRun3
StatusCode verifyCombinationsSize(const CombinationsVector &run2, const CombinationsVector &run3, const std::string &chain) const
PublicToolHandle< Trig::TrigDecisionTool > m_tdtRun2
PublicToolHandle< Trig::TrigDecisionTool > m_tdt
ToolHandle< Trig::IIParticleRetrievalTool > m_toolRun3
std::vector< std::vector< const xAOD::IParticle * > > CombinationsVector
StatusCode execute(const EventContext &context) const override
StatusCode initialize() override
std::set< std::set< const xAOD::IParticle * > > CombinationsSet
StatusCode verifyCombinationsContent(const CombinationsSet &run2, const CombinationsSet &run3, const std::string &chain) const
Gaudi::Property< bool > m_verifyCombinations
Gaudi::Property< bool > m_verifyCombinationsSize
Gaudi::Property< bool > m_failOnDifference
bool combinationsEmpty(const CombinationsVector &combs) const
ToolHandle< Trig::IIParticleRetrievalTool > m_toolRun2
Gaudi::Property< std::vector< std::string > > m_chains
NavigationTesterAlg(const std::string &name, ISvcLocator *pSvcLocator)
Class providing the definition of the 4-vector interface.
std::vector< int > multiplicities(const std::string &chain)
const std::regex gammaXeChain
const std::regex specialElMuChain
const std::vector< std::string > excludedChains
Definition SpecialCases.h:8
const std::regex specialEchain
const std::regex mu2MunoL1Special
The common trigger namespace for trigger analysis tools.
STL namespace.
ostream & operator<<(ostream &s, const SG::VarHandleKey &m)
ICaloAffectedTool is abstract interface for tools checking if 4 mom is in calo affected region.
std::ostream & operator<<(std::ostream &out, const std::pair< FIRST, SECOND > &pair)
Helper print operator.
DataVector< IParticle > IParticleContainer
Simple convenience declaration of IParticleContainer.