ATLAS Offline Software
Loading...
Searching...
No Matches
EgammaSshapeCalibration.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//#include "TrigCaloEvent/TrigEMCluster.h"
8#include "CaloDetDescr/CaloDetDescrElement.h"
11#include <math.h>
12#include <iomanip>
13
14//====================================================================
15// initialize
16//====================================================================
18 CHECK(base_class::initialize());
19 ATH_MSG_DEBUG( "Initialize Tool : " << name() );
20 return StatusCode::SUCCESS;
21}
22
23//====================================================================
24// finalize
25//====================================================================
27 return StatusCode::SUCCESS;
28}
29
30//====================================================================
31// EgammaSshapeCalibration::makeCorrection
32//====================================================================
34 const void *arg) const{
35
36 if(arg!=0){
37 const CaloDetDescrElement *caloDDE = (const CaloDetDescrElement*) arg;
38
39 bool isRange_barrel = m_isRange_barrel();
40
41#ifndef NDEBUG
42 ATH_MSG_DEBUG( "caloDDE->descriptor()->is_lar_em_barrel() = "
43 << caloDDE->descriptor()->is_lar_em_barrel() );
44 ATH_MSG_DEBUG( "caloDDE->descriptor()->is_lar_em_endcap() = "
45 << caloDDE->descriptor()->is_lar_em_endcap() );
46
47 ATH_MSG_DEBUG( "m_isRange_barrel=" << isRange_barrel );
48
49 ATH_MSG_DEBUG( "clus->energy(CaloSampling::PreSamplerB) = "
50 << clus->energy(CaloSampling::PreSamplerB) );
51 ATH_MSG_DEBUG( "clus->energy(CaloSampling::EMB1) = "
52 << clus->energy(CaloSampling::EMB1) );
53 ATH_MSG_DEBUG( "clus->energy(CaloSampling::EMB2) = "
54 << clus->energy(CaloSampling::EMB2) );
55 ATH_MSG_DEBUG( "clus->energy(CaloSampling::EMB3) = "
56 << clus->energy(CaloSampling::EMB3) );
57 ATH_MSG_DEBUG( "clus->energy(CaloSampling::PreSamplerE) = "
58 << clus->energy(CaloSampling::PreSamplerE) );
59 ATH_MSG_DEBUG( "clus->energy(CaloSampling::EME1) = "
60 << clus->energy(CaloSampling::EME1) );
61 ATH_MSG_DEBUG( "clus->energy(CaloSampling::EME2) = "
62 << clus->energy(CaloSampling::EME2) );
63 ATH_MSG_DEBUG( "clus->energy(CaloSampling::EME3) = "
64 << clus->energy(CaloSampling::EME3) );
65
66 if((caloDDE->descriptor()->is_lar_em_barrel() && isRange_barrel) ||
67 (caloDDE->descriptor()->is_lar_em_endcap() && !isRange_barrel))
68 ATH_MSG_DEBUG( "[GOOD]: seedCell location and selected eta range agree" );
69 else if((caloDDE->descriptor()->is_lar_em_barrel() && !isRange_barrel) ||
70 (caloDDE->descriptor()->is_lar_em_endcap() && isRange_barrel))
71 ATH_MSG_DEBUG( "[BAD]: seedCell location and selected eta range disagree !!" );
72#endif
73
74 // check if seedCell is in barrel or end-cap for correct range selection
75 if((caloDDE->descriptor()->is_lar_em_barrel() && !isRange_barrel) ||
76 (caloDDE->descriptor()->is_lar_em_endcap() && isRange_barrel))
77 return;
78
79 double eta = clus->eta(); // cluster position in eta
80 double elt_eta = caloDDE->eta(); // seedCell position in eta
81 double elt_deta = caloDDE->deta(); // seedCell width in eta
82
83 // Find u, the normalized displacement of the cluster within the cell
84 // in the range -1...1, with 0 being at the center.
85 double u = 2*(eta-elt_eta)/elt_deta; // position within cell
86
87 // cluster position in eta without accounting for alignment corrections
88 double elt_eta_raw = clus->rawEta();
89
90 if(elt_eta_raw<0.) u=-u;
91
92 // Sanity-check of valid u-range...
93 if(u>1)
94 u=1;
95 else if(u<-1)
96 u=-1;
97
98 // The eta adjusted for any shift between the actual and nominal coordinates.
99 double aeta = fabs(eta - elt_eta + elt_eta_raw);
100
101#ifndef NDEBUG
102 ATH_MSG_DEBUG( "eta = " << eta );
103 ATH_MSG_DEBUG( "elt_eta = " << elt_eta );
104 ATH_MSG_DEBUG( "elt_deta = " << elt_deta );
105 ATH_MSG_DEBUG( "elt_eta_raw = " << elt_eta_raw );
106 ATH_MSG_DEBUG( "u = " << u );
107 ATH_MSG_DEBUG( "aeta = " << aeta );
108#endif
109
110 // Find the appropriate region
111 int region_ndx=-1;
113 unsigned int nreg = regions.size();
114
115 // find correct region
116 for (unsigned int i=0; i<nreg; i++) {
117 if(aeta>=regions[i][REG_LO] && aeta<regions[i][REG_HI]){
118 region_ndx=i;
119 break;
120 }
121 }
122
123 // Sanity-check for region index...
124 if(region_ndx<0){
125 return;
126 }
127
128 // In a few regions, the fit was done using a cell size different
129 // from what we actually have. Need to recalculate u in this case.
130 if(std::abs(regions[region_ndx][REG_CELLSIZE]-elt_deta) > 1e-3) {
131 float cellsize = regions[region_ndx][REG_CELLSIZE];
132 u = fmod(aeta,cellsize)/cellsize*2 - 1;
133 }
134
135 float energy = clus->energy();
136
137 Builder *builder = new Builder(*this, aeta, u, region_ndx);
138
139 // Calculate the correction for each energy.
140 const CxxUtils::Array<1> energies = m_energies();
141 unsigned int n_energies = energies.size();
142 unsigned int shape[] = {n_energies, 2};
143 CaloRec::WritableArrayData<2> corrtab (shape);
144
145 // If we're outside the range of the table, we'll just be using the
146 // value at the end (no extrapolation). We only need to calculate
147 // that one point in that case.
148 unsigned int beg = 0;
149 unsigned int end = n_energies;
150 if(energy <= energies[0]) // ok. energies also in MeV
151 end = 1;
152 else if(energy >= energies[n_energies-1])// ok. energies also in MeV
153 beg = n_energies-1;
154
155 // Build the table.
156 int n_good = 0;
157 for (unsigned int i=beg; i<end; i++)
158 docalc(i, *builder, energies, corrtab, n_good);
159
160 // If we only evaluated one point, but it wasn't good, keep
161 // searching until we find a good one.
162 while (n_good==0 && beg>0) {
163 --beg;
164 docalc (beg, *builder, energies, corrtab, n_good);
165 }
166 while (n_good == 0 && end<n_energies) {
167 docalc(end, *builder, energies, corrtab, n_good);
168 ++end;
169 }
170
171 // Now interpolate in energy.
172 // But if we're outside of the range of the table, just use the value
173 // at the end (don't extrapolate).
174
175 float offs=0;
176
177 if(n_good==0){ // No good energies --- return a null correction.
178 offs=0;
179 }
180 else if(n_good==1){ // Only one good energy --- nothing to do but to use it.
181 offs=corrtab[0][1];
182 }
183 else if(energy<=corrtab[0][0]){ // Off the low end of the table --- return the first value.
184 offs=corrtab[0][1];
185 }
186 else if(energy>=corrtab[n_good-1][0]) { // Off the high end of the table --- return the last value.
187 offs=corrtab[n_good-1][1];
188 }
189 else{ // Do the interpolation.
190 offs = CaloClusterCorr::interpolate(corrtab,
191 energy,
193 1,
195 n_good);
196 }
197
198 if (eta<0)
199 offs=-offs;
200
201 clus->setEta(eta+offs);
202
203#ifndef NDEBUG
204 ATH_MSG_DEBUG( "Before correction : " << eta );
205 ATH_MSG_DEBUG( "offset =" << offs );
206 ATH_MSG_DEBUG( "After correction : " << eta+offs );
207#endif
208
209 delete builder;
210 }
211}
212
213//====================================================================
214// EgammaSshapeCalibration::docalc
215//====================================================================
218 const CaloRec::Array<1>& energies,
220 int& n_good) const {
221 corrtab[n_good][0] = energies[i];
222 bool good = false;
223 corrtab[n_good][1] = builder.calculate (i, good);
224 if (good)
225 ++n_good;
226}
227
228
229//====================================================================
230//
231// Builder constructor
232//
233//====================================================================
235 double aeta,
236 double u,
237 int region_ndx)
238 : m_corr(corr),
239 m_aeta(aeta),
240 m_u(u),
241 m_region_ndx(region_ndx),
242 m_form (m_corr.m_regions()[region_ndx][REG_FORM])
243{ }
244
245//====================================================================
246// EgammaSshapeCalibration::Builder::calculate
247//====================================================================
249 bool& good) const {
250
251 // Find the proper array of coefficients.
252 CaloRec::Array<2> coef = m_corr.m_correction()[energy_ndx][m_region_ndx];
253
254 // If we don't have coefficients for this energy/region, skip it.
255 if(coef[0].end()[-1]==0) {
256 good = false;
257 return 0;
258 }
259
260 // Which functional form to use?
261 int form;
262 CxxUtils::Array<2> forms = m_corr.m_forms();
263 if (forms.size(0) != 0 && forms.size(1) != 0)
264 form = forms[m_region_ndx][energy_ndx];
265 else
266 form = m_form;
267
268
269 // Evaluate the correction!
270 good = true;
271 float ret = 0;
272 switch (form) {
273 case 0:
274 ret = calc0 (m_aeta, m_u, coef);
275 break;
276 case 3:
277 ret = calc3 (m_aeta, m_u, coef);
278 break;
279 case 4:
280 ret = calc4 (m_aeta, m_u, coef);
281 break;
282 case 5:
283 ret = calc5 (m_aeta, m_u, coef);
284 break;
285 case 10:
286 ret = calc10 (m_aeta, m_u, coef);
287 break;
288 case 11:
289 ret = calc11 (m_aeta, m_u, coef);
290 break;
291 default:
292 abort();
293 }
294
295 return ret;
296}
297
298//====================================================================
299// EgammaSshapeCalibration::Builder::calc0
300//====================================================================
302 float u,
303 const CaloRec::Array<2>& coef) const
304{
305 const unsigned int NPAR = 5;
306 double pars[NPAR];
307
308 unsigned int degree = coef.size(1);
309 for (unsigned int i=0; i < NPAR; i++) {
310 CaloRec::Array<1> xcoef = coef[i];
311 double out = xcoef[0];
312 for (unsigned int j=1; j<degree; j++)
313 out = out * aeta + xcoef[j];
314 pars[i] = out;
315 }
316
317 double c = (u>=0) ? pars[2] : pars[3];
318 return pars[0] * (std::atan (pars[1] * u) + c*u + pars[4]);
319}
320
321//====================================================================
322// EgammaSshapeCalibration::Builder::calc3
323//====================================================================
325 float u,
326 const CaloRec::Array<2>& coef) const
327{
328 const unsigned int NPAR = 4;
329 double pars[NPAR];
330
331 unsigned int degree = coef.size(1);
332 for (unsigned int i=0; i < NPAR; i++) {
333 CaloRec::Array<1> xcoef = coef[i];
334 double out = xcoef[0];
335 for (unsigned int j=1; j<degree; j++)
336 out = out * aeta + xcoef[j];
337 pars[i] = out;
338 }
339
340 double c = pars[2];
341 if (u < 0)
342 c = -c - 2*std::atan(pars[1]);
343 return pars[0] * (std::atan (pars[1] * u) + c*u + pars[3]);
344}
345
346//====================================================================
347// EgammaSshapeCalibration::Builder::calc4
348//====================================================================
350 float u,
351 const CaloRec::Array<2>& coef) const
352{
353 const unsigned int NPAR = 3;
354 double pars[NPAR];
355
356 unsigned int degree = coef.size(1);
357 for (unsigned int i=0; i < NPAR; i++) {
358 CaloRec::Array<1> xcoef = coef[i];
359 double out = xcoef[0];
360 for (unsigned int j=1; j<degree; j++)
361 out = out * aeta + xcoef[j];
362 pars[i] = out;
363 }
364
365 double b = std::max ((double)pars[1], 1e-5);
366 double atanb = std::atan(b);
367 double sq = std::sqrt (b/atanb - 1);
368 double den = (sq/b*atanb - std::atan(sq));
369 return pars[0]* ((- std::atan (b*u) + u*atanb) / den +
370 pars[2]*(1-std::abs(u)));
371}
372
373//====================================================================
374// EgammaSshapeCalibration::Builder::calc5
375//====================================================================
377 float /*u*/,
378 const CaloRec::Array<2>& coef) const
379{
380 const unsigned int NPAR = 1;
381 double pars[NPAR];
382
383 // poly_eval (aeta, coef, NPAR, pars);
384 unsigned int degree = coef.size(1);
385 for (unsigned int i=0; i < NPAR; i++) {
386 CaloRec::Array<1> xcoef = coef[i];
387 double out = xcoef[0];
388 for (unsigned int j=1; j<degree; j++)
389 out = out * aeta + xcoef[j];
390 pars[i] = out;
391 }
392
393 return pars[0];
394}
395
396//====================================================================
397// EgammaSshapeCalibration::Builder::calc10
398//====================================================================
400 float u,
401 const CaloRec::Array<2>& coef) const
402{
403 const unsigned int NPAR = 7;
404 double pars[NPAR];
405
406 unsigned int degree = coef.size(1);
407 for (unsigned int i=0; i < NPAR; i++) {
408 CaloRec::Array<1> xcoef = coef[i];
409 double out = xcoef[0];
410 for (unsigned int j=1; j<degree; j++)
411 out = out * aeta + xcoef[j];
412 pars[i] = out;
413 }
414
415 double c = pars[2];
416 if (u < 0)
417 c = -c - 2*std::atan(pars[1]);
418
419 double offs = pars[0] * (atan (pars[1] * u) + c*u + pars[3]) +
420 pars[4] * std::cos (u * pars[5] * M_PI + pars[6]);
421 if (u > 0.9 || u < -0.9) {
422 double xdiff = pars[4] * (std::cos (pars[5] * M_PI + pars[6]) -
423 std::cos (- pars[5] * M_PI + pars[6]));
424 if (u > 0.9)
425 offs -= (u-0.9)/0.1 * xdiff/2;
426 else
427 offs += (-0.9-u)/0.1 * xdiff/2;
428 }
429 return offs;
430}
431
432//====================================================================
433// EgammaSshapeCalibration::Builder::calc11
434//====================================================================
436 float u,
437 const CaloRec::Array<2>& coef) const
438{
439 const unsigned int NPAR = 8;
440 double pars[NPAR];
441
442 unsigned int degree = coef.size(1);
443 for (unsigned int i=0; i < NPAR; i++) {
444 CaloRec::Array<1> xcoef = coef[i];
445 double out = xcoef[0];
446 for (unsigned int j=1; j<degree; j++)
447 out = out * aeta + xcoef[j];
448 pars[i] = out;
449 }
450
451 double c = (u>=0) ? pars[2] : pars[3];
452 return pars[0] * (std::atan (pars[1] * u) + c*u + pars[4])
453 + pars[5] * std::cos (u * pars[6] * M_PI + pars[7]);
454}
455
#define M_PI
Scalar eta() const
pseudorapidity method
#define ATH_MSG_DEBUG(x)
Definition of CaloDetDescriptor.
#define CHECK(...)
Evaluate an expression and check for errors.
#define sq(x)
static const std::vector< std::string > regions
Helper, used to calculate the values of the energy interpolation table.
This class groups all DetDescr information related to a CaloCell.
const CaloDetDescriptor * descriptor() const
cell descriptor
bool is_lar_em_barrel() const
descriptor belongs to EM barrel
bool is_lar_em_endcap() const
descriptor belongs to EM end cap
Read-only multidimensional array.
unsigned int size(unsigned int dim=0) const
Return the size of the array along one dimension.
Read-write multidimensional array.
float calc4(float, float, const CaloRec::Array< 2 > &) const
float calc0(float, float, const CaloRec::Array< 2 > &) const
Builder(const EgammaSshapeCalibration &, double, double, int)
Constructor.
const EgammaSshapeCalibration & m_corr
float calc11(float, float, const CaloRec::Array< 2 > &) const
float calc10(float, float, const CaloRec::Array< 2 > &) const
virtual float calculate(int energy_ndx, bool &good) const
Calculate the correction for tabulated energy ENERGY_NDX.
float calc5(float, float, const CaloRec::Array< 2 > &) const
float calc3(float, float, const CaloRec::Array< 2 > &) const
Constant< CxxUtils::Array< 1 > > m_energies
Table of energies at which the correction was tabulated.
virtual void makeCorrection(xAOD::TrigEMCluster *, const void *) const override
Virtual function from IEgammaCalibration.
void docalc(int, const CaloClusterCorrectionCommon::TableBuilder &, const CxxUtils::Array< 1 > &, CxxUtils::WritableArray< 2 > &, int &) const
virtual StatusCode finalize() override
Finalization of the tool.
Constant< int > m_energy_degree
Degree of the polynomial interpolation in energy.
virtual StatusCode initialize() override
Initialization of the tool.
Constant< CxxUtils::Array< 2 > > m_regions
Calibration constant: table of regions.
float rawEta() const
get Raw Eta (no calibration)
void setEta(float)
set Eta (calibrated)
float eta() const
get Eta (calibrated)
float energy() const
get Energy (calibrated)
Polynomial interpolation in a table.
float interpolate(const CaloRec::Array< 2 > &a, float x, unsigned int degree, unsigned int ycol=1, const CaloRec::Array< 1 > &regions=CaloRec::Array< 1 >(), int n_points=-1, bool fixZero=false)
Polynomial interpolation in a table.
TrigEMCluster_v1 TrigEMCluster
Define the latest version of the trigger EM cluster class.