ATLAS Offline Software
Loading...
Searching...
No Matches
get_MaterialResolutionEffect.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 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
85
86//============================================================================
87// inputs are particle_type (0=elec, 1=reco unconv photon, 2=reco conv photon,
88// 3=true unconv photon)
89// energy in MeV
90// eta
91// response_type (0=gaussian core fit, 1=sigmaeff 80%, 2=sigma eff
92// 90%)
93//
94// returned value is sigmaE/E change in quadrature to resolution
95//
96double get_MaterialResolutionEffect::getDelta(int particle_type, double energy,
97 double eta, int response_type,
98 int isyst) const {
99
100 // cout << " in getDelta " << endl;
101 if (particle_type < 0 || particle_type > 2)
102 return -999;
103 if (response_type < 0 || response_type > 1)
104 return -999;
105
106 float aeta = std::fabs(eta);
107 double energyGeV = energy * 0.001;
108 double et = energyGeV / cosh(eta);
109
110 // IBL+PP0
111 if (isyst == 5) {
112 double et2 = et;
113 if (et < 5.) {
114 et2 = 5.1;
115 }
116 if (et > 2000) {
117 et2 = 1999.;
118 }
119 if (aeta>=2.5) aeta=2.49;
120
121 int ieta = m_hsyst_IBL_PP0.at(particle_type)->GetXaxis()->FindBin(aeta);
122 int iet = m_hsyst_IBL_PP0.at(particle_type)->GetYaxis()->FindBin(et2);
123 if (m_interpolate) {
124 return 0.01*interpolateTH1(m_hsyst_IBL_PP0_ProjectionY[particle_type][ieta - 1].get(), et2, true);
125 }
126 else {
127 return 0.01*m_hsyst_IBL_PP0.at(particle_type)->GetBinContent(ieta, iet);
128 }
129 }
130
131 int ieta = 0;
132 if (aeta < 0.4) {
133 ieta = 0;
134 } else if (aeta < 0.8) {
135 ieta = 1;
136 } else if (aeta < 1.1) {
137 ieta = 2;
138 } else if (aeta < 1.37) {
139 ieta = 3;
140 } else if (aeta < 1.52) {
141 ieta = 4;
142 } else if (aeta < 1.80) {
143 ieta = 5;
144 } else if (aeta < 2.10) {
145 ieta = 6;
146 } else {
147 ieta = 7;
148 }
149
150 int ibinEt = m_etBins->GetSize() - 2;
151 for (int i = 1; i < m_etBins->GetSize(); i++) {
152 if (et < m_etBins->GetAt(i)) {
153 ibinEt = i - 1;
154 break;
155 }
156 }
157
158 const auto& hist = response_type==0 ? m_hSystPeak : m_hSystResol;
159 if (m_interpolate) {
160 return 0.01*interpolateTH1(hist.at(isyst).at(ieta).at(particle_type).get(), et, true);
161 }
162 else {
163 return 0.01*hist.at(isyst).at(ieta).at(particle_type)->GetBinContent(ibinEt+1);
164 }
165
166}
167//=========================================================================
169{
170 for (size_t i = 0; i < m_hsyst_IBL_PP0.size(); i++) {
171 if (m_hsyst_IBL_PP0[i]) {
172 int nEtaBins = m_hsyst_IBL_PP0[i]->GetNbinsX();
173 // Resize the inner vector to match the size of TH2 x-axis bins
174 m_hsyst_IBL_PP0_ProjectionY[i].resize(nEtaBins);
175 for (int ieta : std::views::iota(1, nEtaBins + 1)) {
176 std::string histName = std::format("h1d_IBL_PP0_ptype{}_EtaBin_{}", i, ieta);
177 m_hsyst_IBL_PP0_ProjectionY[i][ieta - 1].reset( dynamic_cast<TH1*>(m_hsyst_IBL_PP0[i]->ProjectionY(histName.c_str(), ieta, ieta)) );
178 m_hsyst_IBL_PP0_ProjectionY[i][ieta - 1]->SetDirectory( nullptr );
179 }
180 }
181 }
182}
183
184//=========================================================================
185double get_MaterialResolutionEffect::interpolateTH1(TH1 *hist, double x, bool abs_bins)
186{
187 if (!hist) return 0.;
188 int nbins = hist->GetNbinsX();
189
190 if(x<=hist->GetBinCenter(1)) {
191 return abs_bins? std::abs(hist->GetBinContent(1)) : hist->GetBinContent(1);
192 }
193 else if(x>=hist->GetBinCenter(nbins)) {
194 return abs_bins? std::abs(hist->GetBinContent(nbins)) : hist->GetBinContent(nbins);
195 }
196 else {
197 int xbin = hist->FindBin(x);
198 int xbin0, xbin1;
199 if(x<=hist->GetBinCenter(xbin)) {
200 xbin0 = xbin - 1;
201 xbin1 = xbin;
202 }
203 else {
204 xbin0 = xbin;
205 xbin1 = xbin + 1;
206 }
207 double y0 = abs_bins? std::abs(hist->GetBinContent(xbin0)) : hist->GetBinContent(xbin0);
208 double x0 = hist->GetBinCenter(xbin0);
209 double y1 = abs_bins? std::abs(hist->GetBinContent(xbin1)) : hist->GetBinContent(xbin1);
210 double x1 = hist->GetBinCenter(xbin1);
211 return y0 + (x-x0)*((y1-y0)/(x1-x0));
212 }
213}
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.