105 {
106
107
108 SG::ReadHandle<xAOD::IParticleContainer> particles_muons{"Muons", ctx};
109 SG::ReadHandle<xAOD::IParticleContainer> particles_electrons{"Electrons", ctx};
110 SG::ReadHandle<xAOD::IParticleContainer> particles_taus{"TauJets", ctx};
111 SG::ReadHandle<xAOD::IParticleContainer> particles_photons{"Photons", ctx};
112
113 std::map<std::string, SG::ReadHandle<xAOD::IParticleContainer>*>
read_handles;
118
119 if (!particles_muons.
isValid() || !particles_electrons.
isValid() ||
122 return StatusCode::FAILURE;
123 }
124
125 for (
const std::string& chain :
m_chains) {
127
128
129
130
132 ATH_MSG_DEBUG(
"Chain " << chain <<
" is on the exclusion list, skipping");
133 continue;
134 }
135
136
139
140
141 bool hasSupported = false;
142 for (const std::string& sig : ChainNameParseSignature) {
144 hasSupported = true;
145 break;
146 }
147 }
148 if (!hasSupported) {
149 ATH_MSG_DEBUG(
"Chain " << chain <<
" has no supported signatures, skipping");
150 continue;
151 }
153
154
155
156
157
158
159
160
161
162
163
164
165
166 const bool hasTau = std::find(ChainNameParseSignature.begin(),
167 ChainNameParseSignature.end(),
168 "tau") != ChainNameParseSignature.end();
169 const bool hasEMuG = std::any_of(ChainNameParseSignature.begin(),
170 ChainNameParseSignature.end(),
171 [](const std::string& s) { return s == "e" || s == "mu" || s == "g"; });
172 const bool tauListChain = hasTau && !hasEMuG;
173 const double drThreshold = (
m_drFromRun2Lists ? tauListChain : hasTau) ? 0.2 : 0.1;
174
175
176
178 std::replace(containerName.begin(), containerName.end(), '.', '_');
180 if (!
evtStore()->retrieve(composites, containerName).isSuccess()) {
183
184
185
186
188 if (nLegs > 0) {
189 ATH_MSG_INFO(
"Per-leg features of " << chain <<
" (no R2 reference):");
192 }
193 }
194 continue;
195 }
196
197
198
199
202 m_rerunOnlyChains[
chain] += 1;
203 }
204
205
206
207
208
209
210
211
212
213
215 std::vector<const xAOD::IParticle*> r2MatchedPool;
216 if (useLinearisedR2) {
219 for (const ElementLink<xAOD::IParticleContainer>& link : accMatched(*entry)) {
220 if (!
link.isValid())
continue;
222 if (std::find(r2MatchedPool.begin(), r2MatchedPool.end(), orig) == r2MatchedPool.end()) {
223 r2MatchedPool.push_back(orig);
224 }
225 }
226 }
227 ATH_MSG_DEBUG(
"Chain " << chain <<
" uses linearised R2 matching: "
228 << composites->size() << " TrigMatch entries -> pool of "
229 << r2MatchedPool.size() << " individually matched objects");
230 }
231
232 bool isR2R3different = false;
233 size_t nCombinationsTested = 0;
234 bool anyPassR2 = false;
235 bool anyPassR3 = false;
236
237 if (useLinearisedR2) {
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252 std::vector<const SG::ReadHandle<xAOD::IParticleContainer>*> doneContainers;
253 for (const std::string& sig : ChainNameParseSignature) {
256
257
258 if (std::find(doneContainers.begin(), doneContainers.end(), handleItr->second) != doneContainers.end()) continue;
259 doneContainers.push_back(handleItr->second);
260
261 for (const xAOD::IParticle* p : **(handleItr->second)) {
264
265 anyPassR2 |= passR2;
266 anyPassR3 |= passR3;
267
268 if (passR2 && !passR3) {
270 << " (per-object linearised check) - converted navigation may have lost this object");
271 ATH_MSG_ERROR(
" Particle pT=" <<
p->pt() <<
" eta=" <<
p->eta() <<
" phi=" <<
p->phi()
272 << " R2:1 R3:0");
273 isR2R3different = true;
274
275 {
277 m_failingChains[
chain] += 1;
278 }
279 }
280 else if (!passR2 && passR3) {
281 ATH_MSG_DEBUG(
"R3 passes but R2 fails (expected) for chain " << chain
282 << " (per-object linearised check)");
283 ATH_MSG_DEBUG(
" Particle pT=" <<
p->pt() <<
" eta=" <<
p->eta() <<
" phi=" <<
p->phi()
284 << " R2:0 R3:1");
285 }
286 else {
287 ++nCombinationsTested;
288 if (passR2 &&
msgLvl(MSG::DEBUG)) {
290 << " (per-object linearised check) passR2: " << passR2 << " passR3: " << passR3);
291 ATH_MSG_DEBUG(
" Particle pT=" <<
p->pt() <<
" eta=" <<
p->eta() <<
" phi=" <<
p->phi());
292 }
293 }
294 }
295 }
296 }
297 else {
298
299
300 HLT::NestedUniqueCombinationGenerator nucg;
301 ATH_MSG_DEBUG(
"NestedUniqueCombinationGenerator: " << ChainMultiplicity.size() <<
" legs, " << ChainNameParseSignature.size() <<
" signatures");
302
303 bool tooFewOffline = false;
304 for (size_t readhandlesIndex = 0; readhandlesIndex < ChainNameParseSignature.size(); readhandlesIndex++) {
305 const std::string&
sig = ChainNameParseSignature[readhandlesIndex];
307 ATH_MSG_DEBUG(
"Signature " << sig <<
" not supported, skipping chain " << chain);
308 continue;
309 }
311 const size_t nRequired = static_cast<size_t>(ChainMultiplicity[readhandlesIndex]);
313 << " offline objects, chain requires " << nRequired);
314
315
316 if (nOffline < nRequired) {
317 tooFewOffline = true;
318 break;
319 }
320 nucg.
add({nOffline, nRequired});
321 }
322 if (tooFewOffline) {
323 ATH_MSG_DEBUG(
"Not enough offline objects to form any combination for chain " << chain <<
", skipping");
324 continue;
325 }
326
327
328 do {
329 const std::vector<size_t> combination = nucg();
330 ++nucg;
331
332 std::vector<const xAOD::IParticle *>
particles;
333 size_t location_in_combination = 0;
334
335 for (size_t ChainNameIndex = 0; ChainNameIndex < ChainNameParseSignature.size(); ++ChainNameIndex) {
336 const std::string&
sig = ChainNameParseSignature[ChainNameIndex];
338
339 for (size_t ChainMultipIndex = 0; ChainMultipIndex < static_cast<size_t>(ChainMultiplicity[ChainNameIndex]); ++ChainMultipIndex) {
340 const xAOD::IParticle*
p = (*
read_handles[
sig])->
at(combination[location_in_combination]);
341 ATH_MSG_VERBOSE(
"objectIndex --> " << sig <<
" " << combination[location_in_combination]
342 <<
" pT: " <<
p->pt() <<
" eta: " <<
p->eta() <<
" phi: " <<
p->phi());
344 location_in_combination++;
345 }
346 }
347
348
349
350
351
352
353
354
355 bool duplicateOffline = false;
356 for (
size_t i = 0;
i <
particles.size() && !duplicateOffline; ++
i) {
357 for (
size_t j = i + 1;
j <
particles.size(); ++
j) {
358 if (particles[i] == particles[j]) {
359 duplicateOffline = true;
360 break;
361 }
362 }
363 }
364 if (duplicateOffline) {
365 ATH_MSG_VERBOSE(
"Skipping combination with a repeated offline object for chain " << chain);
366 continue;
367 }
368
369
370
371
372
373
376
377 anyPassR2 |= passR2;
378 anyPassR3 |= passR3;
379
380
381 if (passR2 && !passR3) {
383 << " - R3 conversion may be missing trigger information");
384 for (const auto& p : particles) {
387 ATH_MSG_ERROR(
" Particle pT=" <<
p->pt() <<
" eta=" <<
p->eta() <<
" phi=" <<
p->phi()
388 << " R2:" << r2 << " R3:" << r3);
389 }
390 isR2R3different = true;
391
392 {
394 m_failingChains[
chain] += 1;
395 }
396 }
397
398 else if (!passR2 && passR3) {
399 ATH_MSG_DEBUG(
"R3 passes but R2 fails (expected) for chain " << chain);
401 for (const auto& p : particles) {
404 ATH_MSG_DEBUG(
" Particle pT=" <<
p->pt() <<
" eta=" <<
p->eta() <<
" phi=" <<
p->phi()
405 << " R2:" << r2 << " R3:" << r3);
406 }
407 }
408 }
409
410 else {
411 ++nCombinationsTested;
413 ATH_MSG_DEBUG(
"R2/R3 match for chain " << chain <<
" passR2: " << passR2 <<
" passR3: " << passR3);
414 for (const auto& p : particles) {
417 ATH_MSG_DEBUG(
" Particle pT=" <<
p->pt() <<
" eta=" <<
p->eta() <<
" phi=" <<
p->phi()
418 << " R2:" << r2 << " R3:" << r3);
419 }
420 }
421 }
422 } while (nucg);
423
424 }
425
426
427
428 if (anyPassR3 && !anyPassR2) {
429 if (composites->empty()) {
430
431
432
433
434
435
436
438 << "but the R2 TrigMatch reference is EMPTY - unverifiable event");
440 m_emptyR2Chains[
chain] += 1;
441 }
442 else {
443 ATH_MSG_ERROR(
"Chain " << chain <<
": R3 found at least one match but R2 found none "
444 << "- possible inconsistency between converted navigation and TrigMatch container");
445 isR2R3different = true;
446
447
448
449
450
452 m_failingChains[
chain] += 1;
453 }
454 }
455
456 if (!isR2R3different && nCombinationsTested > 0) {
457 ATH_MSG_INFO(
"Chain " << chain <<
": R2/R3 agreement verified (" << nCombinationsTested
458 << (useLinearisedR2 ? " objects)" : " combinations)"));
459 }
460
461
463 ATH_MSG_DEBUG(
"################################### TrigMatch container for " << chain <<
" (" << composites->size() <<
" combinations)");
464 int comboIdx = 0;
466
468 const std::vector<ElementLink<xAOD::IParticleContainer>> featuresInCombination = accMatched(*combination);
469 ATH_MSG_DEBUG(
" Combo[" << comboIdx++ <<
"] (size=" << featuresInCombination.size() <<
"):");
470 for (const ElementLink<xAOD::IParticleContainer>& f : featuresInCombination) {
473 ATH_MSG_DEBUG(
" pt=" << iParticleR2->
pt() <<
" eta=" << iParticleR2->
eta() <<
" phi=" << iParticleR2->
phi()
474 <<
" [" <<
f.dataID() <<
":" <<
f.index() <<
"]");
475 } else {
477 }
478 }
479 }
480 }
481
482
483
486 if (nLegs == 0) {
487 ATH_MSG_ERROR(
"Could not determine number of legs for chain " << chain);
488 return StatusCode::FAILURE;
489 }
493 }
494
495
496 if (isR2R3different) {
498 if (nLegs == 0) {
499 ATH_MSG_ERROR(
"Could not determine number of legs for chain " << chain);
500 return StatusCode::FAILURE;
501 }
502
503
504 ATH_MSG_ERROR(
"R2 pre-matched objects for " << chain <<
":");
507 const std::vector<ElementLink<xAOD::IParticleContainer>> featuresInCombination = accMatched(*combination);
508 for (const ElementLink<xAOD::IParticleContainer>& f : featuresInCombination) {
509 if (!
f.isValid())
continue;
511 ATH_MSG_ERROR(
" R2 object: pT=" << iParticleR2->
pt() <<
" eta=" << iParticleR2->
eta() <<
" phi=" << iParticleR2->
phi());
512 }
513 }
514
515
519 }
520 }
521
522 return StatusCode::SUCCESS;
523}
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_VERBOSE(x,...)
#define ATH_MSG_INFO(x,...)
virtual void lock()=0
Interface to allow an object to lock itself when made const in SG.
size_t size() const
Number of registered mappings.
ServiceHandle< StoreGateSvc > & evtStore()
bool msgLvl(const MSG::Level lvl) const
void add(const UniqueCombinationGenerator &gen)
virtual bool isValid() override final
Can the handle be successfully dereferenced?
Gaudi::Property< bool > m_dumpFeaturesWithoutR2
static bool matchesAnyPattern(const std::string &chain, const std::vector< std::string > &patterns)
True if the chain name contains any of the patterns (substring match).
void dumpFeaturesPerLeg(const std::string &chain, std::size_t nLegs, MSG::Level level, const std::string &linkName="") const
Dump the per-leg R3 features of a chain at the given message level.
Gaudi::Property< std::vector< std::string > > m_chains
PublicToolHandle< Trig::MatchFromCompositeTool > m_matchFromCompositeTool
std::size_t numberOfLegs(const std::string &chain) const
Number of legs of a chain, derived from ChainNameParser::multiplicities().
Gaudi::Property< std::vector< std::string > > m_linearisedR2Chains
Gaudi::Property< bool > m_drFromRun2Lists
Gaudi::Property< bool > m_printSubfeatures
static const xAOD::IParticle * resolveOriginal(const xAOD::IParticle *p)
Resolve a possible shallow copy to its original object via the "originalObjectLink" decoration (mirro...
static bool matchLinearisedR2(std::vector< const xAOD::IParticle * > pool, const std::vector< const xAOD::IParticle * > &particles)
R2 verdict for chains with linearised TrigMatch layout (e.g.
Gaudi::Property< bool > m_r3MatchingRerun
std::mutex m_failingChainsMutex
PublicToolHandle< Trig::R3MatchingTool > m_matchingTool
Gaudi::Property< std::string > m_inputPrefix
Gaudi::Property< std::vector< std::string > > m_chainsToExclude
virtual double eta() const =0
The pseudorapidity ( ) of the particle.
virtual double pt() const =0
The transverse momentum ( ) of the particle.
virtual double phi() const =0
The azimuthal angle ( ) of the particle.
std::vector< int > multiplicities(const std::string &chain)
std::vector< std::string > signatures(const std::string &chain)
mapped_type at(key_type key) const
Look up an element in the map.
SG::ConstAccessor< T, ALLOC > ConstAccessor
pointer & link(pointer p) const
Return a reference to the link for an element.
float j(const xAOD::IParticle &, const xAOD::TrackMeasurementValidation &hit, const Eigen::Matrix3d &jab_inv)
static const unsigned int allowResurrectedDecision
static const unsigned int Physics
TrigCompositeContainer_v1 TrigCompositeContainer
Declare the latest version of the container.
TrigComposite_v1 TrigComposite
Declare the latest version of the class.