ATLAS Offline Software
Loading...
Searching...
No Matches
TrigGlobEffCorrExample3e.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
8/*
9 * The set of examples 3a - 3e illustrates the use of lepton selection tags
10 * for various scenarios:
11 *
12 * - Example 3a: trigger = 2e12_lhloose_L12EM10VH, selecting events containing
13 * >=2 loose electrons, the leading-pT electron always satisfying
14 * in addition tight PID+isolation requirements.
15 *
16 * - Example 3b: trigger = e24_lhmedium_L1EM20VH_OR_e60_lhmedium_OR_e120_lhloose
17 * || 2e12_lhloose_L12EM10VH
18 * selecting events with >=2 loose electrons where the leading-pT
19 * electron also satisfies medium PID requirements.
20 * Only the latter is allowed to fire the single-electron trigger.
21 *
22 * - Example 3c: trigger = e24_lhmedium_L1EM20VH_OR_e60_lhmedium_OR_e120_lhloose
23 * || 2e12_lhloose_L12EM10VH
24 * selecting events with >=2 loose electrons. Any electron also
25 * satisfying medium PID requirements is allowed to fire the
26 * single-electron trigger.
27 *
28 * - Example 3d: trigger = 2e17_lhvloose_nod0 || e7_lhmedium_nod0_mu24
29 * || e26_lhtight_nod0_ivarloose_OR_e60_lhmedium_nod0_OR_e140_lhloose_nod0
30 * same type of selection as example 3c but with 3 PID working
31 * points, using two distinct decorations.
32 *
33 * - Example 3e: same scenario as example 3d, but using an alternative
34 * implementation that requires only one decoration.
35 *
36 */
37/*
38 * We use a single decoration named 'PID', and rely on the decorated value to
39 * indicate whether the electron passes TightLH PID + isolation (=> value = 2)
40 * or only MediumLH PID (=> value = 1). The TrigGlob tool then forms tags
41 * by suffixing the decorated value to the decoration name, i.e. 'PID1' and
42 * 'PID2'. One must then use the latter tags in the properties 'ListOfLegsPerTag'
43 * and 'ListOfTagsPerTool'. */
44
45// ROOT include(s):
46#include <TFile.h>
47#include <TError.h>
48
49// Infrastructure include(s):
50#ifdef XAOD_STANDALONE
51 #include "xAODRootAccess/Init.h"
54#else
57#endif
58
60// EDM include(s):
72
73// stdlib include(s):
74#include <sstream>
75#include <random>
76#include <vector>
77#include <array>
78using std::vector;
79using std::string;
80
82namespace { vector<string> split_comma_delimited(const std::string&); }
83
84#define MSGSOURCE "Example 3e"
85
88using namespace Test;
89int main(int argc, char* argv[])
90{
92 const char* filename = nullptr;
93 bool debug = false, cmdline_error = false, toys = false;
94 for(int i=1;i<argc;++i)
95 {
96 if(string(argv[i]) == "--debug") debug = true;
97 else if(string(argv[i]) == "--toys") toys = true;
98 else if(!filename && *argv[i]!='-') filename = argv[i];
99 else cmdline_error = true;
100 }
101 if(!filename || cmdline_error)
102 {
103 Error(MSGSOURCE, "No file name received!");
104 Error(MSGSOURCE, " Usage: %s [--debug] [--toys] [DxAOD file name]", argv[0]);
105 return 1;
106 }
107 #ifdef XAOD_STANDALONE
108 xAOD::Init(MSGSOURCE).ignore();
109 TFile* file = TFile::Open(filename, "READ");
110 if(!file)
111 {
112 Error(MSGSOURCE, "Unable to open file!");
113 return 2;
114 }
116 xAOD::TStore store;
117 StatusCode::enableFailure();
118 #else
119 IAppMgrUI* app = POOL::Init();
121 TString file(filename);
122 #endif
123 event.readFrom(file).ignore();
124 Long64_t entries = event.getEntries();
125 Info(MSGSOURCE, "Number of events in the file: %lli", entries);
126
127 /* ********************************************************************** */
128
129 Info(MSGSOURCE, "Configuring the electron CP tools");
131 ToolHandleArray<IAsgElectronEfficiencyCorrectionTool> electronEffTools;
133 ToolHandleArray<IAsgElectronEfficiencyCorrectionTool> electronSFTools;
135 std::map<std::string,std::string> legsPerTool;
137 std::map<std::string,std::string> tagsPerTool;
139 std::map<std::string,std::string> legsPerTag;
141 static const SG::Decorator<char> dec_pid("PID");
143 std::bernoulli_distribution bernoulliPdf(0.9);
144
146 vector<asg::AnaToolHandle<IAsgElectronEfficiencyCorrectionTool>> factory;
147 enum{ cLEGS, cTAG, cKEY, cPID, cISO };
148 std::vector<std::array<std::string,5> > toolConfigs = {
151 {"e26_lhtight_nod0_ivarloose_OR_e60_lhmedium_nod0_OR_e140_lhloose_nod0", "PID2",
152 "2016_e26_lhtight_nod0_ivarloose_OR_e60_lhmedium_nod0_OR_e140_lhloose_nod0", "Tight", "GradientLoose"},
154 {"e7_lhmedium_nod0", "PID1,PID2", "2016_e7_lhmedium_nod0", "Medium", ""},
156 {"e17_lhvloose_nod0", "*,PID1,PID2", "2016_e17_lhvloose_nod0", "LooseBLayer", ""},
157 };
158
159 const char* mapPath = "ElectronEfficiencyCorrection/2015_2017/"
160 "rel21.2/Moriond_February2018_v2/map6.txt";
161 for(auto& cfg : toolConfigs)
162 for(int j=0;j<2;++j)
163 {
164 string name = "AsgElectronEfficiencyCorrectionTool/"
165 + ((j? "ElTrigEff_" : "ElTrigSF_")
166 + std::to_string(factory.size()/2));
167 auto t = factory.emplace(factory.end(), name);
168 t->setProperty("MapFilePath", mapPath).ignore();
169 t->setProperty("TriggerKey", string(j?"":"Eff_") + cfg[cKEY]).ignore();
170 t->setProperty("IdKey", cfg[cPID]).ignore();
171 t->setProperty("IsoKey", cfg[cISO]).ignore();
172
173 t->setProperty("CorrelationModel", "TOTAL").ignore();
174 t->setProperty("ForceDataType", (int)PATCore::ParticleDataType::Full).ignore();
175 if(t->initialize() != StatusCode::SUCCESS)
176 {
177 Error(MSGSOURCE, "Unable to initialize the electron CP tool <%s>!",
178 t->name().c_str());
179 return 3;
180 }
181 auto& handles = (j? electronSFTools : electronEffTools);
182 handles.push_back(t->getHandle());
185 name = handles[handles.size()-1].name();
186 legsPerTool[name] = cfg[cLEGS];
187 tagsPerTool[name] = cfg[cTAG];
188 if(!j)
189 {
190 for(auto& tag : ::split_comma_delimited(cfg[cTAG]))
191 {
192 if(legsPerTag[tag]=="") legsPerTag[tag] = cfg[cLEGS];
193 else legsPerTag[tag] += "," + cfg[cLEGS];
194 }
195 }
196
197 }
198
199 /* ********************************************************************** */
200
201 Info(MSGSOURCE, "Configuring the muon CP tools");
203 ToolHandleArray<CP::IMuonTriggerScaleFactors> muonTools;
204 asg::AnaToolHandle<CP::IMuonTriggerScaleFactors> muonTool("CP::MuonTriggerScaleFactors/MuonTrigEff");
205 muonTool.setProperty("MuonQuality", "Tight").ignore();
206 muonTool.setProperty("useRel207", false).ignore();
207 if(muonTool.initialize() != StatusCode::SUCCESS)
208 {
209 Error(MSGSOURCE, "Unable to initialize the muon CP tool!");
210 return 3;
211 }
212 muonTools.push_back(muonTool.getHandle());
213
214 /* ********************************************************************** */
215
216 Info(MSGSOURCE, "Configuring the global trigger SF tool");
217 asg::AnaToolHandle<ITrigGlobalEfficiencyCorrectionTool> myTool("TrigGlobalEfficiencyCorrectionTool/TrigGlobal");
218 myTool.setProperty("ElectronEfficiencyTools", electronEffTools).ignore();
219 myTool.setProperty("ElectronScaleFactorTools", electronSFTools).ignore();
220 myTool.setProperty("MuonTools", muonTools).ignore();
221 const char* triggers2016 =
222 "e26_lhtight_nod0_ivarloose_OR_e60_lhmedium_nod0_OR_e140_lhloose_nod0"
223 "|| e7_lhmedium_nod0_mu24"
224 "|| 2e17_lhvloose_nod0";
225 myTool.setProperty("TriggerCombination2016", triggers2016).ignore();
228 myTool.setProperty("LeptonTagDecorations", "PID?").ignore();
229 myTool.setProperty("ListOfLegsPerTool", legsPerTool).ignore();
230 myTool.setProperty("ListOfTagsPerTool", tagsPerTool).ignore();
231 myTool.setProperty("ListOfLegsPerTag", legsPerTag).ignore();
232
233 if(debug) myTool.setProperty("OutputLevel", MSG::DEBUG).ignore();
234 if(toys) myTool.setProperty("NumberOfToys", 1000).ignore();
235 if(myTool.initialize() != StatusCode::SUCCESS)
236 {
237 Error(MSGSOURCE, "Unable to initialize the TrigGlob tool!");
238 return 3;
239 }
240
243 const unsigned periodRuns[] = {
245 296939, 300345, 301912, 302737, 303638, 303943, 305291, 307124,
246 305359, 309311, 310015
247 };
248 std::uniform_int_distribution<unsigned> uniformPdf(0,
249 sizeof(periodRuns)/sizeof(*periodRuns) - 1);
250 std::default_random_engine randomEngine;
251
252 static const SG::ConstAccessor<int> truthType("truthType");
253 static const SG::ConstAccessor<int> truthOrigin("truthOrigin");
254
255 /* ********************************************************************** */
256
257 Info(MSGSOURCE, "Starting the event loop");
258 unsigned errors = 0;
259 double nSuitableEvents = 0., sumW = 0.;
260 static const SG::Decorator<unsigned> RandomRunNumberDec("RandomRunNumber");
261 for(Long64_t entry = 0; entry < entries; ++entry)
262 {
263 event.getEntry(entry);
264
266 const xAOD::EventInfo* eventInfo = nullptr;
267 event.retrieve(eventInfo,"EventInfo").ignore();
268 unsigned runNumber = periodRuns[uniformPdf(randomEngine)];
269 RandomRunNumberDec(*eventInfo) = runNumber;
270
271 unsigned nTrig_e26 = 0, nTrig_e7 = 0, nTrig_e17 = 0;
272
273 vector<const xAOD::Electron*> myTriggeringElectrons;
274 const xAOD::ElectronContainer* electrons = nullptr;
275 event.retrieve(electrons,"Electrons").ignore();
276 for(auto electron : *electrons)
277 {
278 if(!electron->caloCluster()) continue;
279 float eta = fabs(electron->caloCluster()->etaBE(2));
280 float pt = electron->pt();
281 if(pt<10e3f || eta>=2.47) continue;
282 if(!truthType.isAvailable(*electron)) continue;
283 if(!truthOrigin.isAvailable(*electron)) continue;
284 int t = truthType(*electron), o = truthOrigin(*electron);
285 if(t!=2 || !(o==10 || (o>=12 && o<=22) || o==43)) continue;
287 if(pt < 7e3f) continue;
288 if(pt >= 18e3f) ++nTrig_e17;
289
290 myTriggeringElectrons.push_back(electron);
291 }
292
293 vector<const xAOD::Muon*> myTriggeringMuons;
294 const xAOD::MuonContainer* muons = nullptr;
295 event.retrieve(muons,"Muons").ignore();
296 for(auto muon : *muons)
297 {
298 if(runNumber >= 324320) break; // delete line once all SFs available for 2017
299 float pt = muon->pt();
300 if(pt<10e3f || fabs(muon->eta())>=2.5) continue;
301 auto mt = muon->muonType();
302 if(mt!=xAOD::Muon::Combined && mt!=xAOD::Muon::MuonStandAlone) continue;
303 auto& mtp = *(muon->primaryTrackParticle());
304 if(!truthType.isAvailable(mtp)) continue;
305 if(!truthOrigin.isAvailable(mtp)) continue;
306 int t = truthType(mtp), o = truthOrigin(mtp);
307 if(t!=6 || !(o==10 || (o>=12 && o<=22) || o==43)) continue;
309 if(pt < 25.2e3f) continue;
310
311 myTriggeringMuons.push_back(muon);
312 }
313
317 for(auto electron : myTriggeringElectrons)
318 {
319 bool medium = bernoulliPdf(randomEngine);
320 bool tight = medium && bernoulliPdf(randomEngine);
322 dec_pid(*electron) = tight? 2 : medium? 1 : 0;
323 if(medium && electron->pt()>8e3f) ++nTrig_e7;
324 if(tight && electron->pt()>27e3f) ++nTrig_e26;
325 }
326
328 if(nTrig_e26 < 1
329 && (nTrig_e7==0 || myTriggeringMuons.size()==0)
330 && nTrig_e17 < 2)
331 {
332 continue;
333 }
334
335
337 double sf = 1.;
338 auto cc = myTool->getEfficiencyScaleFactor(myTriggeringElectrons,
339 myTriggeringMuons, sf);
341 {
342 nSuitableEvents += 1;
343 sumW += sf;
344 }
345 else
346 {
347 Warning(MSGSOURCE, "Scale factor evaluation failed");
348 ++errors;
349 }
350 if(errors>10)
351 {
352 Error(MSGSOURCE, "Too many errors reported!");
353 break;
354 }
355 }
356 Info(MSGSOURCE, "Average scale factor: %f (over %ld events)",
357 sumW / nSuitableEvents, long(nSuitableEvents));
358 #ifndef XAOD_STANDALONE
359 ANA_CHECK(app->finalize());
360 #endif
361 return errors? 4 : 0;
362}
363
365namespace
366{
367 inline vector<string> split_comma_delimited(const string& s)
368 {
369 std::stringstream ss(s);
370 std::vector<std::string> tokens;
371 std::string token;
372 while(std::getline(ss, token, ','))
373 {
374 if(token.length()) tokens.push_back(token);
375 }
376 return tokens;
377 }
378}
Scalar eta() const
pseudorapidity method
Base class for elements of a container that can have aux data.
Helper class to provide constant type-safe access to aux data.
macros for messaging and checking status codes
#define ANA_CHECK(EXP)
check whether the given expression was successful
#define ANA_MSG_HEADER(NAME)
for standalone code this creates a new message category
#define ANA_MSG_SOURCE(NAME, TITLE)
the source code part of ANA_MSG_SOURCE
#define ANA_CHECK_SET_TYPE(TYPE)
set the type for ANA_CHECK to report failures
Helper class to provide type-safe access to aux data.
static Double_t ss
const bool debug
@ Ok
The correction was done successfully.
Helper class to provide constant type-safe access to aux data.
Helper class to provide type-safe access to aux data.
Definition Decorator.h:59
a modified tool handle that allows its owner to configure new tools from the C++ side
StatusCode setProperty(const std::string &property, const T2 &value)
set the given property of the tool.
StatusCode initialize()
initialize the tool
const ToolHandle< T > & getHandle() const noexcept
the tool handle we wrap
Tool for accessing xAOD files outside of Athena.
@ kClassAccess
Access auxiliary data using the aux containers.
A relatively simple transient store for objects created in analysis.
Definition TStore.h:45
int main()
Definition hello.cxx:18
double entries
Definition listroot.cxx:49
IAppMgrUI * Init(const char *options="POOLRootAccess/basic.opts")
Bootstraps (creates and configures) the Gaudi Application with the provided options file.
StatusCode Init(const char *appname)
Function initialising ROOT/PyROOT for using the ATLAS EDM.
Definition Init.cxx:31
ElectronContainer_v1 ElectronContainer
Definition of the current "electron container version".
EventInfo_v1 EventInfo
Definition of the latest event info version.
MuonContainer_v1 MuonContainer
Definition of the current "Muon container version".
#define MSGSOURCE
Test code to test ElectronPhotonVariableCorrectionTool Dictionaries.
TFile * file