OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
RoiFunction.cc
Go to the documentation of this file.
1 
2 // -*- mode: c++; c-basic-offset:4 -*-
3 
4 // This file is part of bes, A C++ implementation of the OPeNDAP
5 // Hyrax data server
6 
7 // Copyright (c) 2015 OPeNDAP, Inc.
8 // Authors: James Gallagher <jgallagher@opendap.org>
9 //
10 // This library is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU Lesser General Public
12 // License as published by the Free Software Foundation; either
13 // version 2.1 of the License, or (at your option) any later version.
14 //
15 // This library is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 // Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public
21 // License along with this library; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 //
24 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
25 
26 #include "config.h"
27 
28 #include <cassert>
29 #include <sstream>
30 #include <memory>
31 
32 #include <BaseType.h>
33 #include <Int32.h>
34 #include <Str.h>
35 #include <Array.h>
36 #include <Structure.h>
37 
38 #include <D4RValue.h>
39 #include <Error.h>
40 #include <debug.h>
41 #include <util.h>
42 #include <ServerFunctionsList.h>
43 
44 #include <BESDebug.h>
45 
46 #include "RoiFunction.h"
47 #include "roi_utils.h"
48 
49 using namespace std;
50 
51 namespace libdap {
52 
60 static void check_number_type_array(BaseType *btp, unsigned int rank)
61 {
62  if (!btp)
63  throw InternalErr(__FILE__, __LINE__, "roi() function called with null variable.");
64 
65  if (btp->type() != dods_array_c)
66  throw Error("In function roi(): Expected argument '" + btp->name() + "' to be an Array.");
67 
68  Array *a = static_cast<Array *>(btp);
69  if (!a->var()->is_simple_type() || a->var()->type() == dods_str_c || a->var()->type() == dods_url_c)
70  throw Error("In function roi(): Expected argument '" + btp->name() + "' to be an Array of numeric types.");
71 
72  if (a->dimensions() < rank)
73  throw Error("In function roi(): Expected the array '" + a->name() +"' to be rank " + long_to_string(rank) + " or greater.");
74 }
75 
97 void
98 function_dap2_roi(int argc, BaseType *argv[], DDS &, BaseType **btpp)
99 {
100  const string wrong_args = "Wrong number of arguments to roi(). Expected one or more Arrays and bounding box";
101 
102  // This is the rank of the Array of Slices, not the N-1 arrays to be sliced
103  int rank = 0;
104 
105  switch (argc) {
106  case 0:
107  case 1:
108  // Must have 2 or more arguments
109  throw Error(malformed_expr, wrong_args);
110  default:
111  rank = roi_valid_bbox(argv[argc-1]); // throws if slice is not valid
112 
113  for (int i = 0; i < argc-1; ++i)
114  check_number_type_array(argv[i], rank); // throws if array is not valid
115  break;
116  }
117 
118  auto_ptr<Structure> response(new Structure("roi_subset"));
119 
120  Array *bbox = static_cast<Array*>(argv[argc-1]);
121 
122  for (int i = 0; i < argc-1; ++i) {
123  // cast is safe given the above
124  Array *the_array = static_cast<Array*>(argv[i]);
125  BESDEBUG("roi", "the_array: " << the_array->name() << ": " << (void*)the_array << endl);
126 
127  // For each dimension of the array, apply the slice constraint.
128  // Assume Array[]...[][X][Y] where the slice has dims X and Y
129  // So find the last <rank> dimensions and check that their names
130  // match those of the slice. This loops 'walks backward' over
131  // both the N bbox slices and the right-most N dimensions of
132  // the arrays.
133 
134  unsigned int num_dims = the_array->dimensions();
135  int d = num_dims-1;
136  for (int i = rank-1; i >= 0; --i) {
137  int start, stop;
138  string name;
139  // start, stop, name are value-result parameters
140  roi_bbox_get_slice_data(bbox, i, start, stop, name);
141 
142  // Hack, should use reverse iterators, but Array does not have them
143  Array::Dim_iter iter = the_array->dim_begin() + d;
144 
145  // TODO Make this an option (i.e., turn off the test)?
146  // TODO Make a second option that will match names instead of position
147  if (the_array->dimension_name(iter) != name)
148  throw Error("In function roi(): Dimension name (" + the_array->dimension_name(iter) + ") and slice name (" + name + ") don't match");
149 
150  // TODO Add stride option?
151  BESDEBUG("roi", "Dimension: " << i << ", Start: " << start << ", Stop: " << stop << endl);
152  the_array->add_constraint(iter, start, 1 /*stride*/, stop);
153  --d;
154  }
155 
156  // Add the array to the Structure returned by the function
157  the_array->set_send_p(true); // include it
158 
159  // TODO Why do we have to force this read? The libdap::BaseType::serialize()
160  // code should take care of it, but in the debugger the read_p property is
161  // showing up as true. jhrg 2/26/15 Hack and move on...
162  //if (!the_array->read_p())
163  the_array->set_read_p(false);
164  the_array->read();
165  the_array->set_read_p(true);
166 
167  response->add_var(the_array);
168  }
169 
170  response->set_send_p(true);
171  response->set_read_p(true);
172 
173  *btpp = response.release();
174  return;
175 }
176 
186 BaseType *function_dap4_roi(D4RValueList *, DMR &)
187 {
188  throw Error(malformed_expr, "Not yet implemented for DAP4 functions.");
189 
190  return 0;
191 }
192 
193 } // namesspace libdap
void roi_bbox_get_slice_data(Array *slices, unsigned int i, int &start, int &stop, string &name)
This method extracts values from one element of the Bounding Box (i.e., Array of Structures).
Definition: roi_utils.cc:122
STL namespace.
BaseType * function_dap4_roi(D4RValueList *, DMR &)
Return the bounding box for an array.
Definition: RoiFunction.cc:186
unsigned int roi_valid_bbox(BaseType *btp)
Is the bound box valid?
Definition: roi_utils.cc:90
static class NCMLUtil overview
void function_dap2_roi(int argc, BaseType *argv[], DDS &, BaseType **btpp)
Subset the N arrays using index slicing information.
Definition: RoiFunction.cc:98
#define BESDEBUG(x, y)
macro used to send debug information to the debug stream
Definition: BESDebug.h:64