33#include <libdap/BaseType.h>
34#include <libdap/Float64.h>
35#include <libdap/Str.h>
36#include <libdap/Array.h>
37#include <libdap/Grid.h>
38#include <libdap/Structure.h>
40#include <libdap/DMR.h>
41#include <libdap/D4RValue.h>
43#include <libdap/Byte.h>
44#include <libdap/Int16.h>
45#include <libdap/Int32.h>
46#include <libdap/UInt16.h>
47#include <libdap/UInt32.h>
48#include <libdap/Float32.h>
49#include <libdap/UInt64.h>
50#include <libdap/Int64.h>
54#include "BESInternalError.h"
55#include "BESSyntaxUserError.h"
57#include "StareFunctions.h"
60#define STARE_FUNC "stare"
71string stare_storage_path;
74string stare_sidecar_suffix =
"_stare.nc";
87ostream & operator << (ostream &out,
const stare_matches &m)
89 assert(m.stare_indices.size() == m.row_indices.size()
90 && m.row_indices.size() == m.col_indices.size());
92 auto ti = m.target_indices.begin();
93 auto si = m.stare_indices.begin();
94 auto xi = m.row_indices.begin();
95 auto yi = m.col_indices.begin();
97 while (si != m.stare_indices.end()) {
98 out <<
"Target: " << *ti++ <<
", Dataset Index: " << *si++ <<
", coord: row: " << *xi++ <<
", col: " << *yi++ << endl;
105extract_stare_index_array(Array *var, vector<STARE_ArrayIndexSpatialValue> &values)
107 if (var->var()->type() != dods_uint64_c)
108 throw BESSyntaxUserError(
"STARE server function passed an invalid Index array (" + var->name()
109 +
" is type: " + var->var()->type_name() +
").", __FILE__, __LINE__);
111 values.resize(var->length());
112 var->value((dods_uint64*)values.data());
137target_in_dataset(
const vector<STARE_ArrayIndexSpatialValue> &target_indices,
138 const vector<STARE_ArrayIndexSpatialValue> &data_stare_indices) {
143 for (
const STARE_ArrayIndexSpatialValue &i : target_indices) {
144 for (
const STARE_ArrayIndexSpatialValue &j :data_stare_indices ) {
148 int result = cmpSpatial(i, j);
158 auto r = SpatialRange(data_stare_indices);
159 cerr <<
"built spatial range" << endl;
160 for (
const dods_uint64 &sid : target_indices) {
161 if( r.contains(sid) ) {
return true; }
184count(
const vector<STARE_ArrayIndexSpatialValue> &target_indices,
185 const vector<STARE_ArrayIndexSpatialValue> &dataset_indices,
186 bool all_dataset_matches ) {
187 unsigned int counter = 0;
188 for (
const auto &i : target_indices) {
189 for (
const auto &j : dataset_indices)
192 if (cmpSpatial(i, j) != 0) {
194 BESDEBUG(STARE_FUNC,
"Matching (dataset, target) indices: " << i <<
", " << j << endl);
195 if (!all_dataset_matches)
211unique_ptr<stare_matches>
212stare_subset_helper(
const vector<STARE_ArrayIndexSpatialValue> &target_indices,
213 const vector<STARE_ArrayIndexSpatialValue> &dataset_indices,
214 size_t dataset_rows,
size_t dataset_cols)
218 auto sid_iter = dataset_indices.begin();
219 for (
size_t i = 0; i < dataset_rows; ++i) {
220 for (
size_t j = 0; j < dataset_cols; ++j) {
221 auto sid = *sid_iter++;
222 for (
const auto &target : target_indices) {
223 if (cmpSpatial(sid, target) != 0) {
224 subset->add(i, j, sid, target);
234read_stare_indices_from_function_argument(BaseType *raw_stare_indices,
235 vector<STARE_ArrayIndexSpatialValue> &s_indices) {
237 auto stare_indices =
dynamic_cast<Array *
>(raw_stare_indices);
238 if (stare_indices ==
nullptr)
239 throw BESSyntaxUserError(
240 "Expected an Array but found a " + raw_stare_indices->type_name(), __FILE__, __LINE__);
242 if (stare_indices->var()->type() != dods_uint64_c)
243 throw BESSyntaxUserError(
244 "Expected an Array of UInt64 values but found an Array of " + stare_indices->var()->type_name(),
247 stare_indices->read();
249 extract_stare_index_array(stare_indices, s_indices);
265 if (args->size() != 2) {
267 oss <<
"stare_intersection(): Expected two arguments, but got " << args->size();
271 const BaseType *dependent_var = args->get_rvalue(0)->value(dmr);
272 BaseType *raw_stare_indices = args->get_rvalue(1)->value(dmr);
274 unique_ptr<GeoFile> gf(
new GeoFile(dmr.filename()));
277 vector<STARE_ArrayIndexSpatialValue> dep_var_stare_indices;
278 gf->get_stare_indices(dependent_var->name(), dep_var_stare_indices);
281 vector<STARE_ArrayIndexSpatialValue> target_s_indices;
282 read_stare_indices_from_function_argument(raw_stare_indices, target_s_indices);
285 bool status = target_in_dataset(target_s_indices, dep_var_stare_indices);
287 unique_ptr<Int32> result(
new Int32(
"result"));
289 result->set_value(1);
292 result->set_value(0);
295 return result.release();
319 if (args->size() != 2) {
321 oss <<
"stare_intersection(): Expected two arguments, but got " << args->size();
325 const BaseType *dependent_var = args->get_rvalue(0)->value(dmr);
326 BaseType *raw_stare_indices = args->get_rvalue(1)->value(dmr);
328 unique_ptr<GeoFile> gf(
new GeoFile(dmr.filename()));
331 vector<STARE_ArrayIndexSpatialValue> dep_var_stare_indices;
332 gf->get_stare_indices(dependent_var->name(), dep_var_stare_indices);
335 vector<STARE_ArrayIndexSpatialValue> target_s_indices;
336 read_stare_indices_from_function_argument(raw_stare_indices, target_s_indices);
338 unsigned int num = count(target_s_indices, dep_var_stare_indices,
false);
340 unique_ptr<Int32> result(
new Int32(
"result"));
341 result->set_value(
static_cast<int>(num));
342 return result.release();
362 if (args->size() != 2) {
364 oss <<
"stare_subset(): Expected two arguments, but got " << args->size();
368 const BaseType *dependent_var = args->get_rvalue(0)->value(dmr);
369 BaseType *raw_stare_indices = args->get_rvalue(1)->value(dmr);
371 unique_ptr<GeoFile> gf(
new GeoFile(dmr.filename()));
374 vector<STARE_ArrayIndexSpatialValue> dep_var_stare_indices;
375 gf->get_stare_indices(dependent_var->name(), dep_var_stare_indices);
378 vector<STARE_ArrayIndexSpatialValue> target_s_indices;
379 read_stare_indices_from_function_argument(raw_stare_indices, target_s_indices);
381 unique_ptr <stare_matches> subset = stare_subset_helper(target_s_indices, dep_var_stare_indices,
382 gf->get_variable_rows(dependent_var->name()),
383 gf->get_variable_cols(dependent_var->name()));
386 if (subset->stare_indices.empty()) {
387 subset->stare_indices.push_back(0);
388 subset->target_indices.push_back(0);
389 subset->row_indices.push_back(-1);
390 subset->col_indices.push_back(-1);
393 unique_ptr<Structure> result(
new Structure(
"result"));
395 unique_ptr<Array> stare(
new Array(
"stare",
new UInt64(
"stare")));
399 stare->set_value((dods_uint64*)&(subset->stare_indices[0]),
static_cast<int>(subset->stare_indices.size()));
400 stare->append_dim(
static_cast<int>(subset->stare_indices.size()));
401 result->add_var_nocopy(stare.release());
403 unique_ptr<Array> target(
new Array(
"target",
new UInt64(
"target")));
404 target->set_value((dods_uint64*) &(subset->target_indices[0]),
static_cast<int>(subset->target_indices.size()));
405 target->append_dim(
static_cast<int>(subset->target_indices.size()));
406 result->add_var_nocopy(target.release());
408 unique_ptr<Array> x(
new Array(
"row",
new Int32(
"row")));
409 x->set_value(subset->row_indices,
static_cast<int>(subset->row_indices.size()));
410 x->append_dim(
static_cast<int>(subset->row_indices.size()));
411 result->add_var_nocopy(x.release());
413 unique_ptr<Array> y(
new Array(
"col",
new Int32(
"col")));
414 y->set_value(subset->col_indices,
static_cast<int>(subset->col_indices.size()));
415 y->append_dim(
static_cast<int>(subset->col_indices.size()));
416 result->add_var_nocopy(y.release());
418 return result.release();
429double get_double_value(BaseType *btp)
431 switch (btp->type()) {
432 case libdap::dods_float64_c:
433 return dynamic_cast<Float64*
>(btp)->value();
434 case libdap::dods_int64_c:
435 return static_cast<double>(
dynamic_cast<Int64*
>(btp)->value());
436 case libdap::dods_uint64_c:
437 return static_cast<double>(
dynamic_cast<UInt64*
>(btp)->value());
439 throw BESSyntaxUserError(
string(
"Expected a constant value, but got ").append(btp->type_name())
440 .append(
" instead."), __FILE__, __LINE__);
446StareSubsetArrayFunction::stare_subset_array_dap4_function(D4RValueList *args, DMR &dmr)
448 if (args->size() != 3) {
450 oss <<
"stare_subset_array(): Expected three arguments, but got " << args->size();
451 throw BESSyntaxUserError(oss.str(), __FILE__, __LINE__);
454 auto dependent_var =
dynamic_cast<Array*
>(args->get_rvalue(0)->value(dmr));
456 throw BESSyntaxUserError(
"Expected an Array as teh first argument to stare_subset_array()", __FILE__, __LINE__);
458 BaseType *mask_val_var = args->get_rvalue(1)->value(dmr);
459 double mask_value = get_double_value(mask_val_var);
461 BaseType *raw_stare_indices = args->get_rvalue(2)->value(dmr);
463 unique_ptr<GeoFile> gf(
new GeoFile(dmr.filename()));
466 vector<STARE_ArrayIndexSpatialValue> dep_var_stare_indices;
467 gf->get_stare_indices(dependent_var->name(), dep_var_stare_indices);
470 vector<STARE_ArrayIndexSpatialValue> target_s_indices;
471 read_stare_indices_from_function_argument(raw_stare_indices, target_s_indices);
474 unique_ptr<Array> result(
dynamic_cast<Array*
>(dependent_var->ptr_duplicate()));
477 switch(dependent_var->var()->type()) {
479 build_masked_data<dods_int16>(dependent_var, dep_var_stare_indices, target_s_indices,
480 static_cast<short>(mask_value), result);
483 case dods_float32_c: {
484 build_masked_data<dods_float32>(dependent_var, dep_var_stare_indices, target_s_indices,
485 static_cast<float>(mask_value), result);
490 throw BESInternalError(
string(
"stare_subset_array() failed: Unsupported array element type (")
491 + dependent_var->var()->type_name() +
").", __FILE__, __LINE__);
494 return result.release();
504STARE_SpatialIntervals
505stare_box_helper(
const vector<point> &points,
int resolution) {
506 LatLonDegrees64ValueVector latlonbox;
507 for (
auto &p: points) {
508 latlonbox.push_back(LatLonDegrees64(p.lat, p.lon));
512 return index.CoverBoundingBoxFromLatLonDegrees(latlonbox, resolution);
526STARE_SpatialIntervals
527stare_box_helper(
const point &top_left,
const point &bottom_right,
int resolution) {
528 LatLonDegrees64ValueVector latlonbox;
529 latlonbox.push_back(LatLonDegrees64(top_left.lat, top_left.lon));
530 latlonbox.push_back(LatLonDegrees64(top_left.lat, bottom_right.lon));
531 latlonbox.push_back(LatLonDegrees64(bottom_right.lat, bottom_right.lon));
532 latlonbox.push_back(LatLonDegrees64(bottom_right.lat, top_left.lon));
535 return index.CoverBoundingBoxFromLatLonDegrees(latlonbox, resolution);
539StareBoxFunction::stare_box_dap4_function(libdap::D4RValueList *args, libdap::DMR &dmr)
541 STARE_SpatialIntervals sivs;
543 if (args->size() == 4) {
545 double tl_lat = get_double_value(args->get_rvalue(0)->value(dmr));
546 double tl_lon = get_double_value(args->get_rvalue(1)->value(dmr));
547 double br_lat = get_double_value(args->get_rvalue(2)->value(dmr));
548 double br_lon = get_double_value(args->get_rvalue(3)->value(dmr));
550 sivs = stare_box_helper(point(tl_lat, tl_lon), point(br_lat, br_lon));
552 else if (args->size() >= 6 && (args->size() % 2) == 0) {
554 bool flip_flop =
false;
555 double lat_value = -90;
556 vector<point> points;
557 for (
auto &arg: *args) {
559 point pt(lat_value, get_double_value(arg->value(dmr)));
560 points.push_back(pt);
564 lat_value = get_double_value(arg->value(dmr));
569 sivs = stare_box_helper(points);
573 oss <<
"stare_box(): Expected four corner lat/lon values or a list of three or more points, but got "
574 << args->size() <<
" values.";
575 throw BESSyntaxUserError(oss.str(), __FILE__, __LINE__);
578 unique_ptr<Array> cover(
new Array(
"cover",
new UInt64(
"cover")));
579 cover->set_value((dods_uint64*)(sivs.data()),
static_cast<int>(sivs.size()));
580 cover->append_dim(
static_cast<int>(sivs.size()));
582 return cover.release();
error thrown if there is a user syntax error in the request or any other user error
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.