27 #include <initializer_list> 
   33 #define MSGSOURCE "TrigGlobEffCorrValidation" 
   93             if(kv.first[0] != 
'm') 
continue;
 
   95             for(
char c : kv.first)
 
   97                 if(
c==
'u' && 
leg.back()==
'm') 
leg.replace(
leg.end()-1, 
leg.end(), 
"HLT_mu");
 
   98                 else leg.push_back(
c);
 
  133     std::function<
bool(
const std::vector<const xAOD::Electron*>&,
const std::vector<const xAOD::Muon*>&,
const std::vector<const xAOD::Photon*>&)> 
eventSelection = 
nullptr;
 
  192 template<
class Lepton>
 
  193 inline unsigned count(
const std::vector<const Lepton*>& leptons, 
float ptmin, 
float ptmax = 1e12f)
 
  195     return std::count_if(leptons.cbegin(), leptons.cend(), [=](
const Lepton* 
l){return l->pt()>=ptmin && l->pt()<ptmax;});
 
  198 bool run_test(
const Config& 
cfg, 
int toy_to_debug = -1);
 
  200 using namespace asg::msgUserCode;
 
  205     const std::string flagQuiet(
"--quiet"), flagFast(
"--fast"), flagSkip(
"--skip-if-athena");
 
  209         else if(
argv[
i] == flagFast) 
fast = 
true;
 
  210     #ifndef XAOD_STANDALONE 
  211         else if(
argv[
i] == flagSkip) 
skip = 
true;
 
  216 #ifndef XAOD_STANDALONE 
  217     Warning(
MSGSOURCE, 
"This test doesn't work with athena for the moment.");
 
  222 #ifdef XAOD_STANDALONE 
  223     StatusCode::enableFailure();
 
  234     for(
int i=0;
i<10;++
i)
 
  245     for(
int i=0;
i<10;++
i)
 
  256     for(
int i=0;
i<10;++
i)
 
  262     using VE = 
const std::vector<const xAOD::Electron*>&;
 
  263     using VM = 
const std::vector<const xAOD::Muon*>&;
 
  264     using VP = 
const std::vector<const xAOD::Photon*>&;
 
  267         .setTriggers(
"e24_lhmedium_L1EM20VH_OR_e60_lhmedium_OR_e120_lhloose || mu20_iloose_L1MU15_OR_mu50")
 
  268         .setLeptonPDF(1, 1, {30e3f})
 
  269         .setEfficiency(
"e24_lhmedium_L1EM20VH_OR_e60_lhmedium_OR_e120_lhloose", 0.60)
 
  270         .setEfficiency(
"mu20_iloose_L1MU15_OR_mu50", 0.60)
 
  271         .setExpectedEfficiency(0.60, 1
e-6)
 
  275         .setTriggers(
"e24_lhmedium_L1EM20VH_OR_e60_lhmedium_OR_e120_lhloose || mu20_iloose_L1MU15_OR_mu50")
 
  276         .setLeptonPDF(1, 1, {30e3f})
 
  277         .setUnavailable(
"e24_lhmedium_L1EM20VH_OR_e60_lhmedium_OR_e120_lhloose")
 
  278         .setEfficiency(
"mu20_iloose_L1MU15_OR_mu50", 0.60)
 
  279         .setExpectedEfficiency(0.806800, 1
e-6)
 
  283         .setTriggers(
"e24_lhmedium_L1EM20VH_OR_e60_lhmedium_OR_e120_lhloose || mu20_iloose_L1MU15_OR_mu50")
 
  284         .setLeptonPDF(1, 4, {30e3f})
 
  285         .setEfficiency(
"e24_lhmedium_L1EM20VH_OR_e60_lhmedium_OR_e120_lhloose", 0.40)
 
  289         .setTriggers(
"2e12_lhloose_L12EM10VH")
 
  290         .setLeptonPDF(2, 2, {30e3f})
 
  291         .setEfficiency(
"e12_lhloose_L1EM10VH", 0.50)
 
  292         .setExpectedEfficiency(0.25, 1
e-6)
 
  296         .setTriggers(
"2e12_lhloose_L12EM10VH")
 
  297         .setLeptonPDF(2, 3, {30e3f})
 
  298         .setEfficiency(
"e12_lhloose_L1EM10VH", 0.50)
 
  302         .setTriggers(
"e17_lhloose_mu14")
 
  303         .setLeptonPDF(2, 2, {20e3f})
 
  304         .setEfficiency(
"e17_lhloose", 0.60)
 
  305         .setEfficiency(
"mu14", 0.60)
 
  306         .setExpectedEfficiency(0.36, 1
e-6)
 
  307         .setEventSelection([](VE ve, VM vm, VP) { 
return count(ve,18e3f)>0&&
count(vm,15e3f)>0; })
 
  311         .setTriggers(
"e17_lhloose_mu14")
 
  312         .setLeptonPDF(2, 3, {16e3f, 20e3f})
 
  313         .setEfficiency(
"e17_lhloose", 0.64)
 
  314         .setEfficiency(
"mu14", 0.56)
 
  315         .setEventSelection([](VE ve, VM vm, VP) { 
return count(ve,18e3f)>0&&
count(vm,15e3f)>0; })
 
  319         .setTriggers(
"mu18_mu8noL1")
 
  320         .setLeptonPDF(2, 2, {30e3f})
 
  321         .setEfficiency(
"mu18", 0.70)
 
  322         .setEfficiency(
"mu8noL1", 0.70)
 
  323         .setExpectedEfficiency(0.49, 1
e-6)
 
  327         .setTriggers(
"mu18_mu8noL1")
 
  328         .setLeptonPDF(2, 3, {11e3f, 21e3f})
 
  329         .setEfficiency(
"mu18", 0.60)
 
  330         .setEfficiency(
"mu8noL1", 0.70)
 
  331         .setEventSelection([](VE, VM vm, VP) { 
return count(vm,19e3f)>0&&
count(vm,10e3f)>1; })
 
  335         .setTriggers(
"2e12_lhloose_L12EM10VH || e17_lhloose_mu14 || mu18_mu8noL1")
 
  336         .setLeptonPDF(2, 4, {10e3f, 16e3f, 20e3f})
 
  337         .setEfficiency(
"e12_lhloose_L1EM10VH", 0.50)
 
  338         .setEfficiency(
"e17_lhloose", 0.60)
 
  339         .setEfficiency(
"mu18", 0.60)
 
  340         .setEfficiency(
"mu14", 0.60)
 
  341         .setEfficiency(
"mu8noL1", 0.70)
 
  342         .setEventSelection([](VE ve, VM vm, VP) { 
return count(ve,13e3f)>1 
 
  347         .setTriggers(
"2e12_lhloose_L12EM10VH || e17_lhloose_mu14 || mu18_mu8noL1 || e24_lhmedium_L1EM20VH_OR_e60_lhmedium_OR_e120_lhloose || mu20_iloose_L1MU15_OR_mu50")
 
  348         .setLeptonPDF(1, 4, {10e3f, 16e3f, 20e3f, 30e3f})
 
  349         .setEfficiency(
"e24_lhmedium_L1EM20VH_OR_e60_lhmedium_OR_e120_lhloose", 0.40)
 
  350         .setEfficiency(
"mu20_iloose_L1MU15_OR_mu50", 0.40)
 
  351         .setEfficiency(
"e12_lhloose_L1EM10VH", 0.50)
 
  352         .setEfficiency(
"e17_lhloose", 0.60)
 
  353         .setEfficiency(
"mu18", 0.60)
 
  354         .setEfficiency(
"mu14", 0.60)
 
  355         .setEfficiency(
"mu8noL1", 0.70)
 
  356         .setEventSelection([](VE ve, VM vm, VP) { 
return count(ve,13e3f)>1 
 
  358             || 
count(ve,25e3f)>0 || 
count(vm,21.5e3f)>0; })
 
  362         .setTriggers(
"e17_lhloose_2e9_lhloose")
 
  363         .setLeptonPDF(3, 3, {20e3f})
 
  364         .setEfficiency(
"e17_lhloose", 0.90)
 
  365         .setEfficiency(
"e9_lhloose", 0.90)
 
  366         .setExpectedEfficiency(0.729, 1
e-6)
 
  370         .setTriggers(
"e17_lhloose_2e9_lhloose")
 
  371         .setLeptonPDF(3, 5, {12e3f, 20e3f})
 
  372         .setEfficiency(
"e17_lhloose", 0.60)
 
  373         .setEfficiency(
"e9_lhloose", 0.70)
 
  374         .setEventSelection([](VE ve, VM, VP) { 
return (
count(ve,18e3f)>0&&
count(ve,10e3f)>2); })
 
  379         .setLeptonPDF(3, 3, {10e3f})
 
  380         .setEfficiency(
"mu6", 0.90)
 
  381         .setExpectedEfficiency(0.729, 1
e-6)
 
  386         .setLeptonPDF(3, 5, {10e3f})
 
  387         .setEfficiency(
"mu6", 0.70)
 
  388         .setEventSelection([](VE, VM vm, VP) { 
return count(vm,7e3f)>2; })
 
  392         .setTriggers(
"e12_lhloose_2mu10 || 2e12_lhloose_mu10")
 
  393         .setLeptonPDF(3, 5, {14e3f})
 
  394         .setEfficiency(
"e12_lhloose", 0.50)
 
  395         .setEfficiency(
"mu10", 0.60)
 
  396         .setEventSelection([](VE ve, VM vm, VP) { 
return (
count(ve,13e3f)>1&&
count(vm,11e3f)>0) || (
count(ve,13e3f)>0&&
count(vm,11e3f)>1); })
 
  401         .setTriggers(
"2mu10 || 2mu14 || mu24_iloose_L1MU15")
 
  402         .setLeptonPDF(1, 4, {13e3f, 16e3f, 30e3f})
 
  403         .setEfficiency(
"mu10", 0.70)
 
  404         .setEfficiency(
"mu14", 0.60)
 
  405         .setEfficiency(
"mu24_iloose_L1MU15", 0.30)
 
  406         .setEventSelection([](VE, VM vm, VP) { 
return (
count(vm,11e3f)>1) || (
count(vm,25.5e3f)>1) ; })
 
  410         .setTriggers(
"mu18_mu8noL1 || 2mu14 || mu24_iloose_L1MU15")
 
  411         .setLeptonPDF(1, 4, {11e3f, 16e3f, 20e3f, 30e3f})
 
  412         .setEfficiency(
"mu8noL1", 0.80)
 
  413         .setEfficiency(
"mu14", 0.70)
 
  414         .setEfficiency(
"mu18", 0.60)
 
  415         .setEfficiency(
"mu24_iloose_L1MU15", 0.30)
 
  416         .setEventSelection([](VE, VM vm, VP) { 
return (
count(vm,25.5e3f)>0) || (
count(vm,10e3f)>1&&
count(vm,19e3f)>0) || (
count(vm,15e3f)>1) ; })
 
  420         .setTriggers(
"2e12_lhloose_L12EM10VH || mu18_mu8noL1 || 2mu14 || e17_lhloose_mu14 || e7_lhmedium_mu24 || e24_lhmedium_L1EM20VH_OR_e60_lhmedium_OR_e120_lhloose || mu20_iloose_L1MU15")
 
  421         .setLeptonPDF(2, 2, {11e3f, 13e3f, 16e3f, 20e3f, 30e3f})
 
  422         .setEfficiency(
"mu8noL1", 0.80)
 
  423         .setEfficiency(
"mu14", 0.70)
 
  424         .setEfficiency(
"mu18", 0.60)
 
  425         .setEfficiency(
"mu20_iloose_L1MU15", 0.30)
 
  426         .setEfficiency(
"mu24", 0.37)
 
  427         .setEfficiency(
"e7_lhmedium", 0.53)
 
  428         .setEfficiency(
"e12_lhloose_L1EM10VH", 0.73)
 
  429         .setEfficiency(
"e17_lhloose", 0.67)
 
  430         .setEfficiency(
"e24_lhmedium_L1EM20VH_OR_e60_lhmedium_OR_e120_lhloose", 0.42)
 
  431         .setEventSelection([](VE ve, VM vm, VP) { 
return (
count(vm,25.5e3f)>0) || (
count(ve,25e3f)>0) || (
count(ve,13e3f)>1) || (
count(vm,15e3f)>1)
 
  436         .setTriggers(
"2g22_tight_L12EM15VHI")
 
  437         .setLeptonPDF(2, 3, {30e3f})
 
  438         .setEfficiency(
"g22_tight_L1EM15VHI", 0.60)
 
  439         .setEventSelection([](VE, VM, VP vp) { 
return count(vp,23e3f)>1; })
 
  443         .setTriggers(
"2g50_loose_L12EM20VH || 2g22_tight_L12EM15VHI || g120_loose")
 
  444         .setLeptonPDF(2, 3, {25e3f, 60e3f, 150e3f})
 
  445         .setEfficiency(
"g22_tight_L1EM15VHI", 0.43)
 
  446         .setEfficiency(
"g50_loose_L1EM20VH", 0.74)
 
  447         .setEfficiency(
"g120_loose", 0.82)
 
  448         .setEventSelection([](VE, VM, VP vp) { 
return count(vp,23e3f)>1 || 
count(vp,121e3f)>0; })
 
  452         .setTriggers(
"2g22_tight_L12EM15VHI || g35_medium_g25_medium_L12EM20VH")
 
  453         .setLeptonPDF(2, 4, {24e3f, 30e3f, 40e3f})
 
  454         .setEfficiency(
"g22_tight_L1EM15VHI", 0.43)
 
  455         .setEfficiency(
"g35_medium_L1EM20VH", 0.74)
 
  456         .setEfficiency(
"g25_medium_L1EM20VH", 0.82)
 
  457         .setEventSelection([](VE, VM, VP vp) { 
return count(vp,23e3f)>1; })
 
  461         .setTriggers(
"2g25_loose_g15_loose")
 
  462         .setLeptonPDF(3, 3, {30e3f})
 
  463         .setEfficiency(
"g25_loose", 0.8)
 
  464         .setEfficiency(
"g15_loose", 0.9)
 
  465         .setExpectedEfficiency(0.704, 1
e-6)
 
  469         .setTriggers(
"2g25_loose_g15_loose")
 
  470         .setLeptonPDF(3, 5, {20e3f, 30e3f})
 
  471         .setEfficiency(
"g25_loose", 0.63)
 
  472         .setEfficiency(
"g15_loose", 0.88)
 
  473         .setEventSelection([](VE, VM, VP vp) { 
return count(vp,26e3f)>1 && 
count(vp,16e3f)>2; })
 
  477         .setTriggers(
"e24_lhmedium_L1EM20VH_OR_e60_lhmedium_OR_e120_lhloose || mu20_iloose_L1MU15_OR_mu50 || g120_loose")
 
  478         .setLeptonPDF(1, 2, {150e3f})
 
  479         .setEfficiency(
"e24_lhmedium_L1EM20VH_OR_e60_lhmedium_OR_e120_lhloose", 0.55)
 
  480         .setEfficiency(
"mu20_iloose_L1MU15_OR_mu50", 0.66)
 
  481         .setEfficiency(
"g120_loose", 0.77)
 
  485         .setTriggers(
"e17_lhloose_2e9_lhloose || 3mu6 || 3g20_loose")
 
  486         .setLeptonPDF(4, 6, {30e3f})
 
  487         .setEfficiency(
"e9_lhloose", 0.68)
 
  488         .setEfficiency(
"e17_lhloose", 0.54)
 
  489         .setEfficiency(
"mu6", 0.77)
 
  490         .setEfficiency(
"g20_loose", 0.81)
 
  491         .setEventSelection([](VE ve, VM vm, VP vp) { 
return count(ve,18e3f)>2 || 
count(vm,10e3f)>2 || 
count(vp,21e3f)>2; })
 
  495         .setTriggers(
"g120_loose || 2e12_lhloose_mu10 || 2g22_tight_L12EM15VHI")
 
  496         .setLeptonPDF(3, 6, {150e3f})
 
  497         .setEfficiency(
"e12_lhloose", 0.48)
 
  498         .setEfficiency(
"mu10", 0.62)
 
  499         .setEfficiency(
"g22_tight_L1EM15VHI", 0.35)
 
  500         .setEfficiency(
"g120_loose", 0.56)
 
  501         .setEventSelection([](VE ve, VM vm, VP vp) { 
return (
count(ve,13e3f)>1  && 
count(vm,11e3f)>0) || 
count(vp,21e3f)>0; })
 
  505         .setTriggers(
"4mu4_L14MU3V")
 
  506         .setLeptonPDF(4, 6, {20e3f})
 
  507         .setEfficiency(
"mu4_L1MU3V", 0.72)
 
  508         .setEventSelection([](VE, VM vm, VP) { 
return count(vm,5e3f)>=4; })
 
  515     ToolHandleArray<IAsgElectronEfficiencyCorrectionTool>& electronEffToolsHandles, ToolHandleArray<IAsgElectronEfficiencyCorrectionTool>& electronSFToolsHandles, 
 
  516     ToolHandleArray<CP::IMuonTriggerScaleFactors>& muonToolsHandles,
 
  517     ToolHandleArray<IAsgPhotonEfficiencyCorrectionTool>& photonEffToolsHandles, ToolHandleArray<IAsgPhotonEfficiencyCorrectionTool>& photonSFToolsHandles, 
 
  518     const std::string& 
triggers, 
const std::map<std::string, std::string>& legsPerTool, 
unsigned long nToys, 
bool debug)
 
  521     ANA_CHECK(
tool.setProperty(
"ElectronEfficiencyTools", electronEffToolsHandles));
 
  522     ANA_CHECK(
tool.setProperty(
"ElectronScaleFactorTools", electronSFToolsHandles));
 
  523     ANA_CHECK(
tool.setProperty(
"PhotonEfficiencyTools", photonEffToolsHandles));
 
  524     ANA_CHECK(
tool.setProperty(
"PhotonScaleFactorTools", photonSFToolsHandles));
 
  525     ANA_CHECK(
tool.setProperty(
"ListOfLegsPerTool", legsPerTool));
 
  539     const int nToysPerEvent = (
fast? 250 : 500), nToysPerTest = (
fast? 200 : 2000), nToySamples = 10;
 
  540     std::vector<SimpleElectronEfficiencyCorrectionTool*> electronTools;
 
  541     ToolHandleArray<IAsgElectronEfficiencyCorrectionTool> electronEffToolsHandles, electronSFToolsHandles;
 
  542     std::vector<SimplePhotonEfficiencyCorrectionTool*> photonTools;
 
  543     ToolHandleArray<IAsgPhotonEfficiencyCorrectionTool> photonEffToolsHandles, photonSFToolsHandles;
 
  544     std::map<std::string,std::string> legsPerTool;
 
  545     for(
auto& kv : 
cfg.efficiencies)
 
  550             legsPerTool.emplace(electronTools.back()->name(), kv.first);
 
  551             #ifdef XAOD_STANDALONE 
  552                 electronEffToolsHandles.push_back(electronTools.back());
 
  555             legsPerTool.emplace(electronTools.back()->name(), kv.first);
 
  556             #ifdef XAOD_STANDALONE 
  557                 electronSFToolsHandles.push_back(electronTools.back());
 
  560         else if(kv.first[0]==
'g')
 
  563             legsPerTool.emplace(photonTools.back()->name(), kv.first);
 
  564             #ifdef XAOD_STANDALONE 
  565                 photonEffToolsHandles.push_back(photonTools.back());
 
  568             legsPerTool.emplace(photonTools.back()->name(), kv.first);
 
  569             #ifdef XAOD_STANDALONE 
  570                 photonSFToolsHandles.push_back(photonTools.back());
 
  574     if (!
cfg.unavailable.empty())
 
  578     std::vector<SimpleMuonTriggerScaleFactors*> muonTools;
 
  580     ToolHandleArray<CP::IMuonTriggerScaleFactors> muonToolsHandles;
 
  581     #ifdef XAOD_STANDALONE 
  582         muonToolsHandles.push_back(muonTools.back());
 
  584     std::string 
suffix = ((toy_to_debug>=0)? 
"_debug" : 
"");
 
  587     bool debug = 
cfg.debug || (toy_to_debug>=0);
 
  588     bool compareWithToys = 
cfg.unavailable.empty();
 
  589     ANA_CHECK(
configure(trigGlobTool, electronEffToolsHandles, electronSFToolsHandles, muonToolsHandles, photonEffToolsHandles, photonSFToolsHandles, 
cfg.triggers, legsPerTool, 0, 
debug));
 
  590     if (compareWithToys) {
 
  591         ANA_CHECK(
configure(trigGlobTool_toys, electronEffToolsHandles, electronSFToolsHandles, muonToolsHandles, photonEffToolsHandles, photonSFToolsHandles, 
cfg.triggers, legsPerTool, nToysPerEvent, 
debug));
 
  593     std::default_random_engine rdm;
 
  594     std::uniform_int_distribution<unsigned> nleptonsPdf(
cfg.minLeptons, 
cfg.maxLeptons);
 
  595     std::discrete_distribution<> flavourPdf({1.*
cfg.generateElectrons, 1.*
cfg.generateMuons, 1.*
cfg.generatePhotons});
 
  596     std::uniform_int_distribution<unsigned> ptIndexPdf(0, 
cfg.leptonPtValues.size()-1);
 
  597     std::vector<const xAOD::Electron*> 
electrons;
 
  598     std::vector<const xAOD::Muon*> muons;
 
  599     std::vector<const xAOD::Photon*> photons;
 
  600     std::vector<const xAOD::IParticle*> 
particles;
 
  601     double sum_eff = 0., sum_eff_toys[nToySamples] = {0};
 
  602     for(
int toy=0; toy<nToysPerTest; ++toy)
 
  610             const unsigned nLeptons = nleptonsPdf(rdm);
 
  613                 float pt = 
cfg.leptonPtValues[ptIndexPdf(rdm)];
 
  614                 switch(flavourPdf(rdm))
 
  628                         muons.push_back(
muon);
 
  636                         photons.push_back(
photon);
 
  643         while(
cfg.eventSelection && !
cfg.eventSelection(
electrons, muons, photons));
 
  644         if(toy_to_debug>=0 && toy!=toy_to_debug) 
continue;
 
  652                 Info(
MSGSOURCE, 
"Running %s test again for this toy event, with the debug flag set", 
cfg.testName.c_str());
 
  658         for(
int spl=0;spl<compareWithToys*nToySamples;++spl)
 
  665                     Info(
MSGSOURCE, 
"Running %s test again for this toy event, with the debug flag set", 
cfg.testName.c_str());
 
  671             sum_eff_toys[spl] += eff_toys;
 
  673         if(toy == toy_to_debug) 
return true;
 
  675     if(
cfg.expectedEfficiency > 0.)
 
  677         double eff = sum_eff / nToysPerTest;
 
  678         if(fabs(
eff - 
cfg.expectedEfficiency) > 
cfg.expectedEfficiencyTolerance)
 
  680             Error(
MSGSOURCE, 
"The difference is too large, %f versus %f", 
eff, 
cfg.expectedEfficiency);
 
  686         double eff = sum_eff/nToysPerTest, eff_toys = 0., toys_rms = 0.;
 
  687         for(
double sum : sum_eff_toys) eff_toys += 
sum / nToysPerTest;
 
  688         eff_toys /= nToySamples;
 
  689         for(
double sum : sum_eff_toys) toys_rms += 
pow(
sum/nToysPerTest - eff_toys, 2);
 
  690         toys_rms = sqrt(toys_rms / (nToySamples-1));
 
  691         double  sigma = fabs(
eff-eff_toys) / toys_rms;
 
  695             Error(
MSGSOURCE, 
"The difference is too large");
 
  698         else if(
sigma >= 2.) Warning(
MSGSOURCE, 
"The difference isn't small");
 
  700     for(
auto tool : electronTools) 
delete tool;
 
  701     for(
auto tool : muonTools) 
delete tool;
 
  702     for(
auto tool : photonTools) 
delete tool;