bes  Updated for version 3.20.10
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-2016 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 <BESDebug.h>
37 #include <libdap/InternalErr.h>
38 #include "HDF5RequestHandler.h"
39 #include "HDF5GMCFMissLLArray.h"
40 #include "h5apicompatible.h"
41 
42 using namespace std;
43 using namespace libdap;
44 
45 BaseType *HDF5GMCFMissLLArray::ptr_duplicate()
46 {
47  return new HDF5GMCFMissLLArray(*this);
48 }
49 
50 bool HDF5GMCFMissLLArray::read()
51 {
52 
53  BESDEBUG("h5", "Coming to HDF5GMCFMissLLArray read "<<endl);
54 
55  if (NULL == HDF5RequestHandler::get_lrdata_mem_cache())
56  read_data_NOT_from_mem_cache(false, NULL);
57 
58  else {
59 
60  vector<string> cur_lrd_non_cache_dir_list;
61  HDF5RequestHandler::get_lrd_non_cache_dir_list(cur_lrd_non_cache_dir_list);
62 
63  string cache_key;
64 
65  // Check if this file is included in the non-cache directory
66  if ((cur_lrd_non_cache_dir_list.size() == 0)
67  || ("" == check_str_sect_in_list(cur_lrd_non_cache_dir_list, filename, '/'))) {
68  short cache_flag = 2;
69  vector<string> cur_cache_dlist;
70  HDF5RequestHandler::get_lrd_cache_dir_list(cur_cache_dlist);
71  string cache_dir = check_str_sect_in_list(cur_cache_dlist, filename, '/');
72  if (cache_dir != "") {
73  cache_flag = 3;
74  cache_key = cache_dir + varname;
75  }
76  else
77  cache_key = filename + varname;
78 
79  // Need to obtain the total number of elements.
80  // Obtain dimension size info.
81  vector<size_t> dim_sizes;
82  Dim_iter i_dim = dim_begin();
83  Dim_iter i_enddim = dim_end();
84  while (i_dim != i_enddim) {
85  dim_sizes.push_back(dimension_size(i_dim));
86  ++i_dim;
87  }
88 
89  size_t total_elems = 1;
90  for (unsigned int i = 0; i < dim_sizes.size(); i++)
91  total_elems = total_elems * dim_sizes[i];
92 
93  handle_data_with_mem_cache(dtype, total_elems, cache_flag, cache_key,false);
94  }
95  else
96  read_data_NOT_from_mem_cache(false, NULL);
97  }
98  return true;
99 }
100 
101 // Obtain latitude and longitude for Aquarius and OBPG level 3 products
102 void HDF5GMCFMissLLArray::obtain_aqu_obpg_l3_ll(int* offset, int* step, int nelms, bool add_cache, void* buf)
103 {
104 
105  BESDEBUG("h5", "Coming to obtain_aqu_obpg_l3_ll read "<<endl);
106 
107  // Read File attributes
108  // Latitude Step, SW Point Latitude, Number of Lines
109  // Longitude Step, SW Point Longitude, Number of Columns
110  if (1 != rank)
111  throw InternalErr(__FILE__, __LINE__, "The number of dimension for Aquarius Level 3 map data must be 1");
112 
113  bool check_pass_fileid_key = HDF5RequestHandler::get_pass_fileid();
114  if (false == check_pass_fileid_key) {
115  if ((fileid = H5Fopen(filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) {
116  ostringstream eherr;
117  eherr << "HDF5 File " << filename << " cannot be opened. " << endl;
118  throw InternalErr(__FILE__, __LINE__, eherr.str());
119  }
120  }
121 
122  hid_t rootid = -1;
123  if ((rootid = H5Gopen(fileid, "/", H5P_DEFAULT)) < 0) {
124  HDF5CFUtil::close_fileid(fileid, check_pass_fileid_key);
125  ostringstream eherr;
126  eherr << "HDF5 dataset " << varname << " cannot be opened. " << endl;
127  throw InternalErr(__FILE__, __LINE__, eherr.str());
128  }
129 
130  float LL_first_point = 0.0;
131  float LL_step = 0.0;
132  int LL_total_num = 0;
133 
134  if (CV_LAT_MISS == cvartype) {
135  string Lat_SWP_name = (Aqu_L3 == product_type) ? "SW Point Latitude" : "sw_point_latitude";
136  string Lat_step_name = (Aqu_L3 == product_type) ? "Latitude Step" : "latitude_step";
137  string Num_lines_name = (Aqu_L3 == product_type) ? "Number of Lines" : "number_of_lines";
138  float Lat_SWP = 0.0;
139  float Lat_step = 0.0;
140  int Num_lines = 0;
141  vector<char> dummy_str;
142 
143  obtain_ll_attr_value(fileid, rootid, Lat_SWP_name, Lat_SWP, dummy_str);
144  obtain_ll_attr_value(fileid, rootid, Lat_step_name, Lat_step, dummy_str);
145  obtain_ll_attr_value(fileid, rootid, Num_lines_name, Num_lines, dummy_str);
146  if (Num_lines <= 0) {
147  H5Gclose(rootid);
148  HDF5CFUtil::close_fileid(fileid, check_pass_fileid_key);
149  throw InternalErr(__FILE__, __LINE__, "The number of line must be >0");
150  }
151 
152  // The first number of the latitude is at the north west corner
153  LL_first_point = (float)(Lat_SWP + (Num_lines - 1) * Lat_step);
154  LL_step = (float)(Lat_step * (-1.0));
155  LL_total_num = Num_lines;
156  }
157 
158  if (CV_LON_MISS == cvartype) {
159 
160  string Lon_SWP_name = (Aqu_L3 == product_type) ? "SW Point Longitude" : "sw_point_longitude";
161  string Lon_step_name = (Aqu_L3 == product_type) ? "Longitude Step" : "longitude_step";
162  string Num_columns_name = (Aqu_L3 == product_type) ? "Number of Columns" : "number_of_columns";
163  float Lon_SWP = 0.0;
164  float Lon_step = 0.0;
165  int Num_cols = 0;
166 
167  vector<char> dummy_str_value;
168 
169  obtain_ll_attr_value(fileid, rootid, Lon_SWP_name, Lon_SWP, dummy_str_value);
170  obtain_ll_attr_value(fileid, rootid, Lon_step_name, Lon_step, dummy_str_value);
171  obtain_ll_attr_value(fileid, rootid, Num_columns_name, Num_cols, dummy_str_value);
172  if (Num_cols <= 0) {
173  H5Gclose(rootid);
174  HDF5CFUtil::close_fileid(fileid, check_pass_fileid_key);
175  throw InternalErr(__FILE__, __LINE__, "The number of line must be >0");
176  }
177 
178  // The first number of the latitude is at the north west corner
179  LL_first_point = Lon_SWP;
180  LL_step = Lon_step;
181  LL_total_num = Num_cols;
182  }
183 
184  vector<float> val;
185  val.resize(nelms);
186 
187  if (nelms > LL_total_num) {
188  H5Gclose(rootid);
189  HDF5CFUtil::close_fileid(fileid, check_pass_fileid_key);
190  throw InternalErr(__FILE__, __LINE__,
191  "The number of elements exceeds the total number of Latitude or Longitude");
192  }
193 
194  for (int i = 0; i < nelms; ++i)
195  val[i] = LL_first_point + (offset[0] + i * step[0]) * LL_step;
196 
197  if (true == add_cache) {
198  vector<float> total_val;
199  total_val.resize(LL_total_num);
200  for (int total_i = 0; total_i < LL_total_num; total_i++)
201  total_val[total_i] = LL_first_point + total_i * LL_step;
202  memcpy(buf, &total_val[0], 4 * LL_total_num);
203  }
204 
205  set_value((dods_float32 *) &val[0], nelms);
206  H5Gclose(rootid);
207  HDF5CFUtil::close_fileid(fileid, check_pass_fileid_key);
208 }
209 
210 // Obtain lat/lon for GPM level 3 products
211 void HDF5GMCFMissLLArray::obtain_gpm_l3_ll(int* offset, int* step, int nelms, bool add_cache, void*buf)
212 {
213 
214  if (1 != rank)
215  throw InternalErr(__FILE__, __LINE__, "The number of dimension for GPM Level 3 map data must be 1");
216 
217  bool check_pass_fileid_key = HDF5RequestHandler::get_pass_fileid();
218 
219  if (false == check_pass_fileid_key) {
220  if ((fileid = H5Fopen(filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) {
221  ostringstream eherr;
222  eherr << "HDF5 File " << filename << " cannot be opened. " << endl;
223  throw InternalErr(__FILE__, __LINE__, eherr.str());
224  }
225  }
226 
227  vector<char> grid_info_value;
228  float lat_start = 0;
229  float lon_start = 0.;
230  float lat_res = 0.;
231  float lon_res = 0.;
232 
233  int latsize = 0;
234  int lonsize = 0;
235 
236 
237  if(GPMM_L3 == product_type || GPMS_L3 == product_type) {
238  hid_t grid_grp_id = -1;
239  string grid_grp_name;
240 
241  if ((name() == "nlat") || (name() == "nlon")) {
242 
243  string temp_grid_grp_name(GPM_GRID_GROUP_NAME1, strlen(GPM_GRID_GROUP_NAME1));
244  temp_grid_grp_name = "/" + temp_grid_grp_name;
245  if (H5Lexists(fileid, temp_grid_grp_name.c_str(), H5P_DEFAULT) > 0)
246  grid_grp_name = temp_grid_grp_name;
247  else {
248  string temp_grid_grp_name2(GPM_GRID_GROUP_NAME2, strlen(GPM_GRID_GROUP_NAME2));
249  temp_grid_grp_name2 = "/" + temp_grid_grp_name2;
250  if (H5Lexists(fileid, temp_grid_grp_name2.c_str(), H5P_DEFAULT) > 0)
251  grid_grp_name = temp_grid_grp_name2;
252  else
253  throw InternalErr(__FILE__, __LINE__, "Unknown GPM grid group name ");
254 
255  }
256  }
257 
258  else {
259  string temp_grids_group_name(GPM_GRID_MULTI_GROUP_NAME, strlen(GPM_GRID_MULTI_GROUP_NAME));
260  if (name() == "lnH" || name() == "ltH")
261  grid_grp_name = temp_grids_group_name + "/G2";
262  else if (name() == "lnL" || name() == "ltL") grid_grp_name = temp_grids_group_name + "/G1";
263  }
264 // varname is supposed to include the full path. However, it takes too much effort to obtain the full path
265 // for a created coordiate variable based on the dimension name only. Since GPM has a fixed group G1
266 // for lnL and ltL and another fixed group G2 for lnH and ltH. We just use these names. These information
267 // is from GPM file specification.
268 #if 0
269  if(name() == "lnH" || name() == "ltH" ||
270  name() == "lnL" || name() == "ltL") {
271  string temp_grids_group_name(GPM_GRID_MULTI_GROUP_NAME,strlen(GPM_GRID_MULTI_GROUP_NAME));
272 
273 //cerr<<"varname is "<<varname <<endl;
274  size_t grids_group_pos = varname.find(temp_grids_group_name);
275  if(string::npos == grids_group_pos) {
276  throw InternalErr (__FILE__, __LINE__,
277  "Cannot find group Grids.");
278  }
279 
280  string grids_cgroup_path = varname.substr(grids_group_pos+1);
281  size_t grids_cgroup_pos = varname.find_first_of("/");
282  if(string::npos == grids_cgroup_pos) {
283  throw InternalErr (__FILE__, __LINE__,
284  "Cannot find child group of group Grids.");
285  }
286 
287  string temp_sub_grp_name = grids_cgroup_path.substr(0,grids_cgroup_pos);
288  if(name() == "lnH" || name() == "ltH")
289  sub_grp1_name = temp_sub_grp_name;
290  else if(name() == "lnL" || name() == "ltL")
291  sub_grp2_name = temp_sub_grp_name;
292 
293  grid_grp_name = temp_grids_group_name + "/" + temp_sub_grp_name;
294 
295  }
296 #endif
297 
298  if ((grid_grp_id = H5Gopen(fileid, grid_grp_name.c_str(), H5P_DEFAULT)) < 0) {
299  HDF5CFUtil::close_fileid(fileid, check_pass_fileid_key);
300  ostringstream eherr;
301  eherr << "HDF5 dataset " << varname << " cannot be opened. " << endl;
302  throw InternalErr(__FILE__, __LINE__, eherr.str());
303  }
304 
305  // GPMDPR: update grid_info_name.
306  string grid_info_name(GPM_ATTR2_NAME, strlen(GPM_ATTR2_NAME));
307  if (name() == "lnL" || name() == "ltL")
308  grid_info_name = "G1_" + grid_info_name;
309  else if (name() == "lnH" || name() == "ltH") grid_info_name = "G2_" + grid_info_name;
310 
311  float dummy_value = 0.0;
312  try {
313  obtain_ll_attr_value(fileid, grid_grp_id, grid_info_name, dummy_value, grid_info_value);
314  HDF5CFUtil::parser_gpm_l3_gridheader(grid_info_value, latsize, lonsize, lat_start, lon_start, lat_res, lon_res,
315  false);
316 
317  H5Gclose(grid_grp_id);
318  }
319  catch (...) {
320  H5Gclose(grid_grp_id);
321  H5Fclose(fileid);
322  throw;
323 
324  }
325 
326 
327 }
328  else {
329  vector<char> grid_info_value1;
330  vector<char> grid_info_value2;
331  obtain_gpm_l3_new_grid_info(fileid,grid_info_value1,grid_info_value2);
332  obtain_lat_lon_info(grid_info_value1,grid_info_value2,latsize,lonsize,lat_start,lon_start,lat_res,lon_res);
333  }
334 
335  HDF5CFUtil::close_fileid(fileid, check_pass_fileid_key);
336 
337  try {
338  send_gpm_l3_ll_to_dap(latsize,lonsize,lat_start,lon_start,lat_res,lon_res,offset,step,nelms,add_cache, buf);
339  }
340  catch (...) {
341  throw;
342  }
343 #if 0
344  float lat_start = 0;
345  float lon_start = 0.;
346  float lat_res = 0.;
347  float lon_res = 0.;
348 
349  int latsize = 0;
350  int lonsize = 0;
351 
352  HDF5CFUtil::parser_gpm_l3_gridheader(grid_info_value, latsize, lonsize, lat_start, lon_start, lat_res, lon_res,
353  false);
354 
355  if (0 == latsize || 0 == lonsize) {
356  HDF5CFUtil::close_fileid(fileid, check_pass_fileid_key);
357  throw InternalErr(__FILE__, __LINE__, "Either latitude or longitude size is 0. ");
358  }
359 
360  vector<float> val;
361  val.resize(nelms);
362 
363  if (CV_LAT_MISS == cvartype) {
364 
365  if (nelms > latsize) {
366  H5Gclose(grid_grp_id);
367  HDF5CFUtil::close_fileid(fileid, check_pass_fileid_key);
368  throw InternalErr(__FILE__, __LINE__, "The number of elements exceeds the total number of Latitude ");
369 
370  }
371  for (int i = 0; i < nelms; ++i)
372  val[i] = lat_start + offset[0] * lat_res + lat_res / 2 + i * lat_res * step[0];
373 
374  if (add_cache == true) {
375  vector<float> total_val;
376  total_val.resize(latsize);
377  for (int total_i = 0; total_i < latsize; total_i++)
378  total_val[total_i] = lat_start + lat_res / 2 + total_i * lat_res;
379  memcpy(buf, &total_val[0], 4 * latsize);
380  }
381  }
382  else if (CV_LON_MISS == cvartype) {
383 
384  if (nelms > lonsize) {
385  H5Gclose(grid_grp_id);
386  HDF5CFUtil::close_fileid(fileid, check_pass_fileid_key);
387  throw InternalErr(__FILE__, __LINE__, "The number of elements exceeds the total number of Longitude");
388 
389  }
390 
391  for (int i = 0; i < nelms; ++i)
392  val[i] = lon_start + offset[0] * lon_res + lon_res / 2 + i * lon_res * step[0];
393 
394  if (add_cache == true) {
395  vector<float> total_val;
396  total_val.resize(lonsize);
397  for (int total_i = 0; total_i < lonsize; total_i++)
398  total_val[total_i] = lon_start + lon_res / 2 + total_i * lon_res;
399  memcpy(buf, &total_val[0], 4 * lonsize);
400  }
401 
402  }
403 
404  set_value((dods_float32 *) &val[0], nelms);
405 
406  H5Gclose(grid_grp_id);
407  HDF5CFUtil::close_fileid(fileid, check_pass_fileid_key);
408 #endif
409 
410 #if 0
411 
412  vector<float>val;
413  val.resize(nelms);
414 
415  if (nelms > LL_total_num) {
416  H5Gclose(rootid);
417  //H5Fclose(fileid);
418  throw InternalErr (__FILE__, __LINE__,
419  "The number of elements exceeds the total number of Latitude or Longitude");
420  }
421 
422  for (int i = 0; i < nelms; ++i)
423  val[i] = LL_first_point + (offset[0] + i*step[0])*LL_step;
424 
425  set_value ((dods_float32 *) &val[0], nelms);
426  H5Gclose(rootid);
427  //H5Fclose(fileid);
428 #endif
429 
430 }
431 
432 
433 // Obtain latitude/longitude attribute values
434 //template<class T>
435 template<typename T>
436 void HDF5GMCFMissLLArray::obtain_ll_attr_value(hid_t /*file_id*/, hid_t s_root_id, const string & s_attr_name,
437  T& attr_value, vector<char> & str_attr_value)
438 {
439 
440  BESDEBUG("h5", "Coming to obtain_ll_attr_value"<<endl);
441  hid_t s_attr_id = -1;
442  if ((s_attr_id = H5Aopen_by_name(s_root_id, ".", s_attr_name.c_str(),
443  H5P_DEFAULT, H5P_DEFAULT)) < 0) {
444  string msg = "Cannot open the HDF5 attribute ";
445  msg += s_attr_name;
446  H5Gclose(s_root_id);
447  throw InternalErr(__FILE__, __LINE__, msg);
448  }
449 
450  hid_t attr_type = -1;
451  if ((attr_type = H5Aget_type(s_attr_id)) < 0) {
452  string msg = "cannot get the attribute datatype for the attribute ";
453  msg += s_attr_name;
454  H5Aclose(s_attr_id);
455  H5Gclose(s_root_id);
456  throw InternalErr(__FILE__, __LINE__, msg);
457  }
458 
459  hid_t attr_space = -1;
460  if ((attr_space = H5Aget_space(s_attr_id)) < 0) {
461  string msg = "cannot get the hdf5 dataspace id for the attribute ";
462  msg += s_attr_name;
463  H5Tclose(attr_type);
464  H5Aclose(s_attr_id);
465  H5Gclose(s_root_id);
466  throw InternalErr(__FILE__, __LINE__, msg);
467  }
468 
469  hssize_t num_elm = H5Sget_simple_extent_npoints(attr_space);
470 
471  if (0 == num_elm) {
472  string msg = "cannot get the number for the attribute ";
473  msg += s_attr_name;
474  H5Tclose(attr_type);
475  H5Aclose(s_attr_id);
476  H5Sclose(attr_space);
477  H5Gclose(s_root_id);
478  throw InternalErr(__FILE__, __LINE__, msg);
479  }
480 
481  if (1 != num_elm) {
482  string msg = "The number of attribute must be 1 for Aquarius level 3 data ";
483  msg += s_attr_name;
484  H5Tclose(attr_type);
485  H5Aclose(s_attr_id);
486  H5Sclose(attr_space);
487  H5Gclose(s_root_id);
488  throw InternalErr(__FILE__, __LINE__, msg);
489  }
490 
491  size_t atype_size = H5Tget_size(attr_type);
492  if (atype_size <= 0) {
493  string msg = "cannot obtain the datatype size of the attribute ";
494  msg += s_attr_name;
495  H5Tclose(attr_type);
496  H5Aclose(s_attr_id);
497  H5Sclose(attr_space);
498  H5Gclose(s_root_id);
499  throw InternalErr(__FILE__, __LINE__, msg);
500  }
501 
502  if (H5T_STRING == H5Tget_class(attr_type)) {
503  if (H5Tis_variable_str(attr_type)) {
504  H5Tclose(attr_type);
505  H5Aclose(s_attr_id);
506  H5Sclose(attr_space);
507  H5Gclose(s_root_id);
508  throw InternalErr(__FILE__, __LINE__,
509  "Currently we assume the attributes we use to retrieve lat and lon are NOT variable length string.");
510  }
511  else {
512  str_attr_value.resize(atype_size);
513  if (H5Aread(s_attr_id, attr_type, &str_attr_value[0]) < 0) {
514  string msg = "cannot retrieve the value of the attribute ";
515  msg += s_attr_name;
516  H5Tclose(attr_type);
517  H5Aclose(s_attr_id);
518  H5Sclose(attr_space);
519  H5Gclose(s_root_id);
520  throw InternalErr(__FILE__, __LINE__, msg);
521 
522  }
523  }
524  }
525 
526  else if (H5Aread(s_attr_id, attr_type, &attr_value) < 0) {
527  string msg = "cannot retrieve the value of the attribute ";
528  msg += s_attr_name;
529  H5Tclose(attr_type);
530  H5Aclose(s_attr_id);
531  H5Sclose(attr_space);
532  H5Gclose(s_root_id);
533  throw InternalErr(__FILE__, __LINE__, msg);
534 
535  }
536 
537  H5Tclose(attr_type);
538  H5Sclose(attr_space);
539  H5Aclose(s_attr_id);
540 }
541 
542 void HDF5GMCFMissLLArray::obtain_gpm_l3_new_grid_info(hid_t file,
543  vector<char>& grid_info_value1,
544  vector<char>& grid_info_value2){
545 
546  typedef struct {
547  char* name;
548  char* value;
549  } attr_info_t;
550 
551  attr_info_t attr_na;
552  attr_na.name = NULL;
553  attr_na.value = NULL;
554 
555  herr_t ret_o= H5OVISIT(file, H5_INDEX_NAME, H5_ITER_INC, visit_obj_cb, (void*)&attr_na);
556  if(ret_o < 0){
557  H5Fclose(file);
558  throw InternalErr(__FILE__, __LINE__, "H5OVISIT failed. ");
559  }
560  else if(ret_o >0) {
561 #if 0
562  //printf("Found the attribute.\n");
563  //string grid_info_name_1(attr_na.name);
564  //string grid_info_name_2;
565 
566  //string grid_info_value_1(attr_na.value);
567 
568  vector<char> grid_info_value_1(attr_na.value,attr_na.value+strlen(attr_na.value));
569  vector<char> grid_info_value_2;
570  //grid_info_value1(attr_na.value,attr_na.value+strlen(attr_na.value));
571 #endif
572  BESDEBUG("h5","Found the GPM level 3 Grid_info attribute."<<endl);
573  grid_info_value1.resize(strlen(attr_na.value));
574  memcpy(&grid_info_value1[0],attr_na.value,strlen(attr_na.value));
575 #if 0
576  string tv(grid_info_value1.begin(),grid_info_value1.end());
577  cerr<<"grid_info_value1 is "<<tv <<endl;
578  printf("attr_name 1st is %s\n",attr_na.name);
579  printf("attr_value 1st is %s\n",attr_na.value);
580 #endif
581  // Find the grid_info_value of the second grid.
582  // Note: the memory allocated for the first grid info is released
583  // by the attribute callback function.
584  // In this round, we need to release the memory allocated for the second grid info.
585  herr_t ret_o2= H5OVISIT(file, H5_INDEX_NAME, H5_ITER_INC, visit_obj_cb, (void*)&attr_na);
586  if(ret_o2 < 0) {
587  H5Fclose(file);
588  throw InternalErr(__FILE__, __LINE__, "H5OVISIT failed again. ");
589  }
590  else if(ret_o2>0) {
591  if(attr_na.name) {
592  //printf("attr_name second is %s\n",attr_na.name);
593  free(attr_na.name);
594  }
595  if(attr_na.value) {
596  //printf("attr_value second is %s\n",attr_na.value);
597  //grid_info_value2(attr_na.value,attr_na.value+strlen(attr_na.value));
598  grid_info_value2.resize(strlen(attr_na.value));
599  memcpy(&grid_info_value2[0],attr_na.value,strlen(attr_na.value));
600 #if 0
601  string tv(grid_info_value2.begin(),grid_info_value2.end());
602  //cerr<<"grid_info_value2 is "<<tv <<endl;
603 #endif
604  free(attr_na.value);
605  }
606  }
607  }
608 }
609 
610 void HDF5GMCFMissLLArray::obtain_lat_lon_info(const vector<char>& grid_info_value1,
611  const vector<char>& grid_info_value2,
612  int& latsize,int& lonsize,
613  float& lat_start,float& lon_start,
614  float& lat_res,float& lon_res){
615 
616  float lat1_start = 0;
617  float lon1_start = 0.;
618  float lat1_res = 0.;
619  float lon1_res = 0.;
620  int lat1size = 0;
621  int lon1size = 0;
622 
623  float lat2_start = 0;
624  float lon2_start = 0.;
625  float lat2_res = 0.;
626  float lon2_res = 0.;
627  int lat2size = 0;
628  int lon2size = 0;
629 
630  HDF5CFUtil::parser_gpm_l3_gridheader(grid_info_value1, lat1size, lon1size, lat1_start, lon1_start,
631  lat1_res, lon1_res,false);
632 
633  HDF5CFUtil::parser_gpm_l3_gridheader(grid_info_value2, lat2size, lon2size, lat2_start, lon2_start,
634  lat2_res, lon2_res,false);
635 
636  bool pick_gv1 = true;
637 
638  // We use the resolution (the smaller value is high resolution) to distinguish the two lat/lons.
639  if (name() == "lnL" || name() == "ltL") {
640  if(lat1_res <lat2_res)
641  pick_gv1 = false;
642  }
643  else if (name() == "lnH" || name() == "ltH") {
644  if(lat1_res >lat2_res)
645  pick_gv1 = false;
646  }
647 
648  if(true == pick_gv1) {
649  latsize = lat1size;
650  lonsize = lon1size;
651  lat_start = lat1_start;
652  lon_start = lon1_start;
653  lat_res = lat1_res;
654  lon_res = lon1_res;
655  }
656  else {
657  latsize = lat2size;
658  lonsize = lon2size;
659  lat_start = lat2_start;
660  lon_start = lon2_start;
661  lat_res = lat2_res;
662  lon_res = lon2_res;
663  }
664 }
665 
666 //Callback function to retrieve the grid information.
667 static herr_t
668 attr_info(hid_t loc_id, const char *name, const H5A_info_t *ainfo, void *_op_data)
669 {
670 
671  typedef struct {
672  char* name;
673  char* value;
674  } attr_info_t;
675 
676  herr_t ret = 0;
677  attr_info_t *op_data = (attr_info_t *)_op_data;
678 
679  // Attribute name is GridHeader
680  if(strstr(name,GPM_ATTR2_NAME)!=NULL) {
681  hid_t attr, atype, aspace;
682  attr = H5Aopen(loc_id, name, H5P_DEFAULT);
683  if(attr<0)
684  return -1;
685  atype = H5Aget_type(attr);
686  if(atype <0) {
687  H5Aclose(attr);
688  return -1;
689  }
690  if(H5T_STRING == H5Tget_class(atype)){
691  // Note here: we find that the HDF5 API H5Tis_variable_str() causes seg. fault
692  // when checking if this is a variable length string. A ticket has been submitted
693  // to the HDF group. For GPM, only the fixed-size string is used. So it won't affect
694  // here. When the bug is fixed. We should add a check here to avoid the crash of the prog.
695  if(op_data->name) {
696  if(strncmp(name,op_data->name,strlen(name))!=0) {
697  hid_t aspace = H5Aget_space(attr);
698  if(aspace <0) {
699  H5Aclose(attr);
700  H5Tclose(atype);
701  return -1;
702  }
703  hsize_t num_elms = H5Tget_size(atype)*H5Sget_simple_extent_npoints(aspace);
704 #if 0
705  char *attr_value = op_data->value;
706  attr_value = malloc(num_elms+1);
707  H5Aread(attr,atype,attr_value);
708  printf("attr_value is %s\n",attr_value);
709 #endif
710  char *cur_attr_value = (char*)malloc(num_elms+1);
711  if(H5Aread(attr,atype,(void*)cur_attr_value)<0) {
712  H5Aclose(attr);
713  H5Sclose(aspace);
714  H5Tclose(atype);
715  free(cur_attr_value);
716  return -1;
717  }
718 
719  // There are two grids in the file. This "if clause" is for the second one.
720  if(strncmp(cur_attr_value,op_data->value,strlen(op_data->value))!=0) {
721  free(op_data->name);
722  op_data->name = NULL;
723  op_data->name = (char*)malloc(strlen(name)+1);
724  strncpy(op_data->name,name,strlen(name));
725  if(op_data->value)
726  free(op_data->value);
727  op_data->value = NULL;
728  op_data->value=(char*)malloc(num_elms+1);
729  strncpy(op_data->value,cur_attr_value,strlen(cur_attr_value));
730  ret = 1;
731  }
732  free(cur_attr_value);
733  H5Sclose(aspace);
734  }
735  }
736  else {
737  hid_t aspace = H5Aget_space(attr);
738  if(aspace <0) {
739  H5Aclose(attr);
740  H5Tclose(atype);
741  return -1;
742  }
743 
744  hsize_t num_elms = H5Tget_size(atype)*H5Sget_simple_extent_npoints(aspace);
745  op_data->name = (char*)malloc(strlen(name)+1);
746  strncpy(op_data->name,name,strlen(name));
747 
748 #if 0
749  char *attr_value = op_data->value;
750  attr_value = malloc(num_elms+1);
751  H5Aread(attr,atype,attr_value);
752  printf("attr_value is %s\n",attr_value);
753 #endif
754  op_data->value = (char*)malloc(num_elms+1);
755  if(H5Aread(attr,atype,(void*)op_data->value)<0) {
756  H5Aclose(attr);
757  H5Sclose(aspace);
758  H5Tclose(atype);
759  free(op_data->value);
760  }
761  H5Sclose(aspace);
762  ret =1;
763  }
764  }
765  H5Tclose(atype);
766  H5Aclose(attr);
767  }
768  return ret;
769 
770 }
771 
772 // The callback function to iterate every HDF5 object(including groups and datasets)
773 // Checked the internal HDF5 functions. The object type is used to obtain different
774 // objects in the internal function. So performance-wise, this routine should be
775 // the same as the routine that uses the H5Literate.
776 //
777 static int
778 visit_obj_cb(hid_t group_id, const char *name, const H5O_info_t *oinfo,
779  void *_op_data)
780 {
781  typedef struct {
782  char* name;
783  char* value;
784  } attr_info_t;
785 
786 
787  //lvisit_ud_t *op_data = (lvisit_ud_t *)_op_data;
788  attr_info_t *op_data = (attr_info_t *)_op_data;
789  herr_t ret = 0;
790 
791  if(oinfo->type == H5O_TYPE_GROUP) {
792 
793  hid_t grp = -1;
794  grp = H5Gopen2(group_id,name,H5P_DEFAULT);
795  if(grp < 0)
796  return -1;
797  ret = H5Aiterate2(grp, H5_INDEX_NAME, H5_ITER_INC, NULL, attr_info, op_data);
798 #if 0
799  if(ret > 0) {
800  printf("object: attr name is %s\n",op_data->name);
801  printf("object: attr value is %s\n",op_data->value);
802  }
803 #endif
804  if(ret <0){
805  H5Gclose(grp);
806  return -1;
807  }
808  H5Gclose(grp);
809  }
810  return ret;
811 
812 }
813 
814 
815 
816 #if 0
817 void HDF5GMCFMissLLArray::send_gpm_l3_ll_to_dap(const vector<char>& grid_info_value,int* offset,int* step,
818  int nelms,bool add_cache, void*buf) {
819 
820  float lat_start = 0;
821  float lon_start = 0.;
822  float lat_res = 0.;
823  float lon_res = 0.;
824 
825  int latsize = 0;
826  int lonsize = 0;
827 #endif
828 
829 void HDF5GMCFMissLLArray::send_gpm_l3_ll_to_dap(const int latsize,const int lonsize,const float lat_start,const float lon_start,
830  const float lat_res,const float lon_res, const int* offset,const int* step,
831  const int nelms,const bool add_cache, void*buf) {
832 
833 
834  if (0 == latsize || 0 == lonsize) {
835  throw InternalErr(__FILE__, __LINE__, "Either latitude or longitude size is 0. ");
836  }
837 
838  vector<float> val;
839  val.resize(nelms);
840 
841  if (CV_LAT_MISS == cvartype) {
842 
843  if (nelms > latsize) {
844  throw InternalErr(__FILE__, __LINE__, "The number of elements exceeds the total number of Latitude ");
845 
846  }
847  for (int i = 0; i < nelms; ++i)
848  val[i] = lat_start + offset[0] * lat_res + lat_res / 2 + i * lat_res * step[0];
849 
850  if (add_cache == true) {
851  vector<float> total_val;
852  total_val.resize(latsize);
853  for (int total_i = 0; total_i < latsize; total_i++)
854  total_val[total_i] = lat_start + lat_res / 2 + total_i * lat_res;
855  memcpy(buf, &total_val[0], 4 * latsize);
856  }
857  }
858  else if (CV_LON_MISS == cvartype) {
859 //cerr<<"nelms is "<<nelms <<endl;
860 //cerr<<"lonsize is "<<lonsize <<endl;
861  if (nelms > lonsize) {
862  throw InternalErr(__FILE__, __LINE__, "The number of elements exceeds the total number of Longitude");
863  }
864 
865  for (int i = 0; i < nelms; ++i)
866  val[i] = lon_start + offset[0] * lon_res + lon_res / 2 + i * lon_res * step[0];
867 
868  if (add_cache == true) {
869  vector<float> total_val;
870  total_val.resize(lonsize);
871  for (int total_i = 0; total_i < lonsize; total_i++)
872  total_val[total_i] = lon_start + lon_res / 2 + total_i * lon_res;
873  memcpy(buf, &total_val[0], 4 * lonsize);
874  }
875 
876  }
877 
878  set_value((dods_float32 *) &val[0], nelms);
879 
880 }
881 
882 void HDF5GMCFMissLLArray::read_data_NOT_from_mem_cache(bool add_cache, void*buf)
883 {
884 
885  BESDEBUG("h5", "Coming to HDF5GMCFMissLLArray: read_data_NOT_from_mem_cache "<<endl);
886 
887  // Here we still use vector just in case we need to tackle "rank>1" in the future.
888  // Also we would like to keep it consistent with other similar handlings.
889  vector<int> offset;
890  vector<int> count;
891  vector<int> step;
892 
893  offset.resize(rank);
894  count.resize(rank);
895  step.resize(rank);
896 
897  int nelms = format_constraint(&offset[0], &step[0], &count[0]);
898 
899  if (GPMM_L3 == product_type || GPMS_L3 == product_type || GPM_L3_New == product_type)
900  obtain_gpm_l3_ll(&offset[0], &step[0], nelms, add_cache, buf);
901  else if (Aqu_L3 == product_type || OBPG_L3 == product_type) // Aquarious level 3
902  obtain_aqu_obpg_l3_ll(&offset[0], &step[0], nelms, add_cache, buf);
903 
904  return;
905 
906 }
907 
This class specifies the retrieval of the missing lat/lon values for general HDF5 products.
include the entry functions to execute the handlers