isce3 0.25.0
Loading...
Searching...
No Matches
LUT1d.icc
1#if !defined(ISCE_CORE_LUT1D_ICC)
2#error "LUT1d.icc is an implementation detail of class LUT1d"
3#endif
4
5#include <pyre/journal.h>
6
9template <typename T>
11eval(double x) const {
12
13 // Check if data are available; if not, return ref value
14 T value = _refValue;
15 if (!_haveData) {
16 return value;
17 }
18
19 // Check bounds to see if we need to perform linear extrapolation
20 const int n = _coords.size();
21 if (x < _coords[0]) {
22 if (_extrapolate) {
23 const double dx = _coords[0] - _coords[1];
24 const double dy = _values[0] - _values[1];
25 const double d = x - _coords[1];
26 T result = (dy / dx) * d + _values[1];
27 return result;
28 } else {
29 pyre::journal::error_t errorChannel("isce.core.LUT1d");
30 errorChannel
31 << pyre::journal::at(__HERE__)
32 << "Out of bounds evaluation for LUT1d."
33 << pyre::journal::newline
34 << pyre::journal::endl;
35 return 0;
36 }
37 } else if (x > _coords[n-1]) {
38 if (_extrapolate) {
39 const double dx = _coords[n-1] - _coords[n-2];
40 const double dy = _values[n-1] - _values[n-2];
41 const double d = x - _coords[n-2];
42 T result = (dy / dx) * d + _values[n-2];
43 return result;
44 } else {
45 pyre::journal::error_t errorChannel("isce.core.LUT1d");
46 errorChannel
47 << pyre::journal::at(__HERE__)
48 << "Out of bounds evaluation for LUT1d."
49 << pyre::journal::newline
50 << pyre::journal::endl;
51 return 0;
52 }
53 }
54
55 // Otherwise, proceed with interpolation
56 // Binary search to find leftmost coordinate
57 int low = 0;
58 int high = _coords.size();
59 while (low < high) {
60 const int midpoint = (low + high) / 2;
61 if (_coords[midpoint] < x) {
62 low = midpoint + 1;
63 } else {
64 high = midpoint;
65 }
66 }
67
68 // Check search convergence
69 if (low != high) {
70 pyre::journal::error_t errorChannel("isce.core.LUT1d");
71 errorChannel
72 << pyre::journal::at(__HERE__)
73 << "Binary search did not converge."
74 << pyre::journal::newline
75 << pyre::journal::endl;
76 return 0;
77 }
78
79 // Check if right on top of a coordinate
80 if (std::abs(_coords[high] - x) < 1.0e-12) {
81 return _values[high];
82 }
83
84 // The indices of the x bounds
85 const int j0 = high - 1;
86 const int j1 = high;
87
88 // Get coordinates at bounds
89 double x1 = _coords[j0];
90 double x2 = _coords[j1];
91
92 // Interpolate
93 T result = (x2 - x) / (x2 - x1) * _values[j0] + (x - x1) / (x2 - x1) * _values[j1];
94 return result;
95}
96
97template<typename T>
98typename isce3::core::LUT1d<T>::ArrayXt
99isce3::core::LUT1d<T>::eval(const Eigen::Ref<const Eigen::ArrayXd> & x) const {
100 auto out = ArrayXt(x.size());
101 #pragma omp parallel for
102 for(Eigen::Index n=0; n < x.size(); ++n)
103 out(n) = eval(x(n));
104 return out;
105}
106
107template <typename T>
109isce3::core::avgLUT2dToLUT1d(const isce3::core::LUT2d<T> & lut2d,
110 const int axis) {
111 if (axis != 0 && axis != 1) {
112 std::string error_msg = "ERROR axis not equal to 0 or 1";
113 throw isce3::except::InvalidArgument(ISCE_SRCINFO(), error_msg);
114 }
115
116 // Check if LUT2d has actual data; if not, just return LUT1d with reference value
117 if (!lut2d.haveData()) {
118 return isce3::core::LUT1d<T>(lut2d.refValue());
119 }
120
121 // Determine lut1d size and number of elements to sum
122 const auto lut1d_size = (axis == 0) ? lut2d.width() : lut2d.length();
123 const double n_to_sum_f = (axis == 0) ? static_cast<double>(lut2d.length()) :
124 static_cast<double>(lut2d.width());
125
126 // Get a reference to the LUT2d data
127 const Matrix<T> & data = lut2d.data();
128
129 // Compute sum and average
130 isce3::core::EArray2D<double> ea_values;
131 if (axis == 0)
132 // Sum along rows (x-direction)
133 ea_values = data.map().colwise().sum();
134 else
135 // Sum along columns (y-direction)
136 ea_values = data.map().rowwise().sum();
137 ea_values /= n_to_sum_f;
138
139 // Initialize working valarrays for computing mean along y-direction
140 std::valarray<double> values(0.0, lut1d_size);
141 std::copy(ea_values.data(), ea_values.data() + ea_values.size(), begin(values));
142
143 // Compute final coordinates and values
144 std::valarray<double> coords(lut1d_size);
145 for (size_t j = 0; j < lut1d_size; ++j) {
146 if (axis == 0)
147 coords[j] = lut2d.xStart() + j * lut2d.xSpacing();
148 else
149 coords[j] = lut2d.yStart() + j * lut2d.ySpacing();
150 }
151
152 return isce3::core::LUT1d<T>(coords, values, true);
153}
Data structure for a 2D row-major matrix.
Definition Matrix.h:23
Data structure to hold a 1D Lookup table.
Definition LUT1d.h:15
T eval(double x) const
Evaluate the LUT.
Definition LUT1d.icc:11
Data structure to store 2D Lookup table.
Definition LUT2d.h:20

Generated for ISCE3.0 by doxygen 1.13.2.