ATLAS Offline Software
Loading...
Searching...
No Matches
TrigGlobEffCorrExample3b.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 * For this example (3b), one needs to set up three versions of the electron
39 * trigger tools: two configured for offline tight PID+isolation, to be used for
40 * the leading electron (one for the trigger leg e24_xxx, another for the leg
41 * e12_xxx), and another configured for offline loose PID (for the leg e12_xxx)
42 * to be used for subleading electrons.
43 *
44 * The configuration of the TrigGlobalEfficiencyCorrectionTool is very similar
45 * to the example 3a (e.g. the decoration of electrons is identical), please
46 * refer to that example for more details.
47 * Here, in addition, one needs to let the tool know, via the property
48 * 'ListOfLegsPerTag', that only 'Signal'-tagged electrons are allowed to fire
49 * the e24_xxx leg.
50 *
51 */
52
53// ROOT include(s):
54#include <TFile.h>
55#include <TError.h>
56
57// Infrastructure include(s):
58#ifdef XAOD_STANDALONE
59 #include "xAODRootAccess/Init.h"
62#else
65#endif
66
68// EDM include(s):
80
81// stdlib include(s):
82#include <sstream>
83#include <random>
84#include <vector>
85#include <array>
86using std::vector;
87using std::string;
88
90namespace { vector<string> split_comma_delimited(const std::string&); }
91
92#define MSGSOURCE "Example 3b"
93
96using namespace Test;
97int main(int argc, char* argv[])
98{
100 const char* filename = nullptr;
101 bool debug = false, cmdline_error = false, toys = false;
102 for(int i=1;i<argc;++i)
103 {
104 if(string(argv[i]) == "--debug") debug = true;
105 else if(string(argv[i]) == "--toys") toys = true;
106 else if(!filename && *argv[i]!='-') filename = argv[i];
107 else cmdline_error = true;
108 }
109 if(!filename || cmdline_error)
110 {
111 Error(MSGSOURCE, "No file name received!");
112 Error(MSGSOURCE, " Usage: %s [--debug] [--toys] [DxAOD file name]", argv[0]);
113 return 1;
114 }
115 #ifdef XAOD_STANDALONE
116 xAOD::Init(MSGSOURCE).ignore();
117 TFile* file = TFile::Open(filename, "READ");
118 if(!file)
119 {
120 Error(MSGSOURCE, "Unable to open file!");
121 return 2;
122 }
124 xAOD::TStore store;
125 StatusCode::enableFailure();
126 #else
127 IAppMgrUI* app = POOL::Init();
129 TString file(filename);
130 #endif
131 event.readFrom(file).ignore();
132 Long64_t entries = event.getEntries();
133 Info(MSGSOURCE, "Number of events in the file: %lli", entries);
134
135 /* ********************************************************************** */
136
137 Info(MSGSOURCE, "Configuring the electron CP tools");
139 ToolHandleArray<IAsgElectronEfficiencyCorrectionTool> electronEffTools;
141 ToolHandleArray<IAsgElectronEfficiencyCorrectionTool> electronSFTools;
143 std::map<std::string,std::string> legsPerTool;
145 std::map<std::string,std::string> tagsPerTool;
147 std::map<std::string,std::string> legsPerTag;
149 static const SG::Decorator<char> dec_signal("Signal");
151 std::bernoulli_distribution bernoulliPdf(0.9);
152
154 vector<asg::AnaToolHandle<IAsgElectronEfficiencyCorrectionTool>> factory;
155 enum{ cLEGS, cTAG, cKEY, cPID, cISO };
156 std::vector<std::array<std::string,5> > toolConfigs = {
159 {"e24_lhmedium_L1EM20VH_OR_e60_lhmedium_OR_e120_lhloose", "Signal", "2015_e24_lhmedium_L1EM20VH_OR_e60_lhmedium_OR_e120_lhloose", "Tight", "FixedCutTightTrackOnly"},
161 {"e12_lhloose_L1EM10VH", "Signal", "2015_e12_lhloose_L1EM10VH", "Tight", "FixedCutTightTrackOnly"},
163 {"e12_lhloose_L1EM10VH", "*", "2015_e12_lhloose_L1EM10VH", "LooseBLayer", ""}
164 };
165
166 const char* mapPath = "ElectronEfficiencyCorrection/2015_2017/"
167 "rel21.2/Moriond_February2018_v2/map6.txt";
168 for(auto& cfg : toolConfigs)
169 for(int j=0;j<2;++j)
170 {
171 string name = "AsgElectronEfficiencyCorrectionTool/"
172 + ((j? "ElTrigEff_" : "ElTrigSF_")
173 + std::to_string(factory.size()/2));
174 auto t = factory.emplace(factory.end(), name);
175 t->setProperty("MapFilePath", mapPath).ignore();
176 t->setProperty("TriggerKey", string(j?"":"Eff_") + cfg[cKEY]).ignore();
177 t->setProperty("IdKey", cfg[cPID]).ignore();
178 t->setProperty("IsoKey", cfg[cISO]).ignore();
179
180 t->setProperty("CorrelationModel", "TOTAL").ignore();
181 t->setProperty("ForceDataType", (int)PATCore::ParticleDataType::Full).ignore();
182 if(t->initialize() != StatusCode::SUCCESS)
183 {
184 Error(MSGSOURCE, "Unable to initialize the electron CP tool <%s>!",
185 t->name().c_str());
186 return 3;
187 }
188 auto& handles = (j? electronSFTools : electronEffTools);
189 handles.push_back(t->getHandle());
192 name = handles[handles.size()-1].name();
193 legsPerTool[name] = cfg[cLEGS];
194 tagsPerTool[name] = cfg[cTAG];
195 if(!j)
196 {
197 for(auto& tag : ::split_comma_delimited(cfg[cTAG]))
198 {
199 if(legsPerTag[tag]=="") legsPerTag[tag] = cfg[cLEGS];
200 else legsPerTag[tag] += "," + cfg[cLEGS];
201 }
202 }
203
204 }
205
206 /* ********************************************************************** */
207
208 Info(MSGSOURCE, "Configuring the global trigger SF tool");
209 asg::AnaToolHandle<ITrigGlobalEfficiencyCorrectionTool> myTool("TrigGlobalEfficiencyCorrectionTool/TrigGlobal");
210 myTool.setProperty("ElectronEfficiencyTools", electronEffTools).ignore();
211 myTool.setProperty("ElectronScaleFactorTools", electronSFTools).ignore();
212 const char* triggers2015 =
213 "e24_lhmedium_L1EM20VH_OR_e60_lhmedium_OR_e120_lhloose"
214 "|| 2e12_lhloose_L12EM10VH";
215 myTool.setProperty("TriggerCombination2015", triggers2015).ignore();
216 myTool.setProperty("LeptonTagDecorations", "Signal").ignore();
217 myTool.setProperty("ListOfLegsPerTool", legsPerTool).ignore();
218 myTool.setProperty("ListOfTagsPerTool", tagsPerTool).ignore();
219 myTool.setProperty("ListOfLegsPerTag", legsPerTag).ignore();
220
221 if(debug) myTool.setProperty("OutputLevel", MSG::DEBUG).ignore();
222 if(toys) myTool.setProperty("NumberOfToys", 1000).ignore();
223 if(myTool.initialize() != StatusCode::SUCCESS)
224 {
225 Error(MSGSOURCE, "Unable to initialize the TrigGlob tool!");
226 return 3;
227 }
228
231 const unsigned periodRuns[] = {
233 276073, 278727, 279932, 280423, 281130, 282625
234 };
235 std::uniform_int_distribution<unsigned> uniformPdf(0,
236 sizeof(periodRuns)/sizeof(*periodRuns) - 1);
237 std::default_random_engine randomEngine;
238
239 static const SG::ConstAccessor<int> truthType("truthType");
240 static const SG::ConstAccessor<int> truthOrigin("truthOrigin");
241
242 /* ********************************************************************** */
243
244 Info(MSGSOURCE, "Starting the event loop");
245 unsigned errors = 0;
246 double nSuitableEvents = 0., sumW = 0.;
247 static const SG::Decorator<unsigned> RandomRunNumberDec("RandomRunNumber");
248 for(Long64_t entry = 0; entry < entries; ++entry)
249 {
250 event.getEntry(entry);
251
253 const xAOD::EventInfo* eventInfo = nullptr;
254 event.retrieve(eventInfo,"EventInfo").ignore();
255 unsigned runNumber = periodRuns[uniformPdf(randomEngine)];
256 RandomRunNumberDec(*eventInfo) = runNumber;
257 vector<const xAOD::Electron*> myTriggeringElectrons;
258 const xAOD::ElectronContainer* electrons = nullptr;
259 event.retrieve(electrons,"Electrons").ignore();
260 for(auto electron : *electrons)
261 {
262 if(!electron->caloCluster()) continue;
263 float eta = fabs(electron->caloCluster()->etaBE(2));
264 float pt = electron->pt();
265 if(pt<10e3f || eta>=2.47) continue;
266 if(!truthType.isAvailable(*electron)) continue;
267 if(!truthOrigin.isAvailable(*electron)) continue;
268 int t = truthType(*electron), o = truthOrigin(*electron);
269 if(t!=2 || !(o==10 || (o>=12 && o<=22) || o==43)) continue;
271 if(pt < 13e3f) continue;
272
273 myTriggeringElectrons.push_back(electron);
274 }
275
276 vector<const xAOD::Muon*> myTriggeringMuons;
277
278 if(myTriggeringElectrons.size() < 1) continue;
279
282 auto compareByPt = [](const xAOD::Electron*e1, const xAOD::Electron*e2)
283 { return e1->pt() < e2->pt(); };
284 auto leadingElectron = *std::max_element(myTriggeringElectrons.begin(),
285 myTriggeringElectrons.end(), compareByPt);
286 for(auto electron : myTriggeringElectrons)
287 {
290 dec_signal(*electron) = (electron==leadingElectron)? 1 : 0;
291 }
292
294 if(leadingElectron->pt() < 25e3f
295 && myTriggeringElectrons.size() < 2)
296 {
297 continue;
298 }
299
300
302 double sf = 1.;
303 auto cc = myTool->getEfficiencyScaleFactor(myTriggeringElectrons,
304 myTriggeringMuons, sf);
306 {
307 nSuitableEvents += 1;
308 sumW += sf;
309 }
310 else
311 {
312 Warning(MSGSOURCE, "Scale factor evaluation failed");
313 ++errors;
314 }
315 if(errors>10)
316 {
317 Error(MSGSOURCE, "Too many errors reported!");
318 break;
319 }
320 }
321 Info(MSGSOURCE, "Average scale factor: %f (over %ld events)",
322 sumW / nSuitableEvents, long(nSuitableEvents));
323 #ifndef XAOD_STANDALONE
324 ANA_CHECK(app->finalize());
325 #endif
326 return errors? 4 : 0;
327}
328
330namespace
331{
332 inline vector<string> split_comma_delimited(const string& s)
333 {
334 std::stringstream ss(s);
335 std::vector<std::string> tokens;
336 std::string token;
337 while(std::getline(ss, token, ','))
338 {
339 if(token.length()) tokens.push_back(token);
340 }
341 return tokens;
342 }
343}
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
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.
Electron_v1 Electron
Definition of the current "egamma version".
#define MSGSOURCE
Test code to test ElectronPhotonVariableCorrectionTool Dictionaries.
TFile * file