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