ATLAS Offline Software
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 
18 ParticleScaleFactorTool::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());
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
86  xAOD::Type::ObjectType type = xAOD::Type::Other;
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
174  for(auto& s : tmpSet) {
175  if(s==CP::SystematicVariation("")) continue;
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 
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 
223 const 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 
ParticleScaleFactorTool::Hists::hists
std::map< CP::SystematicVariation, TH1 * > hists
Definition: ParticleScaleFactorTool.h:73
Trk::ParticleSwitcher::particle
constexpr ParticleHypothesis particle[PARTICLEHYPOTHESES]
the array of masses
Definition: ParticleHypothesis.h:79
xAOD::Electron
Electron_v1 Electron
Definition of the current "egamma version".
Definition: Event/xAOD/xAODEgamma/xAODEgamma/Electron.h:17
get_generator_info.result
result
Definition: get_generator_info.py:21
ParticleScaleFactorTool::ParticleScaleFactorTool
ParticleScaleFactorTool(const std::string &name)
Definition: ParticleScaleFactorTool.cxx:18
ParticleScaleFactorTool::applySystematicVariation
StatusCode applySystematicVariation(const CP::SystematicSet &systConfig) override
effects: configure this tool for the given list of systematic variations.
Definition: ParticleScaleFactorTool.cxx:247
ObjectType
ObjectType
Definition: BaseObject.h:11
plotmaker.hist
hist
Definition: plotmaker.py:148
StateLessPT_NewConfig.Format
Format
Definition: StateLessPT_NewConfig.py:149
CaloCondBlobAlgs_fillNoiseFromASCII.db
db
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:42
skel.it
it
Definition: skel.GENtoEVGEN.py:407
asg
Definition: DataHandleTestTool.h:28
CP::SystematicSet
Class to wrap a set of SystematicVariations.
Definition: SystematicSet.h:31
bin
Definition: BinsDiffFromStripMedian.h:43
ParticleScaleFactorTool::Hists::getHist
const std::pair< CP::SystematicVariation, TH1 * > getHist(const CP::SystematicVariation &set) const
Definition: ParticleScaleFactorTool.cxx:224
ParticleScaleFactorTool::part_decor
static double part_decor(const xAOD::IParticle &p, const std::string &varname)
Definition: ParticleScaleFactorTool.h:37
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
CP::SystematicVariation
Definition: SystematicVariation.h:47
xAOD::IParticle
Class providing the definition of the 4-vector interface.
Definition: Event/xAOD/xAODBase/xAODBase/IParticle.h:41
python.CaloAddPedShiftConfig.type
type
Definition: CaloAddPedShiftConfig.py:42
ParticleScaleFactorTool::m_currentSyst
CP::SystematicVariation m_currentSyst
Definition: ParticleScaleFactorTool.h:70
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
ParticleScaleFactorTool::part_pt
static double part_pt(const xAOD::IParticle &p)
Definition: ParticleScaleFactorTool.h:34
lumiFormat.i
int i
Definition: lumiFormat.py:85
SystematicRegistry.h
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
AthCommonDataStore< AthCommonMsg< AlgTool > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
Definition: AthCommonDataStore.h:145
MakeNewFileFromOldAndSubstitution.newHist
dictionary newHist
Definition: ICHEP2016/MakeNewFileFromOldAndSubstitution.py:96
ParticleScaleFactorTool::m_affectingSysts
CP::SystematicSet m_affectingSysts
Definition: ParticleScaleFactorTool.h:80
res
std::pair< std::vector< unsigned int >, bool > res
Definition: JetGroupProductTest.cxx:11
file
TFile * file
Definition: tile_monitor.h:29
hist_file_dump.f
f
Definition: hist_file_dump.py:140
xAOD::double
double
Definition: CompositeParticle_v1.cxx:159
CxxUtils::set
constexpr std::enable_if_t< is_bitmask_v< E >, E & > set(E &lhs, E rhs)
Convenience function to set bits in a class enum bitmask.
Definition: bitmask.h:232
ParticleScaleFactorTool::initialize
virtual StatusCode initialize() override
Initialize is required by AsgTool base class.
Definition: ParticleScaleFactorTool.cxx:35
PathResolver.h
PlotSFuncertainty.nom
nom
Definition: PlotSFuncertainty.py:141
CP::SystematicSet::insert
void insert(const SystematicVariation &systematic)
description: insert a systematic into the set
Definition: SystematicSet.cxx:87
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:76
ParticleScaleFactorTool::m_configFile
std::string m_configFile
Definition: ParticleScaleFactorTool.h:68
ParticleScaleFactorTool::m_hists
std::map< xAOD::Type::ObjectType, Hists > m_hists
Definition: ParticleScaleFactorTool.h:78
xAOD::Photon
Photon_v1 Photon
Definition of the current "egamma version".
Definition: Event/xAOD/xAODEgamma/xAODEgamma/Photon.h:17
PathResolverFindCalibFile
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
Definition: PathResolver.cxx:321
Muon
struct TBPatternUnitContext Muon
CP::SystematicSet::clear
void clear()
description: clear the set
Definition: SystematicSet.cxx:118
ParticleScaleFactorTool::m_isNominal
bool m_isNominal
Definition: ParticleScaleFactorTool.h:81
a
TList * a
Definition: liststreamerinfos.cxx:10
h
ParticleScaleFactorTool.h
ParticleScaleFactorTool::part_eta
static double part_eta(const xAOD::IParticle &p)
Definition: ParticleScaleFactorTool.h:36
python.SystemOfUnits.s
float s
Definition: SystemOfUnits.py:147
xAODType::Tau
@ Tau
The object is a tau (jet)
Definition: ObjectType.h:49
ParticleScaleFactorTool::~ParticleScaleFactorTool
~ParticleScaleFactorTool()
Definition: ParticleScaleFactorTool.cxx:24
dq_make_web_display.cl
cl
print [x.__class__ for x in toList(dqregion.getSubRegions()) ]
Definition: dq_make_web_display.py:25
xAOD::Jet
Jet_v1 Jet
Definition of the current "jet version".
Definition: Event/xAOD/xAODJet/xAODJet/Jet.h:17
ParticleScaleFactorTool::part_pt_gev
static double part_pt_gev(const xAOD::IParticle &p)
Definition: ParticleScaleFactorTool.h:35
CP::SystematicRegistry::getInstance
static SystematicRegistry & getInstance()
Get the singleton instance of the registry for the curren thread.
Definition: SystematicRegistry.cxx:25
ParticleScaleFactorTool::evaluate
virtual double evaluate(const xAOD::IParticle *particle) const override
returns: the value that was calculated from the xAOD::IParticle
Definition: ParticleScaleFactorTool.cxx:190
CP::SystematicVariation::parameter
float parameter() const
description: the numeric parameter contained in the subvariation(), or 0 if the subvariation can't be...
Definition: SystematicVariation.cxx:340
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37