NASA Logo
Ocean Color Science Software

ocssw V2022
Interpolation.hpp
Go to the documentation of this file.
1 #ifndef INTERP_HPP
2 #define INTERP_HPP
3 
4 #include <boost/date_time/posix_time/posix_time.hpp>
5 #include <cmath>
6 #include <string>
7 #include <netcdf>
8 #include "focs/Log.hpp"
9 #include "genutils.h"
10 
11 namespace tmgrn {
12 const boost::posix_time::ptime epoch(boost::gregorian::date(1970, 1, 1));
13 
15 
17 
18 namespace bt = boost::posix_time;
19 const std::locale formats[] = {
20  std::locale(std::locale::classic(), new bt::time_input_facet("%Y-%m-%dT%H:%M:%S")),
21  std::locale(std::locale::classic(), new bt::time_input_facet("%Y/%m/%d %H:%M:%S")),
22  std::locale(std::locale::classic(), new bt::time_input_facet("%d.%m.%Y %H:%M:%S")),
23  std::locale(std::locale::classic(), new bt::time_input_facet("%Y-%m-%dT%H:%M:%SZ")),
24  std::locale(std::locale::classic(), new bt::time_input_facet("minutes since %Y-%m-%d %H:%M:%S"))
25  };
26 std::time_t pt_to_time_t(const bt::ptime &pt);
27 
28 double seconds_from_epoch(const std::string &s);
29 } // namespace tmgrn
30 
31 namespace interp {
32 
33 typedef double (*interpolation_method2D)(double *x, double *y, size_t n, size_t ix, size_t iy, double *lut,
34  double x0, double y0);
35 
36 // template<typename T>
37 // using TouchCallBack = void (*)(float*, const double&, std::vector<T >);
38 // needs to be replaced with a general template function for N-dimensions
39 constexpr double bad_float = BAD_FLT;
40 double bilinear2D(double *x, double *y, size_t n, size_t ix, size_t iy, double *lut, double x0, double y0);
41 
42 const std::map<std::string, interpolation_method2D> methods = {{"bilinear", &bilinear2D}};
43 
44 class Interpolator {
45  public:
46  Interpolator() = default;
47 };
48 
49 template <class T>
51  private:
52  std::vector<T> *interpolators;
53  std::vector<double> times;
54  std::vector<double> weights;
55  size_t first{}, second{};
56 
57  public:
58  TimeInterpolator() = default;
59 
60  TimeInterpolator(std::vector<T> &interpolators, std::vector<double> &times, double current_time)
61  : times(times) {
62  this->interpolators = &interpolators;
63  if (times.size() != interpolators.size()) {
64  EXIT_LOG(std::cerr << "--Error--: size of the time vector and interpolatros vector are different. ")
65  }
66  for (double &t : times) {
67  weights.push_back(std::abs(1.0 / (t - current_time)));
68  }
69  first = 0;
70  second = times.size() - 1;
71  }
72  template <typename... Args>
73  double operator()(Args... args) {
74  return (interpolators->operator[](first)(args...) * weights[first] +
75  interpolators->operator[](second)(args...) * weights[second]) /
76  (weights[first] + weights[second]);
77  }
78 };
79 
80 // needs to be replaced with a general template class for N-dimensions
82  private:
83  double delta_x;
84  double delta_y;
85  double start_x;
86  double start_y;
87  std::vector<double> x_grid;
88  std::vector<double> y_grid;
89  __attribute__((unused)) double end_x;
90  __attribute__((unused)) double end_y;
91  size_t nx;
92  size_t ny;
93  std::vector<double> lut_data;
94  netCDF::NcVar *nc_lut;
96 
97  public:
99 
100  template <typename T, typename U>
101  RegularGridInterpolator2D(T *lut, U *x, U *y, size_t nx, size_t ny,
102  const std::string &methodstr = "bilinear")
103  : nx(nx), ny(ny) {
104  if constexpr (std::is_arithmetic_v<T> || std::is_arithmetic_v<std::decay<T>>) {
105  lut_data.resize(nx * ny);
106  std::transform(lut, lut + lut_data.size(), lut_data.data(),
107  [](T var) { return static_cast<double>(var); });
108  } else if constexpr (std::is_same_v<std::decay<T>, netCDF::NcVar> ||
109  std::is_same_v<T, netCDF::NcVar>) {
110  nc_lut = lut; // to be fully implemented, reading directly from netcdf for binning?
111  } else {
112  EXIT_LOG(std::cerr << "--Error--: passed type for the luts is not supported. Exiting.")
113  }
114  x_grid.resize(nx);
115  y_grid.resize(ny);
116  std::transform(x, x + x_grid.size(), x_grid.begin(), [](U var) { return static_cast<double>(var); });
117  std::transform(y, y + y_grid.size(), y_grid.begin(), [](U var) { return static_cast<double>(var); });
118  delta_x = static_cast<double>((x[nx - 1] - x[0]) / (nx - 1));
119  delta_y = static_cast<double>((y[ny - 1] - y[0]) / (ny - 1));
120  start_x = x[0];
121  start_y = y[0];
122  end_x = x[nx - 1];
123  end_y = y[ny - 1];
124  method = methods.at(methodstr);
125  }
126 
127  double operator()(double x, double y);
128 };
129 template <typename T>
130 size_t search(T *arr, size_t s, size_t e, T val, size_t *i_s, size_t *i_e) {
131  const bool acsending = arr[s] < arr[e];
132  if (acsending) {
133  if (val >= arr[e]) {
134  *i_s = e;
135  *i_e = e;
136  return e;
137  }
138  if (val <= arr[s]) {
139  *i_s = s;
140  *i_e = s;
141  return s;
142  }
143  } else {
144  if (val <= arr[e]) {
145  *i_s = e;
146  *i_e = e;
147  return e;
148  }
149  if (val >= arr[s]) {
150  *i_s = s;
151  *i_e = s;
152  return s;
153  }
154  }
155  while (e - s > 1) {
156  size_t m = (s + e) / 2; // compute median
157  if (acsending) {
158  if (arr[m] <= val) {
159  s = m;
160  } else {
161  e = m;
162  }
163  } else {
164  if (arr[m] <= val) {
165  e = m;
166  } else {
167  s = m;
168  }
169  }
170  }
171  {
172  *i_s = s;
173  *i_e = s + 1;
174  }
175  return s;
176 }
177 
178 template <typename T, typename U, size_t N>
179 class Interp {
180  private:
181  std::array<size_t, N> dimensions;
182  std::array<size_t, N> point;
183  std::array<size_t, N> point_s;
184  std::array<size_t, N> point_e;
185  std::array<size_t, N> pointer_shifts;
186  T *lut;
187  std::vector<U*> grid;
188 
189  public:
190  Interp() = default;
191 
192  template <typename... Args>
193  Interp(T *lut,std::vector<U*> & grid, Args &&...dims) : lut(lut), grid(grid) {
194  if constexpr (sizeof...(Args) != N) {
195  exit(EXIT_FAILURE);
196  }
197  set_dimensions(dims...);
198  set_shifts<N>();
199  }
200 
201  template <typename Arg, typename... Args>
202  void set_dimensions(Arg &&dim, Args &&...dims) {
203  constexpr size_t index = N - sizeof...(Args) - 1;
204  dimensions[index] = static_cast<size_t>(dim);
205  if constexpr (index != N - 1)
206  set_dimensions(dims...);
207  }
208 
209  template <typename Arg, typename... Args>
210  void get_point(Arg &&val, Args &&...vals) {
211  constexpr size_t index = N - sizeof...(Args) - 1;
212  point[index] = search(grid[index], 0, dimensions[index] - 1, val, &point_s[index], &point_e[index]);
213  if constexpr (index != N - 1)
214  get_point(vals...);
215  }
216 
217  template <typename Arg, typename... Args>
218  T get_value(T *lut_ptr, Arg &&val, Args &&...vals) {
219  constexpr size_t index = N - sizeof...(Args) - 1;
220  U w1 = val - grid[index][point_s[index]];
221  U w2 = w1;
222  if (point_s[index] != point_e[index])
223  w2 = grid[index][point_e[index]] - val;
224  T u1, u2;
225  if constexpr (sizeof...(Args) == 0) {
226  u1 = lut_ptr[point_s[index]];
227  if (point_s[index] != point_e[index])
228  u2 = lut_ptr[point_e[index]];
229  else
230  u2 = u1;
231 
232  } else {
233  u1 = get_value(lut_ptr + pointer_shifts[index] * point_s[index], vals...);
234  if (point_s[index] != point_e[index])
235  u2 = get_value(lut_ptr + pointer_shifts[index] * point_e[index], vals...);
236  else
237  u2 = u1;
238  }
239  U inw1, inw2;
240  inw1 = 1.0 / w1;
241  inw2 = 1.0 / w2;
242  if (w1 == 0) {
243  inw1 = 1.0;
244  inw2 = 0;
245  } else if (w2 == 0) {
246  inw1 = 0;
247  inw2 = 1.0;
248  }
249 
250  return (inw1 * u1 + inw2 * u2) / (inw1 + inw2);
251  }
252 
253  template <typename... Args>
254  T operator()(Args &&...vals) {
255  if constexpr (sizeof...(Args) != N) {
256  exit(EXIT_FAILURE);
257  }
258  get_point(vals...);
259  return get_value(lut, vals...);
260  }
261 
262  template <size_t K>
263  void set_shifts() {
264  if constexpr (N - K == 0) {
265  pointer_shifts[K - 1] = 1;
266  } else {
267  pointer_shifts[K - 1] = pointer_shifts[K] * dimensions[K];
268  }
269  if constexpr (K > 0)
270  set_shifts<K - 1>();
271  }
272 
273  template <typename... Args>
274  friend Interp interp(T *lut,std::vector<U*> & grid, Args &&...dims);
275 };
276 
277 template <typename T, typename U, typename... Args, size_t K = sizeof...(Args)>
278 Interp<T, U, K> interp(T *lut,std::vector<U*> & grid, Args &&...dims) {
279  return Interp<T, U, K>(lut, grid, dims...);
280 }
281 
282 } // namespace interp
283 
284 #endif
an array had not been initialized Several spelling and grammar corrections were which is read from the appropriate MCF the above metadata values were hard coded A problem calculating the average background DN for SWIR bands when the moon is in the space view port was corrected The new algorithm used to calculate the average background DN for all reflective bands when the moon is in the space view port is now the same as the algorithm employed by the thermal bands For non SWIR changes in the averages are typically less than Also for non SWIR the black body DNs remain a backup in case the SV DNs are not available For SWIR the changes in computed averages were larger because the old which used the black body suffered from contamination by the micron leak As a consequence of the if SV DNs are not available for the SWIR the EV pixels will not be the granule time is used to identify the appropriate tables within the set given for one LUT the first two or last two tables respectively will be used for the interpolation If there is only one LUT in the set of it will be treated as a constant LUT The manner in which Earth View data is checked for saturation was changed Previously the raw Earth View DNs and Space View DNs were checked against the lookup table values contained in the table dn_sat The change made is to check the raw Earth and Space View DNs to be sure they are less than the maximum saturation value and to check the Space View subtracted Earth View dns against a set of values contained in the new lookup table dn_sat_ev The metadata configuration and ASSOCIATEDINSTRUMENTSHORTNAME from the MOD02HKM product The same metatdata with extensions and were removed from the MOD021KM and MOD02OBC products ASSOCIATEDSENSORSHORTNAME was set to MODIS in all products These changes are reflected in new File Specification which users may consult for exact the pow functions were eliminated in Emissive_Cal and Emissive bands replaced by more efficient code Other calculations throughout the code were also made more efficient Aside from a few round off there was no difference to the product The CPU time decreased by about for a day case and for a night case A minor bug in calculating the uncertainty index for emissive bands was corrected The frame index(0-based) was previously being used the frame number(1-based) should have been used. There were only a few minor changes to the uncertainty index(maximum of 1 digit). 3. Some inefficient arrays(Sigma_RVS_norm_sq) were eliminated and some code lines in Preprocess_L1A_Data were moved into Process_OBCEng_Emiss. There were no changes to the product. Required RAM was reduced by 20 MB. Now
data_t t[NROOTS+1]
Definition: decode_rs.h:77
const std::map< std::string, interpolation_method2D > methods
Interp(T *lut, std::vector< U * > &grid, Args &&...dims)
double bilinear2D(double *x, double *y, size_t n, size_t ix, size_t iy, double *lut, double x0, double y0)
std::time_t pt_to_time_t(const bt::ptime &pt)
int N
Definition: Usds.c:60
double seconds_from_epoch(const std::string &s)
const boost::posix_time::ptime epoch(boost::gregorian::date(1970, 1, 1))
friend Interp interp(T *lut, std::vector< U * > &grid, Args &&...dims)
double(* interpolation_method2D)(double *x, double *y, size_t n, size_t ix, size_t iy, double *lut, double x0, double y0)
void get_point(Arg &&val, Args &&...vals)
@ string
#define EXIT_LOG(...)
Definition: Log.hpp:26
Interp()=default
Interp< T, U, K > interp(T *lut, std::vector< U * > &grid, Args &&...dims)
RegularGridInterpolator2D(T *lut, U *x, U *y, size_t nx, size_t ny, const std::string &methodstr="bilinear")
size_t search(T *arr, size_t s, size_t e, T val, size_t *i_s, size_t *i_e)
const std::locale formats[]
T operator()(Args &&...vals)
std::string & granule_end_time()
double operator()(Args... args)
std::string & granule_start_time()
CGAL::Exact_predicates_inexact_constructions_kernel K
Definition: cgal_interp.cpp:12
integer, parameter double
constexpr double bad_float
TimeInterpolator(std::vector< T > &interpolators, std::vector< double > &times, double current_time)
#define BAD_FLT
Definition: jplaeriallib.h:19
data_t s[NROOTS]
Definition: decode_rs.h:75
void set_dimensions(Arg &&dim, Args &&...dims)
double operator()(double x, double y)
#define abs(a)
Definition: misc.h:90
T get_value(T *lut_ptr, Arg &&val, Args &&...vals)