ATLAS Offline Software
Loading...
Searching...
No Matches
MuonTriggerSFRootCoreTest.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4
5// Script for testing MuonTriggerScaleFactors. For example run with following command: MuonTriggerSFRootCoreTest -x AOD.11499205._000007.pool.root.1 -y 2015 -mc mc15a -t HLT_mu24 -r 278727
6
7// System include(s):
8#include <string>
9
10// ROOT include(s):
11#include <TFile.h>
12#include <TError.h>
13#include <TStopwatch.h>
14#include <TString.h>
15
16// Infrastructure include(s):
17#ifdef ROOTCORE
18# include "xAODRootAccess/Init.h"
21# include "AsgMessaging/Check.h"
22#endif // ROOTCORE
23
24// EDM include(s):
27
28// Local include(s):
32
33
34
35
36
37
38#define CHECK_CPSys(Arg) \
39 if (Arg.isFailure()){ \
40 Warning(#Arg,"Unsupported systematic (in line %i) ",__LINE__); \
41 }
42
43static const std::vector<std::string> qualities { "HighPt", "Tight", "Medium", "Loose", "LowPt" };
44static const std::vector<std::string> binnings { "coarse", "fine" };
45static const std::vector<std::string> types { "data", "mc" };
46
47// Copied from MuonTriggerScaleFactors.cxx
48CP::CorrectionCode getThreshold(Int_t& threshold, const std::string& trigger) {
49 std::size_t index = trigger.find("HLT_mu");
50 if (index != std::string::npos) {
51 std::string rawNumber = trigger.substr(index + 6);
52 if (!rawNumber.empty() && isdigit(rawNumber[0])) {
53 std::stringstream(rawNumber) >> threshold;
54 if (threshold < 10) threshold = 10000;
55 else threshold = (threshold + 1) * 1000;
57 }
58 }
60}
61
63
64public:
65 MuonTriggerSFTester(const char* appName, const std::string& trigger) :
66 m_errorsCount (0),
68 m_systematics (CP::make_systematics_vector(CP::SystematicRegistry::getInstance().recommendedSystematics())),
69 m_appName (appName),
70 m_trigger (trigger)
71 {
72 }
73
74 int initialiseTools(const std::string& customFileName, const std::string& customInputFolder, int year, const std::string& period){
75 for (size_t i = 0; i < qualities.size(); i++) {
76 std::vector<CP::MuonTriggerScaleFactors*> tools{};
77 for (size_t j = 0; j < binnings.size(); j++) {
79 ASG_CHECK_SA(m_appName, tool->setProperty("MuonQuality", qualities[i]));
80 ASG_CHECK_SA(m_appName, tool->setProperty("Binning", binnings[j]));
81 ASG_CHECK_SA(m_appName, tool->setProperty("filename", customFileName));
82 ASG_CHECK_SA(m_appName, tool->setProperty("CustomInputFolder", customInputFolder));
83 ASG_CHECK_SA(m_appName, tool->setProperty("UseExperimental", true));
84 ASG_CHECK_SA(m_appName, tool->setProperty("AllowZeroSF", true));
85 ASG_CHECK_SA(m_appName, tool->setProperty("forceYear", year));
86 ASG_CHECK_SA(m_appName, tool->setProperty("forcePeriod", period));
87
88 tool->msg().setLevel( MSG::WARNING );
89 ASG_CHECK_SA(m_appName, tool->initialize());
90 //CP::CorrectionCode result = tool->setRunNumber(atoi(runNumber));
91 //if (result != CP::CorrectionCode::Ok){
92 // Error(m_appName, "Could not set run number");
93 // return 1;
94 //}
95 tools.push_back(tool);
96 }
97 m_triggerSFTools.push_back(tools);
98 }
99 return 0;
100 }
101
102 int processEvent(xAOD::TEvent& event, int year, const std::string& period){
103 const xAOD::EventInfo* ei = nullptr;
104 RETURN_CHECK(m_appName, event.retrieve(ei, "EventInfo"));
105
106 const xAOD::MuonContainer* muons = nullptr;
107 RETURN_CHECK(m_appName, event.retrieve(muons, "Muons"));
108 if(year == -1 && period == "")
109 static const SG::AuxElement::ConstAccessor<unsigned int> acc_rnd("RandomRunNumber");
110 for (size_t i = 0; i < qualities.size(); i++) {
111 for (size_t j = 0; j < binnings.size(); j++) {
112 for (size_t k = 0; k < m_systematics.size(); k++) {
113 if(m_trigger == "HLT_mu26_ivarmedium" || m_trigger == "HLT_mu50" || m_trigger == "HLT_mu26_ivarmedium_OR_HLT_mu50")
114 checkSingleMuonTrigger(ei, muons, i, j, k);
115 if(muons->size() != 2)
116 continue;
117 if(binnings[j] == "coarse")
118 continue; // not supported right now
119 if(m_trigger == "HLT_2mu14" || m_trigger == "HLT_2mu10"){
120 checkSymDiMuonTrigger(ei, muons, i, j, k);
121 }
122 else{
123 for(auto muon : *muons)
124 checkASymDiMuonTrigger(ei, *muon, i, j, k);
125 }
126 }
127 }
128 }
129 return 0;
130 }
131
132 int checkASymDiMuonTrigger(const xAOD::EventInfo* ei, const xAOD::Muon& muon, unsigned int iquality, unsigned int ibin, unsigned int isystematic){
133 CHECK_CPSys(m_triggerSFTools[iquality][ibin]->applySystematicVariation(m_systematics[isystematic]));
134
135 Int_t threshold = 0;
138 Error("MuonTriggerSFRootCoreTest", "Could not extract threshold for trigger %s", m_trigger.c_str());
139 return 1;
140 }
141 if (muon.pt() < threshold or std::abs(muon.eta()) > 2.5)
142 return 1;
143
144 bool displayWarning = false;
145
146
147
148 double efficiencyMC = 0.;
149 double efficiencyData = 0.;
150
151 result = m_triggerSFTools[iquality][ibin]->getTriggerEfficiency(muon,
152 efficiencyMC,
153 m_trigger,
154 false);
156 Error(m_appName, "Could not retrieve MC efficeincy. Parameters:\n Event number = %i,\n Quality = %s,\n Binning = %s,\n Systematic = %s", static_cast<int>(ei->eventNumber()), qualities[iquality].c_str(), binnings[ibin].c_str(), m_systematics[isystematic].name().c_str());
158 }
159
160 result = m_triggerSFTools[iquality][ibin]->getTriggerEfficiency(muon,
161 efficiencyData,
162 m_trigger,
163 true);
165 Error(m_appName, "Could not retrieve data efficeincy. Parameters:\n Event number = %i,\n Quality = %s,\n Binning = %s,\n Systematic = %s", static_cast<int>(ei->eventNumber()), qualities[iquality].c_str(), binnings[ibin].c_str(), m_systematics[isystematic].name().c_str());
167 }
168 auto triggerSF = efficiencyMC/efficiencyData;
169 if (triggerSF < 0.2 || triggerSF > 1.2) {
170 if (displayWarning) {
171 Warning(m_appName, "Retrieved trigger scale factor %.3f is outside of expected range from 0.2 to 1.2. Parameters:\n Event number = %i,\n Quality = %s,\n Binning = %s,\n Systematic = %s", triggerSF, static_cast<int>(ei->eventNumber()), qualities[iquality].c_str(), binnings[ibin].c_str(), m_systematics[isystematic].name().c_str());
173 }
174 }
175 return 0;
176 }
177
178 int checkSymDiMuonTrigger(const xAOD::EventInfo* ei, const xAOD::MuonContainer* muons, unsigned int iquality, unsigned int ibin, unsigned int isystematic){
179 CHECK_CPSys(m_triggerSFTools[iquality][ibin]->applySystematicVariation(m_systematics[isystematic]));
180 double triggerSF = 0.;
182 result = m_triggerSFTools[iquality][ibin]->getTriggerScaleFactor(*muons, triggerSF, m_trigger);
184 Error(m_appName, "Could not retrieve trigger scale factors. Parameters:\n Event number = %i,\n Quality = %s,\n Binning = %s,\n Systematic = %s", static_cast<int>(ei->eventNumber()), qualities[iquality].c_str(), binnings[ibin].c_str(), m_systematics[isystematic].name().c_str());
186 }
187 if (triggerSF < 0.2 || triggerSF > 1.2) {
188 // Allow scale factor to be outside of this range in case all the muons are below the threshold
189 Int_t threshold = 0;
192 Error("MuonTriggerSFRootCoreTest", "Could not extract threshold for trigger %s", m_trigger.c_str());
193 return 1;
194 }
195 bool displayWarning = false;
197 for (xAOD::MuonContainer::const_iterator mu_itr = muons->begin(); mu_itr != mu_end; ++mu_itr) {
198 if ((**mu_itr).pt() >= threshold and std::abs((**mu_itr).eta()) < 2.5) displayWarning = true;
199 }
200
201 if (displayWarning) {
202 Warning(m_appName, "Retrieved trigger scale factor %.3f is outside of expected range from 0.2 to 1.2. Parameters:\n Event number = %i,\n Quality = %s,\n Binning = %s,\n Systematic = %s", triggerSF, static_cast<int>(ei->eventNumber()), qualities[iquality].c_str(), binnings[ibin].c_str(), m_systematics[isystematic].name().c_str());
204 }
205 }
206
207 return 0;
208 }
209
210
211 int checkSingleMuonTrigger(const xAOD::EventInfo* ei, const xAOD::MuonContainer* muons, unsigned int iquality, unsigned int ibin, unsigned int isystematic){
212
213 CHECK_CPSys(m_triggerSFTools[iquality][ibin]->applySystematicVariation(m_systematics[isystematic]));
216 for (xAOD::MuonContainer::const_iterator mu_itr = muons->begin(); mu_itr != mu_end; ++mu_itr) {
217 for (size_t l = 0; l < types.size(); l++) {
218 if (types[l] != "data" || m_systematics[isystematic].name().find("TrigSystUncertainty") == std::string::npos) {
219 Double_t eff;
220 auto binNumber = m_triggerSFTools[iquality][ibin]->getBinNumber(**mu_itr, m_trigger);
221 result = m_triggerSFTools[iquality][ibin]->getTriggerEfficiency(**mu_itr, eff, m_trigger, types[l] == "data");
223 Error(m_appName, "Could not retrieve trigger efficiency. Paramaters:\n Event number = %i,\n Quality = %s,\n Binning = %s,\n Systematic = %s,\n Type = %s ", static_cast<int>(ei->eventNumber()), qualities[iquality].c_str(), binnings[ibin].c_str(), m_systematics[isystematic].name().c_str(), types[l].c_str());
225 }
226 if (eff < 0 || eff > 1) {
227 Warning(m_appName, "Retrieved trigger efficiency %.3f is outside of expected range from 0 to 1. Paramaters:\n Event number = %i,\n Quality = %s,\n Binning = %s,\n Systematic = %s", eff, static_cast<int>(ei->eventNumber()), qualities[iquality].c_str(), binnings[ibin].c_str(), m_systematics[isystematic].name().c_str());
229 }
230 if (binNumber < 0 || binNumber > 238) {
231 Warning(m_appName, "Retrieved bin number %.i is outside of expected range from 0 to 238. Paramaters:\n Event number = %i,\n Quality = %s,\n Binning = %s,\n Systematic = %s", binNumber, static_cast<int>(ei->eventNumber()), qualities[iquality].c_str(), binnings[ibin].c_str(), m_systematics[isystematic].name().c_str());
233 }
234
235 }
236 }
237 }
238
239 double triggerSF = 0.;
240 result = m_triggerSFTools[iquality][ibin]->getTriggerScaleFactor(*muons, triggerSF, m_trigger);
242 Error(m_appName, "Could not retrieve trigger scale factors. Parameters:\n Event number = %i,\n Quality = %s,\n Binning = %s,\n Systematic = %s", static_cast<int>(ei->eventNumber()), qualities[iquality].c_str(), binnings[ibin].c_str(), m_systematics[isystematic].name().c_str());
244 }
245 if (triggerSF < 0.2 || triggerSF > 1.2) {
246 // Allow scale factor to be outside of this range in case all the muons are below the threshold
247 Int_t threshold = 0;
250 Error("MuonTriggerSFRootCoreTest", "Could not extract threshold for trigger %s", m_trigger.c_str());
251 return 1;
252 }
253 bool displayWarning = false;
255 for (xAOD::MuonContainer::const_iterator mu_itr = muons->begin(); mu_itr != mu_end; ++mu_itr) {
256 if ((**mu_itr).pt() >= threshold and std::abs((**mu_itr).eta()) < 2.5) displayWarning = true;
257 }
258
259 if (displayWarning) {
260 Warning(m_appName, "Retrieved trigger scale factor %.3f is outside of expected range from 0.2 to 1.2. Parameters:\n Event number = %i,\n Quality = %s,\n Binning = %s,\n Systematic = %s", triggerSF, static_cast<int>(ei->eventNumber()), qualities[iquality].c_str(), binnings[ibin].c_str(), m_systematics[isystematic].name().c_str());
262 }
263 }
264 double tmpEffData = 1.;
265 double tmpEffMC = 1.;
266 for (auto muon: *muons) {
267 double effData = 0.;
268 double effMC = 0.;
269 double scaleFactor = 0.;
270 if (m_triggerSFTools[iquality][ibin]->getTriggerEfficiency(*muon, effData, m_trigger, true) != CP::CorrectionCode::Ok) {
271 Error("MuonTriggerSFRootCoreTest", "Could not extract data trigger efficiency for %s which is %f. Parameters:\n Event number = %i,\n Quality = %s,\n Binning = %s,\n Systematic = %s \n muon pt: %f \n eta: %f \n phi: %f", m_trigger.c_str(), scaleFactor, static_cast<int>(ei->eventNumber()), qualities[iquality].c_str(), binnings[ibin].c_str(), m_systematics[isystematic].name().c_str(), muon->pt(), muon->eta(), muon->phi());
272 return 1;
273 }
274 if (m_triggerSFTools[iquality][ibin]->getTriggerEfficiency(*muon, effMC, m_trigger, false) != CP::CorrectionCode::Ok) {
275 Error("MuonTriggerSFRootCoreTest", "Could not extract MC trigger efficiency for %s", m_trigger.c_str());
276 return 1;
277 }
278 if (m_triggerSFTools[iquality][ibin]->getTriggerScaleFactor(*muon, scaleFactor, m_trigger) != CP::CorrectionCode::Ok) {
279 Error("MuonTriggerSFRootCoreTest", "Could not extract MC trigger efficiency for %s", m_trigger.c_str());
280 return 1;
281 }
282 if (scaleFactor < 0.2 || scaleFactor > 1.2 ) {
283 Int_t threshold = 0;
285 Error("MuonTriggerSFRootCoreTest", "Could not extract threshold for trigger %s", m_trigger.c_str());
286 return 1;
287 }
288 if(muon->pt() >= threshold and std::abs(muon->eta()) < 2.5)
289 Warning(m_appName, "Retrieved single muon trigger scale factor %.3f is outside of expected range from 0.2 to 1.2. Parameters:\n Event number = %i,\n Quality = %s,\n Binning = %s,\n Systematic = %s \n muon pt: %f \n eta: %f \n phi: %f", scaleFactor, static_cast<int>(ei->eventNumber()), qualities[iquality].c_str(), binnings[ibin].c_str(), m_systematics[isystematic].name().c_str(), muon->pt(), muon->eta(), muon->phi());
290 }
291 tmpEffData *= 1.-effData;
292 tmpEffMC *= 1.-effMC;
293 }
294 auto sfSingleCalc = (1. - tmpEffData)/(1. - tmpEffMC);
295 if ( triggerSF > 0.2 && (sfSingleCalc - triggerSF) / triggerSF > 0.02) {
296
297 // Warning(m_appName, "Invalid single muon SF result. Parameters:\n Event number = %i,\n Quality = %s,\n Binning = %s \n Systematic = %s \n single SF: %f \n combined SF %f \n ", static_cast<int>(ei->eventNumber()), qualities[iquality].c_str(), binnings[ibin].c_str(), systematics[isystematic].name().c_str(), sfSingleCalc, triggerSFrSF);
299 }
300 return 0;
301 }
302
303
304public:
307
308private:
309 std::vector<std::vector<CP::MuonTriggerScaleFactors*>> m_triggerSFTools;
310 std::vector<CP::SystematicSet> m_systematics;
311 const char* m_appName;
312 std::string m_trigger;
313
314};
315
316
317int main(int argc, char* argv[]) {
318
319 const char* APP_NAME = argv[0];
321 // Read the config provided by the user
322 const char* xAODFileName = "";
323 std::string customInputFolder = "";
324 std::string customFileName = "";
325 const char* nrOfEntries = "";
326 std::string trigger = "";
327 int year = -1;
328 std::string period = "";
329 for (int i = 1; i < argc - 1; i++) {
330 std::string arg = std::string(argv[i]);
331 if (arg == "-x") {
332 xAODFileName = argv[i + 1];
333 }
334 else if (arg == "-d")
335 customInputFolder = argv[i + 1];
336 else if (arg == "-f")
337 customFileName = argv[i + 1];
338 else if (arg == "-e")
339 nrOfEntries = argv[i + 1];
340 else if (arg == "-t")
341 trigger = argv[i + 1];
342 else if (arg == "-y")
343 year = atoi(argv[i + 1]);
344 else if (arg == "-p")
345 period = argv[i + 1];
346 }
347
348 bool error = false;
349 if (xAODFileName[0] == '\0') {
350 Error(APP_NAME, "xAOD file name missing!");
351 error = true;
352 }
353 if (trigger == "") {
354 Error(APP_NAME, "trigger missing!");
355 error = true;
356 }
357 if (error) {
358 Error(APP_NAME, " Usage: %s -x [xAOD file name] -y [year] -p [period] -t [trigger] -d [custom input folder] -f [custom file name] -e [number of events to process]", APP_NAME);
359 return 1;
360 }
361
363
364 Info(APP_NAME, "Opening file: %s", xAODFileName);
365 std::unique_ptr<TFile> ifile(TFile::Open(xAODFileName, "READ"));
366 if (!ifile.get()) {
367 Error(APP_NAME, " Unable to load xAOD input file");
368 return 1;
369 }
370
371 xAOD::TEvent event;
372 RETURN_CHECK(APP_NAME, event.readFrom(ifile.get(), xAOD::TEvent::kClassAccess));
373 Info(APP_NAME, "Number of events in the file: %i", static_cast<int>(event.getEntries()));
374
375 // Decide how many events to run over:
376 int nrOfEntriesToRunOver = 1000;//event.getEntries();
377 if (!std::string(nrOfEntries).empty()) {
378 int e = atoll(nrOfEntries);
379 if (e < nrOfEntriesToRunOver) {
380 nrOfEntriesToRunOver = e;
381 }
382 }
383
384
385 MuonTriggerSFTester sfChecker(APP_NAME, trigger);
386 sfChecker.initialiseTools(customFileName, customInputFolder, year, period);
387 for(Long64_t entry = 0; entry < nrOfEntriesToRunOver; entry++) {
388 // Tell the object which entry to look at:
389 event.getEntry(entry);
390 sfChecker.processEvent(event, year, period);
391
392 }
393
394 Info(APP_NAME, "%i events successfully processed, %i warnings, %i errors detected.", nrOfEntriesToRunOver, sfChecker.m_warningsCount, sfChecker.m_errorsCount);
395 return 0;
396}
397
#define APP_NAME
#define ASG_CHECK_SA(SOURCE, EXP)
Helper macro for checking the status code of a call outside of an ASG tool.
Definition Check.h:76
static const std::vector< std::string > qualities
static const std::vector< std::string > types
#define CHECK_CPSys(Arg)
static const std::vector< std::string > qualities
static const std::vector< std::string > binnings
CP::CorrectionCode getThreshold(Int_t &threshold, const std::string &trigger)
static const std::vector< std::string > types
#define RETURN_CHECK(CONTEXT, EXP)
Helper macro for checking return codes in a compact form in the code.
Definition ReturnCheck.h:26
static const Attributes_t empty
Return value from object correction CP tools.
@ Error
Some error happened during the object correction.
@ Ok
The correction was done successfully.
static void enableFailure() noexcept
DataModel_detail::const_iterator< DataVector > const_iterator
Definition DataVector.h:838
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
size_type size() const noexcept
Returns the number of elements in the collection.
int processEvent(xAOD::TEvent &event, int year, const std::string &period)
std::vector< std::vector< CP::MuonTriggerScaleFactors * > > m_triggerSFTools
int initialiseTools(const std::string &customFileName, const std::string &customInputFolder, int year, const std::string &period)
int checkASymDiMuonTrigger(const xAOD::EventInfo *ei, const xAOD::Muon &muon, unsigned int iquality, unsigned int ibin, unsigned int isystematic)
std::vector< CP::SystematicSet > m_systematics
MuonTriggerSFTester(const char *appName, const std::string &trigger)
int checkSymDiMuonTrigger(const xAOD::EventInfo *ei, const xAOD::MuonContainer *muons, unsigned int iquality, unsigned int ibin, unsigned int isystematic)
int checkSingleMuonTrigger(const xAOD::EventInfo *ei, const xAOD::MuonContainer *muons, unsigned int iquality, unsigned int ibin, unsigned int isystematic)
SG::ConstAccessor< T, ALLOC > ConstAccessor
Definition AuxElement.h:569
This module implements the central registry for handling systematic uncertainties with CP tools.
uint64_t eventNumber() const
The current event's event number.
Tool for accessing xAOD files outside of Athena.
@ kClassAccess
Access auxiliary data using the aux containers.
std::string find(const std::string &s)
return a remapped string
Definition hcg.cxx:138
int main()
Definition hello.cxx:18
Select isolated Photons, Electrons and Muons.
Definition index.py:1
StatusCode Init(const char *appname)
Function initialising ROOT/PyROOT for using the ATLAS EDM.
Definition Init.cxx:31
EventInfo_v1 EventInfo
Definition of the latest event info version.
Muon_v1 Muon
Reference the current persistent version:
MuonContainer_v1 MuonContainer
Definition of the current "Muon container version".