bes  Updated for version 3.17.0
RoiFunction.cc
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 #include <roi_util.h>
46 
47 #include "RoiFunction.h"
48 #include "functions_util.h"
49 
50 using namespace std;
51 using namespace libdap;
52 
53 namespace functions {
54 
76 void
77 function_dap2_roi(int argc, BaseType *argv[], DDS &, BaseType **btpp)
78 {
79  const string wrong_args = "Wrong number of arguments to roi(). Expected one or more Arrays and bounding box";
80 
81  // This is the rank of the Array of Slices, not the N-1 arrays to be sliced
82  int rank = 0;
83 
84  switch (argc) {
85  case 0:
86  case 1:
87  // Must have 2 or more arguments
88  throw Error(malformed_expr, wrong_args);
89  default:
90  rank = roi_valid_bbox(argv[argc-1]); // throws if slice is not valid
91 
92  for (int i = 0; i < argc-1; ++i)
93  check_number_type_array(argv[i], rank); // throws if array is not valid
94  break;
95  }
96 
97  auto_ptr<Structure> response(new Structure("roi_subset"));
98 
99  Array *bbox = static_cast<Array*>(argv[argc-1]);
100 
101  for (int i = 0; i < argc-1; ++i) {
102  // cast is safe given the above
103  Array *the_array = static_cast<Array*>(argv[i]);
104  BESDEBUG("roi", "the_array: " << the_array->name() << ": " << (void*)the_array << endl);
105 
106  // For each dimension of the array, apply the slice constraint.
107  // Assume Array[]...[][X][Y] where the slice has dims X and Y
108  // So find the last <rank> dimensions and check that their names
109  // match those of the slice. This loops 'walks backward' over
110  // both the N bbox slices and the right-most N dimensions of
111  // the arrays.
112 
113  unsigned int num_dims = the_array->dimensions();
114  int d = num_dims-1;
115  for (int i = rank-1; i >= 0; --i) {
116  int start, stop;
117  string name;
118  // start, stop, name are value-result parameters
119  roi_bbox_get_slice_data(bbox, i, start, stop, name);
120 
121  // Hack, should use reverse iterators, but Array does not have them
122  Array::Dim_iter iter = the_array->dim_begin() + d;
123 
124  // TODO Make this an option (i.e., turn off the test)?
125  // TODO Make a second option that will match names instead of position
126  if (the_array->dimension_name(iter) != name)
127  throw Error("In function roi(): Dimension name (" + the_array->dimension_name(iter) + ") and slice name (" + name + ") don't match");
128 
129  // TODO Add stride option?
130  BESDEBUG("roi", "Dimension: " << i << ", Start: " << start << ", Stop: " << stop << endl);
131  the_array->add_constraint(iter, start, 1 /*stride*/, stop);
132  --d;
133  }
134 
135  // Add the array to the Structure returned by the function
136  the_array->set_send_p(true); // include it
137 
138  // TODO Why do we have to force this read? The libdap::BaseType::serialize()
139  // code should take care of it, but in the debugger the read_p property is
140  // showing up as true. jhrg 2/26/15 Hack and move on...
141  //if (!the_array->read_p())
142  the_array->set_read_p(false);
143  the_array->read();
144  the_array->set_read_p(true);
145 
146  response->add_var(the_array);
147  }
148 
149  response->set_send_p(true);
150  response->set_read_p(true);
151 
152  *btpp = response.release();
153  return;
154 }
155 
165 BaseType *function_dap4_roi(D4RValueList *, DMR &)
166 {
167  throw Error(malformed_expr, "Not yet implemented for DAP4 functions.");
168 
169  return 0;
170 }
171 
172 } // namesspace functions
STL namespace.