ATLAS Offline Software
Toggle main menu visibility
Loading...
Searching...
No Matches
Calorimeter
CaloClusterCorrection
src
interpolate.cxx
Go to the documentation of this file.
1
/*
2
Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3
*/
10
11
12
#include "
CaloClusterCorrection/interpolate.h
"
13
#include <vector>
14
#include <cassert>
15
#include <cmath>
16
#include <algorithm>
17
18
namespace
{
19
20
21
// Test to see if two numbers are significantly different.
22
bool
is_different (
float
a
,
float
b)
23
{
24
float
den = std::abs (
a
) + std::abs (b);
25
if
(den == 0)
return
false
;
26
return
std::abs ((
a
-b)/den) > 1
e
-6;
27
}
28
29
30
// Compare the first column of an array with an element.
31
struct
xcompare
32
{
33
bool
operator()
(
const
CaloRec::Array<1>&
a
,
CaloRec::Arrayelt
b)
34
{
35
return
a
[0] <
b
;
36
}
37
};
38
39
40
}
// anonymous namespace.
41
42
43
namespace
CaloClusterCorr
{
44
45
74
float
interpolate
(
const
CaloRec::Array<2>
&
a
,
75
float
x
,
76
unsigned
int
degree,
77
unsigned
int
ycol
/*= 1*/
,
78
const
CaloRec::Array<1>
&
regions
/*= CaloRec::Array<1>()*/
,
79
int
n_points
/*= -1*/
,
80
bool
fixZero
/*= false*/
)
81
{
82
const
int
xcol = 0;
83
84
// Check arguments.
85
if
(n_points < 0)
86
n_points =
static_cast<
int
>
(
a
.size());
87
if
(n_points < 2 || degree < 1) {
88
std::abort();
89
}
90
degree = std::min (degree,
static_cast<
unsigned
int
>
(n_points) - 1);
91
92
// Find subscripts of the input value in the input arrays.
93
unsigned
int
ix = std::lower_bound (
a
.begin(),
a
.begin()+n_points,
x
,
94
xcompare()) -
95
a
.begin();
96
unsigned
int
ir
= std::lower_bound (
regions
.begin(),
regions
.end(),
x
) -
97
regions
.begin();
98
99
// Number of points to try for.
100
// Either degree+1 or degree+2, whichever is even,
101
// to give the same number of points on each side.
102
// If we run up against an edge or a boundary, we'll
103
// fall back to using just degree+1 points (or fewer if we can't
104
// even get that many).
105
// If we end up using degree+2 points, we'll do two interpolations
106
// of degree degree and average them.
107
unsigned
int
npts = degree + 2 - (degree%2);
108
109
// If we run up against the edge of a region boundary,
110
// we'll want to add a pseudopoint right at the boundary
111
// (copying the point closest to the boundary) instead of the
112
// point farthest away from it.
113
bool
extralo =
false
;
114
bool
extrahi =
false
;
115
116
// Starting point index, not considering edges or boundaries.
117
int
ilo = ix - npts/2;
118
119
// Make sure this point is within the array range and has not
120
// crossed a region boundary.
121
if
(ilo < 0) {
122
ilo = 0;
123
npts = degree+1;
124
}
125
while
(ilo < n_points &&
126
ir
> 0 &&
a
[ilo][xcol] <
regions
[
ir
-1])
127
{
128
++ilo;
129
npts = degree+1;
130
extralo =
true
;
131
}
132
133
// Same deal for the right hand edge.
134
// ihi is one past the last point to use.
135
bool
himoved =
false
;
136
int
ihi = ilo + npts;
137
if
(ihi > n_points) {
138
ihi = n_points;
139
npts = degree+1;
140
himoved =
true
;
141
}
142
while
(ihi > 0 &&
ir
<
regions
.size() &&
a
[ihi-1][xcol] >=
regions
[
ir
]) {
143
--ihi;
144
npts = degree+1;
145
himoved =
true
;
146
extrahi =
true
;
147
}
148
149
// The adjustment due to ihi may have moved the low point of the range
150
// back over a boundary. If so, we lose points from the fit.
151
bool
lomoved =
false
;
152
ilo = ihi - npts;
153
if
(ilo < 0) {
154
ilo = 0;
155
lomoved =
true
;
156
}
157
while
(ilo < n_points &&
158
ir
> 0 &&
a
[ilo][xcol] <
regions
[
ir
-1])
159
{
160
++ilo;
161
extralo =
true
;
162
lomoved =
true
;
163
}
164
165
// Copy the points we're going to use to arrays t and d.
166
// t gets the x coordinates, d gets the y coordinates.
167
// Note that the order doesn't matter.
168
// Reserve two extra points in case we end up adding some.
169
assert(ihi >= ilo);
170
npts = ihi - ilo;
171
std::vector<float> t;
172
//coverity[INTEGER_OVERFLOW]
173
t.reserve (npts+2);
174
std::vector<float> d;
175
d.reserve (npts+2);
176
177
// Add the pseudopoints, if needed, removing a point from the other end.
178
// Be careful not to duplicate a point if there's already one
179
// right at the boundary.
180
if
(extralo && is_different (
a
[ilo][xcol],
regions
[
ir
-1])) {
181
if
(!himoved)
182
--ihi;
183
else
184
++npts;
185
t.push_back (
regions
[
ir
-1]);
186
d.push_back (
a
[ilo][ycol]);
187
}
188
if
(extrahi && is_different (
a
[ihi-1][xcol],
regions
[
ir
])) {
189
if
(!lomoved)
190
++ilo;
191
else
192
++npts;
193
t.push_back (
regions
[
ir
]);
194
d.push_back (
a
[ihi-1][ycol]);
195
}
196
197
// Add the rest if the points.
198
for
(; ilo < ihi; ++ilo) {
199
t.push_back (
a
[ilo][xcol]);
200
d.push_back (
a
[ilo][ycol]);
201
}
202
203
// Now figure out the interpolation degree we're really going to use.
204
assert (t.size() == npts);
205
assert (d.size() == npts);
206
//coverity[INTEGER_OVERFLOW]
207
degree = std::min (degree, npts-1);
208
209
// Option to remove zeros in the interpolation table, by averaging
210
// adjacent points. Used to handle a couple bad points in the rfac-v5
211
// table.
212
if
(fixZero) {
213
for
(
size_t
i = 1; i < npts-1; i++) {
214
if
(d[i] == 0) {
215
//coverity[INTEGER_OVERFLOW]
216
d[i] = (d[i-1] + d[i+1])/2;
217
}
218
}
219
}
220
221
// True if we're averaging together two interpolations
222
// (to get a symmetric range).
223
bool
extra = npts != degree+1;
224
225
// If we're averaging two interpolations, we need to be sure the
226
// two extreme points are at the end of the table.
227
// (If extra is true, extrahi and extralo must be false.)
228
if
(extra) {
229
//coverity[INTEGER_OVERFLOW]
230
std::swap
(t[0], t[npts-2]);
231
std::swap
(d[0], d[npts-2]);
232
}
233
234
// Here we start the actual interpolation.
235
// Replace d by the leading diagonal of a divided-difference table,
236
// supplemented by an extra line if extra is true.
237
for
(
unsigned
int
l=0; l<degree; l++) {
238
if
(extra)
239
d[degree+1] = (d[degree+1]-d[degree-1])/(t[degree+1]-t[degree-1-l]);
240
for
(
unsigned
int
i = degree; i > l; --i)
241
d[i] = (d[i]-d[i-1])/(t[i]-t[i-1-l]);
242
}
243
244
// Evaluate the Newton interpolation formula at x, averaging
245
// two values of the last difference if extra is true.
246
float
sum = d[degree];
247
if
(extra)
248
sum = 0.5*(sum+d[degree+1]);
249
for
(
int
j = degree-1; j >= 0; --j)
250
sum = d[j] + (
x
- t[j]) * sum;
251
252
return
sum;
253
}
254
255
256
}
// namespace CaloClusterCorrection
257
a
static Double_t a
Definition
LArPhysWaveHECTool.cxx:38
regions
static const std::vector< std::string > regions
Definition
MuonTriggerSFFilesTest.cxx:21
operator()
void operator()(T1)
x
#define x
CxxUtils::Array
Read-only multidimensional array.
Definition
Control/CxxUtils/CxxUtils/Array.h:135
ir
int ir
counter of the current depth
Definition
fastadd.cxx:49
interpolate.h
Polynomial interpolation in a table.
AllowedVariables::e
e
Definition
AsgElectronSelectorTool.cxx:37
CaloClusterCorr
Definition
CaloClusterCorrectionCommon.h:22
CaloClusterCorr::interpolate
float interpolate(const CaloRec::Array< 2 > &a, float x, unsigned int degree, unsigned int ycol=1, const CaloRec::Array< 1 > ®ions=CaloRec::Array< 1 >(), int n_points=-1, bool fixZero=false)
Polynomial interpolation in a table.
Definition
interpolate.cxx:74
CaloRec::Arrayelt
float Arrayelt
The type of an element of an Array.
Definition
Control/CxxUtils/CxxUtils/Arrayrep.h:26
plotBeamSpotMon.b
b
Definition
plotBeamSpotMon.py:76
std::swap
void swap(ElementLinkVector< DOBJ > &lhs, ElementLinkVector< DOBJ > &rhs)
Definition
AthLinks/ElementLinkVector.h:484
Generated on
for ATLAS Offline Software by
1.17.0