ATLAS Offline Software
Loading...
Searching...
No Matches
TrigGlobEffCorrValidation.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
5// contact: jmaurer@cern.ch
6
14#include "xAODEgamma/Electron.h"
20#include "xAODEgamma/Photon.h"
23
24#include <random>
25#include <functional>
26#include <algorithm>
27#include <initializer_list>
28
29// standalone single-threaded executable:
32
33#define MSGSOURCE "TrigGlobEffCorrValidation"
34
36{
38 std::function<double(float)> m_func;
39public:
40 SimpleElectronEfficiencyCorrectionTool(const std::string& name, double eff = 0.8) : AsgTool(name), m_func([=](float){return eff;}) {}
41 SimpleElectronEfficiencyCorrectionTool(const std::string& name, const std::function<double(float)>& func) : AsgTool(name), m_func(func) {}
43 virtual CP::CorrectionCode getEfficiencyScaleFactor(const xAOD::Electron& electron, double& efficiencyScaleFactor) const override
44 {
45 efficiencyScaleFactor = m_func(electron.pt());
47 }
48 virtual CP::CorrectionCode getEfficiencyScaleFactor(double, double , unsigned int ,double&) const override
49 {
51 }
53 virtual bool isAffectedBySystematic(const CP::SystematicVariation&) const override { return false; }
54 virtual CP::SystematicSet affectingSystematics() const override { return CP::SystematicSet(); }
55 virtual CP::SystematicSet recommendedSystematics() const override { return CP::SystematicSet(); }
56 virtual StatusCode applySystematicVariation(const CP::SystematicSet&) override { return StatusCode::SUCCESS; }
57 virtual int systUncorrVariationIndex( const xAOD::Electron &) const override { return 0; }
58 virtual int getNumberOfToys() const override {return 0;}
59 virtual const CP::SystematicSet& appliedSystematics() const override { static const CP::SystematicSet dummy ; return dummy;};
60 virtual void printCorrelationModels() const override {}
61};
62
64{
66 std::function<double(float)> m_func;
67public:
68 SimplePhotonEfficiencyCorrectionTool(const std::string& name, double eff = 0.8) : AsgTool(name), m_func([=](float){return eff;}) {}
69 SimplePhotonEfficiencyCorrectionTool(const std::string& name, const std::function<double(float)>& func) : AsgTool(name), m_func(func) {}
71 virtual CP::CorrectionCode getEfficiencyScaleFactor(const xAOD::Egamma& photon, double& efficiencyScaleFactor) const override
72 {
73 efficiencyScaleFactor = m_func(photon.pt());
75 }
78 virtual bool isAffectedBySystematic(const CP::SystematicVariation&) const override { return false; }
79 virtual CP::SystematicSet affectingSystematics() const override { return CP::SystematicSet(); }
80 virtual CP::SystematicSet recommendedSystematics() const override { return CP::SystematicSet(); }
81 virtual StatusCode applySystematicVariation(const CP::SystematicSet&) override { return StatusCode::SUCCESS; }
82};
83
85{
87 std::map<std::string, std::function<double(float)>> m_efficiencies;
88public:
89 SimpleMuonTriggerScaleFactors(const std::string& name, const std::map<std::string,std::function<double(float)>>& efficiencies = {}) : AsgTool(name)
90 {
91 for(auto& kv : efficiencies)
92 {
93 if(kv.first[0] != 'm') continue;
94 std::string leg;
95 for(char c : kv.first)
96 {
97 if(c=='u' && leg.back()=='m') leg.replace(leg.end()-1, leg.end(), "HLT_mu");
98 else leg.push_back(c);
99 }
100 m_efficiencies.emplace(leg, kv.second);
101 }
102 }
104 virtual StatusCode initialize(void) override { return StatusCode::SUCCESS; }
105 virtual CP::CorrectionCode getTriggerScaleFactor(const xAOD::MuonContainer&, Double_t&, const std::string&) const override { return CP::CorrectionCode::Ok; }
106 virtual CP::CorrectionCode getTriggerScaleFactor(const xAOD::Muon&, Double_t&, const std::string&) const override { return CP::CorrectionCode::Ok; }
107 virtual CP::CorrectionCode getTriggerEfficiency(const xAOD::Muon& muon, Double_t& efficiency, const std::string& trig, Bool_t) const override
108 {
109 auto itr = m_efficiencies.find(trig);
110 if(itr != m_efficiencies.end())
111 {
112 efficiency = itr->second(muon.pt());
114 }
116 }
117 virtual int getBinNumber(const xAOD::Muon&, const std::string&) const override { return 0; };
118 virtual bool isAffectedBySystematic(const CP::SystematicVariation&) const override { return false; }
119 virtual CP::SystematicSet affectingSystematics() const override { return CP::SystematicSet(); }
120 virtual CP::SystematicSet recommendedSystematics() const override { return CP::SystematicSet(); }
121 virtual StatusCode applySystematicVariation(const CP::SystematicSet&) override { return StatusCode::SUCCESS; }
122 virtual bool isTriggerSupported(const std::string& ) const override {return false;}
123};
124
125struct Config
126{
127 std::string testName;
128 std::string triggers = "";
129 unsigned minLeptons = 1;
130 unsigned maxLeptons = 5;
131 std::vector<float> leptonPtValues;
132 std::map<std::string, std::function<double(float)>> efficiencies;
133 std::function<bool(const std::vector<const xAOD::Electron*>&,const std::vector<const xAOD::Muon*>&,const std::vector<const xAOD::Photon*>&)> eventSelection = nullptr;
134 std::string unavailable;
135 double expectedEfficiency = -1.;
137 bool generateElectrons = false;
138 bool generateMuons = false;
139 bool generatePhotons = false;
140 bool debug = false;
141
142 Config(const char* name) : testName(name), leptonPtValues {30e4f} { }
143 Config& setTriggers(const std::string& t) { triggers = t; return *this; }
144 Config& setLeptonPDF(unsigned nmin, unsigned nmax, std::initializer_list<float> ptvalues)
145 {
146 minLeptons = nmin;
148 leptonPtValues = ptvalues;
149 return *this;
150 }
151 Config& setEfficiency(const std::string& leg, double eff)
152 {
153 efficiencies.emplace(leg, [=](float){return eff;});
154 updateFlavours(leg);
155 return *this;
156 }
157 Config& setEfficiency(const std::string& leg, std::function<double(float)>&& eff)
158 {
159 efficiencies.emplace(leg, eff);
160 updateFlavours(leg);
161 return *this;
162 }
163 Config& setEventSelection(const decltype(eventSelection)& sel) { eventSelection = sel; return *this; }
164 Config& setDebug() { debug = true; return *this; };
166 {
167 expectedEfficiency = eff;
169 return *this;
170 }
171 Config& setUnavailable(const std::string& leg)
172 {
173 if (!unavailable.empty()) unavailable += ',';
174 unavailable += leg;
175 updateFlavours(leg);
176 return *this;
177 }
178private:
179 void updateFlavours(const std::string& leg)
180 {
181 if (leg[0] == 'e') generateElectrons = true;
182 else if (leg[0] == 'm') generateMuons = true;
183 else if (leg[0] == 'g') generatePhotons = true;
184 }
185};
186
190bool quiet = false, fast = false, skip = false;
191
192template<class Lepton>
193inline unsigned count(const std::vector<const Lepton*>& leptons, float ptmin, float ptmax = 1e12f)
194{
195 return std::count_if(leptons.cbegin(), leptons.cend(), [=](const Lepton* l){return l->pt()>=ptmin && l->pt()<ptmax;});
196}
197
198bool run_test(const Config& cfg, int toy_to_debug = -1);
199
200using namespace asg::msgUserCode;
201
202int main(int argc, char* argv[])
203{
204 ANA_CHECK_SET_TYPE(bool);
205 const std::string flagQuiet("--quiet"), flagFast("--fast"), flagSkip("--skip-if-athena");
206 for(int i=1;i<argc;++i)
207 {
208 if(argv[i] == flagQuiet) quiet = true;
209 else if(argv[i] == flagFast) fast = true;
210 #ifndef XAOD_STANDALONE
211 else if(argv[i] == flagSkip) skip = true;
212 #endif
213 }
214 if(skip) return 0;
215
216#ifndef XAOD_STANDALONE
217 Warning(MSGSOURCE, "This test doesn't work with athena for the moment.");
218 // the problem is that one can't initialize a ToolHandle from a pointer
219 // and the Simple* tools are not known to the athena framework.
220#endif
221
222#ifdef XAOD_STANDALONE
223 StatusCode::enableFailure();
225#endif
226 xAOD::TStore store;
228
230 ANA_CHECK(store.record(electronContainer, "Electrons"));
231 auto electronContainerAux = new xAOD::ElectronAuxContainer();
232 ANA_CHECK(store.record(electronContainerAux, "ElectronsAux"));
233 electronContainer->setStore(electronContainerAux);
234 for(int i=0;i<10;++i)
235 {
236 auto el = new xAOD::Electron();
237 electronContainer->push_back(el);
238 }
239
241 ANA_CHECK(store.record(muonContainer, "Muons"));
242 auto muonContainerAux = new xAOD::MuonAuxContainer();
243 ANA_CHECK(store.record(muonContainerAux, "MuonsAux"));
244 muonContainer->setStore(muonContainerAux);
245 for(int i=0;i<10;++i)
246 {
247 auto mu = new xAOD::Muon();
248 muonContainer->push_back(mu);
249 }
250
252 ANA_CHECK(store.record(photonContainer, "Photons"));
253 auto photonContainerAux = new xAOD::PhotonAuxContainer();
254 ANA_CHECK(store.record(photonContainerAux, "PhotonsAux"));
255 photonContainer->setStore(photonContainerAux);
256 for(int i=0;i<10;++i)
257 {
258 auto ph = new xAOD::Photon();
259 photonContainer->push_back(ph);
260 }
261
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*>&;
265
266 ANA_CHECK(run_test(Config("1L (1 lepton)")
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, 1e-6)
272 ));
273
274 ANA_CHECK(run_test(Config("RETURN_UNIT_SCALE_FACTOR")
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, 1e-6)
280 ));
281
282 ANA_CHECK(run_test(Config("1L (2 flavours, 1-4 leptons)")
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)
286 ));
287
288 ANA_CHECK(run_test(Config("2e (2 leptons)")
289 .setTriggers("2e12_lhloose_L12EM10VH")
290 .setLeptonPDF(2, 2, {30e3f})
291 .setEfficiency("e12_lhloose_L1EM10VH", 0.50)
292 .setExpectedEfficiency(0.25, 1e-6)
293 ));
294
295 ANA_CHECK(run_test(Config("2e (2-3 leptons)")
296 .setTriggers("2e12_lhloose_L12EM10VH")
297 .setLeptonPDF(2, 3, {30e3f})
298 .setEfficiency("e12_lhloose_L1EM10VH", 0.50)
299 ));
300
301 ANA_CHECK(run_test(Config("emu (2 leptons)")
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, 1e-6)
307 .setEventSelection([](VE ve, VM vm, VP) { return count(ve,18e3f)>0&&count(vm,15e3f)>0; })
308 ));
309
310 ANA_CHECK(run_test(Config("emu (2-3 leptons)")
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; })
316 ));
317
318 ANA_CHECK(run_test(Config("2mu (asym) (2 leptons)")
319 .setTriggers("mu18_mu8noL1")
320 .setLeptonPDF(2, 2, {30e3f})
321 .setEfficiency("mu18", 0.70)
322 .setEfficiency("mu8noL1", 0.70)
323 .setExpectedEfficiency(0.49, 1e-6)
324 ));
325
326 ANA_CHECK(run_test(Config("2mu (asym) (2-3 leptons)")
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; })
332 ));
333
334 ANA_CHECK(run_test(Config("2e||emu||2mu")
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
343 || (count(ve,18e3f)>0&&count(vm,15e3f)>0) || (count(vm,19e3f)>0&&count(vm,10e3f)>1); })
344 ));
345
346 ANA_CHECK(run_test(Config("2e||emu||2mu||1e||1mu")
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
357 || (count(ve,18e3f)>0&&count(vm,15e3f)>0) || (count(vm,19e3f)>0&&count(vm,10e3f)>1)
358 || count(ve,25e3f)>0 || count(vm,21.5e3f)>0; })
359 ));
360
361 ANA_CHECK(run_test(Config("e_2e (3 leptons)")
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, 1e-6)
367 ));
368
369 ANA_CHECK(run_test(Config("e_2e (3-5 leptons)")
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); })
375 ));
376
377 ANA_CHECK(run_test(Config("3mu (3 leptons)")
378 .setTriggers("3mu6")
379 .setLeptonPDF(3, 3, {10e3f})
380 .setEfficiency("mu6", 0.90)
381 .setExpectedEfficiency(0.729, 1e-6)
382 ));
383
384 ANA_CHECK(run_test(Config("3mu (3-5 leptons)")
385 .setTriggers("3mu6")
386 .setLeptonPDF(3, 5, {10e3f})
387 .setEfficiency("mu6", 0.70)
388 .setEventSelection([](VE, VM vm, VP) { return count(vm,7e3f)>2; })
389 ));
390
391 ANA_CHECK(run_test(Config("2e_mu||e_2mu")
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); })
397 ));
398
399 // not a full test of the function since 2mu10 completely shadows 2mu14, but it validates at least part of the logic. Full test done with photons (see below).
400 ANA_CHECK(run_test(Config("2mu||2mu||mu")
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) ; })
407 ));
408
409 ANA_CHECK(run_test(Config("mu_mu||2mu||mu")
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) ; })
417 ));
418
419 ANA_CHECK(run_test(Config("2e||mu_mu||2mu||emu||emu||e||mu")
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)
432 || (count(vm,10e3f)>1&&count(vm,19e3f)>0) || (count(ve,18e3f)>0&&count(vm,15e3f)>0) || (count(ve,8e3f)>0&&count(vm,25.5e3f)>0); })
433 ));
434
435 ANA_CHECK(run_test(Config("2g (sym)")
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; })
440 ));
441
442 ANA_CHECK(run_test(Config("2g (sym) || 2g (sym) || 1g")
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; })
449 ));
450
451 ANA_CHECK(run_test(Config("2g (sym) || 2g (asym)")
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; })
458 ));
459
460 ANA_CHECK(run_test(Config("2g_g (3 photons)")
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, 1e-6)
466 ));
467
468 ANA_CHECK(run_test(Config("2g_g (3-5 photons)")
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; })
474 ));
475
476 ANA_CHECK(run_test(Config("e || mu || g (factorized)")
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)
482 ));
483
484 ANA_CHECK(run_test(Config("3e || 3mu || 3g (factorized)")
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; })
492 ));
493
494 ANA_CHECK(run_test(Config("e_2mu || 2g || 1g (factorized)")
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; })
502 ));
503
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; })
509 ));
510 return 0;
511}
512
513
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)
519{
520 ANA_CHECK_SET_TYPE(bool);
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));
526 ANA_CHECK(tool.setProperty("MuonTools", muonToolsHandles));
527 ANA_CHECK(tool.setProperty("TriggerCombination2015", triggers));
528 ANA_CHECK(tool.setProperty("NumberOfToys", nToys));
529 ANA_CHECK(tool.setProperty("UseInternalSeed", true));
530 ANA_CHECK(tool.setProperty("OutputLevel", debug? MSG::DEBUG : quiet? MSG::WARNING : MSG::INFO));
531 ANA_CHECK(tool.initialize());
532 return true;
533}
534
535bool run_test(const Config& cfg, int toy_to_debug)
536{
537 ANA_CHECK_SET_TYPE(bool);
538 if(!quiet) Info(MSGSOURCE, "Running test %s", cfg.testName.c_str());
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)
546 {
547 if(kv.first[0]=='e')
548 {
549 electronTools.emplace_back(new SimpleElectronEfficiencyCorrectionTool("EFF-"+kv.first, kv.second));
550 legsPerTool.emplace(electronTools.back()->name(), kv.first);
551 #ifdef XAOD_STANDALONE
552 electronEffToolsHandles.push_back(electronTools.back());
553 #endif
554 electronTools.emplace_back(new SimpleElectronEfficiencyCorrectionTool("SF-"+kv.first, 1.));
555 legsPerTool.emplace(electronTools.back()->name(), kv.first);
556 #ifdef XAOD_STANDALONE
557 electronSFToolsHandles.push_back(electronTools.back());
558 #endif
559 }
560 else if(kv.first[0]=='g')
561 {
562 photonTools.emplace_back(new SimplePhotonEfficiencyCorrectionTool("EFF-"+kv.first, kv.second));
563 legsPerTool.emplace(photonTools.back()->name(), kv.first);
564 #ifdef XAOD_STANDALONE
565 photonEffToolsHandles.push_back(photonTools.back());
566 #endif
567 photonTools.emplace_back(new SimplePhotonEfficiencyCorrectionTool("SF-"+kv.first, 1.));
568 legsPerTool.emplace(photonTools.back()->name(), kv.first);
569 #ifdef XAOD_STANDALONE
570 photonSFToolsHandles.push_back(photonTools.back());
571 #endif
572 }
573 }
574 if (!cfg.unavailable.empty())
575 {
577 }
578 std::vector<SimpleMuonTriggerScaleFactors*> muonTools;
579 muonTools.emplace_back(new SimpleMuonTriggerScaleFactors("EFF-muons", cfg.efficiencies));
580 ToolHandleArray<CP::IMuonTriggerScaleFactors> muonToolsHandles;
581 #ifdef XAOD_STANDALONE
582 muonToolsHandles.push_back(muonTools.back());
583 #endif
584 std::string suffix = ((toy_to_debug>=0)? "_debug" : "");
585 asg::AnaToolHandle<ITrigGlobalEfficiencyCorrectionTool> trigGlobTool("TrigGlobalEfficiencyCorrectionTool/trigGlobTool" + suffix);
586 asg::AnaToolHandle<ITrigGlobalEfficiencyCorrectionTool> trigGlobTool_toys("TrigGlobalEfficiencyCorrectionTool/trigGlobTool_toys" + suffix);
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));
592 }
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)
603 {
604 do
605 {
606 electrons.clear();
607 muons.clear();
608 photons.clear();
609 particles.clear();
610 const unsigned nLeptons = nleptonsPdf(rdm);
611 for(unsigned index=0;index<nLeptons;++index)
612 {
613 float pt = cfg.leptonPtValues[ptIndexPdf(rdm)];
614 switch(flavourPdf(rdm))
615 {
616 case 0:
617 {
618 auto electron = electronContainer->at(electrons.size());
619 particles.push_back(electron);
620 electrons.push_back(electron);
621 electron->setPtEtaPhi(pt, 0.f, 0.f);
622 break;
623 }
624 case 1:
625 {
626 auto muon = muonContainer->at(muons.size());
627 particles.push_back(muon);
628 muons.push_back(muon);
629 muon->setP4(pt, 0.f, 0.f);
630 break;
631 }
632 case 2:
633 {
634 auto photon = photonContainer->at(photons.size());
635 particles.push_back(photon);
636 photons.push_back(photon);
637 photon->setPtEtaPhi(pt, 0.f, 0.f);
638 break;
639 }
640 }
641 }
642 }
643 while(cfg.eventSelection && !cfg.eventSelection(electrons, muons, photons));
644 if(toy_to_debug>=0 && toy!=toy_to_debug) continue;
645
646 double dummy, eff = 0., eff_toys;
647 const int runNumber = 281130;
648 if(trigGlobTool->getEfficiency(runNumber, particles, eff, dummy) != CP::CorrectionCode::Ok)
649 {
650 if(toy_to_debug < 0)
651 {
652 Info(MSGSOURCE, "Running %s test again for this toy event, with the debug flag set", cfg.testName.c_str());
653 run_test(cfg, toy);
654 }
655 return false;
656 }
657 sum_eff += eff;
658 for(int spl=0;spl<compareWithToys*nToySamples;++spl)
659 {
660 eff_toys = 0.;
661 if(trigGlobTool_toys->getEfficiency(runNumber, particles, eff_toys, dummy) != CP::CorrectionCode::Ok)
662 {
663 if(toy_to_debug < 0)
664 {
665 Info(MSGSOURCE, "Running %s test again for this toy event, with the debug flag set", cfg.testName.c_str());
666 run_test(cfg, toy);
667 return false;
668 }
669 return false;
670 }
671 sum_eff_toys[spl] += eff_toys;
672 }
673 if(toy == toy_to_debug) return true;
674 }
675 if(cfg.expectedEfficiency > 0.)
676 {
677 double eff = sum_eff / nToysPerTest;
678 if(fabs(eff - cfg.expectedEfficiency) > cfg.expectedEfficiencyTolerance)
679 {
680 Error(MSGSOURCE, "The difference is too large, %f versus %f", eff, cfg.expectedEfficiency);
681 return false;
682 }
683 }
684 if (compareWithToys)
685 {
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;
692 if(!quiet) Info(MSGSOURCE, "Efficiency: %f, toys: %f (signif. = %.1f sigma)", eff, eff_toys, sigma);
693 if(sigma >= 3.)
694 {
695 Error(MSGSOURCE, "The difference is too large");
696 return false;
697 }
698 else if(sigma >= 2.) Warning(MSGSOURCE, "The difference isn't small");
699 }
700 for(auto tool : electronTools) delete tool;
701 for(auto tool : muonTools) delete tool;
702 for(auto tool : photonTools) delete tool;
703 return true;
704}
#define ASG_TOOL_CLASS(CLASSNAME, INT1)
#define ANA_CHECK(EXP)
check whether the given expression was successful
#define ANA_CHECK_SET_TYPE(TYPE)
set the type for ANA_CHECK to report failures
const bool debug
const int nmax(200)
unsigned count(const std::vector< const Lepton * > &leptons, float ptmin, float ptmax=1e12f)
bool run_test(const Config &cfg, int toy_to_debug=-1)
xAOD::ElectronContainer * electronContainer
xAOD::MuonContainer * muonContainer
bool configure(asg::AnaToolHandle< ITrigGlobalEfficiencyCorrectionTool > &tool, ToolHandleArray< IAsgElectronEfficiencyCorrectionTool > &electronEffToolsHandles, ToolHandleArray< IAsgElectronEfficiencyCorrectionTool > &electronSFToolsHandles, ToolHandleArray< CP::IMuonTriggerScaleFactors > &muonToolsHandles, ToolHandleArray< IAsgPhotonEfficiencyCorrectionTool > &photonEffToolsHandles, ToolHandleArray< IAsgPhotonEfficiencyCorrectionTool > &photonSFToolsHandles, const std::string &triggers, const std::map< std::string, std::string > &legsPerTool, unsigned long nToys, bool debug)
xAOD::PhotonContainer * photonContainer
TrigGlobEffCorr::Lepton Lepton
constexpr int pow(int base, int exp) noexcept
Define macros for attributes used to control the static checker.
#define ATLAS_NO_CHECK_FILE_THREAD_SAFETY
Return value from object correction CP tools.
@ Error
Some error happened during the object correction.
@ Ok
The correction was done successfully.
static void enableFailure() noexcept
Class to wrap a set of SystematicVariations.
static std::string toolnameForDefaultScaleFactor()
To be used with the ListOfLegsPerTool property:
void record(const T *p, const std::string &key)
Definition TestStore.h:81
virtual int systUncorrVariationIndex(const xAOD::Electron &) const override
SimpleElectronEfficiencyCorrectionTool(const std::string &name, const std::function< double(float)> &func)
virtual CP::CorrectionCode getEfficiencyScaleFactor(double, double, unsigned int, double &) const override
virtual bool isAffectedBySystematic(const CP::SystematicVariation &) const override
Declare the interface that this class provides.
SimpleElectronEfficiencyCorrectionTool(const std::string &name, double eff=0.8)
virtual StatusCode applySystematicVariation(const CP::SystematicSet &) override
effects: configure this tool for the given list of systematic variations.
virtual void printCorrelationModels() const override
print available/implemented correlation models
virtual const CP::SystematicSet & appliedSystematics() const override
virtual CP::CorrectionCode applyEfficiencyScaleFactor(const xAOD::Electron &) const override
virtual CP::SystematicSet recommendedSystematics() const override
the list of all systematics this tool recommends to use
virtual CP::CorrectionCode getEfficiencyScaleFactor(const xAOD::Electron &electron, double &efficiencyScaleFactor) const override
virtual CP::SystematicSet affectingSystematics() const override
the list of all systematics this tool can be affected by
virtual CP::SystematicSet affectingSystematics() const override
the list of all systematics this tool can be affected by
virtual CP::CorrectionCode getTriggerScaleFactor(const xAOD::Muon &, Double_t &, const std::string &) const override
virtual CP::CorrectionCode getTriggerScaleFactor(const xAOD::MuonContainer &, Double_t &, const std::string &) const override
virtual StatusCode applySystematicVariation(const CP::SystematicSet &) override
effects: configure this tool for the given list of systematic variations.
virtual StatusCode initialize(void) override
virtual bool isAffectedBySystematic(const CP::SystematicVariation &) const override
Declare the interface that this class provides.
std::map< std::string, std::function< double(float)> > m_efficiencies
SimpleMuonTriggerScaleFactors(const std::string &name, const std::map< std::string, std::function< double(float)> > &efficiencies={})
virtual CP::SystematicSet recommendedSystematics() const override
the list of all systematics this tool recommends to use
virtual CP::CorrectionCode getTriggerEfficiency(const xAOD::Muon &muon, Double_t &efficiency, const std::string &trig, Bool_t) const override
virtual int getBinNumber(const xAOD::Muon &, const std::string &) const override
virtual bool isTriggerSupported(const std::string &) const override
Returns whether the trigger is supported in the current data-period.
virtual CP::SystematicSet affectingSystematics() const override
the list of all systematics this tool can be affected by
virtual CP::CorrectionCode applyEfficiencyScaleFactor(xAOD::Egamma &) const override
Decorate the photon with its scale factor.
virtual bool isAffectedBySystematic(const CP::SystematicVariation &) const override
Declare the interface that this class provides.
virtual CP::CorrectionCode getEfficiencyScaleFactor(const xAOD::Egamma &photon, double &efficiencyScaleFactor) const override
Get the "photon scale factor" as a return value.
virtual CP::SystematicSet recommendedSystematics() const override
the list of all systematics this tool recommends to use
virtual CP::CorrectionCode getEfficiencyScaleFactorError(const xAOD::Egamma &, double &) const override
Get the "photon scale factor error" as a return value.
virtual StatusCode applySystematicVariation(const CP::SystematicSet &) override
effects: configure this tool for the given list of systematic variations.
SimplePhotonEfficiencyCorrectionTool(const std::string &name, double eff=0.8)
SimplePhotonEfficiencyCorrectionTool(const std::string &name, const std::function< double(float)> &func)
a modified tool handle that allows its owner to configure new tools from the C++ side
Base class for the dual-use tool implementation classes.
Definition AsgTool.h:47
AsgTool(const std::string &name)
Constructor specifying the tool instance's name.
Definition AsgTool.cxx:58
STL class.
A relatively simple transient store for objects created in analysis.
Definition TStore.h:45
double ptmax
void efficiency(std::vector< double > &bins, std::vector< double > &values, const std::vector< std::string > &files, const std::string &histname, const std::string &tplotname, const std::string &label="")
int main()
Definition hello.cxx:18
Definition index.py:1
STL namespace.
PhotonAuxContainer_v3 PhotonAuxContainer
Definition of the current photon auxiliary container.
StatusCode Init(const char *appname)
Function initialising ROOT/PyROOT for using the ATLAS EDM.
Definition Init.cxx:31
PhotonContainer_v1 PhotonContainer
Definition of the current "photon container version".
ElectronContainer_v1 ElectronContainer
Definition of the current "electron container version".
Egamma_v1 Egamma
Definition of the current "egamma version".
Definition Egamma.h:17
Muon_v1 Muon
Reference the current persistent version:
Photon_v1 Photon
Definition of the current "egamma version".
MuonAuxContainer_v5 MuonAuxContainer
Definition of the current Muon auxiliary container.
ElectronAuxContainer_v3 ElectronAuxContainer
Definition of the current electron auxiliary container.
MuonContainer_v1 MuonContainer
Definition of the current "Muon container version".
Electron_v1 Electron
Definition of the current "egamma version".
void updateFlavours(const std::string &leg)
Config(const char *name)
Config & setLeptonPDF(unsigned nmin, unsigned nmax, std::initializer_list< float > ptvalues)
Config & setEfficiency(const std::string &leg, std::function< double(float)> &&eff)
Config & setExpectedEfficiency(double eff, double tolerance)
Config & setEventSelection(const decltype(eventSelection)&sel)
std::map< std::string, std::function< double(float)> > efficiencies
std::function< bool(const std::vector< const xAOD::Electron * > &, const std::vector< const xAOD::Muon * > &, const std::vector< const xAOD::Photon * > &)> eventSelection
std::vector< float > leptonPtValues
Config & setTriggers(const std::string &t)
Config & setEfficiency(const std::string &leg, double eff)
Config & setUnavailable(const std::string &leg)
#define MSGSOURCE
Test code to test ElectronPhotonVariableCorrectionTool Dictionaries.