ATLAS Offline Software
Loading...
Searching...
No Matches
CommonDiTauEfficiencyTool.cxx
Go to the documentation of this file.
1
4
5// Framework include(s):
7
8// local include(s)
11
12// ROOT include(s)
13#include "TH2F.h"
14#include "TROOT.h"
15#include "TKey.h"
16#include "TClass.h"
17#include <utility>
18
19using namespace TauAnalysisTools;
20
21//______________________________________________________________________________
33
35{
36 if (m_mSF)
37 for (auto mEntry : *m_mSF)
38 delete std::get<0>(mEntry.second);
39}
40
41
42/*
43 - Find the root files with scale factor inputs on cvmfs using PathResolver
44 (more info here:
45 https://twiki.cern.ch/twiki/bin/viewauth/AtlasComputing/PathResolver)
46 - Call further functions to process and define NP strings and so on
47 - Configure to provide nominal scale factors by default
48*/
50{
51 ATH_MSG_INFO( "Initializing CommonDiTauEfficiencyTool" );
52 // only read in histograms once
53 if (m_mSF==nullptr)
54 {
55 std::string sInputFilePath = PathResolverFindCalibFile(m_sInputFilePath);
56
57 m_mSF = std::make_unique< tSFMAP >();
58 std::unique_ptr< TFile > fSF( TFile::Open( sInputFilePath.c_str(), "READ" ) );
59 if(!fSF)
60 {
61 ATH_MSG_FATAL("Could not open file " << sInputFilePath.c_str());
62 return StatusCode::FAILURE;
63 }
64 ReadInputs(fSF);
65 fSF->Close();
66 }
67
68 // needed later on in generateSystematicSets(), maybe move it there
69 std::vector<std::string> vInputFilePath;
70 split(m_sInputFilePath,'/',vInputFilePath);
71 m_sInputFileName = vInputFilePath.back();
72
74
75 if (m_sWP.size()>0)
76 m_sSFHistName = "sf_"+m_sWP;
77
78 // load empty systematic variation by default
79 if (applySystematicVariation(CP::SystematicSet()) != StatusCode::SUCCESS )
80 return StatusCode::FAILURE;
81
82 return StatusCode::SUCCESS;
83}
84
85
86
87/*
88 Retrieve the scale factors and if requested the values for the NP's and add
89 this stuff in quadrature. Finally return sf_nom +/- n*uncertainty
90*/
91//______________________________________________________________________________
93 double& dEfficiencyScaleFactor)
94{
95 // check which true state is requestet
97 {
98 dEfficiencyScaleFactor = 1.;
100 }
101
102 CP::CorrectionCode tmpCorrectionCode = getValue(m_sSFHistName,
103 xDiTau,
104 dEfficiencyScaleFactor);
105 // return correction code if histogram is not available
106 if (tmpCorrectionCode != CP::CorrectionCode::Ok)
107 return tmpCorrectionCode;
108
109 // skip further process if systematic set is empty
110 if (m_sSystematicSet->size() == 0)
112
113 // get uncertainties summed in quadrature
114 double dTotalSystematic2 = 0.;
115 double dDirection = 0.;
116 for (const auto & syst : *m_sSystematicSet)
117 {
118
119 // check if systematic is available
120 auto it = m_mSystematicsHistNames.find(syst.basename());
121 if (it == m_mSystematicsHistNames.end())[[unlikely]] continue;
122 // get uncertainty value
123 double dUncertaintySyst = 0.;
124
125 // needed for up/down decision
126 dDirection = syst.parameter();
127
128 // build up histogram name
129 std::string sHistName = it->second;
130 if (dDirection>0) sHistName+="_up";
131 else sHistName+="_down";
132 if (!m_sWP.empty()) sHistName+="_"+m_sWP;
133
134 // get the uncertainty from the histogram
135 tmpCorrectionCode = getValue(sHistName,
136 xDiTau,
137 dUncertaintySyst);
138
139 // return correction code if histogram is not available
140 if (tmpCorrectionCode != CP::CorrectionCode::Ok)
141 return tmpCorrectionCode;
142
143 // scale uncertainty with direction, i.e. +/- n*sigma
144 dUncertaintySyst *= dDirection;
145
146 // square uncertainty and add to total uncertainty
147 dTotalSystematic2 += dUncertaintySyst * dUncertaintySyst;
148 }
149
150 // now use dDirection to use up/down uncertainty
151 dDirection = (dDirection > 0.) ? 1. : -1.;
152
153 // finally apply uncertainty (eff * ( 1 +/- \sum )
154 dEfficiencyScaleFactor *= 1. + dDirection * std::sqrt(dTotalSystematic2);
155
157}
158
159/*
160 Get scale factor from getEfficiencyScaleFactor and decorate it to the
161 tau. Note that this can only be done if the variable name is not already used,
162 e.g. if the variable was already decorated on a previous step (enured by the
163 m_bSFIsAvailableCheckedDiTau check).
164
165 Technical note: cannot use `static SG::Decorator` as we will have
166 multiple instances of this tool with different decoration names.
167*/
168//______________________________________________________________________________
170{
171 double dSf = 0.;
172
175 {
176 m_bSFIsAvailableDiTau = decor.isAvailable(xDiTau);
179 {
180 ATH_MSG_DEBUG(m_sVarName << " decoration is available on first ditau processed, switched of applyEfficiencyScaleFactor for further ditaus.");
181 ATH_MSG_DEBUG("If an application of efficiency scale factors needs to be redone, please pass a shallow copy of the original ditau.");
182 }
183 }
186
187 // retrieve scale factor
188 CP::CorrectionCode tmpCorrectionCode = getEfficiencyScaleFactor(xDiTau, dSf);
189 // adding scale factor to tau as decoration
190 decor(xDiTau) = dSf;
191
192 return tmpCorrectionCode;
193}
194
195/*
196 standard check if a systematic is available
197*/
198//______________________________________________________________________________
200{
202 return sys.find(systematic) != sys.end();
203}
204
205/*
206 standard way to return systematics that are available (including recommended
207 systematics)
208*/
209//______________________________________________________________________________
214
215/*
216 standard way to return systematics that are recommended
217*/
218//______________________________________________________________________________
223
224/*
225 Configure the tool to use a systematic variation for further usage, until the
226 tool is reconfigured with this function. The passed systematic set is checked
227 for sanity:
228 - unsupported systematics are skipped
229 - only combinations of up or down supported systematics is allowed
230 - don't mix recommended systematics with other available systematics, cause
231 sometimes recommended are a quadratic sum of the other variations,
232 e.g. TOTAL=(SYST^2 + STAT^2)^0.5
233*/
234//______________________________________________________________________________
236{
237
238 // first check if we already know this systematic configuration
239 auto itSystematicSet = m_mSystematicSets.find(sSystematicSet);
240 if (itSystematicSet != m_mSystematicSets.end())
241 {
242 m_sSystematicSet = &itSystematicSet->first;
243 return StatusCode::SUCCESS;
244 }
245
246 // sanity checks if systematic set is supported
247 double dDirection = 0.;
248 CP::SystematicSet sSystematicSetAvailable;
249 for (const auto & sSyst : sSystematicSet)
250 {
251 // check if systematic is available
252 auto it = m_mSystematicsHistNames.find(sSyst.basename());
253 if (it == m_mSystematicsHistNames.end())
254 {
255 ATH_MSG_VERBOSE("unsupported systematic variation: "<< sSyst.basename()<<"; skipping this one");
256 continue;
257 }
258
259
260 if (sSyst.parameter() * dDirection < 0)
261 {
262 ATH_MSG_ERROR("unsupported set of systematic variations, you should either use only \"UP\" or only \"DOWN\" systematics in one set!");
263 ATH_MSG_ERROR("systematic set will not be applied");
264 return StatusCode::FAILURE;
265 }
266 dDirection = sSyst.parameter();
267
268 if ((m_sRecommendedSystematics.find(sSyst.basename()) != m_sRecommendedSystematics.end()) and sSystematicSet.size() > 1)
269 {
270 ATH_MSG_ERROR("unsupported set of systematic variations, you should not combine \"TAUS_{TRUE|FAKE}_EFF_*_TOTAL\" with other systematic variations!");
271 ATH_MSG_ERROR("systematic set will not be applied");
272 return StatusCode::FAILURE;
273 }
274
275 // finally add the systematic to the set of systematics to process
276 sSystematicSetAvailable.insert(sSyst);
277 }
278
279 // store this calibration for future use, and make it current
280 m_sSystematicSet = &m_mSystematicSets.insert(std::pair<CP::SystematicSet,std::string>(sSystematicSetAvailable, sSystematicSet.name())).first->first;
281
282 return StatusCode::SUCCESS;
283}
284
285//=================================PRIVATE-PART=================================
286void CommonDiTauEfficiencyTool::ReadInputs(std::unique_ptr<TFile> &fFile)
287{
288 m_mSF->clear();
289
290 // initialize function pointer
294
295 TKey *kKey;
296 TIter itNext(fFile->GetListOfKeys());
297 while ((kKey = (TKey*)itNext()))
298 {
299 // parse file content for objects of type TNamed, check their title for
300 // known strings and reset funtion pointer
301 std::string sKeyName = kKey->GetName();
302
303 std::vector<std::string> vSplitName = {};
304 split(sKeyName,'_',vSplitName);
305 if (vSplitName[0] == "sf")
306 {
307 addHistogramToSFMap(kKey, sKeyName);
308 }
309 else
310 {
311 if (sKeyName.find("_up_") != std::string::npos or sKeyName.find("_down_") != std::string::npos)
312 addHistogramToSFMap(kKey, sKeyName);
313 else
314 {
315 size_t iPos = sKeyName.find('_');
316 addHistogramToSFMap(kKey, sKeyName.substr(0,iPos)+"_up"+sKeyName.substr(iPos));
317 addHistogramToSFMap(kKey, sKeyName.substr(0,iPos)+"_down"+sKeyName.substr(iPos));
318 }
319 }
320 }
321 ATH_MSG_INFO("data loaded from " << fFile->GetName());
322}
323
324/*
325 Create the tuple objects for the map
326*/
327//______________________________________________________________________________
328void CommonDiTauEfficiencyTool::addHistogramToSFMap(TKey* kKey, const std::string& sKeyName)
329{
330 // handling for the 3 different input types TH1F/TH1D/TF1, function pointer
331 // handle the access methods for the final scale factor retrieval
332 TClass *cClass = gROOT->GetClass(kKey->GetClassName());
333 if (cClass->InheritsFrom("TH2"))
334 {
335 TH2* oObject = static_cast<TH2*>(kKey->ReadObj());
336 oObject->SetDirectory(0);
337 (*m_mSF)[sKeyName] = tTupleObjectFunc(oObject,&getValueTH2);
338 ATH_MSG_DEBUG("added histogram with name "<<sKeyName);
339 }
340 else if (cClass->InheritsFrom("TH1"))
341 {
342 TH1* oObject = static_cast<TH1*>(kKey->ReadObj());
343 oObject->SetDirectory(0);
344 (*m_mSF)[sKeyName] = tTupleObjectFunc(oObject,&getValueTH1);
345 ATH_MSG_DEBUG("added histogram with name "<<sKeyName);
346 }
347 else
348 {
349 ATH_MSG_DEBUG("ignored object with name "<<sKeyName);
350 }
351}
352
353
354/*
355 This function parses the names of the objects from the input file and
356 generates the systematic sets and defines which ones are recommended or only
357 available. It also checks, based on the root file name, on which tau it needs
358 to be applied, e.g. only on reco taus coming from true taus or on those faked
359 by true electrons...
360 Examples:
361 filename: JetID_TrueHadDiTau_2017-fall.root -> apply only to true ditaus
362 histname: sf_* -> nominal scale factor
363 histname: TOTAL_* -> "total" NP, recommended
364 histname: afii_* -> "total" NP, not recommended, but available
365*/
366//______________________________________________________________________________
368{
369 // creation of basic string for all NPs, e.g. "TAUS_TRUEHADTAU_EFF_RECO_"
370 std::vector<std::string> vSplitInputFilePath = {};
371 split(m_sInputFileName,'_',vSplitInputFilePath);
372 std::string sEfficiencyType = vSplitInputFilePath.at(0);
373 std::string sTruthType = vSplitInputFilePath.at(1);
374 std::transform(sEfficiencyType.begin(), sEfficiencyType.end(), sEfficiencyType.begin(), toupper);
375 std::transform(sTruthType.begin(), sTruthType.end(), sTruthType.begin(), toupper);
376 std::string sSystematicBaseString = "TAUS_"+sTruthType+"_EFF_"+sEfficiencyType+"_";
377 // set truth type to check for in truth matching
378 if (sTruthType=="TRUEHADTAU") m_eCheckTruth = TauAnalysisTools::TruthHadronicTau;
379 if (sTruthType=="TRUEHADDITAU") m_eCheckTruth = TauAnalysisTools::TruthHadronicDiTau;
380
381 for (const auto & mSF : *m_mSF)
382 {
383 // parse for nuisance parameter in histogram name
384 std::vector<std::string> vSplitNP = {};
385 split(mSF.first,'_',vSplitNP);
386 std::string sNP = vSplitNP.at(0);
387 std::string sNPUppercase = vSplitNP.at(0);
388 // skip nominal scale factors
389 if (sNP == "sf") continue;
390 // test if NP starts with a capital letter indicating that this should be recommended
391 bool bIsRecommended = false;
392 if (isupper(sNP.at(0)))
393 bIsRecommended = true;
394 // make sNP uppercase and build final NP entry name
395 std::transform(sNPUppercase.begin(), sNPUppercase.end(), sNPUppercase.begin(), toupper);
396 std::string sSystematicString = sSystematicBaseString+sNPUppercase;
397 // add all found systematics to the AffectingSystematics
398 m_sAffectingSystematics.insert(CP::SystematicVariation (sSystematicString, 1));
399 m_sAffectingSystematics.insert(CP::SystematicVariation (sSystematicString, -1));
400 // only add found uppercase systematics to the RecommendedSystematics
401 if (bIsRecommended)
402 {
403 m_sRecommendedSystematics.insert(CP::SystematicVariation (sSystematicString, 1));
404 m_sRecommendedSystematics.insert(CP::SystematicVariation (sSystematicString, -1));
405 }
406 ATH_MSG_DEBUG("connected base name " << sNP << " with systematic " <<sSystematicString);
407 m_mSystematicsHistNames.insert({sSystematicString,sNP});
408 }
409}
410
411/*
412 return value from the tuple map object based on the pt/eta values (or the
413 corresponding value in case of configuration)
414*/
415//______________________________________________________________________________
417 const xAOD::DiTauJet& xDiTau,
418 double& dEfficiencyScaleFactor) const
419{
420 const tSFMAP& mSF = *m_mSF;
421 auto it = mSF.find (sHistName);
422 if (it == mSF.end())
423 {
424 ATH_MSG_ERROR("Object with name "<<sHistName<<" was not found in input file.");
425 ATH_MSG_DEBUG("Content of input file");
426 for (const auto & eEntry : mSF){
427 ATH_MSG_DEBUG(" Entry: "<<eEntry.first);
428 }
430 }
431
432 // get a tuple (TObject*,functionPointer) from the scale factor map
433 tTupleObjectFunc tTuple = it->second;
434
435 // get pt and eta (for x and y axis respectively)
436 double dX = m_fXDiTau(xDiTau);
437 double dY = m_fYDiTau(xDiTau);
438 double dZ = m_fZDiTau(xDiTau);
439
440 double dVars[3] = {dX, dY, dZ};
441 // finally obtain efficiency scale factor from TH1F/TH1D/TF1, by calling the
442 // function pointer stored in the tuple from the scale factor map
443 return (std::get<1>(tTuple))(std::get<0>(tTuple), dEfficiencyScaleFactor, dVars);
444}
445
446//______________________________________________________________________________
448{
449 // return leading truth tau pt in GeV
450 static const SG::ConstAccessor< float > acc( "TruthVisLeadPt" );
451 return acc( xDiTau ) * 0.001;
452}
453
454//______________________________________________________________________________
456{
457 // return subleading truth tau pt in GeV
458 static const SG::ConstAccessor< float > acc( "TruthVisSubleadPt" );
459 return acc( xDiTau ) * 0.001;
460}
461
462//______________________________________________________________________________
464{
465 // return truth taus distance delta R
466 static const SG::ConstAccessor< float > acc( "TruthVisDeltaR" );
467 return acc( xDiTau );
468}
469
470/*
471 find the particular value in TH1 depending on pt (or the
472 corresponding value in case of configuration)
473 Note: In case values are outside of bin ranges, the closest bin value is used
474*/
475//______________________________________________________________________________
477 double& dEfficiencyScaleFactor, double dVars[])
478{
479 double dPt = dVars[0];
480
481 const TH1* hHist = dynamic_cast<const TH1*>(oObject);
482
483 if (!hHist)
484 {
485 // ATH_MSG_ERROR("Problem with casting TObject of type "<<oObject->ClassName()<<" to TH2F");
487 }
488
489 // protect values from underflow bins
490 dPt = std::max(dPt,hHist->GetXaxis()->GetXmin());
491 // protect values from overflow bins (times .999 to keep it inside last bin)
492 dPt = std::min(dPt,hHist->GetXaxis()->GetXmax() * .999);
493
494 // get bin from TH2 depending on x and y values; finally set the scale factor
495 int iBin = hHist->FindFixBin(dPt);
496 dEfficiencyScaleFactor = hHist->GetBinContent(iBin);
498}
499
500/*
501 find the particular value in TH2 depending on pt and eta (or the
502 corresponding value in case of configuration)
503 Note: In case values are outside of bin ranges, the closest bin value is used
504*/
505//______________________________________________________________________________
507 double& dEfficiencyScaleFactor, double dVars[])
508{
509 double dPt = dVars[0];
510 double dEta = dVars[1];
511
512 const TH2* hHist = dynamic_cast<const TH2*>(oObject);
513
514 if (!hHist)
515 {
516 // ATH_MSG_ERROR("Problem with casting TObject of type "<<oObject->ClassName()<<" to TH2F");
518 }
519
520 // protect values from underflow bins
521 dPt = std::max(dPt,hHist->GetXaxis()->GetXmin());
522 dEta = std::max(dEta,hHist->GetYaxis()->GetXmin());
523 // protect values from overflow bins (times .999 to keep it inside last bin)
524 dPt = std::min(dPt,hHist->GetXaxis()->GetXmax() * .999);
525 dEta = std::min(dEta,hHist->GetYaxis()->GetXmax() * .999);
526
527 // get bin from TH2 depending on x and y values; finally set the scale factor
528 int iBin = hHist->FindFixBin(dPt,dEta);
529 dEfficiencyScaleFactor = hHist->GetBinContent(iBin);
531}
532
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_VERBOSE(x,...)
#define ATH_MSG_INFO(x,...)
#define ATH_MSG_FATAL(x,...)
Efficiency scale factors and uncertainties for ditau jets.
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
Return value from object correction CP tools.
@ Error
Some error happened during the object correction.
@ Ok
The correction was done successfully.
Class to wrap a set of SystematicVariations.
std::string name() const
returns: the systematics joined into a single string.
void insert(const SystematicVariation &systematic)
description: insert a systematic into the set
size_t size() const
returns: size of the set
virtual StatusCode applySystematicVariation(const CP::SystematicSet &sSystematicSet)
configure this tool for the given list of systematic variations.
std::function< double(const xAOD::DiTauJet &xDiTau)> m_fZDiTau
std::tuple< TObject *, CP::CorrectionCode(*)(const TObject *oObject, double &dEfficiencyScaleFactor, double dVars[]) > tTupleObjectFunc
std::function< double(const xAOD::DiTauJet &xDiTau)> m_fXDiTau
void addHistogramToSFMap(TKey *kKey, const std::string &sKeyName)
virtual StatusCode initialize()
Dummy implementation of the initialisation function.
CommonDiTauEfficiencyTool(const std::string &sName)
Create a proper constructor for Athena.
std::unordered_map< CP::SystematicSet, std::string > m_mSystematicSets
std::map< std::string, std::string > m_mSystematicsHistNames
virtual CP::CorrectionCode applyEfficiencyScaleFactor(const xAOD::DiTauJet &xDiTau)
Get the Efficiency Scale Factor of ditau jet.
void generateSystematicSets()
generate a set of relevant systematic variations to be applied
std::map< std::string, tTupleObjectFunc > tSFMAP
static CP::CorrectionCode getValueTH2(const TObject *oObject, double &dEfficiencyScaleFactor, double dVars[])
virtual CP::CorrectionCode getValue(const std::string &sHistName, const xAOD::DiTauJet &xDiTau, double &dEfficiencyScaleFactor) const
Get the scale factor from a particular recommendations histogram.
virtual CP::CorrectionCode getEfficiencyScaleFactor(const xAOD::DiTauJet &xDiTau, double &dEfficiencyScaleFactor)
Get the Efficiency Scale Factor of ditau jet.
bool m_bSFIsAvailableDiTau
true if scale factor name is already decorated
virtual CP::SystematicSet affectingSystematics() const
returns: the list of all systematics this tool can be affected by
virtual bool isAffectedBySystematic(const CP::SystematicVariation &systematic) const
returns: whether this tool is affected by the given systematics
void ReadInputs(std::unique_ptr< TFile > &fFile)
static CP::CorrectionCode getValueTH1(const TObject *oObject, double &dEfficiencyScaleFactor, double dVars[])
bool m_bSFIsAvailableCheckedDiTau
true if cale factor name is already decorated has already been checked
std::function< double(const xAOD::DiTauJet &xDiTau)> m_fYDiTau
virtual CP::SystematicSet recommendedSystematics() const
returns: the list of all systematics this tool recommends to use
AsgTool(const std::string &name)
Constructor specifying the tool instance's name.
Definition AsgTool.cxx:58
SG::Decorator< T, ALLOC > Decorator
Helper class to provide type-safe access to aux data, specialized for JaggedVecElt.
Definition AuxElement.h:576
double TruthSubleadPt(const xAOD::DiTauJet &xDiTau)
return the truth vis pT of the subleading pT matched particle.
TruthMatchedParticleType getTruthParticleType(const xAOD::TauJet &xTau)
return TauJet match type
void split(const std::string &sInput, const char cDelim, std::vector< std::string > &vOut)
double TruthDeltaR(const xAOD::DiTauJet &xDiTau)
return the dR of between the leading and subleading pT matched particle.
double TruthLeadPt(const xAOD::DiTauJet &xDiTau)
return the truth vis pT of the leading pT matched particle.
DiTauJet_v1 DiTauJet
Definition of the current version.
Definition DiTauJet.h:17
#define unlikely(x)