bes  Updated for version 3.20.6
HDF5GCFProduct.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 
33 #include <InternalErr.h>
34 #include <assert.h>
35 #include "HDF5GCFProduct.h"
36 
37 using namespace std;
38 using namespace libdap;
39 
40 
41 // The knowledge on how to distinguish each HDF5 product is all buried here
42 // All product attribute names and values are defined at the header files.
43 H5GCFProduct check_product(hid_t file_id) {
44 
45  hid_t root_id = -1;
46  H5GCFProduct product_type = General_Product;
47 
48  // Open the root group.
49  if ((root_id = H5Gopen(file_id,ROOT_NAME,H5P_DEFAULT))<0){
50  string msg = "cannot open the HDF5 root group ";
51  msg += string(ROOT_NAME);
52  throw InternalErr(__FILE__, __LINE__, msg);
53  }
54 
55  // Check if the product is MEaSUREs SeaWiFS
56  int s_level = -1;
57 
58  // Also set Aquarius level, although we only support
59  // Aquarius level 3, in the future we may support Aquarius
60  // level 2.
61  int a_level = -1;
62 
63 
64  // Check if the product is GPM level 1, if yes, just return.
65  if (true == check_gpm_l1(root_id)){
66  product_type = GPM_L1;
67  }
68 
69  // Check if the product is GPM level 3, if yes, just return.
70  else if (true == check_gpms_l3(root_id)){
71  product_type = GPMS_L3;
72  }
73 
74  else if (true == check_gpmm_l3(root_id)) {
75  product_type = GPMM_L3;
76 
77  }
78 
79  else if (true == check_measure_seawifs(root_id,s_level)) {
80  if (2 == s_level) product_type = Mea_SeaWiFS_L2;
81  if (3 == s_level) product_type = Mea_SeaWiFS_L3;
82  }
83 
84  else if (true == check_aquarius(root_id,a_level)){
85  if (3 == a_level) product_type = Aqu_L3;
86  }
87  else if (true == check_obpg(root_id,a_level)){
88  if (3 == a_level) product_type = OBPG_L3;
89  }
90 
91  else if (true == check_measure_ozone(root_id)) {
92  product_type = Mea_Ozone;
93  }
94  else {
95  int osmapl2s_flag = 1; // This is OSMAPL2S
96  if (true == check_osmapl2s_acosl2s_oco2l1b(root_id,osmapl2s_flag))
97  product_type = OSMAPL2S;
98 
99  if (General_Product == product_type) {
100 
101  int acosl2s_oco2l1b_flag = 2; // This is ACOSL2S_OR_OCO2L1B
102  if (true == check_osmapl2s_acosl2s_oco2l1b(root_id,acosl2s_oco2l1b_flag))
103  product_type = ACOS_L2S_OR_OCO2_L1B;
104  }
105 
106  }
107 
108  H5Gclose(root_id);
109  return product_type;
110 }
111 
112 // Function to check if the product is GPM level 1
113 bool check_gpm_l1(hid_t s_root_id) {
114 
115  htri_t has_gpm_l1_attr1 = -1;
116  bool ret_flag = false;
117 
118 
119  // Here we check the existence of attribute 1 first
120  has_gpm_l1_attr1 = H5Aexists(s_root_id,GPM_ATTR1_NAME);
121 
122  if(has_gpm_l1_attr1 >0) {
123 
124  H5G_info_t g_info;
125  hsize_t nelms = 0;
126 
127  if(H5Gget_info(s_root_id,&g_info) <0) {
128  H5Gclose(s_root_id);
129  throw InternalErr(__FILE__,__LINE__,"Cannot get the HDF5 object info. successfully");
130  }
131 
132  nelms = g_info.nlinks;
133 
134  hid_t cgroup = -1;
135  hid_t attrid = -1;
136 
137  for (unsigned int i = 0; i<nelms; i++) {
138 
139  try {
140 
141  size_t dummy_name_len = 1;
142 
143  // Query the length of object name.
144  ssize_t oname_size =
145  H5Lget_name_by_idx(s_root_id,".",H5_INDEX_NAME,H5_ITER_NATIVE,i,NULL,
146  dummy_name_len, H5P_DEFAULT);
147  if (oname_size <= 0)
148  throw InternalErr(__FILE__,__LINE__,"Error getting the size of the hdf5 object from the root group. ");
149 
150  // Obtain the name of the object
151  vector<char> oname;
152  oname.resize((size_t)oname_size+1);
153 
154  if (H5Lget_name_by_idx(s_root_id,".",H5_INDEX_NAME,H5_ITER_NATIVE,i,&oname[0],
155  (size_t)(oname_size+1), H5P_DEFAULT) < 0)
156  throw InternalErr(__FILE__,__LINE__,"Error getting the hdf5 object name from the root group. ");
157 
158  // Check if it is the hard link or the soft link
159  H5L_info_t linfo;
160  if (H5Lget_info(s_root_id,&oname[0],&linfo,H5P_DEFAULT)<0)
161  throw InternalErr (__FILE__,__LINE__,"HDF5 link name error from the root group. ");
162 
163  // Ignore soft links and external links
164  if(H5L_TYPE_SOFT == linfo.type || H5L_TYPE_EXTERNAL == linfo.type)
165  continue;
166 
167  // Obtain the object type, such as group or dataset.
168  H5O_info_t soinfo;
169  if(H5Oget_info_by_idx(s_root_id,".",H5_INDEX_NAME,H5_ITER_NATIVE, (hsize_t)i,&soinfo,H5P_DEFAULT)<0)
170  throw InternalErr(__FILE__,__LINE__,"Cannot get the HDF5 object info. successfully. ");
171 
172  H5O_type_t obj_type = soinfo.type;
173 
174  // We only need to check the group attribute.
175  if(obj_type == H5O_TYPE_GROUP) {
176 
177  // Check the attribute name of that group
178  cgroup = H5Gopen(s_root_id,&oname[0],H5P_DEFAULT);
179  if(cgroup < 0)
180  throw InternalErr(__FILE__,__LINE__,"Cannot open the group.");
181 
182  int num_attrs = soinfo.num_attrs;
183 
184  // Loop through all the attributes to see if the GPM level 1 swath header exists.
185  for (int j = 0; j < num_attrs; j++) {
186 
187  // Obtain the attribute ID.
188  if ((attrid = H5Aopen_by_idx(cgroup, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC,(hsize_t)j, H5P_DEFAULT, H5P_DEFAULT)) < 0)
189  throw InternalErr(__FILE__,__LINE__,"Unable to open attribute by index " );
190 
191  // Obtain the size of the attribute name.
192  ssize_t name_size = H5Aget_name(attrid, 0, NULL);
193  if (name_size < 0)
194  throw InternalErr(__FILE__,__LINE__,"Unable to obtain the size of the hdf5 attribute name " );
195 
196  string attr_name;
197  attr_name.resize(name_size+1);
198 
199  // Obtain the attribute name.
200  if ((H5Aget_name(attrid, name_size+1, &attr_name[0])) < 0)
201  throw InternalErr(__FILE__,__LINE__,"unable to obtain the hdf5 attribute name ");
202 
203  string swathheader(GPM_SWATH_ATTR2_NAME);
204  if(attr_name.rfind(swathheader) !=string::npos) {
205  H5Aclose(attrid);
206  ret_flag = true;
207  break;
208  }
209  H5Aclose(attrid);
210  }
211 
212  if(true == ret_flag){
213  H5Gclose(cgroup);
214  break;
215  }
216  H5Gclose(cgroup);
217  }
218  }
219  catch(...) {
220  if(s_root_id != -1)
221  H5Gclose(s_root_id);
222  if(cgroup != -1)
223  H5Gclose(cgroup);
224  if(attrid != -1)
225  H5Aclose(attrid);
226  throw;
227  }
228  }
229 
230  }
231 
232  return ret_flag;
233 
234 }
235 
236 
237 // Function to check if the product is GPM level 3
238 bool check_gpms_l3(hid_t s_root_id) {
239 
240  htri_t has_gpm_l3_attr1 = -1;
241  bool ret_flag = false;
242 
243  // Here we check the existence of attribute 1 first
244  has_gpm_l3_attr1 = H5Aexists(s_root_id,GPM_ATTR1_NAME);
245 
246  if(has_gpm_l3_attr1 >0) {
247 
248  htri_t has_gpm_grid_group = -1;
249 
250  has_gpm_grid_group = H5Lexists(s_root_id,GPM_GRID_GROUP_NAME1,H5P_DEFAULT);
251 
252  hid_t s_group_id = -1;
253  if (has_gpm_grid_group >0){
254 
255  // Open the group
256  if ((s_group_id = H5Gopen(s_root_id, GPM_GRID_GROUP_NAME1,H5P_DEFAULT))<0) {
257  string msg = "Cannot open the HDF5 Group ";
258  msg += string(GPM_GRID_GROUP_NAME1);
259  H5Gclose(s_root_id);
260  throw InternalErr(__FILE__, __LINE__, msg);
261  }
262  }
263  else {
264 
265  if(H5Lexists(s_root_id,GPM_GRID_GROUP_NAME2,H5P_DEFAULT) >0) {
266  // Open the group
267  if ((s_group_id = H5Gopen(s_root_id, GPM_GRID_GROUP_NAME2,H5P_DEFAULT))<0) {
268  string msg = "Cannot open the HDF5 Group ";
269  msg += string(GPM_GRID_GROUP_NAME2);
270  H5Gclose(s_root_id);
271  throw InternalErr(__FILE__, __LINE__, msg);
272  }
273 
274  }
275 
276  }
277  if (s_group_id >0) {
278  htri_t has_gpm_l3_attr2 = -1;
279  has_gpm_l3_attr2 = H5Aexists(s_group_id,GPM_ATTR2_NAME);
280  if (has_gpm_l3_attr2 >0)
281  ret_flag = true;
282 
283  H5Gclose(s_group_id);
284  }
285 
286 
287  }
288 
289  return ret_flag;
290 
291 }
292 
293 
294 bool check_gpmm_l3(hid_t s_root_id) {
295 
296  htri_t has_gpm_l3_attr1 = -1;
297  bool ret_flag = false;
298 
299 
300  // Here we check the existence of attribute 1 first
301  has_gpm_l3_attr1 = H5Aexists(s_root_id,GPM_ATTR1_NAME);
302 
303  if(has_gpm_l3_attr1 >0) {
304 
305  if(H5Lexists(s_root_id,GPM_GRID_MULTI_GROUP_NAME,H5P_DEFAULT) >0) {
306  hid_t cgroup_id = -1;
307  // Open the group
308  if ((cgroup_id = H5Gopen(s_root_id, GPM_GRID_MULTI_GROUP_NAME,H5P_DEFAULT))<0) {
309  string msg = "Cannot open the HDF5 Group ";
310  msg += string(GPM_GRID_MULTI_GROUP_NAME);
311  H5Gclose(s_root_id);
312  throw InternalErr(__FILE__, __LINE__, msg);
313  }
314 
315  H5G_info_t g_info;
316  hsize_t nelms = 0;
317 
318  if(H5Gget_info(cgroup_id,&g_info) <0) {
319  H5Gclose(cgroup_id);
320  H5Gclose(s_root_id);
321  throw InternalErr(__FILE__,__LINE__,"Cannot get the HDF5 object info. successfully");
322  }
323 
324  nelms = g_info.nlinks;
325 
326  hid_t cgroup2_id = -1;
327  hid_t attrid = -1;
328 
329  for (unsigned int i = 0; i<nelms; i++) {
330 
331  try {
332 
333  size_t dummy_name_len = 1;
334 
335  // Query the length of object name.
336  ssize_t oname_size =
337  H5Lget_name_by_idx(cgroup_id,".",H5_INDEX_NAME,H5_ITER_NATIVE,i,NULL,
338  dummy_name_len, H5P_DEFAULT);
339  if (oname_size <= 0)
340  throw InternalErr(__FILE__,__LINE__,"Error getting the size of the hdf5 object from the grid group. ");
341 
342  // Obtain the name of the object
343  vector<char> oname;
344  oname.resize((size_t)oname_size+1);
345 
346  if (H5Lget_name_by_idx(cgroup_id,".",H5_INDEX_NAME,H5_ITER_NATIVE,i,&oname[0],
347  (size_t)(oname_size+1), H5P_DEFAULT) < 0)
348  throw InternalErr(__FILE__,__LINE__,"Error getting the hdf5 object name from the root group. ");
349 
350  // Check if it is the hard link or the soft link
351  H5L_info_t linfo;
352  if (H5Lget_info(cgroup_id,&oname[0],&linfo,H5P_DEFAULT)<0)
353  throw InternalErr (__FILE__,__LINE__,"HDF5 link name error from the root group. ");
354 
355  // Ignore soft links and external links
356  if(H5L_TYPE_SOFT == linfo.type || H5L_TYPE_EXTERNAL == linfo.type)
357  continue;
358 
359  // Obtain the object type, such as group or dataset.
360  H5O_info_t soinfo;
361  if(H5Oget_info_by_idx(cgroup_id,".",H5_INDEX_NAME,H5_ITER_NATIVE, (hsize_t)i,&soinfo,H5P_DEFAULT)<0)
362  throw InternalErr(__FILE__,__LINE__,"Cannot get the HDF5 object info. successfully. ");
363 
364  H5O_type_t obj_type = soinfo.type;
365 
366  // We only need to check the group attribute.
367  if(obj_type == H5O_TYPE_GROUP) {
368 
369  // Check the attribute name of that group
370  cgroup2_id = H5Gopen(cgroup_id,&oname[0],H5P_DEFAULT);
371  if(cgroup2_id < 0)
372  throw InternalErr(__FILE__,__LINE__,"Cannot open the group.");
373 
374  htri_t has_gpm_l3_attr2;
375  has_gpm_l3_attr2 = H5Aexists(cgroup2_id,GPM_ATTR2_NAME);
376  if (has_gpm_l3_attr2 >0) {
377  ret_flag = true;
378  H5Gclose(cgroup2_id);
379  break;
380  }
381  else {
382 
383  int num_attrs = soinfo.num_attrs;
384 
385  // Loop through all the attributes to see if the GPM level 1 swath header exists.
386  for (int j = 0; j < num_attrs; j++) {
387 
388  // Obtain the attribute ID.
389  if ((attrid = H5Aopen_by_idx(cgroup2_id, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC,(hsize_t)j, H5P_DEFAULT, H5P_DEFAULT)) < 0)
390  throw InternalErr(__FILE__,__LINE__,"Unable to open attribute by index " );
391 
392  // Obtain the size of the attribute name.
393  ssize_t name_size = H5Aget_name(attrid, 0, NULL);
394  if (name_size < 0)
395  throw InternalErr(__FILE__,__LINE__,"Unable to obtain the size of the hdf5 attribute name " );
396 
397  string attr_name;
398  attr_name.resize(name_size+1);
399 
400  // Obtain the attribute name.
401  if ((H5Aget_name(attrid, name_size+1, &attr_name[0])) < 0)
402  throw InternalErr(__FILE__,__LINE__,"unable to obtain the hdf5 attribute name ");
403 
404  string gridheader(GPM_ATTR2_NAME);
405  if(attr_name.find(gridheader) !=string::npos) {
406  ret_flag = true;
407  break;
408  }
409  }
410 
411  if(true == ret_flag)
412  break;
413 
414  }
415 
416  H5Gclose(cgroup2_id);
417 
418  }
419  }
420  catch(...) {
421  if(s_root_id != -1)
422  H5Gclose(s_root_id);
423  if(cgroup_id != -1)
424  H5Gclose(cgroup_id);
425  if(cgroup2_id != -1)
426  H5Gclose(cgroup2_id);
427  throw;
428  }
429  }
430  H5Gclose(cgroup_id);
431  }
432  }
433  return ret_flag;
434 }
435 
436 // Function to check if the product is MeaSure seaWiFS
437 bool check_measure_seawifs(hid_t s_root_id,int & s_lflag) {
438 
439  htri_t has_seawifs_attr1 = -1;
440  bool ret_flag = false;
441 
442  // Here we check the existence of attribute 1 first since
443  // attribute 1 will tell if the product is SeaWIFS or not.
444  // attribute 2 and 3 will distinguish if it is level 2 or level 3.
445  has_seawifs_attr1 = H5Aexists(s_root_id,SeaWiFS_ATTR1_NAME);
446 
447  if (has_seawifs_attr1 >0) {
448 
449  string attr1_value="";
450  obtain_gm_attr_value(s_root_id, SeaWiFS_ATTR1_NAME, attr1_value);
451  if (0 == attr1_value.compare(SeaWiFS_ATTR1_VALUE)) {
452  htri_t has_seawifs_attr2 = -1;
453  htri_t has_seawifs_attr3 = -1;
454  has_seawifs_attr2 = H5Aexists(s_root_id,SeaWiFS_ATTR2_NAME);
455  has_seawifs_attr3 = H5Aexists(s_root_id,SeaWiFS_ATTR3_NAME);
456 
457  if ((has_seawifs_attr2 >0) && (has_seawifs_attr3 > 0)){
458  string attr2_value ="";
459  string attr3_value ="";
460  obtain_gm_attr_value(s_root_id,SeaWiFS_ATTR2_NAME, attr2_value);
461  obtain_gm_attr_value(s_root_id,SeaWiFS_ATTR3_NAME, attr3_value);
462 
463  // The first part of the <long_name> should be "SeaWiFS"
464  // "Level 2" or "Level 3" should also be inside <long_name>.
465  // OR the short_name should start with "SWDB_L2" and "SWDB_L3".
466 
467  if (((0 == attr2_value.find(SeaWiFS_ATTR2_FPVALUE)) &&
468  (attr2_value.find(SeaWiFS_ATTR2_L2PVALUE)!=string::npos))
469  ||(0 == attr3_value.find(SeaWiFS_ATTR3_L2FPVALUE))) {
470  // "h5","coming to seaWiFS level 2" <<endl;
471  s_lflag = 2;
472  ret_flag = true;
473  }
474  else if (((0 == attr2_value.find(SeaWiFS_ATTR2_FPVALUE)) &&
475  (attr2_value.find(SeaWiFS_ATTR2_L3PVALUE)!=string::npos))
476  ||(0 == attr3_value.find(SeaWiFS_ATTR3_L3FPVALUE))) {
477  s_lflag = 3;
478  ret_flag = true;
479  }
480  }
481  // else if long_name or short_name don't exist, not what we supported.
482  else if ((0 == has_seawifs_attr2 ) || (0 == has_seawifs_attr3))
483  ; // no op
484  else {
485  string msg = "Fail to determine if the HDF5 attribute ";
486  msg += string(SeaWiFS_ATTR2_NAME);
487  msg += "or the HDF5 attribute ";
488  msg += string(SeaWiFS_ATTR3_NAME);
489  msg +=" exists ";
490  H5Gclose(s_root_id);
491  throw InternalErr(__FILE__, __LINE__, msg);
492  }
493  }
494  }
495  else if (0 == has_seawifs_attr1)
496  ;//no op
497  else {
498  string msg = "Fail to determine if the HDF5 attribute ";
499  msg += string(SeaWiFS_ATTR1_NAME);
500  msg +=" exists ";
501  H5Gclose(s_root_id);
502  throw InternalErr(__FILE__, __LINE__, msg);
503  }
504  return ret_flag;
505 }
506 
507  // Function to check if the product is MeaSure seaWiFS
508 bool check_measure_ozone(hid_t s_root_id) {
509 
510  htri_t has_ozone_attr1 = -1;
511  bool ret_flag = false;
512 
513  // Here we check the existence of attribute 1 first since
514  // attribute 1 will tell if the product is SeaWIFS or not.
515  // attribute 2 and 3 will distinguish if it is level 2 or level 3.
516  has_ozone_attr1 = H5Aexists(s_root_id,Ozone_ATTR1_NAME);
517 
518  if (has_ozone_attr1 >0) {
519  string attr1_value = "";
520  obtain_gm_attr_value(s_root_id, Ozone_ATTR1_NAME, attr1_value);
521  if ((0 == attr1_value.compare(Ozone_ATTR1_VALUE1)) ||
522  (0 == attr1_value.compare(Ozone_ATTR1_VALUE2))) {
523  htri_t has_ozone_attr2 = -1;
524  has_ozone_attr2 = H5Aexists(s_root_id,Ozone_ATTR2_NAME);
525  if (has_ozone_attr2 >0) {
526  string attr2_value = "";
527  obtain_gm_attr_value(s_root_id,Ozone_ATTR2_NAME, attr2_value);
528  if(0 == attr2_value.compare(Ozone_ATTR2_VALUE))
529  ret_flag = true;
530  }
531  // else if "ParameterName" attributes don't exist, not what we supported.
532  else if (0 == has_ozone_attr2)
533  ;// no op
534  else {
535  string msg = "Fail to determine if the HDF5 attribute ";
536  msg += string(Ozone_ATTR2_NAME);
537  msg +=" exists ";
538  H5Gclose(s_root_id);
539  throw InternalErr(__FILE__, __LINE__, msg);
540  }
541  }
542  }
543  else if (0 == has_ozone_attr1 )
544  ; // no op
545  else {
546  string msg = "Fail to determine if the HDF5 attribute ";
547  msg += string(Ozone_ATTR1_NAME);
548  msg +=" exists ";
549  H5Gclose(s_root_id);
550  throw InternalErr(__FILE__, __LINE__, msg);
551  }
552  return ret_flag;
553 }
554 // Function to check if the product is Aquarius
555 // We still leave a flag to indicate the level although
556 // we just support the special arrangement of level 3 now.
557 // Possibly level 2 can be added
558 // in the future.
559 bool check_aquarius(hid_t s_root_id,int & s_level) {
560 
561  htri_t has_aquarius_attr1 = -1;
562  bool ret_flag = false;
563 
564  // Here we check the existence of attribute 1 first since
565  // attribute 1 will tell if the product is Aquarius or not.
566  // attribute 2 will tell its level.
567  has_aquarius_attr1 = H5Aexists(s_root_id,Aquarius_ATTR1_NAME);
568  if (has_aquarius_attr1 >0) {
569  string attr1_value = "";
570  obtain_gm_attr_value(s_root_id, Aquarius_ATTR1_NAME, attr1_value);
571  if (0 == attr1_value.compare(Aquarius_ATTR1_VALUE)) {
572  htri_t has_aquarius_attr2 = -1;
573  has_aquarius_attr2 = H5Aexists(s_root_id,Aquarius_ATTR2_NAME);
574  if (has_aquarius_attr2 >0) {
575  string attr2_value ="";
576  obtain_gm_attr_value(s_root_id,Aquarius_ATTR2_NAME, attr2_value);
577 
578  // The "Title" of Aquarius should include "Level-3".
579  if (attr2_value.find(Aquarius_ATTR2_PVALUE)!=string::npos){
580  // Set it to level 3
581  s_level = 3;
582  ret_flag = true;
583  }
584  }
585  // else if long_name or short_name don't exist, not what we supported.
586  else if (0 == has_aquarius_attr2)
587  ; // no op
588  else {
589  string msg = "Fail to determine if the HDF5 attribute ";
590  msg += string(Aquarius_ATTR2_NAME);
591  msg +=" exists ";
592  H5Gclose(s_root_id);
593  throw InternalErr(__FILE__, __LINE__, msg);
594  }
595  }
596  }
597  else if (0 == has_aquarius_attr1)
598  ;// no op
599  else {
600  string msg = "Fail to determine if the HDF5 attribute ";
601  msg += string(Aquarius_ATTR1_NAME);
602  msg +=" exists ";
603  H5Gclose(s_root_id);
604  throw InternalErr(__FILE__, __LINE__, msg);
605  }
606  return ret_flag;
607 }
608 
609 // Function to check if the product is OBPG level 3.
610 // We leave a flag to indicate if this product is level 3 for
611 // possible level 2 support later.
612 bool check_obpg(hid_t s_root_id,int & s_level) {
613 
614  htri_t has_obpg_attr1 = -1;
615  bool ret_flag = false;
616 
617  // Here we check the existence of attribute 1 first since
618  // attribute 1 will tell if the product is OBPG or not.
619  // attribute 2 will tell its level.
620  has_obpg_attr1 = H5Aexists(s_root_id,Obpgl3_ATTR1_NAME);
621  if (has_obpg_attr1 >0) {
622  string attr1_value = "";
623  obtain_gm_attr_value(s_root_id, Obpgl3_ATTR1_NAME, attr1_value);
624  htri_t has_obpg_attr2 = -1;
625  has_obpg_attr2 = H5Aexists(s_root_id,Obpgl3_ATTR2_NAME);
626  if (has_obpg_attr2 >0) {
627  string attr2_value ="";
628  obtain_gm_attr_value(s_root_id,Obpgl3_ATTR2_NAME, attr2_value);
629  if ((0 == attr1_value.compare(Obpgl3_ATTR1_VALUE)) &&
630  (0 == attr2_value.compare(Obpgl3_ATTR2_VALUE))) {
631  // Set it to level 3
632  s_level = 3;
633  ret_flag = true;
634  }
635  }
636  // else if long_name or short_name don't exist, not what we supported.
637  else if (0 == has_obpg_attr2)
638  ; // no op
639  else {
640  string msg = "Fail to determine if the HDF5 attribute ";
641  msg += string(Obpgl3_ATTR2_NAME);
642  msg +=" exists ";
643  H5Gclose(s_root_id);
644  throw InternalErr(__FILE__, __LINE__, msg);
645  }
646  }
647  else if (0 == has_obpg_attr1)
648  ;// no op
649  else {
650  string msg = "Fail to determine if the HDF5 attribute ";
651  msg += string(Obpgl3_ATTR1_NAME);
652  msg +=" exists ";
653  H5Gclose(s_root_id);
654  throw InternalErr(__FILE__, __LINE__, msg);
655  }
656  return ret_flag;
657 }
658 // Function to check if the product is ACOS Level 2 or OSMAPL2S.
659 bool check_osmapl2s_acosl2s_oco2l1b(hid_t s_root_id, int which_pro) {
660 
661  htri_t has_smac_group;
662  bool return_flag = false;
663  has_smac_group = H5Lexists(s_root_id,SMAC2S_META_GROUP_NAME,H5P_DEFAULT);
664 
665  if (has_smac_group >0){
666  hid_t s_group_id = -1;
667 
668  // Open the group
669  if ((s_group_id = H5Gopen(s_root_id, SMAC2S_META_GROUP_NAME,H5P_DEFAULT))<0) {
670  string msg = "Cannot open the HDF5 Group ";
671  msg += string(SMAC2S_META_GROUP_NAME);
672  H5Gclose(s_root_id);
673  throw InternalErr(__FILE__, __LINE__, msg);
674  }
675 
676  // OSMAPL2S
677  if (1 == which_pro) {
678 
679  htri_t has_osmapl2s_attr = -1;
680  // OSMAPL2S will have an attribute called ProjectID
681  has_osmapl2s_attr = H5Aexists(s_group_id,OSMAPL2S_ATTR_NAME);
682  if (has_osmapl2s_attr >0) {
683  string attr_value = "";
684  obtain_gm_attr_value(s_group_id, OSMAPL2S_ATTR_NAME, attr_value);
685  if (attr_value.compare(OSMAPL2S_ATTR_VALUE) == 0)
686  return_flag = true;
687  else
688  return_flag = false;
689  H5Gclose(s_group_id);
690  }
691  else if (0 == has_osmapl2s_attr) {
692  H5Gclose(s_group_id);
693  return_flag = false;
694  }
695  else {
696  string msg = "Fail to determine if the HDF5 link ";
697  msg += string(OSMAPL2S_ATTR_NAME);
698  msg +=" exists ";
699  H5Gclose(s_group_id);
700  H5Gclose(s_root_id);
701  throw InternalErr(__FILE__, __LINE__, msg);
702  }
703  }
704  else if (2 == which_pro) {
705 
706  htri_t has_acos_dset = -1;
707 
708  // ACOSL2S(OCO2L1B) will have a dataset called ProjectId
709  has_acos_dset = H5Lexists(s_group_id,ACOS_L2S_OCO2_L1B_DSET_NAME,H5P_DEFAULT);
710  if (has_acos_dset > 0) {
711  // Obtain the dataset ID
712  hid_t s_dset_id = -1;
713  if ((s_dset_id = H5Dopen(s_group_id, ACOS_L2S_OCO2_L1B_DSET_NAME,H5P_DEFAULT)) < 0) {
714  string msg = "cannot open the HDF5 dataset ";
715  msg += string(ACOS_L2S_OCO2_L1B_DSET_NAME);
716  H5Gclose(s_group_id);
717  H5Gclose(s_root_id);
718  throw InternalErr(__FILE__, __LINE__, msg);
719  }
720 
721  // Obtain the datatype ID
722  hid_t dtype = -1;
723  if ((dtype = H5Dget_type(s_dset_id)) < 0) {
724  H5Dclose(s_dset_id);
725  H5Gclose(s_group_id);
726  H5Gclose(s_root_id);
727  string msg = "cannot get the datatype of HDF5 dataset ";
728  msg += string(ACOS_L2S_OCO2_L1B_DSET_NAME);
729  throw InternalErr(__FILE__, __LINE__, msg);
730  }
731 
732  // Obtain the datatype class
733  H5T_class_t ty_class = H5Tget_class(dtype);
734  if (ty_class < 0) {
735  H5Tclose(dtype);
736  H5Dclose(s_dset_id);
737  H5Gclose(s_group_id);
738  H5Gclose(s_root_id);
739  string msg = "cannot get the datatype class of HDF5 dataset ";
740  msg += string(ACOS_L2S_OCO2_L1B_DSET_NAME);
741  throw InternalErr(__FILE__, __LINE__, msg);
742  }
743 
744  if (ty_class != H5T_STRING) {
745  H5Tclose(dtype);
746  H5Dclose(s_dset_id);
747  H5Gclose(s_group_id);
748  H5Gclose(s_root_id);
749  string msg = "This dataset must be a H5T_STRING class ";
750  msg += string(ACOS_L2S_OCO2_L1B_DSET_NAME);
751  throw InternalErr(__FILE__, __LINE__, msg);
752  }
753 
754 
755  hid_t dspace = -1;
756  if ((dspace = H5Dget_space(s_dset_id)) < 0) {
757  H5Tclose(dtype);
758  H5Dclose(s_dset_id);
759  H5Gclose(s_group_id);
760  H5Gclose(s_root_id);
761  string msg = "cannot get the the dataspace of HDF5 dataset ";
762  msg += string(ACOS_L2S_OCO2_L1B_DSET_NAME);
763  throw InternalErr(__FILE__, __LINE__, msg);
764  }
765 
766  hssize_t num_elem = 0;
767  if ((num_elem = H5Sget_simple_extent_npoints(dspace))<=0) {
768  H5Tclose(dtype);
769  H5Sclose(dspace);
770  H5Dclose(s_dset_id);
771  H5Gclose(s_group_id);
772  H5Gclose(s_root_id);
773  string msg = "cannot get the the number of points of HDF5 dataset ";
774  msg += string(ACOS_L2S_OCO2_L1B_DSET_NAME);
775  throw InternalErr(__FILE__, __LINE__, msg);
776  }
777 
778  size_t dtype_size = H5Tget_size(dtype);
779  if (dtype_size <= 0) {
780  H5Tclose(dtype);
781  H5Dclose(s_dset_id);
782  H5Sclose(dspace);
783  H5Gclose(s_group_id);
784  H5Gclose(s_root_id);
785  string msg = "cannot get the the dataspace of HDF5 dataset ";
786  msg += string(ACOS_L2S_OCO2_L1B_DSET_NAME);
787  throw InternalErr(__FILE__, __LINE__, msg);
788  }
789 
790  size_t total_data_size = num_elem * H5Tget_size(dtype);
791 
792  if (H5Tis_variable_str(dtype)) {
793 
794  vector<char>temp_buf;
795  temp_buf.resize(total_data_size);
796 
797  if (H5Dread(s_dset_id,dtype,H5S_ALL,H5S_ALL,H5P_DEFAULT, &temp_buf[0])<0){
798  H5Tclose(dtype);
799  H5Dclose(s_dset_id);
800  H5Sclose(dspace);
801  H5Gclose(s_group_id);
802  H5Gclose(s_root_id);
803  string msg = "cannot get the the dataspace of HDF5 dataset ";
804  msg += string(ACOS_L2S_OCO2_L1B_DSET_NAME);
805  throw InternalErr(__FILE__, __LINE__, msg);
806  }
807 
808  char *temp_bp = &temp_buf[0];
809  char *onestring = NULL;
810  string total_string="";
811 
812  for (int temp_i = 0; temp_i <num_elem; temp_i++) {
813 
814  // This line will assure that we get the real variable length string value.
815  onestring =*(char **)temp_bp;
816 
817  // Change the C-style string to C++ STD string just for easy handling.
818  if (onestring !=NULL) {
819  string tempstring(onestring);
820  total_string+=tempstring;
821  }
822  // going to the next value.
823  temp_bp += dtype_size;
824  }
825 
826  // Reclaim any VL memory if necessary.
827  herr_t ret_vlen_claim;
828  ret_vlen_claim = H5Dvlen_reclaim(dtype,dspace,H5P_DEFAULT,&temp_buf[0]);
829  if(ret_vlen_claim < 0) {
830  H5Sclose(dspace);
831  H5Tclose(dtype);
832  H5Dclose(s_dset_id);
833  H5Gclose(s_group_id);
834  throw InternalErr(__FILE__, __LINE__, "Cannot reclaim the memory buffer of the HDF5 variable length string.");
835  }
836  H5Sclose(dspace);
837  H5Tclose(dtype);
838  H5Dclose(s_dset_id);
839  H5Gclose(s_group_id);
840 
841  if (total_string.compare(ACOS_L2S_ATTR_VALUE) ==0 ||
842  total_string.compare(OCO2_L1B_ATTR_VALUE) ==0 ||
843  total_string.compare(OCO2_L1B_ATTR_VALUE2)==0)
844  return_flag = true;
845  }
846  else {
847  vector<char> temp_buf(total_data_size+1);
848  if (H5Dread(s_dset_id,dtype,H5S_ALL,H5S_ALL,H5P_DEFAULT, &temp_buf[0])<0){
849  H5Tclose(dtype);
850  H5Dclose(s_dset_id);
851  H5Sclose(dspace);
852  H5Gclose(s_group_id);
853  H5Gclose(s_root_id);
854  string msg = "cannot data of HDF5 dataset ";
855  msg += string(ACOS_L2S_OCO2_L1B_DSET_NAME);
856  throw InternalErr(__FILE__, __LINE__, msg);
857  }
858 
859  string total_string(temp_buf.begin(),temp_buf.end()-1);
860  H5Sclose(dspace);
861  H5Tclose(dtype);
862  H5Dclose(s_dset_id);
863  H5Gclose(s_group_id);
864 
865  if (0 == total_string.compare(ACOS_L2S_ATTR_VALUE) ||
866  0 == total_string.compare(OCO2_L1B_ATTR_VALUE))
867  return_flag = true;
868  else
869  return_flag = false;
870  }
871  }
872  else if (0 == has_acos_dset) {
873  H5Gclose(s_group_id);
874  return_flag = false;
875  }
876  else {
877  string msg = "Fail to determine if the HDF5 link ";
878  msg += string(ACOS_L2S_OCO2_L1B_DSET_NAME);
879  msg +=" exists ";
880  H5Gclose(s_group_id);
881  H5Gclose(s_root_id);
882  throw InternalErr(__FILE__, __LINE__, msg);
883  }
884  }
885  else ;// Other product, don't do anything.
886  }
887  else if (0 == has_smac_group)
888  return_flag = false;
889  else {
890  string msg = "Fail to determine if the link ";
891  msg += string(SMAC2S_META_GROUP_NAME);
892  msg +=" exists or not ";
893  H5Gclose(s_root_id);
894  throw InternalErr(__FILE__, __LINE__, msg);
895  }
896  return return_flag;
897 }
898 
899 void obtain_gm_attr_value(hid_t s_root_id, const char* s_attr_name, string & s_attr_value) {
900 
901  hid_t s_attr_id = -1;
902  if ((s_attr_id = H5Aopen_by_name(s_root_id,".",s_attr_name,
903  H5P_DEFAULT, H5P_DEFAULT)) <0) {
904  string msg = "Cannot open the HDF5 attribute ";
905  msg += string(s_attr_name);
906  H5Gclose(s_root_id);
907  throw InternalErr(__FILE__, __LINE__, msg);
908  }
909 
910  hid_t attr_type = -1;
911  if ((attr_type = H5Aget_type(s_attr_id)) < 0) {
912  string msg = "cannot get the attribute datatype for the attribute ";
913  msg += string(s_attr_name);
914  H5Aclose(s_attr_id);
915  H5Gclose(s_root_id);
916  }
917 
918  hid_t attr_space = -1;
919  if ((attr_space = H5Aget_space(s_attr_id)) < 0) {
920  string msg = "cannot get the hdf5 dataspace id for the attribute ";
921  msg += string(s_attr_name);
922  H5Tclose(attr_type);
923  H5Aclose(s_attr_id);
924  H5Gclose(s_root_id);
925  throw InternalErr(__FILE__, __LINE__, msg);
926  }
927 
928  int num_elm = H5Sget_simple_extent_npoints(attr_space);
929  if (0 == num_elm) {
930  string msg = "cannot get the number for the attribute ";
931  msg += string(s_attr_name);
932  H5Tclose(attr_type);
933  H5Aclose(s_attr_id);
934  H5Sclose(attr_space);
935  H5Gclose(s_root_id);
936  throw InternalErr(__FILE__, __LINE__, msg);
937  }
938 
939  size_t atype_size = H5Tget_size(attr_type);
940  if (atype_size <= 0) {
941  string msg = "cannot obtain the datatype size of the attribute ";
942  msg += string(s_attr_name);
943  H5Tclose(attr_type);
944  H5Aclose(s_attr_id);
945  H5Sclose(attr_space);
946  H5Gclose(s_root_id);
947  throw InternalErr(__FILE__, __LINE__, msg);
948  }
949 
950  if(H5Tis_variable_str(attr_type)) {
951 
952  vector<char> temp_buf;
953  // Variable length string attribute values only store pointers of the actual string value.
954  temp_buf.resize(atype_size*num_elm);
955  if (H5Aread(s_attr_id, attr_type, &temp_buf[0]) < 0) {
956  string msg = "cannot retrieve the value of the attribute ";
957  msg += string(s_attr_name);
958  H5Tclose(attr_type);
959  H5Aclose(s_attr_id);
960  H5Sclose(attr_space);
961  H5Gclose(s_root_id);
962  throw InternalErr(__FILE__, __LINE__, msg);
963  }
964 
965  char *temp_bp;
966  temp_bp = &temp_buf[0];
967  char* onestring;
968  for (unsigned int temp_i = 0; temp_i <num_elm; temp_i++) {
969 
970  // This line will assure that we get the real variable length string value.
971  onestring =*(char **)temp_bp;
972 
973  // Change the C-style string to C++ STD string just for easy appending the attributes in DAP.
974  if (onestring !=NULL)
975  string tempstring(onestring);
976  }
977 
978  temp_bp +=H5Tget_size(attr_type);
979 
980  if (temp_buf.empty() != true) {
981 
982  // Reclaim any VL memory if necessary.
983  herr_t ret_vlen_claim;
984  ret_vlen_claim = H5Dvlen_reclaim(attr_type,attr_space,H5P_DEFAULT,&temp_buf[0]);
985  if(ret_vlen_claim < 0){
986  H5Tclose(attr_type);
987  H5Aclose(s_attr_id);
988  H5Sclose(attr_space);
989  throw InternalErr(__FILE__, __LINE__, "Cannot reclaim the memory buffer of the HDF5 variable length string.");
990  }
991 
992  temp_buf.clear();
993  }
994  }
995  else {
996  vector<char> temp_buf(atype_size*num_elm+1);
997  if (H5Aread(s_attr_id,attr_type, &temp_buf[0])<0){
998  string msg = "cannot retrieve the value of the attribute ";
999  msg += string(s_attr_name);
1000  H5Tclose(attr_type);
1001  H5Aclose(s_attr_id);
1002  H5Sclose(attr_space);
1003  H5Gclose(s_root_id);
1004  throw InternalErr(__FILE__, __LINE__, msg);
1005 
1006  }
1007 
1008  string temp_attr_value(temp_buf.begin(),temp_buf.end());
1009  size_t temp_null_pos = temp_attr_value.find_first_of('\0');
1010  s_attr_value = temp_attr_value.substr(0,temp_null_pos);
1011  }
1012  H5Tclose(attr_type);
1013  H5Sclose(attr_space);
1014  H5Aclose(s_attr_id);
1015 
1016 }
HDF5GCFProduct.h
This file includes functions to identify different NASA HDF5 products. Current supported products inc...
libdap
Definition: BESDapFunctionResponseCache.h:35