bes  Updated for version 3.20.6
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 "InternalErr.h"
38 #include "HDF5RequestHandler.h"
39 
40 #include "HDF5GMCFMissLLArray.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);
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 = Lat_SWP + (Num_lines - 1) * Lat_step;
154  LL_step = 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 Aquarius 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  hid_t grid_grp_id = -1;
228 
229  string grid_grp_name;
230 
231  if ((name() == "nlat") || (name() == "nlon")) {
232 
233  string temp_grid_grp_name(GPM_GRID_GROUP_NAME1, strlen(GPM_GRID_GROUP_NAME1));
234  temp_grid_grp_name = "/" + temp_grid_grp_name;
235  if (H5Lexists(fileid, temp_grid_grp_name.c_str(), H5P_DEFAULT) > 0)
236  grid_grp_name = temp_grid_grp_name;
237  else {
238  string temp_grid_grp_name2(GPM_GRID_GROUP_NAME2, strlen(GPM_GRID_GROUP_NAME2));
239  temp_grid_grp_name2 = "/" + temp_grid_grp_name2;
240  if (H5Lexists(fileid, temp_grid_grp_name2.c_str(), H5P_DEFAULT) > 0)
241  grid_grp_name = temp_grid_grp_name2;
242  else
243  throw InternalErr(__FILE__, __LINE__, "Unknown GPM grid group name ");
244 
245  }
246  }
247 
248  else {
249  string temp_grids_group_name(GPM_GRID_MULTI_GROUP_NAME, strlen(GPM_GRID_MULTI_GROUP_NAME));
250  if (name() == "lnH" || name() == "ltH")
251  grid_grp_name = temp_grids_group_name + "/G2";
252  else if (name() == "lnL" || name() == "ltL") grid_grp_name = temp_grids_group_name + "/G1";
253  }
254 // varname is supposed to include the full path. However, it takes too much effort to obtain the full path
255 // for a created coordiate variable based on the dimension name only. Since GPM has a fixed group G1
256 // for lnL and ltL and another fixed group G2 for lnH and ltH. We just use these names. These information
257 // is from GPM file specification.
258 #if 0
259  if(name() == "lnH" || name() == "ltH" ||
260  name() == "lnL" || name() == "ltL") {
261  string temp_grids_group_name(GPM_GRID_MULTI_GROUP_NAME,strlen(GPM_GRID_MULTI_GROUP_NAME));
262 
263 //cerr<<"varname is "<<varname <<endl;
264  size_t grids_group_pos = varname.find(temp_grids_group_name);
265  if(string::npos == grids_group_pos) {
266  throw InternalErr (__FILE__, __LINE__,
267  "Cannot find group Grids.");
268  }
269 
270  string grids_cgroup_path = varname.substr(grids_group_pos+1);
271  size_t grids_cgroup_pos = varname.find_first_of("/");
272  if(string::npos == grids_cgroup_pos) {
273  throw InternalErr (__FILE__, __LINE__,
274  "Cannot find child group of group Grids.");
275  }
276 
277  string temp_sub_grp_name = grids_cgroup_path.substr(0,grids_cgroup_pos);
278  if(name() == "lnH" || name() == "ltH")
279  sub_grp1_name = temp_sub_grp_name;
280  else if(name() == "lnL" || name() == "ltL")
281  sub_grp2_name = temp_sub_grp_name;
282 
283  grid_grp_name = temp_grids_group_name + "/" + temp_sub_grp_name;
284 
285  }
286 #endif
287 
288  if ((grid_grp_id = H5Gopen(fileid, grid_grp_name.c_str(), H5P_DEFAULT)) < 0) {
289  HDF5CFUtil::close_fileid(fileid, check_pass_fileid_key);
290  ostringstream eherr;
291  eherr << "HDF5 dataset " << varname << " cannot be opened. " << endl;
292  throw InternalErr(__FILE__, __LINE__, eherr.str());
293  }
294 
295  // GPMDPR: update grid_info_name.
296  string grid_info_name(GPM_ATTR2_NAME, strlen(GPM_ATTR2_NAME));
297  if (name() == "lnL" || name() == "ltL")
298  grid_info_name = "G1_" + grid_info_name;
299  else if (name() == "lnH" || name() == "ltH") grid_info_name = "G2_" + grid_info_name;
300 
301  vector<char> grid_info_value;
302  float dummy_value = 0.0;
303  try {
304  obtain_ll_attr_value(fileid, grid_grp_id, grid_info_name, dummy_value, grid_info_value);
305  }
306  catch (...) {
307  HDF5CFUtil::close_fileid(fileid, check_pass_fileid_key);
308  throw;
309 
310  }
311 
312  float lat_start = 0;
313  float lon_start = 0.;
314  float lat_res = 0.;
315  float lon_res = 0.;
316 
317  int latsize = 0;
318  int lonsize = 0;
319 
320  HDF5CFUtil::parser_gpm_l3_gridheader(grid_info_value, latsize, lonsize, lat_start, lon_start, lat_res, lon_res,
321  false);
322 
323  if (0 == latsize || 0 == lonsize) {
324  HDF5CFUtil::close_fileid(fileid, check_pass_fileid_key);
325  throw InternalErr(__FILE__, __LINE__, "Either latitude or longitude size is 0. ");
326  }
327 
328  vector<float> val;
329  val.resize(nelms);
330 
331  if (CV_LAT_MISS == cvartype) {
332 
333  if (nelms > latsize) {
334  H5Gclose(grid_grp_id);
335  HDF5CFUtil::close_fileid(fileid, check_pass_fileid_key);
336  throw InternalErr(__FILE__, __LINE__, "The number of elements exceeds the total number of Latitude ");
337 
338  }
339  for (int i = 0; i < nelms; ++i)
340  val[i] = lat_start + offset[0] * lat_res + lat_res / 2 + i * lat_res * step[0];
341 
342  if (add_cache == true) {
343  vector<float> total_val;
344  total_val.resize(latsize);
345  for (int total_i = 0; total_i < latsize; total_i++)
346  total_val[total_i] = lat_start + lat_res / 2 + total_i * lat_res;
347  memcpy(buf, &total_val[0], 4 * latsize);
348  }
349  }
350  else if (CV_LON_MISS == cvartype) {
351 
352  if (nelms > lonsize) {
353  H5Gclose(grid_grp_id);
354  HDF5CFUtil::close_fileid(fileid, check_pass_fileid_key);
355  throw InternalErr(__FILE__, __LINE__, "The number of elements exceeds the total number of Longitude");
356 
357  }
358 
359  for (int i = 0; i < nelms; ++i)
360  val[i] = lon_start + offset[0] * lon_res + lon_res / 2 + i * lon_res * step[0];
361 
362  if (add_cache == true) {
363  vector<float> total_val;
364  total_val.resize(lonsize);
365  for (int total_i = 0; total_i < lonsize; total_i++)
366  total_val[total_i] = lon_start + lon_res / 2 + total_i * lon_res;
367  memcpy(buf, &total_val[0], 4 * lonsize);
368  }
369 
370  }
371 
372  set_value((dods_float32 *) &val[0], nelms);
373 
374  H5Gclose(grid_grp_id);
375  HDF5CFUtil::close_fileid(fileid, check_pass_fileid_key);
376 
377 #if 0
378 
379  vector<float>val;
380  val.resize(nelms);
381 
382  if (nelms > LL_total_num) {
383  H5Gclose(rootid);
384  //H5Fclose(fileid);
385  throw InternalErr (__FILE__, __LINE__,
386  "The number of elements exceeds the total number of Latitude or Longitude");
387  }
388 
389  for (int i = 0; i < nelms; ++i)
390  val[i] = LL_first_point + (offset[0] + i*step[0])*LL_step;
391 
392  set_value ((dods_float32 *) &val[0], nelms);
393  H5Gclose(rootid);
394  //H5Fclose(fileid);
395 #endif
396 
397 }
398 // Obtain latitude/longitude attribute values
399 //template<class T>
400 template<typename T>
401 void HDF5GMCFMissLLArray::obtain_ll_attr_value(hid_t /*file_id*/, hid_t s_root_id, const string & s_attr_name,
402  T& attr_value, vector<char> & str_attr_value)
403 {
404 
405  BESDEBUG("h5", "Coming to obtain_ll_attr_value"<<endl);
406  hid_t s_attr_id = -1;
407  if ((s_attr_id = H5Aopen_by_name(s_root_id, ".", s_attr_name.c_str(),
408  H5P_DEFAULT, H5P_DEFAULT)) < 0) {
409  string msg = "Cannot open the HDF5 attribute ";
410  msg += s_attr_name;
411  H5Gclose(s_root_id);
412  throw InternalErr(__FILE__, __LINE__, msg);
413  }
414 
415  hid_t attr_type = -1;
416  if ((attr_type = H5Aget_type(s_attr_id)) < 0) {
417  string msg = "cannot get the attribute datatype for the attribute ";
418  msg += s_attr_name;
419  H5Aclose(s_attr_id);
420  H5Gclose(s_root_id);
421  throw InternalErr(__FILE__, __LINE__, msg);
422  }
423 
424  hid_t attr_space = -1;
425  if ((attr_space = H5Aget_space(s_attr_id)) < 0) {
426  string msg = "cannot get the hdf5 dataspace id for the attribute ";
427  msg += s_attr_name;
428  H5Tclose(attr_type);
429  H5Aclose(s_attr_id);
430  H5Gclose(s_root_id);
431  throw InternalErr(__FILE__, __LINE__, msg);
432  }
433 
434  int num_elm = H5Sget_simple_extent_npoints(attr_space);
435 
436  if (0 == num_elm) {
437  string msg = "cannot get the number for the attribute ";
438  msg += s_attr_name;
439  H5Tclose(attr_type);
440  H5Aclose(s_attr_id);
441  H5Sclose(attr_space);
442  H5Gclose(s_root_id);
443  throw InternalErr(__FILE__, __LINE__, msg);
444  }
445 
446  if (1 != num_elm) {
447  string msg = "The number of attribute must be 1 for Aquarius level 3 data ";
448  msg += s_attr_name;
449  H5Tclose(attr_type);
450  H5Aclose(s_attr_id);
451  H5Sclose(attr_space);
452  H5Gclose(s_root_id);
453  throw InternalErr(__FILE__, __LINE__, msg);
454  }
455 
456  size_t atype_size = H5Tget_size(attr_type);
457  if (atype_size <= 0) {
458  string msg = "cannot obtain the datatype size of the attribute ";
459  msg += s_attr_name;
460  H5Tclose(attr_type);
461  H5Aclose(s_attr_id);
462  H5Sclose(attr_space);
463  H5Gclose(s_root_id);
464  throw InternalErr(__FILE__, __LINE__, msg);
465  }
466 
467  if (H5T_STRING == H5Tget_class(attr_type)) {
468  if (H5Tis_variable_str(attr_type)) {
469  H5Tclose(attr_type);
470  H5Aclose(s_attr_id);
471  H5Sclose(attr_space);
472  H5Gclose(s_root_id);
473  throw InternalErr(__FILE__, __LINE__,
474  "Currently we assume the attributes we use to retrieve lat and lon are NOT variable length string.");
475  }
476  else {
477  str_attr_value.resize(atype_size);
478  if (H5Aread(s_attr_id, attr_type, &str_attr_value[0]) < 0) {
479  string msg = "cannot retrieve the value of the attribute ";
480  msg += s_attr_name;
481  H5Tclose(attr_type);
482  H5Aclose(s_attr_id);
483  H5Sclose(attr_space);
484  H5Gclose(s_root_id);
485  throw InternalErr(__FILE__, __LINE__, msg);
486 
487  }
488  }
489  }
490 
491  else if (H5Aread(s_attr_id, attr_type, &attr_value) < 0) {
492  string msg = "cannot retrieve the value of the attribute ";
493  msg += s_attr_name;
494  H5Tclose(attr_type);
495  H5Aclose(s_attr_id);
496  H5Sclose(attr_space);
497  H5Gclose(s_root_id);
498  throw InternalErr(__FILE__, __LINE__, msg);
499 
500  }
501 
502  H5Tclose(attr_type);
503  H5Sclose(attr_space);
504  H5Aclose(s_attr_id);
505 }
506 
507 void HDF5GMCFMissLLArray::read_data_NOT_from_mem_cache(bool add_cache, void*buf)
508 {
509 
510  BESDEBUG("h5", "Coming to HDF5GMCFMissLLArray: read_data_NOT_from_mem_cache "<<endl);
511 
512  // Here we still use vector just in case we need to tackle "rank>1" in the future.
513  // Also we would like to keep it consistent with other similar handlings.
514  vector<int> offset;
515  vector<int> count;
516  vector<int> step;
517 
518  offset.resize(rank);
519  count.resize(rank);
520  step.resize(rank);
521 
522  int nelms = format_constraint(&offset[0], &step[0], &count[0]);
523 
524  if (GPMM_L3 == product_type || GPMS_L3 == product_type)
525  obtain_gpm_l3_ll(&offset[0], &step[0], nelms, add_cache, buf);
526  else if (Aqu_L3 == product_type || OBPG_L3 == product_type) // Aquarious level 3
527  obtain_aqu_obpg_l3_ll(&offset[0], &step[0], nelms, add_cache, buf);
528 
529  return;
530 
531 }
532 
libdap
Definition: BESDapFunctionResponseCache.h:35
HDF5RequestHandler.h
include the entry functions to execute the handlers
HDF5GMCFMissLLArray.h
This class specifies the retrieval of the missing lat/lon values for general HDF5 products.
HDF5GMCFMissLLArray
Definition: HDF5GMCFMissLLArray.h:45