ATLAS Offline Software
Loading...
Searching...
No Matches
Trigger.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 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
26namespace ST {
27
28 const static SG::Decorator<char> dec_trigmatched("trigmatched");
29
30bool 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,"L1_XE55"); // 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); // 2022
56 else if(year == 2023) return IsMETTrigPassed("HLT_xe65_cell_xe90_pfopufit_L1XE50",false); // 2023
57 else if(year == 2024) return IsMETTrigPassed("HLT_xe65_cell_xe105_nn_L1jXE100",false,"L1_jXE100"); // 2024
58
59 return false;
60}
61
62// Can't be const because of the lazy init of the map - JBurr: Now fixed
63bool SUSYObjDef_xAOD::IsMETTrigPassed(const std::string& triggerName, bool j400_OR, const std::string& L1_name) const {
64 // NB - this now applies to the entire function...
65
66 // First check if we're affected by the L1_XE50 bug
67 bool L1_pass = m_trigDecTool->isPassed(L1_name);
68 bool HLT_noalg_L1J400 = m_trigDecTool->isPassed("HLT_noalg_L1J400");
69 if (!L1_pass && j400_OR && HLT_noalg_L1J400) {
70 return emulateHLT(triggerName);
71 }
72 else if (L1_pass) {
73 // See if the TDT knows about this
74 {
75 std::scoped_lock lock (m_triggerCacheMutex);
76 if (isTrigInTDT(lock, triggerName) ) return m_trigDecTool->isPassed(triggerName);
77 }
78 return emulateHLT(triggerName);
79 }
80 return false;
81}
82
83bool SUSYObjDef_xAOD::isTrigInTDT(std::scoped_lock<std::mutex>& /*lock*/,
84 const std::string& triggerName) const
85{
86 auto mapItr = m_checkedTriggers.find(triggerName);
87 if ( mapItr == m_checkedTriggers.end() ) {
88 const auto *cg = m_trigDecTool->getChainGroup(triggerName);
89 return m_checkedTriggers[triggerName] = cg->getListOfTriggers().size() != 0;
90 }
91 else {
92 return mapItr->second;
93 }
94}
95
96
97bool SUSYObjDef_xAOD::emulateHLT(const std::string& triggerName) const {
98 std::scoped_lock lock (m_triggerCacheMutex);
99 // First, check if we've already tried using this trigger
100 auto funcItr = m_metTriggerFuncs.find(triggerName);
101 if (funcItr != m_metTriggerFuncs.end() )
102 return funcItr->second();
103
104 // Next, check that it really is a HLT MET trigger
105 if (triggerName.substr(0,6) != "HLT_xe") {
106 ATH_MSG_ERROR( "Requested trigger " << triggerName << " isn't a MET trigger! (HLT MET items should begin with 'HLT_xe'). Will return false." );
107 return false;
108 }
109
110 // Next, parse the name to work out which containers are needed to emulate the decision
111 std::vector<std::pair<int, std::string> > hypos; // algorithms and thresholds needed
112 std::string temp(triggerName);
113 // Note, we need to split on '_AND_' used for the combined mht+cell trigger
114 do {
115 auto pos = temp.find("_AND_");
116 std::string itemName = temp.substr(0, pos);
117 ATH_MSG_DEBUG( "Split trigger item " << itemName );
118 if (pos == std::string::npos)
119 temp = "";
120 else
121 temp = temp.substr(pos + 5);
122
123 std::regex expr("HLT_xe([[:digit:]]+)_?(mht|pufit|pueta|tc_lcw|)_?(?:L1XE([[:digit:]]+)|)");
124 std::smatch sm;
125 if (!std::regex_match(itemName, sm, expr) ) {
126 ATH_MSG_WARNING( "Regex reading for item " << itemName << " (" << triggerName << ") failed! Will be ignored!" );
127 continue;
128 }
129 if (sm.size() < 4) { // first object is the whole match, then there are three capture groups
130 ATH_MSG_WARNING( "Regex failed to capture the right groups for item " << itemName << " (" << triggerName << ") failed! Will be ignored!" );
131 for (unsigned int ii = 0; ii < sm.size(); ++ii) {
132 ATH_MSG_WARNING( sm[ii] );
133 }
134 continue;
135 }
136 int threshold = std::stoi(sm[1] );
137 std::string algKey = sm[2];
138 std::string metContBaseName = "HLT_xAOD__TrigMissingETContainer_TrigEFMissingET";
139 if (algKey.empty()) hypos.push_back(std::make_pair(threshold, metContBaseName) );
140 else if (algKey == "mht") hypos.push_back(std::make_pair(threshold, metContBaseName+"_mht") );
141 else if (algKey == "pufit") hypos.push_back(std::make_pair(threshold, metContBaseName+"_topocl_PUC") );
142 else if (algKey == "pueta") hypos.push_back(std::make_pair(threshold, metContBaseName+"_topocl_PS") );
143 else if (algKey == "tc_lcw") hypos.push_back(std::make_pair(threshold, metContBaseName+"topocl") );
144
145 ATH_MSG_DEBUG( "Container: " << hypos.back().second << ", Threshold: " << hypos.back().first );
146
147 if (sm[3] != "" && sm[3] != "50") {
148 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" );
149 // Note, now the L1 part is done in the previous section. However I'm keeping this warning here.
150 }
151 }
152 while (!temp.empty());
153
154 // Check if we have the containers and construct the lambda
155 // Already done the L1 decision - only care about HLT
156 std::function<bool()> lambda;
157 bool hasRequired = true;
158 if (hypos.empty()) lambda = [] () {return false;};
159 else {
160 for (const auto& pair : hypos) {
162 auto lambda_hypo = [this, pair] () {
163 const xAOD::TrigMissingETContainer* cont(nullptr);
164 if (evtStore()->retrieve(cont, pair.second) ) {
165 if (cont->empty()) return false;
166 float ex = cont->front()->ex() * 0.001;
167 float ey = cont->front()->ey() * 0.001;
168 float met = std::sqrt(ex*ex + ey*ey);
169 return met > pair.first;
170 }
171 else {
172 return false;
173 }
174 };
175 // an empty std::function evaluates to false
176 if (lambda) {
177 lambda = [lambda, lambda_hypo] () {
178 return lambda() && lambda_hypo();
179 };
180 }
181 else {
182 lambda = lambda_hypo;
183 }
184 }
185 else {
186 hasRequired = false;
187 ATH_MSG_WARNING( "Container: " << pair.second << " missing!" );
188 }
189 }
190 }
191 if (hasRequired) {
192 m_metTriggerFuncs[triggerName] = lambda;
193 return m_metTriggerFuncs.at(triggerName)();
194 }
195 // We can't get the exact trigger decision :( . Look for an alternative
196 std::vector<std::string> replacementTriggers({"HLT_xe110_mht_L1XE50", "HLT_xe100_mht_L1XE50", "HLT_xe90_mht_L1XE50", "HLT_xe70_mht"});
197 for (const std::string& trigName : replacementTriggers) {
198 if (isTrigInTDT(lock, trigName) ) {
199 ATH_MSG_WARNING( "Trigger " << triggerName << " not available and direct emulation impossible! Will use " << trigName << " instead!");
200 m_metTriggerFuncs[triggerName] = [this, trigName] () {
201 return m_trigDecTool->isPassed(trigName);
202 };
203 return m_metTriggerFuncs.at(triggerName)();
204 }
205 }
206 ATH_MSG_ERROR( "Cannot find the trigger in the menu, direct emulation is impossible and no replacement triggers are available! Will return false" );
207 m_metTriggerFuncs.at(triggerName) = [] () {return false;};
208 return m_metTriggerFuncs.at(triggerName)();
209}
210
211
212
213bool SUSYObjDef_xAOD::IsTrigPassed(const std::string& tr_item, unsigned int condition) const {
214 return m_trigDecTool->isPassed(tr_item, condition);
215}
216
217
218bool SUSYObjDef_xAOD::IsTrigMatched(const xAOD::IParticle *part, const std::string& tr_item) {
219 return this->IsTrigMatched({part}, tr_item);
220}
221
222
223bool SUSYObjDef_xAOD::IsTrigMatched(const xAOD::IParticle *part1, const xAOD::IParticle *part2, const std::string& tr_item) {
224 return this->IsTrigMatched({part1, part2}, tr_item);
225}
226
227
228bool SUSYObjDef_xAOD::IsTrigMatched(const std::vector<const xAOD::IParticle*>& v, const std::string& tr_item) {
229 return m_trigMatchingTool->match(v, tr_item);
230}
231
232
233bool SUSYObjDef_xAOD::IsTrigMatched(const std::initializer_list<const xAOD::IParticle*> &v, const std::string& tr_item) {
234 return m_trigMatchingTool->match(v, tr_item);
235}
236
237
238void SUSYObjDef_xAOD::TrigMatch(const xAOD::IParticle* p, std::initializer_list<std::string>::iterator i1, std::initializer_list<std::string>::iterator i2) {
239 dec_trigmatched(*p) = 0;
240
241 for(const auto *it = i1; it != i2; ++it) {
242 auto result = static_cast<int>(this->IsTrigMatched(p, *it));
243 dec_trigmatched(*p) += result;
244 const SG::Decorator<char> dec(*it);
245 dec(*p) = result;
246 }
247}
248
249
250void SUSYObjDef_xAOD::TrigMatch(const xAOD::IParticle* p, const std::initializer_list<std::string>& items) {
251 this->TrigMatch(p, items.begin(), items.end());
252}
253
254
255void SUSYObjDef_xAOD::TrigMatch(const xAOD::IParticle* p, const std::vector<std::string>& items) {
256 dec_trigmatched(*p) = 0;
257
258 for(const auto& item: items) {
259 auto result = static_cast<int>(this->IsTrigMatched(p, item));
260 dec_trigmatched(*p) += result;
261 const SG::Decorator<char> dec(item);
262 dec(*p) = result;
263 }
264}
265
266
267void SUSYObjDef_xAOD::TrigMatch(const std::initializer_list<const xAOD::IParticle*> &v, const std::initializer_list<std::string> &items) {
268 for(const auto& p : v) {
269 this->TrigMatch(p, items);
270 }
271}
272
273
274void SUSYObjDef_xAOD::TrigMatch(const std::initializer_list<const xAOD::IParticle*> &v, const std::vector<std::string>& items) {
275 for(const auto& p : v) {
276 this->TrigMatch(p, items);
277 }
278}
279
280
281void SUSYObjDef_xAOD::TrigMatch(const xAOD::IParticleContainer* v, const std::vector<std::string>& items) {
282 for(const auto p : *v) {
283 this->TrigMatch(p, items);
284 }
285}
286
287
288void SUSYObjDef_xAOD::TrigMatch(const xAOD::IParticleContainer* v, const std::initializer_list<std::string>& items) {
289 for(const auto p : *v) {
290 this->TrigMatch(p, items);
291 }
292}
293
294
295void SUSYObjDef_xAOD::TrigMatch(const xAOD::IParticle* p, const std::string& item) {
296 return this->TrigMatch(p, {item});
297}
298
299
300void SUSYObjDef_xAOD::TrigMatch(const xAOD::IParticleContainer* v, const std::string& item) {
301 return this->TrigMatch(v, {item});
302}
303
304
305void SUSYObjDef_xAOD::TrigMatch(const std::initializer_list<const xAOD::IParticle*> &v, const std::string& item) {
306 return this->TrigMatch(v, {item});
307}
308
309
310float SUSYObjDef_xAOD::GetTrigPrescale(const std::string & tr_item) const {
311 return m_trigDecTool->getPrescale(tr_item);
312}
313
314
315const Trig::ChainGroup* SUSYObjDef_xAOD::GetTrigChainGroup(const std::string& tr_item) const {
316 return m_trigDecTool->getChainGroup(tr_item);
317}
318
319
320 std::vector<std::string> SUSYObjDef_xAOD::GetTriggerOR(const std::string& trigExpr) const {
321
322 static const std::string delOR = "_OR_";
323 std::vector<std::string> trigchains = {};
324 std::string newtrigExpr = TString(trigExpr).Copy().ReplaceAll("||",delOR).Data();
325 newtrigExpr = TString(trigExpr).Copy().ReplaceAll(" ","").Data();
326
327 size_t pos = 0;
328 while ((pos = newtrigExpr.find(delOR)) != std::string::npos) {
329 trigchains.push_back( "HLT_"+newtrigExpr.substr(0, pos) );
330 newtrigExpr.erase(0, pos + delOR.length());
331 }
332 if(pos==std::string::npos)
333 trigchains.push_back("HLT_"+newtrigExpr);
334
335 return trigchains;
336 }
337
338 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, std::vector<std::string>& v_trigs23_cache, std::vector<std::string>& v_trigs24_cache) const {
339
340 // 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
341
342 static const std::string del15 = "_2015_";
343 static const std::string del16 = "_2016_";
344 static const std::string del17 = "_2017_";
345
346 size_t pos = 0;
347 std::string token15, token16, token17, token18, token22, token23, token24;
348
349 //get trigger tokens for 2015, 2016, 2017, 2018 and 2022, 2023, 2024
350 if ( (pos = trigExpr.find(del15)) != std::string::npos) {
351 trigExpr.erase(0, pos + del15.length());
352
353 pos = 0;
354 while ((pos = trigExpr.find(del16)) != std::string::npos) {
355 token15 = trigExpr.substr(0, pos);
356 token16 = trigExpr.erase(0, pos + del16.length() + del17.length() - 1);
357 // 2016-2018 use exact the same trigger string
358 token17 = token16;
359 token18 = token16;
360 }
361 }
362
363 // Find year positions (or npos if not present)
364 size_t p22 = trigExpr.find("2022");
365 size_t p23 = trigExpr.find("2023");
366 size_t p24 = trigExpr.find("2024");
367
368 auto next_pos = [&](size_t self) {
369 size_t next = std::string::npos;
370
371 if (self == p22) {
372 if (p23 > self && p23 < next) next = p23;
373 if (p24 > self && p24 < next) next = p24;
374 }
375 else if (self == p23) {
376 if (p22 > self && p22 < next) next = p22;
377 if (p24 > self && p24 < next) next = p24;
378 }
379 else if (self == p24) {
380 if (p22 > self && p22 < next) next = p22;
381 if (p23 > self && p23 < next) next = p23;
382 }
383
384 return next;
385 };
386
387 // Extract 2022,2023,2024 block
388 if (p22 != std::string::npos) {size_t end = next_pos(p22); token22 = trigExpr.substr(p22, end - p22);}
389 if (p23 != std::string::npos) {size_t end = next_pos(p23); token23 = trigExpr.substr(p23, end - p23);}
390 if (p24 != std::string::npos) {size_t end = next_pos(p24); token24 = trigExpr.substr(p24, end - p24);}
391
392 // Remove trailing underscores from tokens if present
393 std::string* toks[] = { &token22, &token23, &token24 };
394 for (auto t : toks) {
395 while (!t->empty() && t->back() == '_') t->pop_back();
396 }
397
398 //Redefine in case of custom user input
399 if(!m_isRun3){
400 if(token15.empty()) token15 = trigExpr;
401 if(token16.empty()) token16 = trigExpr;
402 if(token17.empty()) token17 = trigExpr;
403 if(token18.empty()) token18 = trigExpr;
404 }
405 else{
406 if(token22.empty()) token22 = trigExpr;
407 if(token23.empty()) token23 = trigExpr;
408 if(token24.empty()) token24 = trigExpr;
409 }
410
411 //get trigger chains for matching in 2015 and 2018
412 if(!m_isRun3){
413 v_trigs15_cache = GetTriggerOR(token15);
414 v_trigs16_cache = GetTriggerOR(token16);
415 v_trigs17_cache = GetTriggerOR(token17);
416 v_trigs18_cache = GetTriggerOR(token18);
417 }
418 //get trigger chains for matching in 2022
419 else{
420 v_trigs22_cache = GetTriggerOR(token22);
421 v_trigs23_cache = GetTriggerOR(token23);
422 v_trigs24_cache = GetTriggerOR(token24);
423 }
424 }
425
426 Trig::FeatureContainer SUSYObjDef_xAOD::GetTriggerFeatures(const std::string& chainName, unsigned int condition) const
427 {
428 return m_trigDecTool->features(chainName,condition);
429 }
430
431double SUSYObjDef_xAOD::GetTriggerGlobalEfficiencySF(const xAOD::ElectronContainer& electrons, const xAOD::MuonContainer& muons, const std::string& trigExpr) {
432
433 double trig_sf(1.);
434
435 if (trigExpr!="multiLepton" && trigExpr!="diLepton") {
436 ATH_MSG_ERROR( "Failed to retrieve multi-lepton trigger SF");
437 return trig_sf;
438 }
439
440 std::vector<const xAOD::Electron*> elec_trig;
441 for (const xAOD::Electron* electron : electrons) {
442 if (!acc_passOR(*electron)) continue;
443 if (!acc_signal(*electron)) continue;
444 elec_trig.push_back(electron);
445 }
446
447 std::vector<const xAOD::Muon*> muon_trig;
448 for (const xAOD::Muon* muon : muons) {
449 if (!acc_passOR(*muon)) continue;
450 if (!acc_signal(*muon)) continue;
451 muon_trig.push_back(muon);
452 }
453
454 bool matched = false;
455 if ((elec_trig.size()+muon_trig.size())>1 && trigExpr=="diLepton") {
456 if ( m_trigGlobalEffCorrTool_diLep->checkTriggerMatching( matched, elec_trig, muon_trig) != CP::CorrectionCode::Ok ) {
457 ATH_MSG_ERROR ("trigGlobEffCorrTool::Trigger matching could not be checked, interrupting execution.");
458 }
459 } else if ((elec_trig.size()+muon_trig.size())>2 && trigExpr=="multiLepton") {
460 if ( m_trigGlobalEffCorrTool_multiLep->checkTriggerMatching( matched, elec_trig, muon_trig) != CP::CorrectionCode::Ok ) {
461 ATH_MSG_ERROR ("trigGlobEffCorrTool::Trigger matching could not be checked, interrupting execution.");
462 }
463 }
464
466 if ((elec_trig.size()+muon_trig.size())>1 && trigExpr=="diLepton" && matched) {
467 result = m_trigGlobalEffCorrTool_diLep->getEfficiencyScaleFactor( elec_trig, muon_trig, trig_sf);
468 }
469 else if ((elec_trig.size()+muon_trig.size())>2 && trigExpr=="multiLepton" && matched) {
470 result = m_trigGlobalEffCorrTool_multiLep->getEfficiencyScaleFactor( elec_trig, muon_trig, trig_sf);
471 }
472
473 switch (result) {
475 ATH_MSG_ERROR( "Failed to retrieve multi-lepton trigger SF");
476 return 1.;
478 ATH_MSG_VERBOSE( "OutOfValidityRange found for multi-lepton trigger SF");
479 return 1.;
480 default:
481 break;
482 }
483
484 return trig_sf;
485}
486
487double SUSYObjDef_xAOD::GetTriggerGlobalEfficiencySFsys(const xAOD::ElectronContainer& electrons, const xAOD::MuonContainer& muons, const CP::SystematicSet& systConfig, const std::string& trigExpr) {
488
489 double sf(1.);
490
491 //Set the new systematic variation
492 if (trigExpr == "diLepton") {
493 StatusCode ret = m_trigGlobalEffCorrTool_diLep->applySystematicVariation(systConfig);
494 if (ret != StatusCode::SUCCESS) {
495 ATH_MSG_ERROR("Cannot configure TrigGlobalEfficiencyCorrectionTool (dilepton trigger) for systematic var. " << systConfig.name() );
496 }
497 }
498
499 if (trigExpr == "multiLepton") {
500 StatusCode ret = m_trigGlobalEffCorrTool_multiLep->applySystematicVariation(systConfig);
501 if (ret != StatusCode::SUCCESS) {
502 ATH_MSG_ERROR("Cannot configure TrigGlobalEfficiencyCorrectionTool (multi-lepton trigger) for systematic var. " << systConfig.name() );
503 }
504 }
505
506 //Get the SF for new config
507 sf = GetTriggerGlobalEfficiencySF (electrons, muons, trigExpr);
508
509 //Roll back to default
510 if (trigExpr == "diLepton") {
511 StatusCode ret = m_trigGlobalEffCorrTool_diLep->applySystematicVariation(m_currentSyst);
512 if (ret != StatusCode::SUCCESS) {
513 ATH_MSG_ERROR("Cannot configure TrigGlobalEfficiencyCorrectionTool (dilepton trigger) back to default.");
514 }
515 }
516 if (trigExpr == "multiLepton") {
517 StatusCode ret = m_trigGlobalEffCorrTool_multiLep->applySystematicVariation(m_currentSyst);
518 if (ret != StatusCode::SUCCESS) {
519 ATH_MSG_ERROR("Cannot configure TrigGlobalEfficiencyCorrectionTool (multi-lepton trigger) back to default.");
520 }
521 }
522
523 return sf;
524}
525
526//
527// GetTriggerGlobalEfficiencySF function is meant to be used for "asymmetric" diphoton trigger SFs
528//
529double SUSYObjDef_xAOD::GetTriggerGlobalEfficiencySF(const xAOD::PhotonContainer& photons, const std::string& trigExpr) {
530
531 double trig_sf(1.);
532
533 if (trigExpr!="diPhoton") {
534 ATH_MSG_ERROR( "Failed to retrieve diphoton trigger SF");
535 return trig_sf;
536 }
537
538 std::vector<const xAOD::Photon*> ph_trig;
539 for (const xAOD::Photon* photon : photons) {
540 if (!acc_passOR(*photon)) continue;
541 if (!acc_signal(*photon)) continue;
542 ph_trig.push_back(photon);
543 }
544
546 if (ph_trig.size()>1) {
547 result = m_trigGlobalEffCorrTool_diPhoton->getEfficiencyScaleFactor(ph_trig, trig_sf);
548 }
549
550 switch (result) {
552 ATH_MSG_ERROR( "Failed to retrieve diphoton trigger SF");
553 return 1.;
555 ATH_MSG_VERBOSE( "OutOfValidityRange found for diphoton trigger SF");
556 return 1.;
557 default:
558 break;
559 }
560
561 return trig_sf;
562}
563
564double SUSYObjDef_xAOD::GetTriggerGlobalEfficiencySFsys(const xAOD::PhotonContainer& photons, const CP::SystematicSet& systConfig, const std::string& trigExpr) {
565
566 double sf(1.);
567
568 //Set the new systematic variation
569 StatusCode ret = m_trigGlobalEffCorrTool_diPhoton->applySystematicVariation(systConfig);
570 if (ret != StatusCode::SUCCESS) {
571 ATH_MSG_ERROR("Cannot configure TrigGlobalEfficiencyCorrectionTool (diphoton trigger) for systematic var. " << systConfig.name() );
572 }
573
574 //Get the SF for new config
575 sf = GetTriggerGlobalEfficiencySF (photons, trigExpr);
576
577 //Roll back to default
578 ret = m_trigGlobalEffCorrTool_diPhoton->applySystematicVariation(m_currentSyst);
579 if (ret != StatusCode::SUCCESS) {
580 ATH_MSG_ERROR("Cannot configure TrigGlobalEfficiencyCorrectionTool (diphoton trigger) back to default.");
581 }
582
583 return sf;
584}
585
586double SUSYObjDef_xAOD::GetTriggerGlobalEfficiency(const xAOD::ElectronContainer& electrons, const xAOD::MuonContainer& muons, const std::string& trigExpr) {
587
588 double trig_eff(1.);
589 double trig_eff_data(1.);
590
591 if (trigExpr!="multiLepton" && trigExpr!="diLepton") {
592 ATH_MSG_ERROR( "Failed to retrieve multi-lepton trigger efficiency");
593 return trig_eff;
594 }
595
596 std::vector<const xAOD::Electron*> elec_trig;
597 for (const xAOD::Electron* electron : electrons) {
598 if (!acc_passOR(*electron)) continue;
599 if (!acc_signal(*electron)) continue;
600 elec_trig.push_back(electron);
601 }
602
603 std::vector<const xAOD::Muon*> muon_trig;
604 for (const xAOD::Muon* muon : muons) {
605 if (!acc_passOR(*muon)) continue;
606 if (!acc_signal(*muon)) continue;
607 muon_trig.push_back(muon);
608 }
609
610 bool matched = false;
611 if ((elec_trig.size()+muon_trig.size())>1 && trigExpr=="diLepton") {
612 if ( m_trigGlobalEffCorrTool_diLep->checkTriggerMatching( matched, elec_trig, muon_trig) != CP::CorrectionCode::Ok ) {
613 ATH_MSG_ERROR ("trigGlobEffCorrTool::Trigger matching could not be checked, interrupting execution.");
614 }
615 } else if ((elec_trig.size()+muon_trig.size())>2 && trigExpr=="multiLepton") {
616 if ( m_trigGlobalEffCorrTool_multiLep->checkTriggerMatching( matched, elec_trig, muon_trig) != CP::CorrectionCode::Ok ) {
617 ATH_MSG_ERROR ("trigGlobEffCorrTool::Trigger matching could not be checked, interrupting execution.");
618 }
619 }
620
622 if ((elec_trig.size()+muon_trig.size())>1 && trigExpr=="diLepton" && matched) {
623 result = m_trigGlobalEffCorrTool_diLep->getEfficiency( elec_trig, muon_trig, trig_eff_data, trig_eff);
624 }
625 else if ((elec_trig.size()+muon_trig.size())>2 && trigExpr=="multiLepton" && matched) {
626 result = m_trigGlobalEffCorrTool_multiLep->getEfficiency( elec_trig, muon_trig, trig_eff_data, trig_eff);
627 }
628
629 switch (result) {
631 ATH_MSG_ERROR( "Failed to retrieve multi-lepton trigger efficiency");
632 return 1.;
634 ATH_MSG_VERBOSE( "OutOfValidityRange found for multi-lepton trigger efficiency");
635 return 1.;
636 default:
637 break;
638 }
639
640 if (isData()) return trig_eff_data;
641 else return trig_eff;
642}
643
644//
645// GetTriggerGlobalEfficiency function is meant to be used for "asymmetric" diphoton trigger SFs
646//
647double SUSYObjDef_xAOD::GetTriggerGlobalEfficiency(const xAOD::PhotonContainer& photons, const std::string& trigExpr) {
648
649 double trig_eff(1.);
650 double trig_eff_data(1.);
651
652 if (trigExpr!="diPhoton") {
653 ATH_MSG_ERROR( "Failed to retrieve diphoton trigger efficiency");
654 return trig_eff;
655 }
656
657 std::vector<const xAOD::Photon*> ph_trig;
658 for (const xAOD::Photon* photon : photons) {
659 if (!acc_passOR(*photon)) continue;
660 if (!acc_signal(*photon)) continue;
661 ph_trig.push_back(photon);
662 }
663
665 if (ph_trig.size()>1) {
666 result = m_trigGlobalEffCorrTool_diPhoton->getEfficiency(ph_trig, trig_eff_data, trig_eff);
667 }
668
669 switch (result) {
671 ATH_MSG_ERROR( "Failed to retrieve diphoton trigger efficiency");
672 return 1.;
674 ATH_MSG_VERBOSE( "OutOfValidityRange found for diphoton trigger efficiency");
675 return 1.;
676 default:
677 break;
678 }
679
680 if (isData()) return trig_eff_data;
681 else return trig_eff;
682}
683
684}
685
#define ATH_MSG_ERROR(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
ServiceHandle< StoreGateSvc > & evtStore()
Return value from object correction CP tools.
@ Error
Some error happened during the object correction.
@ OutOfValidityRange
Input object is out of validity range.
@ Ok
The correction was done successfully.
Class to wrap a set of SystematicVariations.
std::string name() const
returns: the systematics joined into a single string.
const T * front() const
Access the first element in the collection as an rvalue.
bool empty() const noexcept
Returns true if the collection is empty.
Helper class to provide type-safe access to aux data.
Definition Decorator.h:59
asg::AnaToolHandle< Trig::TrigDecisionTool > m_trigDecTool
asg::AnaToolHandle< ITrigGlobalEfficiencyCorrectionTool > m_trigGlobalEffCorrTool_multiLep
bool IsMETTrigPassed(unsigned int runnumber=0, bool j400_OR=false) const override final
Definition Trigger.cxx:30
asg::AnaToolHandle< ITrigGlobalEfficiencyCorrectionTool > m_trigGlobalEffCorrTool_diPhoton
bool isData() const override final
unsigned int GetRunNumber() const override final
void GetTriggerTokens(std::string, std::vector< std::string > &, std::vector< 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:338
asg::AnaToolHandle< Trig::IMatchingTool > m_trigMatchingTool
const Trig::ChainGroup * GetTrigChainGroup(const std::string &) const override final
Definition Trigger.cxx:315
float GetTrigPrescale(const std::string &) const override final
Definition Trigger.cxx:310
int treatAsYear(const int runNumber=-1) const override final
std::vector< std::string > GetTriggerOR(const std::string &trigExpr) const
Definition Trigger.cxx:320
CP::SystematicSet m_currentSyst
bool IsTrigPassed(const std::string &, unsigned int condition=TrigDefs::Physics) const override final
Definition Trigger.cxx:213
double GetTriggerGlobalEfficiency(const xAOD::ElectronContainer &electrons, const xAOD::MuonContainer &muons, const std::string &trigExpr="diLepton") override final
Definition Trigger.cxx:586
bool IsTrigMatched(const xAOD::IParticle *part, const std::string &tr_item) override final
Definition Trigger.cxx:218
double GetTriggerGlobalEfficiencySF(const xAOD::ElectronContainer &electrons, const xAOD::MuonContainer &muons, const std::string &trigExpr="diLepton") override final
Definition Trigger.cxx:431
std::mutex m_triggerCacheMutex
Trig::FeatureContainer GetTriggerFeatures(const std::string &chainName="EF_.*", unsigned int condition=TrigDefs::Physics) const
Definition Trigger.cxx:426
asg::AnaToolHandle< ITrigGlobalEfficiencyCorrectionTool > m_trigGlobalEffCorrTool_diLep
bool emulateHLT(const std::string &triggerName) const
Definition Trigger.cxx:97
double GetTriggerGlobalEfficiencySFsys(const xAOD::ElectronContainer &electrons, const xAOD::MuonContainer &muons, const CP::SystematicSet &systConfig, const std::string &trigExpr="diLepton") override final
Definition Trigger.cxx:487
bool isTrigInTDT(std::scoped_lock< std::mutex > &lock, const std::string &triggerName) const
Definition Trigger.cxx:83
void TrigMatch(const xAOD::IParticle *p, std::initializer_list< std::string >::iterator, std::initializer_list< std::string >::iterator) override final
Definition Trigger.cxx:238
Class providing the definition of the 4-vector interface.
float ex() const
Get the x component of the missing energy.
float ey() const
Get the y component of the missing energy.
bool contains(const std::string &s, const std::string &regx)
does a string contain the substring
Definition hcg.cxx:114
static std::vector< uint32_t > runnumber
Definition iLumiCalc.h:37
static const SG::ConstAccessor< char > acc_signal("signal")
static const SG::Decorator< char > dec_trigmatched("trigmatched")
static const SG::ConstAccessor< char > acc_passOR("passOR")
helper namespace for calculating deltaR for unknown object types
Definition part1.py:1
Definition part2.py:1
PhotonContainer_v1 PhotonContainer
Definition of the current "photon container version".
TrigMissingETContainer_v1 TrigMissingETContainer
DataVector of TrigMissingET - the current version.
ElectronContainer_v1 ElectronContainer
Definition of the current "electron container version".
Muon_v1 Muon
Reference the current persistent version:
Photon_v1 Photon
Definition of the current "egamma version".
setBGCode setTAP setLVL2ErrorBits bool
MuonContainer_v1 MuonContainer
Definition of the current "Muon container version".
Electron_v1 Electron
Definition of the current "egamma version".
DataVector< IParticle > IParticleContainer
Simple convenience declaration of IParticleContainer.