bes Updated for version 3.20.13
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
38using namespace std;
39using 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.
44H5GCFProduct 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
114bool 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,nullptr,
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.data(),
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.data(),&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.data(),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, nullptr);
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
239bool 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
295bool 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,nullptr,
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.data(),
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.data(),&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.data(),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 = (int)(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, nullptr);
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
438bool 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
509bool 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.
560bool 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.
613bool 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.
660bool 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.data())<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.data();
810 char *onestring = nullptr;
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 !=nullptr) {
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.data());
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.data())<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
900void 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 = (int)(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.data()) < 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.data();
968 char* onestring;
969 for (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 !=nullptr)
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.data());
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.data())<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...