ATLAS Offline Software
get_MaterialResolutionEffect.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 
8 #include "TArrayD.h"
9 #include "TFile.h"
10 #include "TH1.h"
11 #include "TH2.h"
12 #include <format> // For std::format
13 #include <ranges> // For std::views::iota
14 
15 namespace {
16 template <typename TargetPtr, typename SourcePtr>
17 TargetPtr checked_cast(SourcePtr ptr) {
19  "attempt to cast to no ptr object");
21  "attempt to cast from no ptr object");
22  if (!ptr) {
23  throw std::runtime_error(
24  "Attempt to cast from nullptr in get_MaterialResolutionEffect");
25  }
26  TargetPtr obj = dynamic_cast<TargetPtr>(ptr);
27  if (not obj) {
28  throw std::runtime_error("failed dynamic cast for " +
29  std::string(ptr->GetName()) +
30  " get_MaterialResolutionEffect");
31  }
32  return obj;
33 }
34 } // namespace
35 
37  : asg::AsgMessaging("get_MaterialResolutionEffect") {
38 
39  const std::string pType[3] = {"Elec", "Unconv", "Conv"};
40  const std::string sType[s_nSys] = {"A", "CD", "EL", "FMX"};
41 
42  const std::string filename = PathResolverFindCalibFile(
43  "ElectronPhotonFourMomentumCorrection/v8/"
44  "histos-systematics-material.root");
45 
46  std::unique_ptr<TFile> file0(TFile::Open(filename.c_str(), "READ"));
47 
48  for (Int_t isys = 0; isys < s_nSys; isys++) { // 0=A, 1=CD, 2=EL, 3=FMX
49  for (Int_t ieta = 0; ieta < s_nEtaBins; ieta++) {
50  for (Int_t iconv = 0; iconv < 3;
51  iconv++) { // 0=electron, 1=unconverted, 2=converted
52  char name[31];
53  sprintf(name, "syst%s_%s_etaBin_%d", pType[iconv].c_str(),
54  sType[isys].c_str(), ieta);
55  m_hSystPeak.at(isys).at(ieta).at(iconv).reset(
56  checked_cast<TH1*>(file0->Get(name)));
57  m_hSystPeak.at(isys).at(ieta).at(iconv)->SetDirectory(nullptr);
58 
59  sprintf(name, "syst%s_sigmaG_%s_etaBin_%d", pType[iconv].c_str(),
60  sType[isys].c_str(), ieta);
61  m_hSystResol.at(isys).at(ieta).at(iconv).reset(
62  checked_cast<TH1*>(file0->Get(name)));
63  m_hSystResol.at(isys).at(ieta).at(iconv)->SetDirectory(nullptr);
64  }
65  }
66  }
67 
68  // IBL+PP0 material systematics stored in 2D histograms
69  m_hsyst_IBL_PP0.at(0).reset(
70  checked_cast<TH2*>(file0->Get("systElec_IBLPP0")));
71  m_hsyst_IBL_PP0.at(0)->SetDirectory(nullptr);
72 
73  m_hsyst_IBL_PP0.at(1).reset(
74  checked_cast<TH2*>(file0->Get("systUnconv_IBLPP0")));
75  m_hsyst_IBL_PP0.at(1)->SetDirectory(nullptr);
76 
77  m_hsyst_IBL_PP0.at(2).reset(
78  checked_cast<TH2*>(file0->Get("systConv_IBLPP0")));
79  m_hsyst_IBL_PP0.at(2)->SetDirectory(nullptr);
80 
81  m_etBins = m_hSystResol.at(0).at(0).at(1)->GetXaxis()->GetXbins();
82 }
83 
84 //============================================================================
85 // inputs are particle_type (0=elec, 1=reco unconv photon, 2=reco conv photon,
86 // 3=true unconv photon)
87 // energy in MeV
88 // eta
89 // response_type (0=gaussian core fit, 1=sigmaeff 80%, 2=sigma eff
90 // 90%)
91 //
92 // returned value is sigmaE/E change in quadrature to resolution
93 //
95  double eta, int response_type,
96  int isyst) const {
97 
98  // cout << " in getDelta " << endl;
99  if (particle_type < 0 || particle_type > 2)
100  return -999;
101  if (response_type < 0 || response_type > 1)
102  return -999;
103 
104  float aeta = std::fabs(eta);
105  double energyGeV = energy * 0.001;
106  double et = energyGeV / cosh(eta);
107 
108  // IBL+PP0
109  if (isyst == 5) {
110  double et2 = et;
111  if (et < 5.) {
112  et2 = 5.1;
113  }
114  if (et > 2000) {
115  et2 = 1999.;
116  }
117  if (aeta>=2.5) aeta=2.49;
118 
119  int ieta = m_hsyst_IBL_PP0.at(particle_type)->GetXaxis()->FindBin(aeta);
120  int iet = m_hsyst_IBL_PP0.at(particle_type)->GetYaxis()->FindBin(et2);
121  if (m_interpolate) {
122  return 0.01*interpolateTH1(m_hsyst_IBL_PP0_ProjectionY[particle_type][ieta - 1].get(), et2, true);
123  }
124  else {
125  return 0.01*m_hsyst_IBL_PP0.at(particle_type)->GetBinContent(ieta, iet);
126  }
127  }
128 
129  int ieta = 0;
130  if (aeta < 0.4) {
131  ieta = 0;
132  } else if (aeta < 0.8) {
133  ieta = 1;
134  } else if (aeta < 1.1) {
135  ieta = 2;
136  } else if (aeta < 1.37) {
137  ieta = 3;
138  } else if (aeta < 1.52) {
139  ieta = 4;
140  } else if (aeta < 1.80) {
141  ieta = 5;
142  } else if (aeta < 2.10) {
143  ieta = 6;
144  } else {
145  ieta = 7;
146  }
147 
148  int ibinEt = m_etBins->GetSize() - 2;
149  for (int i = 1; i < m_etBins->GetSize(); i++) {
150  if (et < m_etBins->GetAt(i)) {
151  ibinEt = i - 1;
152  break;
153  }
154  }
155 
156  auto& hist = response_type==0 ? m_hSystPeak : m_hSystResol;
157  if (m_interpolate) {
158  return 0.01*interpolateTH1(hist.at(isyst).at(ieta).at(particle_type).get(), et, true);
159  }
160  else {
161  return 0.01*hist.at(isyst).at(ieta).at(particle_type)->GetBinContent(ibinEt+1);
162  }
163 
164 }
165 //=========================================================================
167 {
168  for (size_t i = 0; i < m_hsyst_IBL_PP0.size(); i++) {
169  if (m_hsyst_IBL_PP0[i]) {
170  int nEtaBins = m_hsyst_IBL_PP0[i]->GetNbinsX();
171  // Resize the inner vector to match the size of TH2 x-axis bins
173  for (int ieta : std::views::iota(1, nEtaBins + 1)) {
174  std::string histName = std::format("h1d_IBL_PP0_ptype{}_EtaBin_{}", i, ieta);
175  m_hsyst_IBL_PP0_ProjectionY[i][ieta - 1].reset( dynamic_cast<TH1*>(m_hsyst_IBL_PP0[i]->ProjectionY(histName.c_str(), ieta, ieta)) );
176  m_hsyst_IBL_PP0_ProjectionY[i][ieta - 1]->SetDirectory( nullptr );
177  }
178  }
179  }
180 }
181 
182 //=========================================================================
183 double get_MaterialResolutionEffect::interpolateTH1(TH1 *hist, double x, bool abs_bins) const
184 {
185  if (!hist) return 0.;
186  int nbins = hist->GetNbinsX();
187 
188  if(x<=hist->GetBinCenter(1)) {
189  return abs_bins? std::abs(hist->GetBinContent(1)) : hist->GetBinContent(1);
190  }
191  else if(x>=hist->GetBinCenter(nbins)) {
192  return abs_bins? std::abs(hist->GetBinContent(nbins)) : hist->GetBinContent(nbins);
193  }
194  else {
195  int xbin = hist->FindBin(x);
196  int xbin0, xbin1;
197  if(x<=hist->GetBinCenter(xbin)) {
198  xbin0 = xbin - 1;
199  xbin1 = xbin;
200  }
201  else {
202  xbin0 = xbin;
203  xbin1 = xbin + 1;
204  }
205  double y0 = abs_bins? std::abs(hist->GetBinContent(xbin0)) : hist->GetBinContent(xbin0);
206  double x0 = hist->GetBinCenter(xbin0);
207  double y1 = abs_bins? std::abs(hist->GetBinContent(xbin1)) : hist->GetBinContent(xbin1);
208  double x1 = hist->GetBinCenter(xbin1);
209  return y0 + (x-x0)*((y1-y0)/(x1-x0));
210  }
211 }
plotBeamSpotCompare.x1
x1
Definition: plotBeamSpotCompare.py:216
get_MaterialResolutionEffect::m_interpolate
bool m_interpolate
Definition: get_MaterialResolutionEffect.h:65
et
Extra patterns decribing particle interation process.
AddEmptyComponent.histName
string histName
Definition: AddEmptyComponent.py:64
vtune_athena.format
format
Definition: vtune_athena.py:14
TCS::KFMET::nEtaBins
constexpr unsigned nEtaBins
Definition: KalmanMETCorrectionConstants.h:18
xAOD::et
et
Definition: TrigEMCluster_v1.cxx:25
eta
Scalar eta() const
pseudorapidity method
Definition: AmgMatrixBasePlugin.h:83
plotmaker.hist
hist
Definition: plotmaker.py:148
asg
Definition: DataHandleTestTool.h:28
EgammaARTmonitoring_plotsMaker.particle_type
particle_type
Definition: EgammaARTmonitoring_plotsMaker.py:633
athena.value
value
Definition: athena.py:124
get_MaterialResolutionEffect::getDelta
double getDelta(int particle_type, double energy, double eta, int response_type, int isyst) const
get material effect on resolution from distorted geometry as difference to 40 GeV Et electrons smeari...
Definition: get_MaterialResolutionEffect.cxx:94
dbg::ptr
void * ptr(T *p)
Definition: SGImplSvc.cxx:74
get_MaterialResolutionEffect::s_nSys
static const int s_nSys
Definition: get_MaterialResolutionEffect.h:58
x
#define x
SCT_CalibAlgs::nbins
@ nbins
Definition: SCT_CalibNumbers.h:10
get_MaterialResolutionEffect::m_hsyst_IBL_PP0_ProjectionY
std::array< std::vector< std::unique_ptr< TH1 > >, 3 > m_hsyst_IBL_PP0_ProjectionY
Definition: get_MaterialResolutionEffect.h:64
makeTRTBarrelCans.y1
tuple y1
Definition: makeTRTBarrelCans.py:15
ParticleGun_FastCalo_ChargeFlip_Config.energy
energy
Definition: ParticleGun_FastCalo_ChargeFlip_Config.py:78
lumiFormat.i
int i
Definition: lumiFormat.py:85
get_MaterialResolutionEffect::get_MaterialResolutionEffect
get_MaterialResolutionEffect()
constructor (initialization done there reading root files with resolution fit parameters
Definition: get_MaterialResolutionEffect.cxx:36
get_MaterialResolutionEffect.h
get_MaterialResolutionEffect::m_etBins
const TArrayD * m_etBins
Definition: get_MaterialResolutionEffect.h:66
PathResolver.h
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:221
get_MaterialResolutionEffect::interpolateTH1
double interpolateTH1(TH1 *hist, double x, bool abs_bins) const
Definition: get_MaterialResolutionEffect.cxx:183
get_MaterialResolutionEffect::m_hSystPeak
std::array< std::array< std::array< std::unique_ptr< TH1 >, 3 >, s_nEtaBins >, s_nSys > m_hSystPeak
Definition: get_MaterialResolutionEffect.h:59
PathResolverFindCalibFile
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
Definition: PathResolver.cxx:431
get
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition: hcg.cxx:127
CaloCellTimeCorrFiller.filename
filename
Definition: CaloCellTimeCorrFiller.py:24
get_MaterialResolutionEffect::m_hSystResol
std::array< std::array< std::array< std::unique_ptr< TH1 >, 3 >, s_nEtaBins >, s_nSys > m_hSystResol
Definition: get_MaterialResolutionEffect.h:60
get_MaterialResolutionEffect::store_IBL_PP0_YProjections
void store_IBL_PP0_YProjections()
Definition: get_MaterialResolutionEffect.cxx:166
get_MaterialResolutionEffect::m_hsyst_IBL_PP0
std::array< std::unique_ptr< TH2 >, 3 > m_hsyst_IBL_PP0
Definition: get_MaterialResolutionEffect.h:61
get_MaterialResolutionEffect::s_nEtaBins
static const int s_nEtaBins
Definition: get_MaterialResolutionEffect.h:57
python.PyAthena.obj
obj
Definition: PyAthena.py:132