ATLAS Offline Software
Loading...
Searching...
No Matches
CaloSwEtaoff_v3.cxx
Go to the documentation of this file.
1// This file's extension implies that it's C, but it's really -*- C++ -*-.
2/*
3 Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
4*/
11
12
13#include "CaloSwEtaoff_v3.h"
15#include <cmath>
16#include <cassert>
17
18
40 xAOD::CaloCluster* cluster,
41 const CaloDetDescrElement* elt,
42 float eta,
43 float adj_eta,
44 float /*phi*/,
45 float /*adj_phi*/,
46 CaloSampling::CaloSample samp) const
47{
48 // Find u, the normalized displacement of the cluster within the cell.
49 // In the range -1...1, with 0 at the center.
50 float u = (eta - elt->eta()) / elt->deta() * 2;
51 if (elt->eta_raw() < 0)
52 u = -u;
53
54 // u can sometimes be outside of the prescribed range, due to DD bugs.
55 if (u > 1)
56 u = 1;
57 else if (u < -1)
58 u = -1;
59
60 const CxxUtils::Array<2> regions = m_regions (myctx);
61 assert (regions.size(1) == REG_ENTRIES);
62
63 // Look up the region for this correction. Give up if we're outsize
64 // the range of the table.
65 float adj_aeta = std::abs (adj_eta);
66 int region_ndx = find_region (regions, adj_aeta);
67 if (region_ndx < 0)
68 return;
69
70 const CxxUtils::Array<4> correction = m_correction (myctx);
71 const CxxUtils::Array<2> forms = m_forms (myctx);
72
73 // In a few regions, the fit was done using a cell size different
74 // from what we actually have. Need to recalculate u in this case.
75 if (std::abs (regions[region_ndx][REG_CELLSIZE] - elt->deta()) > 1e-3) {
76 float cellsize = regions[region_ndx][REG_CELLSIZE];
77 u = fmod (adj_aeta, cellsize) / cellsize * 2 - 1;
78 }
79
80 // Calculate the correction for each energy.
81 float offs = energy_interpolation (cluster->e(),
82 Builder (correction,
83 regions,
84 forms,
85 adj_aeta,
86 u,
87 region_ndx),
88 m_energies(myctx),
89 m_energy_degree(myctx));
90
91 // Apply the offset correction to the cluster.
92 if (adj_eta < 0)
93 offs = -offs;
94 cluster->setEta (samp, eta + offs);
95}
96
97
104 float aeta)
105{
106 // ??? Would a binary search be better here?
107 // The table shouldn't be very large, so I'll leave it like
108 // this for now.
109 unsigned int nreg = regions.size();
110 for (unsigned int i=0; i < nreg; i++) {
111 if (aeta >= regions[i][REG_LO] && aeta < regions[i][REG_HI])
112 return i;
113 }
114 return -1;
115}
116
117
131 const CxxUtils::Array<2>& forms,
132 float aeta,
133 float u,
134 int region_ndx)
135 : m_correction (correction),
137 m_forms (forms),
138 m_region_ndx (region_ndx),
139 m_aeta (aeta),
140 m_u (u),
141 m_form (regions[region_ndx][REG_FORM])
142{
143}
144
145
152float CaloSwEtaoff_v3::Builder::calculate (int energy_ndx, bool& good) const
153{
154 // Find the proper array of coefficients.
155 CaloRec::Array<2> coef = m_correction[energy_ndx][m_region_ndx];
156
157 // If we don't have coefficients for this energy/region, skip it.
158 if (coef[0].end()[-1] == 0) {
159 good = false;
160 return 0;
161 }
162
163 // Which functional form to use?
164 int form;
165 if (m_forms.size() != 0 && m_forms.size(1) != 0)
166 form = m_forms[m_region_ndx][energy_ndx];
167 else
168 form = m_form;
169
170 // Evaluate the correction!
171 good = true;
172 float ret = 0;
173
174 // Required just for case 13
175 float xlo=0 ;
176 float xhi=0 ;
177 unsigned int reg_n = m_regions.size();
178
179 switch (form) {
180 case 0:
181 ret = calc0 (m_aeta, m_u, coef);
182 break;
183 case 3:
184 ret = calc3 (m_aeta, m_u, coef);
185 break;
186 case 4:
187 ret = calc4 (m_aeta, m_u, coef);
188 break;
189 case 5:
190 ret = calc5 (m_aeta, m_u, coef);
191 break;
192 case 10:
193 ret = calc10 (m_aeta, m_u, coef);
194 break;
195 case 11:
196 ret = calc11 (m_aeta, m_u, coef);
197 break;
198 case 13:
199
200 for (unsigned int i=0; i < reg_n; i++) {
201 if (m_aeta >= m_regions[i][REG_LO] && m_aeta < m_regions[i][REG_HI])
202 {
203 xlo = m_regions[i][REG_LO] ;
204 xhi = m_regions[i][REG_HI] ;
205 }
206 }
207
208 ret = calc13 (m_aeta, m_u, coef, xlo, xhi);
209 break;
210 default:
211 abort();
212 }
213
214 // Protection against correction blowing up due to numerical
215 // problems in calculating the polynomial interpolation.
216 if (fabs(ret) > 0.025) {
217 ret = 0;
218 good = false;
219 }
220
221 return ret;
222}
223
224
225namespace {
226
227
235void poly_eval (float aeta,
236 const CaloRec::Array<2>& coef,
237 unsigned int npar,
238 double pars[])
239{
240 assert (npar <= coef.size(0));
241
242 // Take polynomial degree from the array size.
243 unsigned int degree = coef.size(1);
244
245 // Loop over parameters.
246 for (unsigned int i=0; i < npar; i++) {
247 // Coefficients for this parameter.
248 CaloRec::Array<1> xcoef = coef[i];
249
250 // Evaluate polynomial in @c aeta with coefficients @c xcoef.
251 double out = xcoef[0];
252 for (unsigned int j = 1; j < degree; j++)
253 out = out * aeta + xcoef[j];
254 pars[i] = out;
255 }
256}
257
258
259} // anonymous namespace
260
261
269 float u,
270 const CaloRec::Array<2>& coef)
271{
272 const unsigned int NPAR = 5;
273 double pars[NPAR];
274 poly_eval (aeta, coef, NPAR, pars);
275 double c = (u>=0) ? pars[2] : pars[3];
276 return pars[0] * (std::atan (pars[1] * u) + c*u + pars[4]);
277}
278
279
287 float u,
288 const CaloRec::Array<2>& coef)
289{
290 const unsigned int NPAR = 4;
291 double pars[NPAR];
292 poly_eval (aeta, coef, NPAR, pars);
293 double c = pars[2];
294 if (u < 0)
295 c = -c - 2*std::atan(pars[1]);
296 return pars[0] * (std::atan (pars[1] * u) + c*u + pars[3]);
297}
298
299
307 float u,
308 const CaloRec::Array<2>& coef)
309{
310 const unsigned int NPAR = 3;
311 double pars[NPAR];
312 poly_eval (aeta, coef, NPAR, pars);
313 double b = std::max ((double)pars[1], 1e-5);
314 double atanb = std::atan(b);
315 double sq = std::sqrt (b/atanb - 1);
316 double den = (sq/b*atanb - std::atan(sq));
317 return pars[0]* ((- std::atan (b*u) + u*atanb) / den +
318 pars[2]*(1-std::abs(u)));
319}
320
321
329 float /*u*/,
330 const CaloRec::Array<2>& coef)
331{
332 const unsigned int NPAR = 1;
333 double pars[NPAR];
334 poly_eval (aeta, coef, NPAR, pars);
335 return pars[0];
336}
337
338
346 float u,
347 const CaloRec::Array<2>& coef)
348{
349 const unsigned int NPAR = 7;
350 double pars[NPAR];
351 poly_eval (aeta, coef, NPAR, pars);
352 double c = pars[2];
353 if (u < 0)
354 c = -c - 2*std::atan(pars[1]);
355
356 double offs = pars[0] * (atan (pars[1] * u) + c*u + pars[3]) +
357 pars[4] * std::cos (u * pars[5] * M_PI + pars[6]);
358 if (u > 0.9 || u < -0.9) {
359 double xdiff = pars[4] * (std::cos (pars[5] * M_PI + pars[6]) -
360 std::cos (- pars[5] * M_PI + pars[6]));
361 if (u > 0.9)
362 offs -= (u-0.9)*(1./0.1) * xdiff/2;
363 else
364 offs += (-0.9-u)*(1./0.1) * xdiff/2;
365 }
366 return offs;
367}
368
369
377 float u,
378 const CaloRec::Array<2>& coef)
379{
380 const unsigned int NPAR = 8;
381 double pars[NPAR];
382 poly_eval (aeta, coef, NPAR, pars);
383 double c = (u>=0) ? pars[2] : pars[3];
384 return pars[0] * (std::atan (pars[1] * u) + c*u + pars[4])
385 + pars[5] * std::cos (u * pars[6] * M_PI + pars[7]);
386}
387
388
396 float /*u*/,
397 const CaloRec::Array<2>& coef,
398 float xlo,
399 float xhi)
400{
401 const unsigned int NPAR = 1;
402 double pars[NPAR];
403 float x = (aeta - xlo) / (xhi - xlo) ;
404 poly_eval (x, coef, NPAR, pars);
405 return pars[0];
406}
407
408
409/*
410from python code for writing calc 13
411
412# D3PD edit - udpated by Ewan since Scott only half implemented it
413# "Scaled Polynomial" fit function
414def _calc13 (aeta, u, ptab, m_xlo, m_xhi):
415 x = (aeta - m_xlo) / (m_xhi - m_xlo);
416 p = [_poly_eval (x, pp) for pp in ptab]
417 return p[0]
418*/
#define M_PI
Scalar eta() const
pseudorapidity method
Definition of CaloDetDescrManager.
EM calorimeter eta offset (S-shape) corrections, version 3.
#define sq(x)
static const std::vector< std::string > regions
#define x
static float energy_interpolation(float energy, const TableBuilder &builder, const CaloRec::Array< 1 > &energies, int energy_degree)
Many of the corrections use the same method for doing the final interpolation in energy.
This class groups all DetDescr information related to a CaloCell.
int m_form
The index of the functional form we're evaluating.
const CxxUtils::Array< 2 > & m_forms
Functional form per region.
static float calc10(float aeta, float u, const CaloRec::Array< 2 > &coef)
Evaluate the function Form 10.
static float calc0(float aeta, float u, const CaloRec::Array< 2 > &coef)
Evaluate the function Form 0.
float m_u
The fractional offset in the cell of this cluster.
Builder(const CxxUtils::Array< 4 > &correction, const CxxUtils::Array< 2 > &regions, const CxxUtils::Array< 2 > &forms, float aeta, float u, int region_ndx)
Constructor.
const CxxUtils::Array< 2 > & m_regions
Table of regions.
static float calc4(float aeta, float u, const CaloRec::Array< 2 > &coef)
Evaluate the function Form 4.
float m_aeta
The abs(eta) at which the correction is being evaluated (in cal-local coordinates).
static float calc11(float aeta, float u, const CaloRec::Array< 2 > &coef)
Evaluate the function Form 11.
static float calc3(float aeta, float u, const CaloRec::Array< 2 > &coef)
Evaluate the function Form 3.
int m_region_ndx
The index of the region in which we're evaluating the correction.
const CxxUtils::Array< 4 > & m_correction
virtual float calculate(int energy_ndx, bool &good) const
Calculate the correction for tabulated energy ENERGY_NDX.
static float calc13(float aeta, float u, const CaloRec::Array< 2 > &coef, float xlo, float xhi)
Evaluate the function Form 13.
static float calc5(float aeta, float u, const CaloRec::Array< 2 > &coef)
Evaluate the function Form 5.
static int find_region(const CxxUtils::Array< 2 > &regions, float aeta)
Find the index of the region containing a given value.
virtual void makeTheCorrection(const Context &myctx, xAOD::CaloCluster *cluster, const CaloDetDescrElement *elt, float eta, float adj_eta, float phi, float adj_phi, CaloSampling::CaloSample samp) const override
Virtual function for the correction-specific code.
Constant< CxxUtils::Array< 4 > > m_correction
Calibration constant: tabulated arrays of function parameters.
Constant< CxxUtils::Array< 2 > > m_forms
Calibration constant: Functional form to use per region per energy.
Constant< CxxUtils::Array< 2 > > m_regions
Calibration constant: table of regions.
Constant< CxxUtils::Array< 1 > > m_energies
Calibration constant: table of energies at which the correction was tabulated.
friend class Builder
Constant< int > m_energy_degree
Calibration constant: degree of the polynomial interpolation in energy.
Read-only multidimensional array.
virtual double e() const
The total energy of the particle.
bool setEta(const CaloSample sampling, const float eta)
Set in a given sampling. Returns false if the sample isn't part of the cluster.
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.