ATLAS Offline Software
Trigger.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 // This source file implements all of the functions related to trigger
6 // in the SUSYObjDef_xAOD class
7 
8 // Local include(s):
10 
17 
19 
20 #ifndef XAOD_STANDALONE // For now metadata is Athena-only
22 #endif
23 
24 #include <regex>
25 
26 namespace ST {
27 
28  const static SG::AuxElement::Decorator<char> dec_trigmatched("trigmatched");
29 
30 bool SUSYObjDef_xAOD::IsMETTrigPassed(unsigned int runnumber, bool j400_OR) const {
31 
32  // Returns MET trigger decision for recommended lowest unprescaled evolution described in
33  // https://twiki.cern.ch/twiki/bin/viewauth/Atlas/LowestUnprescaled
34  // For period vs run number, see https://atlas-tagservices.cern.ch/tagservices/RunBrowser/runBrowserReport/rBR_Period_Report.php
35 
36  // if no runNumber specified, just read it from the current event
37  unsigned int rn;
38  if(runnumber>0){
39  rn = runnumber;
40  }
41  else{
42  rn = GetRunNumber(); // it takes care of dealing with data and MC
43  }
44 
45  int year = treatAsYear(rn);
46 
47  if (year == 2015) return IsMETTrigPassed("HLT_xe70_mht",j400_OR); //2015
48  else if(year == 2016 && rn >= 296939 && rn <= 302872 ) return IsMETTrigPassed("HLT_xe90_mht_L1XE50",j400_OR); //2016 A-D3
49  else if(year == 2016 && rn >= 302919 && rn <= 303892 ) return IsMETTrigPassed("HLT_xe100_mht_L1XE50",j400_OR); //2016 D4-F1
50  else if(year == 2016 && rn >= 303943) return IsMETTrigPassed("HLT_xe110_mht_L1XE50",j400_OR); //2016 F2-(open)
51  else if(year == 2017 && rn >= 325713 && rn <= 331975 ) return IsMETTrigPassed("HLT_xe110_pufit_L1XE55", false); // 2017 B1-D5
52  else if(year == 2017 && rn >= 332303 ) return IsMETTrigPassed("HLT_xe110_pufit_L1XE50", false); // 2017 D6-(open)
53  else if(year == 2018 && rn >= 348885 && rn <= 350013 ) return IsMETTrigPassed("HLT_xe110_pufit_xe70_L1XE50", false); // 2018 B-C5
54  else if(year == 2018 && rn >= 350067 ) return IsMETTrigPassed("HLT_xe110_pufit_xe65_L1XE50", false); // 2018 C5-(open)
55  else if(year == 2022) return (IsMETTrigPassed("HLT_xe65_cell_xe90_pfopufit_L1XE50",false)
56  || IsMETTrigPassed("HLT_xe80_cell_xe115_tcpufit_L1XE50 ",false)); // 2022
57  else if(year == 2023) return (IsMETTrigPassed("HLT_xe55_cell_xe70_tcpufit_xe90_pfsum_vssk_L1XE50",false)
58  || IsMETTrigPassed("HLT_xe55_cell_xe70_tcpufit_xe95_pfsum_cssk_L1XE50",false)
59  || IsMETTrigPassed("HLT_xe60_cell_xe95_pfsum_cssk_L1XE50",false)
60  || IsMETTrigPassed("HLT_xe65_cell_xe100_mhtpufit_pf_L1XE50",false)
61  || IsMETTrigPassed("HLT_xe65_cell_xe105_mhtpufit_em_L1XE50",false)
62  || IsMETTrigPassed("HLT_xe75_cell_xe65_tcpufit_xe90_trkmht_L1XE50",false)
63  || IsMETTrigPassed("HLT_xe65_cell_xe90_pfopufit_L1XE50",false)
64  || IsMETTrigPassed("HLT_xe80_cell_xe115_tcpufit_L1XE50 ",false)); // 2023
65 
66  return false;
67 }
68 
69 // Can't be const because of the lazy init of the map - JBurr: Now fixed
70 bool SUSYObjDef_xAOD::IsMETTrigPassed(const std::string& triggerName, bool j400_OR) const {
71  // NB - this now applies to the entire function...
72  //std::string L1item = "L1_XE50"; For now, I'll assume all the triggers use L1_XE50 - might need changing in the future.
73 
74  // First check if we're affected by the L1_XE50 bug
75  bool L1_XE50 = m_trigDecTool->isPassed("L1_XE50");
76  bool L1_XE55 = m_trigDecTool->isPassed("L1_XE55");
77  bool HLT_noalg_L1J400 = m_trigDecTool->isPassed("HLT_noalg_L1J400");
78  if (!L1_XE50 && j400_OR && HLT_noalg_L1J400) {
79  return emulateHLT(triggerName);
80  }
81  else if (L1_XE50 || L1_XE55) {
82  // See if the TDT knows about this
83  {
84  std::scoped_lock lock (m_triggerCacheMutex);
85  if (isTrigInTDT(lock, triggerName) ) return m_trigDecTool->isPassed(triggerName);
86  }
87  return emulateHLT(triggerName);
88  }
89  return false;
90 }
91 
92 bool SUSYObjDef_xAOD::isTrigInTDT(std::scoped_lock<std::mutex>& /*lock*/,
93  const std::string& triggerName) const
94 {
95  auto mapItr = m_checkedTriggers.find(triggerName);
96  if ( mapItr == m_checkedTriggers.end() ) {
97  const auto *cg = m_trigDecTool->getChainGroup(triggerName);
98  return m_checkedTriggers[triggerName] = cg->getListOfTriggers().size() != 0;
99  }
100  else {
101  return mapItr->second;
102  }
103 }
104 
105 
106 bool SUSYObjDef_xAOD::emulateHLT(const std::string& triggerName) const {
107  std::scoped_lock lock (m_triggerCacheMutex);
108  // First, check if we've already tried using this trigger
109  auto funcItr = m_metTriggerFuncs.find(triggerName);
110  if (funcItr != m_metTriggerFuncs.end() )
111  return funcItr->second();
112 
113  // Next, check that it really is a HLT MET trigger
114  if (triggerName.substr(0,6) != "HLT_xe") {
115  ATH_MSG_ERROR( "Requested trigger " << triggerName << " isn't a MET trigger! (HLT MET items should begin with 'HLT_xe'). Will return false." );
116  return false;
117  }
118 
119  // Next, parse the name to work out which containers are needed to emulate the decision
120  std::vector<std::pair<int, std::string> > hypos; // algorithms and thresholds needed
121  std::string temp(triggerName);
122  // Note, we need to split on '_AND_' used for the combined mht+cell trigger
123  do {
124  auto pos = temp.find("_AND_");
125  std::string itemName = temp.substr(0, pos);
126  ATH_MSG_DEBUG( "Split trigger item " << itemName );
127  if (pos == std::string::npos)
128  temp = "";
129  else
130  temp = temp.substr(pos + 5);
131 
132  std::regex expr("HLT_xe([[:digit:]]+)_?(mht|pufit|pueta|tc_lcw|)_?(?:L1XE([[:digit:]]+)|)");
133  std::smatch sm;
134  if (!std::regex_match(itemName, sm, expr) ) {
135  ATH_MSG_WARNING( "Regex reading for item " << itemName << " (" << triggerName << ") failed! Will be ignored!" );
136  continue;
137  }
138  if (sm.size() < 4) { // first object is the whole match, then there are three capture groups
139  ATH_MSG_WARNING( "Regex failed to capture the right groups for item " << itemName << " (" << triggerName << ") failed! Will be ignored!" );
140  for (unsigned int ii = 0; ii < sm.size(); ++ii) {
141  ATH_MSG_WARNING( sm[ii] );
142  }
143  continue;
144  }
145  int threshold = std::stoi(sm[1] );
146  std::string algKey = sm[2];
147  std::string metContBaseName = "HLT_xAOD__TrigMissingETContainer_TrigEFMissingET";
148  if (algKey.empty()) hypos.push_back(std::make_pair(threshold, metContBaseName) );
149  else if (algKey == "mht") hypos.push_back(std::make_pair(threshold, metContBaseName+"_mht") );
150  else if (algKey == "pufit") hypos.push_back(std::make_pair(threshold, metContBaseName+"_topocl_PUC") );
151  else if (algKey == "pueta") hypos.push_back(std::make_pair(threshold, metContBaseName+"_topocl_PS") );
152  else if (algKey == "tc_lcw") hypos.push_back(std::make_pair(threshold, metContBaseName+"topocl") );
153 
154  ATH_MSG_DEBUG( "Container: " << hypos.back().second << ", Threshold: " << hypos.back().first );
155 
156  if (sm[3] != "" && sm[3] != "50") {
157  ATH_MSG_WARNING( "The trigger requires a different L1 item to L1_XE50! This currently isn't allowed for in the code so the emulation will be slightly wrong" );
158  // Note, now the L1 part is done in the previous section. However I'm keeping this warning here.
159  }
160  }
161  while (!temp.empty());
162 
163  // Check if we have the containers and construct the lambda
164  // Already done the L1 decision - only care about HLT
165  std::function<bool()> lambda;
166  bool hasRequired = true;
167  if (hypos.empty()) lambda = [] () {return false;};
168  else {
169  for (const auto& pair : hypos) {
170  if (evtStore()->contains<xAOD::TrigMissingETContainer>(pair.second) ) {
171  auto lambda_hypo = [this, pair] () {
172  const xAOD::TrigMissingETContainer* cont(nullptr);
173  if (evtStore()->retrieve(cont, pair.second) ) {
174  if (cont->empty()) return false;
175  float ex = cont->front()->ex() * 0.001;
176  float ey = cont->front()->ey() * 0.001;
177  float met = std::sqrt(ex*ex + ey*ey);
178  return met > pair.first;
179  }
180  else {
181  return false;
182  }
183  };
184  // an empty std::function evaluates to false
185  if (lambda) {
186  lambda = [lambda, lambda_hypo] () {
187  return lambda() && lambda_hypo();
188  };
189  }
190  else {
191  lambda = lambda_hypo;
192  }
193  }
194  else {
195  hasRequired = false;
196  ATH_MSG_WARNING( "Container: " << pair.second << " missing!" );
197  }
198  }
199  }
200  if (hasRequired) {
201  m_metTriggerFuncs[triggerName] = lambda;
202  return m_metTriggerFuncs.at(triggerName)();
203  }
204  // We can't get the exact trigger decision :( . Look for an alternative
205  std::vector<std::string> replacementTriggers({"HLT_xe110_mht_L1XE50", "HLT_xe100_mht_L1XE50", "HLT_xe90_mht_L1XE50", "HLT_xe70_mht"});
206  for (const std::string& trigName : replacementTriggers) {
207  if (isTrigInTDT(lock, trigName) ) {
208  ATH_MSG_WARNING( "Trigger " << triggerName << " not available and direct emulation impossible! Will use " << trigName << " instead!");
209  m_metTriggerFuncs[triggerName] = [this, trigName] () {
210  return m_trigDecTool->isPassed(trigName);
211  };
212  return m_metTriggerFuncs.at(triggerName)();
213  }
214  }
215  ATH_MSG_ERROR( "Cannot find the trigger in the menu, direct emulation is impossible and no replacement triggers are available! Will return false" );
216  m_metTriggerFuncs.at(triggerName) = [] () {return false;};
217  return m_metTriggerFuncs.at(triggerName)();
218 }
219 
220 
221 
222 bool SUSYObjDef_xAOD::IsTrigPassed(const std::string& tr_item, unsigned int condition) const {
223  return m_trigDecTool->isPassed(tr_item, condition);
224 }
225 
226 
227 bool SUSYObjDef_xAOD::IsTrigMatched(const xAOD::IParticle *part, const std::string& tr_item) {
228  return this->IsTrigMatched({part}, tr_item);
229 }
230 
231 
232 bool SUSYObjDef_xAOD::IsTrigMatched(const xAOD::IParticle *part1, const xAOD::IParticle *part2, const std::string& tr_item) {
233  return this->IsTrigMatched({part1, part2}, tr_item);
234 }
235 
236 
237 bool SUSYObjDef_xAOD::IsTrigMatched(const std::vector<const xAOD::IParticle*>& v, const std::string& tr_item) {
238  return m_trigMatchingTool->match(v, tr_item);
239 }
240 
241 
242 bool SUSYObjDef_xAOD::IsTrigMatched(const std::initializer_list<const xAOD::IParticle*> &v, const std::string& tr_item) {
243  return m_trigMatchingTool->match(v, tr_item);
244 }
245 
246 
248  dec_trigmatched(*p) = 0;
249 
250  for(const auto *it = i1; it != i2; ++it) {
251  auto result = static_cast<int>(this->IsTrigMatched(p, *it));
252  dec_trigmatched(*p) += result;
253  p->auxdecor<char>(*it) = result;
254  }
255 }
256 
257 
258 void SUSYObjDef_xAOD::TrigMatch(const xAOD::IParticle* p, const std::initializer_list<std::string>& items) {
259  this->TrigMatch(p, items.begin(), items.end());
260 }
261 
262 
263 void SUSYObjDef_xAOD::TrigMatch(const xAOD::IParticle* p, const std::vector<std::string>& items) {
264  dec_trigmatched(*p) = 0;
265 
266  for(const auto& item: items) {
267  auto result = static_cast<int>(this->IsTrigMatched(p, item));
268  dec_trigmatched(*p) += result;
269  p->auxdecor<char>(item) = result;
270  }
271 }
272 
273 
274 void SUSYObjDef_xAOD::TrigMatch(const std::initializer_list<const xAOD::IParticle*> &v, const std::initializer_list<std::string> &items) {
275  for(const auto& p : v) {
276  this->TrigMatch(p, items);
277  }
278 }
279 
280 
281 void SUSYObjDef_xAOD::TrigMatch(const std::initializer_list<const xAOD::IParticle*> &v, const std::vector<std::string>& items) {
282  for(const auto& p : v) {
283  this->TrigMatch(p, items);
284  }
285 }
286 
287 
288 void SUSYObjDef_xAOD::TrigMatch(const xAOD::IParticleContainer* v, const std::vector<std::string>& items) {
289  for(const auto& p : *v) {
290  this->TrigMatch(p, items);
291  }
292 }
293 
294 
295 void SUSYObjDef_xAOD::TrigMatch(const xAOD::IParticleContainer* v, const std::initializer_list<std::string>& items) {
296  for(const auto& p : *v) {
297  this->TrigMatch(p, items);
298  }
299 }
300 
301 
302 void SUSYObjDef_xAOD::TrigMatch(const xAOD::IParticle* p, const std::string& item) {
303  return this->TrigMatch(p, {item});
304 }
305 
306 
307 void SUSYObjDef_xAOD::TrigMatch(const xAOD::IParticleContainer* v, const std::string& item) {
308  return this->TrigMatch(v, {item});
309 }
310 
311 
312 void SUSYObjDef_xAOD::TrigMatch(const std::initializer_list<const xAOD::IParticle*> &v, const std::string& item) {
313  return this->TrigMatch(v, {item});
314 }
315 
316 
317 float SUSYObjDef_xAOD::GetTrigPrescale(const std::string & tr_item) const {
318  return m_trigDecTool->getPrescale(tr_item);
319 }
320 
321 
322 const Trig::ChainGroup* SUSYObjDef_xAOD::GetTrigChainGroup(const std::string& tr_item) const {
323  return m_trigDecTool->getChainGroup(tr_item);
324 }
325 
326 
327  std::vector<std::string> SUSYObjDef_xAOD::GetTriggerOR(const std::string& trigExpr) const {
328 
329  static const std::string delOR = "_OR_";
330  std::vector<std::string> trigchains = {};
331  std::string newtrigExpr = TString(trigExpr).Copy().ReplaceAll("||",delOR).Data();
332  newtrigExpr = TString(trigExpr).Copy().ReplaceAll(" ","").Data();
333 
334  size_t pos = 0;
335  while ((pos = newtrigExpr.find(delOR)) != std::string::npos) {
336  trigchains.push_back( "HLT_"+newtrigExpr.substr(0, pos) );
337  newtrigExpr.erase(0, pos + delOR.length());
338  }
339  if(pos==std::string::npos)
340  trigchains.push_back("HLT_"+newtrigExpr);
341 
342  return trigchains;
343  }
344 
345  void SUSYObjDef_xAOD::GetTriggerTokens(std::string trigExpr, std::vector<std::string>& v_trigs15_cache, std::vector<std::string>& v_trigs16_cache, std::vector<std::string>& v_trigs17_cache, std::vector<std::string>& v_trigs18_cache, std::vector<std::string>& v_trigs22_cache) const {
346 
347  // e.g. SINGLE_E_2015_e24_lhmedium_L1EM20VH_OR_e60_lhmedium_OR_e120_lhloose_2016_2018_e26_lhtight_nod0_ivarloose_OR_e60_lhmedium_nod0_OR_e140_lhloose_nod0
348 
349  static const std::string del15 = "_2015_";
350  static const std::string del16 = "_2016_";
351  static const std::string del17 = "_2017_";
352  static const std::string del18 = "_2018_";
353  static const std::string del22 = "_2022_";
354 
355  size_t pos = 0;
356  std::string token15, token16, token17, token18, token22;
357 
358  //get trigger tokens for 2015, 2016, 2017, 2018 and 2022
359  if ( (pos = trigExpr.find(del15)) != std::string::npos) {
360  trigExpr.erase(0, pos + del15.length());
361 
362  pos = 0;
363  while ((pos = trigExpr.find(del16)) != std::string::npos) {
364  token15 = trigExpr.substr(0, pos);
365  token16 = trigExpr.erase(0, pos + del16.length() + del17.length() - 1);
366  // 2016-2018 use exact the same trigger string
367  token17 = token16;
368  token18 = token16;
369  }
370  }
371 
372  if ( (pos = trigExpr.find(del22)) != std::string::npos) {
373  trigExpr.erase(0, pos + del22.length());
374  }
375 
376  //redefine in case of custom user input
377  if(!m_isRun3){
378  if(token15.empty()) token15 = trigExpr;
379  if(token16.empty()) token16 = trigExpr;
380  if(token17.empty()) token17 = trigExpr;
381  if(token18.empty()) token18 = trigExpr;
382  }
383  else{
384  if(token22.empty()) token22 = trigExpr;
385  }
386 
387  //get trigger chains for matching in 2015 and 2018
388  if(!m_isRun3){
389  v_trigs15_cache = GetTriggerOR(token15);
390  v_trigs16_cache = GetTriggerOR(token16);
391  v_trigs17_cache = GetTriggerOR(token17);
392  v_trigs18_cache = GetTriggerOR(token18);
393  }
394  //get trigger chains for matching in 2022
395  else{
396  v_trigs22_cache = GetTriggerOR(token22);
397  }
398  }
399 
401  {
403  }
404 
406 
407  double trig_sf(1.);
408 
409  if (trigExpr!="multiLepton" && trigExpr!="diLepton") {
410  ATH_MSG_ERROR( "Failed to retrieve multi-lepton trigger SF");
411  return trig_sf;
412  }
413 
414  std::vector<const xAOD::Electron*> elec_trig;
415  for (const xAOD::Electron* electron : electrons) {
416  if (!acc_passOR(*electron)) continue;
417  if (!acc_signal(*electron)) continue;
418  elec_trig.push_back(electron);
419  }
420 
421  std::vector<const xAOD::Muon*> muon_trig;
422  for (const xAOD::Muon* muon : muons) {
423  if (!acc_passOR(*muon)) continue;
424  if (!acc_signal(*muon)) continue;
425  muon_trig.push_back(muon);
426  }
427 
428  bool matched = false;
429  if ((elec_trig.size()+muon_trig.size())>1 && trigExpr=="diLepton") {
431  ATH_MSG_ERROR ("trigGlobEffCorrTool::Trigger matching could not be checked, interrupting execution.");
432  }
433  } else if ((elec_trig.size()+muon_trig.size())>2 && trigExpr=="multiLepton") {
435  ATH_MSG_ERROR ("trigGlobEffCorrTool::Trigger matching could not be checked, interrupting execution.");
436  }
437  }
438 
440  if ((elec_trig.size()+muon_trig.size())>1 && trigExpr=="diLepton" && matched) {
441  result = m_trigGlobalEffCorrTool_diLep->getEfficiencyScaleFactor( elec_trig, muon_trig, trig_sf);
442  }
443  else if ((elec_trig.size()+muon_trig.size())>2 && trigExpr=="multiLepton" && matched) {
444  result = m_trigGlobalEffCorrTool_multiLep->getEfficiencyScaleFactor( elec_trig, muon_trig, trig_sf);
445  }
446 
447  switch (result) {
449  ATH_MSG_ERROR( "Failed to retrieve multi-lepton trigger SF");
450  return 1.;
452  ATH_MSG_VERBOSE( "OutOfValidityRange found for multi-lepton trigger SF");
453  return 1.;
454  default:
455  break;
456  }
457 
458  return trig_sf;
459 }
460 
461 double SUSYObjDef_xAOD::GetTriggerGlobalEfficiencySFsys(const xAOD::ElectronContainer& electrons, const xAOD::MuonContainer& muons, const CP::SystematicSet& systConfig, const std::string& trigExpr) {
462 
463  double sf(1.);
464 
465  //Set the new systematic variation
466  if (trigExpr == "diLepton") {
468  if (ret != StatusCode::SUCCESS) {
469  ATH_MSG_ERROR("Cannot configure TrigGlobalEfficiencyCorrectionTool (dilepton trigger) for systematic var. " << systConfig.name() );
470  }
471  }
472 
473  if (trigExpr == "multiLepton") {
475  if (ret != StatusCode::SUCCESS) {
476  ATH_MSG_ERROR("Cannot configure TrigGlobalEfficiencyCorrectionTool (multi-lepton trigger) for systematic var. " << systConfig.name() );
477  }
478  }
479 
480  //Get the SF for new config
481  sf = GetTriggerGlobalEfficiencySF (electrons, muons, trigExpr);
482 
483  //Roll back to default
484  if (trigExpr == "diLepton") {
486  if (ret != StatusCode::SUCCESS) {
487  ATH_MSG_ERROR("Cannot configure TrigGlobalEfficiencyCorrectionTool (dilepton trigger) back to default.");
488  }
489  }
490  if (trigExpr == "multiLepton") {
492  if (ret != StatusCode::SUCCESS) {
493  ATH_MSG_ERROR("Cannot configure TrigGlobalEfficiencyCorrectionTool (multi-lepton trigger) back to default.");
494  }
495  }
496 
497  return sf;
498 }
499 
500 //
501 // GetTriggerGlobalEfficiencySF function is meant to be used for "asymmetric" diphoton trigger SFs
502 //
503 double SUSYObjDef_xAOD::GetTriggerGlobalEfficiencySF(const xAOD::PhotonContainer& photons, const std::string& trigExpr) {
504 
505  double trig_sf(1.);
506 
507  if (trigExpr!="diPhoton") {
508  ATH_MSG_ERROR( "Failed to retrieve diphoton trigger SF");
509  return trig_sf;
510  }
511 
512  std::vector<const xAOD::Photon*> ph_trig;
513  for (const xAOD::Photon* photon : photons) {
514  if (!acc_passOR(*photon)) continue;
515  if (!acc_signal(*photon)) continue;
516  ph_trig.push_back(photon);
517  }
518 
520  if (ph_trig.size()>1) {
522  }
523 
524  switch (result) {
526  ATH_MSG_ERROR( "Failed to retrieve diphoton trigger SF");
527  return 1.;
529  ATH_MSG_VERBOSE( "OutOfValidityRange found for diphoton trigger SF");
530  return 1.;
531  default:
532  break;
533  }
534 
535  return trig_sf;
536 }
537 
538 double SUSYObjDef_xAOD::GetTriggerGlobalEfficiencySFsys(const xAOD::PhotonContainer& photons, const CP::SystematicSet& systConfig, const std::string& trigExpr) {
539 
540  double sf(1.);
541 
542  //Set the new systematic variation
544  if (ret != StatusCode::SUCCESS) {
545  ATH_MSG_ERROR("Cannot configure TrigGlobalEfficiencyCorrectionTool (diphoton trigger) for systematic var. " << systConfig.name() );
546  }
547 
548  //Get the SF for new config
549  sf = GetTriggerGlobalEfficiencySF (photons, trigExpr);
550 
551  //Roll back to default
553  if (ret != StatusCode::SUCCESS) {
554  ATH_MSG_ERROR("Cannot configure TrigGlobalEfficiencyCorrectionTool (diphoton trigger) back to default.");
555  }
556 
557  return sf;
558 }
559 
561 
562  double trig_eff(1.);
563  double trig_eff_data(1.);
564 
565  if (trigExpr!="multiLepton" && trigExpr!="diLepton") {
566  ATH_MSG_ERROR( "Failed to retrieve multi-lepton trigger efficiency");
567  return trig_eff;
568  }
569 
570  std::vector<const xAOD::Electron*> elec_trig;
571  for (const xAOD::Electron* electron : electrons) {
572  if (!acc_passOR(*electron)) continue;
573  if (!acc_signal(*electron)) continue;
574  elec_trig.push_back(electron);
575  }
576 
577  std::vector<const xAOD::Muon*> muon_trig;
578  for (const xAOD::Muon* muon : muons) {
579  if (!acc_passOR(*muon)) continue;
580  if (!acc_signal(*muon)) continue;
581  muon_trig.push_back(muon);
582  }
583 
584  bool matched = false;
585  if ((elec_trig.size()+muon_trig.size())>1 && trigExpr=="diLepton") {
587  ATH_MSG_ERROR ("trigGlobEffCorrTool::Trigger matching could not be checked, interrupting execution.");
588  }
589  } else if ((elec_trig.size()+muon_trig.size())>2 && trigExpr=="multiLepton") {
591  ATH_MSG_ERROR ("trigGlobEffCorrTool::Trigger matching could not be checked, interrupting execution.");
592  }
593  }
594 
596  if ((elec_trig.size()+muon_trig.size())>1 && trigExpr=="diLepton" && matched) {
597  result = m_trigGlobalEffCorrTool_diLep->getEfficiency( elec_trig, muon_trig, trig_eff_data, trig_eff);
598  }
599  else if ((elec_trig.size()+muon_trig.size())>2 && trigExpr=="multiLepton" && matched) {
600  result = m_trigGlobalEffCorrTool_multiLep->getEfficiency( elec_trig, muon_trig, trig_eff_data, trig_eff);
601  }
602 
603  switch (result) {
605  ATH_MSG_ERROR( "Failed to retrieve multi-lepton trigger efficiency");
606  return 1.;
608  ATH_MSG_VERBOSE( "OutOfValidityRange found for multi-lepton trigger efficiency");
609  return 1.;
610  default:
611  break;
612  }
613 
614  if (isData()) return trig_eff_data;
615  else return trig_eff;
616 }
617 
618 //
619 // GetTriggerGlobalEfficiency function is meant to be used for "asymmetric" diphoton trigger SFs
620 //
621 double SUSYObjDef_xAOD::GetTriggerGlobalEfficiency(const xAOD::PhotonContainer& photons, const std::string& trigExpr) {
622 
623  double trig_eff(1.);
624  double trig_eff_data(1.);
625 
626  if (trigExpr!="diPhoton") {
627  ATH_MSG_ERROR( "Failed to retrieve diphoton trigger efficiency");
628  return trig_eff;
629  }
630 
631  std::vector<const xAOD::Photon*> ph_trig;
632  for (const xAOD::Photon* photon : photons) {
633  if (!acc_passOR(*photon)) continue;
634  if (!acc_signal(*photon)) continue;
635  ph_trig.push_back(photon);
636  }
637 
639  if (ph_trig.size()>1) {
640  result = m_trigGlobalEffCorrTool_diPhoton->getEfficiency(ph_trig, trig_eff_data, trig_eff);
641  }
642 
643  switch (result) {
645  ATH_MSG_ERROR( "Failed to retrieve diphoton trigger efficiency");
646  return 1.;
648  ATH_MSG_VERBOSE( "OutOfValidityRange found for diphoton trigger efficiency");
649  return 1.;
650  default:
651  break;
652  }
653 
654  if (isData()) return trig_eff_data;
655  else return trig_eff;
656 }
657 
658 }
659 
LArG4FSStartPointFilter.part
part
Definition: LArG4FSStartPointFilter.py:21
python.PyKernel.retrieve
def retrieve(aClass, aKey=None)
Definition: PyKernel.py:110
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
ST::SUSYObjDef_xAOD::emulateHLT
bool emulateHLT(const std::string &triggerName) const
Definition: Trigger.cxx:106
xAOD::muon
@ muon
Definition: TrackingPrimitives.h:195
ST::SUSYObjDef_xAOD::m_trigGlobalEffCorrTool_multiLep
asg::AnaToolHandle< ITrigGlobalEfficiencyCorrectionTool > m_trigGlobalEffCorrTool_multiLep
Definition: SUSYObjDef_xAOD.h:935
ST::SUSYObjDef_xAOD::GetTriggerGlobalEfficiencySFsys
double GetTriggerGlobalEfficiencySFsys(const xAOD::ElectronContainer &electrons, const xAOD::MuonContainer &muons, const CP::SystematicSet &systConfig, const std::string &trigExpr="diLepton") override final
Definition: Trigger.cxx:461
ST::SUSYObjDef_xAOD::m_triggerCacheMutex
std::mutex m_triggerCacheMutex
Definition: SUSYObjDef_xAOD.h:446
get_generator_info.result
result
Definition: get_generator_info.py:21
python.PerfMonSerializer.p
def p
Definition: PerfMonSerializer.py:743
ST::SUSYObjDef_xAOD::m_trigGlobalEffCorrTool_diPhoton
asg::AnaToolHandle< ITrigGlobalEfficiencyCorrectionTool > m_trigGlobalEffCorrTool_diPhoton
Definition: SUSYObjDef_xAOD.h:943
FeatureContainer.h
ITrigConfigTool.h
ITrigGlobalEfficiencyCorrectionTool.h
ST::SUSYObjDef_xAOD::GetTriggerOR
std::vector< std::string > GetTriggerOR(const std::string &trigExpr) const
Definition: Trigger.cxx:327
ST::SUSYObjDef_xAOD::GetTriggerTokens
void GetTriggerTokens(std::string, std::vector< std::string > &, std::vector< std::string > &, std::vector< std::string > &, std::vector< std::string > &, std::vector< std::string > &) const
Definition: Trigger.cxx:345
ST::SUSYObjDef_xAOD::GetTriggerFeatures
Trig::FeatureContainer GetTriggerFeatures(const std::string &chainName="EF_.*", unsigned int condition=TrigDefs::Physics) const
Definition: Trigger.cxx:400
ST
Definition: Electrons.cxx:41
skel.it
it
Definition: skel.GENtoEVGEN.py:423
CP::SystematicSet
Class to wrap a set of SystematicVariations.
Definition: SystematicSet.h:31
CP::SystematicSet::name
std::string name() const
returns: the systematics joined into a single string.
Definition: SystematicSet.cxx:278
SUSYObjDef_xAOD.h
TrigDecisionTool.h
LArG4GenerateShowerLib.condition
condition
Definition: LArG4GenerateShowerLib.py:19
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
ST::SUSYObjDef_xAOD::m_trigMatchingTool
asg::AnaToolHandle< Trig::IMatchingTool > m_trigMatchingTool
Definition: SUSYObjDef_xAOD.h:947
python.AtlRunQueryAMI.year
year
Definition: AtlRunQueryAMI.py:226
Trig::TrigDecisionToolCore::features
FeatureContainer features(const Trig::ChainGroup *group, unsigned int condition=TrigDefs::Physics) const
Runs 1, 2.
Definition: DecisionAccess.cxx:92
xAOD::IParticle
Class providing the definition of the 4-vector interface.
Definition: Event/xAOD/xAODBase/xAODBase/IParticle.h:40
xAOD::Muon_v1
Class describing a Muon.
Definition: Muon_v1.h:38
PrepareReferenceFile.regex
regex
Definition: PrepareReferenceFile.py:43
Trig::FeatureContainer
Definition: FeatureContainer.h:54
PyPoolBrowser.item
item
Definition: PyPoolBrowser.py:129
part1
Definition: part1.py:1
ST::SUSYObjDef_xAOD::m_trigGlobalEffCorrTool_diLep
asg::AnaToolHandle< ITrigGlobalEfficiencyCorrectionTool > m_trigGlobalEffCorrTool_diLep
Definition: SUSYObjDef_xAOD.h:927
AthCommonDataStore< AthCommonMsg< AlgTool > >::evtStore
ServiceHandle< StoreGateSvc > & evtStore()
The standard StoreGateSvc (event store) Returns (kind of) a pointer to the StoreGateSvc.
Definition: AthCommonDataStore.h:85
CP::CorrectionCode::OutOfValidityRange
@ OutOfValidityRange
Input object is out of validity range.
Definition: CorrectionCode.h:37
CP::CorrectionCode::Error
@ Error
Some error happened during the object correction.
Definition: CorrectionCode.h:36
met
Definition: IMETSignificance.h:24
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
ST::SUSYObjDef_xAOD::GetRunNumber
unsigned int GetRunNumber() const override final
Definition: SUSYObjDef_xAOD.cxx:2977
SG::Decorator
Helper class to provide type-safe access to aux data.
Definition: Decorator.h:58
ret
T ret(T t)
Definition: rootspy.cxx:260
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ST::SUSYObjDef_xAOD::IsTrigPassed
bool IsTrigPassed(const std::string &, unsigned int condition=TrigDefs::Physics) const override final
Definition: Trigger.cxx:222
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
DataVector::front
const T * front() const
Access the first element in the collection as an rvalue.
python.BunchSpacingUtils.rn
rn
Definition: BunchSpacingUtils.py:87
TrigMissingETContainer.h
ST::SUSYObjDef_xAOD::isData
bool isData() const override final
Definition: SUSYObjDef_xAOD.h:156
ST::SUSYObjDef_xAOD::IsTrigMatched
bool IsTrigMatched(const xAOD::IParticle *part, const std::string &tr_item) override final
Definition: Trigger.cxx:227
ST::SUSYObjDef_xAOD::GetTriggerGlobalEfficiency
double GetTriggerGlobalEfficiency(const xAOD::ElectronContainer &electrons, const xAOD::MuonContainer &muons, const std::string &trigExpr="diLepton") override final
Definition: Trigger.cxx:560
DataVector
Derived DataVector<T>.
Definition: DataVector.h:581
Trig::TrigDecisionTool::isPassed
virtual bool isPassed(const std::string &chain, unsigned int condition) const
true if given chain passed
Definition: TrigDecisionTool.cxx:270
DeMoScan.runnumber
runnumber
Definition: DeMoScan.py:266
part2
Definition: part2.py:1
Trig::ChainGroup
Definition: Trigger/TrigAnalysis/TrigDecisionTool/TrigDecisionTool/ChainGroup.h:51
ST::SUSYObjDef_xAOD::IsMETTrigPassed
bool IsMETTrigPassed(unsigned int runnumber=0, bool j400_OR=false) const override final
Definition: Trigger.cxx:30
ST::SUSYObjDef_xAOD::TrigMatch
void TrigMatch(const xAOD::IParticle *p, std::initializer_list< std::string >::iterator, std::initializer_list< std::string >::iterator) override final
Definition: Trigger.cxx:247
threshold
Definition: chainparser.cxx:74
python.ElectronD3PDObject.matched
matched
Definition: ElectronD3PDObject.py:138
TrigJetMonitorAlgorithm.items
items
Definition: TrigJetMonitorAlgorithm.py:79
item
Definition: ItemListSvc.h:43
xAOD::Electron_v1
Definition: Electron_v1.h:34
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:18
ST::SUSYObjDef_xAOD::GetTrigPrescale
float GetTrigPrescale(const std::string &) const override final
Definition: Trigger.cxx:317
AthAnalysisHelper.h
Trig::TrigDecisionToolCore::getPrescale
float getPrescale(const Trig::ChainGroup *chaingroup, unsigned int condition=TrigDefs::Physics) const
Definition: ConfigurationAccess.cxx:88
python.PyAthena.v
v
Definition: PyAthena.py:157
ST::SUSYObjDef_xAOD::GetTrigChainGroup
const Trig::ChainGroup * GetTrigChainGroup(const std::string &) const override final
Definition: Trigger.cxx:322
CP::CorrectionCode::Ok
@ Ok
The correction was done successfully.
Definition: CorrectionCode.h:38
ITrigGlobalEfficiencyCorrectionTool::getEfficiencyScaleFactor
virtual CP::CorrectionCode getEfficiencyScaleFactor(const std::vector< const xAOD::IParticle * > &particles, double &efficiencyScaleFactor)=0
IMatchingTool.h
xAOD::photon
@ photon
Definition: TrackingPrimitives.h:199
ITrigGlobalEfficiencyCorrectionTool::checkTriggerMatching
virtual CP::CorrectionCode checkTriggerMatching(bool &matched, const std::vector< const xAOD::IParticle * > &particles)=0
xAOD::Photon_v1
Definition: Photon_v1.h:37
mapkey::sf
@ sf
Definition: TElectronEfficiencyCorrectionTool.cxx:38
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
ITrigGlobalEfficiencyCorrectionTool::getEfficiency
virtual CP::CorrectionCode getEfficiency(const std::vector< const xAOD::IParticle * > &particles, double &efficiencyData, double &efficiencyMc)=0
ST::SUSYObjDef_xAOD::GetTriggerGlobalEfficiencySF
double GetTriggerGlobalEfficiencySF(const xAOD::ElectronContainer &electrons, const xAOD::MuonContainer &muons, const std::string &trigExpr="diLepton") override final
Definition: Trigger.cxx:405
ST::SUSYObjDef_xAOD::m_isRun3
bool m_isRun3
Definition: SUSYObjDef_xAOD.h:788
ST::SUSYObjDef_xAOD::m_trigDecTool
asg::AnaToolHandle< Trig::TrigDecisionTool > m_trigDecTool
Definition: SUSYObjDef_xAOD.h:946
python.TriggerAPI.TriggerAPISession.chainName
chainName
Definition: TriggerAPISession.py:353
CP::CorrectionCode
Return value from object correction CP tools.
Definition: CorrectionCode.h:31
ST::SUSYObjDef_xAOD::m_currentSyst
CP::SystematicSet m_currentSyst
Definition: SUSYObjDef_xAOD.h:801
xAOD::EgammaParameters::electron
@ electron
Definition: EgammaEnums.h:18
Conditions.h
Trig::TrigDecisionToolCore::getChainGroup
const Trig::ChainGroup * getChainGroup(const std::vector< std::string > &patterns, TrigDefs::Group props=TrigDefs::Group::Default) const
Create/get chain group (.
Definition: ChainGroupFunctions.cxx:38
Trig::ChainGroup::getListOfTriggers
std::vector< std::string > getListOfTriggers() const
Definition: Trigger/TrigAnalysis/TrigDecisionTool/Root/ChainGroup.cxx:467
Trig::IMatchingTool::match
virtual bool match(const xAOD::IParticle &recoObject, const std::string &chain, double matchThreshold=0.1, bool rerun=false) const =0
single object trigger matching. matchThreshold is typically the deltaR requirement to obtain positive...
ST::SUSYObjDef_xAOD::treatAsYear
int treatAsYear(const int runNumber=-1) const override final
Definition: SUSYObjDef_xAOD.cxx:3031
xAOD::bool
setBGCode setTAP setLVL2ErrorBits bool
Definition: TrigDecision_v1.cxx:60
CP::ISystematicsTool::applySystematicVariation
virtual StatusCode applySystematicVariation(const SystematicSet &systConfig)=0
effects: configure this tool for the given list of systematic variations.
DataVector::empty
bool empty() const noexcept
Returns true if the collection is empty.
InDetDD::electrons
@ electrons
Definition: InDetDD_Defs.h:17
ST::SUSYObjDef_xAOD::isTrigInTDT
bool isTrigInTDT(std::scoped_lock< std::mutex > &lock, const std::string &triggerName) const
Definition: Trigger.cxx:92