ATLAS Offline Software
Loading...
Searching...
No Matches
TElectronEfficiencyCorrectionTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3 */
4
14
15// This class header
17// STL includes
18#include <cmath>
19#include <iostream>
20#include <memory>
21#include <cstring>
22// ROOT includes
23#include "TClass.h"
24#include "TFile.h"
25#include "TKey.h"
26#include "TMD5.h"
27#include "TObjString.h"
28#include "TROOT.h"
29#include "TString.h"
30#include "TSystem.h"
31
32namespace mapkey {
33// The "keys" below are indices for the vectors
34//(of size mapkey::end)
35// we use to look up the numbers we need
36enum key
37{
38 sf = 0,
39 stat = 1,
40 eig = 2,
41 uncorr = 3,
42 sys = 4,
43 end = 5
44};
45const char*
46keytostring(int input)
47{
48 switch (input) {
49 case (sf):
50 return "sf";
51 case (stat):
52 return "stat";
53 case (eig):
54 return "eig";
55 case (uncorr):
56 return "uncorr";
57 case (sys):
58 return "sys";
59 }
60 return "";
61}
62}
63
64namespace {
65char const * const LowPt_string = "LowPt" ;
66const std::vector<int> s_keys = { mapkey::sf,
70}
71
73 const char* name)
74 : asg::AsgMessaging(std::string(name))
75 , m_doToyMC(false)
76 , m_doCombToyMC(false)
77 , m_nToyMC(0)
78 , m_seed(0)
79 , m_nSysMax(0)
80 , m_histList{ mapkey::end }
81 , m_fastHistList{ mapkey::end }
82 , m_Rndm()
83{
84}
85
86int
88{
89 // use an int as a StatusCode
90 int sc(1);
91 // Check if files are present
92 if (m_corrFileNameList.empty()) {
93 ATH_MSG_ERROR(" No file added!");
94 return 0;
95 }
96 ATH_MSG_DEBUG("Initializing tool with " << m_corrFileNameList.size()
97 << " configuration file(s)");
98
99 if (m_doToyMC && m_doCombToyMC) {
100 ATH_MSG_ERROR(" Both regular and combined toy MCs booked!"
101 << " Only use one!");
102 return 0;
103 }
104 /*
105 * initialize the random number generator if toyMC propagation booked
106 * Use the 1st 4 bytes of the CheckSum of the reccomendation file as seed
107 */
108 if (m_doToyMC || m_doCombToyMC) {
109 if (m_seed == 0) {
110 // Use the name of the correction for auto-setting of the seed based on
111 // the md5-sum of the file
112 const std::unique_ptr<char[]> fname(
113 gSystem->ExpandPathName(m_corrFileNameList[0].c_str()));
114 std::unique_ptr<TMD5> tmd = std::make_unique<TMD5>();
115 const char* tmd_as_string = TMD5::FileChecksum(fname.get())->AsString();
116 m_seed = *(reinterpret_cast<const unsigned long int*>(tmd_as_string));
117 ATH_MSG_DEBUG("Seed (automatically) set to " << m_seed);
118 } else {
119 ATH_MSG_DEBUG("Seed set to " << m_seed);
120 }
121 m_Rndm = TRandom3(m_seed);
122 }
123 /*
124 * Load the needed histograms
125 */
126 if (0 == getHistograms()) {
127 ATH_MSG_ERROR(" (file: " << __FILE__ << ", line: " << __LINE__ << ")\n"
128 << "! Problem when calling getHistograms()");
129 return 0;
130 }
131 const unsigned int nRunNumbersFull = m_begRunNumberList.size();
132 const unsigned int nRunNumbersFast = m_begRunNumberListFastSim.size();
133
134 ATH_MSG_DEBUG(" (file: " << __FILE__ << ", line: " << __LINE__ << ")\n"
135 << "Found " << nRunNumbersFast
136 << " run number ranges for fast sim with a total of "
138 << " scale factor histograms.");
139
140 ATH_MSG_DEBUG(" (file: " << __FILE__ << ", line: " << __LINE__ << ")\n"
141 << "Found " << nRunNumbersFull
142 << " run number ranges for full sim with a total of "
144 << " scale factor histograms.");
145
146 ATH_MSG_DEBUG("Tool succesfully initialized!");
147
148 return sc;
149}
150
152{
153 const bool isFastSim = dataType == PATCore::ParticleDataType::Fast;
154 const auto& currentmap = (isFastSim) ? m_fastHistList : m_histList;
155
156 return currentmap.at(mapkey::stat).empty() && currentmap.at(mapkey::uncorr).empty();
157}
158
159int
162 const unsigned int runnumber,
163 const double cluster_eta,
164 const double et, /* in MeV */
165 Result& result,
166 const bool onlyTotal) const
167{
168 // Set up the non-0 defaults
169 result.SF = -999;
170 result.Total = 1;
171 /*
172 * Determine Simulation flavour and find the run period
173 */
174 const bool isFastSim = dataType == PATCore::ParticleDataType::Fast;
175 int runnumberIndex = -1;
176 if (isFastSim) {
177 for (unsigned int i = 0; i < m_begRunNumberListFastSim.size(); ++i) {
180 runnumberIndex = i;
181 break;
182 }
183 }
184 } else {
185 for (unsigned int i = 0; i < m_begRunNumberList.size(); ++i) {
186 if (m_begRunNumberList[i] <= runnumber &&
188 runnumberIndex = i;
189 break;
190 }
191 }
192 }
193 if (runnumberIndex < 0) {
194 return 0;
195 }
196 /* What we have is a vector<vector<HistArray>> acting as a map:
197 * Key/Index is SF,Stat,Eigen,UnCorr
198 * The Entry in this index is a vector<HistArray>
199 * Each vector<HistArray> has as many entries as supported Run periods.
200 * Each HistArray has 2D histos (could be standard, low-et, or forward
201 * electrons) The 2D Histo then has the number we want. What follows is the
202 * logic to get to this number.
203 */
204 const auto& currentmap = (isFastSim) ? m_fastHistList : m_histList;
205 const std::vector<HistArray>& sfVector = currentmap.at(mapkey::sf);
206 /*
207 * See if we can find a vector for key SF in the map
208 * and then if we can get the corresponding HisArray
209 * for the run period.
210 */
211 if (sfVector.empty() || runnumberIndex >= static_cast<int>(sfVector.size())) {
212 return 0;
213 }
214 /*
215 * At this stage we have found the relevant period
216 * So we need to locate the right histogram.
217 */
218 const HistArray& sfObjectArray = sfVector[runnumberIndex];
219 const auto& edges = (isFastSim) ? m_fastHistEdges[runnumberIndex]
220 : m_histEdges[runnumberIndex];
221 const int entries = edges.size();
222 /*
223 * Now the logic of finding the histogram
224 * Some parts of the code can be perhaps improved ...
225 */
226 double xValue(et);
227 double yValue(cluster_eta);
228 int smallEt(0);
229 int etaCov(0);
230 int nSF(0);
231 bool invalid = false;
232 bool changedEt = false;
233 int index = -1;
234
235 for (int i = 0; i < entries; ++i) {
236 invalid = false;
237 const HistEdge& histEdge = edges[i];
238 // invalid if we are below minimum et
239 if (et < histEdge.etMin) {
240 smallEt++;
241 invalid = true;
242 }
243
244 // invalid if we are above max eta
245 if (std::abs(yValue) >= histEdge.etaMax) {
246 etaCov++;
247 invalid = true;
248 }
249 // invalid if we are less than minimum eta (forward electrons)
250 if (std::abs(yValue) < histEdge.etaMin) {
251 etaCov++;
252 invalid = true;
253 }
254 /*
255 * Invalid if above max et and is a low Et histogram.
256 * If not low Et histogram then change the xValue to the maximum
257 * availabe Et of ths histogram. As we assume that the SF stays the same
258 * for very high Et
259 */
260 if (et > histEdge.etMax) {
261 if (histEdge.isLowPt) {
262 invalid = true;
263 } else {
264 xValue = histEdge.etMax - 1000 ; //1000 is 1 GeV
265 changedEt = true;
266 }
267 }
268 /*
269 * Get the histogram index in the TObjArray
270 * Also mark how many times we found something
271 * as SF should be unique
272 */
273 if (!invalid) {
274 index = i;
275 if (!changedEt) {
276 nSF++;
277 }
278 }
279 }
280 if (smallEt == entries) {
281 return 0;
282 }
283 if (etaCov == entries) {
284 return 0;
285 }
286 if (nSF > 1) {
287 ATH_MSG_WARNING("More than 1 SF found for eta="
288 << yValue << " , et = " << et << " , run number = "
289 << runnumber << ". Please check your input files!");
290 }
291 if (index < 0) {
292 return 0;
293 }
294
295 /*
296 * Now we have the index of the histogram
297 */
298 const HistEdge& currentEdge = edges[index];
299 /*
300 * If SF is only given in Abs(eta) convert eta input to std::abs()
301 */
302 constexpr double epsilon = 1e-6;
303 if (currentEdge.etaMin >= (0 - epsilon)) {
304 yValue = std::abs(yValue);
305 }
306
307 const TH2* currentHist = static_cast<TH2*>(sfObjectArray[index].get()) ;
308 const int globalBinNumber = currentHist->FindFixBin(xValue, yValue);
309 const double scaleFactor = currentHist->GetBinContent(globalBinNumber);
310 const double scaleFactorErr = currentHist->GetBinError(globalBinNumber);
311 /*
312 * Write the retrieved values to the output
313 */
314 result.SF= scaleFactor;
315 result.Total = scaleFactorErr;
316 result.histIndex = index;
317 result.histBinNum = globalBinNumber;
318 /*
319 * if we only wanted the Total we can exit here
320 */
321 if (onlyTotal) {
322 return 1;
323 }
324 /*
325 * Do the stat error using the available info from the above (SF)
326 */
327 double statErr = -999;
328 const std::vector<HistArray>& statVector = currentmap.at(mapkey::stat);
329 if (runnumberIndex < static_cast<int> (statVector.size())) {
330 if (!statVector[runnumberIndex].empty()) {
331 statErr = static_cast<TH1*>(statVector[runnumberIndex][index].get())
332 ->GetBinContent(globalBinNumber);
333 result.Stat = statErr;
334 }
335 }
336 /*
337 * Do the Uncorr uncertainty
338 */
339 double val = statErr;
340 const std::vector<HistArray>& uncorrVector = currentmap.at(mapkey::uncorr);
341 if (runnumberIndex < static_cast<int>(uncorrVector.size())) {
342 if (!uncorrVector.at(runnumberIndex).empty()) {
343 const double valAdd =
344 static_cast<TH1*>(uncorrVector[runnumberIndex][index].get())
345 ->GetBinContent(globalBinNumber);
346 val = sqrt(val * val + valAdd * valAdd);
347 }
348 }
349 result.UnCorr = val;
350 /*
351 * Do the correlated part
352 * For the N~16 systematic variations
353 * we keep them in a vector of vector of HistArray
354 * The first vector index being the runnumber
355 * The second the systematic
356 * And them the HistArray for high low etc.
357 */
358 result.Corr.resize(m_nSysMax);
359 const std::vector<std::vector<HistArray>>& sysList =
360 (isFastSim) ? m_fastSysList : m_sysList;
361 if (sysList.size() > static_cast<unsigned int>(index)) {
362 if (sysList.at(index).size() > static_cast<unsigned int>(runnumberIndex)) {
363 const int sys_entries = sysList.at(index).at(runnumberIndex).size();
364 for (int sys = 0; sys < sys_entries; ++sys) {
365 double sysVal =
366 static_cast<TH2*>(sysList[index][runnumberIndex][sys].get())
367 ->GetBinContent(globalBinNumber);
368 result.Corr[sys] = sysVal;
369 }
370 }
371 }
372 /*
373 * Do the toys if requested
374 */
375 if (m_doToyMC || m_doCombToyMC) {
376 result.toys.resize(static_cast<size_t>(m_nToyMC));
377 const std::vector<std::vector<HistArray>>& toyMCList =
379 if (toyMCList.size() > (unsigned int)runnumberIndex) {
380 for (int toy = 0; toy < m_nToyMC; ++toy) {
381 if (toyMCList[runnumberIndex][toy].size() >
382 static_cast<unsigned int>(index)) {
383 result.toys[toy] =
384 static_cast<TH2*>(toyMCList[runnumberIndex][toy][index].get())
385 ->GetBinContent(globalBinNumber);
386 }
387 }
388 }
389 }
390 return 1;
391}
392/*
393 * Build the toyMC tables from inputs
394 * Ownership should be tranfered to the map of the tables
395 * and the proper delete happens in the dtor
396 */
397std::vector<TH2*>
399 const TH1* sf,
400 const TH1* stat,
401 const TH1* uncorr,
402 const std::vector<TH1*>& corr,
403 int& randomCounter)
404{
405 ATH_MSG_DEBUG(" (file: " << __FILE__ << ", line: " << __LINE__ << ")! "
406 << "Entering function buildSingleToyMC");
407 std::vector<TH2*> tmpHists;
408 int nBins = (stat->GetNbinsX() + 2) * (stat->GetNbinsY() + 2);
409 tmpHists.reserve(m_nToyMC);
410 for (int toy = 0; toy < m_nToyMC; toy++) {
411 tmpHists.push_back((TH2*)corr.at(0)->Clone());
412 }
413 // Loop over all bins
414 for (int bin = 0; bin < nBins; bin++) {
415 double val = stat->GetBinContent(bin);
416
417 // Add uncorrelated systematics
418 if (uncorr != nullptr) {
419 double valAdd = uncorr->GetBinContent(bin);
420 val = sqrt(val * val + valAdd * valAdd);
421 }
422 for (int toy = 0; toy < m_nToyMC; toy++) {
423 tmpHists.at(toy)->SetBinContent(
424 bin, (val * m_Rndm.Gaus(0, 1)) + sf->GetBinContent(bin));
425 randomCounter++;
426 tmpHists.at(toy)->SetDirectory(nullptr);
427 }
428 }
429 return tmpHists;
430}
431/*
432 * Build the combined toyMC tables from inputs
433 * Ownership should be tranfered to the unique_ptr
434 * in the lookup tables and the proper delete
435 * happens in the dtor
436 */
437TH2*
439 const TH1* sf,
440 const TH1* stat,
441 const TH1* uncorr,
442 const std::vector<TH1*>& corr,
443 const int nSys,
444 int& randomCounter)
445{
446
447 ATH_MSG_DEBUG(" (file: " << __FILE__ << ", line: " << __LINE__ << ")\n"
448 << "Entering function buildSingleCombToyMC");
449
450 TH2* tmpHist;
451 const int nBins = (stat->GetNbinsX() + 2) * (stat->GetNbinsY() + 2);
452 tmpHist = (TH2*)corr.at(0)->Clone();
453 // Create random numbers for the corr. uncertainties
454 std::vector<double> rnd(nSys, 0);
455 for (int s = 0; s < nSys; ++s) {
456 rnd[s] = m_Rndm.Gaus(0, 1);
457 randomCounter++;
458 }
459 // Loop over all bins
460 for (int bin = 0; bin < nBins; ++bin) {
461 double val = stat->GetBinContent(bin);
462
463 // Add uncorrelated systematics
464 if (uncorr != nullptr) {
465 double valAdd = uncorr->GetBinContent(bin);
466 val = sqrt(val * val + valAdd * valAdd);
467 }
468 val = val * m_Rndm.Gaus(0, 1);
469 randomCounter++;
470 // Add larger correlated systematics
471 for (int s = 0; s < nSys; ++s) {
472 if (corr.at(s) != nullptr) {
473 val += static_cast<TH2*>(corr.at(s))->GetBinContent(bin) * rnd[s];
474 }
475 }
476 tmpHist->SetBinContent(bin, val + sf->GetBinContent(bin));
477 }
478 tmpHist->SetDirectory(nullptr);
479 return tmpHist;
480}
481/*
482 * Build the toyMC tables from inputs
483 */
484std::vector<Root::TElectronEfficiencyCorrectionTool::HistArray>
486 const std::vector<TH1*>& sf,
487 const std::vector<TH1*>& eig,
488 const std::vector<TH1*>& stat,
489 const std::vector<TH1*>& uncorr,
490 const std::vector<std::vector<TH1*>>& corr)
491{
492
493 ATH_MSG_DEBUG(" (file: " << __FILE__ << ", line: " << __LINE__ << ")\n"
494 << "Entering function buildToyMCTable");
495
496 int nSys{};
497 int randomCounter(0);
498 std::vector<HistArray> tmpVec;
499 const int stat_entries = stat.size();
500 if (m_doCombToyMC) {
501 for (int toyMC = 0; toyMC < m_nToyMC; toyMC++) {
502 HistArray tmpArray;
503 for (int i = 0; i < stat_entries; ++i) {
504 if (!eig.empty() && !uncorr.empty()) {
505 nSys = (eig.at(i))->GetNbinsX() - 1;
506 tmpArray.emplace_back(buildSingleCombToyMC(sf.at(i),
507 stat.at(i),
508 uncorr.at(i),
509 corr.at(i),
510 nSys,
511 randomCounter));
512 } else {
513 tmpArray.emplace_back(buildSingleCombToyMC(sf.at(i),
514 stat.at(i),
515 nullptr,
516 corr.at(i),
517 nSys,
518 randomCounter));
519 }
520 }
521 tmpVec.emplace_back(std::move(tmpArray));
522 }
523 } else {
524 std::vector<std::vector<TH2*>> tmpVec2;
525 if (!eig.empty() and !uncorr.empty())[[likely]]{
526 for (int i = 0; i < stat_entries; ++i) {
527 nSys = (eig.at(i))->GetNbinsX() - 1;
528 tmpVec2.push_back(buildSingleToyMC(sf.at(i),
529 stat.at(i),
530 uncorr.at(i),
531 corr.at(i),
532 randomCounter));
533 }
534 }
535 for (int toy = 0; toy < m_nToyMC; toy++) {
536 HistArray tmpArray;
537 for (auto& i : tmpVec2) {
538 tmpArray.emplace_back(i.at(toy));
539 }
540 tmpVec.emplace_back(std::move(tmpArray));
541 }
542 }
543 return tmpVec;
544}
545/*
546 * Helper function to retrieve number of uncorrelated bins
547 */
548int
550 std::map<float, std::vector<float>>& pt_eta1) const
551{
552 // Get sf histograms
553 const std::vector<HistArray>& tmpVec = (!m_histList[mapkey::sf].empty())
556
557 int nbinsTotal = 0;
558 pt_eta1.clear();
559 std::vector<float> eta1;
560 eta1.clear();
561
562 // Loop over the different Run range (one TObjeArray for each)
563 for (const auto& ikey : tmpVec) {
564 // Loop over the histograms for a given run numbers
565 for (const auto& entries : ikey) {
566 eta1.clear();
567 // Get number of bins
568 TH2* h_tmp = ((TH2*)entries.get());
569 int nbinsX = h_tmp->GetNbinsX();
570 int nbinsY = h_tmp->GetNbinsY();
571 // fill in the eta pushing back
572 for (int biny = 1; biny <= nbinsY; ++biny) {
573 eta1.push_back(h_tmp->GetYaxis()->GetBinLowEdge(biny));
574 }
575 // associate each pt (bin) with the corresponding/available eta ones
576 for (int binx = 1; binx <= nbinsX; ++binx) {
577 pt_eta1[h_tmp->GetXaxis()->GetBinLowEdge(binx)] = eta1;
578 }
579 }
580 }
581 for (auto& i : pt_eta1) {
582 nbinsTotal += i.second.size();
583 }
584 return nbinsTotal;
585}
586/*
587 * Get the histograms from the input files
588 */
589int
591{
592 ATH_MSG_DEBUG(" (file: " << __FILE__ << ", line: " << __LINE__ << ")\n"
593 << "Entering function getHistograms");
594 // Cache the current directory in the root file
595 TDirectory* origDir = gDirectory;
596 /*
597 * Get the name of the first input ROOT file and
598 * interpret from that what we have:
599 * efficiency vs. efficiencySF; offline vs. trigger; medium, loose,...
600 */
601 if (!m_corrFileNameList.empty()) {
602 TString firstFileNameAndPath = m_corrFileNameList[0].c_str();
603 std::unique_ptr<TObjArray> myStringList(firstFileNameAndPath.Tokenize("/"));
604 int lastIdx = myStringList->GetLast();
605 TString fileName = ((TObjString*)myStringList->At(lastIdx))->GetString();
606 std::unique_ptr<TObjArray> myFileNameTokensList(fileName.Tokenize("."));
607
608 if (myFileNameTokensList->GetLast() < 3) {
609 ATH_MSG_ERROR("input file name has wrong format!");
610 return 0;
611 }
612 }
613 /*
614 * Get all ROOT files and histograms
615 */
616 for (auto& ifile : m_corrFileNameList) {
617 // Load the ROOT file
618 const std::unique_ptr<char[]> fname(gSystem->ExpandPathName(ifile.c_str()));
619 std::unique_ptr<TFile> rootFile(TFile::Open(fname.get(), "READ"));
620 if (!rootFile) {
621 ATH_MSG_ERROR("No ROOT file found here: " << ifile);
622 return 0;
623 }
624 // Loop over all directories inside the root file (correspond to the run
625 // number ranges
626 TIter nextdir(rootFile->GetListOfKeys());
627 TKey* dir = nullptr;
628 TObject* obj = nullptr;
629 while ((dir = (TKey*)nextdir())) {
630 obj = dir->ReadObj();
631 if (obj->IsA()->InheritsFrom("TDirectory")) {
632 // splits string by delimiter --> e.g RunNumber1_RunNumber2
633 std::unique_ptr<TObjArray> dirNameArray(
634 TString(obj->GetName()).Tokenize("_"));
635 // returns index of last string --> if one, the directory name does not
636 // contain any run numbers
637 int lastIdx = dirNameArray->GetLast();
638 if (lastIdx != 1) {
640 "The folder name seems to have the wrong format! Directory name:"
641 << obj->GetName());
642 return 0;
643 }
644 rootFile->cd(obj->GetName());
645 if (0 == this->setupHistogramsInFolder(*dirNameArray, lastIdx)) {
646 ATH_MSG_ERROR("Unable to setup the histograms in directory "
647 << dir->GetName() << "in file " << ifile);
648 return 0;
649 }
650 } else {
651 ATH_MSG_ERROR("Wrong file content! Expected only Directories "
652 << gDirectory->cd());
653 return 0;
654 }
655 // Return to the original ROOT directory
656 gDirectory = origDir;
657 } // End: directory loop
658 } // End: file loop
659
660 // SF Histogram edges caching
662 size_t histListSize = m_histList.at(mapkey::sf).size();
663 size_t edgeListSize = m_histEdges.size();
664 if (histListSize != edgeListSize) {
665 ATH_MSG_ERROR("Histo List and Edge List differ in Run period entries "
666 << histListSize << " vs " << edgeListSize);
667 return 0;
668 }
669 for (size_t i = 0; i < histListSize; ++i) {
670 if (m_histList.at(mapkey::sf).at(i).size() != m_histEdges.at(i).size()) {
672 "Histo List and Edge List differ for the Run period in entry" << i);
673 return 0;
674 }
675 }
676
677 // Caching of Bin edges for Fast simul SF
679 histListSize = m_fastHistList.at(mapkey::sf).size();
680 edgeListSize = m_fastHistEdges.size();
681 if (histListSize != edgeListSize) {
682 ATH_MSG_ERROR("Fast Histo List and Edge List differ in Run period entries "
683 << histListSize << " vs " << edgeListSize);
684 return 0;
685 }
686 for (size_t i = 0; i < histListSize; ++i) {
687 if (m_fastHistList.at(mapkey::sf).at(i).size() !=
688 m_fastHistEdges.at(i).size()) {
690 "Fast Histo List and Edge List differ for the Run period in entry"
691 << i);
692 return 0;
693 }
694 }
695
696 return 1;
697}
698/*
699 * Get the input histograms from a given folder/run number range
700 */
701int
703 const TObjArray& dirNameArray,
704 int lastIdx)
705{
706
707 ATH_MSG_DEBUG(" (file: " << __FILE__ << ", line: " << __LINE__ << ")\n"
708 << "Entering funtion setupHistogramsInFolder");
709
710 int runNumBegin(-1);
711 TString myBegRunNumString =
712 ((TObjString*)dirNameArray.At(lastIdx - 1))->GetString();
713 if (myBegRunNumString.IsDigit()) {
714 runNumBegin = myBegRunNumString.Atoi();
715 }
716 int runNumEnd(-1);
717 TString myEndRunNumString =
718 ((TObjString*)dirNameArray.At(lastIdx))->GetString();
719 if (myEndRunNumString.IsDigit()) {
720 runNumEnd = myEndRunNumString.Atoi();
721 }
722 if (runNumBegin < 0 || runNumEnd < 0 || runNumEnd < runNumBegin) {
723 ATH_MSG_ERROR(" (file: " << __FILE__ << ", line: " << __LINE__ << ")\n"
724 << "Could NOT interpret the run number range: "
725 << runNumBegin << " - " << runNumEnd);
726 return 0;
727 }
729 //--> e.g. "sf" index 0 ,
730 std::vector<std::vector<TH1*>> objsFull(mapkey::end);
731 std::vector<std::vector<TH1*>> objsFast(mapkey::end);
732 // Vector to hold the N~16 systematic variations
733 std::vector<std::vector<TH1*>> sysObjsFull;
734 std::vector<std::vector<TH1*>> sysObjsFast;
735 TIter nextkey(gDirectory->GetListOfKeys());
736 TKey* key = nullptr;
737 TObject* obj = nullptr;
738 int seenSystematics = 0;
739 // Loop of the keys
740 while ((key = (TKey*)nextkey())) {
741 obj = key->ReadObj();
742 if (obj->IsA()->InheritsFrom("TH1")) {
743 // The histogram containing the scale factors need to end with _sf and
744 // need to contain either the string "FullSim" or "AtlFast"!
745 if (std::strstr(obj->GetName(), "FullSim") != nullptr) {
747 static_cast<TH1*>(obj), objsFull, sysObjsFull, seenSystematics);
748 } else if (std::strstr(obj->GetName(), "AtlFast") != nullptr) {
750 static_cast<TH1*>(obj), objsFast, sysObjsFast, seenSystematics);
751 } else {
752 ATH_MSG_ERROR("Could NOT interpret if the histogram: "
753 << obj->GetName() << " is full or fast simulation!");
754 return 0;
755 }
756 }
757 }
758 ATH_MSG_DEBUG(" (file: " << __FILE__ << ", line: " << __LINE__ << ")\n"
759 << "Setting up histograms for Run range "
760 << runNumEnd);
761 // Copy from the temporaries to the actual member variables
762 // via the setup function
763 for (int key : s_keys) {
764 if (!objsFull.at(key).empty()) {
765 if (0 == setup(objsFull.at(key),
766 m_histList[key],
769 runNumBegin,
770 runNumEnd)) {
771 ATH_MSG_ERROR("! Could NOT setup histogram " << key
772 << " for full sim!");
773 return 0;
774 }
775 }
776 if (!objsFast.at(key).empty()) {
777 if (0 == setup(objsFast.at(key),
778 m_fastHistList[key],
781 runNumBegin,
782 runNumEnd)) {
783 ATH_MSG_ERROR("! Could NOT setup histogram " << key << " for fast sim");
784 return 0;
785 }
786 }
787 }
788 m_fastSysList.resize(sysObjsFast.size());
789 for (unsigned int sys = 0; sys < sysObjsFast.size(); sys++) {
790 if (0 == setup(sysObjsFast.at(sys),
791 m_fastSysList[sys],
794 runNumBegin,
795 runNumEnd)) {
796 ATH_MSG_ERROR("! Could NOT setup systematic histograms for fast sim");
797 return 0;
798 }
799 }
800 m_sysList.resize(sysObjsFull.size());
801 for (unsigned int sys = 0; sys < sysObjsFull.size(); sys++) {
802 if (0 == setup(sysObjsFull.at(sys),
803 m_sysList[sys],
806 runNumBegin,
807 runNumEnd)) {
808 ATH_MSG_ERROR("! Could NOT setup systematic histograms for fast sim");
809 return 0;
810 }
811 }
812
813 // Toys
814 if (m_doToyMC || m_doCombToyMC) {
815 bool fullToysBooked =
816 setupUncorrToySyst(objsFull, sysObjsFull, m_uncorrToyMCSystFull);
817 bool fastToysBooked =
818 setupUncorrToySyst(objsFast, sysObjsFast, m_uncorrToyMCSystFast);
819 if (fullToysBooked || fastToysBooked) {
820 if (m_doToyMC) {
821 ATH_MSG_DEBUG("Created tables for " << m_nToyMC
822 << " ToyMC systematics ");
823 }
824 if (m_doCombToyMC) {
825 ATH_MSG_DEBUG("Created tables for " << m_nToyMC
826 << " combined ToyMC systematics ");
827 }
828 }
829 }
830 return 1;
831}
832/*
833 * Helper for Setting up the temporary/intermediate maps
834 * from the histos
835 */
836void
838 TH1* obj,
839 std::vector<std::vector<TH1*>>& objs,
840 std::vector<std::vector<TH1*>>& sysObjs,
841 int& seenSystematics)
842{
843 // Add all except the correlated
844 for (int key : s_keys) {
845 if (TString(obj->GetName())
846 .EndsWith("_" + TString(mapkey::keytostring(key)))) {
847 objs.at(key).emplace_back(obj);
848 }
849 }
850
851 const TString tmpName(obj->GetName());
852 // Special treatment , this is only for photons
853 if (tmpName.EndsWith("_sys")) {
854 objs.at(mapkey::sys).emplace_back(obj);
855 std::vector<TH1*> tmpArray;
856 // clone
857 tmpArray.emplace_back(static_cast<TH1*>(obj->Clone()));
858 sysObjs.emplace_back(tmpArray);
859 seenSystematics++;
860 }
861 // See if we are dealing with correlated
862 if (tmpName.Contains("_corr")) {
863 /*
864 * corr0 in the name triggers a few things
865 * We assume that 0 is the 1st
866 * histogram in a series of corr(i) that
867 * we see for each of the vector entries that
868 * can be one for LowPt,Standard,Forward etc
869 */
870 if (tmpName.EndsWith("corr0")) {
871 // 1st create a TObjectArray
872 std::vector<TH1*> tmpArray;
873 // Register it to the vector
874 sysObjs.emplace_back(tmpArray);
875 // Reset the counter here
876 seenSystematics = 0;
877 }
878 /*
879 * Now we can add to the TObjeArray
880 * This can be Low Pt or high Pt
881 */
882 sysObjs.back().emplace_back(obj);
883 //Increase the counter
884 seenSystematics++;
885 }
886
887 if (seenSystematics > m_nSysMax) {
888 m_nSysMax = seenSystematics;
889 }
890}
891/*
892 * Helper for Setting up the uncorrelated syst for the toys
893 */
894bool
896 std::vector<std::vector<TH1*>>& objs,
897 std::vector<std::vector<TH1*>>& sysObjs,
898 std::vector<std::vector<HistArray>>& uncorrToyMCSyst)
899{
900 bool toysBooked = false;
901 if (!m_histList[mapkey::sf].empty()) {
902 if (objs.at(mapkey::eig).empty() || objs.at(mapkey::stat).empty() ||
903 objs.at(mapkey::uncorr).empty()) {
904
905 if (objs.at(mapkey::stat).size() > 1 || objs.at(mapkey::sys).size() > 1) {
906
907 uncorrToyMCSyst.push_back(buildToyMCTable(
908 objs.at(mapkey::sf), {}, objs.at(mapkey::stat), {}, sysObjs));
909 toysBooked = true;
910 }
911 } else {
912 uncorrToyMCSyst.push_back(buildToyMCTable(objs.at(mapkey::sf),
913 objs.at(mapkey::eig),
914 objs.at(mapkey::stat),
915 objs.at(mapkey::uncorr),
916 sysObjs));
917 toysBooked = true;
918 }
919 }
920 return toysBooked;
921}
922/*
923 * Fill and interpret the setup, depending
924 * on which histograms are found in the input file(s)
925 */
926int
928 const std::vector<TH1*>& hists,
929 std::vector<HistArray>& histList,
930 std::vector<unsigned int>& beginRunNumberList,
931 std::vector<unsigned int>& endRunNumberList,
932 const int runNumBegin,
933 const int runNumEnd) const
934{
935 if (hists.empty()) {
936 ATH_MSG_ERROR("! Could NOT find histogram with name *_sf in folder");
937 return 0;
938 }
939 TH1* tmpHist(nullptr);
940 HistArray tmpArray;
941 for (const auto& hist : hists) {
942 tmpHist = static_cast<TH1*>(hist);
943 tmpHist->SetDirectory(nullptr);
944 tmpArray.emplace_back(tmpHist);
945 }
946 histList.emplace_back(std::move(tmpArray));
947 // Now, we have all the needed info. Fill the vectors accordingly
948 if (!beginRunNumberList.empty()) {
949 if (runNumBegin != (int)beginRunNumberList.back()) {
950 beginRunNumberList.push_back(runNumBegin);
951 }
952 } else {
953 beginRunNumberList.push_back(runNumBegin);
954 }
955 if (!endRunNumberList.empty()) {
956 if (runNumEnd != (int)endRunNumberList.back()) {
957 endRunNumberList.push_back(runNumEnd);
958 }
959 } else {
960 endRunNumberList.push_back(runNumEnd);
961 }
962 return 1;
963}
964
965
967 const std::vector<HistArray>& sfPerPeriodHist,
968 std::vector<std::vector<HistEdge>>& sfPerPeriodEdges) {
969
970 for (const auto& vec : sfPerPeriodHist) {
971 const size_t vecSize = vec.size();
972 std::vector<HistEdge> periodVec;
973 periodVec.reserve(vecSize);
974 for (size_t i = 0; i < vecSize; ++i) {
975 const auto* tmpHist = static_cast<TH2*>(vec[i].get());
976 const auto* const xAxis = tmpHist->GetXaxis();
977 const auto* yAxis = tmpHist->GetYaxis();
978 HistEdge histEdge;
979 histEdge.etaMax = yAxis->GetXmax();
980 histEdge.etaMin = yAxis->GetXmin();
981 histEdge.etMax = xAxis->GetXmax();
982 histEdge.etMin = xAxis->GetXmin();
983 histEdge.isLowPt =
984 (std::strstr(tmpHist->GetName(), LowPt_string) != nullptr);
985
986 periodVec.emplace_back(histEdge);
987 }
988 sfPerPeriodEdges.emplace_back(std::move(periodVec));
989 }
990}
991
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_WARNING(x,...)
std::vector< size_t > vec
static Double_t sc
static TRandom * rnd
size_t size() const
Number of registered mappings.
static const Attributes_t empty
std::vector< unsigned int > m_begRunNumberList
List of run numbers where histograms become valid for full simulation.
static void fillHistEdges(const std::vector< HistArray > &sfPerPeriodHist, std::vector< std::vector< HistEdge > > &sfPerPeriodEdges)
int setupHistogramsInFolder(const TObjArray &dirNameArray, int lastIdx)
std::vector< std::vector< HistEdge > > m_fastHistEdges
std::vector< std::vector< HistArray > > m_fastSysList
std::vector< std::vector< HistArray > > m_uncorrToyMCSystFull
std::vector< std::string > m_corrFileNameList
The list of file name(s).
bool setupUncorrToySyst(std::vector< std::vector< TH1 * > > &objs, std::vector< std::vector< TH1 * > > &sysObjs, std::vector< std::vector< HistArray > > &uncorrToyMCSyst)
bool uncorrEmpty(const PATCore::ParticleDataType::DataType dataType)
Check if stat+uncorr has input.
TH2 * buildSingleCombToyMC(const TH1 *sf, const TH1 *stat, const TH1 *uncorr, const std::vector< TH1 * > &corr, const int nSys, int &randomCounter)
std::vector< unsigned int > m_begRunNumberListFastSim
List of run numbers where histograms become valid for fast simulation.
std::vector< std::vector< HistArray > > m_fastHistList
List of histograms for fast simulation.
std::vector< HistArray > buildToyMCTable(const std::vector< TH1 * > &sf, const std::vector< TH1 * > &eig, const std::vector< TH1 * > &stat, const std::vector< TH1 * > &uncorr, const std::vector< std::vector< TH1 * > > &corr)
int getNbins(std::map< float, std::vector< float > > &ptEta) const
Helpers to get the binning of the uncertainties in a std::map (pt, eta).
std::vector< unsigned int > m_endRunNumberListFastSim
List of run numbers where histograms stop being valid for fast simulation.
std::vector< std::vector< HistArray > > m_sysList
int calculate(const PATCore::ParticleDataType::DataType dataType, const unsigned int runnumber, const double cluster_eta, const double et, Result &result, const bool onlyTotal=false) const
The main calculate method: dataType PATCore::ParticleDataType::DataType (e.g DATA,...
std::vector< TH2 * > buildSingleToyMC(const TH1 *sf, const TH1 *stat, const TH1 *uncorr, const std::vector< TH1 * > &corr, int &randomCounter)
TElectronEfficiencyCorrectionTool(const char *name="TElectronEfficiencyCorrectionTool")
Standard constructor.
std::vector< unsigned int > m_endRunNumberList
List of run numbers where histograms stop being valid for full simulation.
std::vector< std::vector< HistArray > > m_histList
List of histograms for full Geant4 simulation.
std::vector< std::vector< HistEdge > > m_histEdges
std::vector< std::vector< HistArray > > m_uncorrToyMCSystFast
int setup(const std::vector< TH1 * > &hists, std::vector< HistArray > &histList, std::vector< unsigned int > &beginRunNumberList, std::vector< unsigned int > &endRunNumberList, const int runNumBegin, const int runNumEnd) const
Fill and interpret the setup, depending on which histograms are found in the input file(s).
int getHistograms()
Load all histograms from the input file(s).
void setupTempMapsHelper(TH1 *obj, std::vector< std::vector< TH1 * > > &objs, std::vector< std::vector< TH1 * > > &sysObjs, int &seenSystematics)
AsgMessaging(const std::string &name)
Constructor with a name.
STL class.
bool setup(asg::AnaToolHandle< Interface > &tool, const std::string &type, const std::vector< std::string > &config, const std::string &progressFile="")
mostly useful for athena, which will otherwise re-use the previous tool
static std::vector< uint32_t > runnumber
Definition iLumiCalc.h:37
double entries
Definition listroot.cxx:49
Definition index.py:1
const char * keytostring(int input)
STL namespace.
#define likely(x)
Extra patterns decribing particle interation process.