ATLAS Offline Software
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 
14 float 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 //___________________________________________________________________________
plotting.yearwise_efficiency.xval
float xval
Definition: yearwise_efficiency.py:42
WritePulseShapeToCool.ylo
ylo
Definition: WritePulseShapeToCool.py:134
TRT_PAI_utils.h
TRT_PAI_utils::calculate_interpolation
float calculate_interpolation(const float &xval, const float &x1, const float &x2, const float &y1, const float &y2)
Definition: TRT_PAI_utils.h:26
Amg::distance
float distance(const Amg::Vector3D &p1, const Amg::Vector3D &p2)
calculates the distance between two point in 3D space
Definition: GeoPrimitivesHelpers.h:54
TRT_PAI_utils::Interpolate
float Interpolate(const float &xval, const std::vector< float > &xtabulated, const std::vector< float > &ytabulated)
Interpolation function.
Definition: TRT_PAI_utils.cxx:14