bes  Updated for version 3.20.6
HDFGrid.cc
1 // This file is part of the hdf4 data handler for the OPeNDAP data server.
2 
3 // Copyright (c) 2005 OPeNDAP, Inc.
4 // Author: James Gallagher <jgallagher@opendap.org>
5 //
6 // This is free software; you can redistribute it and/or modify it under the
7 // terms of the GNU Lesser General Public License as published by the Free
8 // Software Foundation; either version 2.1 of the License, or (at your
9 // option) any later version.
10 //
11 // This software is distributed in the hope that it will be useful, but
12 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 // License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public License
17 // along with this software; if not, write to the Free Software Foundation,
18 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 //
20 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
21 
23 // Copyright 1996, by the California Institute of Technology.
24 // ALL RIGHTS RESERVED. United States Government Sponsorship
25 // acknowledged. Any commercial use must be negotiated with the
26 // Office of Technology Transfer at the California Institute of
27 // Technology. This software may be subject to U.S. export control
28 // laws and regulations. By accepting this software, the user
29 // agrees to comply with all applicable U.S. export laws and
30 // regulations. User has the responsibility to obtain export
31 // licenses, or other export authority as may be required before
32 // exporting such information to foreign countries or providing
33 // access to foreign persons.
34 
35 // Author: Todd Karakashian, NASA/Jet Propulsion Laboratory
36 // Todd.K.Karakashian@jpl.nasa.gov
37 //
39 
40 #include "config_hdf.h"
41 
42 #include <vector>
43 // Include this on linux to suppres an annoying warning about multiple
44 // definitions of MIN and MAX.
45 #ifdef HAVE_SYS_PARAM_H
46 #include <sys/param.h>
47 #endif
48 #include <mfhdf.h>
49 #include <hdfclass.h>
50 #include <hcstream.h>
51 
52 #include <Error.h>
53 #include <InternalErr.h>
54 #include <debug.h>
55 #include <escaping.h>
56 
57 #include <BESDebug.h>
58 
59 #include "HDFGrid.h"
60 #include "HDFArray.h"
61 #include "hdfutil.h"
62 
63 using namespace libdap;
64 using namespace std;
65 
66 HDFGrid::HDFGrid(const string &n, const string &d) :
67  Grid(n, d) {
68 }
69 
70 HDFGrid::~HDFGrid() {
71 }
72 BaseType *HDFGrid::ptr_duplicate() {
73  return new HDFGrid(*this);
74 }
75 
76 void LoadGridFromSDS(HDFGrid * gr, const hdf_sds & sds);
77 
78 // Build a vector of array_ce structs. This holds the constraint
79 // information *for each map* of the Grid.
80 vector<array_ce> HDFGrid::get_map_constraints() {
81  vector<array_ce> a_ce_vec;
82 
83  // Load the array_ce vector with info about each map vector.
84  for (Grid::Map_iter p = map_begin(); p != map_end(); ++p) {
85  Array & a = static_cast<Array &> (**p);
86  Array::Dim_iter q = a.dim_begin(); // maps have only one dimension.
87  int start = a.dimension_start(q, true);
88  int stop = a.dimension_stop(q, true);
89  int stride = a.dimension_stride(q, true);
90  int edge = (int) ((stop - start) / stride) + 1;
91  array_ce a_ce(a.name(), start, edge, stride);
92  a_ce_vec.push_back(a_ce);
93  }
94 
95  return a_ce_vec;
96 }
97 
98 // Read in a Grid from an SDS in an HDF file.
99 bool HDFGrid::read() {
100  int err = 0;
101  int status = read_tagref(-1, -1, err);
102  if (err)
103  throw Error(unknown_error, "Could not read from dataset.");
104  return status;
105 }
106 
107 bool HDFGrid::read_tagref(int32, int32 ref, int &err) {
108  if (read_p())
109  return true;
110 
111  err = 0; // OK initially
112 
113  string hdf_file = dataset();
114  string hdf_name = this->name();
115 
116  hdf_sds sds;
117 
118  // read in SDS
119  hdfistream_sds sdsin(hdf_file.c_str());
120  try {
121  vector<int> start;
122  vector<int> edge;
123  vector<int> stride;
124  HDFArray *primary_array = static_cast<HDFArray *> (array_var());
125  if (!primary_array)
126  throw InternalErr(__FILE__, __LINE__, "Expected an HDFArray.");
127 
128  bool isslab = primary_array->GetSlabConstraint(start, edge, stride);
129 
130  // get slab constraint from primary array
131  if (isslab)
132  sdsin.setslab(start, edge, stride, false);
133 
134  // get the constraints on each map
135  sdsin.set_map_ce(get_map_constraints());
136 
137  if (ref != -1)
138  sdsin.seek_ref(ref);
139  else
140  sdsin.seek(hdf_name.c_str());
141 
142  // If we read the array, we also read the maps. 2/3/2002 jhrg
143  if (array_var()->send_p() || array_var()->is_in_selection()) {
144  sdsin >> sds;
145  if (!sds) {
146  throw Error(
147  string("Could not read ") + array_var()->name()
148  + string(" from dataset ") + dataset()
149  + string("."));
150  }
151 
152  LoadGridFromSDS(this, sds); // load data into primary array
153  }
154  // load map data. There's little point in checking if the maps really
155  // need to be read. If the array was read, chances are good and the
156  // map vectors are much smaller. If the array was not read, then some
157  // map must be marked to be sent or we wouldn't be here. So just load
158  // the maps...
159 
160  // Read only if not above. sdsin >> hdf_sds also reads the maps so we
161  // should read here only if we didn't read above.
162  if (!(array_var()->send_p() || array_var()->is_in_selection())) {
163  // This initialization is done by hdfistream_sds op>>(hdf_sds&)
164  // but not hdfistream_sds op>>(hdf_dim&).
165  sds.dims = vector<hdf_dim> ();
166  sds.data = hdf_genvec(); // needed?
167  // sds.ref = SDidtoref(_sds_id);
168  sdsin >> sds.dims;
169  }
170 
171  for (Grid::Map_iter p = map_begin(); p != map_end(); ++p) {
172  if ((*p)->send_p() || (*p)->is_in_selection()) {
173  for (unsigned int i = 0; i < sds.dims.size(); i++) {
174  if ((*p)->name() == sds.dims[i].name) {
175  // Read the data from the sds dimension.
176  char *data = static_cast<char *> (ExportDataForDODS(
177  sds.dims[i].scale));
178  (*p)->val2buf(data);
179  delete[] data;
180  (*p)->set_read_p(true);
181  }
182  }
183  }
184  }
185 
186  sdsin.close();
187  } catch (...) {
188  sdsin.close();
189  err = 1;
190  return false;
191  }
192 
193  return true;
194 }
195 
196 void HDFGrid::transfer_attributes(AttrTable *at) {
197  if (at) {
198  array_var()->transfer_attributes(at);
199 
200  Map_iter map = map_begin();
201  while (map != map_end()) {
202  (*map)->transfer_attributes(at);
203  map++;
204  }
205 
206  AttrTable *mine = at->get_attr_table(name());
207 
208  if (mine) {
209  mine->set_is_global_attribute(false);
210  AttrTable::Attr_iter at_p = mine->attr_begin();
211  while (at_p != mine->attr_end()) {
212  if (mine->get_attr_type(at_p) == Attr_container)
213  get_attr_table().append_container(
214  new AttrTable(*mine->get_attr_table(at_p)),
215  mine->get_name(at_p));
216  else
217  get_attr_table().append_attr(mine->get_name(at_p),
218  mine->get_type(at_p), mine->get_attr_vector(at_p));
219  at_p++;
220  }
221  }
222 
223  // Now look for those pesky <var>_dim_<digit> attributes
224 
225  string dim_name_base = name() + "_dim_";
226 
227  AttrTable::Attr_iter a_p = at->attr_begin();
228  while (a_p != at->attr_end()) {
229  string::size_type i = at->get_name(a_p).find(dim_name_base);
230  // Found a matching container?
231  // See comment in HDFArray::transfer_attributes regarding 'i == 0'
232  // jhrg 8/17/11
233  if (i == 0 && at->get_attr_type(a_p) == Attr_container) {
234  AttrTable *dim = at->get_attr_table(a_p);
235  // Get the integer from the end of the name and use that as the
236  // index to find the matching Map variable.
237  BESDEBUG("h4", "dim->name(): " << dim->get_name() << endl);
238  BESDEBUG("h4", "dim->get_name().substr(i + dim_name_base.length()): "
239  << dim->get_name().substr(i + dim_name_base.length()) << endl);
240  int n = atoi(dim->get_name().substr(i + dim_name_base.length()).c_str());
241  // Note that the maps are HDFArray instances, so we use that
242  // for the actual copy operation.
243  BESDEBUG("h4", "Inside HDFGrid::transfer_attreibutes: n = " << n << endl);
244  static_cast<HDFArray&> (*(*(map_begin() + n))).transfer_dimension_attribute(dim);
245  }
246 
247  a_p++;
248  }
249  }
250 }
251 
array_ce
Definition: hdfclass.h:157
HDFGrid
Definition: HDFGrid.h:56
HDFArray
Definition: HDFArray.h:55
hdf_sds
Definition: hdfclass.h:179
libdap
Definition: BESDapFunctionResponseCache.h:35
hdfistream_sds
Definition: hcstream.h:84
hdf_genvec
Definition: hdfclass.h:71
Error