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