ATLAS Offline Software
Loading...
Searching...
No Matches
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
15namespace {
16template <typename TargetPtr, typename SourcePtr>
17TargetPtr checked_cast(SourcePtr ptr) {
18 static_assert(std::is_pointer<TargetPtr>::value,
19 "attempt to cast to no ptr object");
20 static_assert(std::is_pointer<SourcePtr>::value,
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//
94double get_MaterialResolutionEffect::getDelta(int particle_type, double energy,
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 const 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
172 m_hsyst_IBL_PP0_ProjectionY[i].resize(nEtaBins);
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//=========================================================================
183double get_MaterialResolutionEffect::interpolateTH1(TH1 *hist, double x, bool abs_bins)
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}
Scalar eta() const
pseudorapidity method
float et(const xAOD::jFexSRJetRoI *j)
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
#define x
AsgMessaging(const std::string &name)
Constructor with a name.
get_MaterialResolutionEffect()
constructor (initialization done there reading root files with resolution fit parameters
static double interpolateTH1(TH1 *hist, double x, bool abs_bins)
std::array< std::array< std::array< std::unique_ptr< TH1 >, 3 >, s_nEtaBins >, s_nSys > m_hSystPeak
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...
std::array< std::unique_ptr< TH2 >, 3 > m_hsyst_IBL_PP0
std::array< std::array< std::array< std::unique_ptr< TH1 >, 3 >, s_nEtaBins >, s_nSys > m_hSystResol
std::array< std::vector< std::unique_ptr< TH1 > >, 3 > m_hsyst_IBL_PP0_ProjectionY
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition hcg.cxx:130
void * ptr(T *p)
Definition SGImplSvc.cxx:74
Extra patterns decribing particle interation process.