ATLAS Offline Software
Calculator.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 // contact: jmaurer@cern.ch
6 
11 
12 #include <random>
13 #include <iterator>
14 
15 using namespace TrigGlobEffCorr;
16 using std::placeholders::_1;
17 using std::placeholders::_2;
18 using std::placeholders::_3;
19 using std::placeholders::_4;
20 
22  asg::AsgMessaging(&parent),
23  m_parent(&parent)
24 {
25  msg().setLevel(parent.msg().level());
26  m_periods.reserve(nPeriodsToReserve);
27 }
28 
29 bool Calculator::addPeriod(ImportData& data, const std::pair<unsigned,unsigned>& boundaries, const std::string& combination,
30  bool useToys, std::size_t& uniqueElectronLeg, std::size_t& uniquePhotonLeg)
31 {
32  bool success = true;
33  m_parent = data.getParent();
34 
35  auto triggers = data.parseTriggerString(combination, success);
36  if(!success) return false;
37  if(!triggers.size())
38  {
39  ATH_MSG_ERROR("The trigger combination is empty!");
40  return false;
41  }
42 
43  if(!findUniqueLeg(xAOD::Type::Electron, uniqueElectronLeg, triggers)) return false;
44  if(!findUniqueLeg(xAOD::Type::Photon, uniquePhotonLeg, triggers)) return false;
45 
48  if(helper.duplicates())
49  {
50  ATH_MSG_ERROR("The following combination of triggers contains duplicates: " << combination);
51  return false;
52  }
53  if(!useToys)
54  {
55  success = helper.findAndBindFunction();
56  if(!helper.m_formula)
57  {
58  ATH_MSG_ERROR("This trigger combination is currently not supported with an explicit formula (you may use toys instead, slower): " << combination);
59  return false;
60  }
61  }
62  else
63  {
64  helper.m_formula = std::bind(&Calculator::globalEfficiency_Toys, ::_1, ::_2, ::_3, triggers, ::_4);
65  }
66  if(success)
67  {
68  if(data.adaptTriggerListForTriggerMatching(triggers))
69  {
70  m_periods.emplace_back(boundaries, std::move(helper.m_formula), std::move(triggers));
71  }
72  else
73  {
74  if(m_parent->m_validTrigMatchTool) return false;
75  m_periods.emplace_back(boundaries, std::move(helper.m_formula));
76  }
77  }
78  else
79  {
80  ATH_MSG_ERROR("Unspecified error occurred while trying to find the formula for the trigger combination " << combination);
81  }
82  return success;
83 }
84 
85 bool Calculator::findUniqueLeg(xAOD::Type::ObjectType obj, std::size_t& uniqueLeg, const std::vector<TrigDef>& defs)
86 {
87  if(uniqueLeg) return true;
88  for(auto& def : defs)
89  {
90  TriggerProperties tp(def);
91  for(auto itr=tp.cbegin(obj);itr!=tp.cend(obj);++itr)
92  {
93  if(uniqueLeg && uniqueLeg!=*itr)
94  {
95  ATH_MSG_ERROR("The property 'ListOfLegsPerTool' needs to be filled as the specified trigger combination involves several electron (or photon) trigger legs");
96  return false;
97  }
98  uniqueLeg = *itr;
99  }
100  }
101  return true;
102 }
103 
105 {
106  auto period = std::find_if(m_periods.cbegin(), m_periods.cend(),
107  [=](const Period& p) { return runNumber>=p.m_boundaries.first && runNumber<=p.m_boundaries.second; });
108  if(period == m_periods.end())
109  {
110  ATH_MSG_ERROR("No trigger combination has been specified for run " << runNumber);
111  return nullptr;
112  }
113  return &*period;
114 }
115 
117 {
118  m_parent = &parent;
119  m_forceUnitSF = false;
120  auto period = getPeriod(runNumber);
121  if(!period) return false;
122  m_cachedEfficiencies.clear();
123  bool success = period->m_formula && period->m_formula(this, leptons, runNumber, efficiencies);
124  if (m_forceUnitSF)
125  {
126  efficiencies.data() = 1.;
127  efficiencies.mc() = 1.;
128  success = true;
129  }
130  return success;
131 }
132 
134 {
135  matched = false;
136  m_parent = &parent;
137  auto period = getPeriod(runNumber);
138  if(!period) return false;
139  if(!period->m_triggers.size())
140  {
141  ATH_MSG_ERROR("Empty list of triggers for run number " << runNumber);
142  return false;
143  }
144  auto& trigMatchTool = m_parent->m_trigMatchTool;
145 
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)
150  {
151  if(!fillListOfLegsFor(leptons[i], period->m_triggers, validLegs[i])) return false;
152  }
153 
155  std::vector<flat_set<std::size_t> > firedLegs;
156  std::vector<const xAOD::IParticle*> trigLeptons;
157  const std::size_t magicWordHLT = 0xf7b8b87ef2917d66;
158 
159  for(auto& trig : period->m_triggers)
160  {
162  auto itr = m_parent->m_dictionary.find(trig.name ^ magicWordHLT);
163  if(itr == m_parent->m_dictionary.end())
164  {
165  itr = m_parent->m_dictionary.emplace(trig.name ^ magicWordHLT, "HLT_" + m_parent->m_dictionary.at(trig.name)).first;
166  }
167  const std::string& chain = itr->second;
168 
169  unsigned nLegs = 0;
170  if(trig.type & TT_SINGLELEPTON_FLAG) nLegs = 1;
171  else if(trig.type & TT_DILEPTON_FLAG) nLegs = 2;
172  else if(trig.type & TT_TRILEPTON_FLAG) nLegs = 3;
173  else
174  {
175  ATH_MSG_ERROR("Unsupported trigger (type = " << std::hex << trig.type << std::dec << ") " << chain );
176  return false;
177  }
178  firedLegs.resize(nLegs);
179  trigLeptons.resize(nLegs);
180  for(unsigned i0=0;i0<nLep;++i0)
181  {
182  firedLegs[0].swap(validLegs[i0]);
183  trigLeptons[0] = leptons[i0].particle();
184  if(nLegs == 1)
185  {
186  if(canTriggerBeFired(trig, firedLegs)
187  && trigMatchTool->match(trigLeptons, chain)) return (matched = true);
188  }
189  else for(unsigned i1=i0+1;i1<nLep;++i1)
190  {
191  firedLegs[1].swap(validLegs[i1]);
192  trigLeptons[1] = leptons[i1].particle();
193  if(nLegs == 2)
194  {
195  if(canTriggerBeFired(trig, firedLegs)
196  && trigMatchTool->match(trigLeptons, chain)) return (matched = true);
197  }
198  else for(unsigned i2=i1+1;i2<nLep;++i2)
199  {
200  firedLegs[2].swap(validLegs[i2]);
201  trigLeptons[2] = leptons[i2].particle();
202  if(canTriggerBeFired(trig, firedLegs)
203  && trigMatchTool->match(trigLeptons, chain)) return (matched = true);
204  firedLegs[2].swap(validLegs[i2]);
205  }
206  firedLegs[1].swap(validLegs[i1]);
207  }
208  firedLegs[0].swap(validLegs[i0]);
209  }
210  }
211  return true;
212 }
213 
215 {
216  triggers.clear();
217  m_parent = &parent;
218  auto period = getPeriod(runNumber);
219  if(!period) return false;
220  if(!period->m_triggers.size())
221  {
222  ATH_MSG_ERROR("Empty list of triggers for run number " << runNumber << " (was there a configuration issue? please check for warnings during initialization)");
223  return false;
224  }
225  bool success = true;
226  auto notfound = parent.m_dictionary.end();
227  for(auto& trig : period->m_triggers)
228  {
229  auto itr = parent.m_dictionary.find(trig.name);
230  if(itr == notfound)
231  {
232  ATH_MSG_ERROR("can't retrieve name of trigger with hash " << trig.name << " (shouldn't happen; contact tool developers!)");
233  success = false;
234  }
235  else triggers.push_back(itr->second);
236  }
237  if(!success) triggers.clear();
238  return success;
239 }
240 
241 Efficiencies Calculator::getCachedTriggerLegEfficiencies(const Lepton& lepton, unsigned runNumber, std::size_t leg, bool& success)
242 {
243  auto insertion = m_cachedEfficiencies.emplace(std::make_pair(&lepton, leg), Efficiencies());
244  Efficiencies& efficiencies = insertion.first->second;
245  if(insertion.second)
246  {
248  switch(lepton.type())
249  {
252  break;
253  case xAOD::Type::Muon:
255  break;
256  case xAOD::Type::Photon:
258  break;
259  default: ATH_MSG_ERROR("Unsupported particle type");
260  }
261  switch (res)
262  {
264  break;
266  m_forceUnitSF = true;
267  break;
269  [[fallthrough]];
270  default:
271  success = false;
272  efficiencies.data() = -777.;
273  efficiencies.mc() = -777.;
274  }
275  }
276  if(efficiencies.mc()==-777. && !m_forceUnitSF) success = false;
277  return efficiencies;
278 }
279 
283 template<typename Trig1L>
284 auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber, const Trig1L trig, Efficiencies& globalEfficiencies)
285  -> std::enable_if_t<Trig1L::is1L(), bool>
286 {
287  ATH_MSG_DEBUG("Entered Calculator::globalEfficiency_One1L() at line " << __LINE__);
288  if(!trig)
289  {
290  globalEfficiencies = {0.};
291  return true;
292  }
293  globalEfficiencies = {1.};
294  bool success = true;
295  for(auto& lepton : leptons)
296  {
297  if(trig.irrelevantFor(lepton) || !aboveThreshold(lepton, trig())) continue;
298  auto efficiencies = getCachedTriggerLegEfficiencies(lepton, runNumber, trig(), success);
299  globalEfficiencies *= ~efficiencies;
300  }
301  globalEfficiencies = ~globalEfficiencies;
302  return success;
303 }
304 
308 template<typename Trig1L_obj1, typename Trig1L_obj2>
309 auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber, const Trig1L_obj1 trig1, const Trig1L_obj2 trig2, Efficiencies& globalEfficiencies)
310  -> std::enable_if_t<Trig1L_obj1::is1L()
311  && Trig1L_obj2::is1L()
313  bool>
314 {
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.};
319  bool success = true;
320  for(auto& lepton : leptons)
321  {
322  std::size_t leg;
323  if(trig1.relevantFor(lepton)) leg = trig1();
324  else if(trig2.relevantFor(lepton)) leg = trig2();
325  else continue;
326  if(!aboveThreshold(lepton, leg)) continue;
327  auto efficiencies = getCachedTriggerLegEfficiencies(lepton, runNumber, leg, success);
328  globalEfficiencies *= ~efficiencies;
329  }
330  globalEfficiencies = ~globalEfficiencies;
331  return success;
332 }
333 
337 template<typename Trig1L>
338 auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber, const flat_set<Trig1L>& trigs, Efficiencies& globalEfficiencies)
339  -> std::enable_if_t<Trig1L::is1L(), bool>
340 {
341  ATH_MSG_DEBUG("Entered Calculator::globalEfficiency_Several1L() at line " << __LINE__);
342  if(trigs.size() == 1) return globalEfficiency(leptons, runNumber, *trigs.cbegin(), globalEfficiencies);
343  if(!trigs.size())
344  {
345  globalEfficiencies = {0.};
346  return true;
347  }
348  globalEfficiencies = {1.};
349  bool success = true;
350  for(auto& lepton : leptons)
351  {
352  if(Trig1L::irrelevantFor(lepton)) continue;
353  std::size_t loosestLeg = getLoosestLegAboveThreshold(lepton, trigs, success);
354  if(loosestLeg && success)
355  {
356  auto efficiencies = getCachedTriggerLegEfficiencies(lepton, runNumber, loosestLeg, success);
357  globalEfficiencies *= ~efficiencies;
358  }
359  }
360  globalEfficiencies = ~globalEfficiencies;
361  return success;
362 }
363 
367 template<typename Trig1L_obj1, typename Trig1L_obj2>
368 auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber,
369  const flat_set<Trig1L_obj1>& trigs1, const flat_set<Trig1L_obj2>& trigs2, Efficiencies& globalEfficiencies)
370  -> std::enable_if_t<Trig1L_obj1::is1L()
371  && Trig1L_obj2::is1L()
373  bool>
374 {
375  ATH_MSG_DEBUG("Entered Calculator::globalEfficiency_Several1L() at line " << __LINE__);
376  if(trigs1.size()==1 && trigs2.size()==1)
377  {
378  return globalEfficiency(leptons, runNumber, *trigs1.cbegin(), *trigs2.cbegin(), globalEfficiencies);
379  }
380  if(!trigs1.size()) return globalEfficiency(leptons, runNumber, trigs2, globalEfficiencies);
381  if(!trigs2.size()) return globalEfficiency(leptons, runNumber, trigs1, globalEfficiencies);
382  globalEfficiencies = {1.};
383  bool success = true;
384  for(auto& lepton : leptons)
385  {
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);
389  else continue;
390  if(loosestLeg && success)
391  {
392  auto efficiencies = getCachedTriggerLegEfficiencies(lepton, runNumber, loosestLeg, success);
393  globalEfficiencies *= ~efficiencies;
394  }
395  }
396  globalEfficiencies = ~globalEfficiencies;
397  return success;
398 }
399 
403 template<typename Trig2Lmix>
404 auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber, const Trig2Lmix trig, Efficiencies& globalEfficiencies)
405  -> std::enable_if_t<Trig2Lmix::is2Lmix(), bool>
406 {
407  ATH_MSG_DEBUG("Entered Calculator::globalEfficiency_One2L() at line " << __LINE__);
409  bool success = globalEfficiency(leptons, runNumber, trig.side1(), efficiencies[0])
410  && globalEfficiency(leptons, runNumber, trig.side2(), efficiencies[1]);
411  if(success) globalEfficiencies = efficiencies[0] * efficiencies[1];
412  else globalEfficiencies = {0.};
413  return success;
414 }
415 
419 template<typename Trig2Lsym>
420 auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber, const Trig2Lsym trig , Efficiencies& globalEfficiencies)
421  -> std::enable_if_t<Trig2Lsym::is2Lsym(), bool>
422 {
423  ATH_MSG_DEBUG("Entered Calculator::globalEfficiency_One2L() at line " << __LINE__);
424  globalEfficiencies = {0.};
425  if(!trig) return true;
426  Efficiencies singleInefficiencies(1.);
427  bool success = true;
428  for(auto& lepton : leptons)
429  {
430  if(trig.irrelevantFor(lepton) || !aboveThreshold(lepton, trig())) continue;
431  auto efficiencies = getCachedTriggerLegEfficiencies(lepton, runNumber, trig(), success);
432  globalEfficiencies = ~efficiencies*globalEfficiencies + efficiencies*~singleInefficiencies;
433  singleInefficiencies *= ~efficiencies;
434  }
435  return success;
436 }
437 
441 template<typename Trig2Lasym>
442 auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber, const Trig2Lasym trig, Efficiencies& globalEfficiencies)
443  -> std::enable_if_t<Trig2Lasym::is2Lasym(), bool>
444 {
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.};
450  bool success = true;
451  for(auto& lepton : leptons)
452  {
453  if(trig.irrelevantFor(lepton)) continue;
454  Efficiencies efficiencies[2] = {{0.}, {0.}};
455  int loosest = 0;
456  if(aboveThreshold(lepton, trig(0)))
457  {
458  efficiencies[0] = getCachedTriggerLegEfficiencies(lepton, runNumber, trig(0), success);
459  if(aboveThreshold(lepton, trig(1)))
460  {
461  efficiencies[1] = getCachedTriggerLegEfficiencies(lepton, runNumber, trig(1), success);
462  loosest = m_parent->getLoosestLeg(lepton, trig(0), trig(1), success)==trig(1);
463  }
464  }
465  else if(aboveThreshold(lepton, trig(1)))
466  {
467  efficiencies[1] = getCachedTriggerLegEfficiencies(lepton, runNumber, trig(1), success);
468  loosest = 1;
469  }
470  else continue;
471  const int tightest = 1 - loosest;
472  globalEfficiencies = ~efficiencies[loosest]*globalEfficiencies
473  + (efficiencies[loosest]-efficiencies[tightest])*~singleInefficiencies[tightest]
474  + efficiencies[tightest]*~twoSingleInefficiencies;
475  twoSingleInefficiencies *= ~efficiencies[loosest];
476  for(int i=0;i<2;++i) singleInefficiencies[i] *= ~efficiencies[i];
477  }
478  return success;
479 }
480 
484 template<typename Trig2Lmix, typename Trig1L_obj1, typename Trig1L_obj2>
485 auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber,
486  const Trig2Lmix trig2Lmix, const flat_set<Trig1L_obj1>& trigs1L1, const flat_set<Trig1L_obj2>& trigs1L2, Efficiencies& globalEfficiencies)
487  -> std::enable_if_t<Trig2Lmix::is2Lmix()
488  && Trig1L_obj1::is1L() && Trig2Lmix::object1()==Trig1L_obj1::object()
489  && Trig1L_obj2::is1L() && Trig2Lmix::object2()==Trig1L_obj2::object(),
490  bool>
491 {
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);
498  bool success = globalEfficiency(leptons, runNumber, trigs1L1, efficiencies[0])
499  && globalEfficiency(leptons, runNumber, trigs1L2, efficiencies[1])
500  && globalEfficiency(leptons, runNumber, trig2Lmix.addTo(trigs1L1), efficiencies[2])
501  && globalEfficiency(leptons, runNumber, trig2Lmix.addTo(trigs1L2), efficiencies[3]);
502  if(success)
503  {
504  globalEfficiencies = Efficiencies(1.) - ~efficiencies[0]*~efficiencies[1]
506  }
507  else globalEfficiencies = {0.};
508  return success;
509 }
510 
514 template<typename Trig2L, typename Trig1L>
515 inline auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber,
516  const Trig2L trig2L, const Trig1L trig1L, Efficiencies& globalEfficiencies)
517  -> std::enable_if_t<Trig2L::is2Lnomix()
518  && Trig1L::is1L()
520  bool>
521 {
522  ATH_MSG_DEBUG("Entered Calculator::globalEfficiency_One2LSeveral1L() at line " << __LINE__);
523  return globalEfficiency(leptons, runNumber, trig2L, flat_set<Trig1L>{trig1L}, globalEfficiencies);
524 }
525 
529 template<typename Trig2Lsym, typename Trig1L>
530 auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber,
531  const Trig2Lsym trig2L, const flat_set<Trig1L>& trigs1L, Efficiencies& globalEfficiencies)
532  -> std::enable_if_t<Trig2Lsym::is2Lsym()
533  && Trig1L::is1L()
535  bool>
536 {
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.};
541  Efficiencies twoSingleInefficiencies = {1.};
542  bool success = true;
543  for(auto& lepton : leptons)
544  {
545  if(trig2L.irrelevantFor(lepton)) continue;
546  Efficiencies efficiencies1L(0.), efficiencies2L(0.);
547  const Efficiencies* loosestLegEfficiency;
548  std::size_t loosest1lepLeg = getLoosestLegAboveThreshold(lepton, trigs1L, success);
549  if(loosest1lepLeg)
550  {
551  efficiencies1L = getCachedTriggerLegEfficiencies(lepton, runNumber, loosest1lepLeg, success);
552  if(aboveThreshold(lepton, trig2L()))
553  {
554  efficiencies2L = getCachedTriggerLegEfficiencies(lepton, runNumber, trig2L(), success);
555  loosestLegEfficiency = (m_parent->getLoosestLeg(lepton, trig2L(), loosest1lepLeg , success)==trig2L())? &efficiencies2L : &efficiencies1L;
556  }
557  else loosestLegEfficiency = &efficiencies1L;
558  }
559  else if(aboveThreshold(lepton, trig2L()))
560  {
561  efficiencies2L = getCachedTriggerLegEfficiencies(lepton, runNumber, trig2L(), success);
562  loosestLegEfficiency = &efficiencies2L;
563  }
564  else continue;
565  globalEfficiencies = ~(*loosestLegEfficiency)*globalEfficiencies + efficiencies1L;
566  if(loosestLegEfficiency==&efficiencies2L) globalEfficiencies += ~twoSingleInefficiencies*(efficiencies2L - efficiencies1L);
567  twoSingleInefficiencies *= ~(*loosestLegEfficiency);
568  }
569  return success;
570 }
571 
575 template<typename Trig2Lasym, typename Trig1L>
576 auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber,
577  const Trig2Lasym trig2L, const flat_set<Trig1L>& trigs1L, Efficiencies& globalEfficiencies)
578  -> std::enable_if_t<Trig2Lasym::is2Lasym()
579  && Trig1L::is1L()
581  bool>
582 {
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.};
589  bool success = true;
590  for(auto& lepton : leptons)
591  {
592  if(trig2L.irrelevantFor(lepton)) continue;
593  flat_set<std::size_t> validLegs;
594  for(std::size_t leg : trig2L.legs) if(aboveThreshold(lepton, leg)) validLegs.insert(leg);
595  Efficiencies efficiencies1L = {0.};
596  std::size_t loosest1lepLeg = getLoosestLegAboveThreshold(lepton, trigs1L, success);
597  if(loosest1lepLeg)
598  {
599  efficiencies1L = getCachedTriggerLegEfficiencies(lepton, runNumber, loosest1lepLeg, success);
600  validLegs.insert(loosest1lepLeg);
601  }
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);
605  Efficiencies efficienciesMedium = {0.};
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)
610  {
611  globalEfficiencies += (efficienciesLoose-efficienciesMedium)*~twoSingleInefficiencies[looseLegs.first==trig2L.legs[0]];
612  if(loosest1lepLeg!=looseLegs.second) globalEfficiencies += (efficienciesMedium-efficiencies1L)*~threeSingleInefficiencies;
613  }
614  threeSingleInefficiencies *= ~efficienciesLoose;
615  twoSingleInefficiencies[0] *= (looseLegs.first!=trig2L.legs[1])?~efficienciesLoose:~efficienciesMedium;
616  twoSingleInefficiencies[1] *= (looseLegs.first!=trig2L.legs[0])?~efficienciesLoose:~efficienciesMedium;
617  }
618  return success;
619 }
620 
624 template<typename Trig2Lsym, typename Trig1L>
625 auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber,
626  const Trig2Lsym trig2L1, const Trig2Lsym trig2L2, const flat_set<Trig1L>& trigs1L, Efficiencies& globalEfficiencies)
627  -> std::enable_if_t<Trig2Lsym::is2Lsym()
628  && Trig1L::is1L()
630  bool>
631 {
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.};
636  Efficiencies singleInefficiencies{1.};
637  Efficiencies efficiencies2Lsym[2] = {{0.},{0.}};
638 
639  bool success = true;
640  for(auto& lepton : leptons)
641  {
642  if(trig2L1.irrelevantFor(lepton)) continue;
643  flat_set<std::size_t> validLegs;
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()})
647  {
648  if(leg && aboveThreshold(lepton, leg))
649  {
650  validLegs.insert(leg);
651  efficiencies.emplace(leg, getCachedTriggerLegEfficiencies(lepton, runNumber, leg, success));
652  }
653  else efficiencies.emplace(leg, 0.);
654  }
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;
659  globalEfficiencies = globalEfficiencies*~efficiencies[looseLegs.first] + efficiencies[loosest1lepLeg];
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]);
663  efficiencies2Lsym[0] = ~efficiencies[looseLegs.first]*efficiencies2Lsym[0] + efficiencies[lambda23];
664  efficiencies2Lsym[1] = ~efficiencies[looseLegs.first]*efficiencies2Lsym[1] + efficiencies[lambda13];
665  if(looseLegs.first==trig2L1()) efficiencies2Lsym[0] += (efficiencies[trig2L1()]-efficiencies[lambda23])*~singleInefficiencies;
666  if(looseLegs.first==trig2L2()) efficiencies2Lsym[1] += (efficiencies[trig2L2()]-efficiencies[lambda13])*~singleInefficiencies;
667  singleInefficiencies *= ~efficiencies[looseLegs.first];
668  }
669  return success;
670 }
671 
675 template<typename Trig2Lasym, typename Trig2Lsym, typename Trig1L>
676 auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber,
677  const Trig2Lasym trig2Lasym, const Trig2Lsym trig2Lsym, const flat_set<Trig1L>& trigs1L, Efficiencies& globalEfficiencies)
678  -> std::enable_if_t<Trig2Lasym::is2Lasym()
679  && Trig2Lsym::is2Lsym() && Trig2Lsym::object()==Trig2Lasym::object()
680  && Trig1L::is1L() && Trig1L::object()==Trig2Lasym::object(),
681  bool>
682 {
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())
687  {
688  ATH_MSG_ERROR("implementation -- does this function work properly when the two 2L triggers have one leg in common? Must be checked");
689  return false;
690  }
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.}};
695 
696  bool success = true;
697  for(auto& lepton : leptons)
698  {
699  if(trig2Lasym.irrelevantFor(lepton)) continue;
700  flat_set<std::size_t> validLegs;
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})
704  {
705  if(leg && aboveThreshold(lepton, leg))
706  {
707  validLegs.insert(leg);
708  efficiencies.emplace(leg, getCachedTriggerLegEfficiencies(lepton, runNumber, leg, success));
709  }
710  else efficiencies.emplace(leg, 0.);
711  }
712  if(!validLegs.size()) continue;
713 
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);
739 
741  globalEfficiencies = globalEfficiencies*~efficiencies[loosestLeg] + efficiencies[loosest1lepLeg]
742  + (efficiencies[tau13] - efficiencies[secondTightestLeg])*~singleInefficiencies[0]
743  + (efficiencies[tau12] - efficiencies[secondTightestLeg])*~singleInefficiencies[1]
744  + (efficiencies[tau23] - efficiencies[secondTightestLeg])*efficiencies2Lsym[2];
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)
749  globalEfficiencies += (efficiencies[secondTightestLeg]-efficiencies[tightestLeg])*~singleInefficiencies[2];
750 
751  efficiencies2Lasym = ~efficiencies[loosestLeg]*efficiencies2Lasym + efficiencies[lambda14];
752  if(loosestLeg==trig2Lasym(0) || loosestLeg==trig2Lasym(1))
753  {
755  efficiencies2Lasym += (efficiencies[loosestLeg]-efficiencies[secondLoosestLeg])*~singleInefficiencies[loosestLeg==trig2Lasym(0)]
756  + (efficiencies[secondLoosestLeg]-efficiencies[lambda14])*~singleInefficiencies[2];
757  }
758  efficiencies2Lsym[0] = ~efficiencies[lambda124]*efficiencies2Lsym[0] + efficiencies[lambda24];
759  efficiencies2Lsym[1] = ~efficiencies[lambda134]*efficiencies2Lsym[1] + efficiencies[lambda34];
760  efficiencies2Lsym[2] = ~efficiencies[loosestLeg]*efficiencies2Lsym[2] + efficiencies[lambda234];
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];
764  singleInefficiencies[0] *= ~efficiencies[lambda124];
765  singleInefficiencies[1] *= ~efficiencies[lambda134];
766  singleInefficiencies[2] *= ~efficiencies[loosestLeg];
767  }
768  return success;
769 }
770 
774 template<typename Trig3Lsym>
775 auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber, const Trig3Lsym trig, Efficiencies& globalEfficiencies)
776  -> std::enable_if_t<Trig3Lsym::is3Lsym(), bool>
777 {
778  ATH_MSG_DEBUG("Entered Calculator::globalEfficiency_One3L() at line " << __LINE__);
779  globalEfficiencies = {0.};
780  Efficiencies singleInefficiencies{1.}, efficiencies2L{0.};
781  bool success = true;
782  for(auto& lepton : leptons)
783  {
784  if(trig.irrelevantFor(lepton) || !aboveThreshold(lepton, trig())) continue;
785  auto efficiencies = getCachedTriggerLegEfficiencies(lepton, runNumber, trig(), success);
786  globalEfficiencies = ~efficiencies*globalEfficiencies + efficiencies*efficiencies2L;
787  efficiencies2L = ~efficiencies*efficiencies2L + efficiencies*~singleInefficiencies;
788  singleInefficiencies *= ~efficiencies;
789  }
790  return success;
791 }
792 
796 template<typename Trig3Lhalfsym>
797 auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber, const Trig3Lhalfsym trig, Efficiencies& globalEfficiencies)
798  -> std::enable_if_t<Trig3Lhalfsym::is3Lhalfsym(), bool>
799 {
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.};
805  bool success = true;
806  for(auto& lepton : leptons)
807  {
808  if(trig.irrelevantFor(lepton)) continue;
809  Efficiencies efficiencies[2] = {{0.}, {0.}};
810  const int asym = 0, sym = 1;
811  int loosestLeg;
812  if(aboveThreshold(lepton, trig.asymLeg()))
813  {
814  efficiencies[asym] = getCachedTriggerLegEfficiencies(lepton, runNumber, trig.asymLeg(), success);
815  if(aboveThreshold(lepton, trig.symLeg()))
816  {
817  efficiencies[sym] = getCachedTriggerLegEfficiencies(lepton, runNumber, trig.symLeg(), success);
818  loosestLeg = m_parent->getLoosestLeg(lepton, trig.asymLeg(), trig.symLeg(), success)==trig.asymLeg()? asym : sym;
819  }
820  else loosestLeg = asym;
821  }
822  else if(aboveThreshold(lepton, trig.symLeg()))
823  {
824  efficiencies[sym] = getCachedTriggerLegEfficiencies(lepton, runNumber, trig.symLeg(), success);
825  loosestLeg = sym;
826  }
827  else continue;
828  Efficiencies delta = efficiencies[asym] - efficiencies[sym];
829  if(loosestLeg == asym)
830  {
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];
834  }
835  else
836  {
837  globalEfficiencies = ~efficiencies[sym]*globalEfficiencies + efficiencies[asym]*efficiencies2L2L - delta*efficiencies2Lasym;
838  efficiencies2L2L = ~efficiencies[sym]*efficiencies2L2L + efficiencies[sym]*~twoSingleInefficiencies;
839  efficiencies2Lasym = ~efficiencies[sym]*efficiencies2Lasym + efficiencies[asym]*~twoSingleInefficiencies - delta*~singleInefficiencies[asym];
840  }
841  efficiencies2Lsym = ~efficiencies[sym]*efficiencies2Lsym + efficiencies[sym]*~singleInefficiencies[sym];
842  twoSingleInefficiencies *= ~efficiencies[loosestLeg];
843  singleInefficiencies[sym] *= ~efficiencies[sym];
844  singleInefficiencies[asym] *= ~efficiencies[asym];
845  }
846  return success;
847 }
848 
852 template<typename Trig2L, typename Trig2Lmix>
853 auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber, const Trig2L trig2L, const Trig2Lmix trig2Lmix, Efficiencies& globalEfficiencies)
854  -> std::enable_if_t<Trig2L::is2Lnomix()
855  && Trig2Lmix::is2Lmix()
856  && (Trig2Lmix::object1()==Trig2L::object() || Trig2Lmix::object2()==Trig2L::object()),
857  bool>
858 {
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;
865  return success;
866 }
867 
871 template<typename Trig2L_obj1, typename Trig2L_obj2, typename Trig2Lmix>
872 auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber,
873  const Trig2L_obj1 trig2L_obj1, const Trig2L_obj2 trig2L_obj2, const Trig2Lmix trig2Lmix, Efficiencies& globalEfficiencies)
874  -> std::enable_if_t<Trig2Lmix::is2Lmix()
875  && Trig2L_obj1::is2Lnomix() && Trig2L_obj1::object() == Trig2Lmix::object1()
876  && Trig2L_obj2::is2Lnomix() && Trig2L_obj2::object() == Trig2Lmix::object2(),
877 
878  bool>
879 {
880  ATH_MSG_DEBUG("Entered Calculator::globalEfficiency_Three2L() at line " << __LINE__);
881  Efficiencies efficiencies2L[2] = {{0.}, {0.}}, efficiencies2Lor1L[2] = {{0.}, {0.}};
882  bool success = true;
883  if(trig2L_obj1)
884  {
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];
888  }
889  else if(trig2Lmix) success = success && globalEfficiency(leptons, runNumber, trig2Lmix.template side<Trig2L_obj1>(), efficiencies2Lor1L[0]);
890  if(trig2L_obj2)
891  {
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];
895  }
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];
898  return success;
899 }
900 
904 template<typename Trig2L_obj1, typename Trig2L_obj2, typename Trig2Lmix, typename Trig1L_obj1, typename Trig1L_obj2>
905 auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber, const Trig2L_obj1 trig2L_obj1, const Trig2L_obj2 trig2L_obj2,
906  const Trig2Lmix trig2Lmix, const flat_set<Trig1L_obj1>& trigs1L_obj1, const flat_set<Trig1L_obj2>& trigs1L_obj2, Efficiencies& globalEfficiencies)
907  -> std::enable_if_t<Trig2Lmix::is2Lmix()
908  && Trig2L_obj1::is2Lnomix() && Trig2L_obj1::object()==Trig2Lmix::object1()
909  && Trig2L_obj2::is2Lnomix() && Trig2L_obj2::object()==Trig2Lmix::object2()
910  && Trig1L_obj1::is1L() && Trig1L_obj1::object()==Trig2Lmix::object1()
911  && Trig1L_obj2::is1L() && Trig1L_obj2::object()==Trig2Lmix::object2(),
912 
913  bool>
914 {
915  ATH_MSG_DEBUG("Entered Calculator::globalEfficiency_Three2LSeveral1L() at line " << __LINE__);
917  bool success = true;
918  if(trig2L_obj1) success = success && globalEfficiency(leptons, runNumber, trig2L_obj1, trigs1L_obj1, efficiencies[0]);
919  else success = success && globalEfficiency(leptons, runNumber, trigs1L_obj1, efficiencies[0]);
920  if(trig2L_obj2) success = success && globalEfficiency(leptons, runNumber, trig2L_obj2, trigs1L_obj2, efficiencies[1]);
921  else success = success && globalEfficiency(leptons, runNumber, trigs1L_obj2, efficiencies[1]);
922  if(trig2Lmix && !trig2Lmix.hiddenBy(trigs1L_obj1))
923  {
924  auto t = trig2Lmix.addTo(trigs1L_obj1);
925  if(trig2L_obj1) success = success && globalEfficiency(leptons, runNumber, trig2L_obj1, t, efficiencies[2]);
926  else success = success && globalEfficiency(leptons, runNumber, t, efficiencies[2]);
927  }
928  else efficiencies[2] = efficiencies[0];
929  if(trig2Lmix && !trig2Lmix.hiddenBy(trigs1L_obj2))
930  {
931  auto t = trig2Lmix.addTo(trigs1L_obj2);
932  if(trig2L_obj2) success = success && globalEfficiency(leptons, runNumber, trig2L_obj2, t, efficiencies[3]);
933  else success = success && globalEfficiency(leptons, runNumber, t, efficiencies[3]);
934  }
935  else efficiencies[3] = efficiencies[1];
936  globalEfficiencies = Efficiencies(1.) - ~efficiencies[0]*~efficiencies[1] + (efficiencies[2]-efficiencies[0])*(efficiencies[3]-efficiencies[1]);
937  return success;
938 }
939 
943 template<typename Trig2L_obj1, typename Trig2Lsym_obj1, typename Trig2L_obj2, typename Trig2Lsym_obj2,
944  typename Trig2Lmix, typename Trig1L_obj1, typename Trig1L_obj2>
945 auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber,
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,
948  const flat_set<Trig1L_obj1>& trigs1L_obj1, const flat_set<Trig1L_obj2>& trigs1L_obj2, Efficiencies& globalEfficiencies)
949  -> std::enable_if_t<Trig2Lmix::is2Lmix()
950  && Trig2L_obj1::is2Lnomix() && Trig2L_obj1::object()==Trig2Lmix::object1()
951  && Trig2L_obj2::is2Lnomix() && Trig2L_obj2::object()==Trig2Lmix::object2()
952  && Trig2Lsym_obj1::is2Lsym() && Trig2Lsym_obj1::object()==Trig2Lmix::object1()
953  && Trig2Lsym_obj2::is2Lsym() && Trig2Lsym_obj2::object()==Trig2Lmix::object2()
954  && Trig1L_obj1::is1L() && Trig1L_obj1::object()==Trig2Lmix::object1()
955  && Trig1L_obj2::is1L() && Trig1L_obj2::object()==Trig2Lmix::object2(),
956  bool>
957 {
958  ATH_MSG_DEBUG("Entered Calculator::globalEfficiency_Six2LSeveral1L() at line " << __LINE__);
959 
960  auto singleObjectFactor = [=](auto trig2L, auto trig2Lsym, auto& trigs1L, Efficiencies (&efficiencies)[4]) -> bool
961  {
962  auto eval_for = [=](const auto& trigs1L_extended, Efficiencies& eff) -> bool
963  {
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);
968  };
969 
970  bool success = eval_for(trigs1L, efficiencies[0]);
971  if(trig2Lmix1) success = success && eval_for(trig2Lmix1.addTo(trigs1L), efficiencies[1]);
972  else efficiencies[1] = efficiencies[0];
973  if(trig2Lmix2)
974  {
975  auto t = trig2Lmix2.addTo(trigs1L);
976  success = success && eval_for(t, efficiencies[2]);
977  if(trig2Lmix1) success && eval_for(trig2Lmix1.addTo(t), efficiencies[3]);
978  else efficiencies[3] = efficiencies[2];
979  }
980  else
981  {
982  efficiencies[2] = efficiencies[0];
983  efficiencies[3] = efficiencies[1];
984  }
985  return success;
986  };
987 
988  Efficiencies efficiencies1[4], efficiencies2[4];
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]);
994  return success;
995 }
996 
1000 template<typename Trig3Lmix>
1001 auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber, const Trig3Lmix trig, Efficiencies& globalEfficiencies)
1002  -> std::enable_if_t<Trig3Lmix::is3Lmix(), bool>
1003 {
1004  ATH_MSG_DEBUG("Entered Calculator::globalEfficiency_One3L() at line " << __LINE__);
1005  Efficiencies efficiencies[2] = {{0.}, {0.}};
1006  bool success = globalEfficiency(leptons, runNumber, trig.template side<Trig3Lmix::object1()>(), efficiencies[0])
1007  && globalEfficiency(leptons, runNumber, trig.template side<Trig3Lmix::object2()>(), efficiencies[1]);
1008  globalEfficiencies = efficiencies[0]*efficiencies[1];
1009  return success;
1010 }
1011 
1015 template<typename Trig3Lmix1, typename Trig3Lmix2>
1016 auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber, const Trig3Lmix1 trig1, const Trig3Lmix2 trig2, Efficiencies& globalEfficiencies)
1017  -> std::enable_if_t<Trig3Lmix1::is3Lmix()
1018  && Trig3Lmix2::is3Lmix()
1019  && Trig3Lmix1::object1() == Trig3Lmix2::object2()
1020  && Trig3Lmix1::object2() == Trig3Lmix2::object1(),
1021  bool>
1022 {
1023  ATH_MSG_DEBUG("Entered Calculator::globalEfficiency_Two3L() at line " << __LINE__);
1024  Efficiencies efficiencies[6] = {{0.}, {0.}, {0.}, {0.}, {0.}, {0.}};
1025  auto trig2La = trig1.template side<Trig3Lmix1::object1()>();
1026  auto trig1La = trig2.template side<Trig3Lmix2::object2()>();
1027  bool success = globalEfficiency(leptons, runNumber, trig1La, efficiencies[0])
1028  && globalEfficiency(leptons, runNumber, trig2La, efficiencies[1]);
1029  if(!trig2La.hiddenBy(trig1La)) success = success && globalEfficiency(leptons, runNumber, trig2La, trig1La, efficiencies[2]);
1030  else efficiencies[2] = efficiencies[0];
1031  auto trig2Lb = trig2.template side<Trig3Lmix2::object1()>();
1032  auto trig1Lb = trig1.template side<Trig3Lmix1::object2()>();
1033  success = success && globalEfficiency(leptons, runNumber, trig1Lb, efficiencies[3])
1034  && globalEfficiency(leptons, runNumber, trig2Lb, efficiencies[4]);
1035  if(!trig2Lb.hiddenBy(trig1Lb)) success = success && globalEfficiency(leptons, runNumber, trig2Lb, trig1Lb, efficiencies[5]);
1036  else efficiencies[5] = efficiencies[3];
1037  globalEfficiencies = efficiencies[0]*efficiencies[4] + efficiencies[3]*efficiencies[1]
1039  return success;
1040 }
1041 
1045 template<typename Trig4Lsym>
1046 auto Calculator::globalEfficiency(const LeptonList& leptons, unsigned runNumber, const Trig4Lsym trig, Efficiencies& globalEfficiencies)
1047  -> std::enable_if_t<Trig4Lsym::is4Lsym(), bool>
1048 {
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)
1054  {
1055  if(trig.irrelevantFor(lepton) || !aboveThreshold(lepton, trig())) continue;
1056  auto efficiencies = getCachedTriggerLegEfficiencies(lepton, runNumber, trig(), success);
1057  globalEfficiencies = ~efficiencies*globalEfficiencies + efficiencies*efficiencies3L;
1058  efficiencies3L = ~efficiencies*efficiencies3L + efficiencies*efficiencies2L;
1059  efficiencies2L = ~efficiencies*efficiencies2L + efficiencies*~singleInefficiencies;
1060  singleInefficiencies *= ~efficiencies;
1061  }
1062  return success;
1063 }
1064 
1065 bool Calculator::globalEfficiency_Factorized2(const LeptonList& leptons, unsigned runNumber, GlobEffFunc func1, GlobEffFunc func2, Efficiencies& globalEfficiencies)
1066 {
1068  if(!func1(this, leptons, runNumber, efficiencies[0])) return false;
1069  if(!func2(this, leptons, runNumber, efficiencies[1])) return false;
1070  globalEfficiencies = ~(~efficiencies[0] * ~efficiencies[1]);
1071  return true;
1072 }
1073 
1074 bool Calculator::globalEfficiency_Factorized3(const LeptonList& leptons, unsigned runNumber, GlobEffFunc func1, GlobEffFunc func2, GlobEffFunc func3, Efficiencies& globalEfficiencies)
1075 {
1077  if(!func1(this, leptons, runNumber, efficiencies[0])) return false;
1078  if(!func2(this, leptons, runNumber, efficiencies[1])) return false;
1079  if(!func3(this, leptons, runNumber, efficiencies[2])) return false;
1080  globalEfficiencies = ~(~efficiencies[0] * ~efficiencies[1]* ~efficiencies[2]);
1081  return true;
1082 }
1083 
1084 bool Calculator::fillListOfLegsFor(const Lepton& lepton, const std::vector<TrigDef>& triggers, flat_set<std::size_t>& validLegs) const
1085 {
1086  validLegs.clear();
1087  for(auto& trig : triggers)
1088  {
1089  TriggerProperties tp(trig);
1090  if(!tp.valid())
1091  {
1092  ATH_MSG_ERROR("Unrecognized trigger type " << trig.type);
1093  return false;
1094  }
1095  auto end = tp.cend(lepton.type());
1096  for(auto itr=tp.cbegin(lepton.type()); itr!=end; ++itr)if(aboveThreshold(lepton, *itr)) validLegs.emplace(*itr);
1097  }
1098  return true;
1099 }
1100 
1101 bool Calculator::canTriggerBeFired(const TrigDef& trig, const std::vector<flat_set<std::size_t> >& firedLegs) const
1102 {
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)
1108  {
1109  // single-lepton and symmetric multilepton triggers
1110  return std::count_if(
1111  firedLegs.cbegin(),
1112  firedLegs.cend(),
1113  [&](auto& legs) { return legs.count(trig.leg[0]); }) >= nLegs;
1114  }
1115  else if(nLegs == 2)
1116  {
1117  // asymmetric or mixed-flavour dilepton triggers
1118  bool n0 = false, n1 = false;
1119  for(auto& legs : firedLegs)
1120  {
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]);
1125  }
1126  }
1127  else if(nLegs == 3)
1128  {
1129  // other trilepton triggers
1130  auto end = firedLegs.end();
1131  for(auto legs0=firedLegs.begin();legs0!=end;++legs0)
1132  {
1133  for(int i=0;i<3;++i)
1134  {
1135  if(!legs0->count(trig.leg[i])) continue;
1136  for(auto legs1=legs0+1;legs1!=end;++legs1)
1137  {
1138  for(int j=1;j<3;++j)
1139  {
1140  if(!legs1->count(trig.leg[(i+j)%3])) continue;
1141  for(auto legs2=legs1+1;legs2!=end;++legs2)
1142  {
1143  if(legs2->count(trig.leg[(i+3-j)%3])) return true;
1144  }
1145  }
1146  }
1147  }
1148  }
1149  }
1150  else
1151  {
1152  ATH_MSG_ERROR("incomplete support of 4-lepton triggers.");
1153  }
1154  return false;
1155 }
1156 
1158  const std::vector<TrigDef>& triggers, Efficiencies& globalEfficiencies)
1159 {
1160  ATH_MSG_DEBUG("Entered Calculator::globalEfficiency_Toys() at line " << __LINE__);
1161  globalEfficiencies = {0.};
1162  if(m_parent->m_numberOfToys <= 0)
1163  {
1164  ATH_MSG_ERROR("The specified number of toys is <= 0");
1165  return false;
1166  }
1167  std::map<const Lepton*, std::vector<std::pair<std::size_t, Efficiencies> > > leptonEfficiencies;
1168  for(auto& lepton : leptons)
1169  {
1170  flat_set<std::size_t> validLegs;
1171  if(!fillListOfLegsFor(lepton, triggers, validLegs)) return false;
1172  auto& efficiencies = leptonEfficiencies[&lepton];
1173  const int nLegs = validLegs.size();
1174  if(nLegs)
1175  {
1176  bool success = true;
1177  for(std::size_t leg : m_parent->getSortedLegs(lepton, validLegs, success))
1178  {
1179  efficiencies.emplace_back(leg, getCachedTriggerLegEfficiencies(lepton, runNumber, leg, success));
1180  }
1181  if(!success) return false;
1182  }
1183  }
1184  unsigned long seed;
1186  {
1187  if(!m_parent->retrieveEventNumber(seed))
1188  {
1189  ATH_MSG_WARNING("Will use internal seed instead of event number");
1190  seed = m_parent->m_seed++;
1191  }
1192  }
1193  else seed = m_parent->m_seed++;
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};
1198  for(unsigned long toy=0;toy<m_parent->m_numberOfToys;++toy)
1199  {
1200  for(int step=0;step<2;++step)
1201  {
1202  auto legs = firedLegs.begin();
1203  for(auto& kv : leptonEfficiencies)
1204  {
1205  legs->clear();
1206  double x = uniformPdf(randomEngine);
1207  for(auto& p : kv.second)
1208  {
1209  if(x < (step? p.second.mc(): p.second.data())) legs->emplace(p.first);
1210  }
1211  ++legs;
1212  }
1213  for(auto& trig : triggers)
1214  {
1215  if(!canTriggerBeFired(trig, firedLegs)) continue;
1216  ++nPassed[step];
1217  break;
1218  }
1219  }
1220  }
1221  globalEfficiencies.data() = double(nPassed[0]) / double(m_parent->m_numberOfToys);
1222  globalEfficiencies.mc() = double(nPassed[1]) / double(m_parent->m_numberOfToys);
1223  return true;
1224 }
1225 
1226 Calculator::Helper::Helper(const std::vector<TrigDef>& defs) :
1227  m_formula(nullptr), m_defs(defs)
1228 {
1229 }
1230 
1232 {
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;
1236  return false;
1237 }
1238 
1240 {
1241  template<typename T>
1243  {
1244  using TrigType = T;
1245  using ArgType = std::add_const_t<T>;
1246  static constexpr bool multiple() { return false; }
1247  static constexpr bool optional() { return false; }
1248  static void add(T& arg, ImportData::TrigDef& def) { arg.setDefinition(def); }
1249  static constexpr bool valid(const T& arg) { return bool(arg); }
1250  };
1251 
1252  template<typename T>
1254  {
1255  using TrigType = T;
1256  using ArgType = const flat_set<T>&;
1257  static constexpr bool multiple() { return true; }
1258  static constexpr bool optional() { return false; }
1259  static void add(flat_set<T>& arg, ImportData::TrigDef& def) { arg.emplace().first->setDefinition(def); }
1260  static constexpr bool valid(const flat_set<T>& arg) { return arg.size(); }
1261  };
1262 
1263  template<typename T>
1265  {
1268  static constexpr bool multiple() { return BindPackedParam<T>::multiple(); }
1269  static constexpr bool optional() { return true; }
1270  static void add(std::remove_cv_t<std::remove_reference_t<ArgType>>& arg, ImportData::TrigDef def) { BindPackedParam<T>::add(arg, def); }
1271  static constexpr bool valid(ArgType& arg) { return BindPackedParam<T>::valid(arg); }
1272  };
1273 }
1274 
1275 template<typename Param>
1277 {
1278  std::remove_cv_t<std::remove_reference_t<typename Param::ArgType>> trigs;
1279  for(auto& def : m_defs)
1280  {
1281  if(def.used || def.type!=Param::TrigType::type()) continue;
1282  def.used = true;
1283  Param::add(trigs, def);
1284  if(!Param::multiple()) break;
1285  }
1286  if(!Param::optional() && !Param::valid(trigs)) throw NoSuchTrigger();
1287  return trigs;
1288 }
1289 
1290 template<typename... Trigs>
1292 {
1293  for(auto& def : m_defs) def.used = false;
1294  using fnptr = bool(Calculator::*)(const LeptonList&, unsigned, typename BindPackedParam<Trigs>::ArgType..., Efficiencies&);
1295  try
1296  {
1297  m_formula = std::bind<fnptr>(&Calculator::globalEfficiency, ::_1, ::_2, ::_3, extract<BindPackedParam<Trigs>>()..., ::_4);
1298  if(std::all_of(m_defs.cbegin(), m_defs.cend(), [](auto& def){return def.used;})) return true;
1299  }
1300  catch(NoSuchTrigger){}
1301  m_formula = nullptr;
1302  return false;
1303 }
1304 
1305 template<TriggerType object_flag>
1307 {
1308  using A = TriggerClass<object_flag>;
1309  using A1L = flat_set<typename A::T_1>;
1310  using A_2sym = typename A::T_2sym;
1311  using A_2asym = typename A::T_2asym;
1312  if(m_n2L + m_n3L + m_n4L == 0)
1313  {
1314  return bindFunction<typename A::T_1>() || bindFunction<A1L>();
1315  }
1316  else if(m_n2L==1 && m_n3L + m_n4L == 0)
1317  {
1318  return bindFunction<A_2sym>() || bindFunction<A_2asym>()
1319  || bindFunction<A_2sym, A1L>() || bindFunction<A_2asym, A1L>();
1320  }
1321  else if(m_n2L==2 && m_n3L + m_n4L == 0)
1322  {
1323  return bindFunction<A_2sym, A_2sym, Optional<A1L>>() || bindFunction<A_2asym, A_2sym, Optional<A1L>>();
1324  }
1325  else if(m_n3L==1 && m_n1L + m_n2L + m_n4L == 0)
1326  {
1327  return bindFunction<typename A::T_3sym>() || bindFunction<typename A::T_3halfsym>();
1328  }
1329  else if(m_n4L==1 && m_n1L + m_n2L + m_n3L == 0)
1330  {
1331  return bindFunction<typename A::T_4sym>();
1332  }
1333  return false;
1334 }
1335 
1336 template<TriggerType object_flag1, TriggerType object_flag2>
1338 {
1340  using A = TriggerClass<object_flag1>;
1341  using B = TriggerClass<object_flag2>;
1343  using A_1 = typename A::T_1;
1344  using B_1 = typename B::T_1;
1345  using OA1L = Optional<flat_set<A_1>>;
1346  using OB1L = Optional<flat_set<B_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;
1352 
1354  if(m_n1L>0 && m_n2L + m_n3L + m_n4L == 0)
1355  {
1356  return bindFunction<A_1, B_1>() || bindFunction<flat_set<A_1>, flat_set<B_1>>();
1357  }
1358  else if(m_n2L==1 && m_n3L + m_n4L == 0)
1359  { // one dilepton trigger (+ single-lepton triggers)
1360  return bindFunction<AB_1_1>() || bindFunction<AB_1_1, flat_set<A_1>, flat_set<B_1>>();
1361  }
1362  else if(m_n2L>=2 && m_n2L<=6 && m_n3L + m_n4L == 0)
1363  { // several dilepton triggers (+ single-lepton triggers)
1364  return
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>()
1369  || bindFunction<Optional<A_2sym>, Optional<B_2sym>, Optional<AB_1_1>, OA1L, OB1L>()
1371  || bindFunction<Optional<A_2sym>, Optional<B_2asym>, Optional<AB_1_1>, OA1L, OB1L>()
1374  || bindFunction<Optional<A_2sym>, Optional<A_2sym>, Optional<B_2sym>, Optional<B_2sym>, Optional<AB_1_1>, Optional<AB_1_1>, OA1L, OB1L>()
1376  || bindFunction<Optional<A_2sym>, Optional<A_2sym>, Optional<B_2asym>, Optional<B_2sym>, Optional<AB_1_1>, Optional<AB_1_1>, OA1L, OB1L>()
1378  }
1379  else if(m_n3L==1 && m_n1L + m_n2L + m_n4L == 0)
1380  { // one mixed trilepton trigger
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>();
1383  }
1384  else if(m_n3L==2 && m_n1L + m_n2L + m_n4L == 0)
1385  { // two mixed trilepton triggers
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>();
1390  }
1391  return false;
1392 }
1393 
1395 {
1396  auto countTriggers = [&](auto nlep_flag) { return std::count_if(m_defs.cbegin(), m_defs.cend(), [=](auto& def){return def.type&nlep_flag;}); };
1397  m_n1L = countTriggers(TT_SINGLELEPTON_FLAG);
1398  m_n2L = countTriggers(TT_DILEPTON_FLAG);
1399  m_n3L = countTriggers(TT_TRILEPTON_FLAG);
1400  m_n4L = countTriggers(TT_TETRALEPTON_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;}); };
1402 
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>();
1407 
1409  bool success = false;
1410  if(exclusively(TT_ELECTRON_FLAG|TT_MUON_FLAG)) success = findAndBindFunction<TT_ELECTRON_FLAG,TT_MUON_FLAG>();
1411  else if(exclusively(TT_ELECTRON_FLAG|TT_PHOTON_FLAG)) success = findAndBindFunction<TT_ELECTRON_FLAG,TT_PHOTON_FLAG>();
1412  else if(exclusively(TT_MUON_FLAG|TT_PHOTON_FLAG)) success = findAndBindFunction<TT_MUON_FLAG,TT_PHOTON_FLAG>();
1413  if(success) return true;
1414 
1416  std::vector<Helper> helpers;
1417  for(auto obj_flag : {TT_ELECTRON_FLAG, TT_MUON_FLAG, TT_PHOTON_FLAG})
1418  {
1419  if(std::any_of(m_defs.cbegin(), m_defs.cend(),
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); });
1423  m_defs.swap(trigs2);
1424  if(!trigs1.size()) continue;
1425  helpers.emplace_back(trigs1);
1426  if(!helpers.back().findAndBindFunction()) return false;
1427  }
1428  if(helpers.size())
1429  {
1430  if(m_defs.size())
1431  {
1432  if(!findAndBindFunction()) return false;
1433  if(helpers.size() == 1) m_formula = std::bind(&Calculator::globalEfficiency_Factorized2, ::_1, ::_2, ::_3,
1434  std::move(m_formula), std::move(helpers[0].m_formula), ::_4);
1435  else if(helpers.size()==2) m_formula = std::bind(&Calculator::globalEfficiency_Factorized3, ::_1, ::_2, ::_3,
1436  std::move(m_formula), std::move(helpers[0].m_formula), std::move(helpers[1].m_formula), ::_4);
1437  else
1438  {
1439  m_formula = nullptr;
1440  return false;
1441  }
1442  }
1443  else
1444  {
1445  if(helpers.size() == 2) m_formula = std::bind(&Calculator::globalEfficiency_Factorized2, ::_1, ::_2, ::_3,
1446  std::move(helpers[0].m_formula), std::move(helpers[1].m_formula), ::_4);
1447  else if(helpers.size() == 3) m_formula = std::bind(&Calculator::globalEfficiency_Factorized3, ::_1, ::_2, ::_3,
1448  std::move(helpers[0].m_formula), std::move(helpers[1].m_formula), std::move(helpers[2].m_formula), ::_4);
1449  else return false;
1450  }
1451  return true;
1452  }
1453 
1454  return false;
1455 }
sTgcDigitEffiDump.efficiencies
list efficiencies
translate the station name indices into the string staiton name
Definition: sTgcDigitEffiDump.py:23
python.AtlRunQueryAMI.period
period
Definition: AtlRunQueryAMI.py:225
TrigGlobEffCorr::TrigGlobEffCorr::Calculator::Helper::BindPackedParam::add
static void add(T &arg, ImportData::TrigDef &def)
Definition: Calculator.cxx:1248
TrigGlobEffCorr::Calculator::addPeriod
bool addPeriod(ImportData &data, const std::pair< unsigned, unsigned > &boundaries, const std::string &combination, bool useToys, std::size_t &uniqueElectronLeg, std::size_t &uniquePhotonLeg)
Definition: Calculator.cxx:29
TrigGlobalEfficiencyCorrectionTool::getSortedLegs
std::vector< std::size_t > getSortedLegs(const TrigGlobEffCorr::Lepton &lepton, const flat_set< std::size_t > &legs, bool &success)
data
char data[hepevt_bytes_allocation_ATLAS]
Definition: HepEvt.cxx:11
TrigGlobEffCorr::Calculator::m_forceUnitSF
bool m_forceUnitSF
Definition: Calculator.h:53
xAOD::Electron
Electron_v1 Electron
Definition of the current "egamma version".
Definition: Event/xAOD/xAODEgamma/xAODEgamma/Electron.h:17
Calculator.h
TrigGlobEffCorr::TrigGlobEffCorr::Calculator::Helper::BindPackedParam
Definition: Calculator.cxx:1243
runLayerRecalibration.chain
chain
Definition: runLayerRecalibration.py:175
TrigGlobEffCorr::TrigGlobEffCorr::Calculator::Helper::BindPackedParam::valid
static constexpr bool valid(const T &arg)
Definition: Calculator.cxx:1249
ObjectType
ObjectType
Definition: BaseObject.h:11
TrigGlobEffCorr::Calculator::m_periods
std::vector< Period > m_periods
pointer updated at each call to compute() because the parent tool might have been moved in-between
Definition: Calculator.h:51
TrigGlobEffCorr::Calculator::findUniqueLeg
bool findUniqueLeg(xAOD::Type::ObjectType obj, std::size_t &uniqueLeg, const std::vector< TrigDef > &defs)
Definition: Calculator.cxx:85
TrigGlobEffCorr::Lepton::photon
const xAOD::Photon * photon() const
Definition: Lepton.h:32
TrigGlobEffCorr
the template specializations below must be enclosed in this namespace
Definition: Calculator.cxx:1240
TrigGlobEffCorr::TrigGlobEffCorr::Calculator::Helper::BindPackedParam< flat_set< T > >::ArgType
const flat_set< T > & ArgType
Definition: Calculator.cxx:1256
asg
Definition: DataHandleTestTool.h:28
Efficiencies
TrigGlobEffCorr::Efficiencies Efficiencies
Definition: TrigGlobalEfficiencyCorrectionTool.cxx:29
ParticleTest.tp
tp
Definition: ParticleTest.py:25
TrigGlobEffCorr::TT_SINGLELEPTON_FLAG
@ TT_SINGLELEPTON_FLAG
Definition: ImportData.h:36
TrigGlobalEfficiencyCorrectionTool::m_useInternalSeed
bool m_useInternalSeed
Definition: TrigGlobalEfficiencyCorrectionTool.h:128
TrigGlobEffCorr::Efficiencies
Definition: Efficiencies.h:16
Lepton.h
TrigGlobEffCorr::Calculator::Helper::Helper
Helper(const std::vector< TrigDef > &defs)
Definition: Calculator.cxx:1226
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
python.TrigTLAMonitorAlgorithm.triggers
triggers
Definition: TrigTLAMonitorAlgorithm.py:196
Trigger.h
CheckTagAssociation.notfound
notfound
Definition: CheckTagAssociation.py:105
TrigGlobEffCorr::Calculator::Helper::BindPackedParam
to decorate the parameters of the findAndBind() function(s)
Definition: Calculator.h:233
x
#define x
TrigGlobEffCorr::TT_MUON_FLAG
@ TT_MUON_FLAG
Definition: ImportData.h:27
TrigGlobEffCorr::TrigGlobEffCorr::Calculator::Helper::BindPackedParam< flat_set< T > >::TrigType
T TrigType
Definition: Calculator.cxx:1255
xAOD::unsigned
unsigned
Definition: RingSetConf_v1.cxx:662
XMLtoHeader.count
count
Definition: XMLtoHeader.py:85
flat_set
boost::container::flat_set< Key > flat_set
Definition: CheckConfig.cxx:11
TrigGlobEffCorr::Calculator::aboveThreshold
bool aboveThreshold(const Lepton &p, std::size_t leg) const
Definition: Calculator.h:55
mergePhysValFiles.end
end
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:93
TrigGlobalEfficiencyCorrectionTool::m_seed
unsigned long m_seed
Definition: TrigGlobalEfficiencyCorrectionTool.h:151
TrigGlobEffCorr::TrigGlobEffCorr::Calculator::Helper::BindPackedParam< Calculator::Helper::Optional< T > >::optional
static constexpr bool optional()
Definition: Calculator.cxx:1269
TrigGlobEffCorr::TT_ELECTRON_FLAG
@ TT_ELECTRON_FLAG
Definition: ImportData.h:26
TRT::Hit::side
@ side
Definition: HitInfo.h:83
ImportData.h
runBeamSpotCalibration.helper
helper
Definition: runBeamSpotCalibration.py:112
TrigGlobEffCorr::TrigGlobEffCorr::Calculator::Helper::BindPackedParam< Calculator::Helper::Optional< T > >::multiple
static constexpr bool multiple()
Definition: Calculator.cxx:1268
TrigGlobEffCorr::TrigGlobEffCorr::Calculator::Helper::BindPackedParam::ArgType
std::add_const_t< T > ArgType
Definition: Calculator.cxx:1245
TrigGlobEffCorr::Calculator::compute
bool compute(TrigGlobalEfficiencyCorrectionTool &parent, const LeptonList &leptons, unsigned runNumber, Efficiencies &efficiencies)
Definition: Calculator.cxx:116
TrigGlobEffCorr::Lepton::tag
std::size_t tag() const
Definition: Lepton.h:29
TrigGlobalEfficiencyCorrectionTool::TLE_ERROR
@ TLE_ERROR
Definition: TrigGlobalEfficiencyCorrectionTool.h:187
calibdata.valid
list valid
Definition: calibdata.py:45
TrigGlobEffCorr::Calculator::Helper::extract
auto extract()
Definition: Calculator.cxx:1276
TrigGlobEffCorr::Calculator::globalEfficiency_Factorized2
bool globalEfficiency_Factorized2(const LeptonList &leptons, unsigned runNumber, GlobEffFunc func1, GlobEffFunc func2, Efficiencies &globalEfficiencies)
Definition: Calculator.cxx:1065
TrigGlobEffCorr::Calculator::Helper::duplicates
bool duplicates() const
Definition: Calculator.cxx:1231
A
TrigGlobEffCorr::Lepton::muon
const xAOD::Muon * muon() const
Definition: Lepton.h:31
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:210
TrigGlobEffCorr::ImportData::TrigDef::leg
std::array< std::size_t, 4 > leg
Definition: ImportData.h:96
TrigGlobEffCorr::Calculator::Helper::bindFunction
bool bindFunction()
Definition: Calculator.cxx:1291
TrigGlobEffCorr::Calculator::GlobEffFunc
std::function< bool(Calculator *, const LeptonList &, unsigned, Efficiencies &)> GlobEffFunc
Definition: Calculator.h:30
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
TrigGlobEffCorr::TT_PHOTON_FLAG
@ TT_PHOTON_FLAG
Definition: ImportData.h:28
TrigGlobEffCorr::Calculator
Definition: Calculator.h:27
lumiFormat.i
int i
Definition: lumiFormat.py:85
TrigGlobEffCorr::TrigGlobEffCorr::Calculator::Helper::BindPackedParam::multiple
static constexpr bool multiple()
Definition: Calculator.cxx:1246
TrigGlobEffCorr::Calculator::m_cachedEfficiencies
std::map< std::pair< const Lepton *, std::size_t >, Efficiencies > m_cachedEfficiencies
Definition: Calculator.h:52
TrigGlobEffCorr::Calculator::Helper::m_n1L
unsigned m_n1L
Definition: Calculator.h:224
TrigGlobEffCorr::ImportData
Definition: ImportData.h:88
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
TrigGlobEffCorr::Calculator::m_parent
TrigGlobalEfficiencyCorrectionTool * m_parent
Definition: Calculator.h:49
res
std::pair< std::vector< unsigned int >, bool > res
Definition: JetGroupProductTest.cxx:14
asg::AsgMessaging::msg
MsgStream & msg() const
The standard message stream.
Definition: AsgMessaging.cxx:49
test_pyathena.parent
parent
Definition: test_pyathena.py:15
compute_lumi.leg
leg
Definition: compute_lumi.py:95
add
bool add(const std::string &hname, TKey *tobj)
Definition: fastadd.cxx:55
TrigGlobEffCorr::TrigGlobEffCorr::Calculator::Helper::BindPackedParam< flat_set< T > >::multiple
static constexpr bool multiple()
Definition: Calculator.cxx:1257
TrigGlobEffCorr::TT_TETRALEPTON_FLAG
@ TT_TETRALEPTON_FLAG
Definition: ImportData.h:80
TrigGlobalEfficiencyCorrectionTool::m_validTrigMatchTool
bool m_validTrigMatchTool
Definition: TrigGlobalEfficiencyCorrectionTool.h:152
xAOD::double
double
Definition: CompositeParticle_v1.cxx:159
TrigGlobalEfficiencyCorrectionTool::TLE_OK
@ TLE_OK
Definition: TrigGlobalEfficiencyCorrectionTool.h:185
TrigGlobEffCorr::TT_TRILEPTON_FLAG
@ TT_TRILEPTON_FLAG
Definition: ImportData.h:54
TrigGlobalEfficiencyCorrectionTool::TLE_UNAVAILABLE
@ TLE_UNAVAILABLE
Definition: TrigGlobalEfficiencyCorrectionTool.h:186
create_dcsc_inputs_sqlite.arg
list arg
Definition: create_dcsc_inputs_sqlite.py:48
TrigGlobEffCorr::Calculator::Helper::m_defs
std::vector< TrigDef > m_defs
Definition: Calculator.h:223
TrigGlobEffCorr::Calculator::Helper::NoSuchTrigger
Definition: Calculator.h:231
TrigGlobEffCorr::Efficiencies::mc
double & mc()
Definition: Efficiencies.h:26
TrigGlobEffCorr::Calculator::LeptonList
TrigGlobalEfficiencyCorrectionTool::LeptonList LeptonList
Definition: Calculator.h:28
TrigGlobEffCorr::TrigGlobEffCorr::Calculator::Helper::BindPackedParam< Calculator::Helper::Optional< T > >::ArgType
typename BindPackedParam< T >::ArgType ArgType
Definition: Calculator.cxx:1267
TrigGlobEffCorr::Lepton
Definition: Lepton.h:18
TrigGlobEffCorr::Calculator::Helper::m_formula
std::function< bool(Calculator *, const LeptonList &, unsigned, Efficiencies &)> m_formula
Definition: Calculator.h:218
python.ElectronD3PDObject.matched
matched
Definition: ElectronD3PDObject.py:138
TrigGlobEffCorr::Calculator::globalEfficiency_Factorized3
bool globalEfficiency_Factorized3(const LeptonList &leptons, unsigned runNumber, GlobEffFunc func1, GlobEffFunc func2, GlobEffFunc func3, Efficiencies &globalEfficiencies)
Definition: Calculator.cxx:1074
TrigGlobalEfficiencyCorrectionTool
Definition: TrigGlobalEfficiencyCorrectionTool.h:39
TrigGlobEffCorr::TrigGlobEffCorr::Calculator::Helper::BindPackedParam< flat_set< T > >::valid
static constexpr bool valid(const flat_set< T > &arg)
Definition: Calculator.cxx:1260
TrigGlobEffCorr::Lepton::type
xAOD::Type::ObjectType type() const
Definition: Lepton.h:28
TrigGlobEffCorr::ImportData::TrigDef
Definition: ImportData.h:93
xAOD::Photon
Photon_v1 Photon
Definition of the current "egamma version".
Definition: Event/xAOD/xAODEgamma/xAODEgamma/Photon.h:17
Muon
struct TBPatternUnitContext Muon
Rtt_histogram.n1
n1
Definition: Rtt_histogram.py:21
TrigGlobalEfficiencyCorrectionTool::getTriggerLegEfficiencies
TLE_RESULT getTriggerLegEfficiencies(const xAOD::Electron *p, unsigned runNumber, std::size_t leg, std::size_t tag, TrigGlobEffCorr::Efficiencies &efficiencies)
DeMoAtlasDataLoss.runNumber
string runNumber
Definition: DeMoAtlasDataLoss.py:64
TrigGlobEffCorr::Calculator::Calculator
Calculator(TrigGlobalEfficiencyCorrectionTool &parent, unsigned nPeriodsToReserve)
Definition: Calculator.cxx:21
TrigGlobEffCorr::Calculator::checkTriggerMatching
bool checkTriggerMatching(TrigGlobalEfficiencyCorrectionTool &parent, bool &matched, const LeptonList &leptons, unsigned runNumber)
Definition: Calculator.cxx:133
TrigGlobEffCorr::Calculator::getCachedTriggerLegEfficiencies
Efficiencies getCachedTriggerLegEfficiencies(const Lepton &lepton, unsigned runNumber, std::size_t leg, bool &success)
Definition: Calculator.cxx:241
TrigGlobalEfficiencyCorrectionTool::m_trigMatchTool
ToolHandle< Trig::IMatchingTool > m_trigMatchTool
Definition: TrigGlobalEfficiencyCorrectionTool.h:129
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
TrigGlobEffCorr::Calculator::Helper::m_n3L
unsigned m_n3L
Definition: Calculator.h:224
TrigGlobEffCorr::Calculator::Helper::m_n4L
unsigned m_n4L
Definition: Calculator.h:224
TrigGlobEffCorr::TrigGlobEffCorr::Calculator::Helper::BindPackedParam< flat_set< T > >::add
static void add(flat_set< T > &arg, ImportData::TrigDef &def)
Definition: Calculator.cxx:1259
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
TrigGlobalEfficiencyCorrectionTool::m_numberOfToys
unsigned long m_numberOfToys
Definition: TrigGlobalEfficiencyCorrectionTool.h:127
TrigGlobEffCorr::TT_DILEPTON_FLAG
@ TT_DILEPTON_FLAG
Definition: ImportData.h:41
TrigGlobEffCorr::Calculator::Helper::findAndBindFunction
bool findAndBindFunction()
top-level function
Definition: Calculator.cxx:1394
TrigGlobEffCorr::TrigGlobEffCorr::Calculator::Helper::BindPackedParam< Calculator::Helper::Optional< T > >::add
static void add(std::remove_cv_t< std::remove_reference_t< ArgType >> &arg, ImportData::TrigDef def)
Definition: Calculator.cxx:1270
LArCellBinning.step
step
Definition: LArCellBinning.py:158
TrigGlobEffCorr::TriggerProperties
Definition: Trigger.h:25
TrigGlobEffCorr::Calculator::globalEfficiency
auto globalEfficiency(const LeptonList &, unsigned, const Trig1L, Efficiencies &) -> std::enable_if_t< Trig1L::is1L(), bool >
One single-lepton trigger.
Definition: Calculator.cxx:284
TrigGlobEffCorr::TrigGlobEffCorr::Calculator::Helper::BindPackedParam< flat_set< T > >::optional
static constexpr bool optional()
Definition: Calculator.cxx:1258
TrigGlobEffCorr::TrigGlobEffCorr::Calculator::Helper::BindPackedParam< Calculator::Helper::Optional< T > >::TrigType
typename BindPackedParam< T >::TrigType TrigType
Definition: Calculator.cxx:1266
TrigGlobEffCorr::Calculator::Helper
Definition: Calculator.h:212
TrigGlobEffCorr::Calculator::fillListOfLegsFor
bool fillListOfLegsFor(const Lepton &lepton, const std::vector< TrigDef > &triggers, flat_set< std::size_t > &validLegs) const
Definition: Calculator.cxx:1084
pickleTool.object
object
Definition: pickleTool.py:30
dqt_zlumi_alleff_HIST.eff
int eff
Definition: dqt_zlumi_alleff_HIST.py:113
TrigGlobEffCorr::Calculator::canTriggerBeFired
bool canTriggerBeFired(const TrigDef &trig, const std::vector< flat_set< std::size_t > > &firedLegs) const
Definition: Calculator.cxx:1101
TrigGlobEffCorr::Efficiencies::data
double & data()
Definition: Efficiencies.h:25
TrigGlobalEfficiencyCorrectionTool::retrieveEventNumber
bool retrieveEventNumber(unsigned long &eventNumber)
TrigGlobEffCorr::Calculator::globalEfficiency_Toys
bool globalEfficiency_Toys(const LeptonList &, unsigned, const std::vector< TrigDef > &triggers, Efficiencies &)
Definition: Calculator.cxx:1157
TrigGlobEffCorr::Calculator::getRelevantTriggersForUser
bool getRelevantTriggersForUser(TrigGlobalEfficiencyCorrectionTool &parent, std::vector< std::string > &triggers, unsigned runNumber)
Definition: Calculator.cxx:214
python.PyAthena.obj
obj
Definition: PyAthena.py:132
TrigGlobEffCorr::TriggerClass
Definition: Trigger.h:307
TrigGlobEffCorr::TrigGlobEffCorr::Calculator::Helper::BindPackedParam::optional
static constexpr bool optional()
Definition: Calculator.cxx:1247
xAOD::bool
setBGCode setTAP setLVL2ErrorBits bool
Definition: TrigDecision_v1.cxx:60
TrigGlobalEfficiencyCorrectionTool::m_dictionary
std::map< std::size_t, std::string > m_dictionary
Definition: TrigGlobalEfficiencyCorrectionTool.h:143
TrigGlobEffCorr::Calculator::Helper::m_n2L
unsigned m_n2L
Definition: Calculator.h:224
TrigGlobEffCorr::Calculator::Period
Definition: Calculator.h:41
TrigGlobEffCorr::Lepton::electron
const xAOD::Electron * electron() const
Definition: Lepton.h:30
TrigGlobEffCorr::TrigGlobEffCorr::Calculator::Helper::BindPackedParam< Calculator::Helper::Optional< T > >::valid
static constexpr bool valid(ArgType &arg)
Definition: Calculator.cxx:1271
TrigGlobEffCorr::TrigGlobEffCorr::Calculator::Helper::BindPackedParam::TrigType
T TrigType
Definition: Calculator.cxx:1244
TrigGlobEffCorr::Calculator::Helper::Optional
Definition: Calculator.h:232
TrigGlobEffCorr::Calculator::getPeriod
const Period * getPeriod(unsigned runNumber) const
Definition: Calculator.cxx:104