ATLAS Offline Software
Trigger.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 // 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;
254  dec(*p) = result;
255  }
256 }
257 
258 
259 void SUSYObjDef_xAOD::TrigMatch(const xAOD::IParticle* p, const std::initializer_list<std::string>& items) {
260  this->TrigMatch(p, items.begin(), items.end());
261 }
262 
263 
264 void SUSYObjDef_xAOD::TrigMatch(const xAOD::IParticle* p, const std::vector<std::string>& items) {
265  dec_trigmatched(*p) = 0;
266 
267  for(const auto& item: items) {
268  auto result = static_cast<int>(this->IsTrigMatched(p, item));
269  dec_trigmatched(*p) += result;
271  dec(*p) = result;
272  }
273 }
274 
275 
276 void SUSYObjDef_xAOD::TrigMatch(const std::initializer_list<const xAOD::IParticle*> &v, const std::initializer_list<std::string> &items) {
277  for(const auto& p : v) {
278  this->TrigMatch(p, items);
279  }
280 }
281 
282 
283 void SUSYObjDef_xAOD::TrigMatch(const std::initializer_list<const xAOD::IParticle*> &v, const std::vector<std::string>& items) {
284  for(const auto& p : v) {
285  this->TrigMatch(p, items);
286  }
287 }
288 
289 
290 void SUSYObjDef_xAOD::TrigMatch(const xAOD::IParticleContainer* v, const std::vector<std::string>& items) {
291  for(const auto& p : *v) {
292  this->TrigMatch(p, items);
293  }
294 }
295 
296 
297 void SUSYObjDef_xAOD::TrigMatch(const xAOD::IParticleContainer* v, const std::initializer_list<std::string>& items) {
298  for(const auto& p : *v) {
299  this->TrigMatch(p, items);
300  }
301 }
302 
303 
304 void SUSYObjDef_xAOD::TrigMatch(const xAOD::IParticle* p, const std::string& item) {
305  return this->TrigMatch(p, {item});
306 }
307 
308 
309 void SUSYObjDef_xAOD::TrigMatch(const xAOD::IParticleContainer* v, const std::string& item) {
310  return this->TrigMatch(v, {item});
311 }
312 
313 
314 void SUSYObjDef_xAOD::TrigMatch(const std::initializer_list<const xAOD::IParticle*> &v, const std::string& item) {
315  return this->TrigMatch(v, {item});
316 }
317 
318 
319 float SUSYObjDef_xAOD::GetTrigPrescale(const std::string & tr_item) const {
320  return m_trigDecTool->getPrescale(tr_item);
321 }
322 
323 
324 const Trig::ChainGroup* SUSYObjDef_xAOD::GetTrigChainGroup(const std::string& tr_item) const {
325  return m_trigDecTool->getChainGroup(tr_item);
326 }
327 
328 
329  std::vector<std::string> SUSYObjDef_xAOD::GetTriggerOR(const std::string& trigExpr) const {
330 
331  static const std::string delOR = "_OR_";
332  std::vector<std::string> trigchains = {};
333  std::string newtrigExpr = TString(trigExpr).Copy().ReplaceAll("||",delOR).Data();
334  newtrigExpr = TString(trigExpr).Copy().ReplaceAll(" ","").Data();
335 
336  size_t pos = 0;
337  while ((pos = newtrigExpr.find(delOR)) != std::string::npos) {
338  trigchains.push_back( "HLT_"+newtrigExpr.substr(0, pos) );
339  newtrigExpr.erase(0, pos + delOR.length());
340  }
341  if(pos==std::string::npos)
342  trigchains.push_back("HLT_"+newtrigExpr);
343 
344  return trigchains;
345  }
346 
347  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 {
348 
349  // 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
350 
351  static const std::string del15 = "_2015_";
352  static const std::string del16 = "_2016_";
353  static const std::string del17 = "_2017_";
354  static const std::string del18 = "_2018_";
355  static const std::string del22 = "_2022_";
356 
357  size_t pos = 0;
358  std::string token15, token16, token17, token18, token22;
359 
360  //get trigger tokens for 2015, 2016, 2017, 2018 and 2022
361  if ( (pos = trigExpr.find(del15)) != std::string::npos) {
362  trigExpr.erase(0, pos + del15.length());
363 
364  pos = 0;
365  while ((pos = trigExpr.find(del16)) != std::string::npos) {
366  token15 = trigExpr.substr(0, pos);
367  token16 = trigExpr.erase(0, pos + del16.length() + del17.length() - 1);
368  // 2016-2018 use exact the same trigger string
369  token17 = token16;
370  token18 = token16;
371  }
372  }
373 
374  if ( (pos = trigExpr.find(del22)) != std::string::npos) {
375  trigExpr.erase(0, pos + del22.length());
376  }
377 
378  //redefine in case of custom user input
379  if(!m_isRun3){
380  if(token15.empty()) token15 = trigExpr;
381  if(token16.empty()) token16 = trigExpr;
382  if(token17.empty()) token17 = trigExpr;
383  if(token18.empty()) token18 = trigExpr;
384  }
385  else{
386  if(token22.empty()) token22 = trigExpr;
387  }
388 
389  //get trigger chains for matching in 2015 and 2018
390  if(!m_isRun3){
391  v_trigs15_cache = GetTriggerOR(token15);
392  v_trigs16_cache = GetTriggerOR(token16);
393  v_trigs17_cache = GetTriggerOR(token17);
394  v_trigs18_cache = GetTriggerOR(token18);
395  }
396  //get trigger chains for matching in 2022
397  else{
398  v_trigs22_cache = GetTriggerOR(token22);
399  }
400  }
401 
403  {
405  }
406 
408 
409  double trig_sf(1.);
410 
411  if (trigExpr!="multiLepton" && trigExpr!="diLepton") {
412  ATH_MSG_ERROR( "Failed to retrieve multi-lepton trigger SF");
413  return trig_sf;
414  }
415 
416  std::vector<const xAOD::Electron*> elec_trig;
417  for (const xAOD::Electron* electron : electrons) {
418  if (!acc_passOR(*electron)) continue;
419  if (!acc_signal(*electron)) continue;
420  elec_trig.push_back(electron);
421  }
422 
423  std::vector<const xAOD::Muon*> muon_trig;
424  for (const xAOD::Muon* muon : muons) {
425  if (!acc_passOR(*muon)) continue;
426  if (!acc_signal(*muon)) continue;
427  muon_trig.push_back(muon);
428  }
429 
430  bool matched = false;
431  if ((elec_trig.size()+muon_trig.size())>1 && trigExpr=="diLepton") {
433  ATH_MSG_ERROR ("trigGlobEffCorrTool::Trigger matching could not be checked, interrupting execution.");
434  }
435  } else if ((elec_trig.size()+muon_trig.size())>2 && trigExpr=="multiLepton") {
437  ATH_MSG_ERROR ("trigGlobEffCorrTool::Trigger matching could not be checked, interrupting execution.");
438  }
439  }
440 
442  if ((elec_trig.size()+muon_trig.size())>1 && trigExpr=="diLepton" && matched) {
443  result = m_trigGlobalEffCorrTool_diLep->getEfficiencyScaleFactor( elec_trig, muon_trig, trig_sf);
444  }
445  else if ((elec_trig.size()+muon_trig.size())>2 && trigExpr=="multiLepton" && matched) {
446  result = m_trigGlobalEffCorrTool_multiLep->getEfficiencyScaleFactor( elec_trig, muon_trig, trig_sf);
447  }
448 
449  switch (result) {
451  ATH_MSG_ERROR( "Failed to retrieve multi-lepton trigger SF");
452  return 1.;
454  ATH_MSG_VERBOSE( "OutOfValidityRange found for multi-lepton trigger SF");
455  return 1.;
456  default:
457  break;
458  }
459 
460  return trig_sf;
461 }
462 
463 double SUSYObjDef_xAOD::GetTriggerGlobalEfficiencySFsys(const xAOD::ElectronContainer& electrons, const xAOD::MuonContainer& muons, const CP::SystematicSet& systConfig, const std::string& trigExpr) {
464 
465  double sf(1.);
466 
467  //Set the new systematic variation
468  if (trigExpr == "diLepton") {
470  if (ret != StatusCode::SUCCESS) {
471  ATH_MSG_ERROR("Cannot configure TrigGlobalEfficiencyCorrectionTool (dilepton trigger) for systematic var. " << systConfig.name() );
472  }
473  }
474 
475  if (trigExpr == "multiLepton") {
477  if (ret != StatusCode::SUCCESS) {
478  ATH_MSG_ERROR("Cannot configure TrigGlobalEfficiencyCorrectionTool (multi-lepton trigger) for systematic var. " << systConfig.name() );
479  }
480  }
481 
482  //Get the SF for new config
483  sf = GetTriggerGlobalEfficiencySF (electrons, muons, trigExpr);
484 
485  //Roll back to default
486  if (trigExpr == "diLepton") {
488  if (ret != StatusCode::SUCCESS) {
489  ATH_MSG_ERROR("Cannot configure TrigGlobalEfficiencyCorrectionTool (dilepton trigger) back to default.");
490  }
491  }
492  if (trigExpr == "multiLepton") {
494  if (ret != StatusCode::SUCCESS) {
495  ATH_MSG_ERROR("Cannot configure TrigGlobalEfficiencyCorrectionTool (multi-lepton trigger) back to default.");
496  }
497  }
498 
499  return sf;
500 }
501 
502 //
503 // GetTriggerGlobalEfficiencySF function is meant to be used for "asymmetric" diphoton trigger SFs
504 //
505 double SUSYObjDef_xAOD::GetTriggerGlobalEfficiencySF(const xAOD::PhotonContainer& photons, const std::string& trigExpr) {
506 
507  double trig_sf(1.);
508 
509  if (trigExpr!="diPhoton") {
510  ATH_MSG_ERROR( "Failed to retrieve diphoton trigger SF");
511  return trig_sf;
512  }
513 
514  std::vector<const xAOD::Photon*> ph_trig;
515  for (const xAOD::Photon* photon : photons) {
516  if (!acc_passOR(*photon)) continue;
517  if (!acc_signal(*photon)) continue;
518  ph_trig.push_back(photon);
519  }
520 
522  if (ph_trig.size()>1) {
524  }
525 
526  switch (result) {
528  ATH_MSG_ERROR( "Failed to retrieve diphoton trigger SF");
529  return 1.;
531  ATH_MSG_VERBOSE( "OutOfValidityRange found for diphoton trigger SF");
532  return 1.;
533  default:
534  break;
535  }
536 
537  return trig_sf;
538 }
539 
540 double SUSYObjDef_xAOD::GetTriggerGlobalEfficiencySFsys(const xAOD::PhotonContainer& photons, const CP::SystematicSet& systConfig, const std::string& trigExpr) {
541 
542  double sf(1.);
543 
544  //Set the new systematic variation
546  if (ret != StatusCode::SUCCESS) {
547  ATH_MSG_ERROR("Cannot configure TrigGlobalEfficiencyCorrectionTool (diphoton trigger) for systematic var. " << systConfig.name() );
548  }
549 
550  //Get the SF for new config
551  sf = GetTriggerGlobalEfficiencySF (photons, trigExpr);
552 
553  //Roll back to default
555  if (ret != StatusCode::SUCCESS) {
556  ATH_MSG_ERROR("Cannot configure TrigGlobalEfficiencyCorrectionTool (diphoton trigger) back to default.");
557  }
558 
559  return sf;
560 }
561 
563 
564  double trig_eff(1.);
565  double trig_eff_data(1.);
566 
567  if (trigExpr!="multiLepton" && trigExpr!="diLepton") {
568  ATH_MSG_ERROR( "Failed to retrieve multi-lepton trigger efficiency");
569  return trig_eff;
570  }
571 
572  std::vector<const xAOD::Electron*> elec_trig;
573  for (const xAOD::Electron* electron : electrons) {
574  if (!acc_passOR(*electron)) continue;
575  if (!acc_signal(*electron)) continue;
576  elec_trig.push_back(electron);
577  }
578 
579  std::vector<const xAOD::Muon*> muon_trig;
580  for (const xAOD::Muon* muon : muons) {
581  if (!acc_passOR(*muon)) continue;
582  if (!acc_signal(*muon)) continue;
583  muon_trig.push_back(muon);
584  }
585 
586  bool matched = false;
587  if ((elec_trig.size()+muon_trig.size())>1 && trigExpr=="diLepton") {
589  ATH_MSG_ERROR ("trigGlobEffCorrTool::Trigger matching could not be checked, interrupting execution.");
590  }
591  } else if ((elec_trig.size()+muon_trig.size())>2 && trigExpr=="multiLepton") {
593  ATH_MSG_ERROR ("trigGlobEffCorrTool::Trigger matching could not be checked, interrupting execution.");
594  }
595  }
596 
598  if ((elec_trig.size()+muon_trig.size())>1 && trigExpr=="diLepton" && matched) {
599  result = m_trigGlobalEffCorrTool_diLep->getEfficiency( elec_trig, muon_trig, trig_eff_data, trig_eff);
600  }
601  else if ((elec_trig.size()+muon_trig.size())>2 && trigExpr=="multiLepton" && matched) {
602  result = m_trigGlobalEffCorrTool_multiLep->getEfficiency( elec_trig, muon_trig, trig_eff_data, trig_eff);
603  }
604 
605  switch (result) {
607  ATH_MSG_ERROR( "Failed to retrieve multi-lepton trigger efficiency");
608  return 1.;
610  ATH_MSG_VERBOSE( "OutOfValidityRange found for multi-lepton trigger efficiency");
611  return 1.;
612  default:
613  break;
614  }
615 
616  if (isData()) return trig_eff_data;
617  else return trig_eff;
618 }
619 
620 //
621 // GetTriggerGlobalEfficiency function is meant to be used for "asymmetric" diphoton trigger SFs
622 //
623 double SUSYObjDef_xAOD::GetTriggerGlobalEfficiency(const xAOD::PhotonContainer& photons, const std::string& trigExpr) {
624 
625  double trig_eff(1.);
626  double trig_eff_data(1.);
627 
628  if (trigExpr!="diPhoton") {
629  ATH_MSG_ERROR( "Failed to retrieve diphoton trigger efficiency");
630  return trig_eff;
631  }
632 
633  std::vector<const xAOD::Photon*> ph_trig;
634  for (const xAOD::Photon* photon : photons) {
635  if (!acc_passOR(*photon)) continue;
636  if (!acc_signal(*photon)) continue;
637  ph_trig.push_back(photon);
638  }
639 
641  if (ph_trig.size()>1) {
642  result = m_trigGlobalEffCorrTool_diPhoton->getEfficiency(ph_trig, trig_eff_data, trig_eff);
643  }
644 
645  switch (result) {
647  ATH_MSG_ERROR( "Failed to retrieve diphoton trigger efficiency");
648  return 1.;
650  ATH_MSG_VERBOSE( "OutOfValidityRange found for diphoton trigger efficiency");
651  return 1.;
652  default:
653  break;
654  }
655 
656  if (isData()) return trig_eff_data;
657  else return trig_eff;
658 }
659 
660 }
661 
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:938
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:463
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
ST::SUSYObjDef_xAOD::m_trigGlobalEffCorrTool_diPhoton
asg::AnaToolHandle< ITrigGlobalEfficiencyCorrectionTool > m_trigGlobalEffCorrTool_diPhoton
Definition: SUSYObjDef_xAOD.h:946
FeatureContainer.h
ITrigConfigTool.h
ITrigGlobalEfficiencyCorrectionTool.h
ST::SUSYObjDef_xAOD::GetTriggerOR
std::vector< std::string > GetTriggerOR(const std::string &trigExpr) const
Definition: Trigger.cxx:329
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:347
ST::SUSYObjDef_xAOD::GetTriggerFeatures
Trig::FeatureContainer GetTriggerFeatures(const std::string &chainName="EF_.*", unsigned int condition=TrigDefs::Physics) const
Definition: Trigger.cxx:402
ST
Definition: Electrons.cxx:41
skel.it
it
Definition: skel.GENtoEVGEN.py:396
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:950
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:41
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
part1
Definition: part1.py:1
ST::SUSYObjDef_xAOD::m_trigGlobalEffCorrTool_diLep
asg::AnaToolHandle< ITrigGlobalEfficiencyCorrectionTool > m_trigGlobalEffCorrTool_diLep
Definition: SUSYObjDef_xAOD.h:930
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
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:210
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:3008
SG::Decorator
Helper class to provide type-safe access to aux data.
Definition: Decorator.h:59
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:562
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: 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
Conditions.h
ST::SUSYObjDef_xAOD::GetTrigPrescale
float GetTrigPrescale(const std::string &) const override final
Definition: Trigger.cxx:319
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:154
ST::SUSYObjDef_xAOD::GetTrigChainGroup
const Trig::ChainGroup * GetTrigChainGroup(const std::string &) const override final
Definition: Trigger.cxx:324
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:407
ST::SUSYObjDef_xAOD::m_isRun3
bool m_isRun3
Definition: SUSYObjDef_xAOD.h:791
ST::SUSYObjDef_xAOD::m_trigDecTool
asg::AnaToolHandle< Trig::TrigDecisionTool > m_trigDecTool
Definition: SUSYObjDef_xAOD.h:949
python.TriggerAPI.TriggerAPISession.chainName
chainName
Definition: TriggerAPISession.py:426
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:804
xAOD::EgammaParameters::electron
@ electron
Definition: EgammaEnums.h:18
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: 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:3062
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