OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
HDFGrid.cc
Go to the documentation of this file.
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 HDFGrid::HDFGrid(const string &n, const string &d) :
64  Grid(n, d) {
65 }
66 
68 }
70  return new HDFGrid(*this);
71 }
72 
73 void LoadGridFromSDS(HDFGrid * gr, const hdf_sds & sds);
74 
75 // Build a vector of array_ce structs. This holds the constraint
76 // information *for each map* of the Grid.
77 vector<array_ce> HDFGrid::get_map_constraints() {
78  vector<array_ce> a_ce_vec;
79 
80  // Load the array_ce vector with info about each map vector.
81  for (Grid::Map_iter p = map_begin(); p != map_end(); ++p) {
82  Array & a = static_cast<Array &> (**p);
83  Array::Dim_iter q = a.dim_begin(); // maps have only one dimension.
84  int start = a.dimension_start(q, true);
85  int stop = a.dimension_stop(q, true);
86  int stride = a.dimension_stride(q, true);
87  int edge = (int) ((stop - start) / stride) + 1;
88  array_ce a_ce(a.name(), start, edge, stride);
89  a_ce_vec.push_back(a_ce);
90  }
91 
92  return a_ce_vec;
93 }
94 
95 // Read in a Grid from an SDS in an HDF file.
96 bool HDFGrid::read() {
97  int err = 0;
98  int status = read_tagref(-1, -1, err);
99  if (err)
100  throw Error(unknown_error, "Could not read from dataset.");
101  return status;
102 }
103 
104 bool HDFGrid::read_tagref(int32, int32 ref, int &err) {
105  if (read_p())
106  return true;
107 
108  err = 0; // OK initially
109 
110  string hdf_file = dataset();
111  string hdf_name = this->name();
112 
113  hdf_sds sds;
114 
115  // read in SDS
116  hdfistream_sds sdsin(hdf_file.c_str());
117  try {
118  vector<int> start, edge, stride;
119  HDFArray *primary_array = static_cast<HDFArray *> (array_var());
120  if (!primary_array)
121  throw InternalErr(__FILE__, __LINE__, "Expected an HDFArray.");
122 
123  bool isslab = primary_array->GetSlabConstraint(start, edge, stride);
124 
125  // get slab constraint from primary array
126  if (isslab)
127  sdsin.setslab(start, edge, stride, false);
128 
129  // get the constraints on each map
130  sdsin.set_map_ce(get_map_constraints());
131 
132  if (ref != -1)
133  sdsin.seek_ref(ref);
134  else
135  sdsin.seek(hdf_name.c_str());
136 
137  // If we read the array, we also read the maps. 2/3/2002 jhrg
138  if (array_var()->send_p() || array_var()->is_in_selection()) {
139  sdsin >> sds;
140  if (!sds) {
141  throw Error(
142  string("Could not read ") + array_var()->name()
143  + string(" from dataset ") + dataset()
144  + string("."));
145  }
146 
147  LoadGridFromSDS(this, sds); // load data into primary array
148  }
149  // load map data. There's little point in checking if the maps really
150  // need to be read. If the array was read, chances are good and the
151  // map vectors are much smaller. If the array was not read, then some
152  // map must be marked to be sent or we wouldn't be here. So just load
153  // the maps...
154 
155  // Read only if not above. sdsin >> hdf_sds also reads the maps so we
156  // should read here only if we didn't read above.
157  if (!(array_var()->send_p() || array_var()->is_in_selection())) {
158  // This initialization is done by hdfistream_sds op>>(hdf_sds&)
159  // but not hdfistream_sds op>>(hdf_dim&).
160  sds.dims = vector<hdf_dim> ();
161  sds.data = hdf_genvec(); // needed?
162  // sds.ref = SDidtoref(_sds_id);
163  sdsin >> sds.dims;
164  }
165 
166  for (Grid::Map_iter p = map_begin(); p != map_end(); ++p) {
167  if ((*p)->send_p() || (*p)->is_in_selection()) {
168  for (unsigned int i = 0; i < sds.dims.size(); i++) {
169  if ((*p)->name() == sds.dims[i].name) {
170  // Read the data from the sds dimension.
171  char *data = static_cast<char *> (ExportDataForDODS(
172  sds.dims[i].scale));
173  (*p)->val2buf(data);
174  delete[] data;
175  (*p)->set_read_p(true);
176  }
177  }
178  }
179  }
180 
181  sdsin.close();
182  } catch (...) {
183  sdsin.close();
184  err = 1;
185  return false;
186  }
187 
188  return true;
189 }
190 
191 void HDFGrid::transfer_attributes(AttrTable *at) {
192  if (at) {
193  array_var()->transfer_attributes(at);
194 
195  Map_iter map = map_begin();
196  while (map != map_end()) {
197  (*map)->transfer_attributes(at);
198  map++;
199  }
200 
201  AttrTable *mine = at->get_attr_table(name());
202 
203  if (mine) {
204  mine->set_is_global_attribute(false);
205  AttrTable::Attr_iter at_p = mine->attr_begin();
206  while (at_p != mine->attr_end()) {
207  if (mine->get_attr_type(at_p) == Attr_container)
208  get_attr_table().append_container(
209  new AttrTable(*mine->get_attr_table(at_p)),
210  mine->get_name(at_p));
211  else
212  get_attr_table().append_attr(mine->get_name(at_p),
213  mine->get_type(at_p), mine->get_attr_vector(at_p));
214  at_p++;
215  }
216  }
217 
218  // Now look for those pesky <var>_dim_<digit> attributes
219 
220  string dim_name_base = name() + "_dim_";
221 
222  AttrTable::Attr_iter a_p = at->attr_begin();
223  while (a_p != at->attr_end()) {
224  string::size_type i = at->get_name(a_p).find(dim_name_base);
225  // Found a matching container?
226  // See comment in HDFArray::transfer_attributes regarding 'i == 0'
227  // jhrg 8/17/11
228  if (i == 0 && at->get_attr_type(a_p) == Attr_container) {
229  AttrTable *dim = at->get_attr_table(a_p);
230  // Get the integer from the end of the name and use that as the
231  // index to find the matching Map variable.
232  BESDEBUG("h4", "dim->name(): " << dim->get_name() << endl);
233  BESDEBUG("h4", "dim->get_name().substr(i + dim_name_base.length()): "
234  << dim->get_name().substr(i + dim_name_base.length()) << endl);
235  int n = atoi(dim->get_name().substr(i + dim_name_base.length()).c_str());
236  // Note that the maps are HDFArray instances, so we use that
237  // for the actual copy operation.
238  BESDEBUG("h4", "Inside HDFGrid::transfer_attreibutes: n = " << n << endl);
239  static_cast<HDFArray&> (*(*(map_begin() + n))).transfer_dimension_attribute(dim);
240  }
241 
242  a_p++;
243  }
244  }
245 }
246 
HDFGrid(const string &n, const string &d)
Definition: HDFGrid.cc:63
vector< hdf_dim > dims
Definition: hdfclass.h:186
bool GetSlabConstraint(vector< int > &start_array, vector< int > &edge_array, vector< int > &stride_array)
Definition: HDFArray.cc:156
virtual bool read_tagref(int32 tag, int32 ref, int &error)
Definition: HDFGrid.cc:104
virtual BaseType * ptr_duplicate()
Definition: HDFGrid.cc:69
hdf_genvec data
Definition: hdfclass.h:187
void * ExportDataForDODS(const hdf_genvec &v)
Definition: hdfutil.cc:50
virtual ~HDFGrid()
Definition: HDFGrid.cc:67
virtual void transfer_attributes(AttrTable *at_container)
Definition: HDFGrid.cc:191
virtual bool read()
Definition: HDFGrid.cc:96
#define BESDEBUG(x, y)
macro used to send debug information to the debug stream
Definition: BESDebug.h:64
void LoadGridFromSDS(HDFGrid *gr, const hdf_sds &sds)
Definition: hc2dap.cc:484
virtual vector< array_ce > get_map_constraints()
Definition: HDFGrid.cc:77