ATLAS Offline Software
Loading...
Searching...
No Matches
CommonDiTauSmearingTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5
6
7// local include(s)
9// Framework include(s):
12
13// ROOT include(s)
14#include "TROOT.h"
15#include "TClass.h"
16#include "TKey.h"
17#include "TH3.h"
18
19
20using namespace TauAnalysisTools;
21
22//______________________________________________________________________________
33
34/*
35 - Find the root files with smearing inputs on eos/cvmfs using PathResolver
36 - Call further functions to process and define NP strings and so on
37 - Configure to provide nominal smearings by default
38*/
40{
41 ATH_MSG_INFO( "Initializing CommonDiTauSmearingTool" );
42
43 // only read in histograms once
44 if (m_mDTSF.empty())
45 {
46 std::string sInputFilePath = PathResolverFindCalibFile(m_sInputFilePath);
47 std::unique_ptr< TFile > fSF( TFile::Open(sInputFilePath.c_str(), "READ") );
48 if(fSF == nullptr)
49 {
50 ATH_MSG_FATAL("Could not open file " << sInputFilePath.c_str());
51 return StatusCode::FAILURE;
52 }
53 ReadInputs(fSF.get(), m_mDTSF);
54 fSF->Close();
55 }
56
58
59 // load empty systematic variation by default
60 if (applySystematicVariation(CP::SystematicSet()) != StatusCode::SUCCESS )
61 return StatusCode::FAILURE;
62
63 return StatusCode::SUCCESS;
64}
65
66/*
67 Retrieve the smearing value and if requested the values for the NP's and add
68 this stuff in quadrature. Finally apply the correction to the tau pt of the
69 non-const tau.
70*/
71//______________________________________________________________________________
73{
74 // step out here if we run on data
75 if (m_bIsData)
77
78 // check which true state is requested
80 {
82 }
83
84 double dCorrection = 1.;
85 // get standard scale factor
86 CP::CorrectionCode tmpCorrectionCode = getValue("sf",
87 xDiTau,
88 dCorrection);
89 // return correction code if histogram is not available
90 if (tmpCorrectionCode != CP::CorrectionCode::Ok)
91 return tmpCorrectionCode;
92
93 // skip further process if systematic set is empty
94 if (m_sSystematicSet->size() > 0)
95 {
96 // get uncertainties summed in quadrature
97 double dTotalSystematic2 = 0;
98 double dDirection = 0;
99 for (auto syst : *m_sSystematicSet)
100 {
101 // check if systematic is available
102 auto it = m_mSystematicsHistNames.find(syst.basename());
103 if (it == m_mSystematicsHistNames.end())[[unlikely]] {
104 continue;
105 }
106 // get uncertainty value
107 double dUncertaintySyst = 0;
108 tmpCorrectionCode = getValue(it->second,
109 xDiTau,
110 dUncertaintySyst);
111
112 // return correction code if histogram is not available
113 if (tmpCorrectionCode != CP::CorrectionCode::Ok)
114 return tmpCorrectionCode;
115
116 // needed for up/down decision
117 dDirection = syst.parameter();
118
119 // scale uncertainty with direction, i.e. +/- n*sigma
120 dUncertaintySyst *= dDirection;
121
122 // square uncertainty and add to total uncertainty
123 dTotalSystematic2 += dUncertaintySyst * dUncertaintySyst;
124 }
125
126 // now use dDirection to use up/down uncertainty
127 dDirection = (dDirection > 0) ? +1 : -1;
128
129 // finally apply uncertainty (eff * ( 1 +/- \sum )
130 dCorrection *= 1 + dDirection * std::sqrt(dTotalSystematic2);
131 }
132
133 // finally apply correction
134 xDiTau.setP4( xDiTau.pt() * dCorrection,
135 xDiTau.eta(), xDiTau.phi(), xDiTau.m());
137}
138
139/*
140 Create a non-const copy of the passed const xDiTau object and apply the
141 correction to the non-const copy.
142 */
143//______________________________________________________________________________
145 xAOD::DiTauJet*& xDiTauCopy ) const
146{
147
148 // A sanity check:
149 if( xDiTauCopy )
150 {
151 ATH_MSG_WARNING( "Non-null pointer received. "
152 "There's a possible memory leak!" );
153 }
154
155 // Create a new object:
156 xDiTauCopy = new xAOD::DiTauJet();
157 xDiTauCopy->makePrivateStore( xDiTau );
158
159 // Use the other function to modify this object:
160 return applyCorrection( *xDiTauCopy );
161}
162
163/*
164 standard check if a systematic is available
165*/
166//______________________________________________________________________________
168{
170 return sys.find(systematic) != sys.end();
171}
172
173/*
174 standard way to return systematics that are available (including recommended
175 systematics)
176*/
177//______________________________________________________________________________
182
183/*
184 standard way to return systematics that are recommended
185*/
186//______________________________________________________________________________
191
192/*
193 Configure the tool to use a systematic variation for further usage, until the
194 tool is reconfigured with this function. The passed systematic set is checked
195 for sanity:
196 - unsupported systematics are skipped
197 - only combinations of up or down supported systematics is allowed
198 - don't mix recommended systematics with other available systematics, cause
199 sometimes recommended are a quadratic sum of the other variations,
200 e.g. TOTAL=(SYST^2 + STAT^2)^0.5
201*/
202//______________________________________________________________________________
204{
205 // first check if we already know this systematic configuration
206 auto itSystematicSet = m_mSystematicSets.find(sSystematicSet);
207 if (itSystematicSet != m_mSystematicSets.end())
208 {
209 m_sSystematicSet = &itSystematicSet->first;
210 return StatusCode::SUCCESS;
211 }
212
213 // sanity checks if systematic set is supported
214 double dDirection = 0.;
215 CP::SystematicSet sSystematicSetAvailable;
216 for (auto& sSyst : sSystematicSet)
217 {
218 // check if systematic is available
219 auto it = m_mSystematicsHistNames.find(sSyst.basename());
220 if (it == m_mSystematicsHistNames.end())
221 {
222 ATH_MSG_VERBOSE("unsupported systematic variation: "<< sSyst.basename()<<"; skipping this one");
223 continue;
224 }
225
226 if (sSyst.parameter() * dDirection < 0)
227 {
228 ATH_MSG_ERROR("unsupported set of systematic variations, you should either use only \"UP\" or only \"DOWN\" systematics in one set!");
229 ATH_MSG_ERROR("systematic set will not be applied");
230 return StatusCode::FAILURE;
231 }
232 dDirection = sSyst.parameter();
233
234 if ((m_sRecommendedSystematics.find(sSyst.basename()) != m_sRecommendedSystematics.end()) and sSystematicSet.size() > 1)
235 {
236 ATH_MSG_ERROR("unsupported set of systematic variations, you should not combine \"TAUS_{TRUE|FAKE}_SME_TOTAL\" with other systematic variations!");
237 ATH_MSG_ERROR("systematic set will not be applied");
238 return StatusCode::FAILURE;
239 }
240
241 // finally add the systematic to the set of systematics to process
242 sSystematicSetAvailable.insert(sSyst);
243 }
244
245 // store this calibration for future use, and make it current
246 m_sSystematicSet = &m_mSystematicSets.insert(std::pair<CP::SystematicSet,std::string>(sSystematicSetAvailable, sSystematicSet.name())).first->first;
247
248 return StatusCode::SUCCESS;
249}
250
251//=================================PRIVATE-PART=================================
252
253template<class T>
254void CommonDiTauSmearingTool::ReadInputs(TFile* fFile, std::map<std::string, T>& mMap)
255{
256 // initialize function pointer
257 m_fX = &TruthLeadPt;
259 m_fZ = &TruthDeltaR;
260
261 TKey *kKey;
262 TIter itNext(fFile->GetListOfKeys());
263 while ((kKey = (TKey*)itNext()))
264 {
265 TClass *cClass = gROOT->GetClass(kKey->GetClassName());
266 std::string sKeyName = kKey->GetName();
267
268 if (!cClass->InheritsFrom("TH3"))
269 continue;
270
271 T tObj = (T)kKey->ReadObj();
272 tObj->SetDirectory(0);
273 mMap[sKeyName] = tObj;
274 }
275 ATH_MSG_INFO("data loaded from " << fFile->GetName());
276}
277
278//______________________________________________________________________________
280{
281 std::vector<std::string> vInputFilePath;
282 split(m_sInputFilePath,'/',vInputFilePath);
283 std::string sInputFileName = vInputFilePath.back();
284
285 // creation of basic string for all NPs, e.g. "TAUS_TRUEHADTAU_SME_TES_"
286 std::vector<std::string> vSplitInputFilePath = {};
287 split(sInputFileName,'_',vSplitInputFilePath);
288 std::string sEfficiencyType = vSplitInputFilePath.at(0);
289 std::string sTruthType = vSplitInputFilePath.at(1);
290 std::transform(sEfficiencyType.begin(), sEfficiencyType.end(), sEfficiencyType.begin(), toupper);
291 std::transform(sTruthType.begin(), sTruthType.end(), sTruthType.begin(), toupper);
292 std::string sSystematicBaseString = "TAUS_"+sTruthType+"_SME_"+sEfficiencyType+"_";
293
294 // set truth type to check for in truth matching
295 if (sTruthType=="TRUEHADTAU") m_eCheckTruth = TauAnalysisTools::TruthHadronicTau;
296 if (sTruthType=="TRUEHADDITAU") m_eCheckTruth = TauAnalysisTools::TruthHadronicDiTau;
297
298 for (const auto & mSF : m_mDTSF)
299 {
300 // parse for nuisance parameter in histogram name
301 std::vector<std::string> vSplitNP = {};
302 split(mSF.first,'_',vSplitNP);
303 std::string sNP = vSplitNP.at(0);
304 std::string sNPUppercase = vSplitNP.at(0);
305
306 // skip nominal scale factors
307 if (sNP == "sf") continue;
308
309 // test if NP starts with a capital letter indicating that this should be recommended
310 bool bIsRecommended = false;
311 if (isupper(sNP.at(0)))
312 bIsRecommended = true;
313
314 // make sNP uppercase and build final NP entry name
315 std::transform(sNPUppercase.begin(), sNPUppercase.end(), sNPUppercase.begin(), toupper);
316 std::string sSystematicString = sSystematicBaseString+sNPUppercase;
317
318 // add all found systematics to the AffectingSystematics
319 m_sAffectingSystematics.insert(CP::SystematicVariation (sSystematicString, 1));
320 m_sAffectingSystematics.insert(CP::SystematicVariation (sSystematicString, -1));
321 // only add found uppercase systematics to the RecommendedSystematics
322 if (bIsRecommended)
323 {
324 m_sRecommendedSystematics.insert(CP::SystematicVariation (sSystematicString, 1));
325 m_sRecommendedSystematics.insert(CP::SystematicVariation (sSystematicString, -1));
326 }
327
328 ATH_MSG_DEBUG("connected histogram base name " << sNP << " with systematic " <<sSystematicString);
329 m_mSystematicsHistNames.insert({sSystematicString,sNP});
330 }
331}
332
333//______________________________________________________________________________
335 const xAOD::DiTauJet& xDiTau,
336 double& dEfficiencyScaleFactor) const
337{
338 TH3* hHist = m_mDTSF.at(sHistName);
339 if (!hHist)
340 {
341 ATH_MSG_ERROR("Histogram with name "<<sHistName<<" was not found in input file.");
343 }
344
345 double dX = m_fX(xDiTau);
346 double dY = m_fY(xDiTau);
347 double dZ = m_fZ(xDiTau);
348
349 // protect values from underflow bins
350 dX = std::max(dX,hHist->GetXaxis()->GetXmin());
351 dY = std::max(dY,hHist->GetYaxis()->GetXmin());
352 dZ = std::max(dZ,hHist->GetZaxis()->GetXmin());
353 // protect values from overflow bins (times .999 to keep it inside last bin)
354 dX = std::min(dX,hHist->GetXaxis()->GetXmax() * .999);
355 dY = std::min(dY,hHist->GetYaxis()->GetXmax() * .999);
356 dZ = std::min(dZ,hHist->GetZaxis()->GetXmax() * .999);
357
358 int iBin = hHist->FindFixBin(dX,dY,dZ);
359 dEfficiencyScaleFactor = hHist->GetBinContent(iBin);
360
362}
363
365{
366 if (m_bIsConfigured)
367 return StatusCode::SUCCESS;
368
369 const xAOD::EventInfo* xEventInfo = nullptr;
370 ATH_CHECK(evtStore()->retrieve(xEventInfo,"EventInfo"));
372 m_bIsConfigured = true;
373
374 return StatusCode::SUCCESS;
375}
376
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_VERBOSE(x,...)
#define ATH_MSG_INFO(x,...)
#define ATH_MSG_FATAL(x,...)
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
ServiceHandle< StoreGateSvc > & evtStore()
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
double(* m_fY)(const xAOD::DiTauJet &xDiTau)
CommonDiTauSmearingTool(const std::string &sName)
Create a proper constructor for Athena.
virtual CP::SystematicSet recommendedSystematics() const
returns: the list of all systematics this tool recommends to use
virtual CP::CorrectionCode applyCorrection(xAOD::DiTauJet &xDiTau) const
Apply the correction on a modifiable object.
std::unordered_map< CP::SystematicSet, std::string > m_mSystematicSets
std::map< std::string, std::string > m_mSystematicsHistNames
double(* m_fX)(const xAOD::DiTauJet &xDiTau)
virtual CP::CorrectionCode correctedCopy(const xAOD::DiTauJet &xDiTau, xAOD::DiTauJet *&xDiTauCopy) const
Create a corrected copy from a constant ditau.
virtual bool isAffectedBySystematic(const CP::SystematicVariation &systematic) const
returns: whether this tool is affected by the given systematics
double(* m_fZ)(const xAOD::DiTauJet &xDiTau)
virtual StatusCode applySystematicVariation(const CP::SystematicSet &sSystematicSet)
configure this tool for the given list of systematic variations.
virtual CP::SystematicSet affectingSystematics() const
returns: the list of all systematics this tool can be affected by
virtual CP::CorrectionCode getValue(const std::string &sHistName, const xAOD::DiTauJet &xDiTau, double &dCorrectionFactor) const
void ReadInputs(TFile *fFile, std::map< std::string, T > &mMap)
Gaudi::Property< std::string > m_sInputFilePath
virtual StatusCode initialize()
Dummy implementation of the initialisation function.
virtual StatusCode beginEvent()
Function called when a new events is loaded.
AsgMetadataTool(const std::string &name)
Normal ASG tool constructor with a name.
void setP4(double pt, double eta, double phi, double m)
Set methods for IParticle values.
virtual double eta() const
The pseudorapidity ( ) of the particle.
virtual double m() const
The invariant mass of the particle.
virtual double pt() const
The transverse momentum ( ) of the particle.
virtual double phi() const
The azimuthal angle ( ) of the particle.
bool eventType(EventType type) const
Check for one particular bitmask value.
@ IS_SIMULATION
true: simulation, false: data
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.
EventInfo_v1 EventInfo
Definition of the latest event info version.
DiTauJet_v1 DiTauJet
Definition of the current version.
Definition DiTauJet.h:17
#define unlikely(x)