17 using std::placeholders::_1;
18 using std::placeholders::_2;
19 using std::placeholders::_3;
20 using std::placeholders::_4;
23 unsigned nPeriodsToReserve)
30 const std::pair<unsigned, unsigned>& boundaries,
31 const std::string& combination,
bool useToys,
32 std::size_t& uniqueElectronLeg,
33 std::size_t& uniquePhotonLeg) {
37 auto triggers =
data.parseTriggerString(combination, success);
54 ATH_MSG_ERROR(
"The following combination of triggers contains duplicates: "
59 success =
helper.findAndBindFunction();
62 "This trigger combination is currently not supported with an "
63 "explicit formula (you may use toys instead, slower): "
82 "Unspecified error occurred while trying to find the formula for the "
83 "trigger combination "
90 std::size_t& uniqueLeg,
91 const std::vector<TrigDef>& defs) {
94 for (
auto& def : defs) {
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");
114 return runNumber >= p.m_boundaries.first &&
115 runNumber <= p.m_boundaries.second;
118 ATH_MSG_ERROR(
"No trigger combination has been specified for run "
134 bool success =
period->m_formula &&
146 std::unordered_map<std::string, bool>* matched_per_trigger,
149 if(matched_per_trigger) {
150 for(
auto& [
key,
flag] : *matched_per_trigger)
flag =
false;
157 if (!
period->m_triggers.size()) {
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) {
174 std::vector<flat_set<std::size_t>> firedLegs;
175 std::vector<const xAOD::IParticle*> trigLeptons;
176 const std::size_t magicWordHLT = 0xf7b8b87ef2917d66;
178 for (
auto& trig :
period->m_triggers) {
183 .emplace(trig.name ^ magicWordHLT,
187 const std::string&
chain = itr->second;
198 << std::hex << trig.type << std::dec <<
") " <<
chain);
201 firedLegs.resize(nLegs);
202 trigLeptons.resize(nLegs);
203 for (
unsigned i0 = 0; i0 < nLep; ++i0) {
204 firedLegs[0].swap(validLegs[i0]);
205 trigLeptons[0] = leptons[i0].particle();
211 if(!matched_per_trigger)
return true;
212 if(matched_per_trigger->count(
chain)) matched_per_trigger->at(
chain) =
true;
215 for (
unsigned i1 = i0 + 1; i1 < nLep; ++i1) {
216 firedLegs[1].swap(validLegs[i1]);
217 trigLeptons[1] = leptons[i1].particle();
221 if(!matched_per_trigger)
return true;
222 if(matched_per_trigger->count(
chain)) matched_per_trigger->at(
chain) =
true;
225 for (
unsigned i2 = i1 + 1; i2 < nLep; ++i2) {
226 firedLegs[2].swap(validLegs[i2]);
227 trigLeptons[2] = leptons[i2].particle();
230 if(!matched_per_trigger)
return true;
231 if(matched_per_trigger->count(
chain)) matched_per_trigger->at(
chain) =
true;
233 firedLegs[2].swap(validLegs[i2]);
235 firedLegs[1].swap(validLegs[i1]);
252 if (!
period->m_triggers.size()) {
255 <<
" (was there a configuration issue? please check for "
256 "warnings during initialization)");
261 for (
auto& trig :
period->m_triggers) {
262 auto itr =
parent.m_dictionary.find(trig.name);
266 <<
" (shouldn't happen; contact tool developers!)");
283 if (insertion.second) {
285 switch (lepton.
type()) {
323 template <
typename Trig1L>
327 -> std::enable_if_t<Trig1L::is1L(),
bool> {
328 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_One1L() at line "
331 globalEfficiencies = {0.};
334 globalEfficiencies = {1.};
336 for (
auto& lepton : leptons) {
337 if (trig.irrelevantFor(lepton) || !aboveThreshold(lepton, trig()))
340 getCachedTriggerLegEfficiencies(lepton,
runNumber, trig(), success);
343 globalEfficiencies = ~globalEfficiencies;
350 template <
typename Trig1L_obj1,
typename Trig1L_obj2>
352 const Trig1L_obj1 trig1,
353 const Trig1L_obj2 trig2,
355 -> std::enable_if_t<Trig1L_obj1::is1L() && Trig1L_obj2::is1L() &&
358 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_Two1L() at line "
361 return globalEfficiency(leptons,
runNumber, trig2, globalEfficiencies);
363 return globalEfficiency(leptons,
runNumber, trig1, globalEfficiencies);
364 globalEfficiencies = {1.};
366 for (
auto& lepton : leptons) {
368 if (trig1.relevantFor(lepton))
370 else if (trig2.relevantFor(lepton))
374 if (!aboveThreshold(lepton,
leg))
377 getCachedTriggerLegEfficiencies(lepton,
runNumber,
leg, success);
380 globalEfficiencies = ~globalEfficiencies;
387 template <
typename Trig1L>
391 -> std::enable_if_t<Trig1L::is1L(),
bool> {
392 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_Several1L() at line "
394 if (trigs.size() == 1)
395 return globalEfficiency(leptons,
runNumber, *trigs.cbegin(),
398 globalEfficiencies = {0.};
401 globalEfficiencies = {1.};
403 for (
auto& lepton : leptons) {
404 if (Trig1L::irrelevantFor(lepton))
406 std::size_t loosestLeg =
407 getLoosestLegAboveThreshold(lepton, trigs, success);
408 if (loosestLeg && success) {
410 loosestLeg, success);
414 globalEfficiencies = ~globalEfficiencies;
421 template <
typename Trig1L_obj1,
typename Trig1L_obj2>
426 -> std::enable_if_t<Trig1L_obj1::is1L() && Trig1L_obj2::is1L() &&
429 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_Several1L() at line "
431 if (trigs1.size() == 1 && trigs2.size() == 1) {
432 return globalEfficiency(leptons,
runNumber, *trigs1.cbegin(),
433 *trigs2.cbegin(), globalEfficiencies);
436 return globalEfficiency(leptons,
runNumber, trigs2, globalEfficiencies);
438 return globalEfficiency(leptons,
runNumber, trigs1, globalEfficiencies);
439 globalEfficiencies = {1.};
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);
449 if (loosestLeg && success) {
451 loosestLeg, success);
455 globalEfficiencies = ~globalEfficiencies;
462 template <
typename Trig2Lmix>
464 const Trig2Lmix trig,
466 -> std::enable_if_t<Trig2Lmix::is2Lmix(),
bool> {
467 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_One2L() at line "
476 globalEfficiencies = {0.};
483 template <
typename Trig2Lsym>
485 const Trig2Lsym trig,
487 -> std::enable_if_t<Trig2Lsym::is2Lsym(),
bool> {
488 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_One2L() at line "
490 globalEfficiencies = {0.};
495 for (
auto& lepton : leptons) {
496 if (trig.irrelevantFor(lepton) || !aboveThreshold(lepton, trig()))
499 getCachedTriggerLegEfficiencies(lepton,
runNumber, trig(), success);
500 globalEfficiencies = ~
efficiencies * globalEfficiencies +
510 template <
typename Trig2Lasym>
512 const Trig2Lasym trig,
514 -> std::enable_if_t<Trig2Lasym::is2Lasym(),
bool> {
515 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_One2L() at line "
517 if (trig.symmetric())
518 return globalEfficiency(leptons,
runNumber, trig.to_symmetric(),
520 globalEfficiencies = {0.};
524 twoSingleInefficiencies = {1.};
526 for (
auto& lepton : leptons) {
527 if (trig.irrelevantFor(lepton))
531 if (aboveThreshold(lepton, trig(0))) {
533 getCachedTriggerLegEfficiencies(lepton,
runNumber, trig(0), success);
534 if (aboveThreshold(lepton, trig(1))) {
537 loosest = m_parent->getLoosestLeg(lepton, trig(0), trig(1), success) ==
540 }
else if (aboveThreshold(lepton, trig(1))) {
542 getCachedTriggerLegEfficiencies(lepton,
runNumber, trig(1), success);
546 const int tightest = 1 - loosest;
547 globalEfficiencies = ~
efficiencies[loosest] * globalEfficiencies +
549 ~singleInefficiencies[tightest] +
552 for (
int i = 0;
i < 2; ++
i)
561 template <
typename Trig2Lmix,
typename Trig1L_obj1,
typename Trig1L_obj2>
563 const Trig2Lmix trig2Lmix,
567 -> std::enable_if_t<Trig2Lmix::is2Lmix() && Trig1L_obj1::is1L() &&
569 Trig1L_obj2::is1L() &&
572 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_One2LSeveral1L() at 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,
583 globalEfficiency(leptons,
runNumber, trig2Lmix.addTo(trigs1L1),
585 globalEfficiency(leptons,
runNumber, trig2Lmix.addTo(trigs1L2),
593 globalEfficiencies = {0.};
600 template <
typename Trig2L,
typename Trig1L>
606 -> std::enable_if_t<Trig2L::is2Lnomix() && Trig1L::is1L() &&
609 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_One2LSeveral1L() at line "
618 template <
typename Trig2Lsym,
typename Trig1L>
620 const Trig2Lsym trig2L,
623 -> std::enable_if_t<Trig2Lsym::is2Lsym() && Trig1L::is1L() &&
626 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_One2LSeveral1L() at line "
629 return globalEfficiency(leptons,
runNumber, trig2L, globalEfficiencies);
630 if (!trig2L || trig2L.hiddenBy(trigs1L))
631 return globalEfficiency(leptons,
runNumber, trigs1L, globalEfficiencies);
632 globalEfficiencies = {0.};
635 for (
auto& lepton : leptons) {
636 if (trig2L.irrelevantFor(lepton))
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,
648 loosestLegEfficiency =
649 (m_parent->getLoosestLeg(lepton, trig2L(), loosest1lepLeg,
650 success) == trig2L())
654 loosestLegEfficiency = &efficiencies1L;
655 }
else if (aboveThreshold(lepton, trig2L())) {
657 getCachedTriggerLegEfficiencies(lepton,
runNumber, trig2L(), success);
658 loosestLegEfficiency = &efficiencies2L;
662 ~(*loosestLegEfficiency) * globalEfficiencies + efficiencies1L;
663 if (loosestLegEfficiency == &efficiencies2L)
664 globalEfficiencies +=
665 ~twoSingleInefficiencies * (efficiencies2L - efficiencies1L);
666 twoSingleInefficiencies *= ~(*loosestLegEfficiency);
674 template <
typename Trig2Lasym,
typename Trig1L>
676 const Trig2Lasym trig2L,
679 -> std::enable_if_t<Trig2Lasym::is2Lasym() && Trig1L::is1L() &&
682 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_One2LSeveral1L() at line "
684 if (trig2L.symmetric())
685 return globalEfficiency(leptons,
runNumber, trig2L.to_symmetric(), trigs1L,
688 return globalEfficiency(leptons,
runNumber, trig2L, globalEfficiencies);
689 if (!trig2L || trig2L.hiddenBy(trigs1L))
690 return globalEfficiency(leptons,
runNumber, trigs1L, globalEfficiencies);
691 globalEfficiencies = {0.};
693 threeSingleInefficiencies = {1.};
695 for (
auto& lepton : leptons) {
696 if (trig2L.irrelevantFor(lepton))
699 for (std::size_t
leg : trig2L.legs)
700 if (aboveThreshold(lepton,
leg))
701 validLegs.insert(
leg);
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);
710 if (!validLegs.size())
712 auto looseLegs = m_parent->getTwoLoosestLegs(lepton, validLegs, success);
713 auto efficienciesLoose =
714 (looseLegs.first == loosest1lepLeg)
716 : getCachedTriggerLegEfficiencies(lepton,
runNumber,
717 looseLegs.first, success);
719 if (validLegs.size() >= 2)
721 (looseLegs.second == loosest1lepLeg)
723 : getCachedTriggerLegEfficiencies(lepton,
runNumber,
724 looseLegs.second, success);
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;
735 threeSingleInefficiencies *= ~efficienciesLoose;
736 twoSingleInefficiencies[0] *= (looseLegs.first != trig2L.legs[1])
738 : ~efficienciesMedium;
739 twoSingleInefficiencies[1] *= (looseLegs.first != trig2L.legs[0])
741 : ~efficienciesMedium;
749 template <
typename Trig2Lsym,
typename Trig1L>
751 const Trig2Lsym trig2L1,
752 const Trig2Lsym trig2L2,
755 -> std::enable_if_t<Trig2Lsym::is2Lsym() && Trig1L::is1L() &&
758 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_Two2LSeveral1L() at line "
760 if (!trig2L1 || trig2L1 == trig2L2 || trig2L1.hiddenBy(trigs1L))
761 return globalEfficiency(leptons,
runNumber, trig2L2, trigs1L,
763 if (!trig2L2 || trig2L2.hiddenBy(trigs1L))
764 return globalEfficiency(leptons,
runNumber, trig2L1, trigs1L,
766 globalEfficiencies = {0.};
771 for (
auto& lepton : leptons) {
772 if (trig2L1.irrelevantFor(lepton))
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);
786 if (!validLegs.size())
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] +
795 if (looseLegs.first == trig2L1())
796 globalEfficiencies +=
797 efficiencies2Lsym[1] *
799 if (looseLegs.first == trig2L2())
800 globalEfficiencies +=
801 efficiencies2Lsym[0] *
803 if (looseLegs.first != loosest1lepLeg)
804 globalEfficiencies +=
805 ~singleInefficiencies *
807 efficiencies2Lsym[0] =
810 efficiencies2Lsym[1] =
813 if (looseLegs.first == trig2L1())
814 efficiencies2Lsym[0] +=
816 ~singleInefficiencies;
817 if (looseLegs.first == trig2L2())
818 efficiencies2Lsym[1] +=
820 ~singleInefficiencies;
829 template <
typename Trig2Lasym,
typename Trig2Lsym,
typename Trig1L>
831 const Trig2Lasym trig2Lasym,
832 const Trig2Lsym trig2Lsym,
835 -> std::enable_if_t<Trig2Lasym::is2Lasym() && Trig2Lsym::is2Lsym() &&
840 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_Two2LSeveral1L() at line "
842 if (!trig2Lasym || trig2Lasym.hiddenBy(trigs1L))
843 return globalEfficiency(leptons,
runNumber, trig2Lsym, trigs1L,
845 if (!trig2Lsym || trig2Lsym.hiddenBy(trigs1L))
846 return globalEfficiency(leptons,
runNumber, trig2Lasym, trigs1L,
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");
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.}};
860 efficiencies2Lsym[3] = {{0.}, {0.}, {0.}};
863 for (
auto& lepton : leptons) {
864 if (trig2Lasym.irrelevantFor(lepton))
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);
879 if (!validLegs.size())
882 const auto sortedLegs = m_parent->getSortedLegs(lepton, validLegs, success);
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
898 std::size_t lambda24 = (lambda124 != trig2Lsym()) ? lambda124
899 : (lambda234 != trig2Lasym(1)) ? lambda234
901 std::size_t lambda34 = (lambda134 != trig2Lsym()) ? lambda134
902 : (lambda234 != trig2Lasym(0)) ? lambda234
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))
930 (secondLoosestLeg == trig2Lasym(0)) ? trig2Lasym(1) : trig2Lasym(0);
931 else if (secondTightestLeg == trig2Lasym(0) ||
932 secondTightestLeg == trig2Lasym(1))
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);
943 ~singleInefficiencies[0] +
945 ~singleInefficiencies[1] +
947 efficiencies2Lsym[2];
948 if (loosestLeg == trig2Lsym())
949 globalEfficiencies +=
952 else if (loosestLeg == trig2Lasym(1))
953 globalEfficiencies +=
955 efficiencies2Lsym[0];
956 else if (loosestLeg == trig2Lasym(0))
957 globalEfficiencies +=
959 efficiencies2Lsym[1];
960 if (secondTightestLeg &&
961 tightestLeg == loosest1lepLeg)
962 globalEfficiencies +=
965 ~singleInefficiencies[2];
969 if (loosestLeg == trig2Lasym(0) || loosestLeg == trig2Lasym(1)) {
972 efficiencies2Lasym +=
974 ~singleInefficiencies[loosestLeg == trig2Lasym(0)] +
976 ~singleInefficiencies[2];
978 efficiencies2Lsym[0] = ~
efficiencies[lambda124] * efficiencies2Lsym[0] +
980 efficiencies2Lsym[1] = ~
efficiencies[lambda134] * efficiencies2Lsym[1] +
982 efficiencies2Lsym[2] = ~
efficiencies[loosestLeg] * efficiencies2Lsym[2] +
984 if (lambda124 == trig2Lsym())
985 efficiencies2Lsym[0] +=
987 ~singleInefficiencies[0];
988 if (lambda134 == trig2Lsym())
989 efficiencies2Lsym[1] +=
991 ~singleInefficiencies[1];
992 if (loosestLeg == trig2Lsym())
993 efficiencies2Lsym[2] +=
995 ~singleInefficiencies[2];
1006 template <
typename Trig3Lsym>
1008 const Trig3Lsym trig,
1010 -> std::enable_if_t<Trig3Lsym::is3Lsym(),
bool> {
1011 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_One3L() at 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()))
1020 getCachedTriggerLegEfficiencies(lepton,
runNumber, trig(), success);
1021 globalEfficiencies =
1033 template <
typename Trig3Lhalfsym>
1035 const Trig3Lhalfsym trig,
1037 -> std::enable_if_t<Trig3Lhalfsym::is3Lhalfsym(),
bool> {
1038 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_One3L() at line "
1040 if (trig.symmetric())
1041 return globalEfficiency(leptons,
runNumber, trig.to_symmetric(),
1042 globalEfficiencies);
1043 globalEfficiencies = {0.};
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))
1053 const int asym = 0, sym = 1;
1055 if (aboveThreshold(lepton, trig.asymLeg())) {
1057 lepton,
runNumber, trig.asymLeg(), success);
1058 if (aboveThreshold(lepton, trig.symLeg())) {
1060 lepton,
runNumber, trig.symLeg(), success);
1062 m_parent->getLoosestLeg(lepton, trig.asymLeg(), trig.symLeg(),
1063 success) == trig.asymLeg()
1068 }
else if (aboveThreshold(lepton, trig.symLeg())) {
1070 lepton,
runNumber, trig.symLeg(), success);
1075 if (loosestLeg == asym) {
1076 globalEfficiencies = ~
efficiencies[asym] * globalEfficiencies +
1078 delta * efficiencies2Lsym;
1079 efficiencies2L2L = ~
efficiencies[asym] * efficiencies2L2L +
1081 delta * ~singleInefficiencies[sym];
1082 efficiencies2Lasym = ~
efficiencies[asym] * efficiencies2Lasym +
1084 delta * ~singleInefficiencies[sym];
1086 globalEfficiencies = ~
efficiencies[sym] * globalEfficiencies +
1088 delta * efficiencies2Lasym;
1089 efficiencies2L2L = ~
efficiencies[sym] * efficiencies2L2L +
1091 efficiencies2Lasym = ~
efficiencies[sym] * efficiencies2Lasym +
1093 delta * ~singleInefficiencies[asym];
1095 efficiencies2Lsym = ~
efficiencies[sym] * efficiencies2Lsym +
1107 template <
typename Trig2L,
typename Trig2Lmix>
1109 const Trig2L trig2L,
1110 const Trig2Lmix trig2Lmix,
1112 -> std::enable_if_t<Trig2L::is2Lnomix() && Trig2Lmix::is2Lmix() &&
1116 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_Two2L() at line "
1118 Efficiencies efficiencies1L, efficiencies2L, efficiencies2Lor1L;
1121 trig2Lmix.template antiside<Trig2L>(), efficiencies1L);
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;
1136 template <
typename Trig2L_obj1,
typename Trig2L_obj2,
typename Trig2Lmix>
1138 const Trig2L_obj1 trig2L_obj1,
1139 const Trig2L_obj2 trig2L_obj2,
1140 const Trig2Lmix trig2Lmix,
1142 -> std::enable_if_t<Trig2Lmix::is2Lmix() && Trig2L_obj1::is2Lnomix() &&
1144 Trig2L_obj2::is2Lnomix() &&
1148 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_Three2L() at line "
1151 efficiencies2Lor1L[2] = {{0.}, {0.}};
1152 bool success =
true;
1154 success = success && globalEfficiency(leptons,
runNumber, trig2L_obj1,
1158 success && globalEfficiency(leptons,
runNumber, trig2L_obj1,
1159 trig2Lmix.template side<Trig2L_obj1>(),
1160 efficiencies2Lor1L[0]);
1162 efficiencies2Lor1L[0] = efficiencies2L[0];
1163 }
else if (trig2Lmix)
1165 success && globalEfficiency(leptons,
runNumber,
1166 trig2Lmix.template side<Trig2L_obj1>(),
1167 efficiencies2Lor1L[0]);
1169 success = success && globalEfficiency(leptons,
runNumber, trig2L_obj2,
1173 success && globalEfficiency(leptons,
runNumber, trig2L_obj2,
1174 trig2Lmix.template side<Trig2L_obj2>(),
1175 efficiencies2Lor1L[1]);
1177 efficiencies2Lor1L[1] = efficiencies2L[1];
1178 }
else if (trig2Lmix)
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];
1192 template <
typename Trig2L_obj1,
typename Trig2L_obj2,
typename Trig2Lmix,
1193 typename Trig1L_obj1,
typename Trig1L_obj2>
1195 const Trig2L_obj1 trig2L_obj1,
1196 const Trig2L_obj2 trig2L_obj2,
1197 const Trig2Lmix trig2Lmix,
1201 -> std::enable_if_t<Trig2Lmix::is2Lmix() && Trig2L_obj1::is2Lnomix() &&
1203 Trig2L_obj2::is2Lnomix() &&
1205 Trig1L_obj1::is1L() &&
1207 Trig1L_obj2::is1L() &&
1212 "Entered Calculator::globalEfficiency_Three2LSeveral1L() at line "
1215 bool success =
true;
1217 success = success && globalEfficiency(leptons,
runNumber, trig2L_obj1,
1220 success = success && globalEfficiency(leptons,
runNumber, trigs1L_obj1,
1223 success = success && globalEfficiency(leptons,
runNumber, trig2L_obj2,
1226 success = success && globalEfficiency(leptons,
runNumber, trigs1L_obj2,
1228 if (trig2Lmix && !trig2Lmix.hiddenBy(trigs1L_obj1)) {
1229 auto t = trig2Lmix.addTo(trigs1L_obj1);
1231 success = success && globalEfficiency(leptons,
runNumber, trig2L_obj1,
t,
1238 if (trig2Lmix && !trig2Lmix.hiddenBy(trigs1L_obj2)) {
1239 auto t = trig2Lmix.addTo(trigs1L_obj2);
1241 success = success && globalEfficiency(leptons,
runNumber, trig2L_obj2,
t,
1248 globalEfficiencies =
1258 template <
typename Trig2L_obj1,
typename Trig2Lsym_obj1,
typename Trig2L_obj2,
1259 typename Trig2Lsym_obj2,
typename Trig2Lmix,
typename Trig1L_obj1,
1260 typename Trig1L_obj2>
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,
1268 -> std::enable_if_t<Trig2Lmix::is2Lmix() && Trig2L_obj1::is2Lnomix() &&
1270 Trig2L_obj2::is2Lnomix() &&
1272 Trig2Lsym_obj1::is2Lsym() &&
1274 Trig2Lsym_obj2::is2Lsym() &&
1276 Trig1L_obj1::is1L() &&
1278 Trig1L_obj2::is1L() &&
1281 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_Six2LSeveral1L() at line "
1284 auto singleObjectFactor = [=](
auto trig2L,
auto trig2Lsym,
auto& trigs1L,
1286 auto eval_for = [=](
const auto& trigs1L_extended,
1288 if (trig2L && trig2Lsym)
1289 return this->globalEfficiency(leptons,
runNumber, trig2L, trig2Lsym,
1290 trigs1L_extended,
eff);
1292 return this->globalEfficiency(leptons,
runNumber, trig2L,
1293 trigs1L_extended,
eff);
1295 return this->globalEfficiency(leptons,
runNumber, trig2Lsym,
1296 trigs1L_extended,
eff);
1298 return this->globalEfficiency(leptons,
runNumber, trigs1L_extended,
1304 success = success && eval_for(trig2Lmix1.addTo(trigs1L),
efficiencies[1]);
1308 auto t = trig2Lmix2.addTo(trigs1L);
1322 bool success = singleObjectFactor(trig2L_obj1, trig2Lsym_obj1, trigs1L_obj1,
1324 singleObjectFactor(trig2L_obj2, trig2Lsym_obj2, trigs1L_obj2,
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] +
1334 (efficiencies2[0] - efficiencies2[1] -
1335 efficiencies2[2] + efficiencies2[3]);
1342 template <
typename Trig3Lmix>
1344 const Trig3Lmix trig,
1346 -> std::enable_if_t<Trig3Lmix::is3Lmix(),
bool> {
1347 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_One3L() at line "
1350 bool success = globalEfficiency(leptons,
runNumber,
1351 trig.template
side<Trig3Lmix::object1()>(),
1354 trig.template
side<Trig3Lmix::object2()>(),
1363 template <
typename Trig3Lmix1,
typename Trig3Lmix2>
1365 const Trig3Lmix1 trig1,
1366 const Trig3Lmix2 trig2,
1368 -> std::enable_if_t<Trig3Lmix1::is3Lmix() && Trig3Lmix2::is3Lmix() &&
1369 Trig3Lmix1::object1() == Trig3Lmix2::object2() &&
1370 Trig3Lmix1::object2() == Trig3Lmix2::object1(),
1372 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_Two3L() at line "
1375 auto trig2La = trig1.template side<Trig3Lmix1::object1()>();
1376 auto trig1La = trig2.template side<Trig3Lmix2::object2()>();
1380 if (!trig2La.hiddenBy(trig1La))
1381 success = success && globalEfficiency(leptons,
runNumber, trig2La, trig1La,
1385 auto trig2Lb = trig2.template side<Trig3Lmix2::object1()>();
1386 auto trig1Lb = trig1.template side<Trig3Lmix1::object2()>();
1387 success = success &&
1390 if (!trig2Lb.hiddenBy(trig1Lb))
1391 success = success && globalEfficiency(leptons,
runNumber, trig2Lb, trig1Lb,
1395 globalEfficiencies =
1405 template <
typename Trig4Lsym>
1407 const Trig4Lsym trig,
1409 -> std::enable_if_t<Trig4Lsym::is4Lsym(),
bool> {
1410 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_One4L() at 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()))
1419 getCachedTriggerLegEfficiencies(lepton,
runNumber, trig(), success);
1420 globalEfficiencies =
1453 globalEfficiencies =
1459 const std::vector<TrigDef>&
triggers,
1469 for (
auto itr =
tp.cbegin(lepton.
type()); itr !=
end; ++itr)
1471 validLegs.emplace(*itr);
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>(
1483 if (sameLegs == nLegs) {
1485 return std::count_if(firedLegs.cbegin(), firedLegs.cend(), [&](
auto& legs) {
1486 return legs.count(trig.leg[0]);
1488 }
else if (nLegs == 2) {
1490 bool n0 =
false,
n1 =
false;
1491 for (
auto& legs : firedLegs) {
1492 if (n0 && legs.count(trig.
leg[1]))
1494 if (
n1 && legs.count(trig.
leg[0]))
1496 n0 = n0 || legs.count(trig.
leg[0]);
1497 n1 =
n1 || legs.count(trig.
leg[1]);
1499 }
else if (nLegs == 3) {
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]))
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]))
1510 for (
auto legs2 = legs1 + 1; legs2 !=
end; ++legs2) {
1511 if (legs2->count(trig.
leg[(
i + 3 - j) % 3]))
1526 const std::vector<TrigDef>&
triggers,
1528 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_Toys() at line "
1530 globalEfficiencies = {0.};
1535 std::map<const Lepton*, std::vector<std::pair<std::size_t, Efficiencies>>>
1537 for (
auto& lepton : leptons) {
1542 const int nLegs = validLegs.size();
1544 bool success =
true;
1545 for (std::size_t
leg :
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};
1569 auto legs = firedLegs.begin();
1570 for (
auto& kv : leptonEfficiencies) {
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);
1587 globalEfficiencies.
data() =
1589 globalEfficiencies.
mc() =
1595 : m_formula(nullptr), m_defs(defs) {}
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)
1608 template <
typename T>
1618 template <
typename T>
1625 arg.emplace().first->setDefinition(def);
1630 template <
typename T>
1637 static void add(std::remove_cv_t<std::remove_reference_t<ArgType>>&
arg,
1647 template <
typename Param>
1649 std::remove_cv_t<std::remove_reference_t<typename Param::ArgType>> trigs;
1650 for (
auto& def :
m_defs) {
1655 if (!Param::multiple())
1663 template <
typename... Trigs>
1675 [](
auto& def) { return def.used; }))
1683 template <TriggerType
object_flag>
1689 using A_2sym =
typename A::T_2sym;
1690 using A_2asym =
typename A::T_2asym;
1692 return bindFunction<typename A::T_1>() || bindFunction<A1L>();
1694 return bindFunction<A_2sym>() || bindFunction<A_2asym>() ||
1695 bindFunction<A_2sym, A1L>() || bindFunction<A_2asym, A1L>();
1697 return bindFunction<A_2sym, A_2sym, Optional<A1L>>() ||
1700 return bindFunction<typename A::T_3sym>() ||
1701 bindFunction<typename A::T_3halfsym>();
1703 return bindFunction<typename A::T_4sym>();
1708 template <TriggerType
object_flag1, TriggerType
object_flag2>
1716 using A_1 =
typename A::T_1;
1717 using B_1 =
typename B::T_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;
1729 return bindFunction<A_1, B_1>() ||
1731 }
else if (
m_n2L == 1 &&
1734 return bindFunction<AB_1_1>() ||
1741 bindFunction<A_2sym, AB_1_1>() || bindFunction<A_2asym, AB_1_1>() ||
1742 bindFunction<B_2sym, AB_1_1>() ||
1743 bindFunction<B_2asym, AB_1_1>()
1766 }
else if (
m_n3L == 1 &&
1768 return bindFunction<typename AB::T_2sym_1>() ||
1769 bindFunction<typename AB::T_1_2sym>() ||
1770 bindFunction<typename AB::T_2asym_1>() ||
1771 bindFunction<typename AB::T_1_2asym>();
1772 }
else if (
m_n3L == 2 &&
1774 return bindFunction<typename AB::T_2sym_1, typename AB::T_1_2sym>() ||
1775 bindFunction<typename AB::T_2asym_1, typename AB::T_1_2sym>() ||
1776 bindFunction<typename AB::T_2sym_1, typename AB::T_1_2asym>() ||
1777 bindFunction<typename AB::T_2asym_1, typename AB::T_1_2asym>();
1784 auto countTriggers = [&](
auto nlep_flag) {
1786 [=](
auto& def) { return def.type & nlep_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;
1800 return findAndBindFunction<TT_ELECTRON_FLAG>();
1802 return findAndBindFunction<TT_MUON_FLAG>();
1804 return findAndBindFunction<TT_PHOTON_FLAG>();
1808 bool success =
false;
1810 success = findAndBindFunction<TT_ELECTRON_FLAG, TT_MUON_FLAG>();
1812 success = findAndBindFunction<TT_ELECTRON_FLAG, TT_PHOTON_FLAG>();
1814 success = findAndBindFunction<TT_MUON_FLAG, TT_PHOTON_FLAG>();
1819 std::vector<Helper> helpers;
1821 if (std::any_of(
m_defs.cbegin(),
1825 return (def.type & obj_flag) &&
1826 TriggerProperties(def.type).mixed();
1829 std::vector<ImportData::TrigDef> trigs1, trigs2;
1831 std::back_inserter(trigs1), std::back_inserter(trigs2),
1832 [&](
auto& def) { return (def.type & obj_flag); });
1836 helpers.emplace_back(trigs1);
1837 if (!helpers.back().findAndBindFunction())
1840 if (helpers.size()) {
1844 if (helpers.size() == 1)
1848 else if (helpers.size() == 2)
1858 if (helpers.size() == 2)
1860 ::_2, ::_3, std::move(helpers[0].
m_formula),
1862 else if (helpers.size() == 3)
1864 ::_2, ::_3, std::move(helpers[0].
m_formula),