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