OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
HDF5GMCFMissLLArray.cc
Go to the documentation of this file.
1 // This file is part of the hdf5_handler implementing for the CF-compliant
2 // Copyright (c) 2011-2013 The HDF Group, Inc. and OPeNDAP, Inc.
3 //
4 // This is free software; you can redistribute it and/or modify it under the
5 // terms of the GNU Lesser General Public License as published by the Free
6 // Software Foundation; either version 2.1 of the License, or (at your
7 // option) any later version.
8 //
9 // This software is distributed in the hope that it will be useful, but
10 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
12 // License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 //
18 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
19 // You can contact The HDF Group, Inc. at 1800 South Oak Street,
20 // Suite 203, Champaign, IL 61820
21 
31 
32 #include "config_hdf5.h"
33 #include <iostream>
34 #include <sstream>
35 #include <cassert>
36 #include <debug.h>
37 #include "InternalErr.h"
38 #include <BESDebug.h>
39 
40 #include "HDF5GMCFMissLLArray.h"
41 
42 
43 
45 {
46  return new HDF5GMCFMissLLArray(*this);
47 }
48 
50 {
51 
52  BESDEBUG("h5","Coming to HDF5GMCFMissLLArray read "<<endl);
53  // Here we still use vector just in case we need to tackle "rank>1" in the future.
54  // Also we would like to keep it consistent with other similar handlings.
55 
56  vector<int>offset;
57  vector<int>count;
58  vector<int>step;
59 
60  offset.resize(rank);
61  count.resize(rank);
62  step.resize(rank);
63 
64  int nelms = format_constraint (&offset[0], &step[0], &count[0]);
65 
66  if (GPMM_L3 == product_type || GPMS_L3 == product_type)
67  obtain_gpm_l3_ll(&offset[0],&step[0],nelms);
68  else if (Aqu_L3 == product_type || OBPG_L3 == product_type) // Aquarious level 3
69  obtain_aqu_obpg_l3_ll(&offset[0],&step[0],nelms);
70 
71  return true;
72 }
73 
74 void HDF5GMCFMissLLArray::obtain_aqu_obpg_l3_ll(int* offset,int* step,int nelms) {
75 
76  // Read File attributes
77  // Latitude Step, SW Point Latitude, Number of Lines
78  // Longitude Step, SW Point Longitude, Number of Columns
79 
80  if (1 != rank )
81  throw InternalErr (__FILE__, __LINE__,
82  "The number of dimension for Aquarius Level 3 map data must be 1");
83 
84  string check_pass_fileid_key_str="H5.EnablePassFileID";
85  bool check_pass_fileid_key = false;
86  check_pass_fileid_key = HDF5CFDAPUtil::check_beskeys(check_pass_fileid_key_str);
87  if(false == check_pass_fileid_key) {
88  if ((fileid = H5Fopen(filename.c_str(),H5F_ACC_RDONLY,H5P_DEFAULT))<0) {
89  ostringstream eherr;
90  eherr << "HDF5 File " << filename
91  << " cannot be opened. "<<endl;
92  throw InternalErr (__FILE__, __LINE__, eherr.str ());
93  }
94  }
95 
96  hid_t rootid = -1;
97  if ((rootid = H5Gopen(fileid,"/",H5P_DEFAULT)) < 0) {
98  // H5Fclose(fileid);
99  HDF5CFUtil::close_fileid(fileid,check_pass_fileid_key);
100  ostringstream eherr;
101  eherr << "HDF5 dataset " << varname
102  << " cannot be opened. "<<endl;
103  throw InternalErr (__FILE__, __LINE__, eherr.str ());
104  }
105 
106  float LL_first_point = 0.0;
107  float LL_step = 0.0;
108  int LL_total_num = 0;
109 
110  if (CV_LAT_MISS == cvartype) {
111  string Lat_SWP_name =(Aqu_L3 == product_type)?"SW Point Latitude":"sw_point_latitude";
112  string Lat_step_name =(Aqu_L3== product_type)?"Latitude Step":"latitude_step";
113  string Num_lines_name =(Aqu_L3== product_type)?"Number of Lines":"number_of_lines";
114  float Lat_SWP = 0.0;
115  float Lat_step = 0.0;
116  int Num_lines = 0;
117  vector<char> dummy_str;
118 
119  obtain_ll_attr_value(fileid,rootid,Lat_SWP_name,Lat_SWP,dummy_str);
120  obtain_ll_attr_value(fileid,rootid,Lat_step_name,Lat_step,dummy_str);
121  obtain_ll_attr_value(fileid,rootid,Num_lines_name,Num_lines,dummy_str);
122  // STOP
123  if (Num_lines <= 0) {
124  H5Gclose(rootid);
125  HDF5CFUtil::close_fileid(fileid,check_pass_fileid_key);
126  //H5Fclose(fileid);
127  throw InternalErr(__FILE__,__LINE__,"The number of line must be >0");
128  }
129 
130  // The first number of the latitude is at the north west corner
131  LL_first_point = Lat_SWP + (Num_lines -1)*Lat_step;
132  LL_step = Lat_step *(-1.0);
133  LL_total_num = Num_lines;
134  }
135 
136  if (CV_LON_MISS == cvartype) {
137  string Lon_SWP_name =(Aqu_L3==product_type)?"SW Point Longitude":"sw_point_longitude";
138  string Lon_step_name =(Aqu_L3==product_type)? "Longitude Step":"longitude_step";
139  string Num_columns_name =(Aqu_L3==product_type)? "Number of Columns":"number_of_columns";
140  float Lon_SWP = 0.0;
141  float Lon_step = 0.0;
142  int Num_cols =0;
143 
144  vector<char>dummy_str_value;
145 
146  obtain_ll_attr_value(fileid,rootid,Lon_SWP_name,Lon_SWP,dummy_str_value);
147  obtain_ll_attr_value(fileid,rootid,Lon_step_name,Lon_step,dummy_str_value);
148  obtain_ll_attr_value(fileid,rootid,Num_columns_name,Num_cols,dummy_str_value);
149  if (Num_cols <= 0) {
150  H5Gclose(rootid);
151  HDF5CFUtil::close_fileid(fileid,check_pass_fileid_key);
152  //H5Fclose(fileid);
153  throw InternalErr(__FILE__,__LINE__,"The number of line must be >0");
154  }
155 
156  // The first number of the latitude is at the north west corner
157  LL_first_point = Lon_SWP;
158  LL_step = Lon_step;
159  LL_total_num = Num_cols;
160  }
161 
162  vector<float>val;
163  val.resize(nelms);
164 
165  if (nelms > LL_total_num) {
166  H5Gclose(rootid);
167  HDF5CFUtil::close_fileid(fileid,check_pass_fileid_key);
168  //H5Fclose(fileid);
169  throw InternalErr (__FILE__, __LINE__,
170  "The number of elements exceeds the total number of Latitude or Longitude");
171  }
172 
173  for (int i = 0; i < nelms; ++i)
174  val[i] = LL_first_point + (offset[0] + i*step[0])*LL_step;
175 
176  set_value ((dods_float32 *) &val[0], nelms);
177  H5Gclose(rootid);
178  HDF5CFUtil::close_fileid(fileid,check_pass_fileid_key);
179  //H5Fclose(fileid);
180 
181 }
182 
183 void HDF5GMCFMissLLArray::obtain_gpm_l3_ll(int* offset,int* step,int nelms) {
184 
185  if (1 != rank )
186  throw InternalErr (__FILE__, __LINE__,
187  "The number of dimension for Aquarius Level 3 map data must be 1");
188 
189  string check_pass_fileid_key_str="H5.EnablePassFileID";
190  bool check_pass_fileid_key = false;
191  check_pass_fileid_key = HDF5CFDAPUtil::check_beskeys(check_pass_fileid_key_str);
192 
193  if(false == check_pass_fileid_key) {
194  if ((fileid = H5Fopen(filename.c_str(),H5F_ACC_RDONLY,H5P_DEFAULT))<0) {
195  ostringstream eherr;
196  eherr << "HDF5 File " << filename
197  << " cannot be opened. "<<endl;
198  throw InternalErr (__FILE__, __LINE__, eherr.str ());
199  }
200  }
201 
202  hid_t grid_grp_id = -1;
203 
204  string grid_grp_name;
205  //string sub_grp1_name, sub_grp2_name;
206  // GPMDPR: update grid_group_name.
207 // cerr<<"name is "<<name <<endl;
208  if((name() == "nlat") || (name() == "nlon")) {
209  string temp_grid_grp_name(GPM_GRID_GROUP_NAME1,strlen(GPM_GRID_GROUP_NAME1));
210  temp_grid_grp_name = "/" + temp_grid_grp_name;
211  if(H5Lexists(fileid,temp_grid_grp_name.c_str(),H5P_DEFAULT) >0)
212  grid_grp_name = temp_grid_grp_name;
213  else {
214  string temp_grid_grp_name2(GPM_GRID_GROUP_NAME2,strlen(GPM_GRID_GROUP_NAME2));
215  temp_grid_grp_name2 = "/"+temp_grid_grp_name2;
216  if(H5Lexists(fileid,temp_grid_grp_name2.c_str(),H5P_DEFAULT) >0)
217  grid_grp_name = temp_grid_grp_name2;
218  else
219  throw InternalErr (__FILE__, __LINE__,"Unknown GPM grid group name ");
220 
221  }
222  }
223 
224  else {
225  string temp_grids_group_name(GPM_GRID_MULTI_GROUP_NAME,strlen(GPM_GRID_MULTI_GROUP_NAME));
226  if(name() == "lnH" || name() == "ltH")
227  grid_grp_name = temp_grids_group_name + "/G2" ;
228  else if(name() == "lnL" || name() == "ltL")
229  grid_grp_name = temp_grids_group_name + "/G1" ;
230  }
231 // varname is supposed to include the full path. However, it takes too much effort to obtain the full path
232 // for a created coordiate variable based on the dimension name only. Since GPM has a fixed group G1
233 // for lnL and ltL and another fixed group G2 for lnH and ltH. We just use these names. These information
234 // is from GPM file specification.
235 #if 0
236  if(name() == "lnH" || name() == "ltH" ||
237  name() == "lnL" || name() == "ltL") {
238  string temp_grids_group_name(GPM_GRID_MULTI_GROUP_NAME,strlen(GPM_GRID_MULTI_GROUP_NAME));
239 
240 cerr<<"varname is "<<varname <<endl;
241  size_t grids_group_pos = varname.find(temp_grids_group_name);
242  if(string::npos == grids_group_pos) {
243  throw InternalErr (__FILE__, __LINE__,
244  "Cannot find group Grids.");
245  }
246 
247  string grids_cgroup_path = varname.substr(grids_group_pos+1);
248  size_t grids_cgroup_pos = varname.find_first_of("/");
249  if(string::npos == grids_cgroup_pos) {
250  throw InternalErr (__FILE__, __LINE__,
251  "Cannot find child group of group Grids.");
252  }
253 
254  string temp_sub_grp_name = grids_cgroup_path.substr(0,grids_cgroup_pos);
255  if(name() == "lnH" || name() == "ltH")
256  sub_grp1_name = temp_sub_grp_name;
257  else if(name() == "lnL" || name() == "ltL")
258  sub_grp2_name = temp_sub_grp_name;
259 
260  grid_grp_name = temp_grids_group_name + "/" + temp_sub_grp_name;
261 
262  }
263 #endif
264 
265  if ((grid_grp_id = H5Gopen(fileid,grid_grp_name.c_str(),H5P_DEFAULT)) < 0) {
266  HDF5CFUtil::close_fileid(fileid,check_pass_fileid_key);
267  ostringstream eherr;
268  eherr << "HDF5 dataset " << varname
269  << " cannot be opened. "<<endl;
270  throw InternalErr (__FILE__, __LINE__, eherr.str ());
271  }
272 
273  // GPMDPR: update grid_info_name.
274  string grid_info_name(GPM_ATTR2_NAME,strlen(GPM_ATTR2_NAME));
275  if(name() == "lnL" || name() == "ltL")
276  grid_info_name = "G1_" + grid_info_name;
277  else if(name() == "lnH" || name() == "ltH")
278  grid_info_name = "G2_" + grid_info_name;
279 
280  vector<char> grid_info_value;
281  float dummy_value = 0.0;
282  try {
283  obtain_ll_attr_value(fileid,grid_grp_id,grid_info_name,dummy_value,grid_info_value);
284  }
285  catch(...) {
286  HDF5CFUtil::close_fileid(fileid,check_pass_fileid_key);
287  throw;
288 
289  }
290 
291  float lat_start = 0;;
292  float lon_start = 0.;
293  float lat_res = 0.;
294  float lon_res = 0.;
295 
296  int latsize = 0;
297  int lonsize = 0;
298 
299  //vector<char> info_value(grid_info_value.begin(),grid_info_value.end());
300  HDF5CFUtil::parser_gpm_l3_gridheader(grid_info_value,latsize,lonsize,
301  lat_start,lon_start,lat_res,lon_res,false);
302 
303  if(0 == latsize || 0 == lonsize) {
304  HDF5CFUtil::close_fileid(fileid,check_pass_fileid_key);
305  throw InternalErr (__FILE__, __LINE__, "Either latitude or longitude size is 0. ");
306  }
307 
308  vector<float>val;
309  val.resize(nelms);
310 
311  if(CV_LAT_MISS == cvartype) {
312 
313  if(nelms > latsize) {
314  H5Gclose(grid_grp_id);
315  HDF5CFUtil::close_fileid(fileid,check_pass_fileid_key);
316  //H5Fclose(fileid);
317  throw InternalErr (__FILE__, __LINE__,
318  "The number of elements exceeds the total number of Latitude ");
319 
320  }
321  for (int i = 0; i < nelms; ++i)
322  val[i] = lat_start+offset[0]*lat_res+lat_res/2 + i*lat_res*step[0];
323  }
324  else if(CV_LON_MISS == cvartype) {
325 
326  if(nelms > lonsize) {
327  H5Gclose(grid_grp_id);
328  HDF5CFUtil::close_fileid(fileid,check_pass_fileid_key);
329  //H5Fclose(fileid);
330  throw InternalErr (__FILE__, __LINE__,
331  "The number of elements exceeds the total number of Longitude");
332 
333  }
334 
335  for (int i = 0; i < nelms; ++i)
336  val[i] = lon_start+offset[0]*lon_res+lon_res/2 + i*lon_res*step[0];
337  }
338 
339  set_value ((dods_float32 *) &val[0], nelms);
340 
341  H5Gclose(grid_grp_id);
342  HDF5CFUtil::close_fileid(fileid,check_pass_fileid_key);
343 
344 #if 0
345 
346 
347  vector<float>val;
348  val.resize(nelms);
349 
350  if (nelms > LL_total_num) {
351  H5Gclose(rootid);
352  //H5Fclose(fileid);
353  throw InternalErr (__FILE__, __LINE__,
354  "The number of elements exceeds the total number of Latitude or Longitude");
355  }
356 
357  for (int i = 0; i < nelms; ++i)
358  val[i] = LL_first_point + (offset[0] + i*step[0])*LL_step;
359 
360  set_value ((dods_float32 *) &val[0], nelms);
361  H5Gclose(rootid);
362  //H5Fclose(fileid);
363 #endif
364 
365 }
366 //template<class T>
367 template<typename T>
368 void HDF5GMCFMissLLArray::obtain_ll_attr_value(hid_t file_id, hid_t s_root_id,
369  const string & s_attr_name, T& attr_value,
370  vector<char> & str_attr_value) {
371 
372  hid_t s_attr_id = -1;
373  if ((s_attr_id = H5Aopen_by_name(s_root_id,".",s_attr_name.c_str(),
374  H5P_DEFAULT, H5P_DEFAULT)) <0) {
375  string msg = "Cannot open the HDF5 attribute ";
376  msg += s_attr_name;
377  H5Gclose(s_root_id);
378  //H5Fclose(file_id);
379  throw InternalErr(__FILE__, __LINE__, msg);
380  }
381 
382  hid_t attr_type = -1;
383  if ((attr_type = H5Aget_type(s_attr_id)) < 0) {
384  string msg = "cannot get the attribute datatype for the attribute ";
385  msg += s_attr_name;
386  H5Aclose(s_attr_id);
387  H5Gclose(s_root_id);
388  //H5Fclose(file_id);
389  throw InternalErr(__FILE__, __LINE__, msg);
390  }
391 
392  hid_t attr_space = -1;
393  if ((attr_space = H5Aget_space(s_attr_id)) < 0) {
394  string msg = "cannot get the hdf5 dataspace id for the attribute ";
395  msg += s_attr_name;
396  H5Tclose(attr_type);
397  H5Aclose(s_attr_id);
398  H5Gclose(s_root_id);
399  //H5Fclose(file_id);
400  throw InternalErr(__FILE__, __LINE__, msg);
401  }
402 
403  int num_elm = H5Sget_simple_extent_npoints(attr_space);
404 
405  if (0 == num_elm ) {
406  string msg = "cannot get the number for the attribute ";
407  msg += s_attr_name;
408  H5Tclose(attr_type);
409  H5Aclose(s_attr_id);
410  H5Sclose(attr_space);
411  H5Gclose(s_root_id);
412  //H5Fclose(file_id);
413  throw InternalErr(__FILE__, __LINE__, msg);
414  }
415 
416  if (1 != num_elm) {
417  string msg = "The number of attribute must be 1 for Aquarius level 3 data ";
418  msg += s_attr_name;
419  H5Tclose(attr_type);
420  H5Aclose(s_attr_id);
421  H5Sclose(attr_space);
422  H5Gclose(s_root_id);
423  //H5Fclose(file_id);
424  throw InternalErr(__FILE__, __LINE__, msg);
425  }
426 
427 
428  size_t atype_size = H5Tget_size(attr_type);
429  if (atype_size <= 0) {
430  string msg = "cannot obtain the datatype size of the attribute ";
431  msg += s_attr_name;
432  H5Tclose(attr_type);
433  H5Aclose(s_attr_id);
434  H5Sclose(attr_space);
435  H5Gclose(s_root_id);
436  //H5Fclose(file_id);
437  throw InternalErr(__FILE__, __LINE__, msg);
438  }
439 
440  if(H5T_STRING == H5Tget_class(attr_type)) {
441  if(H5Tis_variable_str(attr_type)) {
442  H5Tclose(attr_type);
443  H5Aclose(s_attr_id);
444  H5Sclose(attr_space);
445  H5Gclose(s_root_id);
446  throw InternalErr(__FILE__,__LINE__,
447  "Currently we assume the attributes we use to retrieve lat and lon are NOT variable length string.");
448  }
449  else {
450  str_attr_value.resize(atype_size);
451  if (H5Aread(s_attr_id,attr_type, &str_attr_value[0])<0){
452  string msg = "cannot retrieve the value of the attribute ";
453  msg += s_attr_name;
454  H5Tclose(attr_type);
455  H5Aclose(s_attr_id);
456  H5Sclose(attr_space);
457  H5Gclose(s_root_id);
458  //H5Fclose(file_id);
459  throw InternalErr(__FILE__, __LINE__, msg);
460 
461  }
462  }
463  }
464 
465  else if (H5Aread(s_attr_id,attr_type, &attr_value)<0){
466  string msg = "cannot retrieve the value of the attribute ";
467  msg += s_attr_name;
468  H5Tclose(attr_type);
469  H5Aclose(s_attr_id);
470  H5Sclose(attr_space);
471  H5Gclose(s_root_id);
472  //H5Fclose(file_id);
473  throw InternalErr(__FILE__, __LINE__, msg);
474 
475  }
476 
477  H5Tclose(attr_type);
478  H5Sclose(attr_space);
479  H5Aclose(s_attr_id);
480 }
481 
482 
483 
484 // parse constraint expr. and make hdf5 coordinate point location.
485 // return number of elements to read.
486 int
487 HDF5GMCFMissLLArray::format_constraint (int *offset, int *step, int *count)
488 {
489  long nels = 1;
490  int id = 0;
491 
492  Dim_iter p = dim_begin ();
493 
494  while (p != dim_end ()) {
495 
496  int start = dimension_start (p, true);
497  int stride = dimension_stride (p, true);
498  int stop = dimension_stop (p, true);
499 
500 
501  // Check for illegical constraint
502  if (stride < 0 || start < 0 || stop < 0 || start > stop) {
503  ostringstream oss;
504 
505  oss << "Array/Grid hyperslab indices are bad: [" << start <<
506  ":" << stride << ":" << stop << "]";
507  throw Error (malformed_expr, oss.str ());
508  }
509 
510  // Check for an empty constraint and use the whole dimension if so.
511  if (start == 0 && stop == 0 && stride == 0) {
512  start = dimension_start (p, false);
513  stride = dimension_stride (p, false);
514  stop = dimension_stop (p, false);
515  }
516 
517  offset[id] = start;
518  step[id] = stride;
519  count[id] = ((stop - start) / stride) + 1; // count of elements
520  nels *= count[id]; // total number of values for variable
521 
522  BESDEBUG ("h5",
523  "=format_constraint():"
524  << "id=" << id << " offset=" << offset[id]
525  << " step=" << step[id]
526  << " count=" << count[id]
527  << endl);
528 
529  id++;
530  p++;
531  }
532 
533  return nels;
534 }
535 
This class specifies the retrieval of the missing lat/lon values for general HDF5 products...
static void close_fileid(hid_t, bool)
Definition: HDF5CFUtil.cc:395
static void parser_gpm_l3_gridheader(const std::vector< char > &value, int &latsize, int &lonsize, float &lat_start, float &lon_start, float &lat_res, float &lon_res, bool check_reg_orig)
Definition: HDF5CFUtil.cc:233
static bool check_beskeys(const string key)
Definition: h5cfdaputil.cc:39
virtual BaseType * ptr_duplicate()
HDF5GMCFMissLLArray(int rank, const string &filename, const hid_t fileid, H5DataType dtype, const string &varfullpath, H5GCFProduct product_type, CVType cvartype, const string &n="", BaseType *v=0)
#define BESDEBUG(x, y)
macro used to send debug information to the debug stream
Definition: BESDebug.h:64
int format_constraint(int *cor, int *step, int *edg)