bes  Updated for version 3.20.13
StareFunctions.h
1 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
2 // Access Protocol.
3 
4 // Copyright (c) 2019 OPeNDAP, Inc.
5 // Authors: Kodi Neumiller <kneumiller@opendap.org>
6 //
7 // This library is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU Lesser General Public
9 // License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 //
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // Lesser General Public License for more details.
16 //
17 // You should have received a copy of the GNU Lesser General Public
18 // License along with this library; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 //
21 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
22 
23 #include <string>
24 #include <utility>
25 
26 #include <STARE.h>
27 #include <hdf5.h>
28 
29 #include <libdap/BaseType.h>
30 #include <libdap/dods-datatypes.h>
31 
32 #include <libdap/ServerFunction.h>
33 
34 #define STARE_STORAGE_PATH_KEY "FUNCTIONS.stareStoragePath"
35 #define STARE_SIDECAR_SUFFIX_KEY "FUNCTIONS.stareSidecarSuffix"
36 
37 namespace libdap {
38 class BaseType;
39 class DDS;
40 class D4RValueList;
41 class DMR;
42 }
43 
44 namespace functions {
45 
46 // These default values can be overridden using BES keys.
47 // See DapFunctions.cc. jhrg 5/21/20
48 extern string stare_storage_path;
49 extern string stare_sidecar_suffix;
50 
51 bool target_in_dataset(const std::vector<STARE_ArrayIndexSpatialValue> &target_indices,
52  const std::vector<STARE_ArrayIndexSpatialValue> &data_stare_indices);
53 
54 unsigned int count(const std::vector<STARE_ArrayIndexSpatialValue> &target_indices,
55  const std::vector<STARE_ArrayIndexSpatialValue> &dataset_indices, bool all_target_matches = false);
56 
71 template <class T>
72 void stare_subset_array_helper(vector<T> &result_data, const vector<T> &src_data,
73  const vector<STARE_ArrayIndexSpatialValue> &target_indices,
74  const vector<STARE_ArrayIndexSpatialValue> &dataset_indices)
75 {
76  assert(dataset_indices.size() == src_data.size());
77  assert(dataset_indices.size() == result_data.size());
78 
79  auto r = result_data.begin();
80  auto s = src_data.begin();
81  for (const auto &i : dataset_indices) {
82  for (const auto &j : target_indices) {
83  if (cmpSpatial(i, j) != 0) { // != 0 --> i is in j OR j is in i
84  *r = *s;
85  break;
86  }
87  }
88  ++r; ++s;
89  }
90 }
91 
109 template<class T>
110 void build_masked_data(libdap::Array *dependent_var,
111  const vector<STARE_ArrayIndexSpatialValue> &dep_var_stare_indices,
112  const vector<STARE_ArrayIndexSpatialValue> &target_s_indices,
113  T mask_value,
114  unique_ptr<libdap::Array> &result)
115 {
116  vector<T> src_data(dependent_var->length());
117  dependent_var->read(); // TODO Do we need to call read() here? jhrg 6/16/20
118  dependent_var->value(src_data.data());
119 
120  //T mask_value = 0; // TODO This should use the value in mask_val_var. jhrg 6/16/20
121  vector<T> result_data(dependent_var->length(), mask_value);
122 
123  stare_subset_array_helper(result_data, src_data, target_s_indices, dep_var_stare_indices);
124 
125  result->set_value(result_data, result_data.size());
126 }
127 
130  std::vector<libdap::dods_int32> row_indices;
131  std::vector<libdap::dods_int32> col_indices;
132 
133  std::vector<STARE_ArrayIndexSpatialValue> stare_indices;
134  std::vector<STARE_ArrayIndexSpatialValue> target_indices;
135 
136  // Pass by value and use move
137  stare_matches(std::vector<libdap::dods_int32> row, std::vector<libdap::dods_int32> col,
138  std::vector<STARE_ArrayIndexSpatialValue> si, std::vector<STARE_ArrayIndexSpatialValue> ti)
139  : row_indices(std::move(row)), col_indices(std::move(col)), stare_indices(std::move(si)),
140  target_indices(std::move(ti)) {}
141 
142  stare_matches() = default;
143 
144  void add(libdap::dods_int32 row, libdap::dods_int32 col, STARE_ArrayIndexSpatialValue si, STARE_ArrayIndexSpatialValue ti) {
145  row_indices.push_back(row);
146  col_indices.push_back(col);
147  stare_indices.push_back(si);
148  target_indices.push_back(ti);
149  }
150 
151  friend std::ostream &operator<<(std::ostream &out, const stare_matches &m);
152 };
153 
154 unique_ptr<stare_matches> stare_subset_helper(const std::vector<STARE_ArrayIndexSpatialValue> &target_indices,
155  const std::vector<STARE_ArrayIndexSpatialValue> &dataset_indices,
156  size_t row, size_t cols);
157 
158 class StareIntersectionFunction : public libdap::ServerFunction {
159 public:
160  static libdap::BaseType *stare_intersection_dap4_function(libdap::D4RValueList *args, libdap::DMR &dmr);
161 
162  friend class StareFunctionsTest;
163 
165  setName("stare_intersection");
166  setDescriptionString(
167  "The stare_intersection: Returns 1 if the coverage of the current dataset includes any of the given STARE indices, 0 otherwise.");
168  setUsageString(
169  "stare_intersection(var, STARE index [, STARE index ...]) | stare_intersection(var, $UInt64(<size hint>:STARE index [, STARE index ...]))");
170  setRole("http://services.opendap.org/dap4/server-side-function/stare_intersection");
171  setDocUrl("http://docs.opendap.org/index.php/Server_Side_Processing_Functions#stare_intersection");
173  setVersion("0.3");
174  }
175 
176  ~StareIntersectionFunction() override = default;
177 };
178 
179 class StareCountFunction : public libdap::ServerFunction {
180 public:
181  static libdap::BaseType *stare_count_dap4_function(libdap::D4RValueList *args, libdap::DMR &dmr);
182 
183  friend class StareFunctionsTest;
184 
186  setName("stare_count");
187  setDescriptionString(
188  "The stare_count: Returns the number of the STARE indices that are included in the coverage of this dataset.");
189  setUsageString(
190  "stare_count(var, STARE index [, STARE index ...]) | stare_count(var, $UInt64(<size hint>:STARE index [, STARE index ...]))");
191  setRole("http://services.opendap.org/dap4/server-side-function/stare_count");
192  setDocUrl("http://docs.opendap.org/index.php/Server_Side_Processing_Functions#stare_count");
193  setFunction(stare_count_dap4_function);
194  setVersion("0.3");
195  }
196 
197  ~StareCountFunction() override = default;
198 };
199 
200 class StareSubsetFunction : public libdap::ServerFunction {
201 public:
202  static libdap::BaseType *stare_subset_dap4_function(libdap::D4RValueList *args, libdap::DMR &dmr);
203 
204  friend class StareFunctionsTest;
205 
207  setName("stare_subset");
208  setDescriptionString(
209  "The stare_subset: Returns the set of the STARE indices that are included in the coverage of this dataset.");
210  setUsageString("stare_subset(var, $UInt64(<size hint>:STARE index [, STARE index ...]))");
211  setRole("http://services.opendap.org/dap4/server-side-function/stare_subset");
212  setDocUrl("http://docs.opendap.org/index.php/Server_Side_Processing_Functions#stare_subset");
213  setFunction(stare_subset_dap4_function);
214  setVersion("0.3");
215  }
216 
217  ~StareSubsetFunction() override = default;
218 };
219 
220 class StareSubsetArrayFunction : public libdap::ServerFunction {
221 public:
222  static libdap::BaseType *stare_subset_array_dap4_function(libdap::D4RValueList *args, libdap::DMR &dmr);
223 
224  friend class StareFunctionsTest;
225 
227  setName("stare_subset_array");
228  setDescriptionString(
229  "The stare_subset: Returns a masked copy of 'var' for the subset given the set of STARE indices that are included in the coverage of this dataset.");
230  setUsageString("stare_subset_array(var, mask-val, $UInt64(<size hint>:STARE index [, STARE index ...]))");
231  setRole("http://services.opendap.org/dap4/server-side-function/stare_subset_array");
232  setDocUrl("http://docs.opendap.org/index.php/Server_Side_Processing_Functions#stare_subset_array");
233  setFunction(stare_subset_array_dap4_function);
234  setVersion("0.1");
235  }
236 
237  ~StareSubsetArrayFunction() override = default;
238 };
239 
243 struct point {
244  double lat;
245  double lon;
246  point() = default;
247  point(double lat_, double lon_) : lat(lat_), lon(lon_) {}
248 };
249 
250 STARE_SpatialIntervals stare_box_helper(const vector<point> &points, int resolution = 6);
251 STARE_SpatialIntervals stare_box_helper(const point &top_left, const point &bottom_right, int resolution = 6);
252 
253 class StareBoxFunction : public libdap::ServerFunction {
254 public:
255  static libdap::BaseType *stare_box_dap4_function(libdap::D4RValueList *args, libdap::DMR &dmr);
256 
257  friend class StareFunctionsTest;
258 
259  StareBoxFunction() {
260  setName("stare_box");
261  setDescriptionString(
262  "The stare_box() function: Returns a STARE cover for the region within the four lat/lon corner points.");
263  setUsageString("stare_box(tl_lat, tl_lon, br_lat, br_lon) or stare_box(p1_lat, p1_lon, ..., p4_lat, p4_lon)");
264  setRole("http://services.opendap.org/dap4/server-side-function/stare_box");
265  setDocUrl("http://docs.opendap.org/index.php/Server_Side_Processing_Functions#stare_box");
266  setFunction(stare_box_dap4_function);
267  setVersion("0.1");
268  }
269 
270  ~StareBoxFunction() override = default;
271 };
272 
273 } // functions namespace
static libdap::BaseType * stare_count_dap4_function(libdap::D4RValueList *args, libdap::DMR &dmr)
Count the number of STARE indices in the arg that overlap the indices of this dataset.
static libdap::BaseType * stare_intersection_dap4_function(libdap::D4RValueList *args, libdap::DMR &dmr)
Return true/false indicating that the given stare indices intersect the variables.
static libdap::BaseType * stare_subset_dap4_function(libdap::D4RValueList *args, libdap::DMR &dmr)
For the given target STARE indices, return the overlapping dataset X, Y, and STARE indices.
Hold the result from the subset helper function as a collection of vectors.
friend std::ostream & operator<<(std::ostream &out, const stare_matches &m)
Write a collection of STARE Matches to an ostream.