ATLAS Offline Software
Loading...
Searching...
No Matches
ParticleScaleFactorTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5// ReweightUtils includes
7
9
11
12#include "TH2D.h"
13#include "TKey.h"
14#include "TClass.h"
15#include "TFile.h"
16#include <stdexcept>
17
18ParticleScaleFactorTool::ParticleScaleFactorTool( const std::string& name ) : asg::AsgTool( name ){
19
20 declareProperty( "File", m_configFile = "" , "User should specify config file to read");
21
22}
23
25
26 //delete all histograms
27 for(auto& a : m_hists) {
28 for(auto& b : a.second.hists) {
29 delete b.second;
30 }
31 }
32
33}
34
36
37
39 if(file=="") return StatusCode::FAILURE;
40
41 TFile* f = TFile::Open(file.c_str());
42
43 if(!f) {
44 ATH_MSG_ERROR("Could not open file " << file);
45 return StatusCode::FAILURE;
46 }
47
48 m_affectingSysts.insert(CP::SystematicVariation("")); //add the nominal syst
49
50 //loop over the keys in the file, we are looking for TDirectory (systematics) and TH1 (factors)
51 std::unique_ptr<TIterator> itr(f->GetListOfKeys()->MakeIterator());
52 TKey* key = 0;
53 while( (key = static_cast<TKey*>(itr->Next())) ) {
54 TClass* cl = TClass::GetClass(key->GetClassName());
55 if(!cl || !cl->InheritsFrom(TDirectory::Class())) continue;
56 ATH_MSG_DEBUG("Detected systematic " << key->GetName());
57 m_affectingSysts.insert(CP::SystematicVariation(key->GetName()));
58 if(!CP::SystematicVariation(key->GetName()).parameter()) {
59 ATH_MSG_ERROR("Systematic must be of form: <string>__Xup OR <string>__Xdown ... where X is a number");
60 return StatusCode::FAILURE;
61 }
62 }
63
64 itr->Reset();
65 while( (key = static_cast<TKey*>(itr->Next())) ) {
66 TClass* cl = TClass::GetClass(key->GetClassName());
67 if(!cl || !cl->InheritsFrom("TH1")) continue;
68
69
70 ATH_MSG_DEBUG("Detected scale factor " << key->GetName());
71
72 //loop over systematics
73 for(auto& syst : m_affectingSysts) {
74 TString h = (syst==CP::SystematicVariation("")) ? std::string(key->GetName()) : syst.name()+ "/" + std::string(key->GetName());
75 TH1* hist = static_cast<TH1*>(f->Get(h));
76 if(!hist) {
77 if(!(syst==CP::SystematicVariation(""))) {
78 ATH_MSG_VERBOSE("No " << syst.name() << " variation of " << key->GetName());
79 continue; //fine, just no systematic variation
80 } else {
81 ATH_MSG_ERROR("Failed at retrieving " << key->GetName());
82 return StatusCode::FAILURE;
83 }
84 }
85 //detect particle type from title
87 if(strcmp(hist->GetTitle(),"Electron")==0) type = xAOD::Type::Electron;
88 else if(strcmp(hist->GetTitle(),"Muon")==0) type = xAOD::Type::Muon;
89 else if(strcmp(hist->GetTitle(),"Jet")==0) type = xAOD::Type::Jet;
90 else if(strcmp(hist->GetTitle(),"Photon")==0) type = xAOD::Type::Photon;
91 else if(strcmp(hist->GetTitle(),"Tau")==0) type = xAOD::Type::Tau;
92 else {
93 ATH_MSG_ERROR("Unknown particle type: " << hist->GetTitle());
94 return StatusCode::FAILURE;
95 }
96
97 //check all axis are labelled
98 if(strlen(hist->GetXaxis()->GetTitle())==0 ||
99 (hist->GetDimension()>1 && strlen(hist->GetYaxis()->GetTitle())==0) ||
100 (hist->GetDimension()>2 && strlen(hist->GetZaxis()->GetTitle())==0) ) {
101 ATH_MSG_ERROR("All axis of histogram " << hist->GetName() << " need to be labelled");
102 return StatusCode::FAILURE;
103 }
104 //see if nominal already present, if it is we have to 'extend' the existing histogram
105 TH1*& existHist = m_hists[type].hists[syst.name()];
106 if(existHist) {
107 ATH_MSG_DEBUG("Combining " << hist->GetTitle() << ": f(" <<
108 existHist->GetXaxis()->GetTitle() << "," << hist->GetXaxis()->GetTitle() <<
109 ") = 2*f(" << existHist->GetXaxis()->GetTitle() << ")*f(" <<
110 hist->GetXaxis()->GetTitle() << ")/[f(" << existHist->GetXaxis()->GetTitle() <<
111 ")+f(" << hist->GetXaxis()->GetTitle() << ")]");
112
113 TH1* newHist = 0;
114 if(existHist->GetDimension()==1 && hist->GetDimension()==1) {
115 std::vector<double> binEdges1, binEdges2;
116 for(int i=1;i<=existHist->GetNbinsX()+1;i++) binEdges1.push_back(existHist->GetBinLowEdge(i));
117 for(int i=1;i<=hist->GetNbinsX()+1;i++) binEdges2.push_back(hist->GetBinLowEdge(i));
118 newHist = new TH2D("myHist","myHist",existHist->GetNbinsX(),&binEdges1[0],hist->GetNbinsX(),&binEdges2[0]);
119 newHist->SetDirectory(0);
120 newHist->GetXaxis()->SetTitle(existHist->GetTitle());
121 newHist->GetYaxis()->SetTitle(hist->GetTitle());
122 for(int i=0;i<=existHist->GetNbinsX()+1;i++) {
123 for(int j=0;j<=hist->GetNbinsX()+1;j++) {
124 double a = existHist->GetBinContent(i); double b = hist->GetBinContent(j);
125 if(a && b) newHist->SetBinContent(newHist->GetBin(i,j), 2.0 * (a*b)/(a+b) );
126 //combine error ...
127 if(!(syst==CP::SystematicVariation(""))) {
128 double da = existHist->GetBinError(i);double db = hist->GetBinError(j);
129 if(a && b) newHist->SetBinError(newHist->GetBin(i,j), 2.0 * (da*b*b + db*a*a)/((a+b)*(a+b)) );
130 }
131 }
132 }
133 delete existHist;
134 existHist = newHist;
135 } else {
136 ATH_MSG_ERROR("Unsupported scale factor reparamertization :-(");
137 return StatusCode::FAILURE;
138 }
139
140 } else {
141 existHist = static_cast<TH1*>(hist->Clone("myHist")); existHist->SetDirectory(0);
142 //no systematic if nominal hist ...
143 //if(syst==CP::SystematicVariation("")) for(int i=0;i<(hist->GetNbinsX()+2)*(hist->GetNbinsY()+2)*(hist->GetNbinsZ()+2);i++) hist->SetBinError(i,0);
144 }
145
146 if(syst==CP::SystematicVariation("")) {
147 for(int i=0;i<hist->GetDimension();i++) {
148 std::string axisTitle = ( i==0 ) ? hist->GetXaxis()->GetTitle() : ( (i==1) ? hist->GetYaxis()->GetTitle() : hist->GetZaxis()->GetTitle() );
149 axisTitle.erase(remove_if(axisTitle.begin(), axisTitle.end(), isspace),axisTitle.end());
150 std::function<double(const xAOD::IParticle&)> bfunc;
151 ATH_MSG_DEBUG(" Parameter " << axisTitle);
152 if(axisTitle=="pt" || axisTitle=="pt/MeV" || axisTitle=="pt[MeV]") {
153 bfunc = part_pt;
154 } else if(axisTitle == "pt/GeV" || axisTitle=="pt[GeV]") {
155 bfunc = part_pt_gev;
156 } else if(axisTitle=="eta") {
157 bfunc = part_eta;
158 } else {
159 bfunc = std::bind(part_decor, std::placeholders::_1, axisTitle);
160 }
161 m_hists[type].axisFuncs.push_back(std::move(bfunc));
162 }
163 }
164 }
165
166
167
168
169 }
170
171 //remove the nominal syst to finish up
173 m_affectingSysts.clear();
174 for(auto& s : tmpSet) {
175 if(s==CP::SystematicVariation("")) continue;
176 m_affectingSysts.insert(s);
177 //m_affectingSysts.insert(CP::SystematicVariation(s.basename(),-1)); //add the negative fluctuation
178 }
179
180
181 f->Close();
182 delete f;
183 f = 0;
184
185 if(CP::SystematicRegistry::getInstance().registerSystematics(*this) != StatusCode::SUCCESS ) return StatusCode::FAILURE;
186
187 return StatusCode::SUCCESS;
188}
189
190double ParticleScaleFactorTool::evaluate( const xAOD::IParticle* particle ) const {
191 //check we have a hist for this particle type
192 auto histItr = m_hists.find(particle->type());
193 if(histItr==m_hists.end()) {
194 ATH_MSG_ERROR("No scale factor available for particle type: " << particle->type());
195 throw std::runtime_error(TString::Format("%s : No scale factor available for particle type %d",name().c_str(),int(particle->type())).Data());
196 }
197
198
199 std::pair<CP::SystematicVariation,TH1*> res = histItr->second.getHist(m_currentSyst);
200
201 const TH1* hist = res.second;
202
203
204 int bin = 0;
205 switch(hist->GetDimension()) {
206 case 1: bin = hist->FindFixBin(histItr->second.axisFuncs[0](*particle)); break;
207 case 2: bin = hist->FindFixBin(histItr->second.axisFuncs[0](*particle),histItr->second.axisFuncs[1](*particle)); break;
208 case 3: bin = hist->FindFixBin(histItr->second.axisFuncs[0](*particle),histItr->second.axisFuncs[1](*particle),histItr->second.axisFuncs[2](*particle)); break;
209 }
210
211 if(res.first.parameter() == 0.) return hist->GetBinContent(bin); //must have been nominal;
212
213 double nom = histItr->second.getHist(CP::SystematicVariation("")).second->GetBinContent(bin);
214 //got here so get nominal hist and do difference ...
215 return nom + (m_currentSyst.parameter()/res.first.parameter()) * (hist->GetBinContent(bin) - nom);
216
217
218
219
220
221}
222
223const std::pair<CP::SystematicVariation,TH1*>
225 //find hist that matches basename and take the one that has the closest parameter value
226 std::pair<CP::SystematicVariation,TH1*> result(CP::SystematicVariation(""),0);
227 for(auto& s : hists) {
228 if(s.first.basename()!=set.basename()) continue;
229 if(!result.second) {result = s;}
230 else {
231 if(set.parameter()*s.first.parameter()>0) result = s;
232 }
233 }
234 if(result.second) return result;
235 //return nominal
236 auto it = hists.find(CP::SystematicVariation(""));
237 if (it != hists.end()){
238 result = *it;
239 } else {
240 throw std::runtime_error("ParticleScaleFactorTool::Hists::getHist: hist not found!");
241 }
242 return result;
243}
244
245
246
248 for(auto& syst : systConfig) {
249 for(auto& s : m_affectingSysts) {
250 if(s.basename()==syst.basename()) {
251 m_currentSyst = syst; m_isNominal=false;
252 return StatusCode::SUCCESS;
253 }
254 }
255 }
257 m_isNominal = true;
258 return StatusCode::SUCCESS;
259}
260
261
262
#define ATH_MSG_ERROR(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_DEBUG(x)
std::pair< std::vector< unsigned int >, bool > res
static Double_t a
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
Header file for AthHistogramAlgorithm.
static SystematicRegistry & getInstance()
Get the singleton instance of the registry for the curren thread.
Class to wrap a set of SystematicVariations.
float parameter() const
description: the numeric parameter contained in the subvariation(), or 0 if the subvariation can't be...
virtual double evaluate(const xAOD::IParticle *particle) const override
returns: the value that was calculated from the xAOD::IParticle
std::map< xAOD::Type::ObjectType, Hists > m_hists
CP::SystematicVariation m_currentSyst
static double part_decor(const xAOD::IParticle &p, const std::string &varname)
ParticleScaleFactorTool(const std::string &name)
static double part_pt_gev(const xAOD::IParticle &p)
static double part_eta(const xAOD::IParticle &p)
static double part_pt(const xAOD::IParticle &p)
virtual StatusCode initialize() override
Initialize is required by AsgTool base class.
StatusCode applySystematicVariation(const CP::SystematicSet &systConfig) override
effects: configure this tool for the given list of systematic variations.
AsgTool(const std::string &name)
Constructor specifying the tool instance's name.
Definition AsgTool.cxx:58
STL class.
Class providing the definition of the 4-vector interface.
ObjectType
Type of objects that have a representation in the xAOD EDM.
Definition ObjectType.h:32
@ Jet
The object is a jet.
Definition ObjectType.h:40
@ Photon
The object is a photon.
Definition ObjectType.h:47
@ Other
An object not falling into any of the other categories.
Definition ObjectType.h:34
@ Muon
The object is a muon.
Definition ObjectType.h:48
@ Electron
The object is an electron.
Definition ObjectType.h:46
@ Tau
The object is a tau (jet)
Definition ObjectType.h:49
const std::pair< CP::SystematicVariation, TH1 * > getHist(const CP::SystematicVariation &set) const
std::map< CP::SystematicVariation, TH1 * > hists
TFile * file