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