51 static double string_to_double(
const char *val)
59 double v = w32strtod(val, &ptr);
61 double v = strtod(val, &ptr);
64 if ((v == 0.0 && (val == ptr || errno == HUGE_VAL || errno == ERANGE))
66 throw Error(malformed_expr,
string(
"Could not convert the string '") + val +
"' to a double.");
70 istringstream iss(val);
74 double abs_val = fabs(v);
75 if (abs_val > DODS_DBL_MAX || (abs_val != 0.0 && abs_val < DODS_DBL_MIN))
76 throw Error(malformed_expr,
string(
"Could not convert the string '") + val +
"' to a double.");
90 static double get_attribute_double_value(BaseType *var, vector<string> &attributes)
94 AttrTable &attr = var->get_attr_table();
95 string attribute_value =
"";
97 vector<string>::iterator i = attributes.begin();
98 while (attribute_value ==
"" && i != attributes.end()) {
102 attribute_value = attr.get_attr(*i++);
107 if (attribute_value.empty()) {
108 if (var->type() == dods_grid_c)
109 return get_attribute_double_value(dynamic_cast<Grid&>(*var).get_array(), attributes);
111 throw Error(malformed_expr,
string(
"No COARDS/CF '") + values.substr(0, values.length() - 2)
112 +
"' attribute was found for the variable '"
113 + var->name() +
"'.");
116 return string_to_double(remove_quotes(attribute_value).c_str());
119 static double get_attribute_double_value(BaseType *var,
const string &attribute)
121 AttrTable &attr = var->get_attr_table();
122 string attribute_value = attr.get_attr(attribute);
126 if (attribute_value.empty()) {
127 if (var->type() == dods_grid_c)
128 return get_attribute_double_value(dynamic_cast<Grid&>(*var).get_array(), attribute);
130 throw Error(malformed_expr,
string(
"No COARDS '") + attribute
131 +
"' attribute was found for the variable '"
132 + var->name() +
"'.");
135 return string_to_double(remove_quotes(attribute_value).c_str());
138 static double get_y_intercept(BaseType *var)
140 vector<string> attributes;
141 attributes.push_back(
"add_offset");
142 attributes.push_back(
"add_off");
143 return get_attribute_double_value(var, attributes);
146 static double get_slope(BaseType *var)
148 return get_attribute_double_value(var,
"scale_factor");
151 static double get_missing_value(BaseType *var)
153 return get_attribute_double_value(var,
"missing_value");
172 string(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") +
173 "<function name=\"linear_scale\" version=\"1.0b1\" href=\"http://docs.opendap.org/index.php/Server_Side_Processing_Functions#linear_scale\">\n" +
177 Str *response =
new Str(
"info");
178 response->set_value(info);
184 DBG(cerr <<
"argc = " << argc << endl);
185 if (!(argc == 1 || argc == 3 || argc == 4))
186 throw Error(malformed_expr,
"Wrong number of arguments to linear_scale(). See linear_scale() for more information");
189 bool use_missing =
false;
190 double m, b, missing = 0.0;
192 m = extract_double_value(argv[1]);
193 b = extract_double_value(argv[2]);
194 missing = extract_double_value(argv[3]);
196 }
else if (argc == 3) {
197 m = extract_double_value(argv[1]);
198 b = extract_double_value(argv[2]);
201 m = get_slope(argv[0]);
207 b = get_y_intercept(argv[0]);
217 missing = get_missing_value(argv[0]);
225 DBG(cerr <<
"m: " << m <<
", b: " << b << endl);DBG(cerr <<
"use_missing: " << use_missing <<
", missing: " << missing << endl);
231 if (argv[0]->type() == dods_grid_c) {
234 Array *source =
dynamic_cast<Grid*
>(argv[0])->get_array();
238 data = extract_double_array(source);
239 int length = source->length();
240 for (
int i = 0; i < length; ++i)
241 data[i] = data[i] * m + b;
245 DBG2(cerr <<
"data[" << i <<
"]: " << data[i] << endl);
246 if (!use_missing || !double_eq(data[i], missing))
247 data[i] = data[i] * m + b;
248 DBG2(cerr <<
" >> data[" << i <<
"]: " << data[i] << endl);
253 Float64 *temp_f =
new Float64(source->name());
254 source->add_var(temp_f);
257 source.val2buf(static_cast<void*>(data),
false);
259 source->set_value(data, length);
264 dest->set_send_p(
true);
267 Grid &source =
dynamic_cast<Grid&
>(*argv[0]);
269 DBG(cerr <<
"Grid send_p: " << source.send_p() << endl);
270 DBG(cerr <<
"Grid Array send_p: " << source.get_array()->send_p() << endl);
274 source.set_send_p(
true);
278 Array *a = source.get_array();
280 data = extract_double_array(a);
283 int length = a->length();
284 for (
int i = 0; i < length; ++i)
285 data[i] = data[i] * m + b;
289 Grid::Map_iter s = source.map_begin();
290 while (s != source.map_end()) {
291 static_cast<Array*
>(*s)->read();
298 Grid *result =
new Grid(source);
302 result->get_array()->add_var_nocopy(
new Float64(source.name()));
303 result->get_array()->set_value(data, length);
308 Grid::Map_iter s = source.map_begin();
309 Grid::Map_iter d = result->map_begin();
310 while (s != source.map_end()) {
311 Array *a =
static_cast<Array*
>(*s);
313 switch(a->var()->type()) {
315 vector<dods_byte> v(a->length());
317 static_cast<Array*
>(*d)->set_value(v, v.size());
320 case dods_float32_c: {
321 vector<dods_float32> v(a->length());
323 static_cast<Array*
>(*d)->set_value(v, a->length());
327 throw Error(
"Non-numeric Grid Map not supported by linear_scale().");
334 DBG(cerr <<
"Grid send_p: " << result->send_p() << endl);
335 DBG(cerr <<
"Grid Array send_p: " << result->get_array()->send_p() << endl);
339 else if (argv[0]->is_vector_type()) {
341 Array &source =
dynamic_cast<Array&
> (*argv[0]);
342 source.set_send_p(
true);
345 if (source.get_parent() && source.get_parent()->type() == dods_grid_c)
346 source.get_parent()->read();
350 data = extract_double_array(&source);
351 int length = source.length();
354 if (!use_missing || !double_eq(data[i], missing))
355 data[i] = data[i] * m + b;
359 Float64 *temp_f =
new Float64(source.name());
360 source.add_var(temp_f);
362 source.val2buf(static_cast<void*>(data),
false);
369 Array &source =
dynamic_cast<Array&
>(*argv[0]);
372 if (source.get_parent() && source.get_parent()->type() == dods_grid_c) {
373 source.get_parent()->set_send_p(
true);
374 source.get_parent()->read();
379 data = extract_double_array(&source);
380 int length = source.length();
381 for (
int i = 0; i < length; ++i)
382 data[i] = data[i] * m + b;
384 Array *result =
new Array(source);
386 result->add_var_nocopy(
new Float64(source.name()));
387 result->set_value(data, length);
393 else if (argv[0]->is_simple_type() && !(argv[0]->type() == dods_str_c || argv[0]->type() == dods_url_c)) {
394 double data = extract_double_value(argv[0]);
395 if (!use_missing || !double_eq(data, missing))
398 Float64 *fdest =
new Float64(argv[0]->name());
400 fdest->set_value(data);
404 throw Error(malformed_expr,
"The linear_scale() function works only for numeric Grids, Arrays and scalars.");
void function_linear_scale(int argc, BaseType *argv[], DDS &, BaseType **btpp)
Given a BaseType, scale it using 'y = mx + b'.