ATLAS Offline Software
TopTriggerCPTools.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3  */
4 
6 
7 #include <map>
8 #include <set>
9 #include <string>
10 #include <vector>
11 #include <unordered_map>
12 
13 // Top includes
15 #include "TopEvent/EventTools.h"
16 
17 // PathResolver include(s):
19 
20 // Trigger include(s):
32 #include "PATCore/PATCoreEnums.h"
33 #include "xAODBase/ObjectType.h"
34 #include <boost/algorithm/string.hpp>
35 #include <boost/algorithm/string/join.hpp>
36 
37 namespace top {
38  TriggerCPTools::TriggerCPTools(const std::string& name) :
39  asg::AsgTool(name) {
40  declareProperty("config", m_config);
41 
42  declareProperty("TrigConfigTool", m_trigConfTool);
43  declareProperty("TrigDecisionTool", m_trigDecisionTool);
44  declareProperty("TrigMatchTool", m_trigMatchTool);
45  declareProperty("GlobalTriggerEffTool", m_globalTriggerEffTool);
46  declareProperty("GlobalTriggerEffToolLoose", m_globalTriggerEffToolLoose);
47 
48  m_muonTool = asg::AnaToolHandle<CP::IMuonTriggerScaleFactors>("CP::MuonTriggerScaleFactors/MuonTrigEff");
49  m_muonToolLoose = asg::AnaToolHandle<CP::IMuonTriggerScaleFactors>("CP::MuonTriggerScaleFactors/MuonTrigEffLoose");
50  }
51 
53  ATH_MSG_INFO("top::TriggerCPTools initialize...");
54 
55  if (m_config->makeAllCPTools()) {
56  if (!m_config->isTruthDxAOD()) {
58  const std::string trig_config_name = "xAODConfigTool";
59  if (asg::ToolStore::contains<TrigConf::ITrigConfigTool>(trig_config_name)) {
60  m_trigConfTool = asg::ToolStore::get<TrigConf::ITrigConfigTool>(trig_config_name);
61  } else {
62  TrigConf::xAODConfigTool* configTool = new TrigConf::xAODConfigTool(trig_config_name);
63  top::check(configTool->initialize(), "Failed to initialize trigger config tool");
64  m_trigConfTool = configTool;
65  }
66 
68  const std::string trig_decision_name = "TrigDecisionTool";
69  if (asg::ToolStore::contains<Trig::TrigDecisionTool>(trig_decision_name)) {
70  m_trigDecisionTool = asg::ToolStore::get<Trig::TrigDecisionTool>(trig_decision_name);
71  } else {
72  Trig::TrigDecisionTool* trigDecTool = new Trig::TrigDecisionTool(trig_decision_name);
73  top::check(trigDecTool->setProperty("ConfigTool", m_trigConfTool), "Failed to setProperty");
74  top::check(trigDecTool->setProperty("TrigDecisionKey", "xTrigDecision"), "Failed to setProperty");
75  if (m_config->isRun3()) {
76  top::check(trigDecTool->setProperty("NavigationFormat", "TrigComposite"), "Failed to setProperty"); // Read Run 3 navigation (options are "TrigComposite" for R3 or "TriggElement" for R2, R2 navigation is not kept in most DAODs)
77  top::check(trigDecTool->setProperty("HLTSummary", "HLTNav_Summary_DAODSlimmed"), "Failed to setProperty"); // Name of R3 navigation container (if reading from AOD, then "HLTNav_Summary_AODSlimmed" instead)
78  }
79  top::check(trigDecTool->initialize(), "Failed to initialize trigger decision tool");
80  m_trigDecisionTool = trigDecTool;
81  }
82 
83  if (m_config->isRun3()) {
84  static const std::string trigger_scoring_tool_name = "Trig::DRScoringTool";
85  if (asg::ToolStore::contains<Trig::IMatchScoringTool>(trigger_scoring_tool_name)) {
86  m_trigScoringTool = asg::ToolStore::get<Trig::IMatchScoringTool>(trigger_scoring_tool_name);
87  } else {
88  Trig::DRScoringTool* trigScoringTool = new Trig::DRScoringTool(trigger_scoring_tool_name);
89  top::check(trigScoringTool->initialize(), "Failed to initialize trig. scoring tool");
90  m_trigScoringTool = trigScoringTool;
91  }
92  }
93 
94  // Trigger matching tool
95  static const std::string trig_match_name = "MatchingTool";
96  if (asg::ToolStore::contains<Trig::IMatchingTool>(trig_match_name)) {
97  m_trigMatchTool = asg::ToolStore::get<Trig::IMatchingTool>(trig_match_name);
98  } else {
99  if (m_config->isRun3()) {
100  Trig::R3MatchingTool* trigMatchTool = new Trig::R3MatchingTool(trig_match_name);
101  top::check(trigMatchTool->initialize(), "Failed to initialize trig. matching tool");
102  m_trigMatchTool = trigMatchTool;
103  } else {
104  Trig::MatchFromCompositeTool* trigMatchTool = new Trig::MatchFromCompositeTool(trig_match_name);
105  top::check(trigMatchTool->setProperty("RemapBrokenLinks", m_config->triggerMatchingElementRelink()),
106  "Failed to remap broken links for the trig. maching tool");
107  top::check(trigMatchTool->initialize(),
108  "Failed to initialize trig. matching tool");
109  m_trigMatchTool = trigMatchTool;
110  }
111  }
112 
114  if (m_config->useTaus()) {
115  const std::string tauMatchName = "TrigTauMatchingTool";
116  if (asg::ToolStore::contains<Trig::ITrigTauMatchingTool>(tauMatchName)) {
117  m_trigMatchTauTool = asg::ToolStore::get<Trig::ITrigTauMatchingTool>(tauMatchName);
118  } else {
119  Trig::TrigTauMatchingTool* trigMatchTauTool = new Trig::TrigTauMatchingTool(tauMatchName);
120  top::check(trigMatchTauTool->setProperty("TrigDecisionTool", m_trigDecisionTool),
121  "Failed to set trig dec tool for tau matching");
122  top::check(trigMatchTauTool->initialize(),
123  "Failed to initialize tau trigger matching tool");
124  m_trigMatchTauTool = trigMatchTauTool;
125  }
126  }
128  if (m_config->useGlobalTrigger()) {
130  "Failed to construct global trigger efficiencies");
131  }
132  } else {
133  ATH_MSG_INFO("top::TriggerCPTools: no need to initialise anything on truth DxAOD");
134  }
135  } else {
136  ATH_MSG_INFO("top::TriggerCPTools: no need to initialise anything in mini-xAOD mode");
137  }
138 
139  return StatusCode::SUCCESS;
140  }
141 
143  StatusCode statusCode = StatusCode::SUCCESS;
144 
145  // utilities for TrigGlobEffCorr::ImportData
146  TrigGlobEffCorr::ImportData triggerData;
147  top::check(triggerData.importTriggers(), "failed to import trigger data");
148  auto const& triggerDict = triggerData.getDictionary();
149  std::unordered_map<std::string, TrigGlobEffCorr::ImportData::TrigDef> triggerDefs;
150  for (auto&& kv : triggerData.getTriggerDefs()) {
151  auto it = triggerDict.find(kv.first);
152  if (it != triggerDict.end()) {
153  triggerDefs[it->second] = kv.second;
154  }
155  }
156  auto getTriggerLegs =
157  [&](std::unordered_map<std::string, std::vector<std::pair<std::string, int> > > const& triggerCombination,
158  std::unordered_map<std::string, std::set<std::string> >& electronLegsByPeriod,
159  std::unordered_map<std::string, std::set<std::string> >& photonLegsByPeriod) {
160  for (auto&& kv : triggerCombination) {
161  std::string const& period = kv.first;
162  for (auto const& trigKey : kv.second) {
163  auto triggerDefsIt = triggerDefs.find(trigKey.first);
164  if (triggerDefsIt == triggerDefs.end()) {
165  statusCode = StatusCode::FAILURE;
166  ATH_MSG_ERROR("unrecognized trigger `" << trigKey.first << "'");
167  continue;
168  }
169  auto const& trigDef = triggerDefsIt->second;
170  for (auto const& leg : trigDef.leg) {
171  if (!leg) continue;
172  std::string const& legname = triggerDict.at(leg);
173  bool ok = true;
174  xAOD::Type::ObjectType legtype = triggerData.associatedLeptonFlavour(legname, ok);
175  if (!ok) {
176  statusCode = StatusCode::FAILURE;
177  ATH_MSG_ERROR("could not determine object type for trigger leg `" << legname <<
178  "'");
179  continue;
180  }
181  switch (legtype) {
183  electronLegsByPeriod[period].insert(legname);
184  break;
185 
186  case xAOD::Type::Muon:
187  break;
188 
189  case xAOD::Type::Photon:
190  photonLegsByPeriod[period].insert(legname);
191  break;
192 
193  default:
194  statusCode = StatusCode::FAILURE;
196  "trigger leg `" << legname << "' has unsupported object type `" << legtype << "'");
197  continue;
198  }
199  }
200  }
201  }
202  };
203 
204  // Get trigger strings from configuration
205  std::map<std::string, std::string> triggerCombination, triggerCombinationLoose;
206  std::vector<std::string> electronSystematics, muonSystematics, photonSystematics, electronToolNames, muonToolNames, photonToolNames;
207  std::unordered_map<std::string, std::vector<std::pair<std::string, int> > > const emptymap;
208  std::unordered_map<std::string, std::vector<std::pair<std::string, int> > > const&
209  triggersByPeriod = (m_config->doTightEvents() ? m_config->getGlobalTriggers() : emptymap),
210  triggersByPeriodLoose = (m_config->doLooseEvents() ? m_config->getGlobalTriggersLoose() : emptymap);
211 
212  std::unordered_map<std::string, std::set<std::string> > electronLegsByPeriod, electronLegsByPeriodLoose, photonLegsByPeriod, photonLegsByPeriodLoose;
213  getTriggerLegs(triggersByPeriod, electronLegsByPeriod, photonLegsByPeriod);
214  getTriggerLegs(triggersByPeriodLoose, electronLegsByPeriodLoose, photonLegsByPeriodLoose);
215 
216  // Get quality
217  std::string electronID, electronIDLoose, electronIsolation, electronIsolationLoose, muonQuality, muonQualityLoose;
218  std::string photonIso, photonIsoLoose;
219  if (m_config->doTightEvents()) {
220  electronID = m_config->electronID();
221  electronIsolation = m_config->electronIsolationSF();
222  muonQuality = m_config->muonQuality();
223  photonIso = m_config->photonIsolation();
224  }
225  if (m_config->doLooseEvents()) {
226  electronIDLoose = m_config->electronIDLoose();
227  electronIsolationLoose = m_config->electronIsolationSFLoose();
228  muonQualityLoose = m_config->muonQualityLoose();
229  photonIsoLoose = m_config->photonIsolationLoose();
230  }
231 
232  // Tidy name for e/gamma
233  electronID = mapWorkingPoints(electronID);
234  electronIDLoose = mapWorkingPoints(electronIDLoose);
235  // This is hopefully only temporary
236  electronIsolation = mapWorkingPoints(electronIsolation);
237  electronIsolationLoose = mapWorkingPoints(electronIsolationLoose);
238 
239  // Create electron trigger SF and Eff tools
240  ToolHandleArray<IAsgElectronEfficiencyCorrectionTool> electronEffTools, electronSFTools, electronEffToolsLoose,
241  electronSFToolsLoose;
242  std::map<std::string, std::string> legsPerTool, legsPerToolLoose;
243  int nTools = 0;
244 
245  // Loop over the triggers found (electrons - tight)
246  for (auto& y_t : electronLegsByPeriod) {
247  std::string year = y_t.first;
248  for (auto& trigKey : y_t.second) {
249  nTools++;
250  for (int j = 0; j < 2; ++j) { // one tool instance for efficiencies, another for scale factors
251  ATH_MSG_INFO("TIGHT " << year << " " << trigKey << " " << electronID << " " << electronIsolation);
252  auto t = m_electronToolsFactory.emplace(
253  m_electronToolsFactory.end(), "AsgElectronEfficiencyCorrectionTool/ElTrigEff_" + std::to_string(
254  j) + "_" + std::to_string(nTools));
255  if (!m_config->isRun3()) {
256  top::check(t->setProperty("MapFilePath",
257  "ElectronEfficiencyCorrection/2015_2018/rel21.2/Precision_Summer2020_v1/map4.txt"),
258  "Fail");
259  }
260  top::check(t->setProperty("TriggerKey",
261  (j ? year + "_" + trigKey : "Eff_" + year + "_" + trigKey)),
262  "Failed to set TriggerKey");
263  if (electronID != "None") top::check(t->setProperty("IdKey", electronID), "Failed to set IdKey");
264  if (electronIsolation != "None") top::check(t->setProperty("IsoKey",
265  electronIsolation), "Failed to set IsoKey");
266  top::check(t->setProperty("CorrelationModel", "TOTAL"), "Failed to set CorrelationModel");
267  top::check(t->setProperty("ForceDataType",
268  (int) PATCore::ParticleDataType::Full), "Failed to set ForceDataType");
269  top::check(t->setProperty("OutputLevel", MSG::INFO), "Failed to set OutputLevel");
270  top::check(t->initialize(), "Failed to initalise");
271  // Using syntax from examples
272  auto& handles = j ? electronSFTools : electronEffTools;
273  handles.push_back(t->getHandle());
274  std::string name = handles[handles.size() - 1].name();
275  legsPerTool[name] = trigKey + " [" + year + "]";
276  ATH_MSG_INFO("TIGHT " << name << " -> " << trigKey);
277  electronToolNames.push_back(name);
278  // Special - Record the systematic names from the efficiency tool (not SF tool)
279  if (electronSystematics.size() == 0 && j == 1) {
280  for (auto& s :
281  handles[handles.size() - 1]->recommendedSystematics().getBaseNames()) electronSystematics.push_back(s);
282 
283  }
284  }
285  }
286  }
287 
288  // Loop over the triggers found (electrons - loose)
289  nTools = 0;
290  for (auto& y_t : electronLegsByPeriodLoose) {
291  std::string year = y_t.first;
292  for (auto& trigKey : y_t.second) {
293  nTools++;
294  for (int j = 0; j < 2; ++j) { // one tool instance for efficiencies, another for scale factors
295  ATH_MSG_INFO("LOOSE " << year << " " << trigKey << " " << electronIDLoose << " " << electronIsolationLoose);
296  auto tLoose = m_electronToolsFactoryLoose.emplace(
297  m_electronToolsFactoryLoose.end(), "AsgElectronEfficiencyCorrectionTool/ElTrigEffLoose_" + std::to_string(
298  j) + "_" + std::to_string(nTools));
299  if (!m_config->isRun3()) {
300  top::check(tLoose->setProperty("MapFilePath",
301  "ElectronEfficiencyCorrection/2015_2018/rel21.2/Precision_Summer2020_v1/map4.txt"),
302  "Fail");
303  }
304  top::check(tLoose->setProperty("TriggerKey",
305  (j ? year + "_" + trigKey : "Eff_" + year + "_" + trigKey)),
306  "Failed to set TriggerKey");
307  if (electronIDLoose !=
308  "None") top::check(tLoose->setProperty("IdKey", electronIDLoose), "Failed to set IdKey");
309  if (electronIsolationLoose != "None") top::check(tLoose->setProperty("IsoKey",
310  electronIsolationLoose),
311  "Failed to set IsoKey");
312  top::check(tLoose->setProperty("CorrelationModel", "TOTAL"), "Failed to set CorrelationModel");
313  top::check(tLoose->setProperty("ForceDataType",
314  (int) PATCore::ParticleDataType::Full), "Failed to set ForceDataType");
315  top::check(tLoose->setProperty("OutputLevel", MSG::INFO), "Failed to set OutputLevel");
316  top::check(tLoose->initialize(), "Failed to initalise");
317  // Using syntax from examples
318  auto& handlesLoose = j ? electronSFToolsLoose : electronEffToolsLoose;
319  handlesLoose.push_back(tLoose->getHandle());
320  std::string name = handlesLoose[handlesLoose.size() - 1].name();
321  legsPerToolLoose[name] = trigKey + " [" + year + "]";
322  ATH_MSG_INFO("LOOSE " << name << " -> " << trigKey);
323  electronToolNames.push_back(name);
324  // Special - Record the systematic names from the efficiency tool (not SF tool)
325  if (electronSystematics.size() == 0 && j == 1) {
326  for (auto& s :
327  handlesLoose[handlesLoose.size() -
328  1]->recommendedSystematics().getBaseNames()) electronSystematics.push_back(s);
329  }
330  }
331  }
332  }
333 
334  // Create muon trigger SF tool
335  ToolHandleArray<CP::IMuonTriggerScaleFactors> muonTools;
336  ToolHandleArray<CP::IMuonTriggerScaleFactors> muonToolsLoose;
337 
338  if (m_config->doTightEvents()) {
339  if (muonQuality != "None") top::check(m_muonTool.setProperty("MuonQuality",
340  muonQuality), "Failed to set MuonQuality");
341  top::check(m_muonTool.setProperty("AllowZeroSF", true), "Failed to set AllowZeroSF");
342  if (m_config->muonSFCustomInputFolderTrigger() != " ") {
343  top::check(m_muonTool.setProperty("CustomInputFolder", m_config->muonSFCustomInputFolderTrigger()), "Failed to set CustomInputFolder property for MuonTriggerScaleFactors tool");
344  }
345  if (m_config->muonForcePeriod() != " ") {
346  top::check(m_muonTool.setProperty("forcePeriod", m_config->muonForcePeriod()), "Failed to set forcePeriod property for MuonTriggerScaleFactors tool");
347  } else{
348  top::check(m_muonTool.setProperty("forcePeriod", ""), "Failed to set forcePeriod property for MuonTriggerScaleFactors tool");
349  }
350  if (m_config->muonForceYear() != -1) {
351  top::check(m_muonTool.setProperty("forceYear", m_config->muonForceYear()), "Failed to set forceYear property for MuonTriggerScaleFactors tool");
352  }
353  top::check(m_muonTool.initialize(), "Failed to initialise");
354  muonTools.push_back(m_muonTool.getHandle());
355  ATH_MSG_INFO("Muon tool name (tight) " << muonTools[muonTools.size() - 1].name());
356  muonToolNames.push_back(muonTools[muonTools.size() - 1].name());
357  // Special - Get muon systematics
358  if (muonSystematics.size() == 0) {
359  for (auto& s:
360  muonTools[muonTools.size() - 1]->recommendedSystematics().getBaseNames()) muonSystematics.push_back(s);
361  }
362  }
363 
364  if (m_config->doLooseEvents()) {
365  if (muonQualityLoose != "None") top::check(m_muonToolLoose.setProperty("MuonQuality",
366  muonQualityLoose),
367  "Failed to set MuonQuality");
368  top::check(m_muonToolLoose.setProperty("AllowZeroSF", true), "Failed to set AllowZeroSF");
369  if (m_config->muonSFCustomInputFolderTrigger() != " ") {
370  top::check(m_muonToolLoose.setProperty("CustomInputFolder", m_config->muonSFCustomInputFolderTrigger()), "Failed to set CustomInputFolder property for MuonTriggerScaleFactors loose tool");
371  }
372  top::check(m_muonToolLoose.initialize(), "Failed to initialise");
373  muonToolsLoose.push_back(m_muonToolLoose.getHandle());
374  ATH_MSG_INFO("Muon tool name (loose) " << muonToolsLoose[muonToolsLoose.size() - 1].name());
375  muonToolNames.push_back(muonToolsLoose[muonToolsLoose.size() - 1].name());
376  // Special - Get muon systematics
377  if (muonSystematics.size() == 0) {
378  for (auto& s: muonToolsLoose[muonToolsLoose.size() - 1]->recommendedSystematics().getBaseNames()) muonSystematics.push_back(s);
379  }
380  }
381 
382  // Setup photon tools
383  ToolHandleArray<IAsgPhotonEfficiencyCorrectionTool> photonEffTools;
384  ToolHandleArray<IAsgPhotonEfficiencyCorrectionTool> photonSFTools;
385  ToolHandleArray<IAsgPhotonEfficiencyCorrectionTool> photonEffToolsLoose;
386  ToolHandleArray<IAsgPhotonEfficiencyCorrectionTool> photonSFToolsLoose;
387 
388  const std::string photonKey = PhotonKeys(triggersByPeriod);
389  const std::string photonKeyLoose = PhotonKeys(triggersByPeriodLoose);
390 
391  static const std::string mapPath = "PhotonEfficiencyCorrection/2015_2018/rel21.2/Summer2020_Rec_v1/map2.txt";
392  if (photonKey != "" || photonKeyLoose != "") {
393  if (m_config->doTightEvents()) {
394  nTools = 0;
395  top::check(CheckPhotonIsolation(photonIso), "Unsupported photon isolation for photon triggers provided: " + photonIso);
396  for (auto& y_t : photonLegsByPeriod) {
397  const std::string year = y_t.first;
398  for (auto& trigKey : y_t.second) {
399  nTools++;
400  for(int j=0;j<2;++j) {
401  const std::string nameTool = "AsgPhotonEfficiencyCorrectionTool/" + std::string(j? "PhTrigEff" : "PhTrigSF") + "_" + std::to_string(nTools);
402  auto t = m_photonToolsFactory.emplace(m_photonToolsFactory.end(), nameTool);
403  top::check(t->setProperty("MapFilePath", mapPath.c_str()), "Cannot set MapFilePath");
404  top::check(t->setProperty("TriggerKey", std::string(j ? "" : "Eff_") + photonKey), "Cannot set TriggerKey");
405  top::check(t->setProperty("IsoKey", photonIso), "Cannot set IsoKey");
406  top::check(t->setProperty("ForceDataType", (int)PATCore::ParticleDataType::Full), "Cannot set ForceDataType");
407  top::check(t->setProperty("OutputLevel", MSG::ERROR), "Cannot set OutputLevel");
408  top::check(t->initialize(), "Cannot initialise the photon tools");
409  auto& photonHandles = (j? photonSFTools : photonEffTools);
410  photonHandles.push_back(t->getHandle());
411  const std::string name = photonHandles.back().name();
412  legsPerTool[name] = trigKey + " [" + year + "]";
413  photonToolNames.push_back(name);
414  if (photonSystematics.size() == 0 && j == 1) {
415  for (const auto& s : photonHandles.back()->recommendedSystematics().getBaseNames()) {
416  photonSystematics.push_back(s);
417  }
418  }
419  }
420  }
421  }
422  }
423 
424  if (m_config->doLooseEvents()) {
425  nTools = 0;
426  top::check(CheckPhotonIsolation(photonIsoLoose), "Unsupported photon isolation for photon triggers provided: " + photonIsoLoose);
427  for (auto& y_t : photonLegsByPeriodLoose) {
428  const std::string year = y_t.first;
429  for (auto& trigKey : y_t.second) {
430  nTools++;
431  for(int j=0;j<2;++j) {
432  const std::string nameTool = "AsgPhotonEfficiencyCorrectionTool/" + std::string(j? "PhTrigEff" : "PhTrigSF") + "_" + std::to_string(nTools);
433  auto tLoose = m_photonToolsFactoryLoose.emplace(m_photonToolsFactoryLoose.end(), nameTool);
434  top::check(tLoose->setProperty("MapFilePath", mapPath.c_str()), "Cannot set MapFilePath");
435  top::check(tLoose->setProperty("TriggerKey", std::string(j ? "" : "Eff_") + photonKeyLoose), "Cannot set TriggerKey");
436  top::check(tLoose->setProperty("IsoKey", photonIsoLoose), "Cannot set IsoKey");
437  top::check(tLoose->setProperty("ForceDataType", (int)PATCore::ParticleDataType::Full), "Cannot set ForceDataType");
438  top::check(tLoose->setProperty("OutputLevel", MSG::ERROR), "Cannot set OutputLevel");
439  top::check(tLoose->initialize(), "Cannot initialise the photon tools");
440  auto& photonHandlesLoose = (j? photonSFToolsLoose : photonEffToolsLoose);
441  photonHandlesLoose.push_back(tLoose->getHandle());
442  const std::string name = photonHandlesLoose.back().name();
443  legsPerToolLoose[name] = trigKey + " [" + year + "]";
444  photonToolNames.push_back(name);
445  if (photonSystematics.size() == 0 && j == 1) {
446  for (const auto& s : photonHandlesLoose.back()->recommendedSystematics().getBaseNames()) {
447  photonSystematics.push_back(s);
448  }
449  }
450  }
451  }
452  }
453  }
454  }
455 
456  auto combineStrings = [](const std::vector<std::pair<std::string, int> >& input ) {
457  std::vector<std::string> tmp;
458  for (const auto& i : input) {
459  tmp.push_back(i.first);
460  }
461  return boost::algorithm::join(tmp, " || ");
462  };
463 
464  for (auto& key : triggersByPeriod) {
465  if (triggerCombination.find(key.first) == triggerCombination.end()) {
466  triggerCombination[key.first] = "";
467  } else {
468  triggerCombination[key.first] += " || ";
469  }
470  triggerCombination[key.first] += combineStrings(key.second);
471  }
472  for (auto& key : triggersByPeriodLoose) {
473  if (triggerCombinationLoose.find(key.first) == triggerCombinationLoose.end()) {
474  triggerCombinationLoose[key.first] = "";
475  } else {
476  triggerCombinationLoose[key.first] += " || ";
477  }
478  triggerCombinationLoose[key.first] += combineStrings(key.second);
479  }
480 
481  // Print out what we configured
482  for (auto kv: triggerCombination) ATH_MSG_DEBUG("TRIG (TIGHT): " << kv.first << " -> " << kv.second);
483  for (auto kv: triggerCombinationLoose) ATH_MSG_DEBUG("TRIG (LOOSE): " << kv.first << " -> " << kv.second);
484 
485  // Make the global trigger tool
486  if (m_config->doTightEvents()) {
487  TrigGlobalEfficiencyCorrectionTool* globalTriggerEffTool = new TrigGlobalEfficiencyCorrectionTool("TrigGlobalEfficiencyCorrectionTool::TrigGlobal");
488  top::check(globalTriggerEffTool->setProperty("ElectronEfficiencyTools", electronEffTools), "Failed to attach electron efficiency tools");
489  top::check(globalTriggerEffTool->setProperty("ElectronScaleFactorTools", electronSFTools), "Failed to attach electron scale factor tools");
490  top::check(globalTriggerEffTool->setProperty("MuonTools", muonTools), "Failed to attach muon tools");
491  top::check(globalTriggerEffTool->setProperty("PhotonEfficiencyTools", photonEffTools), "Failed to attach photon eff tools");
492  top::check(globalTriggerEffTool->setProperty("PhotonScaleFactorTools", photonSFTools), "Failed to attach photon SF tools");
493  top::check(globalTriggerEffTool->setProperty("ListOfLegsPerTool", legsPerTool), "Failed to define list of legs per tool");
494  top::check(globalTriggerEffTool->setProperty("TriggerCombination", triggerCombination), "Failed to define trigger combination");
495  top::check(globalTriggerEffTool->setProperty("TriggerMatchingTool", m_trigMatchTool), "Failed to set TriggerMatchingTool");
496  // Setting MSG::ERROR to avoid flooding output with invalid efficiency warnings before event selection is complete
497  top::check(globalTriggerEffTool->setProperty("OutputLevel", MSG::ERROR), "Failed to set message level");
498  top::check(globalTriggerEffTool->initialize(), "Failed to initalise");
499  m_globalTriggerEffTool = globalTriggerEffTool;
500  }
501  if (m_config->doLooseEvents()) {
502  TrigGlobalEfficiencyCorrectionTool* globalTriggerEffToolLoose = new TrigGlobalEfficiencyCorrectionTool("TrigGlobalEfficiencyCorrectionTool::TrigGlobalLoose");
503  top::check(globalTriggerEffToolLoose->setProperty("ElectronEfficiencyTools", electronEffToolsLoose), "Failed to attach electron efficiency tools");
504  top::check(globalTriggerEffToolLoose->setProperty("ElectronScaleFactorTools", electronSFToolsLoose), "Failed to attach electron scale factor tools");
505  top::check(globalTriggerEffToolLoose->setProperty("MuonTools", muonToolsLoose), "Failed to attach muon tools");
506  top::check(globalTriggerEffToolLoose->setProperty("PhotonEfficiencyTools", photonEffToolsLoose), "Failed to attach photon eff tools");
507  top::check(globalTriggerEffToolLoose->setProperty("PhotonScaleFactorTools", photonSFToolsLoose), "Failed to attach photon SF tools");
508  top::check(globalTriggerEffToolLoose->setProperty("ListOfLegsPerTool", legsPerToolLoose), "Failed to define list of legs per tool");
509  top::check(globalTriggerEffToolLoose->setProperty("TriggerCombination", triggerCombinationLoose), "Failed to define trigger combination");
510  top::check(globalTriggerEffToolLoose->setProperty("TriggerMatchingTool", m_trigMatchTool), "Failed to set TriggerMatchingTool");
511  // Setting MSG::ERROR to avoid flooding output with invalid efficiency warnings before event selection is complete
512  top::check(globalTriggerEffToolLoose->setProperty("OutputLevel", MSG::ERROR), "Failed to set message level");
513  top::check(globalTriggerEffToolLoose->initialize(), "Failed to initalise");
514  m_globalTriggerEffToolLoose = globalTriggerEffToolLoose;
515  }
516 
517  // Set information about systematics inside TopConfig
518  m_config->setGlobalTriggerConfiguration(electronSystematics, muonSystematics, photonSystematics, electronToolNames, muonToolNames, photonToolNames);
519 
520  return statusCode;
521  }
522 
523  std::string TriggerCPTools::mapWorkingPoints(const std::string& type) {
524  std::string working_point = "";
525  // ID
526  if (type == "LooseAndBLayerLLH" || type == "LooseBLayer" || type == "LooseAndBLayerLH") {
527  working_point = "LooseBLayer";
528  }
529  if (type == "MediumLLH" || type == "Medium" || type == "MediumLH") {
530  working_point = "Medium";
531  }
532  if (type == "TightLLH" || type == "Tight" || type == "TightLH") {
533  working_point = "Tight";
534  }
535 
536  // Temporary ISO map to handle the mess that is EGamma+IFF right now...
537  if (type.find("Pflow") != std::string::npos) {
538  ATH_MSG_WARNING("You selected a Pflow isolation WP for at least one of your electron collections - BE WARNED THAT THESE ARE NOT YET READY TO BE RELEASED FOR USE IN PHYSICS ANALYSES AND OF COURSE DON'T HAVE ASSOCIATED SCALE FACTORS YET!!!");
539  if (type == "PflowLoose") working_point = "FCLoose";
540  if (type == "PflowTight") working_point = "FCTight";
541  }
542  if (type == "Tight") working_point = "FCTight";
543  if (type == "Loose") working_point = "FCLoose";
544  if (type == "HighPtCaloOnly") working_point = "FCHighPtCaloOnly";
545  if (type == "TightTrackOnly") working_point = "Gradient";
546  if (type == "TightTrackOnly_FixedRad") working_point = "Gradient";
547 
548  // this hack is needed as the run 2 triggers do not have SFs for Tight_VarRad, but Run 3 do...
549  if (!m_config->isRun3() && type == "Tight_VarRad") return "FCTight";
550  if (type == "FCTight" || type == "FCLoose" || type == "FCHighPtCaloOnly" || type == "Gradient" || type == "Tight_VarRad") working_point = type;
551 
552  return working_point;
553  }
554 
555  std::string TriggerCPTools::PhotonKeys(const std::unordered_map<std::string, std::vector<std::pair<std::string, int> > >& map) const {
556  // check of the trigger names are one of the supported
557  std::string result("");
558  if (map.empty()) return result;
559 
560  const std::vector<std::pair<std::string,std::string> > supported = {{"2015","3g15_loose"},
561  {"2016","3g20_loose"},
562  {"2017","2g25_loose_g15_loose"},
563  {"2018","2g25_loose_g15_loose"}};
564 
565  // check if the keys for each year match the supported photon trigger
566  bool isPhoton(true);
567  for (const auto& isupported : supported) {
568  auto it = map.find(isupported.first);
569  if (it == map.end()) continue;
570  const std::vector<std::pair<std::string, int> > keys = it->second;
571  if (std::find_if(keys.begin(), keys.end(), [&isupported](const std::pair<std::string, int>& pair){return isupported.second == pair.first;}) == keys.end()) {
572  isPhoton = false;
573  }
574  }
575 
576  if (isPhoton) {
577  result = "TRI_PH_2015_g15_loose_2016_g20_loose_2017_2018_g15_loose";
578  }
579 
580  return result;
581  }
582 
583  StatusCode TriggerCPTools::CheckPhotonIsolation(const std::string& isol) const {
584  // only these isolations are available for photons triggers
585  // we need to check for these as the code otherwise crashed
586  // with a meaningless error
587  static const std::vector<std::string> allowedIso = {"TightCaloOnly", "Loose", "FixedCutTight", "FixedCutLoose"};
588 
589  if (std::find(allowedIso.begin(), allowedIso.end(), isol) == allowedIso.end()) {
590  return StatusCode::FAILURE;
591  }
592 
593  return StatusCode::SUCCESS;
594  }
595 } // namespace top
asg::AnaToolHandle::initialize
StatusCode initialize()
initialize the tool
top::TriggerCPTools::m_electronToolsFactory
std::vector< asg::AnaToolHandle< IAsgElectronEfficiencyCorrectionTool > > m_electronToolsFactory
Definition: TopTriggerCPTools.h:60
python.AtlRunQueryAMI.period
period
Definition: AtlRunQueryAMI.py:225
asg::AnaToolHandle< CP::IMuonTriggerScaleFactors >
python.SystemOfUnits.s
int s
Definition: SystemOfUnits.py:131
xAOD::Electron
Electron_v1 Electron
Definition of the current "egamma version".
Definition: Event/xAOD/xAODEgamma/xAODEgamma/Electron.h:17
xAODConfigTool.h
top::TriggerCPTools::m_config
std::shared_ptr< top::TopConfig > m_config
Definition: TopTriggerCPTools.h:41
top::TriggerCPTools::m_trigScoringTool
ToolHandle< Trig::IMatchScoringTool > m_trigScoringTool
Definition: TopTriggerCPTools.h:46
MuonTriggerScaleFactors.h
get_generator_info.result
result
Definition: get_generator_info.py:21
top
TopConfig A simple configuration that is NOT a singleton.
Definition: AnalysisTrackingHelper.cxx:58
Trig::DRScoringTool::initialize
virtual StatusCode initialize() override
Dummy implementation of the initialisation function.
Definition: DRScoringTool.cxx:13
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
top::TriggerCPTools::m_trigDecisionTool
ToolHandle< Trig::TrigDecisionTool > m_trigDecisionTool
Definition: TopTriggerCPTools.h:44
ObjectType
ObjectType
Definition: BaseObject.h:11
IAsgElectronEfficiencyCorrectionTool.h
AthCommonDataStore< AthCommonMsg< AlgTool > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T > &t)
Definition: AthCommonDataStore.h:145
top::TriggerCPTools::m_photonToolsFactory
std::vector< asg::AnaToolHandle< IAsgPhotonEfficiencyCorrectionTool > > m_photonToolsFactory
Definition: TopTriggerCPTools.h:62
top::TriggerCPTools::m_trigConfTool
ToolHandle< TrigConf::ITrigConfigTool > m_trigConfTool
Definition: TopTriggerCPTools.h:43
top::TriggerCPTools::m_globalTriggerEffToolLoose
ToolHandle< ITrigGlobalEfficiencyCorrectionTool > m_globalTriggerEffToolLoose
Definition: TopTriggerCPTools.h:49
Trig::TrigTauMatchingTool
Definition: TrigTauMatching.h:21
TrigGlobEffCorr::ImportData::getTriggerDefs
const std::map< std::size_t, TrigDef > & getTriggerDefs() const
Definition: ImportData.h:125
top::TriggerCPTools::m_muonToolLoose
asg::AnaToolHandle< CP::IMuonTriggerScaleFactors > m_muonToolLoose
Definition: TopTriggerCPTools.h:59
skel.it
it
Definition: skel.GENtoEVGEN.py:423
top::TriggerCPTools::m_electronToolsFactoryLoose
std::vector< asg::AnaToolHandle< IAsgElectronEfficiencyCorrectionTool > > m_electronToolsFactoryLoose
Definition: TopTriggerCPTools.h:61
asg
Definition: DataHandleTestTool.h:28
Trig::MatchFromCompositeTool
Tool to perform matching to selected offline particles using the list of candidates created by the De...
Definition: MatchFromCompositeTool.h:28
TrigGlobalEfficiencyCorrectionTool::initialize
virtual StatusCode initialize() override
Dummy implementation of the initialisation function.
Definition: TrigGlobalEfficiencyCorrectionTool.cxx:69
top::TriggerCPTools::PhotonKeys
std::string PhotonKeys(const std::unordered_map< std::string, std::vector< std::pair< std::string, int > > > &map) const
Definition: TopTriggerCPTools.cxx:555
TrigGlobalEfficiencyCorrectionTool.h
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
dumpTruth.statusCode
statusCode
Definition: dumpTruth.py:89
python.AtlRunQueryAMI.year
year
Definition: AtlRunQueryAMI.py:226
MatchFromCompositeTool.h
asg::AnaToolHandle::setProperty
StatusCode setProperty(const std::string &property, const T2 &value)
set the given property of the tool.
Trig::TrigDecisionTool
Definition: TrigDecisionTool.h:65
TrigGlobEffCorr::ImportData::getDictionary
const std::map< std::size_t, std::string > & getDictionary() const
Definition: ImportData.h:130
EventTools.h
A few functions for doing operations on particles / events. Currently holds code for dR,...
ImportData.h
PATCore::ParticleDataType::Full
@ Full
Definition: PATCoreEnums.h:22
ObjectType.h
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
Trig::TrigTauMatchingTool::initialize
virtual StatusCode initialize(void)
Dummy implementation of the initialisation function.
Definition: TrigTauMatching.cxx:33
lumiFormat.i
int i
Definition: lumiFormat.py:92
TrigGlobEffCorr::ImportData::associatedLeptonFlavour
xAOD::Type::ObjectType associatedLeptonFlavour(std::size_t leg, bool &success)
Definition: ImportData.cxx:526
TrigGlobEffCorr::ImportData
Definition: ImportData.h:88
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
top::TriggerCPTools::m_photonToolsFactoryLoose
std::vector< asg::AnaToolHandle< IAsgPhotonEfficiencyCorrectionTool > > m_photonToolsFactoryLoose
Definition: TopTriggerCPTools.h:63
PlotPulseshapeFromCool.input
input
Definition: PlotPulseshapeFromCool.py:106
PATCoreEnums.h
IMuonTriggerScaleFactors.h
top::check
void check(bool thingToCheck, const std::string &usefulFailureMessage)
Print an error message and terminate if thingToCheck is false.
Definition: EventTools.cxx:15
compute_lumi.leg
leg
Definition: compute_lumi.py:95
DeMoUpdate.tmp
string tmp
Definition: DeMoUpdate.py:1167
top::TriggerCPTools::m_muonTool
asg::AnaToolHandle< CP::IMuonTriggerScaleFactors > m_muonTool
Definition: TopTriggerCPTools.h:58
TrigTauMatching.h
top::TriggerCPTools::TriggerCPTools
TriggerCPTools(const std::string &name)
Definition: TopTriggerCPTools.cxx:38
TCS::join
std::string join(const std::vector< std::string > &v, const char c=',')
Definition: Trigger/TrigT1/L1Topo/L1TopoCommon/Root/StringUtils.cxx:10
PathResolver.h
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:192
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
MatchingTool.h
Trig::DRScoringTool
Score pairs of particles based on their deltaR.
Definition: DRScoringTool.h:15
DRScoringTool.h
TrigGlobalEfficiencyCorrectionTool
Definition: TrigGlobalEfficiencyCorrectionTool.h:39
TopConfig.h
TrigConf::xAODConfigTool::initialize
virtual StatusCode initialize() override
Function initialising the tool.
Definition: xAODConfigTool.cxx:78
top::TriggerCPTools::mapWorkingPoints
std::string mapWorkingPoints(const std::string &type)
Definition: TopTriggerCPTools.cxx:523
xAOD::Photon
Photon_v1 Photon
Definition of the current "egamma version".
Definition: Event/xAOD/xAODEgamma/xAODEgamma/Photon.h:17
Muon
struct TBPatternUnitContext Muon
top::TriggerCPTools::m_trigMatchTauTool
ToolHandle< Trig::ITrigTauMatchingTool > m_trigMatchTauTool
Definition: TopTriggerCPTools.h:47
asg::AnaToolHandle::getHandle
const ToolHandle< T > & getHandle() const noexcept
the tool handle we wrap
RatesAnalysisFullMenu.TrigDecisionTool
TrigDecisionTool
Definition: RatesAnalysisFullMenu.py:110
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
xAOD::EgammaHelpers::isPhoton
bool isPhoton(const xAOD::Egamma *eg)
is the object a photon
Definition: EgammaxAODHelpers.cxx:22
R3MatchingTool.h
top::TriggerCPTools::initialize
StatusCode initialize()
Dummy implementation of the initialisation function.
Definition: TopTriggerCPTools.cxx:52
top::TriggerCPTools::initialiseGlobalTriggerEff
StatusCode initialiseGlobalTriggerEff()
Definition: TopTriggerCPTools.cxx:142
Trig::R3MatchingTool
Definition: R3MatchingTool.h:20
python.Bindings.keys
keys
Definition: Control/AthenaPython/python/Bindings.py:790
TrigGlobEffCorr::ImportData::importTriggers
bool importTriggers()
Definition: ImportData.cxx:106
top::TriggerCPTools::m_trigMatchTool
ToolHandle< Trig::IMatchingTool > m_trigMatchTool
Definition: TopTriggerCPTools.h:45
top::TriggerCPTools::CheckPhotonIsolation
StatusCode CheckPhotonIsolation(const std::string &isol) const
Definition: TopTriggerCPTools.cxx:583
Trig::R3MatchingTool::initialize
virtual StatusCode initialize() override
Dummy implementation of the initialisation function.
Definition: R3MatchingTool.cxx:24
Trig::TrigDecisionTool::initialize
StatusCode initialize()
Definition: TrigDecisionTool.cxx:45
TopTriggerCPTools.h
Trig::MatchFromCompositeTool::initialize
StatusCode initialize() override
Initialise the tool.
Definition: MatchFromCompositeTool.cxx:44
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37
TrigConf::xAODConfigTool
Trigger configuration metadata tool for xAOD analysis.
Definition: xAODConfigTool.h:55
top::TriggerCPTools::m_globalTriggerEffTool
ToolHandle< ITrigGlobalEfficiencyCorrectionTool > m_globalTriggerEffTool
Definition: TopTriggerCPTools.h:48