16 using std::placeholders::_1;
17 using std::placeholders::_2;
18 using std::placeholders::_3;
19 using std::placeholders::_4;
30 bool useToys, std::size_t& uniqueElectronLeg, std::size_t& uniquePhotonLeg)
35 auto triggers =
data.parseTriggerString(combination, success);
36 if(!success)
return false;
50 ATH_MSG_ERROR(
"The following combination of triggers contains duplicates: " << combination);
55 success =
helper.findAndBindFunction();
58 ATH_MSG_ERROR(
"This trigger combination is currently not supported with an explicit formula (you may use toys instead, slower): " << combination);
80 ATH_MSG_ERROR(
"Unspecified error occurred while trying to find the formula for the trigger combination " << combination);
87 if(uniqueLeg)
return true;
91 for(
auto itr=
tp.cbegin(
obj);itr!=
tp.cend(
obj);++itr)
93 if(uniqueLeg && uniqueLeg!=*itr)
95 ATH_MSG_ERROR(
"The property 'ListOfLegsPerTool' needs to be filled as the specified trigger combination involves several electron (or photon) trigger legs");
107 [=](
const Period&
p) { return runNumber>=p.m_boundaries.first && runNumber<=p.m_boundaries.second; });
139 if(!
period->m_triggers.size())
147 const unsigned nLep = leptons.size();
148 std::vector<flat_set<std::size_t> > validLegs(leptons.size());
149 for(
unsigned i=0;
i<nLep;++
i)
155 std::vector<flat_set<std::size_t> > firedLegs;
156 std::vector<const xAOD::IParticle*> trigLeptons;
157 const std::size_t magicWordHLT = 0xf7b8b87ef2917d66;
159 for(
auto& trig :
period->m_triggers)
167 const std::string&
chain = itr->second;
175 ATH_MSG_ERROR(
"Unsupported trigger (type = " << std::hex << trig.type << std::dec <<
") " <<
chain );
178 firedLegs.resize(nLegs);
179 trigLeptons.resize(nLegs);
180 for(
unsigned i0=0;i0<nLep;++i0)
182 firedLegs[0].swap(validLegs[i0]);
183 trigLeptons[0] = leptons[i0].particle();
187 && trigMatchTool->match(trigLeptons,
chain))
return (
matched =
true);
189 else for(
unsigned i1=i0+1;i1<nLep;++i1)
191 firedLegs[1].swap(validLegs[i1]);
192 trigLeptons[1] = leptons[i1].particle();
196 && trigMatchTool->match(trigLeptons,
chain))
return (
matched =
true);
198 else for(
unsigned i2=i1+1;i2<nLep;++i2)
200 firedLegs[2].swap(validLegs[i2]);
201 trigLeptons[2] = leptons[i2].particle();
203 && trigMatchTool->match(trigLeptons,
chain))
return (
matched =
true);
204 firedLegs[2].swap(validLegs[i2]);
206 firedLegs[1].swap(validLegs[i1]);
208 firedLegs[0].swap(validLegs[i0]);
220 if(!
period->m_triggers.size())
222 ATH_MSG_ERROR(
"Empty list of triggers for run number " <<
runNumber <<
" (was there a configuration issue? please check for warnings during initialization)");
227 for(
auto& trig :
period->m_triggers)
229 auto itr =
parent.m_dictionary.find(trig.name);
232 ATH_MSG_ERROR(
"can't retrieve name of trigger with hash " << trig.name <<
" (shouldn't happen; contact tool developers!)");
235 else triggers.push_back(itr->second);
248 switch(lepton.
type())
283 template<
typename Trig1L>
285 -> std::enable_if_t<Trig1L::is1L(),
bool>
287 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_One1L() at line " << __LINE__);
290 globalEfficiencies = {0.};
293 globalEfficiencies = {1.};
295 for(
auto& lepton : leptons)
297 if(trig.irrelevantFor(lepton) || !aboveThreshold(lepton, trig()))
continue;
301 globalEfficiencies = ~globalEfficiencies;
308 template<
typename Trig1L_obj1,
typename Trig1L_obj2>
310 -> std::enable_if_t<Trig1L_obj1::is1L()
311 && Trig1L_obj2::is1L()
315 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_Two1L() at line " << __LINE__);
316 if(!trig1)
return globalEfficiency(leptons,
runNumber, trig2, globalEfficiencies);
317 if(!trig2)
return globalEfficiency(leptons,
runNumber, trig1, globalEfficiencies);
318 globalEfficiencies = {1.};
320 for(
auto& lepton : leptons)
323 if(trig1.relevantFor(lepton))
leg = trig1();
324 else if(trig2.relevantFor(lepton))
leg = trig2();
326 if(!aboveThreshold(lepton,
leg))
continue;
330 globalEfficiencies = ~globalEfficiencies;
337 template<
typename Trig1L>
339 -> std::enable_if_t<Trig1L::is1L(),
bool>
341 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_Several1L() at line " << __LINE__);
342 if(trigs.size() == 1)
return globalEfficiency(leptons,
runNumber, *trigs.cbegin(), globalEfficiencies);
345 globalEfficiencies = {0.};
348 globalEfficiencies = {1.};
350 for(
auto& lepton : leptons)
352 if(Trig1L::irrelevantFor(lepton))
continue;
353 std::size_t loosestLeg = getLoosestLegAboveThreshold(lepton, trigs, success);
354 if(loosestLeg && success)
360 globalEfficiencies = ~globalEfficiencies;
367 template<
typename Trig1L_obj1,
typename Trig1L_obj2>
370 -> std::enable_if_t<Trig1L_obj1::is1L()
371 && Trig1L_obj2::is1L()
375 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_Several1L() at line " << __LINE__);
376 if(trigs1.size()==1 && trigs2.size()==1)
378 return globalEfficiency(leptons,
runNumber, *trigs1.cbegin(), *trigs2.cbegin(), globalEfficiencies);
380 if(!trigs1.size())
return globalEfficiency(leptons,
runNumber, trigs2, globalEfficiencies);
381 if(!trigs2.size())
return globalEfficiency(leptons,
runNumber, trigs1, globalEfficiencies);
382 globalEfficiencies = {1.};
384 for(
auto& lepton : leptons)
386 std::size_t loosestLeg;
387 if(Trig1L_obj1::relevantFor(lepton)) loosestLeg = getLoosestLegAboveThreshold(lepton, trigs1, success);
388 else if(Trig1L_obj2::relevantFor(lepton)) loosestLeg = getLoosestLegAboveThreshold(lepton, trigs2, success);
390 if(loosestLeg && success)
396 globalEfficiencies = ~globalEfficiencies;
403 template<
typename Trig2Lmix>
405 -> std::enable_if_t<Trig2Lmix::is2Lmix(),
bool>
407 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_One2L() at line " << __LINE__);
412 else globalEfficiencies = {0.};
419 template<
typename Trig2Lsym>
421 -> std::enable_if_t<Trig2Lsym::is2Lsym(),
bool>
423 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_One2L() at line " << __LINE__);
424 globalEfficiencies = {0.};
425 if(!trig)
return true;
428 for(
auto& lepton : leptons)
430 if(trig.irrelevantFor(lepton) || !aboveThreshold(lepton, trig()))
continue;
441 template<
typename Trig2Lasym>
443 -> std::enable_if_t<Trig2Lasym::is2Lasym(),
bool>
445 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_One2L() at line " << __LINE__);
446 if(trig.symmetric())
return globalEfficiency(leptons,
runNumber, trig.to_symmetric(), globalEfficiencies);
447 globalEfficiencies = {0.};
448 if(!trig)
return true;
449 Efficiencies singleInefficiencies[2] = {{1.},{1.}}, twoSingleInefficiencies = {1.};
451 for(
auto& lepton : leptons)
453 if(trig.irrelevantFor(lepton))
continue;
456 if(aboveThreshold(lepton, trig(0)))
459 if(aboveThreshold(lepton, trig(1)))
462 loosest = m_parent->getLoosestLeg(lepton, trig(0), trig(1), success)==trig(1);
465 else if(aboveThreshold(lepton, trig(1)))
471 const int tightest = 1 - loosest;
472 globalEfficiencies = ~
efficiencies[loosest]*globalEfficiencies
484 template<
typename Trig2Lmix,
typename Trig1L_obj1,
typename Trig1L_obj2>
487 -> std::enable_if_t<Trig2Lmix::is2Lmix()
492 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_One2LSeveral1L() at line " << __LINE__);
493 if(!(trigs1L1.size() + trigs1L2.size()))
494 return globalEfficiency(leptons,
runNumber, trig2Lmix, globalEfficiencies);
495 if(trig2Lmix.hiddenBy(trigs1L1) || trig2Lmix.hiddenBy(trigs1L2))
496 return globalEfficiency(leptons,
runNumber, trigs1L1, trigs1L2, globalEfficiencies);
507 else globalEfficiencies = {0.};
514 template<
typename Trig2L,
typename Trig1L>
516 const Trig2L trig2L,
const Trig1L trig1L,
Efficiencies& globalEfficiencies)
517 -> std::enable_if_t<Trig2L::is2Lnomix()
522 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_One2LSeveral1L() at line " << __LINE__);
529 template<
typename Trig2Lsym,
typename Trig1L>
532 -> std::enable_if_t<Trig2Lsym::is2Lsym()
537 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_One2LSeveral1L() at line " << __LINE__);
538 if(!trigs1L.size())
return globalEfficiency(leptons,
runNumber, trig2L, globalEfficiencies);
539 if(!trig2L || trig2L.hiddenBy(trigs1L))
return globalEfficiency(leptons,
runNumber, trigs1L, globalEfficiencies);
540 globalEfficiencies = {0.};
543 for(
auto& lepton : leptons)
545 if(trig2L.irrelevantFor(lepton))
continue;
548 std::size_t loosest1lepLeg = getLoosestLegAboveThreshold(lepton, trigs1L, success);
551 efficiencies1L = getCachedTriggerLegEfficiencies(lepton,
runNumber, loosest1lepLeg, success);
552 if(aboveThreshold(lepton, trig2L()))
554 efficiencies2L = getCachedTriggerLegEfficiencies(lepton,
runNumber, trig2L(), success);
555 loosestLegEfficiency = (m_parent->getLoosestLeg(lepton, trig2L(), loosest1lepLeg , success)==trig2L())? &efficiencies2L : &efficiencies1L;
557 else loosestLegEfficiency = &efficiencies1L;
559 else if(aboveThreshold(lepton, trig2L()))
561 efficiencies2L = getCachedTriggerLegEfficiencies(lepton,
runNumber, trig2L(), success);
562 loosestLegEfficiency = &efficiencies2L;
565 globalEfficiencies = ~(*loosestLegEfficiency)*globalEfficiencies + efficiencies1L;
566 if(loosestLegEfficiency==&efficiencies2L) globalEfficiencies += ~twoSingleInefficiencies*(efficiencies2L - efficiencies1L);
567 twoSingleInefficiencies *= ~(*loosestLegEfficiency);
575 template<
typename Trig2Lasym,
typename Trig1L>
578 -> std::enable_if_t<Trig2Lasym::is2Lasym()
583 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_One2LSeveral1L() at line " << __LINE__);
584 if(trig2L.symmetric())
return globalEfficiency(leptons,
runNumber, trig2L.to_symmetric(), trigs1L, globalEfficiencies);
585 if(!trigs1L.size())
return globalEfficiency(leptons,
runNumber, trig2L, globalEfficiencies);
586 if(!trig2L || trig2L.hiddenBy(trigs1L))
return globalEfficiency(leptons,
runNumber, trigs1L, globalEfficiencies);
587 globalEfficiencies = {0.};
588 Efficiencies twoSingleInefficiencies[2] = {{1.}, {1.}}, threeSingleInefficiencies = {1.};
590 for(
auto& lepton : leptons)
592 if(trig2L.irrelevantFor(lepton))
continue;
594 for(std::size_t
leg : trig2L.legs)
if(aboveThreshold(lepton,
leg)) validLegs.insert(
leg);
596 std::size_t loosest1lepLeg = getLoosestLegAboveThreshold(lepton, trigs1L, success);
599 efficiencies1L = getCachedTriggerLegEfficiencies(lepton,
runNumber, loosest1lepLeg, success);
600 validLegs.insert(loosest1lepLeg);
602 if(!validLegs.size())
continue;
603 auto looseLegs = m_parent->getTwoLoosestLegs(lepton,validLegs,success);
604 auto efficienciesLoose = (looseLegs.first==loosest1lepLeg)? efficiencies1L : getCachedTriggerLegEfficiencies(lepton,
runNumber, looseLegs.first, success);
606 if(validLegs.size()>=2)
607 efficienciesMedium = (looseLegs.second==loosest1lepLeg)? efficiencies1L : getCachedTriggerLegEfficiencies(lepton,
runNumber, looseLegs.second, success);
608 globalEfficiencies = ~efficienciesLoose*globalEfficiencies + efficiencies1L;
609 if(loosest1lepLeg!=looseLegs.first)
611 globalEfficiencies += (efficienciesLoose-efficienciesMedium)*~twoSingleInefficiencies[looseLegs.first==trig2L.legs[0]];
612 if(loosest1lepLeg!=looseLegs.second) globalEfficiencies += (efficienciesMedium-efficiencies1L)*~threeSingleInefficiencies;
614 threeSingleInefficiencies *= ~efficienciesLoose;
615 twoSingleInefficiencies[0] *= (looseLegs.first!=trig2L.legs[1])?~efficienciesLoose:~efficienciesMedium;
616 twoSingleInefficiencies[1] *= (looseLegs.first!=trig2L.legs[0])?~efficienciesLoose:~efficienciesMedium;
624 template<
typename Trig2Lsym,
typename Trig1L>
627 -> std::enable_if_t<Trig2Lsym::is2Lsym()
632 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_Two2LSeveral1L() at line " << __LINE__);
633 if(!trig2L1 || trig2L1==trig2L2 || trig2L1.hiddenBy(trigs1L))
return globalEfficiency(leptons,
runNumber, trig2L2, trigs1L, globalEfficiencies);
634 if(!trig2L2 || trig2L2.hiddenBy(trigs1L))
return globalEfficiency(leptons,
runNumber, trig2L1, trigs1L, globalEfficiencies);
635 globalEfficiencies = {0.};
640 for(
auto& lepton : leptons)
642 if(trig2L1.irrelevantFor(lepton))
continue;
644 std::map<std::size_t, Efficiencies>
efficiencies{{0,0.}};
645 std::size_t loosest1lepLeg = getLoosestLegAboveThreshold(lepton, trigs1L, success);
646 for(std::size_t
leg : {loosest1lepLeg, trig2L1(), trig2L2()})
648 if(
leg && aboveThreshold(lepton,
leg))
650 validLegs.insert(
leg);
655 if(!validLegs.size())
continue;
656 auto looseLegs = m_parent->getTwoLoosestLegs(lepton, validLegs, success);
657 std::size_t lambda13 = (looseLegs.first!=trig2L2())? looseLegs.first : looseLegs.second;
658 std::size_t lambda23 = (looseLegs.first!=trig2L1())? looseLegs.first : looseLegs.second;
660 if(looseLegs.first==trig2L1()) globalEfficiencies += efficiencies2Lsym[1]*(
efficiencies[trig2L1()] -
efficiencies[looseLegs.second]);
661 if(looseLegs.first==trig2L2()) globalEfficiencies += efficiencies2Lsym[0]*(
efficiencies[trig2L2()] -
efficiencies[looseLegs.second]);
662 if(looseLegs.first!=loosest1lepLeg) globalEfficiencies += ~singleInefficiencies*(
efficiencies[looseLegs.second] -
efficiencies[loosest1lepLeg]);
665 if(looseLegs.first==trig2L1()) efficiencies2Lsym[0] += (
efficiencies[trig2L1()]-
efficiencies[lambda23])*~singleInefficiencies;
666 if(looseLegs.first==trig2L2()) efficiencies2Lsym[1] += (
efficiencies[trig2L2()]-
efficiencies[lambda13])*~singleInefficiencies;
675 template<
typename Trig2Lasym,
typename Trig2Lsym,
typename Trig1L>
678 -> std::enable_if_t<Trig2Lasym::is2Lasym()
683 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_Two2LSeveral1L() at line " << __LINE__);
684 if(!trig2Lasym || trig2Lasym.hiddenBy(trigs1L))
return globalEfficiency(leptons,
runNumber, trig2Lsym, trigs1L, globalEfficiencies);
685 if(!trig2Lsym || trig2Lsym.hiddenBy(trigs1L))
return globalEfficiency(leptons,
runNumber, trig2Lasym, trigs1L, globalEfficiencies);
686 if(trig2Lasym(0)==trig2Lsym() || trig2Lasym(1)==trig2Lsym())
688 ATH_MSG_ERROR(
"implementation -- does this function work properly when the two 2L triggers have one leg in common? Must be checked");
691 if(trig2Lasym.symmetric())
return globalEfficiency(leptons,
runNumber, trig2Lasym.to_symmetric(), trig2Lsym, trigs1L, globalEfficiencies);
692 globalEfficiencies = {0.};
693 Efficiencies singleInefficiencies[3] = {{1.}, {1.}, {1.}};
694 Efficiencies efficiencies2Lasym {0.}, efficiencies2Lsym[3] = {{0.},{0.},{0.}};
697 for(
auto& lepton : leptons)
699 if(trig2Lasym.irrelevantFor(lepton))
continue;
701 std::map<std::size_t, Efficiencies>
efficiencies{{0,0.}};
702 std::size_t loosest1lepLeg = getLoosestLegAboveThreshold(lepton, trigs1L, success);
703 for(std::size_t
leg : {trig2Lasym(0), trig2Lasym(1), trig2Lsym(), loosest1lepLeg})
705 if(
leg && aboveThreshold(lepton,
leg))
707 validLegs.insert(
leg);
712 if(!validLegs.size())
continue;
714 const auto sortedLegs = m_parent->getSortedLegs(lepton, validLegs, success);
715 if(!success)
return false;
716 std::size_t loosestLeg = sortedLegs[0];
717 std::size_t secondLoosestLeg = validLegs.size()>=2 ? sortedLegs[1] : 0;
718 std::size_t secondTightestLeg = validLegs.size()>=3 ? sortedLegs[2] : 0;
719 std::size_t tightestLeg = validLegs.size()>=4 ? sortedLegs[3]: 0;
720 std::size_t lambda124 = (loosestLeg!=trig2Lasym(1))? loosestLeg : secondLoosestLeg;
721 std::size_t lambda134 = (loosestLeg!=trig2Lasym(0))? loosestLeg : secondLoosestLeg;
722 std::size_t lambda234 = (loosestLeg!=trig2Lsym())? loosestLeg : secondLoosestLeg;
723 std::size_t lambda14 = (lambda124!=trig2Lasym(0))? lambda124 : (lambda134!=trig2Lasym(1))? lambda134 : secondTightestLeg;
724 std::size_t lambda24 = (lambda124!=trig2Lsym())? lambda124 : (lambda234!=trig2Lasym(1))? lambda234 : secondTightestLeg;
725 std::size_t lambda34 = (lambda134!=trig2Lsym())? lambda134 : (lambda234!=trig2Lasym(0))? lambda234 : secondTightestLeg;
726 std::size_t tau13=0, tau12=0, tau23=0;
727 if(loosestLeg==trig2Lsym() || loosestLeg==trig2Lasym(0)) tau12 = (loosestLeg==trig2Lsym())? trig2Lasym(0) : trig2Lsym();
728 else if(secondLoosestLeg==trig2Lsym() || secondLoosestLeg==trig2Lasym(0)) tau12 = (secondLoosestLeg==trig2Lsym())? trig2Lasym(0) : trig2Lsym();
729 else if(secondTightestLeg==trig2Lsym() || secondTightestLeg==trig2Lasym(0)) tau12 = (secondTightestLeg==trig2Lsym())? trig2Lasym(0) : trig2Lsym();
730 else if(tightestLeg==trig2Lsym() || tightestLeg==trig2Lasym(0)) tau12 = (tightestLeg==trig2Lsym())? trig2Lasym(0) : trig2Lsym();
731 if(loosestLeg==trig2Lsym() || loosestLeg==trig2Lasym(1)) tau13 = (loosestLeg==trig2Lsym())? trig2Lasym(1) : trig2Lsym();
732 else if(secondLoosestLeg==trig2Lsym() || secondLoosestLeg==trig2Lasym(1)) tau13 = (secondLoosestLeg==trig2Lsym())? trig2Lasym(1) : trig2Lsym();
733 else if(secondTightestLeg==trig2Lsym() || secondTightestLeg==trig2Lasym(1)) tau13 = (secondTightestLeg==trig2Lsym())? trig2Lasym(1) : trig2Lsym();
734 else if(tightestLeg==trig2Lsym() || tightestLeg==trig2Lasym(1)) tau13 = (tightestLeg==trig2Lsym())? trig2Lasym(1) : trig2Lsym();
735 if(loosestLeg==trig2Lasym(0) || loosestLeg==trig2Lasym(1)) tau23 = (loosestLeg==trig2Lasym(0))? trig2Lasym(1) : trig2Lasym(0);
736 else if(secondLoosestLeg==trig2Lasym(0) || secondLoosestLeg==trig2Lasym(1)) tau23 = (secondLoosestLeg==trig2Lasym(0))? trig2Lasym(1) : trig2Lasym(0);
737 else if(secondTightestLeg==trig2Lasym(0) || secondTightestLeg==trig2Lasym(1)) tau23 = (secondTightestLeg==trig2Lasym(0))? trig2Lasym(1) : trig2Lasym(0);
738 else if(tightestLeg==trig2Lasym(0) || tightestLeg==trig2Lasym(1)) tau23 = (tightestLeg==trig2Lasym(0))? trig2Lasym(1) : trig2Lasym(0);
745 if(loosestLeg==trig2Lsym()) globalEfficiencies += (
efficiencies[trig2Lsym()]-
efficiencies[secondLoosestLeg])*efficiencies2Lasym;
746 else if(loosestLeg==trig2Lasym(1)) globalEfficiencies += (
efficiencies[trig2Lasym(1)]-
efficiencies[secondLoosestLeg])*efficiencies2Lsym[0];
747 else if(loosestLeg==trig2Lasym(0)) globalEfficiencies += (
efficiencies[trig2Lasym(0)]-
efficiencies[secondLoosestLeg])*efficiencies2Lsym[1];
748 if(secondTightestLeg && tightestLeg==loosest1lepLeg)
752 if(loosestLeg==trig2Lasym(0) || loosestLeg==trig2Lasym(1))
755 efficiencies2Lasym += (
efficiencies[loosestLeg]-
efficiencies[secondLoosestLeg])*~singleInefficiencies[loosestLeg==trig2Lasym(0)]
761 if(lambda124==trig2Lsym()) efficiencies2Lsym[0] += (
efficiencies[trig2Lsym()]-
efficiencies[lambda24])*~singleInefficiencies[0];
762 if(lambda134==trig2Lsym()) efficiencies2Lsym[1] += (
efficiencies[trig2Lsym()]-
efficiencies[lambda34])*~singleInefficiencies[1];
763 if(loosestLeg==trig2Lsym()) efficiencies2Lsym[2] += (
efficiencies[trig2Lsym()]-
efficiencies[lambda234])*~singleInefficiencies[2];
774 template<
typename Trig3Lsym>
776 -> std::enable_if_t<Trig3Lsym::is3Lsym(),
bool>
778 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_One3L() at line " << __LINE__);
779 globalEfficiencies = {0.};
780 Efficiencies singleInefficiencies{1.}, efficiencies2L{0.};
782 for(
auto& lepton : leptons)
784 if(trig.irrelevantFor(lepton) || !aboveThreshold(lepton, trig()))
continue;
796 template<
typename Trig3Lhalfsym>
798 -> std::enable_if_t<Trig3Lhalfsym::is3Lhalfsym(),
bool>
800 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_One3L() at line " << __LINE__);
801 if(trig.symmetric())
return globalEfficiency(leptons,
runNumber, trig.to_symmetric(), globalEfficiencies);
802 globalEfficiencies = {0.};
803 Efficiencies singleInefficiencies[2] = {{1.}, {1.}}, twoSingleInefficiencies{1.};
804 Efficiencies efficiencies2Lsym{0.}, efficiencies2Lasym{0.}, efficiencies2L2L{0.};
806 for(
auto& lepton : leptons)
808 if(trig.irrelevantFor(lepton))
continue;
810 const int asym = 0, sym = 1;
812 if(aboveThreshold(lepton, trig.asymLeg()))
815 if(aboveThreshold(lepton, trig.symLeg()))
818 loosestLeg = m_parent->getLoosestLeg(lepton, trig.asymLeg(), trig.symLeg(), success)==trig.asymLeg()? asym : sym;
820 else loosestLeg = asym;
822 else if(aboveThreshold(lepton, trig.symLeg()))
829 if(loosestLeg == asym)
831 globalEfficiencies = ~
efficiencies[asym]*globalEfficiencies +
efficiencies[sym]*efficiencies2L2L + delta*efficiencies2Lsym;
832 efficiencies2L2L = ~
efficiencies[asym]*efficiencies2L2L +
efficiencies[sym]*~twoSingleInefficiencies + delta*~singleInefficiencies[sym];
833 efficiencies2Lasym = ~
efficiencies[asym]*efficiencies2Lasym +
efficiencies[sym]*~twoSingleInefficiencies + delta*~singleInefficiencies[sym];
837 globalEfficiencies = ~
efficiencies[sym]*globalEfficiencies +
efficiencies[asym]*efficiencies2L2L - delta*efficiencies2Lasym;
839 efficiencies2Lasym = ~
efficiencies[sym]*efficiencies2Lasym +
efficiencies[asym]*~twoSingleInefficiencies - delta*~singleInefficiencies[asym];
852 template<
typename Trig2L,
typename Trig2Lmix>
854 -> std::enable_if_t<Trig2L::is2Lnomix()
855 && Trig2Lmix::is2Lmix()
859 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_Two2L() at line " << __LINE__);
860 Efficiencies efficiencies1L, efficiencies2L, efficiencies2Lor1L;
861 bool success = globalEfficiency(leptons,
runNumber, trig2Lmix.template antiside<Trig2L>(), efficiencies1L);
862 success = success && globalEfficiency(leptons,
runNumber, trig2L, efficiencies2L);
863 success = success && globalEfficiency(leptons,
runNumber, trig2L, trig2Lmix.template side<Trig2L>(), efficiencies2Lor1L);
864 globalEfficiencies = efficiencies2L*~efficiencies1L + efficiencies1L*efficiencies2Lor1L;
871 template<
typename Trig2L_obj1,
typename Trig2L_obj2,
typename Trig2Lmix>
873 const Trig2L_obj1 trig2L_obj1,
const Trig2L_obj2 trig2L_obj2,
const Trig2Lmix trig2Lmix,
Efficiencies& globalEfficiencies)
874 -> std::enable_if_t<Trig2Lmix::is2Lmix()
880 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_Three2L() at line " << __LINE__);
881 Efficiencies efficiencies2L[2] = {{0.}, {0.}}, efficiencies2Lor1L[2] = {{0.}, {0.}};
885 success = success && globalEfficiency(leptons,
runNumber, trig2L_obj1, efficiencies2L[0]);
886 if(trig2Lmix) success = success && globalEfficiency(leptons,
runNumber, trig2L_obj1, trig2Lmix.template side<Trig2L_obj1>(), efficiencies2Lor1L[0]);
887 else efficiencies2Lor1L[0] = efficiencies2L[0];
889 else if(trig2Lmix) success = success && globalEfficiency(leptons,
runNumber, trig2Lmix.template side<Trig2L_obj1>(), efficiencies2Lor1L[0]);
892 success = success && globalEfficiency(leptons,
runNumber, trig2L_obj2, efficiencies2L[1]);
893 if(trig2Lmix) success = success && globalEfficiency(leptons,
runNumber, trig2L_obj2, trig2Lmix.template side<Trig2L_obj2>(), efficiencies2Lor1L[1]);
894 else efficiencies2Lor1L[1] = efficiencies2L[1];
896 else if(trig2Lmix) success = success && globalEfficiency(leptons,
runNumber, trig2Lmix.template side<Trig2L_obj2>(), efficiencies2Lor1L[1]);
897 globalEfficiencies = efficiencies2L[0]*~efficiencies2Lor1L[1] + efficiencies2L[1]*~efficiencies2Lor1L[0] + efficiencies2Lor1L[0]*efficiencies2Lor1L[1];
904 template<
typename Trig2L_obj1,
typename Trig2L_obj2,
typename Trig2Lmix,
typename Trig1L_obj1,
typename Trig1L_obj2>
907 -> std::enable_if_t<Trig2Lmix::is2Lmix()
915 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_Three2LSeveral1L() at line " << __LINE__);
918 if(trig2L_obj1) success = success && globalEfficiency(leptons,
runNumber, trig2L_obj1, trigs1L_obj1,
efficiencies[0]);
920 if(trig2L_obj2) success = success && globalEfficiency(leptons,
runNumber, trig2L_obj2, trigs1L_obj2,
efficiencies[1]);
922 if(trig2Lmix && !trig2Lmix.hiddenBy(trigs1L_obj1))
924 auto t = trig2Lmix.addTo(trigs1L_obj1);
925 if(trig2L_obj1) success = success && globalEfficiency(leptons,
runNumber, trig2L_obj1,
t,
efficiencies[2]);
929 if(trig2Lmix && !trig2Lmix.hiddenBy(trigs1L_obj2))
931 auto t = trig2Lmix.addTo(trigs1L_obj2);
932 if(trig2L_obj2) success = success && globalEfficiency(leptons,
runNumber, trig2L_obj2,
t,
efficiencies[3]);
943 template<
typename Trig2L_obj1,
typename Trig2Lsym_obj1,
typename Trig2L_obj2,
typename Trig2Lsym_obj2,
944 typename Trig2Lmix,
typename Trig1L_obj1,
typename Trig1L_obj2>
946 const Trig2L_obj1 trig2L_obj1,
const Trig2Lsym_obj1 trig2Lsym_obj1,
const Trig2L_obj2 trig2L_obj2,
const Trig2Lsym_obj2 trig2Lsym_obj2,
947 const Trig2Lmix trig2Lmix1,
const Trig2Lmix trig2Lmix2,
949 -> std::enable_if_t<Trig2Lmix::is2Lmix()
958 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_Six2LSeveral1L() at line " << __LINE__);
962 auto eval_for = [=](
const auto& trigs1L_extended,
Efficiencies&
eff) ->
bool
964 if(trig2L && trig2Lsym)
return this->globalEfficiency(leptons,
runNumber, trig2L, trig2Lsym, trigs1L_extended,
eff);
965 else if(trig2L)
return this->globalEfficiency(leptons,
runNumber, trig2L, trigs1L_extended,
eff);
966 else if(trig2Lsym)
return this->globalEfficiency(leptons,
runNumber, trig2Lsym, trigs1L_extended,
eff);
967 else return this->globalEfficiency(leptons,
runNumber, trigs1L_extended,
eff);
971 if(trig2Lmix1) success = success && eval_for(trig2Lmix1.addTo(trigs1L),
efficiencies[1]);
975 auto t = trig2Lmix2.addTo(trigs1L);
977 if(trig2Lmix1) success && eval_for(trig2Lmix1.addTo(
t),
efficiencies[3]);
989 bool success = singleObjectFactor(trig2L_obj1, trig2Lsym_obj1, trigs1L_obj1, efficiencies1)
990 && singleObjectFactor(trig2L_obj2, trig2Lsym_obj2, trigs1L_obj2, efficiencies2);
991 globalEfficiencies =
Efficiencies(1.) - ~efficiencies1[0]*~efficiencies2[0] + (efficiencies1[1]-efficiencies1[0])*(efficiencies2[1]-efficiencies2[0])
992 + (efficiencies1[2]-efficiencies1[0])*(efficiencies2[2]-efficiencies2[0])
993 - (efficiencies1[0]-efficiencies1[1]-efficiencies1[2]+efficiencies1[3])*(efficiencies2[0]-efficiencies2[1]-efficiencies2[2]+efficiencies2[3]);
1000 template<
typename Trig3Lmix>
1002 -> std::enable_if_t<Trig3Lmix::is3Lmix(),
bool>
1004 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_One3L() at line " << __LINE__);
1015 template<
typename Trig3Lmix1,
typename Trig3Lmix2>
1017 -> std::enable_if_t<Trig3Lmix1::is3Lmix()
1018 && Trig3Lmix2::is3Lmix()
1019 && Trig3Lmix1::object1() == Trig3Lmix2::object2()
1020 && Trig3Lmix1::object2() == Trig3Lmix2::object1(),
1023 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_Two3L() at line " << __LINE__);
1025 auto trig2La = trig1.template side<Trig3Lmix1::object1()>();
1026 auto trig1La = trig2.template side<Trig3Lmix2::object2()>();
1029 if(!trig2La.hiddenBy(trig1La)) success = success && globalEfficiency(leptons,
runNumber, trig2La, trig1La,
efficiencies[2]);
1031 auto trig2Lb = trig2.template side<Trig3Lmix2::object1()>();
1032 auto trig1Lb = trig1.template side<Trig3Lmix1::object2()>();
1035 if(!trig2Lb.hiddenBy(trig1Lb)) success = success && globalEfficiency(leptons,
runNumber, trig2Lb, trig1Lb,
efficiencies[5]);
1045 template<
typename Trig4Lsym>
1047 -> std::enable_if_t<Trig4Lsym::is4Lsym(),
bool>
1049 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_One4L() at line " << __LINE__);
1050 globalEfficiencies = {0.};
1051 Efficiencies singleInefficiencies{1.}, efficiencies2L{0.}, efficiencies3L{0.};
1052 bool success =
true;
1053 for(
auto& lepton : leptons)
1055 if(trig.irrelevantFor(lepton) || !aboveThreshold(lepton, trig()))
continue;
1096 for(
auto itr=
tp.cbegin(lepton.
type()); itr!=
end; ++itr)
if(
aboveThreshold(lepton, *itr)) validLegs.emplace(*itr);
1103 const int nLegs =
static_cast<int>(std::count_if(
1104 trig.
leg.begin(), trig.
leg.end(), [](
auto x){ return x != 0ul; }));
1105 const int sameLegs =
static_cast<int>(
std::count(
1106 trig.
leg.begin(), trig.
leg.end(), trig.
leg[0]));
1107 if(sameLegs == nLegs)
1110 return std::count_if(
1113 [&](
auto& legs) { return legs.count(trig.leg[0]); }) >= nLegs;
1118 bool n0 =
false,
n1 =
false;
1119 for(
auto& legs : firedLegs)
1121 if(n0 && legs.count(trig.
leg[1]))
return true;
1122 if(
n1 && legs.count(trig.
leg[0]))
return true;
1123 n0 = n0 || legs.count(trig.
leg[0]);
1124 n1 =
n1 || legs.count(trig.
leg[1]);
1130 auto end = firedLegs.end();
1131 for(
auto legs0=firedLegs.begin();legs0!=
end;++legs0)
1133 for(
int i=0;
i<3;++
i)
1135 if(!legs0->count(trig.
leg[
i]))
continue;
1136 for(
auto legs1=legs0+1;legs1!=
end;++legs1)
1138 for(
int j=1;j<3;++j)
1140 if(!legs1->count(trig.
leg[(
i+j)%3]))
continue;
1141 for(
auto legs2=legs1+1;legs2!=
end;++legs2)
1143 if(legs2->count(trig.
leg[(
i+3-j)%3]))
return true;
1160 ATH_MSG_DEBUG(
"Entered Calculator::globalEfficiency_Toys() at line " << __LINE__);
1161 globalEfficiencies = {0.};
1167 std::map<const Lepton*, std::vector<std::pair<std::size_t, Efficiencies> > > leptonEfficiencies;
1168 for(
auto& lepton : leptons)
1173 const int nLegs = validLegs.size();
1176 bool success =
true;
1181 if(!success)
return false;
1194 std::mt19937_64 randomEngine(seed);
1195 std::uniform_real_distribution<double> uniformPdf(0., 1.);
1196 std::vector<flat_set<std::size_t> > firedLegs(leptonEfficiencies.size());
1197 unsigned long nPassed[2] = {0, 0};
1202 auto legs = firedLegs.begin();
1203 for(
auto& kv : leptonEfficiencies)
1206 double x = uniformPdf(randomEngine);
1207 for(
auto&
p : kv.second)
1209 if(
x < (
step?
p.second.mc():
p.second.data())) legs->emplace(
p.first);
1227 m_formula(nullptr), m_defs(defs)
1233 for(
auto itr1=
m_defs.cbegin(); itr1!=
m_defs.cend(); ++itr1)
1234 for(
auto itr2=itr1+1; itr2!=
m_defs.cend(); ++itr2)
1235 if(itr1->type==itr2->type && itr1->leg==itr2->leg)
return true;
1241 template<
typename T>
1252 template<
typename T>
1263 template<
typename T>
1275 template<
typename Param>
1278 std::remove_cv_t<std::remove_reference_t<typename Param::ArgType>> trigs;
1284 if(!Param::multiple())
break;
1290 template<
typename... Trigs>
1293 for(
auto& def :
m_defs) def.used =
false;
1298 if(std::all_of(
m_defs.cbegin(),
m_defs.cend(), [](
auto& def){return def.used;}))
return true;
1305 template<TriggerType
object_flag>
1310 using A_2sym =
typename A::T_2sym;
1311 using A_2asym =
typename A::T_2asym;
1314 return bindFunction<typename A::T_1>() || bindFunction<A1L>();
1318 return bindFunction<A_2sym>() || bindFunction<A_2asym>()
1319 || bindFunction<A_2sym, A1L>() || bindFunction<A_2asym, A1L>();
1327 return bindFunction<typename A::T_3sym>() || bindFunction<typename A::T_3halfsym>();
1331 return bindFunction<typename A::T_4sym>();
1336 template<TriggerType
object_flag1, TriggerType
object_flag2>
1343 using A_1 =
typename A::T_1;
1344 using B_1 =
typename B::T_1;
1347 using A_2sym =
typename A::T_2sym;
1348 using B_2sym =
typename B::T_2sym;
1349 using A_2asym =
typename A::T_2asym;
1350 using B_2asym =
typename B::T_2asym;
1351 using AB_1_1 =
typename AB::T_1_1;
1356 return bindFunction<A_1, B_1>() || bindFunction<flat_set<A_1>,
flat_set<B_1>>();
1360 return bindFunction<AB_1_1>() || bindFunction<AB_1_1, flat_set<A_1>,
flat_set<B_1>>();
1366 bindFunction<A_2sym, AB_1_1>() || bindFunction<A_2asym, AB_1_1>()
1367 || bindFunction<B_2sym, AB_1_1>() || bindFunction<B_2asym, AB_1_1>()
1381 return bindFunction<typename AB::T_2sym_1>() || bindFunction<typename AB::T_1_2sym>()
1382 || bindFunction<typename AB::T_2asym_1>() || bindFunction<typename AB::T_1_2asym>();
1386 return bindFunction<typename AB::T_2sym_1, typename AB::T_1_2sym>()
1387 || bindFunction<typename AB::T_2asym_1, typename AB::T_1_2sym>()
1388 || bindFunction<typename AB::T_2sym_1, typename AB::T_1_2asym>()
1389 || bindFunction<typename AB::T_2asym_1, typename AB::T_1_2asym>();
1396 auto countTriggers = [&](
auto nlep_flag) {
return std::count_if(
m_defs.cbegin(),
m_defs.cend(), [=](
auto& def){return def.type&nlep_flag;}); };
1401 auto exclusively = [&](
auto obj_flags) {
return std::none_of(
m_defs.cbegin(),
m_defs.cend(), [=](
auto& def){return def.type&TT_MASK_FLAVOUR&~obj_flags;}); };
1404 if(exclusively(
TT_ELECTRON_FLAG))
return findAndBindFunction<TT_ELECTRON_FLAG>();
1405 if(exclusively(
TT_MUON_FLAG))
return findAndBindFunction<TT_MUON_FLAG>();
1406 if(exclusively(
TT_PHOTON_FLAG))
return findAndBindFunction<TT_PHOTON_FLAG>();
1409 bool success =
false;
1413 if(success)
return true;
1416 std::vector<Helper> helpers;
1420 [&](
auto& def){ return (def.type&obj_flag) && TriggerProperties(def.type).mixed();}))
continue;
1421 std::vector<ImportData::TrigDef> trigs1, trigs2;
1422 std::partition_copy(
m_defs.begin(),
m_defs.end(), std::back_inserter(trigs1), std::back_inserter(trigs2), [&](
auto& def){ return (def.type&obj_flag); });
1424 if(!trigs1.size())
continue;
1425 helpers.emplace_back(trigs1);
1426 if(!helpers.back().findAndBindFunction())
return false;