ATLAS Offline Software
Loading...
Searching...
No Matches
Calculator.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3*/
4
5// contact: jmaurer@cern.ch
6
8
9#include <iterator>
10#include <random>
11
15
16using namespace TrigGlobEffCorr;
17using std::placeholders::_1;
18using std::placeholders::_2;
19using std::placeholders::_3;
20using std::placeholders::_4;
21
23 unsigned nPeriodsToReserve)
24 : asg::AsgMessaging(&parent), m_parent(&parent) {
25 msg().setLevel(parent.msg().level());
26 m_periods.reserve(nPeriodsToReserve);
27}
28
30 const std::pair<unsigned, unsigned>& boundaries,
31 const std::string& combination, bool useToys,
32 std::size_t& uniqueElectronLeg,
33 std::size_t& uniquePhotonLeg) {
34 bool success = true;
35 m_parent = data.getParent();
36
37 auto triggers = data.parseTriggerString(combination, success);
38 if (!success)
39 return false;
40 if (!triggers.size()) {
41 ATH_MSG_ERROR("The trigger combination is empty!");
42 return false;
43 }
44
45 if (!findUniqueLeg(xAOD::Type::Electron, uniqueElectronLeg, triggers))
46 return false;
47 if (!findUniqueLeg(xAOD::Type::Photon, uniquePhotonLeg, triggers))
48 return false;
49
52 Helper helper(triggers);
53 if (helper.duplicates()) {
54 ATH_MSG_ERROR("The following combination of triggers contains duplicates: "
55 << combination);
56 return false;
57 }
58 if (!useToys) {
59 success = helper.findAndBindFunction();
60 if (!helper.m_formula) {
62 "This trigger combination is currently not supported with an "
63 "explicit formula (you may use toys instead, slower): "
64 << combination);
65 return false;
66 }
67 } else {
68 helper.m_formula = std::bind(&Calculator::globalEfficiency_Toys, ::_1, ::_2,
69 ::_3, triggers, ::_4);
70 }
71 if (success) {
72 if (data.adaptTriggerListForTriggerMatching(triggers)) {
73 m_periods.emplace_back(boundaries, std::move(helper.m_formula),
74 std::move(triggers));
75 } else {
76 if (m_parent->m_validTrigMatchTool)
77 return false;
78 m_periods.emplace_back(boundaries, std::move(helper.m_formula));
79 }
80 } else {
82 "Unspecified error occurred while trying to find the formula for the "
83 "trigger combination "
84 << combination);
85 }
86 return success;
87}
88
90 std::size_t& uniqueLeg,
91 const std::vector<TrigDef>& defs) {
92 if (uniqueLeg)
93 return true;
95 for (auto& def : defs) {
96 TriggerProperties tp(def);
97 for (auto itr = tp.cbegin(obj); itr != tp.cend(obj); ++itr) {
98 if (uniqueLeg && uniqueLeg != *itr) {
100 "The property 'ListOfLegsPerTool' needs to be filled as the "
101 "specified trigger combination involves several electron (or "
102 "photon) trigger legs");
103 return false;
104 }
105 uniqueLeg = *itr;
106 }
107 }
108 return true;
109}
110
111const Calculator::Period* Calculator::getPeriod(unsigned runNumber) const {
112 auto period =
113 std::find_if(m_periods.cbegin(), m_periods.cend(), [=](const Period& p) {
114 return runNumber >= p.m_boundaries.first &&
115 runNumber <= p.m_boundaries.second;
116 });
117 if (period == m_periods.end()) {
118 ATH_MSG_ERROR("No trigger combination has been specified for run "
119 << runNumber);
120 return nullptr;
121 }
122 return &*period;
123}
124
126 const LeptonList& leptons, unsigned runNumber,
127 Efficiencies& efficiencies) {
128 m_parent = &parent;
129 m_forceUnitSF = false;
130 auto period = getPeriod(runNumber);
131 if (!period)
132 return false;
133 m_cachedEfficiencies.clear();
134 bool success = period->m_formula &&
135 period->m_formula(this, leptons, runNumber, efficiencies);
136 if (m_forceUnitSF) {
137 efficiencies.data() = 1.;
138 efficiencies.mc() = 1.;
139 success = true;
140 }
141 return success;
142}
143
145 TrigGlobalEfficiencyCorrectionTool& parent, bool& matched,
146 std::unordered_map<std::string, bool>* matched_per_trigger,
147 const LeptonList& leptons, unsigned runNumber) {
148 matched = false;
149 if(matched_per_trigger) {
150 for(auto& [key, flag] : *matched_per_trigger) flag = false;
151 }
152
153 m_parent = &parent;
154 auto period = getPeriod(runNumber);
155 if (!period)
156 return false;
157 if (!period->m_triggers.size()) {
158 ATH_MSG_ERROR("Empty list of triggers for run number " << runNumber);
159 return false;
160 }
161 auto& trigMatchTool = m_parent->m_trigMatchTool;
162
165 const unsigned nLep = leptons.size();
166 std::vector<flat_set<std::size_t>> validLegs(leptons.size());
167 for (unsigned i = 0; i < nLep; ++i) {
168 if (!fillListOfLegsFor(leptons[i], period->m_triggers, validLegs[i]))
169 return false;
170 }
171
174 std::vector<flat_set<std::size_t>> firedLegs;
175 std::vector<const xAOD::IParticle*> trigLeptons;
176 const std::size_t magicWordHLT = 0xf7b8b87ef2917d66;
177
178 for (auto& trig : period->m_triggers) {
180 auto itr = m_parent->m_dictionary.find(trig.name ^ magicWordHLT);
181 if (itr == m_parent->m_dictionary.end()) {
182 itr = m_parent->m_dictionary
183 .emplace(trig.name ^ magicWordHLT,
184 "HLT_" + m_parent->m_dictionary.at(trig.name))
185 .first;
186 }
187 const std::string& chain = itr->second;
188
189 unsigned nLegs = 0;
190 if (trig.type & TT_SINGLELEPTON_FLAG)
191 nLegs = 1;
192 else if (trig.type & TT_DILEPTON_FLAG)
193 nLegs = 2;
194 else if (trig.type & TT_TRILEPTON_FLAG)
195 nLegs = 3;
196 else {
197 ATH_MSG_ERROR("Unsupported trigger (type = "
198 << std::hex << trig.type << std::dec << ") " << chain);
199 return false;
200 }
201 firedLegs.resize(nLegs);
202 trigLeptons.resize(nLegs);
203 for (unsigned i0 = 0; i0 < nLep; ++i0) {
204 firedLegs[0].swap(validLegs[i0]);
206 trigLeptons[0] = leptons[i0].particle();
207 if (nLegs == 1) {
208 // Check we have enough lepton(s) on trigger plateau and test the trigger matching
209 if(canTriggerBeFired(trig, firedLegs) && trigMatchTool->match(trigLeptons, chain)) {
210 matched = true;
211 if(!matched_per_trigger) return true;
212 if(matched_per_trigger->count(chain)) matched_per_trigger->at(chain) = true;
213 }
214 } else
215 for (unsigned i1 = i0 + 1; i1 < nLep; ++i1) {
216 firedLegs[1].swap(validLegs[i1]);
217 trigLeptons[1] = leptons[i1].particle();
218 if (nLegs == 2) {
219 if(canTriggerBeFired(trig, firedLegs) && trigMatchTool->match(trigLeptons, chain)) {
220 matched = true;
221 if(!matched_per_trigger) return true;
222 if(matched_per_trigger->count(chain)) matched_per_trigger->at(chain) = true;
223 }
224 } else
225 for (unsigned i2 = i1 + 1; i2 < nLep; ++i2) {
226 firedLegs[2].swap(validLegs[i2]);
227 trigLeptons[2] = leptons[i2].particle();
228 if(canTriggerBeFired(trig, firedLegs) && trigMatchTool->match(trigLeptons, chain)) {
229 matched = true;
230 if(!matched_per_trigger) return true;
231 if(matched_per_trigger->count(chain)) matched_per_trigger->at(chain) = true;
232 }
233 firedLegs[2].swap(validLegs[i2]);
234 }
235 firedLegs[1].swap(validLegs[i1]);
236 }
237 firedLegs[0].swap(
238 validLegs[i0]);
239 }
240 }
241 return true;
242}
243
246 std::vector<std::string>& triggers, unsigned runNumber) {
247 triggers.clear();
248 m_parent = &parent;
249 auto period = getPeriod(runNumber);
250 if (!period)
251 return false;
252 if (!period->m_triggers.size()) {
253 ATH_MSG_ERROR("Empty list of triggers for run number "
254 << runNumber
255 << " (was there a configuration issue? please check for "
256 "warnings during initialization)");
257 return false;
258 }
259 bool success = true;
260 auto notfound = parent.m_dictionary.end();
261 for (auto& trig : period->m_triggers) {
262 auto itr = parent.m_dictionary.find(trig.name);
263 if (itr == notfound) {
264 ATH_MSG_ERROR("can't retrieve name of trigger with hash "
265 << trig.name
266 << " (shouldn't happen; contact tool developers!)");
267 success = false;
268 } else
269 triggers.push_back(itr->second);
270 }
271 if (!success)
272 triggers.clear();
273 return success;
274}
275
277 unsigned runNumber,
278 std::size_t leg,
279 bool& success) {
280 auto insertion = m_cachedEfficiencies.emplace(std::make_pair(&lepton, leg),
281 Efficiencies());
282 Efficiencies& efficiencies = insertion.first->second;
283 if (insertion.second) {
285 switch (lepton.type()) {
287 res = m_parent->getTriggerLegEfficiencies(
288 lepton.electron(), runNumber, leg, lepton.tag(), efficiencies);
289 break;
290 case xAOD::Type::Muon:
291 res = m_parent->getTriggerLegEfficiencies(lepton.muon(), runNumber, leg,
292 lepton.tag(), efficiencies);
293 break;
295 res = m_parent->getTriggerLegEfficiencies(
296 lepton.photon(), runNumber, leg, lepton.tag(), efficiencies);
297 break;
298 default:
299 ATH_MSG_ERROR("Unsupported particle type");
300 }
301 switch (res) {
303 break;
305 m_forceUnitSF = true;
306 break;
308 [[fallthrough]];
309 default:
310 success = false;
311 efficiencies.data() = -777.;
312 efficiencies.mc() = -777.;
313 }
314 }
315 if (efficiencies.mc() == -777. && !m_forceUnitSF)
316 success = false;
317 return efficiencies;
318}
319
323template <typename Trig1L>
324auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber,
325 const Trig1L trig,
326 Efficiencies& globalEfficiencies)
327 -> std::enable_if_t<Trig1L::is1L(), bool> {
328 ATH_MSG_DEBUG("Entered Calculator::globalEfficiency_One1L() at line "
329 << __LINE__);
330 if (!trig) {
331 globalEfficiencies = {0.};
332 return true;
333 }
334 globalEfficiencies = {1.};
335 bool success = true;
336 for (auto& lepton : leptons) {
337 if (trig.irrelevantFor(lepton) || !aboveThreshold(lepton, trig()))
338 continue;
339 auto efficiencies =
340 getCachedTriggerLegEfficiencies(lepton, runNumber, trig(), success);
341 globalEfficiencies *= ~efficiencies;
342 }
343 globalEfficiencies = ~globalEfficiencies;
344 return success;
345}
346
350template <typename Trig1L_obj1, typename Trig1L_obj2>
351auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber,
352 const Trig1L_obj1 trig1,
353 const Trig1L_obj2 trig2,
354 Efficiencies& globalEfficiencies)
355 -> std::enable_if_t<Trig1L_obj1::is1L() && Trig1L_obj2::is1L() &&
356 Trig1L_obj1::object() != Trig1L_obj2::object(),
357 bool> {
358 ATH_MSG_DEBUG("Entered Calculator::globalEfficiency_Two1L() at line "
359 << __LINE__);
360 if (!trig1)
361 return globalEfficiency(leptons, runNumber, trig2, globalEfficiencies);
362 if (!trig2)
363 return globalEfficiency(leptons, runNumber, trig1, globalEfficiencies);
364 globalEfficiencies = {1.};
365 bool success = true;
366 for (auto& lepton : leptons) {
367 std::size_t leg;
368 if (trig1.relevantFor(lepton))
369 leg = trig1();
370 else if (trig2.relevantFor(lepton))
371 leg = trig2();
372 else
373 continue;
374 if (!aboveThreshold(lepton, leg))
375 continue;
376 auto efficiencies =
377 getCachedTriggerLegEfficiencies(lepton, runNumber, leg, success);
378 globalEfficiencies *= ~efficiencies;
379 }
380 globalEfficiencies = ~globalEfficiencies;
381 return success;
382}
383
387template <typename Trig1L>
388auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber,
389 const flat_set<Trig1L>& trigs,
390 Efficiencies& globalEfficiencies)
391 -> std::enable_if_t<Trig1L::is1L(), bool> {
392 ATH_MSG_DEBUG("Entered Calculator::globalEfficiency_Several1L() at line "
393 << __LINE__);
394 if (trigs.size() == 1)
395 return globalEfficiency(leptons, runNumber, *trigs.cbegin(),
396 globalEfficiencies);
397 if (!trigs.size()) {
398 globalEfficiencies = {0.};
399 return true;
400 }
401 globalEfficiencies = {1.};
402 bool success = true;
403 for (auto& lepton : leptons) {
404 if (Trig1L::irrelevantFor(lepton))
405 continue;
406 std::size_t loosestLeg =
407 getLoosestLegAboveThreshold(lepton, trigs, success);
408 if (loosestLeg && success) {
409 auto efficiencies = getCachedTriggerLegEfficiencies(lepton, runNumber,
410 loosestLeg, success);
411 globalEfficiencies *= ~efficiencies;
412 }
413 }
414 globalEfficiencies = ~globalEfficiencies;
415 return success;
416}
417
421template <typename Trig1L_obj1, typename Trig1L_obj2>
422auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber,
423 const flat_set<Trig1L_obj1>& trigs1,
424 const flat_set<Trig1L_obj2>& trigs2,
425 Efficiencies& globalEfficiencies)
426 -> std::enable_if_t<Trig1L_obj1::is1L() && Trig1L_obj2::is1L() &&
427 Trig1L_obj1::object() != Trig1L_obj2::object(),
428 bool> {
429 ATH_MSG_DEBUG("Entered Calculator::globalEfficiency_Several1L() at line "
430 << __LINE__);
431 if (trigs1.size() == 1 && trigs2.size() == 1) {
432 return globalEfficiency(leptons, runNumber, *trigs1.cbegin(),
433 *trigs2.cbegin(), globalEfficiencies);
434 }
435 if (!trigs1.size())
436 return globalEfficiency(leptons, runNumber, trigs2, globalEfficiencies);
437 if (!trigs2.size())
438 return globalEfficiency(leptons, runNumber, trigs1, globalEfficiencies);
439 globalEfficiencies = {1.};
440 bool success = true;
441 for (auto& lepton : leptons) {
442 std::size_t loosestLeg;
443 if (Trig1L_obj1::relevantFor(lepton))
444 loosestLeg = getLoosestLegAboveThreshold(lepton, trigs1, success);
445 else if (Trig1L_obj2::relevantFor(lepton))
446 loosestLeg = getLoosestLegAboveThreshold(lepton, trigs2, success);
447 else
448 continue;
449 if (loosestLeg && success) {
450 auto efficiencies = getCachedTriggerLegEfficiencies(lepton, runNumber,
451 loosestLeg, success);
452 globalEfficiencies *= ~efficiencies;
453 }
454 }
455 globalEfficiencies = ~globalEfficiencies;
456 return success;
457}
458
462template <typename Trig2Lmix>
463auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber,
464 const Trig2Lmix trig,
465 Efficiencies& globalEfficiencies)
466 -> std::enable_if_t<Trig2Lmix::is2Lmix(), bool> {
467 ATH_MSG_DEBUG("Entered Calculator::globalEfficiency_One2L() at line "
468 << __LINE__);
469 Efficiencies efficiencies[2];
470 bool success =
471 globalEfficiency(leptons, runNumber, trig.side1(), efficiencies[0]) &&
472 globalEfficiency(leptons, runNumber, trig.side2(), efficiencies[1]);
473 if (success)
474 globalEfficiencies = efficiencies[0] * efficiencies[1];
475 else
476 globalEfficiencies = {0.};
477 return success;
478}
479
483template <typename Trig2Lsym>
484auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber,
485 const Trig2Lsym trig,
486 Efficiencies& globalEfficiencies)
487 -> std::enable_if_t<Trig2Lsym::is2Lsym(), bool> {
488 ATH_MSG_DEBUG("Entered Calculator::globalEfficiency_One2L() at line "
489 << __LINE__);
490 globalEfficiencies = {0.};
491 if (!trig)
492 return true;
493 Efficiencies singleInefficiencies(1.);
494 bool success = true;
495 for (auto& lepton : leptons) {
496 if (trig.irrelevantFor(lepton) || !aboveThreshold(lepton, trig()))
497 continue;
498 auto efficiencies =
499 getCachedTriggerLegEfficiencies(lepton, runNumber, trig(), success);
500 globalEfficiencies = ~efficiencies * globalEfficiencies +
501 efficiencies * ~singleInefficiencies;
502 singleInefficiencies *= ~efficiencies;
503 }
504 return success;
505}
506
510template <typename Trig2Lasym>
511auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber,
512 const Trig2Lasym trig,
513 Efficiencies& globalEfficiencies)
514 -> std::enable_if_t<Trig2Lasym::is2Lasym(), bool> {
515 ATH_MSG_DEBUG("Entered Calculator::globalEfficiency_One2L() at line "
516 << __LINE__);
517 if (trig.symmetric())
518 return globalEfficiency(leptons, runNumber, trig.to_symmetric(),
519 globalEfficiencies);
520 globalEfficiencies = {0.};
521 if (!trig)
522 return true;
523 Efficiencies singleInefficiencies[2] = {{1.}, {1.}},
524 twoSingleInefficiencies = {1.};
525 bool success = true;
526 for (auto& lepton : leptons) {
527 if (trig.irrelevantFor(lepton))
528 continue;
529 Efficiencies efficiencies[2] = {{0.}, {0.}};
530 int loosest = 0;
531 if (aboveThreshold(lepton, trig(0))) {
532 efficiencies[0] =
533 getCachedTriggerLegEfficiencies(lepton, runNumber, trig(0), success);
534 if (aboveThreshold(lepton, trig(1))) {
535 efficiencies[1] = getCachedTriggerLegEfficiencies(lepton, runNumber,
536 trig(1), success);
537 loosest = m_parent->getLoosestLeg(lepton, trig(0), trig(1), success) ==
538 trig(1);
539 }
540 } else if (aboveThreshold(lepton, trig(1))) {
541 efficiencies[1] =
542 getCachedTriggerLegEfficiencies(lepton, runNumber, trig(1), success);
543 loosest = 1;
544 } else
545 continue;
546 const int tightest = 1 - loosest;
547 globalEfficiencies = ~efficiencies[loosest] * globalEfficiencies +
548 (efficiencies[loosest] - efficiencies[tightest]) *
549 ~singleInefficiencies[tightest] +
550 efficiencies[tightest] * ~twoSingleInefficiencies;
551 twoSingleInefficiencies *= ~efficiencies[loosest];
552 for (int i = 0; i < 2; ++i)
553 singleInefficiencies[i] *= ~efficiencies[i];
554 }
555 return success;
556}
557
561template <typename Trig2Lmix, typename Trig1L_obj1, typename Trig1L_obj2>
562auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber,
563 const Trig2Lmix trig2Lmix,
564 const flat_set<Trig1L_obj1>& trigs1L1,
565 const flat_set<Trig1L_obj2>& trigs1L2,
566 Efficiencies& globalEfficiencies)
567 -> std::enable_if_t<Trig2Lmix::is2Lmix() && Trig1L_obj1::is1L() &&
568 Trig2Lmix::object1() == Trig1L_obj1::object() &&
569 Trig1L_obj2::is1L() &&
570 Trig2Lmix::object2() == Trig1L_obj2::object(),
571 bool> {
572 ATH_MSG_DEBUG("Entered Calculator::globalEfficiency_One2LSeveral1L() at line "
573 << __LINE__);
574 if (!(trigs1L1.size() + trigs1L2.size()))
575 return globalEfficiency(leptons, runNumber, trig2Lmix, globalEfficiencies);
576 if (trig2Lmix.hiddenBy(trigs1L1) || trig2Lmix.hiddenBy(trigs1L2))
577 return globalEfficiency(leptons, runNumber, trigs1L1, trigs1L2,
578 globalEfficiencies);
579 Efficiencies efficiencies[4];
580 bool success =
581 globalEfficiency(leptons, runNumber, trigs1L1, efficiencies[0]) &&
582 globalEfficiency(leptons, runNumber, trigs1L2, efficiencies[1]) &&
583 globalEfficiency(leptons, runNumber, trig2Lmix.addTo(trigs1L1),
584 efficiencies[2]) &&
585 globalEfficiency(leptons, runNumber, trig2Lmix.addTo(trigs1L2),
586 efficiencies[3]);
587 if (success) {
588 globalEfficiencies = Efficiencies(1.) -
589 ~efficiencies[0] * ~efficiencies[1] +
590 (efficiencies[2] - efficiencies[0]) *
591 (efficiencies[3] - efficiencies[1]);
592 } else
593 globalEfficiencies = {0.};
594 return success;
595}
596
600template <typename Trig2L, typename Trig1L>
601inline auto Calculator::globalEfficiency(const LeptonList& leptons,
602 unsigned runNumber,
603 const Trig2L trig2L,
604 const Trig1L trig1L,
605 Efficiencies& globalEfficiencies)
606 -> std::enable_if_t<Trig2L::is2Lnomix() && Trig1L::is1L() &&
607 Trig2L::object() == Trig1L::object(),
608 bool> {
609 ATH_MSG_DEBUG("Entered Calculator::globalEfficiency_One2LSeveral1L() at line "
610 << __LINE__);
611 return globalEfficiency(leptons, runNumber, trig2L, flat_set<Trig1L>{trig1L},
612 globalEfficiencies);
613}
614
618template <typename Trig2Lsym, typename Trig1L>
619auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber,
620 const Trig2Lsym trig2L,
621 const flat_set<Trig1L>& trigs1L,
622 Efficiencies& globalEfficiencies)
623 -> std::enable_if_t<Trig2Lsym::is2Lsym() && Trig1L::is1L() &&
624 Trig1L::object() == Trig2Lsym::object(),
625 bool> {
626 ATH_MSG_DEBUG("Entered Calculator::globalEfficiency_One2LSeveral1L() at line "
627 << __LINE__);
628 if (!trigs1L.size())
629 return globalEfficiency(leptons, runNumber, trig2L, globalEfficiencies);
630 if (!trig2L || trig2L.hiddenBy(trigs1L))
631 return globalEfficiency(leptons, runNumber, trigs1L, globalEfficiencies);
632 globalEfficiencies = {0.};
633 Efficiencies twoSingleInefficiencies = {1.};
634 bool success = true;
635 for (auto& lepton : leptons) {
636 if (trig2L.irrelevantFor(lepton))
637 continue;
638 Efficiencies efficiencies1L(0.), efficiencies2L(0.);
639 const Efficiencies* loosestLegEfficiency;
640 std::size_t loosest1lepLeg =
641 getLoosestLegAboveThreshold(lepton, trigs1L, success);
642 if (loosest1lepLeg) {
643 efficiencies1L = getCachedTriggerLegEfficiencies(lepton, runNumber,
644 loosest1lepLeg, success);
645 if (aboveThreshold(lepton, trig2L())) {
646 efficiencies2L = getCachedTriggerLegEfficiencies(lepton, runNumber,
647 trig2L(), success);
648 loosestLegEfficiency =
649 (m_parent->getLoosestLeg(lepton, trig2L(), loosest1lepLeg,
650 success) == trig2L())
651 ? &efficiencies2L
652 : &efficiencies1L;
653 } else
654 loosestLegEfficiency = &efficiencies1L;
655 } else if (aboveThreshold(lepton, trig2L())) {
656 efficiencies2L =
657 getCachedTriggerLegEfficiencies(lepton, runNumber, trig2L(), success);
658 loosestLegEfficiency = &efficiencies2L;
659 } else
660 continue;
661 globalEfficiencies =
662 ~(*loosestLegEfficiency) * globalEfficiencies + efficiencies1L;
663 if (loosestLegEfficiency == &efficiencies2L)
664 globalEfficiencies +=
665 ~twoSingleInefficiencies * (efficiencies2L - efficiencies1L);
666 twoSingleInefficiencies *= ~(*loosestLegEfficiency);
667 }
668 return success;
669}
670
674template <typename Trig2Lasym, typename Trig1L>
675auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber,
676 const Trig2Lasym trig2L,
677 const flat_set<Trig1L>& trigs1L,
678 Efficiencies& globalEfficiencies)
679 -> std::enable_if_t<Trig2Lasym::is2Lasym() && Trig1L::is1L() &&
680 Trig1L::object() == Trig2Lasym::object(),
681 bool> {
682 ATH_MSG_DEBUG("Entered Calculator::globalEfficiency_One2LSeveral1L() at line "
683 << __LINE__);
684 if (trig2L.symmetric())
685 return globalEfficiency(leptons, runNumber, trig2L.to_symmetric(), trigs1L,
686 globalEfficiencies);
687 if (!trigs1L.size())
688 return globalEfficiency(leptons, runNumber, trig2L, globalEfficiencies);
689 if (!trig2L || trig2L.hiddenBy(trigs1L))
690 return globalEfficiency(leptons, runNumber, trigs1L, globalEfficiencies);
691 globalEfficiencies = {0.};
692 Efficiencies twoSingleInefficiencies[2] = {{1.}, {1.}},
693 threeSingleInefficiencies = {1.};
694 bool success = true;
695 for (auto& lepton : leptons) {
696 if (trig2L.irrelevantFor(lepton))
697 continue;
698 flat_set<std::size_t> validLegs;
699 for (std::size_t leg : trig2L.legs)
700 if (aboveThreshold(lepton, leg))
701 validLegs.insert(leg);
702 Efficiencies efficiencies1L = {0.};
703 std::size_t loosest1lepLeg =
704 getLoosestLegAboveThreshold(lepton, trigs1L, success);
705 if (loosest1lepLeg) {
706 efficiencies1L = getCachedTriggerLegEfficiencies(lepton, runNumber,
707 loosest1lepLeg, success);
708 validLegs.insert(loosest1lepLeg);
709 }
710 if (!validLegs.size())
711 continue;
712 auto looseLegs = m_parent->getTwoLoosestLegs(lepton, validLegs, success);
713 auto efficienciesLoose =
714 (looseLegs.first == loosest1lepLeg)
715 ? efficiencies1L
716 : getCachedTriggerLegEfficiencies(lepton, runNumber,
717 looseLegs.first, success);
718 Efficiencies efficienciesMedium = {0.};
719 if (validLegs.size() >= 2)
720 efficienciesMedium =
721 (looseLegs.second == loosest1lepLeg)
722 ? efficiencies1L
723 : getCachedTriggerLegEfficiencies(lepton, runNumber,
724 looseLegs.second, success);
725 globalEfficiencies =
726 ~efficienciesLoose * globalEfficiencies + efficiencies1L;
727 if (loosest1lepLeg != looseLegs.first) {
728 globalEfficiencies +=
729 (efficienciesLoose - efficienciesMedium) *
730 ~twoSingleInefficiencies[looseLegs.first == trig2L.legs[0]];
731 if (loosest1lepLeg != looseLegs.second)
732 globalEfficiencies +=
733 (efficienciesMedium - efficiencies1L) * ~threeSingleInefficiencies;
734 }
735 threeSingleInefficiencies *= ~efficienciesLoose;
736 twoSingleInefficiencies[0] *= (looseLegs.first != trig2L.legs[1])
737 ? ~efficienciesLoose
738 : ~efficienciesMedium;
739 twoSingleInefficiencies[1] *= (looseLegs.first != trig2L.legs[0])
740 ? ~efficienciesLoose
741 : ~efficienciesMedium;
742 }
743 return success;
744}
745
749template <typename Trig2Lsym, typename Trig1L>
750auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber,
751 const Trig2Lsym trig2L1,
752 const Trig2Lsym trig2L2,
753 const flat_set<Trig1L>& trigs1L,
754 Efficiencies& globalEfficiencies)
755 -> std::enable_if_t<Trig2Lsym::is2Lsym() && Trig1L::is1L() &&
756 Trig1L::object() == Trig2Lsym::object(),
757 bool> {
758 ATH_MSG_DEBUG("Entered Calculator::globalEfficiency_Two2LSeveral1L() at line "
759 << __LINE__);
760 if (!trig2L1 || trig2L1 == trig2L2 || trig2L1.hiddenBy(trigs1L))
761 return globalEfficiency(leptons, runNumber, trig2L2, trigs1L,
762 globalEfficiencies);
763 if (!trig2L2 || trig2L2.hiddenBy(trigs1L))
764 return globalEfficiency(leptons, runNumber, trig2L1, trigs1L,
765 globalEfficiencies);
766 globalEfficiencies = {0.};
767 Efficiencies singleInefficiencies{1.};
768 Efficiencies efficiencies2Lsym[2] = {{0.}, {0.}};
769
770 bool success = true;
771 for (auto& lepton : leptons) {
772 if (trig2L1.irrelevantFor(lepton))
773 continue;
774 flat_set<std::size_t> validLegs;
775 std::map<std::size_t, Efficiencies> efficiencies{{0, 0.}};
776 std::size_t loosest1lepLeg =
777 getLoosestLegAboveThreshold(lepton, trigs1L, success);
778 for (std::size_t leg : {loosest1lepLeg, trig2L1(), trig2L2()}) {
779 if (leg && aboveThreshold(lepton, leg)) {
780 validLegs.insert(leg);
781 efficiencies.emplace(leg, getCachedTriggerLegEfficiencies(
782 lepton, runNumber, leg, success));
783 } else
784 efficiencies.emplace(leg, 0.);
785 }
786 if (!validLegs.size())
787 continue;
788 auto looseLegs = m_parent->getTwoLoosestLegs(lepton, validLegs, success);
789 std::size_t lambda13 =
790 (looseLegs.first != trig2L2()) ? looseLegs.first : looseLegs.second;
791 std::size_t lambda23 =
792 (looseLegs.first != trig2L1()) ? looseLegs.first : looseLegs.second;
793 globalEfficiencies = globalEfficiencies * ~efficiencies[looseLegs.first] +
794 efficiencies[loosest1lepLeg];
795 if (looseLegs.first == trig2L1())
796 globalEfficiencies +=
797 efficiencies2Lsym[1] *
798 (efficiencies[trig2L1()] - efficiencies[looseLegs.second]);
799 if (looseLegs.first == trig2L2())
800 globalEfficiencies +=
801 efficiencies2Lsym[0] *
802 (efficiencies[trig2L2()] - efficiencies[looseLegs.second]);
803 if (looseLegs.first != loosest1lepLeg)
804 globalEfficiencies +=
805 ~singleInefficiencies *
806 (efficiencies[looseLegs.second] - efficiencies[loosest1lepLeg]);
807 efficiencies2Lsym[0] =
808 ~efficiencies[looseLegs.first] * efficiencies2Lsym[0] +
809 efficiencies[lambda23];
810 efficiencies2Lsym[1] =
811 ~efficiencies[looseLegs.first] * efficiencies2Lsym[1] +
812 efficiencies[lambda13];
813 if (looseLegs.first == trig2L1())
814 efficiencies2Lsym[0] +=
815 (efficiencies[trig2L1()] - efficiencies[lambda23]) *
816 ~singleInefficiencies;
817 if (looseLegs.first == trig2L2())
818 efficiencies2Lsym[1] +=
819 (efficiencies[trig2L2()] - efficiencies[lambda13]) *
820 ~singleInefficiencies;
821 singleInefficiencies *= ~efficiencies[looseLegs.first];
822 }
823 return success;
824}
825
829template <typename Trig2Lasym, typename Trig2Lsym, typename Trig1L>
830auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber,
831 const Trig2Lasym trig2Lasym,
832 const Trig2Lsym trig2Lsym,
833 const flat_set<Trig1L>& trigs1L,
834 Efficiencies& globalEfficiencies)
835 -> std::enable_if_t<Trig2Lasym::is2Lasym() && Trig2Lsym::is2Lsym() &&
836 Trig2Lsym::object() == Trig2Lasym::object() &&
837 Trig1L::is1L() &&
838 Trig1L::object() == Trig2Lasym::object(),
839 bool> {
840 ATH_MSG_DEBUG("Entered Calculator::globalEfficiency_Two2LSeveral1L() at line "
841 << __LINE__);
842 if (!trig2Lasym || trig2Lasym.hiddenBy(trigs1L))
843 return globalEfficiency(leptons, runNumber, trig2Lsym, trigs1L,
844 globalEfficiencies);
845 if (!trig2Lsym || trig2Lsym.hiddenBy(trigs1L))
846 return globalEfficiency(leptons, runNumber, trig2Lasym, trigs1L,
847 globalEfficiencies);
848 if (trig2Lasym(0) == trig2Lsym() || trig2Lasym(1) == trig2Lsym()) {
850 "implementation -- does this function work properly when the two 2L "
851 "triggers have one leg in common? Must be checked");
852 return false;
853 }
854 if (trig2Lasym.symmetric())
855 return globalEfficiency(leptons, runNumber, trig2Lasym.to_symmetric(),
856 trig2Lsym, trigs1L, globalEfficiencies);
857 globalEfficiencies = {0.};
858 Efficiencies singleInefficiencies[3] = {{1.}, {1.}, {1.}};
859 Efficiencies efficiencies2Lasym{0.},
860 efficiencies2Lsym[3] = {{0.}, {0.}, {0.}};
861
862 bool success = true;
863 for (auto& lepton : leptons) {
864 if (trig2Lasym.irrelevantFor(lepton))
865 continue;
866 flat_set<std::size_t> validLegs;
867 std::map<std::size_t, Efficiencies> efficiencies{{0, 0.}};
868 std::size_t loosest1lepLeg =
869 getLoosestLegAboveThreshold(lepton, trigs1L, success);
870 for (std::size_t leg :
871 {trig2Lasym(0), trig2Lasym(1), trig2Lsym(), loosest1lepLeg}) {
872 if (leg && aboveThreshold(lepton, leg)) {
873 validLegs.insert(leg);
874 efficiencies.emplace(leg, getCachedTriggerLegEfficiencies(
875 lepton, runNumber, leg, success));
876 } else
877 efficiencies.emplace(leg, 0.);
878 }
879 if (!validLegs.size())
880 continue;
881
882 const auto sortedLegs = m_parent->getSortedLegs(lepton, validLegs, success);
883 if (!success)
884 return false;
885 std::size_t loosestLeg = sortedLegs[0];
886 std::size_t secondLoosestLeg = validLegs.size() >= 2 ? sortedLegs[1] : 0;
887 std::size_t secondTightestLeg = validLegs.size() >= 3 ? sortedLegs[2] : 0;
888 std::size_t tightestLeg = validLegs.size() >= 4 ? sortedLegs[3] : 0;
889 std::size_t lambda124 =
890 (loosestLeg != trig2Lasym(1)) ? loosestLeg : secondLoosestLeg;
891 std::size_t lambda134 =
892 (loosestLeg != trig2Lasym(0)) ? loosestLeg : secondLoosestLeg;
893 std::size_t lambda234 =
894 (loosestLeg != trig2Lsym()) ? loosestLeg : secondLoosestLeg;
895 std::size_t lambda14 = (lambda124 != trig2Lasym(0)) ? lambda124
896 : (lambda134 != trig2Lasym(1)) ? lambda134
897 : secondTightestLeg;
898 std::size_t lambda24 = (lambda124 != trig2Lsym()) ? lambda124
899 : (lambda234 != trig2Lasym(1)) ? lambda234
900 : secondTightestLeg;
901 std::size_t lambda34 = (lambda134 != trig2Lsym()) ? lambda134
902 : (lambda234 != trig2Lasym(0)) ? lambda234
903 : secondTightestLeg;
904 std::size_t tau13 = 0, tau12 = 0, tau23 = 0;
905 if (loosestLeg == trig2Lsym() || loosestLeg == trig2Lasym(0))
906 tau12 = (loosestLeg == trig2Lsym()) ? trig2Lasym(0) : trig2Lsym();
907 else if (secondLoosestLeg == trig2Lsym() ||
908 secondLoosestLeg == trig2Lasym(0))
909 tau12 = (secondLoosestLeg == trig2Lsym()) ? trig2Lasym(0) : trig2Lsym();
910 else if (secondTightestLeg == trig2Lsym() ||
911 secondTightestLeg == trig2Lasym(0))
912 tau12 = (secondTightestLeg == trig2Lsym()) ? trig2Lasym(0) : trig2Lsym();
913 else if (tightestLeg == trig2Lsym() || tightestLeg == trig2Lasym(0))
914 tau12 = (tightestLeg == trig2Lsym()) ? trig2Lasym(0) : trig2Lsym();
915 if (loosestLeg == trig2Lsym() || loosestLeg == trig2Lasym(1))
916 tau13 = (loosestLeg == trig2Lsym()) ? trig2Lasym(1) : trig2Lsym();
917 else if (secondLoosestLeg == trig2Lsym() ||
918 secondLoosestLeg == trig2Lasym(1))
919 tau13 = (secondLoosestLeg == trig2Lsym()) ? trig2Lasym(1) : trig2Lsym();
920 else if (secondTightestLeg == trig2Lsym() ||
921 secondTightestLeg == trig2Lasym(1))
922 tau13 = (secondTightestLeg == trig2Lsym()) ? trig2Lasym(1) : trig2Lsym();
923 else if (tightestLeg == trig2Lsym() || tightestLeg == trig2Lasym(1))
924 tau13 = (tightestLeg == trig2Lsym()) ? trig2Lasym(1) : trig2Lsym();
925 if (loosestLeg == trig2Lasym(0) || loosestLeg == trig2Lasym(1))
926 tau23 = (loosestLeg == trig2Lasym(0)) ? trig2Lasym(1) : trig2Lasym(0);
927 else if (secondLoosestLeg == trig2Lasym(0) ||
928 secondLoosestLeg == trig2Lasym(1))
929 tau23 =
930 (secondLoosestLeg == trig2Lasym(0)) ? trig2Lasym(1) : trig2Lasym(0);
931 else if (secondTightestLeg == trig2Lasym(0) ||
932 secondTightestLeg == trig2Lasym(1))
933 tau23 =
934 (secondTightestLeg == trig2Lasym(0)) ? trig2Lasym(1) : trig2Lasym(0);
935 else if (tightestLeg == trig2Lasym(0) || tightestLeg == trig2Lasym(1))
936 tau23 = (tightestLeg == trig2Lasym(0)) ? trig2Lasym(1) : trig2Lasym(0);
937
939 globalEfficiencies =
940 globalEfficiencies * ~efficiencies[loosestLeg] +
941 efficiencies[loosest1lepLeg] +
942 (efficiencies[tau13] - efficiencies[secondTightestLeg]) *
943 ~singleInefficiencies[0] +
944 (efficiencies[tau12] - efficiencies[secondTightestLeg]) *
945 ~singleInefficiencies[1] +
946 (efficiencies[tau23] - efficiencies[secondTightestLeg]) *
947 efficiencies2Lsym[2];
948 if (loosestLeg == trig2Lsym())
949 globalEfficiencies +=
950 (efficiencies[trig2Lsym()] - efficiencies[secondLoosestLeg]) *
951 efficiencies2Lasym;
952 else if (loosestLeg == trig2Lasym(1))
953 globalEfficiencies +=
954 (efficiencies[trig2Lasym(1)] - efficiencies[secondLoosestLeg]) *
955 efficiencies2Lsym[0];
956 else if (loosestLeg == trig2Lasym(0))
957 globalEfficiencies +=
958 (efficiencies[trig2Lasym(0)] - efficiencies[secondLoosestLeg]) *
959 efficiencies2Lsym[1];
960 if (secondTightestLeg &&
961 tightestLeg == loosest1lepLeg)
963 globalEfficiencies +=
964 (efficiencies[secondTightestLeg] - efficiencies[tightestLeg]) *
965 ~singleInefficiencies[2];
966
967 efficiencies2Lasym =
968 ~efficiencies[loosestLeg] * efficiencies2Lasym + efficiencies[lambda14];
969 if (loosestLeg == trig2Lasym(0) || loosestLeg == trig2Lasym(1)) {
972 efficiencies2Lasym +=
973 (efficiencies[loosestLeg] - efficiencies[secondLoosestLeg]) *
974 ~singleInefficiencies[loosestLeg == trig2Lasym(0)] +
975 (efficiencies[secondLoosestLeg] - efficiencies[lambda14]) *
976 ~singleInefficiencies[2];
977 }
978 efficiencies2Lsym[0] = ~efficiencies[lambda124] * efficiencies2Lsym[0] +
979 efficiencies[lambda24];
980 efficiencies2Lsym[1] = ~efficiencies[lambda134] * efficiencies2Lsym[1] +
981 efficiencies[lambda34];
982 efficiencies2Lsym[2] = ~efficiencies[loosestLeg] * efficiencies2Lsym[2] +
983 efficiencies[lambda234];
984 if (lambda124 == trig2Lsym())
985 efficiencies2Lsym[0] +=
986 (efficiencies[trig2Lsym()] - efficiencies[lambda24]) *
987 ~singleInefficiencies[0];
988 if (lambda134 == trig2Lsym())
989 efficiencies2Lsym[1] +=
990 (efficiencies[trig2Lsym()] - efficiencies[lambda34]) *
991 ~singleInefficiencies[1];
992 if (loosestLeg == trig2Lsym())
993 efficiencies2Lsym[2] +=
994 (efficiencies[trig2Lsym()] - efficiencies[lambda234]) *
995 ~singleInefficiencies[2];
996 singleInefficiencies[0] *= ~efficiencies[lambda124];
997 singleInefficiencies[1] *= ~efficiencies[lambda134];
998 singleInefficiencies[2] *= ~efficiencies[loosestLeg];
999 }
1000 return success;
1001}
1002
1006template <typename Trig3Lsym>
1007auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber,
1008 const Trig3Lsym trig,
1009 Efficiencies& globalEfficiencies)
1010 -> std::enable_if_t<Trig3Lsym::is3Lsym(), bool> {
1011 ATH_MSG_DEBUG("Entered Calculator::globalEfficiency_One3L() at line "
1012 << __LINE__);
1013 globalEfficiencies = {0.};
1014 Efficiencies singleInefficiencies{1.}, efficiencies2L{0.};
1015 bool success = true;
1016 for (auto& lepton : leptons) {
1017 if (trig.irrelevantFor(lepton) || !aboveThreshold(lepton, trig()))
1018 continue;
1019 auto efficiencies =
1020 getCachedTriggerLegEfficiencies(lepton, runNumber, trig(), success);
1021 globalEfficiencies =
1022 ~efficiencies * globalEfficiencies + efficiencies * efficiencies2L;
1023 efficiencies2L =
1024 ~efficiencies * efficiencies2L + efficiencies * ~singleInefficiencies;
1025 singleInefficiencies *= ~efficiencies;
1026 }
1027 return success;
1028}
1029
1033template <typename Trig3Lhalfsym>
1034auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber,
1035 const Trig3Lhalfsym trig,
1036 Efficiencies& globalEfficiencies)
1037 -> std::enable_if_t<Trig3Lhalfsym::is3Lhalfsym(), bool> {
1038 ATH_MSG_DEBUG("Entered Calculator::globalEfficiency_One3L() at line "
1039 << __LINE__);
1040 if (trig.symmetric())
1041 return globalEfficiency(leptons, runNumber, trig.to_symmetric(),
1042 globalEfficiencies);
1043 globalEfficiencies = {0.};
1044 Efficiencies singleInefficiencies[2] = {{1.}, {1.}},
1045 twoSingleInefficiencies{1.};
1046 Efficiencies efficiencies2Lsym{0.}, efficiencies2Lasym{0.},
1047 efficiencies2L2L{0.};
1048 bool success = true;
1049 for (auto& lepton : leptons) {
1050 if (trig.irrelevantFor(lepton))
1051 continue;
1052 Efficiencies efficiencies[2] = {{0.}, {0.}};
1053 const int asym = 0, sym = 1;
1054 int loosestLeg;
1055 if (aboveThreshold(lepton, trig.asymLeg())) {
1056 efficiencies[asym] = getCachedTriggerLegEfficiencies(
1057 lepton, runNumber, trig.asymLeg(), success);
1058 if (aboveThreshold(lepton, trig.symLeg())) {
1059 efficiencies[sym] = getCachedTriggerLegEfficiencies(
1060 lepton, runNumber, trig.symLeg(), success);
1061 loosestLeg =
1062 m_parent->getLoosestLeg(lepton, trig.asymLeg(), trig.symLeg(),
1063 success) == trig.asymLeg()
1064 ? asym
1065 : sym;
1066 } else
1067 loosestLeg = asym;
1068 } else if (aboveThreshold(lepton, trig.symLeg())) {
1069 efficiencies[sym] = getCachedTriggerLegEfficiencies(
1070 lepton, runNumber, trig.symLeg(), success);
1071 loosestLeg = sym;
1072 } else
1073 continue;
1074 Efficiencies delta = efficiencies[asym] - efficiencies[sym];
1075 if (loosestLeg == asym) {
1076 globalEfficiencies = ~efficiencies[asym] * globalEfficiencies +
1077 efficiencies[sym] * efficiencies2L2L +
1078 delta * efficiencies2Lsym;
1079 efficiencies2L2L = ~efficiencies[asym] * efficiencies2L2L +
1080 efficiencies[sym] * ~twoSingleInefficiencies +
1081 delta * ~singleInefficiencies[sym];
1082 efficiencies2Lasym = ~efficiencies[asym] * efficiencies2Lasym +
1083 efficiencies[sym] * ~twoSingleInefficiencies +
1084 delta * ~singleInefficiencies[sym];
1085 } else {
1086 globalEfficiencies = ~efficiencies[sym] * globalEfficiencies +
1087 efficiencies[asym] * efficiencies2L2L -
1088 delta * efficiencies2Lasym;
1089 efficiencies2L2L = ~efficiencies[sym] * efficiencies2L2L +
1090 efficiencies[sym] * ~twoSingleInefficiencies;
1091 efficiencies2Lasym = ~efficiencies[sym] * efficiencies2Lasym +
1092 efficiencies[asym] * ~twoSingleInefficiencies -
1093 delta * ~singleInefficiencies[asym];
1094 }
1095 efficiencies2Lsym = ~efficiencies[sym] * efficiencies2Lsym +
1096 efficiencies[sym] * ~singleInefficiencies[sym];
1097 twoSingleInefficiencies *= ~efficiencies[loosestLeg];
1098 singleInefficiencies[sym] *= ~efficiencies[sym];
1099 singleInefficiencies[asym] *= ~efficiencies[asym];
1100 }
1101 return success;
1102}
1103
1107template <typename Trig2L, typename Trig2Lmix>
1108auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber,
1109 const Trig2L trig2L,
1110 const Trig2Lmix trig2Lmix,
1111 Efficiencies& globalEfficiencies)
1112 -> std::enable_if_t<Trig2L::is2Lnomix() && Trig2Lmix::is2Lmix() &&
1113 (Trig2Lmix::object1() == Trig2L::object() ||
1114 Trig2Lmix::object2() == Trig2L::object()),
1115 bool> {
1116 ATH_MSG_DEBUG("Entered Calculator::globalEfficiency_Two2L() at line "
1117 << __LINE__);
1118 Efficiencies efficiencies1L, efficiencies2L, efficiencies2Lor1L;
1119 bool success =
1120 globalEfficiency(leptons, runNumber,
1121 trig2Lmix.template antiside<Trig2L>(), efficiencies1L);
1122 success =
1123 success && globalEfficiency(leptons, runNumber, trig2L, efficiencies2L);
1124 success = success && globalEfficiency(leptons, runNumber, trig2L,
1125 trig2Lmix.template side<Trig2L>(),
1126 efficiencies2Lor1L);
1127 globalEfficiencies =
1128 efficiencies2L * ~efficiencies1L + efficiencies1L * efficiencies2Lor1L;
1129 return success;
1130}
1131
1136template <typename Trig2L_obj1, typename Trig2L_obj2, typename Trig2Lmix>
1137auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber,
1138 const Trig2L_obj1 trig2L_obj1,
1139 const Trig2L_obj2 trig2L_obj2,
1140 const Trig2Lmix trig2Lmix,
1141 Efficiencies& globalEfficiencies)
1142 -> std::enable_if_t<Trig2Lmix::is2Lmix() && Trig2L_obj1::is2Lnomix() &&
1143 Trig2L_obj1::object() == Trig2Lmix::object1() &&
1144 Trig2L_obj2::is2Lnomix() &&
1145 Trig2L_obj2::object() == Trig2Lmix::object2(),
1146
1147 bool> {
1148 ATH_MSG_DEBUG("Entered Calculator::globalEfficiency_Three2L() at line "
1149 << __LINE__);
1150 Efficiencies efficiencies2L[2] = {{0.}, {0.}},
1151 efficiencies2Lor1L[2] = {{0.}, {0.}};
1152 bool success = true;
1153 if (trig2L_obj1) {
1154 success = success && globalEfficiency(leptons, runNumber, trig2L_obj1,
1155 efficiencies2L[0]);
1156 if (trig2Lmix)
1157 success =
1158 success && globalEfficiency(leptons, runNumber, trig2L_obj1,
1159 trig2Lmix.template side<Trig2L_obj1>(),
1160 efficiencies2Lor1L[0]);
1161 else
1162 efficiencies2Lor1L[0] = efficiencies2L[0];
1163 } else if (trig2Lmix)
1164 success =
1165 success && globalEfficiency(leptons, runNumber,
1166 trig2Lmix.template side<Trig2L_obj1>(),
1167 efficiencies2Lor1L[0]);
1168 if (trig2L_obj2) {
1169 success = success && globalEfficiency(leptons, runNumber, trig2L_obj2,
1170 efficiencies2L[1]);
1171 if (trig2Lmix)
1172 success =
1173 success && globalEfficiency(leptons, runNumber, trig2L_obj2,
1174 trig2Lmix.template side<Trig2L_obj2>(),
1175 efficiencies2Lor1L[1]);
1176 else
1177 efficiencies2Lor1L[1] = efficiencies2L[1];
1178 } else if (trig2Lmix)
1179 success =
1180 success && globalEfficiency(leptons, runNumber,
1181 trig2Lmix.template side<Trig2L_obj2>(),
1182 efficiencies2Lor1L[1]);
1183 globalEfficiencies = efficiencies2L[0] * ~efficiencies2Lor1L[1] +
1184 efficiencies2L[1] * ~efficiencies2Lor1L[0] +
1185 efficiencies2Lor1L[0] * efficiencies2Lor1L[1];
1186 return success;
1187}
1188
1192template <typename Trig2L_obj1, typename Trig2L_obj2, typename Trig2Lmix,
1193 typename Trig1L_obj1, typename Trig1L_obj2>
1194auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber,
1195 const Trig2L_obj1 trig2L_obj1,
1196 const Trig2L_obj2 trig2L_obj2,
1197 const Trig2Lmix trig2Lmix,
1198 const flat_set<Trig1L_obj1>& trigs1L_obj1,
1199 const flat_set<Trig1L_obj2>& trigs1L_obj2,
1200 Efficiencies& globalEfficiencies)
1201 -> std::enable_if_t<Trig2Lmix::is2Lmix() && Trig2L_obj1::is2Lnomix() &&
1202 Trig2L_obj1::object() == Trig2Lmix::object1() &&
1203 Trig2L_obj2::is2Lnomix() &&
1204 Trig2L_obj2::object() == Trig2Lmix::object2() &&
1205 Trig1L_obj1::is1L() &&
1206 Trig1L_obj1::object() == Trig2Lmix::object1() &&
1207 Trig1L_obj2::is1L() &&
1208 Trig1L_obj2::object() == Trig2Lmix::object2(),
1209
1210 bool> {
1212 "Entered Calculator::globalEfficiency_Three2LSeveral1L() at line "
1213 << __LINE__);
1214 Efficiencies efficiencies[4];
1215 bool success = true;
1216 if (trig2L_obj1)
1217 success = success && globalEfficiency(leptons, runNumber, trig2L_obj1,
1218 trigs1L_obj1, efficiencies[0]);
1219 else
1220 success = success && globalEfficiency(leptons, runNumber, trigs1L_obj1,
1221 efficiencies[0]);
1222 if (trig2L_obj2)
1223 success = success && globalEfficiency(leptons, runNumber, trig2L_obj2,
1224 trigs1L_obj2, efficiencies[1]);
1225 else
1226 success = success && globalEfficiency(leptons, runNumber, trigs1L_obj2,
1227 efficiencies[1]);
1228 if (trig2Lmix && !trig2Lmix.hiddenBy(trigs1L_obj1)) {
1229 auto t = trig2Lmix.addTo(trigs1L_obj1);
1230 if (trig2L_obj1)
1231 success = success && globalEfficiency(leptons, runNumber, trig2L_obj1, t,
1232 efficiencies[2]);
1233 else
1234 success =
1235 success && globalEfficiency(leptons, runNumber, t, efficiencies[2]);
1236 } else
1237 efficiencies[2] = efficiencies[0];
1238 if (trig2Lmix && !trig2Lmix.hiddenBy(trigs1L_obj2)) {
1239 auto t = trig2Lmix.addTo(trigs1L_obj2);
1240 if (trig2L_obj2)
1241 success = success && globalEfficiency(leptons, runNumber, trig2L_obj2, t,
1242 efficiencies[3]);
1243 else
1244 success =
1245 success && globalEfficiency(leptons, runNumber, t, efficiencies[3]);
1246 } else
1247 efficiencies[3] = efficiencies[1];
1248 globalEfficiencies =
1249 Efficiencies(1.) - ~efficiencies[0] * ~efficiencies[1] +
1250 (efficiencies[2] - efficiencies[0]) * (efficiencies[3] - efficiencies[1]);
1251 return success;
1252}
1253
1258template <typename Trig2L_obj1, typename Trig2Lsym_obj1, typename Trig2L_obj2,
1259 typename Trig2Lsym_obj2, typename Trig2Lmix, typename Trig1L_obj1,
1260 typename Trig1L_obj2>
1262 const LeptonList& leptons, unsigned runNumber,
1263 const Trig2L_obj1 trig2L_obj1, const Trig2Lsym_obj1 trig2Lsym_obj1,
1264 const Trig2L_obj2 trig2L_obj2, const Trig2Lsym_obj2 trig2Lsym_obj2,
1265 const Trig2Lmix trig2Lmix1, const Trig2Lmix trig2Lmix2,
1266 const flat_set<Trig1L_obj1>& trigs1L_obj1,
1267 const flat_set<Trig1L_obj2>& trigs1L_obj2, Efficiencies& globalEfficiencies)
1268 -> std::enable_if_t<Trig2Lmix::is2Lmix() && Trig2L_obj1::is2Lnomix() &&
1269 Trig2L_obj1::object() == Trig2Lmix::object1() &&
1270 Trig2L_obj2::is2Lnomix() &&
1271 Trig2L_obj2::object() == Trig2Lmix::object2() &&
1272 Trig2Lsym_obj1::is2Lsym() &&
1273 Trig2Lsym_obj1::object() == Trig2Lmix::object1() &&
1274 Trig2Lsym_obj2::is2Lsym() &&
1275 Trig2Lsym_obj2::object() == Trig2Lmix::object2() &&
1276 Trig1L_obj1::is1L() &&
1277 Trig1L_obj1::object() == Trig2Lmix::object1() &&
1278 Trig1L_obj2::is1L() &&
1279 Trig1L_obj2::object() == Trig2Lmix::object2(),
1280 bool> {
1281 ATH_MSG_DEBUG("Entered Calculator::globalEfficiency_Six2LSeveral1L() at line "
1282 << __LINE__);
1283
1284 auto singleObjectFactor = [=](auto trig2L, auto trig2Lsym, auto& trigs1L,
1285 Efficiencies(&efficiencies)[4]) -> bool {
1286 auto eval_for = [=](const auto& trigs1L_extended,
1287 Efficiencies& eff) -> bool {
1288 if (trig2L && trig2Lsym)
1289 return this->globalEfficiency(leptons, runNumber, trig2L, trig2Lsym,
1290 trigs1L_extended, eff);
1291 else if (trig2L)
1292 return this->globalEfficiency(leptons, runNumber, trig2L,
1293 trigs1L_extended, eff);
1294 else if (trig2Lsym)
1295 return this->globalEfficiency(leptons, runNumber, trig2Lsym,
1296 trigs1L_extended, eff);
1297 else
1298 return this->globalEfficiency(leptons, runNumber, trigs1L_extended,
1299 eff);
1300 };
1301
1302 bool success = eval_for(trigs1L, efficiencies[0]);
1303 if (trig2Lmix1)
1304 success = success && eval_for(trig2Lmix1.addTo(trigs1L), efficiencies[1]);
1305 else
1306 efficiencies[1] = efficiencies[0];
1307 if (trig2Lmix2) {
1308 auto t = trig2Lmix2.addTo(trigs1L);
1309 success = success && eval_for(t, efficiencies[2]);
1310 if (trig2Lmix1)
1311 success&& eval_for(trig2Lmix1.addTo(t), efficiencies[3]);
1312 else
1313 efficiencies[3] = efficiencies[2];
1314 } else {
1315 efficiencies[2] = efficiencies[0];
1316 efficiencies[3] = efficiencies[1];
1317 }
1318 return success;
1319 };
1320
1321 Efficiencies efficiencies1[4], efficiencies2[4];
1322 bool success = singleObjectFactor(trig2L_obj1, trig2Lsym_obj1, trigs1L_obj1,
1323 efficiencies1) &&
1324 singleObjectFactor(trig2L_obj2, trig2Lsym_obj2, trigs1L_obj2,
1325 efficiencies2);
1326 globalEfficiencies = Efficiencies(1.) -
1327 ~efficiencies1[0] * ~efficiencies2[0] +
1328 (efficiencies1[1] - efficiencies1[0]) *
1329 (efficiencies2[1] - efficiencies2[0]) +
1330 (efficiencies1[2] - efficiencies1[0]) *
1331 (efficiencies2[2] - efficiencies2[0]) -
1332 (efficiencies1[0] - efficiencies1[1] - efficiencies1[2] +
1333 efficiencies1[3]) *
1334 (efficiencies2[0] - efficiencies2[1] -
1335 efficiencies2[2] + efficiencies2[3]);
1336 return success;
1337}
1338
1342template <typename Trig3Lmix>
1343auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber,
1344 const Trig3Lmix trig,
1345 Efficiencies& globalEfficiencies)
1346 -> std::enable_if_t<Trig3Lmix::is3Lmix(), bool> {
1347 ATH_MSG_DEBUG("Entered Calculator::globalEfficiency_One3L() at line "
1348 << __LINE__);
1349 Efficiencies efficiencies[2] = {{0.}, {0.}};
1350 bool success = globalEfficiency(leptons, runNumber,
1351 trig.template side<Trig3Lmix::object1()>(),
1352 efficiencies[0]) &&
1353 globalEfficiency(leptons, runNumber,
1354 trig.template side<Trig3Lmix::object2()>(),
1355 efficiencies[1]);
1356 globalEfficiencies = efficiencies[0] * efficiencies[1];
1357 return success;
1358}
1359
1363template <typename Trig3Lmix1, typename Trig3Lmix2>
1364auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber,
1365 const Trig3Lmix1 trig1,
1366 const Trig3Lmix2 trig2,
1367 Efficiencies& globalEfficiencies)
1368 -> std::enable_if_t<Trig3Lmix1::is3Lmix() && Trig3Lmix2::is3Lmix() &&
1369 Trig3Lmix1::object1() == Trig3Lmix2::object2() &&
1370 Trig3Lmix1::object2() == Trig3Lmix2::object1(),
1371 bool> {
1372 ATH_MSG_DEBUG("Entered Calculator::globalEfficiency_Two3L() at line "
1373 << __LINE__);
1374 Efficiencies efficiencies[6] = {{0.}, {0.}, {0.}, {0.}, {0.}, {0.}};
1375 auto trig2La = trig1.template side<Trig3Lmix1::object1()>();
1376 auto trig1La = trig2.template side<Trig3Lmix2::object2()>();
1377 bool success =
1378 globalEfficiency(leptons, runNumber, trig1La, efficiencies[0]) &&
1379 globalEfficiency(leptons, runNumber, trig2La, efficiencies[1]);
1380 if (!trig2La.hiddenBy(trig1La))
1381 success = success && globalEfficiency(leptons, runNumber, trig2La, trig1La,
1382 efficiencies[2]);
1383 else
1384 efficiencies[2] = efficiencies[0];
1385 auto trig2Lb = trig2.template side<Trig3Lmix2::object1()>();
1386 auto trig1Lb = trig1.template side<Trig3Lmix1::object2()>();
1387 success = success &&
1388 globalEfficiency(leptons, runNumber, trig1Lb, efficiencies[3]) &&
1389 globalEfficiency(leptons, runNumber, trig2Lb, efficiencies[4]);
1390 if (!trig2Lb.hiddenBy(trig1Lb))
1391 success = success && globalEfficiency(leptons, runNumber, trig2Lb, trig1Lb,
1392 efficiencies[5]);
1393 else
1394 efficiencies[5] = efficiencies[3];
1395 globalEfficiencies =
1396 efficiencies[0] * efficiencies[4] + efficiencies[3] * efficiencies[1] +
1397 (efficiencies[2] - efficiencies[0] - efficiencies[1]) *
1398 (efficiencies[3] + efficiencies[4] - efficiencies[5]);
1399 return success;
1400}
1401
1405template <typename Trig4Lsym>
1406auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber,
1407 const Trig4Lsym trig,
1408 Efficiencies& globalEfficiencies)
1409 -> std::enable_if_t<Trig4Lsym::is4Lsym(), bool> {
1410 ATH_MSG_DEBUG("Entered Calculator::globalEfficiency_One4L() at line "
1411 << __LINE__);
1412 globalEfficiencies = {0.};
1413 Efficiencies singleInefficiencies{1.}, efficiencies2L{0.}, efficiencies3L{0.};
1414 bool success = true;
1415 for (auto& lepton : leptons) {
1416 if (trig.irrelevantFor(lepton) || !aboveThreshold(lepton, trig()))
1417 continue;
1418 auto efficiencies =
1419 getCachedTriggerLegEfficiencies(lepton, runNumber, trig(), success);
1420 globalEfficiencies =
1421 ~efficiencies * globalEfficiencies + efficiencies * efficiencies3L;
1422 efficiencies3L =
1423 ~efficiencies * efficiencies3L + efficiencies * efficiencies2L;
1424 efficiencies2L =
1425 ~efficiencies * efficiencies2L + efficiencies * ~singleInefficiencies;
1426 singleInefficiencies *= ~efficiencies;
1427 }
1428 return success;
1429}
1430
1432 const LeptonList& leptons, unsigned runNumber, GlobEffFunc func1,
1433 GlobEffFunc func2, Efficiencies& globalEfficiencies) {
1434 Efficiencies efficiencies[2];
1435 if (!func1(this, leptons, runNumber, efficiencies[0]))
1436 return false;
1437 if (!func2(this, leptons, runNumber, efficiencies[1]))
1438 return false;
1439 globalEfficiencies = ~(~efficiencies[0] * ~efficiencies[1]);
1440 return true;
1441}
1442
1444 const LeptonList& leptons, unsigned runNumber, GlobEffFunc func1,
1445 GlobEffFunc func2, GlobEffFunc func3, Efficiencies& globalEfficiencies) {
1446 Efficiencies efficiencies[3];
1447 if (!func1(this, leptons, runNumber, efficiencies[0]))
1448 return false;
1449 if (!func2(this, leptons, runNumber, efficiencies[1]))
1450 return false;
1451 if (!func3(this, leptons, runNumber, efficiencies[2]))
1452 return false;
1453 globalEfficiencies =
1454 ~(~efficiencies[0] * ~efficiencies[1] * ~efficiencies[2]);
1455 return true;
1456}
1457
1459 const std::vector<TrigDef>& triggers,
1460 flat_set<std::size_t>& validLegs) const {
1461 validLegs.clear();
1462 for (auto& trig : triggers) {
1463 TriggerProperties tp(trig);
1464 if (!tp.valid()) {
1465 ATH_MSG_ERROR("Unrecognized trigger type " << trig.type);
1466 return false;
1467 }
1468 auto end = tp.cend(lepton.type());
1469 for (auto itr = tp.cbegin(lepton.type()); itr != end; ++itr)
1470 if (aboveThreshold(lepton, *itr))
1471 validLegs.emplace(*itr);
1472 }
1473 return true;
1474}
1475
1477 const TrigDef& trig,
1478 const std::vector<flat_set<std::size_t>>& firedLegs) const {
1479 const int nLegs = static_cast<int>(std::count_if(
1480 trig.leg.begin(), trig.leg.end(), [](auto x) { return x != 0ul; }));
1481 const int sameLegs = static_cast<int>(
1482 std::count(trig.leg.begin(), trig.leg.end(), trig.leg[0]));
1483 if (sameLegs == nLegs) {
1484 // single-lepton and symmetric multilepton triggers
1485 return std::count_if(firedLegs.cbegin(), firedLegs.cend(), [&](auto& legs) {
1486 return legs.count(trig.leg[0]);
1487 }) >= nLegs;
1488 } else if (nLegs == 2) {
1489 // asymmetric or mixed-flavour dilepton triggers
1490 bool n0 = false, n1 = false;
1491 for (auto& legs : firedLegs) {
1492 if (n0 && legs.count(trig.leg[1]))
1493 return true;
1494 if (n1 && legs.count(trig.leg[0]))
1495 return true;
1496 n0 = n0 || legs.count(trig.leg[0]);
1497 n1 = n1 || legs.count(trig.leg[1]);
1498 }
1499 } else if (nLegs == 3) {
1500 // other trilepton triggers
1501 auto end = firedLegs.end();
1502 for (auto legs0 = firedLegs.begin(); legs0 != end; ++legs0) {
1503 for (int i = 0; i < 3; ++i) {
1504 if (!legs0->count(trig.leg[i]))
1505 continue;
1506 for (auto legs1 = legs0 + 1; legs1 != end; ++legs1) {
1507 for (int j = 1; j < 3; ++j) {
1508 if (!legs1->count(trig.leg[(i + j) % 3]))
1509 continue;
1510 for (auto legs2 = legs1 + 1; legs2 != end; ++legs2) {
1511 if (legs2->count(trig.leg[(i + 3 - j) % 3]))
1512 return true;
1513 }
1514 }
1515 }
1516 }
1517 }
1518 } else {
1519 ATH_MSG_ERROR("incomplete support of 4-lepton triggers.");
1520 }
1521 return false;
1522}
1523
1525 unsigned runNumber,
1526 const std::vector<TrigDef>& triggers,
1527 Efficiencies& globalEfficiencies) {
1528 ATH_MSG_DEBUG("Entered Calculator::globalEfficiency_Toys() at line "
1529 << __LINE__);
1530 globalEfficiencies = {0.};
1531 if (m_parent->m_numberOfToys <= 0) {
1532 ATH_MSG_ERROR("The specified number of toys is <= 0");
1533 return false;
1534 }
1535 std::map<const Lepton*, std::vector<std::pair<std::size_t, Efficiencies>>>
1536 leptonEfficiencies;
1537 for (auto& lepton : leptons) {
1538 flat_set<std::size_t> validLegs;
1539 if (!fillListOfLegsFor(lepton, triggers, validLegs))
1540 return false;
1541 auto& efficiencies = leptonEfficiencies[&lepton];
1542 const int nLegs = validLegs.size();
1543 if (nLegs) {
1544 bool success = true;
1545 for (std::size_t leg :
1546 m_parent->getSortedLegs(lepton, validLegs, success)) {
1547 efficiencies.emplace_back(leg, getCachedTriggerLegEfficiencies(
1548 lepton, runNumber, leg, success));
1549 }
1550 if (!success)
1551 return false;
1552 }
1553 }
1554 unsigned long seed;
1555 if (!m_parent->m_useInternalSeed) {
1556 if (!m_parent->retrieveEventNumber(seed)) {
1557 ATH_MSG_WARNING("Will use internal seed instead of event number");
1558 seed = m_parent->m_seed++;
1559 }
1560 } else
1561 seed = m_parent->m_seed++;
1562 std::mt19937_64 randomEngine(seed);
1563 std::uniform_real_distribution<double> uniformPdf(0., 1.);
1564 std::vector<flat_set<std::size_t>> firedLegs(leptonEfficiencies.size());
1565 unsigned long nPassed[2] = {0, 0};
1566 for (unsigned long toy = 0; toy < m_parent->m_numberOfToys; ++toy) {
1567 for (int step = 0; step < 2; ++step)
1568 {
1569 auto legs = firedLegs.begin();
1570 for (auto& kv : leptonEfficiencies) {
1571 legs->clear();
1572 double x = uniformPdf(randomEngine);
1573 for (auto& p : kv.second) {
1574 if (x < (step ? p.second.mc() : p.second.data()))
1575 legs->emplace(p.first);
1576 }
1577 ++legs;
1578 }
1579 for (auto& trig : triggers) {
1580 if (!canTriggerBeFired(trig, firedLegs))
1581 continue;
1582 ++nPassed[step];
1583 break;
1584 }
1585 }
1586 }
1587 globalEfficiencies.data() =
1588 double(nPassed[0]) / double(m_parent->m_numberOfToys);
1589 globalEfficiencies.mc() =
1590 double(nPassed[1]) / double(m_parent->m_numberOfToys);
1591 return true;
1592}
1593
1594Calculator::Helper::Helper(const std::vector<TrigDef>& defs)
1595 : m_formula(nullptr), m_defs(defs) {}
1596
1597bool Calculator::Helper::duplicates() const {
1598 for (auto itr1 = m_defs.cbegin(); itr1 != m_defs.cend(); ++itr1)
1599 for (auto itr2 = itr1 + 1; itr2 != m_defs.cend(); ++itr2)
1600 if (itr1->type == itr2->type && itr1->leg == itr2->leg)
1601 return true;
1602 return false;
1603}
1604
1607{
1608template <typename T>
1609struct TrigGlobEffCorr::Calculator::Helper::BindPackedParam {
1610 using TrigType = T;
1611 using ArgType = std::add_const_t<T>;
1612 static constexpr bool multiple() { return false; }
1613 static constexpr bool optional() { return false; }
1614 static void add(T& arg, ImportData::TrigDef& def) { arg.setDefinition(def); }
1615 static constexpr bool valid(const T& arg) { return bool(arg); }
1616};
1617
1618template <typename T>
1619struct TrigGlobEffCorr::Calculator::Helper::BindPackedParam<flat_set<T>> {
1620 using TrigType = T;
1621 using ArgType = const flat_set<T>&;
1622 static constexpr bool multiple() { return true; }
1623 static constexpr bool optional() { return false; }
1624 static void add(flat_set<T>& arg, ImportData::TrigDef& def) {
1625 arg.emplace().first->setDefinition(def);
1626 }
1627 static constexpr bool valid(const flat_set<T>& arg) { return arg.size(); }
1628};
1629
1630template <typename T>
1631struct TrigGlobEffCorr::Calculator::Helper::BindPackedParam<
1632 Calculator::Helper::Optional<T>> {
1635 static constexpr bool multiple() { return BindPackedParam<T>::multiple(); }
1636 static constexpr bool optional() { return true; }
1637 static void add(std::remove_cv_t<std::remove_reference_t<ArgType>>& arg,
1638 ImportData::TrigDef def) {
1639 BindPackedParam<T>::add(arg, def);
1640 }
1641 static constexpr bool valid(ArgType& arg) {
1642 return BindPackedParam<T>::valid(arg);
1643 }
1644};
1645} // namespace TrigGlobEffCorr
1646
1647template <typename Param>
1648auto Calculator::Helper::extract() {
1649 std::remove_cv_t<std::remove_reference_t<typename Param::ArgType>> trigs;
1650 for (auto& def : m_defs) {
1651 if (def.used || def.type != Param::TrigType::type())
1652 continue;
1653 def.used = true;
1654 Param::add(trigs, def);
1655 if (!Param::multiple())
1656 break;
1657 }
1658 if (!Param::optional() && !Param::valid(trigs))
1659 throw NoSuchTrigger();
1660 return trigs;
1661}
1662
1663template <typename... Trigs>
1664bool Calculator::Helper::bindFunction() {
1665 for (auto& def : m_defs)
1666 def.used = false;
1667 using fnptr = bool (Calculator::*)(
1668 const LeptonList&, unsigned, typename BindPackedParam<Trigs>::ArgType...,
1669 Efficiencies&);
1670 try {
1671 m_formula =
1672 std::bind<fnptr>(&Calculator::globalEfficiency, ::_1, ::_2, ::_3,
1673 extract<BindPackedParam<Trigs>>()..., ::_4);
1674 if (std::all_of(m_defs.cbegin(), m_defs.cend(),
1675 [](auto& def) { return def.used; }))
1676 return true;
1677 } catch (NoSuchTrigger) {
1678 }
1679 m_formula = nullptr;
1680 return false;
1681}
1682
1683template <TriggerType object_flag>
1684bool Calculator::Helper::findAndBindFunction()
1686{
1688 using A1L = flat_set<typename A::T_1>;
1689 using A_2sym = typename A::T_2sym;
1690 using A_2asym = typename A::T_2asym;
1691 if (m_n2L + m_n3L + m_n4L == 0) {
1693 } else if (m_n2L == 1 && m_n3L + m_n4L == 0) {
1696 } else if (m_n2L == 2 && m_n3L + m_n4L == 0) {
1698 bindFunction<A_2asym, A_2sym, Optional<A1L>>();
1699 } else if (m_n3L == 1 && m_n1L + m_n2L + m_n4L == 0) {
1702 } else if (m_n4L == 1 && m_n1L + m_n2L + m_n3L == 0) {
1704 }
1705 return false;
1706}
1707
1708template <TriggerType object_flag1, TriggerType object_flag2>
1709bool Calculator::Helper::findAndBindFunction()
1711{
1716 using A_1 = typename A::T_1;
1717 using B_1 = typename B::T_1;
1718 using OA1L = Optional<flat_set<A_1>>;
1719 using OB1L = Optional<flat_set<B_1>>;
1720 using A_2sym = typename A::T_2sym;
1721 using B_2sym = typename B::T_2sym;
1722 using A_2asym = typename A::T_2asym;
1723 using B_2asym = typename B::T_2asym;
1724 using AB_1_1 = typename AB::T_1_1;
1725
1728 if (m_n1L > 0 && m_n2L + m_n3L + m_n4L == 0) {
1729 return bindFunction<A_1, B_1>() ||
1731 } else if (m_n2L == 1 &&
1732 m_n3L + m_n4L ==
1733 0) { // one dilepton trigger (+ single-lepton triggers)
1734 return bindFunction<AB_1_1>() ||
1736 } else if (m_n2L >= 2 && m_n2L <= 6 &&
1737 m_n3L + m_n4L ==
1738 0) { // several dilepton triggers (+ single-lepton triggers)
1739 return
1746 OA1L, OB1L>() ||
1748 OA1L, OB1L>() ||
1750 OA1L, OB1L>() ||
1752 OA1L, OB1L>()
1756 OA1L, OB1L>() ||
1759 OB1L>() ||
1762 OB1L>() ||
1765 OB1L>();
1766 } else if (m_n3L == 1 &&
1767 m_n1L + m_n2L + m_n4L == 0) { // one mixed trilepton trigger
1772 } else if (m_n3L == 2 &&
1773 m_n1L + m_n2L + m_n4L == 0) { // two mixed trilepton triggers
1778 }
1779 return false;
1780}
1781
1782bool Calculator::Helper::findAndBindFunction()
1783{
1784 auto countTriggers = [&](auto nlep_flag) {
1785 return std::count_if(m_defs.cbegin(), m_defs.cend(),
1786 [=](auto& def) { return def.type & nlep_flag; });
1787 };
1788 m_n1L = countTriggers(TT_SINGLELEPTON_FLAG);
1789 m_n2L = countTriggers(TT_DILEPTON_FLAG);
1790 m_n3L = countTriggers(TT_TRILEPTON_FLAG);
1791 m_n4L = countTriggers(TT_TETRALEPTON_FLAG);
1792 auto exclusively = [&](auto obj_flags) {
1793 return std::none_of(m_defs.cbegin(), m_defs.cend(), [=](auto& def) {
1794 return def.type & TT_MASK_FLAVOUR & ~obj_flags;
1795 });
1796 };
1797
1799 if (exclusively(TT_ELECTRON_FLAG))
1801 if (exclusively(TT_MUON_FLAG))
1803 if (exclusively(TT_PHOTON_FLAG))
1805
1808 bool success = false;
1809 if (exclusively(TT_ELECTRON_FLAG | TT_MUON_FLAG))
1811 else if (exclusively(TT_ELECTRON_FLAG | TT_PHOTON_FLAG))
1813 else if (exclusively(TT_MUON_FLAG | TT_PHOTON_FLAG))
1815 if (success)
1816 return true;
1817
1819 std::vector<Helper> helpers;
1820 for (auto obj_flag : {TT_ELECTRON_FLAG, TT_MUON_FLAG, TT_PHOTON_FLAG}) {
1821 if (std::any_of(m_defs.cbegin(),
1822 m_defs.cend(),
1824 [&](auto& def) {
1825 return (def.type & obj_flag) &&
1826 TriggerProperties(def.type).mixed();
1827 }))
1828 continue;
1829 std::vector<ImportData::TrigDef> trigs1, trigs2;
1830 std::partition_copy(m_defs.begin(), m_defs.end(),
1831 std::back_inserter(trigs1), std::back_inserter(trigs2),
1832 [&](auto& def) { return (def.type & obj_flag); });
1833 m_defs.swap(trigs2);
1834 if (!trigs1.size())
1835 continue;
1836 helpers.emplace_back(trigs1);
1837 if (!helpers.back().findAndBindFunction())
1838 return false;
1839 }
1840 if (helpers.size()) {
1841 if (m_defs.size()) {
1842 if (!findAndBindFunction())
1843 return false;
1844 if (helpers.size() == 1)
1846 ::_2, ::_3, std::move(m_formula),
1847 std::move(helpers[0].m_formula), ::_4);
1848 else if (helpers.size() == 2)
1850 ::_2, ::_3, std::move(m_formula),
1851 std::move(helpers[0].m_formula),
1852 std::move(helpers[1].m_formula), ::_4);
1853 else {
1854 m_formula = nullptr;
1855 return false;
1856 }
1857 } else {
1858 if (helpers.size() == 2)
1860 ::_2, ::_3, std::move(helpers[0].m_formula),
1861 std::move(helpers[1].m_formula), ::_4);
1862 else if (helpers.size() == 3)
1864 ::_2, ::_3, std::move(helpers[0].m_formula),
1865 std::move(helpers[1].m_formula),
1866 std::move(helpers[2].m_formula), ::_4);
1867 else
1868 return false;
1869 }
1870 return true;
1871 }
1872
1873 return false;
1874}
#define ATH_MSG_ERROR(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
boost::container::flat_set< Key > flat_set
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
std::pair< std::vector< unsigned int >, bool > res
TrigGlobEffCorr::Efficiencies Efficiencies
#define x
std::vector< TrigDef > m_defs
Definition Calculator.h:300
bool findAndBindFunction()
top-level function
std::function< bool(Calculator *, const LeptonList &, unsigned, Efficiencies &)> m_formula
Definition Calculator.h:295
TrigGlobalEfficiencyCorrectionTool * m_parent
Definition Calculator.h:66
std::vector< Period > m_periods
pointer updated at each call to compute() because the parent tool might have been moved in-between
Definition Calculator.h:69
std::map< std::pair< const Lepton *, std::size_t >, Efficiencies > m_cachedEfficiencies
Definition Calculator.h:71
bool checkTriggerMatching(TrigGlobalEfficiencyCorrectionTool &parent, bool &matched, const LeptonList &leptons, unsigned runNumber)
auto globalEfficiency(const LeptonList &, unsigned, const Trig1L, Efficiencies &) -> std::enable_if_t< Trig1L::is1L(), bool >
One single-lepton trigger.
auto getLoosestLegAboveThreshold(const Lepton &lepton, const flat_set< Trig1L > &trigs, bool &success) -> std::enable_if_t< Trig1L::is1L(), std::size_t >
Definition Calculator.h:78
Efficiencies getCachedTriggerLegEfficiencies(const Lepton &lepton, unsigned runNumber, std::size_t leg, bool &success)
bool canTriggerBeFired(const TrigDef &trig, const std::vector< flat_set< std::size_t > > &firedLegs) const
TrigGlobalEfficiencyCorrectionTool::LeptonList LeptonList
Definition Calculator.h:27
bool addPeriod(ImportData &data, const std::pair< unsigned, unsigned > &boundaries, const std::string &combination, bool useToys, std::size_t &uniqueElectronLeg, std::size_t &uniquePhotonLeg)
std::function< bool(Calculator *, const LeptonList &, unsigned, Efficiencies &)> GlobEffFunc
Definition Calculator.h:29
TrigGlobEffCorr::ImportData::TrigDef TrigDef
Definition Calculator.h:28
bool getRelevantTriggersForUser(TrigGlobalEfficiencyCorrectionTool &parent, std::vector< std::string > &triggers, unsigned runNumber)
bool fillListOfLegsFor(const Lepton &lepton, const std::vector< TrigDef > &triggers, flat_set< std::size_t > &validLegs) const
bool globalEfficiency_Factorized2(const LeptonList &leptons, unsigned runNumber, GlobEffFunc func1, GlobEffFunc func2, Efficiencies &globalEfficiencies)
bool compute(TrigGlobalEfficiencyCorrectionTool &parent, const LeptonList &leptons, unsigned runNumber, Efficiencies &efficiencies)
const Period * getPeriod(unsigned runNumber) const
bool findUniqueLeg(xAOD::Type::ObjectType obj, std::size_t &uniqueLeg, const std::vector< TrigDef > &defs)
bool globalEfficiency_Factorized3(const LeptonList &leptons, unsigned runNumber, GlobEffFunc func1, GlobEffFunc func2, GlobEffFunc func3, Efficiencies &globalEfficiencies)
Calculator(TrigGlobalEfficiencyCorrectionTool &parent, unsigned nPeriodsToReserve)
bool globalEfficiency_Toys(const LeptonList &, unsigned, const std::vector< TrigDef > &triggers, Efficiencies &)
bool aboveThreshold(const Lepton &p, std::size_t leg) const
Definition Calculator.h:74
const xAOD::Muon * muon() const
Definition Lepton.h:34
std::size_t tag() const
Definition Lepton.h:30
const xAOD::Electron * electron() const
Definition Lepton.h:31
const xAOD::Photon * photon() const
Definition Lepton.h:37
xAOD::Type::ObjectType type() const
Definition Lepton.h:29
MsgStream & msg() const
The standard message stream.
AsgMessaging(const std::string &name)
Constructor with a name.
the template specializations below must be enclosed in this namespace
ObjectType
Type of objects that have a representation in the xAOD EDM.
Definition ObjectType.h:32
@ Photon
The object is a photon.
Definition ObjectType.h:47
@ Muon
The object is a muon.
Definition ObjectType.h:48
@ Electron
The object is an electron.
Definition ObjectType.h:46
hold the test vectors and ease the comparison
to decorate the parameters of the findAndBind() function(s)
Definition Calculator.h:317
std::array< std::size_t, 4 > leg
Definition ImportData.h:93
static void add(std::remove_cv_t< std::remove_reference_t< ArgType > > &arg, ImportData::TrigDef def)