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 &&
152 if (!
period->m_triggers.size()) {
160 const unsigned nLep = leptons.size();
161 std::vector<flat_set<std::size_t>> validLegs(leptons.size());
162 for (
unsigned i = 0;
i < nLep; ++
i) {
169 std::vector<flat_set<std::size_t>> firedLegs;
170 std::vector<const xAOD::IParticle*> trigLeptons;
171 const std::size_t magicWordHLT = 0xf7b8b87ef2917d66;
173 for (
auto& trig :
period->m_triggers) {
178 .emplace(trig.name ^ magicWordHLT,
182 const std::string&
chain = itr->second;
193 << std::hex << trig.type << std::dec <<
") " <<
chain);
196 firedLegs.resize(nLegs);
197 trigLeptons.resize(nLegs);
198 for (
unsigned i0 = 0; i0 < nLep; ++i0) {
199 firedLegs[0].swap(validLegs[i0]);
200 trigLeptons[0] = leptons[i0].particle();
205 && trigMatchTool->match(trigLeptons,
chain))
208 for (
unsigned i1 = i0 + 1; i1 < nLep; ++i1) {
209 firedLegs[1].swap(validLegs[i1]);
210 trigLeptons[1] = leptons[i1].particle();
213 trigMatchTool->match(trigLeptons,
chain))
216 for (
unsigned i2 = i1 + 1; i2 < nLep; ++i2) {
217 firedLegs[2].swap(validLegs[i2]);
218 trigLeptons[2] = leptons[i2].particle();
220 trigMatchTool->match(trigLeptons,
chain))
222 firedLegs[2].swap(validLegs[i2]);
224 firedLegs[1].swap(validLegs[i1]);
241 if (!
period->m_triggers.size()) {
244 <<
" (was there a configuration issue? please check for "
245 "warnings during initialization)");
250 for (
auto& trig :
period->m_triggers) {
251 auto itr =
parent.m_dictionary.find(trig.name);
255 <<
" (shouldn't happen; contact tool developers!)");
272 if (insertion.second) {
274 switch (lepton.
type()) {
312 template <
typename Trig1L>
316 -> std::enable_if_t<Trig1L::is1L(),
bool> {
317 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_One1L() at line "
320 globalEfficiencies = {0.};
323 globalEfficiencies = {1.};
325 for (
auto& lepton : leptons) {
326 if (trig.irrelevantFor(lepton) || !aboveThreshold(lepton, trig()))
329 getCachedTriggerLegEfficiencies(lepton,
runNumber, trig(), success);
332 globalEfficiencies = ~globalEfficiencies;
339 template <
typename Trig1L_obj1,
typename Trig1L_obj2>
341 const Trig1L_obj1 trig1,
342 const Trig1L_obj2 trig2,
344 -> std::enable_if_t<Trig1L_obj1::is1L() && Trig1L_obj2::is1L() &&
347 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_Two1L() at line "
350 return globalEfficiency(leptons,
runNumber, trig2, globalEfficiencies);
352 return globalEfficiency(leptons,
runNumber, trig1, globalEfficiencies);
353 globalEfficiencies = {1.};
355 for (
auto& lepton : leptons) {
357 if (trig1.relevantFor(lepton))
359 else if (trig2.relevantFor(lepton))
363 if (!aboveThreshold(lepton,
leg))
366 getCachedTriggerLegEfficiencies(lepton,
runNumber,
leg, success);
369 globalEfficiencies = ~globalEfficiencies;
376 template <
typename Trig1L>
380 -> std::enable_if_t<Trig1L::is1L(),
bool> {
381 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_Several1L() at line "
383 if (trigs.size() == 1)
384 return globalEfficiency(leptons,
runNumber, *trigs.cbegin(),
387 globalEfficiencies = {0.};
390 globalEfficiencies = {1.};
392 for (
auto& lepton : leptons) {
393 if (Trig1L::irrelevantFor(lepton))
395 std::size_t loosestLeg =
396 getLoosestLegAboveThreshold(lepton, trigs, success);
397 if (loosestLeg && success) {
399 loosestLeg, success);
403 globalEfficiencies = ~globalEfficiencies;
410 template <
typename Trig1L_obj1,
typename Trig1L_obj2>
415 -> std::enable_if_t<Trig1L_obj1::is1L() && Trig1L_obj2::is1L() &&
418 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_Several1L() at line "
420 if (trigs1.size() == 1 && trigs2.size() == 1) {
421 return globalEfficiency(leptons,
runNumber, *trigs1.cbegin(),
422 *trigs2.cbegin(), globalEfficiencies);
425 return globalEfficiency(leptons,
runNumber, trigs2, globalEfficiencies);
427 return globalEfficiency(leptons,
runNumber, trigs1, globalEfficiencies);
428 globalEfficiencies = {1.};
430 for (
auto& lepton : leptons) {
431 std::size_t loosestLeg;
432 if (Trig1L_obj1::relevantFor(lepton))
433 loosestLeg = getLoosestLegAboveThreshold(lepton, trigs1, success);
434 else if (Trig1L_obj2::relevantFor(lepton))
435 loosestLeg = getLoosestLegAboveThreshold(lepton, trigs2, success);
438 if (loosestLeg && success) {
440 loosestLeg, success);
444 globalEfficiencies = ~globalEfficiencies;
451 template <
typename Trig2Lmix>
453 const Trig2Lmix trig,
455 -> std::enable_if_t<Trig2Lmix::is2Lmix(),
bool> {
456 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_One2L() at line "
465 globalEfficiencies = {0.};
472 template <
typename Trig2Lsym>
474 const Trig2Lsym trig,
476 -> std::enable_if_t<Trig2Lsym::is2Lsym(),
bool> {
477 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_One2L() at line "
479 globalEfficiencies = {0.};
484 for (
auto& lepton : leptons) {
485 if (trig.irrelevantFor(lepton) || !aboveThreshold(lepton, trig()))
488 getCachedTriggerLegEfficiencies(lepton,
runNumber, trig(), success);
489 globalEfficiencies = ~
efficiencies * globalEfficiencies +
499 template <
typename Trig2Lasym>
501 const Trig2Lasym trig,
503 -> std::enable_if_t<Trig2Lasym::is2Lasym(),
bool> {
504 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_One2L() at line "
506 if (trig.symmetric())
507 return globalEfficiency(leptons,
runNumber, trig.to_symmetric(),
509 globalEfficiencies = {0.};
513 twoSingleInefficiencies = {1.};
515 for (
auto& lepton : leptons) {
516 if (trig.irrelevantFor(lepton))
520 if (aboveThreshold(lepton, trig(0))) {
522 getCachedTriggerLegEfficiencies(lepton,
runNumber, trig(0), success);
523 if (aboveThreshold(lepton, trig(1))) {
526 loosest = m_parent->getLoosestLeg(lepton, trig(0), trig(1), success) ==
529 }
else if (aboveThreshold(lepton, trig(1))) {
531 getCachedTriggerLegEfficiencies(lepton,
runNumber, trig(1), success);
535 const int tightest = 1 - loosest;
536 globalEfficiencies = ~
efficiencies[loosest] * globalEfficiencies +
538 ~singleInefficiencies[tightest] +
541 for (
int i = 0;
i < 2; ++
i)
550 template <
typename Trig2Lmix,
typename Trig1L_obj1,
typename Trig1L_obj2>
552 const Trig2Lmix trig2Lmix,
556 -> std::enable_if_t<Trig2Lmix::is2Lmix() && Trig1L_obj1::is1L() &&
558 Trig1L_obj2::is1L() &&
561 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_One2LSeveral1L() at line "
563 if (!(trigs1L1.size() + trigs1L2.size()))
564 return globalEfficiency(leptons,
runNumber, trig2Lmix, globalEfficiencies);
565 if (trig2Lmix.hiddenBy(trigs1L1) || trig2Lmix.hiddenBy(trigs1L2))
566 return globalEfficiency(leptons,
runNumber, trigs1L1, trigs1L2,
572 globalEfficiency(leptons,
runNumber, trig2Lmix.addTo(trigs1L1),
574 globalEfficiency(leptons,
runNumber, trig2Lmix.addTo(trigs1L2),
582 globalEfficiencies = {0.};
589 template <
typename Trig2L,
typename Trig1L>
595 -> std::enable_if_t<Trig2L::is2Lnomix() && Trig1L::is1L() &&
598 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_One2LSeveral1L() at line "
607 template <
typename Trig2Lsym,
typename Trig1L>
609 const Trig2Lsym trig2L,
612 -> std::enable_if_t<Trig2Lsym::is2Lsym() && Trig1L::is1L() &&
615 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_One2LSeveral1L() at line "
618 return globalEfficiency(leptons,
runNumber, trig2L, globalEfficiencies);
619 if (!trig2L || trig2L.hiddenBy(trigs1L))
620 return globalEfficiency(leptons,
runNumber, trigs1L, globalEfficiencies);
621 globalEfficiencies = {0.};
624 for (
auto& lepton : leptons) {
625 if (trig2L.irrelevantFor(lepton))
629 std::size_t loosest1lepLeg =
630 getLoosestLegAboveThreshold(lepton, trigs1L, success);
631 if (loosest1lepLeg) {
632 efficiencies1L = getCachedTriggerLegEfficiencies(lepton,
runNumber,
633 loosest1lepLeg, success);
634 if (aboveThreshold(lepton, trig2L())) {
635 efficiencies2L = getCachedTriggerLegEfficiencies(lepton,
runNumber,
637 loosestLegEfficiency =
638 (m_parent->getLoosestLeg(lepton, trig2L(), loosest1lepLeg,
639 success) == trig2L())
643 loosestLegEfficiency = &efficiencies1L;
644 }
else if (aboveThreshold(lepton, trig2L())) {
646 getCachedTriggerLegEfficiencies(lepton,
runNumber, trig2L(), success);
647 loosestLegEfficiency = &efficiencies2L;
651 ~(*loosestLegEfficiency) * globalEfficiencies + efficiencies1L;
652 if (loosestLegEfficiency == &efficiencies2L)
653 globalEfficiencies +=
654 ~twoSingleInefficiencies * (efficiencies2L - efficiencies1L);
655 twoSingleInefficiencies *= ~(*loosestLegEfficiency);
663 template <
typename Trig2Lasym,
typename Trig1L>
665 const Trig2Lasym trig2L,
668 -> std::enable_if_t<Trig2Lasym::is2Lasym() && Trig1L::is1L() &&
671 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_One2LSeveral1L() at line "
673 if (trig2L.symmetric())
674 return globalEfficiency(leptons,
runNumber, trig2L.to_symmetric(), trigs1L,
677 return globalEfficiency(leptons,
runNumber, trig2L, globalEfficiencies);
678 if (!trig2L || trig2L.hiddenBy(trigs1L))
679 return globalEfficiency(leptons,
runNumber, trigs1L, globalEfficiencies);
680 globalEfficiencies = {0.};
682 threeSingleInefficiencies = {1.};
684 for (
auto& lepton : leptons) {
685 if (trig2L.irrelevantFor(lepton))
688 for (std::size_t
leg : trig2L.legs)
689 if (aboveThreshold(lepton,
leg))
690 validLegs.insert(
leg);
692 std::size_t loosest1lepLeg =
693 getLoosestLegAboveThreshold(lepton, trigs1L, success);
694 if (loosest1lepLeg) {
695 efficiencies1L = getCachedTriggerLegEfficiencies(lepton,
runNumber,
696 loosest1lepLeg, success);
697 validLegs.insert(loosest1lepLeg);
699 if (!validLegs.size())
701 auto looseLegs = m_parent->getTwoLoosestLegs(lepton, validLegs, success);
702 auto efficienciesLoose =
703 (looseLegs.first == loosest1lepLeg)
705 : getCachedTriggerLegEfficiencies(lepton,
runNumber,
706 looseLegs.first, success);
708 if (validLegs.size() >= 2)
710 (looseLegs.second == loosest1lepLeg)
712 : getCachedTriggerLegEfficiencies(lepton,
runNumber,
713 looseLegs.second, success);
715 ~efficienciesLoose * globalEfficiencies + efficiencies1L;
716 if (loosest1lepLeg != looseLegs.first) {
717 globalEfficiencies +=
718 (efficienciesLoose - efficienciesMedium) *
719 ~twoSingleInefficiencies[looseLegs.first == trig2L.legs[0]];
720 if (loosest1lepLeg != looseLegs.second)
721 globalEfficiencies +=
722 (efficienciesMedium - efficiencies1L) * ~threeSingleInefficiencies;
724 threeSingleInefficiencies *= ~efficienciesLoose;
725 twoSingleInefficiencies[0] *= (looseLegs.first != trig2L.legs[1])
727 : ~efficienciesMedium;
728 twoSingleInefficiencies[1] *= (looseLegs.first != trig2L.legs[0])
730 : ~efficienciesMedium;
738 template <
typename Trig2Lsym,
typename Trig1L>
740 const Trig2Lsym trig2L1,
741 const Trig2Lsym trig2L2,
744 -> std::enable_if_t<Trig2Lsym::is2Lsym() && Trig1L::is1L() &&
747 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_Two2LSeveral1L() at line "
749 if (!trig2L1 || trig2L1 == trig2L2 || trig2L1.hiddenBy(trigs1L))
750 return globalEfficiency(leptons,
runNumber, trig2L2, trigs1L,
752 if (!trig2L2 || trig2L2.hiddenBy(trigs1L))
753 return globalEfficiency(leptons,
runNumber, trig2L1, trigs1L,
755 globalEfficiencies = {0.};
760 for (
auto& lepton : leptons) {
761 if (trig2L1.irrelevantFor(lepton))
764 std::map<std::size_t, Efficiencies>
efficiencies{{0, 0.}};
765 std::size_t loosest1lepLeg =
766 getLoosestLegAboveThreshold(lepton, trigs1L, success);
767 for (std::size_t
leg : {loosest1lepLeg, trig2L1(), trig2L2()}) {
768 if (
leg && aboveThreshold(lepton,
leg)) {
769 validLegs.insert(
leg);
775 if (!validLegs.size())
777 auto looseLegs = m_parent->getTwoLoosestLegs(lepton, validLegs, success);
778 std::size_t lambda13 =
779 (looseLegs.first != trig2L2()) ? looseLegs.first : looseLegs.second;
780 std::size_t lambda23 =
781 (looseLegs.first != trig2L1()) ? looseLegs.first : looseLegs.second;
782 globalEfficiencies = globalEfficiencies * ~
efficiencies[looseLegs.first] +
784 if (looseLegs.first == trig2L1())
785 globalEfficiencies +=
786 efficiencies2Lsym[1] *
788 if (looseLegs.first == trig2L2())
789 globalEfficiencies +=
790 efficiencies2Lsym[0] *
792 if (looseLegs.first != loosest1lepLeg)
793 globalEfficiencies +=
794 ~singleInefficiencies *
796 efficiencies2Lsym[0] =
799 efficiencies2Lsym[1] =
802 if (looseLegs.first == trig2L1())
803 efficiencies2Lsym[0] +=
805 ~singleInefficiencies;
806 if (looseLegs.first == trig2L2())
807 efficiencies2Lsym[1] +=
809 ~singleInefficiencies;
818 template <
typename Trig2Lasym,
typename Trig2Lsym,
typename Trig1L>
820 const Trig2Lasym trig2Lasym,
821 const Trig2Lsym trig2Lsym,
824 -> std::enable_if_t<Trig2Lasym::is2Lasym() && Trig2Lsym::is2Lsym() &&
829 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_Two2LSeveral1L() at line "
831 if (!trig2Lasym || trig2Lasym.hiddenBy(trigs1L))
832 return globalEfficiency(leptons,
runNumber, trig2Lsym, trigs1L,
834 if (!trig2Lsym || trig2Lsym.hiddenBy(trigs1L))
835 return globalEfficiency(leptons,
runNumber, trig2Lasym, trigs1L,
837 if (trig2Lasym(0) == trig2Lsym() || trig2Lasym(1) == trig2Lsym()) {
839 "implementation -- does this function work properly when the two 2L "
840 "triggers have one leg in common? Must be checked");
843 if (trig2Lasym.symmetric())
844 return globalEfficiency(leptons,
runNumber, trig2Lasym.to_symmetric(),
845 trig2Lsym, trigs1L, globalEfficiencies);
846 globalEfficiencies = {0.};
847 Efficiencies singleInefficiencies[3] = {{1.}, {1.}, {1.}};
849 efficiencies2Lsym[3] = {{0.}, {0.}, {0.}};
852 for (
auto& lepton : leptons) {
853 if (trig2Lasym.irrelevantFor(lepton))
856 std::map<std::size_t, Efficiencies>
efficiencies{{0, 0.}};
857 std::size_t loosest1lepLeg =
858 getLoosestLegAboveThreshold(lepton, trigs1L, success);
859 for (std::size_t
leg :
860 {trig2Lasym(0), trig2Lasym(1), trig2Lsym(), loosest1lepLeg}) {
861 if (
leg && aboveThreshold(lepton,
leg)) {
862 validLegs.insert(
leg);
868 if (!validLegs.size())
871 const auto sortedLegs = m_parent->getSortedLegs(lepton, validLegs, success);
874 std::size_t loosestLeg = sortedLegs[0];
875 std::size_t secondLoosestLeg = validLegs.size() >= 2 ? sortedLegs[1] : 0;
876 std::size_t secondTightestLeg = validLegs.size() >= 3 ? sortedLegs[2] : 0;
877 std::size_t tightestLeg = validLegs.size() >= 4 ? sortedLegs[3] : 0;
878 std::size_t lambda124 =
879 (loosestLeg != trig2Lasym(1)) ? loosestLeg : secondLoosestLeg;
880 std::size_t lambda134 =
881 (loosestLeg != trig2Lasym(0)) ? loosestLeg : secondLoosestLeg;
882 std::size_t lambda234 =
883 (loosestLeg != trig2Lsym()) ? loosestLeg : secondLoosestLeg;
884 std::size_t lambda14 = (lambda124 != trig2Lasym(0)) ? lambda124
885 : (lambda134 != trig2Lasym(1)) ? lambda134
887 std::size_t lambda24 = (lambda124 != trig2Lsym()) ? lambda124
888 : (lambda234 != trig2Lasym(1)) ? lambda234
890 std::size_t lambda34 = (lambda134 != trig2Lsym()) ? lambda134
891 : (lambda234 != trig2Lasym(0)) ? lambda234
893 std::size_t tau13 = 0, tau12 = 0, tau23 = 0;
894 if (loosestLeg == trig2Lsym() || loosestLeg == trig2Lasym(0))
895 tau12 = (loosestLeg == trig2Lsym()) ? trig2Lasym(0) : trig2Lsym();
896 else if (secondLoosestLeg == trig2Lsym() ||
897 secondLoosestLeg == trig2Lasym(0))
898 tau12 = (secondLoosestLeg == trig2Lsym()) ? trig2Lasym(0) : trig2Lsym();
899 else if (secondTightestLeg == trig2Lsym() ||
900 secondTightestLeg == trig2Lasym(0))
901 tau12 = (secondTightestLeg == trig2Lsym()) ? trig2Lasym(0) : trig2Lsym();
902 else if (tightestLeg == trig2Lsym() || tightestLeg == trig2Lasym(0))
903 tau12 = (tightestLeg == trig2Lsym()) ? trig2Lasym(0) : trig2Lsym();
904 if (loosestLeg == trig2Lsym() || loosestLeg == trig2Lasym(1))
905 tau13 = (loosestLeg == trig2Lsym()) ? trig2Lasym(1) : trig2Lsym();
906 else if (secondLoosestLeg == trig2Lsym() ||
907 secondLoosestLeg == trig2Lasym(1))
908 tau13 = (secondLoosestLeg == trig2Lsym()) ? trig2Lasym(1) : trig2Lsym();
909 else if (secondTightestLeg == trig2Lsym() ||
910 secondTightestLeg == trig2Lasym(1))
911 tau13 = (secondTightestLeg == trig2Lsym()) ? trig2Lasym(1) : trig2Lsym();
912 else if (tightestLeg == trig2Lsym() || tightestLeg == trig2Lasym(1))
913 tau13 = (tightestLeg == trig2Lsym()) ? trig2Lasym(1) : trig2Lsym();
914 if (loosestLeg == trig2Lasym(0) || loosestLeg == trig2Lasym(1))
915 tau23 = (loosestLeg == trig2Lasym(0)) ? trig2Lasym(1) : trig2Lasym(0);
916 else if (secondLoosestLeg == trig2Lasym(0) ||
917 secondLoosestLeg == trig2Lasym(1))
919 (secondLoosestLeg == trig2Lasym(0)) ? trig2Lasym(1) : trig2Lasym(0);
920 else if (secondTightestLeg == trig2Lasym(0) ||
921 secondTightestLeg == trig2Lasym(1))
923 (secondTightestLeg == trig2Lasym(0)) ? trig2Lasym(1) : trig2Lasym(0);
924 else if (tightestLeg == trig2Lasym(0) || tightestLeg == trig2Lasym(1))
925 tau23 = (tightestLeg == trig2Lasym(0)) ? trig2Lasym(1) : trig2Lasym(0);
932 ~singleInefficiencies[0] +
934 ~singleInefficiencies[1] +
936 efficiencies2Lsym[2];
937 if (loosestLeg == trig2Lsym())
938 globalEfficiencies +=
941 else if (loosestLeg == trig2Lasym(1))
942 globalEfficiencies +=
944 efficiencies2Lsym[0];
945 else if (loosestLeg == trig2Lasym(0))
946 globalEfficiencies +=
948 efficiencies2Lsym[1];
949 if (secondTightestLeg &&
950 tightestLeg == loosest1lepLeg)
951 globalEfficiencies +=
954 ~singleInefficiencies[2];
958 if (loosestLeg == trig2Lasym(0) || loosestLeg == trig2Lasym(1)) {
961 efficiencies2Lasym +=
963 ~singleInefficiencies[loosestLeg == trig2Lasym(0)] +
965 ~singleInefficiencies[2];
967 efficiencies2Lsym[0] = ~
efficiencies[lambda124] * efficiencies2Lsym[0] +
969 efficiencies2Lsym[1] = ~
efficiencies[lambda134] * efficiencies2Lsym[1] +
971 efficiencies2Lsym[2] = ~
efficiencies[loosestLeg] * efficiencies2Lsym[2] +
973 if (lambda124 == trig2Lsym())
974 efficiencies2Lsym[0] +=
976 ~singleInefficiencies[0];
977 if (lambda134 == trig2Lsym())
978 efficiencies2Lsym[1] +=
980 ~singleInefficiencies[1];
981 if (loosestLeg == trig2Lsym())
982 efficiencies2Lsym[2] +=
984 ~singleInefficiencies[2];
995 template <
typename Trig3Lsym>
997 const Trig3Lsym trig,
999 -> std::enable_if_t<Trig3Lsym::is3Lsym(),
bool> {
1000 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_One3L() at line "
1002 globalEfficiencies = {0.};
1003 Efficiencies singleInefficiencies{1.}, efficiencies2L{0.};
1004 bool success =
true;
1005 for (
auto& lepton : leptons) {
1006 if (trig.irrelevantFor(lepton) || !aboveThreshold(lepton, trig()))
1009 getCachedTriggerLegEfficiencies(lepton,
runNumber, trig(), success);
1010 globalEfficiencies =
1022 template <
typename Trig3Lhalfsym>
1024 const Trig3Lhalfsym trig,
1026 -> std::enable_if_t<Trig3Lhalfsym::is3Lhalfsym(),
bool> {
1027 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_One3L() at line "
1029 if (trig.symmetric())
1030 return globalEfficiency(leptons,
runNumber, trig.to_symmetric(),
1031 globalEfficiencies);
1032 globalEfficiencies = {0.};
1034 twoSingleInefficiencies{1.};
1035 Efficiencies efficiencies2Lsym{0.}, efficiencies2Lasym{0.},
1036 efficiencies2L2L{0.};
1037 bool success =
true;
1038 for (
auto& lepton : leptons) {
1039 if (trig.irrelevantFor(lepton))
1042 const int asym = 0, sym = 1;
1044 if (aboveThreshold(lepton, trig.asymLeg())) {
1046 lepton,
runNumber, trig.asymLeg(), success);
1047 if (aboveThreshold(lepton, trig.symLeg())) {
1049 lepton,
runNumber, trig.symLeg(), success);
1051 m_parent->getLoosestLeg(lepton, trig.asymLeg(), trig.symLeg(),
1052 success) == trig.asymLeg()
1057 }
else if (aboveThreshold(lepton, trig.symLeg())) {
1059 lepton,
runNumber, trig.symLeg(), success);
1064 if (loosestLeg == asym) {
1065 globalEfficiencies = ~
efficiencies[asym] * globalEfficiencies +
1067 delta * efficiencies2Lsym;
1068 efficiencies2L2L = ~
efficiencies[asym] * efficiencies2L2L +
1070 delta * ~singleInefficiencies[sym];
1071 efficiencies2Lasym = ~
efficiencies[asym] * efficiencies2Lasym +
1073 delta * ~singleInefficiencies[sym];
1075 globalEfficiencies = ~
efficiencies[sym] * globalEfficiencies +
1077 delta * efficiencies2Lasym;
1078 efficiencies2L2L = ~
efficiencies[sym] * efficiencies2L2L +
1080 efficiencies2Lasym = ~
efficiencies[sym] * efficiencies2Lasym +
1082 delta * ~singleInefficiencies[asym];
1084 efficiencies2Lsym = ~
efficiencies[sym] * efficiencies2Lsym +
1096 template <
typename Trig2L,
typename Trig2Lmix>
1098 const Trig2L trig2L,
1099 const Trig2Lmix trig2Lmix,
1101 -> std::enable_if_t<Trig2L::is2Lnomix() && Trig2Lmix::is2Lmix() &&
1105 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_Two2L() at line "
1107 Efficiencies efficiencies1L, efficiencies2L, efficiencies2Lor1L;
1110 trig2Lmix.template antiside<Trig2L>(), efficiencies1L);
1112 success && globalEfficiency(leptons,
runNumber, trig2L, efficiencies2L);
1113 success = success && globalEfficiency(leptons,
runNumber, trig2L,
1114 trig2Lmix.template side<Trig2L>(),
1115 efficiencies2Lor1L);
1116 globalEfficiencies =
1117 efficiencies2L * ~efficiencies1L + efficiencies1L * efficiencies2Lor1L;
1125 template <
typename Trig2L_obj1,
typename Trig2L_obj2,
typename Trig2Lmix>
1127 const Trig2L_obj1 trig2L_obj1,
1128 const Trig2L_obj2 trig2L_obj2,
1129 const Trig2Lmix trig2Lmix,
1131 -> std::enable_if_t<Trig2Lmix::is2Lmix() && Trig2L_obj1::is2Lnomix() &&
1133 Trig2L_obj2::is2Lnomix() &&
1137 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_Three2L() at line "
1140 efficiencies2Lor1L[2] = {{0.}, {0.}};
1141 bool success =
true;
1143 success = success && globalEfficiency(leptons,
runNumber, trig2L_obj1,
1147 success && globalEfficiency(leptons,
runNumber, trig2L_obj1,
1148 trig2Lmix.template side<Trig2L_obj1>(),
1149 efficiencies2Lor1L[0]);
1151 efficiencies2Lor1L[0] = efficiencies2L[0];
1152 }
else if (trig2Lmix)
1154 success && globalEfficiency(leptons,
runNumber,
1155 trig2Lmix.template side<Trig2L_obj1>(),
1156 efficiencies2Lor1L[0]);
1158 success = success && globalEfficiency(leptons,
runNumber, trig2L_obj2,
1162 success && globalEfficiency(leptons,
runNumber, trig2L_obj2,
1163 trig2Lmix.template side<Trig2L_obj2>(),
1164 efficiencies2Lor1L[1]);
1166 efficiencies2Lor1L[1] = efficiencies2L[1];
1167 }
else if (trig2Lmix)
1169 success && globalEfficiency(leptons,
runNumber,
1170 trig2Lmix.template side<Trig2L_obj2>(),
1171 efficiencies2Lor1L[1]);
1172 globalEfficiencies = efficiencies2L[0] * ~efficiencies2Lor1L[1] +
1173 efficiencies2L[1] * ~efficiencies2Lor1L[0] +
1174 efficiencies2Lor1L[0] * efficiencies2Lor1L[1];
1181 template <
typename Trig2L_obj1,
typename Trig2L_obj2,
typename Trig2Lmix,
1182 typename Trig1L_obj1,
typename Trig1L_obj2>
1184 const Trig2L_obj1 trig2L_obj1,
1185 const Trig2L_obj2 trig2L_obj2,
1186 const Trig2Lmix trig2Lmix,
1190 -> std::enable_if_t<Trig2Lmix::is2Lmix() && Trig2L_obj1::is2Lnomix() &&
1192 Trig2L_obj2::is2Lnomix() &&
1194 Trig1L_obj1::is1L() &&
1196 Trig1L_obj2::is1L() &&
1201 "Entered Calculator::globalEfficiency_Three2LSeveral1L() at line "
1204 bool success =
true;
1206 success = success && globalEfficiency(leptons,
runNumber, trig2L_obj1,
1209 success = success && globalEfficiency(leptons,
runNumber, trigs1L_obj1,
1212 success = success && globalEfficiency(leptons,
runNumber, trig2L_obj2,
1215 success = success && globalEfficiency(leptons,
runNumber, trigs1L_obj2,
1217 if (trig2Lmix && !trig2Lmix.hiddenBy(trigs1L_obj1)) {
1218 auto t = trig2Lmix.addTo(trigs1L_obj1);
1220 success = success && globalEfficiency(leptons,
runNumber, trig2L_obj1,
t,
1227 if (trig2Lmix && !trig2Lmix.hiddenBy(trigs1L_obj2)) {
1228 auto t = trig2Lmix.addTo(trigs1L_obj2);
1230 success = success && globalEfficiency(leptons,
runNumber, trig2L_obj2,
t,
1237 globalEfficiencies =
1247 template <
typename Trig2L_obj1,
typename Trig2Lsym_obj1,
typename Trig2L_obj2,
1248 typename Trig2Lsym_obj2,
typename Trig2Lmix,
typename Trig1L_obj1,
1249 typename Trig1L_obj2>
1252 const Trig2L_obj1 trig2L_obj1,
const Trig2Lsym_obj1 trig2Lsym_obj1,
1253 const Trig2L_obj2 trig2L_obj2,
const Trig2Lsym_obj2 trig2Lsym_obj2,
1254 const Trig2Lmix trig2Lmix1,
const Trig2Lmix trig2Lmix2,
1257 -> std::enable_if_t<Trig2Lmix::is2Lmix() && Trig2L_obj1::is2Lnomix() &&
1259 Trig2L_obj2::is2Lnomix() &&
1261 Trig2Lsym_obj1::is2Lsym() &&
1263 Trig2Lsym_obj2::is2Lsym() &&
1265 Trig1L_obj1::is1L() &&
1267 Trig1L_obj2::is1L() &&
1270 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_Six2LSeveral1L() at line "
1273 auto singleObjectFactor = [=](
auto trig2L,
auto trig2Lsym,
auto& trigs1L,
1275 auto eval_for = [=](
const auto& trigs1L_extended,
1277 if (trig2L && trig2Lsym)
1278 return this->globalEfficiency(leptons,
runNumber, trig2L, trig2Lsym,
1279 trigs1L_extended,
eff);
1281 return this->globalEfficiency(leptons,
runNumber, trig2L,
1282 trigs1L_extended,
eff);
1284 return this->globalEfficiency(leptons,
runNumber, trig2Lsym,
1285 trigs1L_extended,
eff);
1287 return this->globalEfficiency(leptons,
runNumber, trigs1L_extended,
1293 success = success && eval_for(trig2Lmix1.addTo(trigs1L),
efficiencies[1]);
1297 auto t = trig2Lmix2.addTo(trigs1L);
1311 bool success = singleObjectFactor(trig2L_obj1, trig2Lsym_obj1, trigs1L_obj1,
1313 singleObjectFactor(trig2L_obj2, trig2Lsym_obj2, trigs1L_obj2,
1316 ~efficiencies1[0] * ~efficiencies2[0] +
1317 (efficiencies1[1] - efficiencies1[0]) *
1318 (efficiencies2[1] - efficiencies2[0]) +
1319 (efficiencies1[2] - efficiencies1[0]) *
1320 (efficiencies2[2] - efficiencies2[0]) -
1321 (efficiencies1[0] - efficiencies1[1] - efficiencies1[2] +
1323 (efficiencies2[0] - efficiencies2[1] -
1324 efficiencies2[2] + efficiencies2[3]);
1331 template <
typename Trig3Lmix>
1333 const Trig3Lmix trig,
1335 -> std::enable_if_t<Trig3Lmix::is3Lmix(),
bool> {
1336 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_One3L() at line "
1339 bool success = globalEfficiency(leptons,
runNumber,
1340 trig.template
side<Trig3Lmix::object1()>(),
1343 trig.template
side<Trig3Lmix::object2()>(),
1352 template <
typename Trig3Lmix1,
typename Trig3Lmix2>
1354 const Trig3Lmix1 trig1,
1355 const Trig3Lmix2 trig2,
1357 -> std::enable_if_t<Trig3Lmix1::is3Lmix() && Trig3Lmix2::is3Lmix() &&
1358 Trig3Lmix1::object1() == Trig3Lmix2::object2() &&
1359 Trig3Lmix1::object2() == Trig3Lmix2::object1(),
1361 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_Two3L() at line "
1364 auto trig2La = trig1.template side<Trig3Lmix1::object1()>();
1365 auto trig1La = trig2.template side<Trig3Lmix2::object2()>();
1369 if (!trig2La.hiddenBy(trig1La))
1370 success = success && globalEfficiency(leptons,
runNumber, trig2La, trig1La,
1374 auto trig2Lb = trig2.template side<Trig3Lmix2::object1()>();
1375 auto trig1Lb = trig1.template side<Trig3Lmix1::object2()>();
1376 success = success &&
1379 if (!trig2Lb.hiddenBy(trig1Lb))
1380 success = success && globalEfficiency(leptons,
runNumber, trig2Lb, trig1Lb,
1384 globalEfficiencies =
1394 template <
typename Trig4Lsym>
1396 const Trig4Lsym trig,
1398 -> std::enable_if_t<Trig4Lsym::is4Lsym(),
bool> {
1399 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_One4L() at line "
1401 globalEfficiencies = {0.};
1402 Efficiencies singleInefficiencies{1.}, efficiencies2L{0.}, efficiencies3L{0.};
1403 bool success =
true;
1404 for (
auto& lepton : leptons) {
1405 if (trig.irrelevantFor(lepton) || !aboveThreshold(lepton, trig()))
1408 getCachedTriggerLegEfficiencies(lepton,
runNumber, trig(), success);
1409 globalEfficiencies =
1442 globalEfficiencies =
1448 const std::vector<TrigDef>&
triggers,
1458 for (
auto itr =
tp.cbegin(lepton.
type()); itr !=
end; ++itr)
1460 validLegs.emplace(*itr);
1468 const int nLegs =
static_cast<int>(std::count_if(
1469 trig.
leg.begin(), trig.
leg.end(), [](
auto x) { return x != 0ul; }));
1470 const int sameLegs =
static_cast<int>(
1472 if (sameLegs == nLegs) {
1474 return std::count_if(firedLegs.cbegin(), firedLegs.cend(), [&](
auto& legs) {
1475 return legs.count(trig.leg[0]);
1477 }
else if (nLegs == 2) {
1479 bool n0 =
false,
n1 =
false;
1480 for (
auto& legs : firedLegs) {
1481 if (n0 && legs.count(trig.
leg[1]))
1483 if (
n1 && legs.count(trig.
leg[0]))
1485 n0 = n0 || legs.count(trig.
leg[0]);
1486 n1 =
n1 || legs.count(trig.
leg[1]);
1488 }
else if (nLegs == 3) {
1490 auto end = firedLegs.end();
1491 for (
auto legs0 = firedLegs.begin(); legs0 !=
end; ++legs0) {
1492 for (
int i = 0;
i < 3; ++
i) {
1493 if (!legs0->count(trig.
leg[
i]))
1495 for (
auto legs1 = legs0 + 1; legs1 !=
end; ++legs1) {
1496 for (
int j = 1; j < 3; ++j) {
1497 if (!legs1->count(trig.
leg[(
i + j) % 3]))
1499 for (
auto legs2 = legs1 + 1; legs2 !=
end; ++legs2) {
1500 if (legs2->count(trig.
leg[(
i + 3 - j) % 3]))
1515 const std::vector<TrigDef>&
triggers,
1517 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_Toys() at line "
1519 globalEfficiencies = {0.};
1524 std::map<const Lepton*, std::vector<std::pair<std::size_t, Efficiencies>>>
1526 for (
auto& lepton : leptons) {
1531 const int nLegs = validLegs.size();
1533 bool success =
true;
1534 for (std::size_t
leg :
1551 std::mt19937_64 randomEngine(seed);
1552 std::uniform_real_distribution<double> uniformPdf(0., 1.);
1553 std::vector<flat_set<std::size_t>> firedLegs(leptonEfficiencies.size());
1554 unsigned long nPassed[2] = {0, 0};
1558 auto legs = firedLegs.begin();
1559 for (
auto& kv : leptonEfficiencies) {
1561 double x = uniformPdf(randomEngine);
1562 for (
auto&
p : kv.second) {
1563 if (
x < (
step ?
p.second.mc() :
p.second.data()))
1564 legs->emplace(
p.first);
1576 globalEfficiencies.
data() =
1578 globalEfficiencies.
mc() =
1584 : m_formula(nullptr), m_defs(defs) {}
1587 for (
auto itr1 =
m_defs.cbegin(); itr1 !=
m_defs.cend(); ++itr1)
1588 for (
auto itr2 = itr1 + 1; itr2 !=
m_defs.cend(); ++itr2)
1589 if (itr1->type == itr2->type && itr1->leg == itr2->leg)
1597 template <
typename T>
1607 template <
typename T>
1614 arg.emplace().first->setDefinition(def);
1619 template <
typename T>
1626 static void add(std::remove_cv_t<std::remove_reference_t<ArgType>>&
arg,
1636 template <
typename Param>
1638 std::remove_cv_t<std::remove_reference_t<typename Param::ArgType>> trigs;
1639 for (
auto& def :
m_defs) {
1644 if (!Param::multiple())
1652 template <
typename... Trigs>
1664 [](
auto& def) { return def.used; }))
1672 template <TriggerType
object_flag>
1678 using A_2sym =
typename A::T_2sym;
1679 using A_2asym =
typename A::T_2asym;
1681 return bindFunction<typename A::T_1>() || bindFunction<A1L>();
1683 return bindFunction<A_2sym>() || bindFunction<A_2asym>() ||
1684 bindFunction<A_2sym, A1L>() || bindFunction<A_2asym, A1L>();
1686 return bindFunction<A_2sym, A_2sym, Optional<A1L>>() ||
1689 return bindFunction<typename A::T_3sym>() ||
1690 bindFunction<typename A::T_3halfsym>();
1692 return bindFunction<typename A::T_4sym>();
1697 template <TriggerType
object_flag1, TriggerType
object_flag2>
1705 using A_1 =
typename A::T_1;
1706 using B_1 =
typename B::T_1;
1709 using A_2sym =
typename A::T_2sym;
1710 using B_2sym =
typename B::T_2sym;
1711 using A_2asym =
typename A::T_2asym;
1712 using B_2asym =
typename B::T_2asym;
1713 using AB_1_1 =
typename AB::T_1_1;
1718 return bindFunction<A_1, B_1>() ||
1720 }
else if (
m_n2L == 1 &&
1723 return bindFunction<AB_1_1>() ||
1730 bindFunction<A_2sym, AB_1_1>() || bindFunction<A_2asym, AB_1_1>() ||
1731 bindFunction<B_2sym, AB_1_1>() ||
1732 bindFunction<B_2asym, AB_1_1>()
1755 }
else if (
m_n3L == 1 &&
1757 return bindFunction<typename AB::T_2sym_1>() ||
1758 bindFunction<typename AB::T_1_2sym>() ||
1759 bindFunction<typename AB::T_2asym_1>() ||
1760 bindFunction<typename AB::T_1_2asym>();
1761 }
else if (
m_n3L == 2 &&
1763 return bindFunction<typename AB::T_2sym_1, typename AB::T_1_2sym>() ||
1764 bindFunction<typename AB::T_2asym_1, typename AB::T_1_2sym>() ||
1765 bindFunction<typename AB::T_2sym_1, typename AB::T_1_2asym>() ||
1766 bindFunction<typename AB::T_2asym_1, typename AB::T_1_2asym>();
1773 auto countTriggers = [&](
auto nlep_flag) {
1775 [=](
auto& def) { return def.type & nlep_flag; });
1781 auto exclusively = [&](
auto obj_flags) {
1782 return std::none_of(
m_defs.cbegin(),
m_defs.cend(), [=](
auto& def) {
1783 return def.type & TT_MASK_FLAVOUR & ~obj_flags;
1789 return findAndBindFunction<TT_ELECTRON_FLAG>();
1791 return findAndBindFunction<TT_MUON_FLAG>();
1793 return findAndBindFunction<TT_PHOTON_FLAG>();
1797 bool success =
false;
1799 success = findAndBindFunction<TT_ELECTRON_FLAG, TT_MUON_FLAG>();
1801 success = findAndBindFunction<TT_ELECTRON_FLAG, TT_PHOTON_FLAG>();
1803 success = findAndBindFunction<TT_MUON_FLAG, TT_PHOTON_FLAG>();
1808 std::vector<Helper> helpers;
1810 if (std::any_of(
m_defs.cbegin(),
1814 return (def.type & obj_flag) &&
1815 TriggerProperties(def.type).mixed();
1818 std::vector<ImportData::TrigDef> trigs1, trigs2;
1820 std::back_inserter(trigs1), std::back_inserter(trigs2),
1821 [&](
auto& def) { return (def.type & obj_flag); });
1825 helpers.emplace_back(trigs1);
1826 if (!helpers.back().findAndBindFunction())
1829 if (helpers.size()) {
1833 if (helpers.size() == 1)
1837 else if (helpers.size() == 2)
1847 if (helpers.size() == 2)
1849 ::_2, ::_3, std::move(helpers[0].
m_formula),
1851 else if (helpers.size() == 3)
1853 ::_2, ::_3, std::move(helpers[0].
m_formula),