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