38 static char rcsid[]
not_used = {
"$Id: ce_functions.cc 25915 2012-10-24 00:14:58Z jimg $" };
51 #undef FUNCTION_DAP // undef so the dap() function always returns an error;
87 double w32strtod(
const char *,
char **);
103 inline bool double_eq(
double lhs,
double rhs,
double epsilon = 1.0e-5)
106 return (lhs - rhs) < ((lhs + rhs) / epsilon);
108 return (rhs - lhs) < ((lhs + rhs) / epsilon);
125 "The CE Evaluator built an argument list where some constants held no values.");
127 string s =
dynamic_cast<Str&
> (*arg).
value();
129 DBG(cerr <<
"s: " << s << endl);
135 template<
class T>
static void set_array_using_double_helper(Array * a,
double *src,
int src_len)
137 T *values =
new T[src_len];
138 for (
int i = 0; i < src_len; ++i)
139 values[i] = (T) src[i];
142 a->val2buf(values,
true);
144 a->set_value(values, src_len);
172 throw InternalErr(__FILE__, __LINE__,
"The function requires a DAP numeric-type array argument.");
178 if (dest->
length() != src_len)
182 "The source and destination array sizes don't match (" +
long_to_string(src_len) +
" versus "
191 set_array_using_double_helper<dods_byte> (dest, src, src_len);
194 set_array_using_double_helper<dods_uint16> (dest, src, src_len);
197 set_array_using_double_helper<dods_int16> (dest, src, src_len);
200 set_array_using_double_helper<dods_uint32> (dest, src, src_len);
203 set_array_using_double_helper<dods_int32> (dest, src, src_len);
206 set_array_using_double_helper<dods_float32> (dest, src, src_len);
209 set_array_using_double_helper<dods_float64> (dest, src, src_len);
213 "The argument list built by the CE parser contained an unsupported numeric type.");
220 template<
class T>
static double *extract_double_array_helper(Array * a)
222 int length = a->length();
224 T *b =
new T[length];
227 double *dest =
new double[length];
228 for (
int i = 0; i < length; ++i)
229 dest[i] = (
double) b[i];
247 throw InternalErr(__FILE__, __LINE__,
string(
"The Array '") + a->
name() +
"'does not contain values.");
255 return extract_double_array_helper<dods_byte> (a);
257 return extract_double_array_helper<dods_uint16> (a);
259 return extract_double_array_helper<dods_int16> (a);
261 return extract_double_array_helper<dods_uint32> (a);
263 return extract_double_array_helper<dods_int32> (a);
265 return extract_double_array_helper<dods_float32> (a);
267 return extract_double_array_helper<dods_float64> (a);
270 "The argument list built by the CE parser contained an unsupported numeric type.");
289 "The CE Evaluator built an argument list where some constants held no values.");
295 switch (arg->
type()) {
297 return (
double) (
dynamic_cast<Byte&
> (*arg).
value());
299 return (
double) (
dynamic_cast<UInt16&
> (*arg).
value());
301 return (
double) (
dynamic_cast<Int16&
> (*arg).
value());
303 return (
double) (
dynamic_cast<UInt32&
> (*arg).
value());
305 return (
double) (
dynamic_cast<Int32&
> (*arg).
value());
307 return (
double) (
dynamic_cast<Float32&
> (*arg).
value());
312 "The argument list built by the CE parser contained an unsupported numeric type.");
326 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\
328 <function name=\"geogrid\" version=\"1.2\"/>\
329 <function name=\"grid\" version=\"1.0\"/>\
330 <function name=\"linear_scale\" version=\"1.0b1\"/>\
331 <function name=\"version\" version=\"1.0\"/>\
332 <function name=\"dap\" version=\"1.0\"/>\
337 Str *response =
new Str(
"version");
348 throw Error(
"The 'dap' function must be called with a version number.\n\
349 see http://docs.opendap.org/index.php/Server_Side_Processing_Functions#dap");
353 dds.set_dap_version(pv);
356 "The 'dap' function is not supported in lieu of Constraint expression 'keywords.'\n\
357 see http://docs.opendap.org/index.php/Server_Side_Processing_Functions#keywords");
361 static void parse_gse_expression(gse_arg * arg, BaseType * expr)
366 bool status =
gse_parse((
void *) arg) == 0;
372 static void apply_grid_selection_expr(Grid * grid, GSEClause * clause)
376 Grid::Map_iter map_i = grid->map_begin();
377 while (map_i != grid->map_end() && (*map_i)->name() != clause->get_map_name())
380 if (map_i == grid->map_end())
382 "The map vector '" + clause->get_map_name() +
"' is not in the grid '" + grid->name() +
"'.");
385 Array::Dim_iter grid_dim = (grid->get_array()->dim_begin() + (map_i - grid->map_begin()));
387 Array *map =
dynamic_cast<Array *
> ((*map_i));
389 throw InternalErr(__FILE__, __LINE__,
"Expected an Array");
390 int start = max(map->dimension_start(map->dim_begin()), clause->get_start());
391 int stop = min(map->dimension_stop(map->dim_begin()), clause->get_stop());
395 msg <<
"The expressions passed to grid() do not result in an inclusive \n" <<
"subset of '"
396 << clause->get_map_name() <<
"'. The map's values range " <<
"from " << clause->get_map_min_value()
397 <<
" to " << clause->get_map_max_value() <<
".";
401 DBG(cerr <<
"Setting constraint on " << map->name()
402 <<
"[" << start <<
":" << stop <<
"]" << endl);
405 map->add_constraint(map->dim_begin(), start, 1, stop);
406 grid->get_array()->add_constraint(grid_dim, start, 1, stop);
409 static void apply_grid_selection_expressions(Grid * grid, vector<GSEClause *> clauses)
411 vector<GSEClause *>::iterator clause_i = clauses.begin();
412 while (clause_i != clauses.end())
413 apply_grid_selection_expr(grid, *clause_i++);
415 grid->set_read_p(
false);
437 if (!(l_lat = dynamic_cast<Array *>(dds.
var(
"Latitude")))
438 || !(l_lon =
dynamic_cast<Array *
>(dds.
var(
"Latitude"))))
443 l_lat =
dynamic_cast<Array*
>(argv[0]);
444 l_lon =
dynamic_cast<Array*
>(argv[1]);
445 if (!l_lat || !l_lon)
518 DBG(cerr <<
"Entering function_grid..." << endl);
522 string(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
523 +
"<function name=\"grid\" version=\"1.0\" href=\"http://docs.opendap.org/index.php/Server_Side_Processing_Functions#grid\">\n"
527 Str *response =
new Str(
"info");
533 Grid *original_grid =
dynamic_cast<Grid *
> (argv[0]);
540 Grid *l_grid =
dynamic_cast<Grid *
> (btp);
543 throw InternalErr(__FILE__, __LINE__,
"Expected a Grid.");
546 DBG(cerr <<
"grid: past initialization code" << endl);
556 (*i++)->set_send_p(
true);
560 DBG(cerr <<
"grid: past map read" << endl);
566 vector<GSEClause *> clauses;
568 for (
int i = 1; i < argc; ++i) {
569 parse_gse_expression(arg, argv[i]);
575 apply_grid_selection_expressions(l_grid, clauses);
577 DBG(cerr <<
"grid: past gse application" << endl);
631 string(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
632 +
"<function name=\"geogrid\" version=\"1.2\" href=\"http://docs.opendap.org/index.php/Server_Side_Processing_Functions#geogrid\">\n"
636 Str *response =
new Str(
"version");
651 if (argc < 1 || !(l_grid = dynamic_cast<Grid *> (argv[0]->ptr_duplicate())))
657 "Wrong number of arguments to geogrid() (expected at least 5 args). See geogrid() for more information.");
659 bool grid_lat_lon_form;
662 if (!(l_lat = dynamic_cast<Array *> (argv[1])))
663 grid_lat_lon_form =
false;
664 else if (!(l_lon = dynamic_cast<Array *> (argv[2])))
666 "When using the Grid, Lat, Lon form of geogrid() both the lat and lon maps must be given (lon map missing)!");
668 grid_lat_lon_form =
true;
670 if (grid_lat_lon_form && argc < 7)
672 "Wrong number of arguments to geogrid() (expected at least 7 args). See geogrid() for more information.");
691 (*i++)->set_send_p(
true);
698 DBG(cerr <<
"geogrid: past map read" << endl);
702 int min_arg_count = (grid_lat_lon_form) ? 7 : 5;
703 if (argc > min_arg_count) {
706 vector<GSEClause *> clauses;
708 for (
int i = min_arg_count; i < argc; ++i) {
709 parse_gse_expression(arg, argv[i]);
715 apply_grid_selection_expressions(l_grid, clauses);
725 int box_index_offset = (grid_lat_lon_form) ? 3 : 1;
731 DBG(cerr <<
"geogrid: past bounding box set" << endl);
735 DBG(cerr <<
"geogrid: past apply constraint" << endl);
743 }
catch (exception & e) {
744 throw InternalErr(
string(
"A C++ exception was thrown from inside geogrid(): ") + e.what());
753 static double string_to_double(
const char *val)
760 double v = w32strtod(val, &ptr);
762 double v = strtod(val, &ptr);
765 if ((v == 0.0 && (val == ptr || errno == HUGE_VAL || errno == ERANGE)) || *ptr !=
'\0') {
766 throw Error(
malformed_expr,
string(
"Could not convert the string '") + val +
"' to a double.");
769 double abs_val = fabs(v);
771 throw Error(
malformed_expr,
string(
"Could not convert the string '") + val +
"' to a double.");
785 static double get_attribute_double_value(BaseType *var, vector<string> &attributes)
789 AttrTable &attr = var->get_attr_table();
790 string attribute_value =
"";
792 vector<string>::iterator i = attributes.begin();
793 while (attribute_value ==
"" && i != attributes.end()) {
797 attribute_value = attr.get_attr(*i++);
802 if (attribute_value.empty()) {
804 return get_attribute_double_value(dynamic_cast<Grid&> (*var).get_array(), attributes);
808 string(
"No COARDS/CF '") + values.substr(0, values.length() - 2)
809 +
"' attribute was found for the variable '" + var->name() +
"'.");
812 return string_to_double(
remove_quotes(attribute_value).c_str());
815 static double get_attribute_double_value(BaseType *var,
const string &attribute)
817 AttrTable &attr = var->get_attr_table();
818 string attribute_value = attr.get_attr(attribute);
822 if (attribute_value.empty()) {
824 return get_attribute_double_value(dynamic_cast<Grid&> (*var).get_array(), attribute);
827 string(
"No COARDS '") + attribute +
"' attribute was found for the variable '" + var->name() +
"'.");
830 return string_to_double(
remove_quotes(attribute_value).c_str());
833 static double get_y_intercept(BaseType *var)
835 vector<string> attributes;
836 attributes.push_back(
"add_offset");
837 attributes.push_back(
"add_off");
838 return get_attribute_double_value(var, attributes);
841 static double get_slope(BaseType *var)
843 return get_attribute_double_value(var,
"scale_factor");
846 static double get_missing_value(BaseType *var)
848 return get_attribute_double_value(var,
"missing_value");
867 string(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
868 +
"<function name=\"linear_scale\" version=\"1.0b1\" href=\"http://docs.opendap.org/index.php/Server_Side_Processing_Functions#linear_scale\">\n"
872 Str *response =
new Str(
"info");
879 DBG(cerr <<
"argc = " << argc << endl);
880 if (!(argc == 1 || argc == 3 || argc == 4))
882 "Wrong number of arguments to linear_scale(). See linear_scale() for more information");
885 bool use_missing =
false;
886 double m, b, missing = 0.0;
893 else if (argc == 3) {
899 m = get_slope(argv[0]);
905 b = get_y_intercept(argv[0]);
914 missing = get_missing_value(argv[0]);
921 DBG(cerr <<
"m: " << m <<
", b: " << b << endl);
DBG(cerr <<
"use_missing: " << use_missing <<
", missing: " << missing << endl);
930 Array *source =
dynamic_cast<Grid*
>(argv[0])->get_array();
935 int length = source->
length();
936 for (
int i = 0; i < length; ++i)
937 data[i] = data[i] * m + b;
941 DBG2(cerr <<
"data[" << i <<
"]: " << data[i] << endl);
942 if (!use_missing || !
double_eq(data[i], missing))
943 data[i] = data[i] * m + b;
944 DBG2(cerr <<
" >> data[" << i <<
"]: " << data[i] << endl);
953 source.
val2buf(static_cast<void*>(data),
false);
963 Grid &source =
dynamic_cast<Grid&
>(*argv[0]);
965 DBG(cerr <<
"Grid send_p: " << source.
send_p() << endl);
980 for (
int i = 0; i < length; ++i)
981 data[i] = data[i] * m + b;
986 while (s != source.
map_end()) {
1006 while (s != source.
map_end()) {
1011 vector<dods_byte> v(a->
length());
1017 vector<dods_float32> v(a->
length());
1023 throw Error(
"Non-numeric Grid Map not supported by linear_scale().");
1030 DBG(cerr <<
"Grid send_p: " << result->
send_p() << endl);
1035 else if (argv[0]->is_vector_type()) {
1037 Array &source =
dynamic_cast<Array&
> (*argv[0]);
1047 int length = source.
length();
1049 while (i < length) {
1050 if (!use_missing || !
double_eq(data[i], missing))
1051 data[i] = data[i] * m + b;
1058 source.
val2buf(static_cast<void*> (data),
false);
1065 Array &source =
dynamic_cast<Array&
>(*argv[0]);
1076 int length = source.
length();
1077 for (
int i = 0; i < length; ++i)
1078 data[i] = data[i] * m + b;
1089 else if (argv[0]->is_simple_type() && !(argv[0]->type() ==
dods_str_c || argv[0]->type() ==
dods_url_c)) {
1091 if (!use_missing || !
double_eq(data, missing))
1092 data = data * m + b;
1101 throw Error(
malformed_expr,
"The linear_scale() function works only for numeric Grids, Arrays and scalars.");
1130 string(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") +
1131 "<function name=\"geoarray\" version=\"0.9b1\" href=\"http://docs.opendap.org/index.php/Server_Side_Processing_Functions#geoarray\">\n" +
1135 Str *response =
new Str(
"version");
1136 response->set_value(info);
1141 DBG(cerr <<
"argc = " << argc << endl);
1142 if (!(argc == 5 || argc == 9 || argc == 11))
1143 throw Error(
malformed_expr,
"Wrong number of arguments to geoarray(). See geoarray() for more information.");
1146 Array *l_array = dynamic_cast < Array * >(argv[0]->ptr_duplicate());
1148 throw Error(
malformed_expr,
"The first argument to geoarray() must be an Array variable!");
1160 ArrayGeoConstraint agc(l_array);
1162 agc.set_bounding_box(bb_left, bb_top, bb_right, bb_bottom);
1164 agc.apply_constraint_to_data();
1165 *btpp = agc.get_constrained_array();
1174 ArrayGeoConstraint agc (l_array, var_left, var_top, var_right, var_bottom);
1176 agc.set_bounding_box(bb_left, bb_top, bb_right, bb_bottom);
1178 agc.apply_constraint_to_data();
1179 *btpp = agc.get_constrained_array();
1190 ArrayGeoConstraint agc(l_array,
1191 var_left, var_top, var_right, var_bottom,
1194 agc.set_bounding_box(bb_left, bb_top, bb_right, bb_bottom);
1196 agc.apply_constraint_to_data();
1197 *btpp = agc.get_constrained_array();
1202 throw InternalErr(__FILE__, __LINE__,
"Wrong number of args to geoarray.");
1208 catch (exception & e) {
1211 (
"A C++ exception was thrown from inside geoarray(): ")
1216 throw InternalErr(__FILE__, __LINE__,
"Impossible condition in geoarray.");