ATLAS Offline Software
Loading...
Searching...
No Matches
TRT_PAI_utils.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include "TRT_PAI_utils.h"
6
7#include <algorithm>
8#include <cmath>
9#include <iostream>
10#include <limits>
11#include <vector>
12//___________________________________________________________________________
13
14float TRT_PAI_utils::Interpolate(const float& xval,
15 const std::vector<float>& xtabulated,
16 const std::vector<float>& ytabulated) {
17 //
18 // Interpolate the tabulated x and y values and return the yvalue
19 // that is interpolated from xval.
20 // If xval is outside the tabulated x values, returns 0.;
21
22#ifndef NDEBUG
23
24 if ( xtabulated.size() != ytabulated.size() ) {
25 std::cerr << "TRT_PAI_Process::TRT_PAI_utils::Interpolate:";
26 std::cerr << " ERROR - tabulated arrays must be of similar size"
27 << std::endl;
28 std::cerr << "xsize= " << xtabulated.size()
29 << " ysize= " << ytabulated.size()
30 << std::endl;
31
32 return 0;
33 }
34 if ( xtabulated.empty() ) {
35 std::cerr << "TRT_PAI_Process::TRT_PAI_utils::Interpolate:"
36 << "ERROR - tabulated arrays are empty"
37 << std::endl;
38 return 0;
39 }
40
41 // Maybe also test the assumption that they are already sorted here??
42
43#endif
44
45 // A rather special case:
46 if ( xtabulated.size()==1 ) {
47 return ytabulated.at(1); //FIXME - surely this will fail if ytabulated.size()==1??
48 }
49 // For performance reasons, we only get the beginnings and endings out once:
50 const std::vector<float>::const_iterator xBeginIter(xtabulated.begin());
51 const std::vector<float>::const_iterator xEndIter(xtabulated.end());
52
53 const std::vector<float>::const_iterator xLowerBoundIter(lower_bound(xBeginIter, xEndIter, xval));
54 // xLowerBoundIter is now the first item that does not come before xval.
55 //
56 // This means that:
57 // - If one of the xtabulated values equals to xval, xLowerBoundIter points to that value
58 // - Otherwise, xLowerBoundIter points to the next tabulated value - or the last value.
59
60 //Y|
61 // | E
62 // | +
63 // | D
64 // | +
65 // |
66 // | +
67 // |
68 // | +
69 // | C
70 // | +
71 // |
72 // | +
73 // | B
74 // | +
75 // | A
76 // |
77 // |__________________________________
78 // X
79 // '+' represent entries in xtabulated/ytabulated vectors.
80 // Case (A) xval < *(xBeginIter)
81 // xLowerBoundIter==xBeginIter
82 // ==> Special Case: Use xBeginIter and xBeginIter+1
83 // Cases (B), (C) & (D)
84 // Both xLowerBoundIter-1 and xLowerBoundIter are valid iterators
85 // ==> Normal Case: Use xLowerBoundIter-1 and xLowerBoundIter
86 // Case (E) xval > *(xEndIter-1)
87 // xLowerBoundIter==xEndIter
88 // ==> Special Case: xEndIter-2 and xEndIter-1
89
90 if ( xLowerBoundIter==xEndIter ) {
91 //Note: this xLowerBoundIter==xEndIter check can cause endless amounts of pain if left out!
92 // Interpolation/extrapolation determined by the last two points.
93 const std::vector<float>::const_iterator yEndIter(ytabulated.end());
94 return TRT_PAI_utils::calculate_interpolation(xval, *(xEndIter-2), *(xEndIter-1), *(yEndIter-2), *(yEndIter-1));
95 }
96
97 if ( ((*xLowerBoundIter)-xval)<std::numeric_limits<float>::epsilon() ) {
98 //Should never check for exact equality in floats only that they are the same within precision.
99 //We lie exactly on a grid point, and must return the corresponding y value
100 std::vector<float>::const_iterator yIter(ytabulated.begin());
101 std::advance(yIter, std::distance(xBeginIter, xLowerBoundIter));
102 return *yIter;
103 }
104
105 // We want to interpolate normally, but if xval falls outside the
106 // tabulated range, we will extrapolate the tabulation by the line
107 // connecting the last two points in either end:
108
109 if (xLowerBoundIter==xBeginIter) {
110 // Interpolation/extrapolation determined by the first two points.
111 const std::vector<float>::const_iterator yBeginIter(ytabulated.begin());
112 return TRT_PAI_utils::calculate_interpolation(xval, *xBeginIter, *(xBeginIter+1), *yBeginIter, *(yBeginIter+1));
113 }
114
115 // We are comfortably inside the array:
116 std::vector<float>::const_iterator ylo(ytabulated.begin());
117 std::advance(ylo, std::distance(xBeginIter, xLowerBoundIter));
118 return TRT_PAI_utils::calculate_interpolation(xval, *(xLowerBoundIter-1), *xLowerBoundIter, *(ylo-1), *ylo);
119}
120
121//___________________________________________________________________________
float calculate_interpolation(const float &xval, const float &x1, const float &x2, const float &y1, const float &y2)
float Interpolate(const float &xval, const std::vector< float > &xtabulated, const std::vector< float > &ytabulated)
Interpolation function.