ATLAS Offline Software
Loading...
Searching...
No Matches
TrigGlobalEfficiencyAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
6
12
14 ISvcLocator *svcLoc)
15 : EL::AnaAlgorithm(name, svcLoc)
16{
17 declareProperty("matchingTool", m_trigMatchingTool, "trigger matching tool");
18}
19
21{
22
23 if (m_trigList_2015.empty() && m_trigList_2016.empty() && m_trigList_2017.empty() && m_trigList_2018.empty()
24 && m_trigList_2022.empty() && m_trigList_2023.empty() && m_trigList_2024.empty() && m_trigList_2025.empty()) {
25 ATH_MSG_ERROR("A list of triggers needs to be provided");
26 return StatusCode::FAILURE;
27 }
28
32
36
40
42
43 // retrieve the trigger matching tool
44 ANA_CHECK(m_trigMatchingTool.retrieve());
45
46 // prepare trigger data
48 ANA_CHECK(triggerData.importTriggers());
49 const auto & triggerDict = triggerData.getDictionary();
50 std::unordered_map<std::string, TrigGlobEffCorr::ImportData::TrigDef> triggerDefs;
51 for (const auto &[key, trigDef] : triggerData.getTriggerDefs()) {
52 auto it = triggerDict.find(key);
53 if (it != triggerDict.end()) {
54 triggerDefs[it->second] = trigDef;
55 }
56 }
57
58 // now we can build a map of triggers per year, and extract the electron/photon legs as needed
59 std::unordered_map<std::string, std::vector<std::string> > trigMap;
60 trigMap["2015"] = m_trigList_2015;
61 trigMap["2016"] = m_trigList_2016;
62 trigMap["2017"] = m_trigList_2017;
63 trigMap["2018"] = m_trigList_2018;
64 trigMap["2022"] = m_trigList_2022;
65 trigMap["2023"] = m_trigList_2023;
66 trigMap["2024"] = m_trigList_2024;
67 trigMap["2025"] = m_trigList_2025;
68
69 // combine all the trigger legs in the expected format
70 std::map<std::string, std::string> triggerCombination;
71 auto combineStrings = [](const std::vector<std::string>& input ) {
72 std::string combinedString;
73 bool first = true;
74 for (const auto & i : input) {
75 if (!first) {
76 combinedString += " || ";
77 }
78 combinedString += i;
79 first = false;
80 }
81 return combinedString;
82 };
83 for (const auto &[year, triggers] : trigMap) {
84 if (triggers.empty()) continue;
85 if (triggerCombination.find(year) == triggerCombination.end()) {
86 triggerCombination[year] = "";
87 } else {
88 triggerCombination[year] += " || ";
89 }
90 triggerCombination[year] += combineStrings(triggers);
91 }
92
93 // collect the combined electron and photon trigger keys supported by Egamma
94 std::map<std::string,std::string> electronLegsPerKey, photonLegsPerKey;
95 if (!m_doMatchingOnly) {
96 if (m_isRun3Geo) {
97 ANA_CHECK(TrigGlobalEfficiencyCorrectionTool::suggestElectronMapKeys(triggerCombination, "2015_2025/rel22.2/2025_Run3_Consolidated_Recommendation_v4", electronLegsPerKey));
98 }
99 else {
100 ANA_CHECK(TrigGlobalEfficiencyCorrectionTool::suggestElectronMapKeys(triggerCombination, "2015_2018/rel21.2/Precision_Summer2020_v1", electronLegsPerKey));
101 }
102 ANA_CHECK(TrigGlobalEfficiencyCorrectionTool::suggestPhotonMapKeys(triggerCombination, "2015_2018/rel21.2/Summer2020_Rec_v1", photonLegsPerKey));
103 }
104
105 std::map<std::string, std::string> legsPerTool;
107
108 // ELECTRON TOOLS
109 ToolHandleArray<IAsgElectronEfficiencyCorrectionTool> electronEffTools, electronSFTools;
110 int nTools = 0;
111 if (!m_electronsHandle.empty() && !m_doMatchingOnly) {
112 if (m_electronID.empty()) ATH_MSG_ERROR("Electron ID was not set for TrigGlobalEfficiencyAlg!");
113 for (const auto &[trigKey, triggers] : electronLegsPerKey) {
114 if (trigKey == nameForDefaultSF) { // no tool needed in this case
115 auto [itr, added] = legsPerTool.emplace(nameForDefaultSF, triggers);
116 if (!added) itr->second += "," + triggers;
117 continue;
118 }
119 nTools++;
120 for (bool isSFTool : {true, false}) { // one tool instance for efficiencies, another for scale factors
121 auto t = m_electronToolsFactory.emplace(m_electronToolsFactory.end(),
122 "AsgElectronEfficiencyCorrectionTool/ElTrigEff_"
123 + std::to_string(isSFTool) + "_" + std::to_string(nTools) + "_" + m_electronID.value() + "_" + m_electronIsol.value());
124 if (!m_isRun3Geo) {
125 ANA_CHECK(t->setProperty("MapFilePath", "ElectronEfficiencyCorrection/2015_2025/rel22.2/2025_Run2Rel22_Recommendation_v3/map1.txt"));
126 }
127 ANA_CHECK(t->setProperty("IdKey", m_electronID.value()));
128 ANA_CHECK(t->setProperty("IsoKey", m_electronIsol.value()));
129 ANA_CHECK(t->setProperty("TriggerKey", isSFTool ? trigKey : "Eff_" + trigKey ));
130 ANA_CHECK(t->setProperty("CorrelationModel", "TOTAL"));
131 ANA_CHECK(t->setProperty("ForceDataType", PATCore::ParticleDataType::Full));
132 ANA_CHECK(t->setProperty("OutputLevel", msg().level()));
133 ANA_CHECK(t->initialize());
134 // now record the handle
135 auto& handles = (isSFTool? electronSFTools : electronEffTools);
136 handles.push_back(t->getHandle());
137 std::string name = handles[handles.size()-1].name();
138 legsPerTool[name] = triggers;
139 // and add the systematics
140 ANA_CHECK(m_systematicsList.addSystematics( *handles[handles.size()-1] ));
141 }
142 }
143 }
144
145 // PHOTON TOOLS
146 ToolHandleArray<IAsgPhotonEfficiencyCorrectionTool> photonEffTools, photonSFTools;
147 nTools = 0;
148 if (!m_photonsHandle.empty() && !m_doMatchingOnly) {
149 if (m_photonIsol.empty()) ATH_MSG_ERROR("Photon Isolation was not set for TrigGlobalEfficiencyAlg!");
150 for (const auto &[trigKey, triggers] : photonLegsPerKey) {
151 if (trigKey == nameForDefaultSF) { // no tool needed in this case
152 auto [itr, added] = legsPerTool.emplace(nameForDefaultSF, triggers);
153 if (!added) itr->second += "," + triggers;
154 continue;
155 }
156 nTools++;
157 for (bool isSFTool : {true, false}) { // one tool instance for efficiencies, another for scale factors
158 auto t = m_photonToolsFactory.emplace(m_photonToolsFactory.end(),
159 "AsgPhotonEfficiencyCorrectionTool/PhTrigEff_"
160 + std::to_string(isSFTool) + "_" + std::to_string(nTools) + "_" + m_photonIsol.value());
161 if (!m_isRun3Geo) {
162 ANA_CHECK(t->setProperty("MapFilePath", "PhotonEfficiencyCorrection/2015_2018/rel21.2/Summer2020_Rec_v1/map3.txt"));
163 }
164 ANA_CHECK(t->setProperty("IsoKey", m_photonIsol.value()));
165 ANA_CHECK(t->setProperty("TriggerKey", isSFTool ? trigKey : "Eff_" + trigKey ));
166 ANA_CHECK(t->setProperty("ForceDataType", PATCore::ParticleDataType::Full));
167 ANA_CHECK(t->setProperty("OutputLevel", msg().level()));
168 ANA_CHECK(t->initialize());
169 // now record the handle
170 auto& handles = (isSFTool? photonSFTools : photonEffTools);
171 handles.push_back(t->getHandle());
172 std::string name = handles[handles.size()-1].name();
173 legsPerTool[name] = triggers;
174 // and add the systematics
175 ANA_CHECK(m_systematicsList.addSystematics( *handles[handles.size()-1] ));
176 }
177 }
178 }
179
180 // MUON TOOLS
181 ToolHandleArray<CP::IMuonTriggerScaleFactors> muonTools;
182 if (!m_muonsHandle.empty() && !m_doMatchingOnly) {
183 if (m_muonID.empty()) ATH_MSG_ERROR("Muon ID was not set for TrigGlobalEfficiencyAlg!");
184 m_muonTool = asg::AnaToolHandle<CP::IMuonTriggerScaleFactors>("CP::MuonTriggerScaleFactors/MuonTrigEff_" + m_muonID.value());
185 ANA_CHECK(m_muonTool.setProperty("MuonQuality", m_muonID.value()));
186 ANA_CHECK(m_muonTool.setProperty("AllowZeroSF", true));
187 ANA_CHECK(m_muonTool.initialize());
188 // now record the handle
189 muonTools.push_back(m_muonTool.getHandle());
190 // and add the efficiency systematics
191 ANA_CHECK(m_systematicsList.addSystematics( *m_muonTool ));
192 }
193
194 // create the individual trigger-matching decorators
195 for(const std::string& trig : m_separateMatchingTriggers) {
196 std::string s = trig;
197 std::replace(s.begin(), s.end(), '-', '_');
198 std::replace(s.begin(), s.end(), '.', 'p');
199
200 m_separateMatchingDecorators.emplace(trig, SysWriteDecorHandle<bool>("triggerMatch_"+s+m_separateMatchingDecorSuffix+"_%SYS%", this));
202
203 m_separateMatchingFlags[trig] = false;
204 }
205
206 // finally, set up the global trigger tool
207 m_tgecTool = asg::AnaToolHandle<ITrigGlobalEfficiencyCorrectionTool>("TrigGlobalEfficiencyCorrectionTool/TrigGlobal_" + this->name() );
208 ANA_CHECK(m_tgecTool.setProperty("ElectronEfficiencyTools", electronEffTools));
209 ANA_CHECK(m_tgecTool.setProperty("ElectronScaleFactorTools", electronSFTools));
210 ANA_CHECK(m_tgecTool.setProperty("PhotonEfficiencyTools", photonEffTools));
211 ANA_CHECK(m_tgecTool.setProperty("PhotonScaleFactorTools", photonSFTools));
212 ANA_CHECK(m_tgecTool.setProperty("MuonTools", muonTools));
213 ANA_CHECK(m_tgecTool.setProperty("ListOfLegsPerTool", legsPerTool));
214 ANA_CHECK(m_tgecTool.setProperty("TriggerCombination", triggerCombination));
215 ANA_CHECK(m_tgecTool.setProperty("TriggerMatchingTool", m_trigMatchingTool));
216 ANA_CHECK(m_tgecTool.setProperty("NumberOfToys", m_numToys));
217 ANA_CHECK(m_tgecTool.setProperty("OutputLevel", MSG::ERROR));
218 ANA_CHECK(m_tgecTool.initialize());
219
220 ANA_CHECK(m_systematicsList.initialize());
221
222 return StatusCode::SUCCESS;
223}
224
226{
227
229
230 for (const auto & syst : m_systematicsList.systematicsVector()) {
231 CP::SysFilterReporter filter (filterCombiner, syst);
232
233 // retrieve lepton collections with selections
234 const xAOD::ElectronContainer* electrons(nullptr);
235 const xAOD::PhotonContainer* photons(nullptr);
236 const xAOD::MuonContainer* muons(nullptr);
237 std::vector<const xAOD::Electron*> selectedElectrons;
238 std::vector<const xAOD::Photon*> selectedPhotons;
239 std::vector<const xAOD::Muon*> selectedMuons;
240
241 if (!m_electronsHandle.empty()) {
242 ANA_CHECK(m_electronsHandle.retrieve(electrons, syst));
243 for (const xAOD::Electron *el: *electrons) {
244 if (m_electronSelection.getBool(*el, syst)) selectedElectrons.push_back(el);
245 }
246 }
247 if (!m_photonsHandle.empty()) {
248 ANA_CHECK(m_photonsHandle.retrieve(photons, syst));
249 for (const xAOD::Photon *ph: *photons) {
250 if (m_photonSelection.getBool(*ph, syst)) selectedPhotons.push_back(ph);
251 }
252 }
253 if (!m_muonsHandle.empty()) {
254 ANA_CHECK(m_muonsHandle.retrieve(muons, syst));
255 for (const xAOD::Muon *mu: *muons) {
256 if (m_muonSelection.getBool(*mu, syst)) selectedMuons.push_back(mu);
257 }
258 }
259
260 ANA_CHECK(m_tgecTool->applySystematicVariation(syst));
261
262 // compute the scale factor
263 double sf;
264 if (selectedElectrons.empty() && selectedMuons.empty() && selectedPhotons.empty()) sf = 1.0;
265 else if (m_doMatchingOnly) sf = 1.0;
266 else {
267 sf = NAN;
268 m_tgecTool->getEfficiencyScaleFactor(selectedElectrons, selectedMuons, selectedPhotons,
269 sf).ignore();
270 }
271
272 // Retrieve EventInfo
273 const xAOD::EventInfo *evtInfo {nullptr};
274 ANA_CHECK(m_eventInfoHandle.retrieve(evtInfo, syst));
275
276 // Check if we have trigger matching
277 bool matched = false;
278 if (!(selectedElectrons.empty() && selectedMuons.empty() && selectedPhotons.empty())) {
279 if(m_separateMatchingTriggers.value().empty()) {
280 ANA_CHECK(m_tgecTool->checkTriggerMatching(matched, selectedElectrons, selectedMuons, selectedPhotons));
281 } else {
282 ANA_CHECK(m_tgecTool->checkTriggerMatching(m_separateMatchingFlags, selectedElectrons, selectedMuons, selectedPhotons));
283 for(const auto& [trig, flag] : m_separateMatchingFlags) {
284 if(flag) matched = true;
285 m_separateMatchingDecorators.at(trig).set(*evtInfo, flag, syst);
286 }
287 }
288 }
289 if (matched) filter.setPassed(true);
290
291 // Decorate global outputs onto the EventInfo
292 m_scaleFactorDecoration.set(*evtInfo, sf, syst);
293 m_matchingDecoration.set(*evtInfo, matched, syst);
294 }
295
296 return StatusCode::SUCCESS;
297}
298
300{
301
302 ANA_CHECK (m_filterParams.finalize());
303 return StatusCode::SUCCESS;
304}
#define ATH_MSG_ERROR(x)
#define ANA_CHECK(EXP)
check whether the given expression was successful
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
a reporter class that combines the filter decisions for all systematics
a systematics aware filter reporter
a data handle for reading systematics varied input data
asg::AnaToolHandle< ITrigGlobalEfficiencyCorrectionTool > m_tgecTool
Trigger Global Efficiency Correction Tool handle.
Gaudi::Property< std::vector< std::string > > m_trigList_2024
SysReadHandle< xAOD::EventInfo > m_eventInfoHandle
EventInfo to decorate.
Gaudi::Property< std::vector< std::string > > m_trigList_2018
virtual StatusCode finalize() final override
Gaudi::Property< std::string > m_electronIsol
electron Isolation
Gaudi::Property< std::vector< std::string > > m_trigList_2023
Gaudi::Property< std::string > m_separateMatchingDecorSuffix
separate chain matching decorator suffix
std::unordered_map< std::string, SysWriteDecorHandle< bool > > m_separateMatchingDecorators
Gaudi::Property< std::vector< std::string > > m_separateMatchingTriggers
store separate trigger matching flags for each trigger
Gaudi::Property< std::string > m_electronID
electron ID
ToolHandle< Trig::IMatchingTool > m_trigMatchingTool
trigger matching tool
Gaudi::Property< std::string > m_photonIsol
photon Isolation
std::vector< asg::AnaToolHandle< IAsgPhotonEfficiencyCorrectionTool > > m_photonToolsFactory
RAII on-the-fly tool creation for photons.
SysWriteDecorHandle< char > m_matchingDecoration
decoration of the global trigger matching flag
SysReadSelectionHandle m_muonSelection
input muon selection
Gaudi::Property< std::vector< std::string > > m_trigList_2017
Gaudi::Property< bool > m_noFilter
whether to not apply an event filter
Gaudi::Property< std::string > m_muonID
muon quality
std::vector< asg::AnaToolHandle< IAsgElectronEfficiencyCorrectionTool > > m_electronToolsFactory
RAII on-the-fly tool creation for electrons.
Gaudi::Property< int > m_numToys
number of toy experiments to run to estimate the trigger combination efficiency, instead of using an ...
SysReadSelectionHandle m_electronSelection
input electron selection
Gaudi::Property< std::vector< std::string > > m_trigList_2015
list of triggers or trigger chains
Gaudi::Property< bool > m_doMatchingOnly
whether to only run the global trigger matching, and not compute efficiency SFs
SysWriteDecorHandle< float > m_scaleFactorDecoration
decoration of the global trigger SF
TrigGlobalEfficiencyAlg(const std::string &name, ISvcLocator *pSvcLocator=nullptr)
Gaudi::Property< std::vector< std::string > > m_trigList_2022
virtual StatusCode initialize() final override
asg::AnaToolHandle< IMuonTriggerScaleFactors > m_muonTool
the muon trigger SF handle
SysReadSelectionHandle m_photonSelection
input photon selection
Gaudi::Property< std::vector< std::string > > m_trigList_2016
Gaudi::Property< std::vector< std::string > > m_trigList_2025
std::unordered_map< std::string, bool > m_separateMatchingFlags
SysReadHandle< xAOD::PhotonContainer > m_photonsHandle
input photon collection
virtual StatusCode execute() final override
SysReadHandle< xAOD::ElectronContainer > m_electronsHandle
input electron collection
SysFilterReporterParams m_filterParams
the filter reporter params
Gaudi::Property< bool > m_isRun3Geo
whether to use Run 3 settings
SysReadHandle< xAOD::MuonContainer > m_muonsHandle
input muon collection
AnaAlgorithm(const std::string &name, ISvcLocator *pSvcLocator)
constructor with parameters
static std::string toolnameForDefaultScaleFactor()
To be used with the ListOfLegsPerTool property:
const std::map< std::size_t, std::string > & getDictionary() const
Definition ImportData.h:142
const std::map< std::size_t, TrigDef > & getTriggerDefs() const
Definition ImportData.h:126
static CP::CorrectionCode suggestPhotonMapKeys(const std::map< std::string, std::string > &triggerCombination, const std::string &version, std::map< std::string, std::string > &legsPerKey)
static CP::CorrectionCode suggestElectronMapKeys(const std::map< std::string, std::string > &triggerCombination, const std::string &version, std::map< std::string, std::string > &legsPerKey)
a modified tool handle that allows its owner to configure new tools from the C++ side
This module defines the arguments passed from the BATCH driver to the BATCH worker.
PhotonContainer_v1 PhotonContainer
Definition of the current "photon container version".
ElectronContainer_v1 ElectronContainer
Definition of the current "electron container version".
EventInfo_v1 EventInfo
Definition of the latest event info version.
Muon_v1 Muon
Reference the current persistent version:
Photon_v1 Photon
Definition of the current "egamma version".
MuonContainer_v1 MuonContainer
Definition of the current "Muon container version".
Electron_v1 Electron
Definition of the current "egamma version".
MsgStream & msg
Definition testRead.cxx:32