28#include <unordered_set>
37#include <libdap/Str.h>
38#include <libdap/Structure.h>
39#include <libdap/util.h>
40#include <libdap/D4Attributes.h>
42#include <BESNotFoundError.h>
43#include <BESInternalError.h>
44#include <BESInternalFatalError.h>
46#include <TheBESKeys.h>
47#include <BESContextManager.h>
50#include "DmrppTypeFactory.h"
51#include "DmrppD4Group.h"
52#include "DmrppArray.h"
54#include "D4ParserSax2.h"
58#define ERROR(x) do { cerr << "ERROR: " << x << " " << __FILE__ << ":" << __LINE__ << endl; } while(false)
63using SD_mapping_info_t =
struct {
77namespace build_dmrpp_util_h4 {
81#define VERBOSE(x) do { if (verbose) (x); } while(false)
82#define prolog std::string("build_dmrpp_h4::").append(__func__).append("() - ")
84constexpr auto INVOCATION_CONTEXT =
"invocation";
88int SDfree_mapping_info(SD_mapping_info_t *map_info)
90 intn ret_value = SUCCEED;
93 if (map_info ==
nullptr)
96 map_info->nblocks = 0;
98 if (map_info->offsets !=
nullptr) {
99 HDfree(map_info->offsets);
100 map_info->offsets =
nullptr;
103 if (map_info->lengths) {
104 HDfree(map_info->lengths);
105 map_info->lengths =
nullptr;
111void close_hdf4_file_ids(int32 sd_id, int32 file_id) {
118size_t combine_linked_blocks(
const SD_mapping_info_t &map_info, vector<int> & merged_lengths, vector<int> &merged_offsets) {
120 int num_eles = map_info.nblocks;
123 for (
int i = 0; i<offset.size(); i++) {
124 cout<<
"offset["<<i<<
"]= "<<offset[i] <<endl;
125 cout<<
"length["<<i<<
"]= "<<length[i] <<endl;
130 merged_offsets.push_back(map_info.offsets[0]);
132 int temp_length = map_info.lengths[0];
134 for (
int i = 0; i <(num_eles-1); i++) {
139 if (map_info.offsets[i+1] !=(map_info.offsets[i] + map_info.lengths[i])) {
140 merged_lengths.push_back(temp_length);
141 merged_offsets.push_back(map_info.offsets[i+1]);
142 temp_length = map_info.lengths[i+1];
145 temp_length +=map_info.lengths[i+1];
151 merged_lengths.push_back(temp_length);
153 return merged_lengths.size();
165vector<unsigned long long>
166write_chunk_position_in_array(
int rank,
const unsigned long long *lengths,
const int32_t *strides)
168 vector<unsigned long long> chunk_pos;
170 for(
int i = 0; i < rank; i++){
171 unsigned long long index = lengths[i] * (
unsigned long long)strides[i];
172 chunk_pos.push_back(index);
192int read_chunk(
int sdsid, SD_mapping_info_t *map_info,
int *origin)
194 intn ret_value = SUCCEED;
198 SDfree_mapping_info(map_info);
207 intn info_count = SDgetdatainfo(sdsid, origin, 0, 0,
nullptr,
nullptr);
208 if (info_count == FAIL) {
209 ERROR(
"SDgetedatainfo() failed in read_chunk().\n");
214 if (info_count > 0) {
215 map_info->nblocks = (int32) info_count;
216 map_info->offsets = (int32 *)HDmalloc(
sizeof(int32)*map_info->nblocks);
217 if (map_info->offsets ==
nullptr) {
218 ERROR(
"HDmalloc() failed: Out of Memory");
221 map_info->lengths = (int32 *)HDmalloc(
sizeof(int32)*map_info->nblocks);
222 if (map_info->lengths ==
nullptr) {
223 HDfree(map_info->offsets);
224 ERROR(
"HDmalloc() failed: Out of Memory");
228 ret_value = SDgetdatainfo(sdsid, origin, 0, info_count, map_info->offsets, map_info->lengths);
236string get_sds_fill_value_str(int32 sdsid, int32 datatype) {
240 if (SDcheckempty(sdsid,&emptySDS) == FAIL) {
242 throw BESInternalError(
"SDcheckempty fails. ",__FILE__,__LINE__);
251 if (SDgetfillvalue(sdsid, &fvalue) == SUCCEED)
252 ret_value = to_string(fvalue);
254 else if(emptySDS == 1)
255 ret_value = to_string(255);
261 if (SDgetfillvalue(sdsid, &fvalue) == SUCCEED)
262 ret_value = to_string(fvalue);
263 else if(emptySDS == 1)
264 ret_value = to_string(FILL_BYTE);
270 if (SDgetfillvalue(sdsid, &fvalue) == SUCCEED)
271 ret_value = to_string(fvalue);
272 else if(emptySDS == 1)
273 ret_value = to_string(FILL_SHORT);
279 if (SDgetfillvalue(sdsid, &fvalue) == SUCCEED)
280 ret_value = to_string(fvalue);
281 else if(emptySDS == 1)
282 ret_value = to_string(65535);
288 if (SDgetfillvalue(sdsid, &fvalue) == SUCCEED)
289 ret_value = to_string(fvalue);
290 else if(emptySDS == 1)
291 ret_value = to_string(FILL_LONG);
297 if (SDgetfillvalue(sdsid, &fvalue) == SUCCEED)
298 ret_value = to_string(fvalue);
299 else if(emptySDS == 1)
300 ret_value = to_string(4294967295);
306 if (SDgetfillvalue(sdsid, &fvalue) == SUCCEED)
307 ret_value = to_string(fvalue);
308 else if(emptySDS == 1)
309 ret_value = to_string(FILL_FLOAT);
315 if (SDgetfillvalue(sdsid, &fvalue) == SUCCEED)
316 ret_value = to_string(fvalue);
317 else if(emptySDS == 1)
318 ret_value = to_string(FILL_DOUBLE);
328bool SD_set_fill_value(int32 sdsid, int32 datatype, BaseType *btp) {
330 string fill_value = get_sds_fill_value_str(sdsid,datatype);
331 if (!fill_value.empty()) {
332 auto dc =
dynamic_cast<DmrppCommon *
>(btp);
334 ERROR(
"Expected to find a DmrppCommon instance but did not.");
337 dc->set_uses_fill_value(
true);
338 dc->set_fill_value_string(fill_value);
342bool ingest_sds_info_to_chunk(
int file, int32 obj_ref, BaseType *btp) {
344 int32 sds_index = SDreftoindex(file, obj_ref);
345 if (sds_index == FAIL) {
346 ERROR(
"SDreftoindex() failed");
350 int sdsid = SDselect(file, sds_index);
352 ERROR(
"SDselect() failed");
356 VERBOSE(cerr <<
"Name: " << btp->name() << endl);
357 VERBOSE(cerr <<
"DMR FQN: " << btp->FQN() << endl);
358 VERBOSE(cerr <<
"sdsid: " << sdsid << endl);
360 char obj_name[H4_MAX_NC_NAME];
362 int32 dimsizes[H4_MAX_VAR_DIMS];
363 int32 data_type = -1;
364 int32 num_attrs = -1;
366 int status = SDgetinfo(sdsid, obj_name, &rank, dimsizes, &data_type, &num_attrs);
367 if (status == FAIL) {
368 ERROR(
"SDgetinfo() failed.");
374 int32 chunk_flag = -1;
376 status = SDgetchunkinfo(sdsid, &cdef, &chunk_flag);
377 if (status == FAIL) {
378 ERROR(
"SDgetchunkinfo() failed.");
383 switch (chunk_flag) {
385 VERBOSE(cerr <<
"No chunking.\n");
390 ERROR(
"Invalid rank.");
394 VERBOSE(cerr <<
"HDF_CHUNK or HDF_COMP.\n");
398 ERROR(
"NBit Compression chunking not supported.");
402 ERROR(
"Unknown chunking flag.");
409 int result = Hgetntinfo(data_type, &info);
410 if (result == FAIL) {
411 ERROR(
"Hgetntinfo() failed.");
416 if (strncmp(info.byte_order,
"bigEndian", 9) == 0)
418 else if (strncmp(info.byte_order,
"littleEndian", 12) == 0)
421 endian_name =
"UNKNOWN";
424 auto dc =
dynamic_cast<DmrppCommon *
>(btp);
426 ERROR(
"Expected to find a DmrppCommon instance but did not.");
434 comp_coder_t comp_coder_type = COMP_CODE_NONE;
437 if (SDgetcompinfo(sdsid, &comp_coder_type, &c_info) == FAIL) {
438 ERROR(
"SDgetcompinfo() failed.");
444 if (chunk_flag == HDF_CHUNK || chunk_flag == HDF_COMP ) {
445 vector<unsigned long long> chunk_dimension_sizes(rank, 0);
446 for (
int i = 0; i < rank; i++) {
447 if (chunk_flag == HDF_CHUNK) {
448 chunk_dimension_sizes[i] = cdef.chunk_lengths[i];
451 chunk_dimension_sizes[i] = cdef.comp.chunk_lengths[i];
454 if (chunk_flag == HDF_COMP) {
456 if (comp_coder_type == COMP_CODE_DEFLATE) {
457 dc->ingest_compression_type(
"deflate");
458 vector<unsigned int> deflate_levels;
459 deflate_levels.push_back(c_info.deflate.level);
460 dc->set_deflate_levels(deflate_levels);
463 ERROR(
"Encounter unsupported compression method. Currently only support deflate compression.");
468 dc->set_chunk_dimension_sizes(chunk_dimension_sizes);
472 SD_mapping_info_t map_info;
473 map_info.is_empty = 0;
474 map_info.nblocks = 0;
475 map_info.offsets =
nullptr;
476 map_info.lengths =
nullptr;
477 map_info.data_type = data_type;
481 vector<unsigned long long> position_in_array(rank, 0);
484 vector<int> steps(rank, 0);
485 vector<int32_t> strides(rank, 0);
486 int number_of_chunks = 1;
487 for (
int i = 0; i < rank; i++) {
489 steps[i] = 1 + ((dimsizes[i] - 1) / chunk_dimension_sizes[i]);
490 number_of_chunks = number_of_chunks * steps[i];
494 VERBOSE(cerr <<
"number_of_chunks: " << number_of_chunks << endl);
495 VERBOSE(cerr <<
"rank: " << rank << endl);
496 VERBOSE(cerr <<
"chunk dimension sizes: ");
497 VERBOSE(copy(chunk_dimension_sizes.begin(), chunk_dimension_sizes.end(),
498 ostream_iterator<int32>(cerr,
" ")));
502 vector<uint32> info_count(number_of_chunks);
503 intn max_num_blocks = SDgetallchunkdatainfo(sdsid,number_of_chunks,rank,steps.data(),0,info_count.data(),
505 if (max_num_blocks == FAIL) {
506 ERROR(
"SDgetallchunkdatainfo failed.");
511 vector<int32>offsetarray(max_num_blocks*number_of_chunks);
512 vector<int32>lengtharray(max_num_blocks*number_of_chunks);
514 max_num_blocks = SDgetallchunkdatainfo(sdsid,number_of_chunks,rank,steps.data(),max_num_blocks,info_count.data(),
515 offsetarray.data(),lengtharray.data());
516 if (max_num_blocks == FAIL) {
517 ERROR(
"SDgetallchunkdatainfo failed.");
521 bool LBChunk = (max_num_blocks>1);
524 for (
int k = 0; k < number_of_chunks; ++k) {
526 auto pia = write_chunk_position_in_array(rank, chunk_dimension_sizes.data(), strides.data());
529 if (info_count[k] >1) {
531 VERBOSE(cerr <<
"number of blocks in a chunk is: " << info_count[k]<< endl);
532 for (
unsigned int i = 0; i < info_count[k]; i++) {
533 VERBOSE(cerr <<
"offsets[" << k <<
", " << i <<
"]: " << offsetarray[ol_counter] << endl);
534 VERBOSE(cerr <<
"lengths[" << k <<
", " << i <<
"]: " << lengtharray[ol_counter] << endl);
536 dc->add_chunk(endian_name, lengtharray[ol_counter], offsetarray[ol_counter], pia,
true,i);
539 ol_counter +=max_num_blocks-info_count[k];
543 else if (info_count[k] == 1) {
545 dc->add_chunk(endian_name, lengtharray[ol_counter], offsetarray[ol_counter], pia);
546 ol_counter +=max_num_blocks;
548 else if (info_count[k] == 0)
549 ol_counter +=max_num_blocks;
553 for(
int i = rank-1; i >= 0 ; i--) {
554 if ((k+1) % scale == 0) {
555 strides[i] = ++strides[i] % steps[i];
557 scale = scale * steps[i];
561 dc->set_multi_linked_blocks_chunk(LBChunk);
567 if (chunk_flag == HDF_CHUNK || chunk_flag == HDF_COMP ) {
568 vector<unsigned long long> chunk_dimension_sizes(rank, 0);
569 for (
int i = 0; i < rank; i++) {
570 if (chunk_flag == HDF_CHUNK) {
571 chunk_dimension_sizes[i] = cdef.chunk_lengths[i];
574 chunk_dimension_sizes[i] = cdef.comp.chunk_lengths[i];
577 if (chunk_flag == HDF_COMP) {
579 if (comp_coder_type == COMP_CODE_DEFLATE) {
580 dc->ingest_compression_type(
"deflate");
581 vector<unsigned int> deflate_levels;
582 deflate_levels.push_back(c_info.deflate.level);
583 dc->set_deflate_levels(deflate_levels);
586 ERROR(
"Encounter unsupported compression method. Currently only support deflate compression.");
591 dc->set_chunk_dimension_sizes(chunk_dimension_sizes);
593 SD_mapping_info_t map_info;
594 map_info.is_empty = 0;
595 map_info.nblocks = 0;
596 map_info.offsets =
nullptr;
597 map_info.lengths =
nullptr;
598 map_info.data_type = data_type;
600 vector<unsigned long long> position_in_array(rank, 0);
603 vector<int> steps(rank, 0);
604 vector<int32_t> strides(rank, 0);
605 int number_of_chunks = 1;
606 for(
int i = 0; i < rank; i++) {
607 steps[i] = 1 + ((dimsizes[i] - 1) / chunk_dimension_sizes[i]);
608 number_of_chunks = number_of_chunks * steps[i];
612 VERBOSE(cerr <<
"number_of_chunks: " << number_of_chunks << endl);
613 VERBOSE(cerr <<
"rank: " << rank << endl);
614 VERBOSE(cerr <<
"chunk dimension sizes: ");
615 VERBOSE(copy(chunk_dimension_sizes.begin(), chunk_dimension_sizes.end(),
616 ostream_iterator<int32>(cerr,
" ")));
619 bool LBChunk =
false;
621 for (
int k = 0; k < number_of_chunks; ++k) {
622 auto info_count = read_chunk(sdsid, &map_info, strides.data());
623 if (info_count == FAIL) {
624 ERROR(
"read_chunk() failed.");
629 auto pia = write_chunk_position_in_array(rank, chunk_dimension_sizes.data(), strides.data());
632 if (map_info.nblocks >1) {
636 VERBOSE(cerr <<
"number of blocks in a chunk is: " << map_info.nblocks << endl);
637 for (
unsigned int i = 0; i < map_info.nblocks; i++) {
638 VERBOSE(cerr <<
"offsets[" << k <<
", " << i <<
"]: " << map_info.offsets[i] << endl);
639 VERBOSE(cerr <<
"lengths[" << k <<
", " << i <<
"]: " << map_info.lengths[i] << endl);
641 dc->add_chunk(endian_name, map_info.lengths[i], map_info.offsets[i], pia,
true,i);
646 else if (map_info.nblocks == 1) {
647 dc->add_chunk(endian_name, map_info.lengths[0], map_info.offsets[0], pia);
652 for(
int i = rank-1; i >= 0 ; i--) {
653 if ((k+1) % scale == 0) {
654 strides[i] = ++strides[i] % steps[i];
656 scale = scale * steps[i];
658 SDfree_mapping_info(&map_info);
661 dc->set_multi_linked_blocks_chunk(LBChunk);
664 else if (chunk_flag == HDF_NONE) {
665 SD_mapping_info_t map_info;
666 map_info.is_empty = 0;
667 map_info.nblocks = 0;
668 map_info.offsets =
nullptr;
669 map_info.lengths =
nullptr;
670 map_info.data_type = data_type;
673 if (comp_coder_type != COMP_CODE_NONE) {
674 if (comp_coder_type == COMP_CODE_DEFLATE) {
675 dc->ingest_compression_type(
"deflate");
676 vector<unsigned int> deflate_levels;
677 deflate_levels.push_back(c_info.deflate.level);
678 dc->set_deflate_levels(deflate_levels);
681 ERROR(
"Encounter unsupported compression method. Currently only support deflate compression.");
687 vector<int> origin(rank, 0);
688 auto info_count = read_chunk(sdsid, &map_info, origin.data());
689 if (info_count == FAIL) {
690 ERROR(
"read_chunk() failed in the middle of ingest_sds_info_to_chunk().");
695 vector<unsigned long long> position_in_array(rank, 0);
696 if (map_info.nblocks ==1) {
697 dc->add_chunk(endian_name, map_info.lengths[0], map_info.offsets[0], position_in_array);
699 else if (map_info.nblocks>1) {
703 vector<int> merged_lengths;
704 vector<int> merged_offsets;
705 size_t merged_number_blocks = combine_linked_blocks(map_info, merged_lengths, merged_offsets);
706 for (
unsigned i = 0; i < merged_number_blocks; i++) {
707 VERBOSE(cerr <<
"offsets[" << i <<
"]: " << map_info.offsets[i] << endl);
708 VERBOSE(cerr <<
"lengths[" << i <<
"]: " << map_info.lengths[i] << endl);
711 dc->add_chunk(endian_name, merged_lengths[i], merged_offsets[i],
true,i);
715 SDfree_mapping_info(&map_info);
719 ERROR(
"Unknown chunking type.");
725 if (
false == SD_set_fill_value(sdsid,data_type, btp)) {
726 ERROR(
"SD_set_fill_value failed");
736size_t combine_linked_blocks_vdata(
const vector<int>& lengths,
const vector<int>& offsets, vector<int> & merged_lengths, vector<int> &merged_offsets) {
738 size_t num_eles = lengths.size();
741 for (
int i = 0; i<offset.size(); i++) {
742 cout<<
"offset["<<i<<
"]= "<<offset[i] <<endl;
743 cout<<
"length["<<i<<
"]= "<<length[i] <<endl;
748 merged_offsets.push_back(offsets[0]);
749 int temp_length = lengths[0];
751 for (
size_t i = 0; i <(num_eles-1); i++) {
756 if (offsets[i+1] !=(offsets[i] + lengths[i])) {
757 merged_lengths.push_back(temp_length);
758 merged_offsets.push_back(offsets[i+1]);
759 temp_length = lengths[i+1];
762 temp_length +=lengths[i+1];
768 merged_lengths.push_back(temp_length);
771for (
int i = 0; i <merged_lengths.size(); i++) {
772cout <<
"merged_lengths["<<i<<
"]= "<<merged_lengths[i]<<endl;
773cout <<
"merged_offsets["<<i<<
"]= "<<merged_offsets[i]<<endl;
777 return merged_lengths.size();
782bool ingest_vdata_info_to_chunk(int32 file_id, int32 obj_ref, BaseType *btp) {
784 int32 vdata_id = VSattach(file_id, obj_ref,
"r");
785 if (vdata_id == FAIL){
786 ERROR(
"VSattach() failed.");
791 int32 field_datatype = VFfieldtype(vdata_id,0);
792 if (field_datatype == FAIL){
793 ERROR(
"VFfieldtype() failed.");
800 int result = Hgetntinfo(field_datatype, &info);
801 if (result == FAIL) {
802 ERROR(
"Hgetntinfo() failed in ingest_vdata_info_to_chunk.");
807 if (strncmp(info.byte_order,
"bigEndian", 9) == 0)
809 else if (strncmp(info.byte_order,
"littleEndian", 12) == 0)
812 endian_name =
"UNKNOWN";
815 int32 num_linked_blocks = VSgetdatainfo(vdata_id,0,0,
nullptr,
nullptr);
817 if (num_linked_blocks == FAIL){
818 ERROR(
"VSgetdatainfo() failed in ingest_vdata_info_to_chunk.");
822 if (num_linked_blocks == 1) {
826 if (VSgetdatainfo(vdata_id,0,1,&offset,&length) == FAIL){
827 ERROR(
"VSgetdatainfo() failed, cannot obtain offset and length info.");
832 auto dc =
dynamic_cast<DmrppCommon *
>(btp);
834 ERROR(
"Expected to find a DmrppCommon instance but did not in ingested_vdata_info_to_chunk");
838 auto da =
dynamic_cast<DmrppArray *
>(btp);
840 ERROR(
"Expected to find a DmrppArray instance but did not in ingested_vdata_info_to_chunk");
845 if (da->width_ll() != (int64_t)length) {
846 ERROR(
"The retrieved vdata size is no equal to the original size.");
850 dc->add_chunk(endian_name, (
unsigned long long)length, (
unsigned long long)offset,
"");
853 int32 total_num_fields = VFnfields(vdata_id);
854 if (total_num_fields == 1) {
857 VSgetdatainfo(vdata_id,0,1,&offset,&length);
858cout <<
"offset is: "<<offset <<endl;
859cout <<
"length is: "<<length <<endl;
865 else if (num_linked_blocks >1) {
870 lengths.resize(num_linked_blocks);
871 offsets.resize(num_linked_blocks);
872 if (VSgetdatainfo(vdata_id, 0, num_linked_blocks, offsets.data(), lengths.data()) == FAIL) {
873 ERROR(
"VSgetdatainfo() failed, cannot obtain offset and length info when the num_linked_blocks is >1.");
877 vector<int>merged_lengths;
878 vector<int>merged_offsets;
879 size_t merged_number_blocks = combine_linked_blocks_vdata(lengths,offsets,merged_lengths,merged_offsets);
880 auto dc =
dynamic_cast<DmrppCommon *
>(btp);
882 ERROR(
"Expected to find a DmrppArray instance but did not when num_linked_blocks is >1.");
887 for (
unsigned i = 0; i < merged_number_blocks; i++)
888 dc->add_chunk(endian_name, merged_lengths[i], merged_offsets[i],
true,i);
898bool obtain_compress_encode_data(
string &encoded_str,
const Bytef*source_data,
size_t source_data_size,
string &err_msg) {
900 uLong ssize = (uLong)source_data_size;
901 uLongf csize = (uLongf)ssize*2;
902 vector<Bytef> compressed_src;
903 compressed_src.resize(source_data_size*2);
905 int retval = compress(compressed_src.data(), &csize, source_data, ssize);
907 err_msg =
"Fail to compress the data";
911 encoded_str = base64::Base64::encode(compressed_src.data(),(
int)csize);
918bool add_missing_cf_grid(
const string &filename,BaseType *btp,
const D4Attribute *eos_cf_attr,
string &err_msg) {
920 VERBOSE(cerr<<
"Coming to add_missing_cf_grid"<<endl);
922 string eos_cf_attr_value = eos_cf_attr->value(0);
924 VERBOSE(cerr<<
"eos_cf_attr_value: "<<eos_cf_attr_value <<endl);
926 size_t space_pos = eos_cf_attr_value.find_last_of(
' ');
927 if (space_pos ==string::npos) {
928 err_msg =
"Attribute eos_latlon must have space inside";
932 string grid_name = eos_cf_attr_value.substr(0,space_pos);
933 string cf_name = eos_cf_attr_value.substr(space_pos+1);
935 VERBOSE(cerr<<
"grid_name: "<<grid_name <<endl);
936 VERBOSE(cerr<<
"cf_name: "<<cf_name<<endl);
938 if (cf_name ==
"YDim")
941 int32 gridfd = GDopen(
const_cast < char *
>(filename.c_str()), DFACC_READ);
943 err_msg =
"HDF-EOS: GDopen failed";
946 int32 gridid = GDattach(gridfd,
const_cast<char *
>(grid_name.c_str()));
948 err_msg =
"HDF-EOS: GDattach failed to attach " + grid_name;
960 if (GDgridinfo(gridid, &xdim, &ydim, upleft,
964 err_msg =
"GDgridinfo failed for grid name: " + grid_name;
968 auto dc =
dynamic_cast<DmrppCommon *
>(btp);
972 err_msg =
"Expected to find a DmrppCommon instance but did not in add_missing_cf_grid";
975 auto da =
dynamic_cast<DmrppArray *
>(btp);
979 err_msg =
"Expected to find a DmrppArray instance but did not in add_missing_cf_grid";
983 da->set_missing_data(
true);
985 int total_num = is_xdim?xdim:ydim;
986 vector<double>val(total_num);
992 evalue = lowright[0];
996 evalue = lowright[1];
999 double step_v = (evalue - svalue)/total_num;
1002 for(
int i = 1;i<total_num; i++)
1003 val[i] = val[i-1] + step_v;
1005 da->set_value(val.data(),total_num);
1006 da->set_read_p(
true);
1016bool add_missing_eos_latlon(
const string &filename,BaseType *btp,
const D4Attribute *eos_ll_attr,
string &err_msg) {
1018 VERBOSE(cerr<<
"Coming to add_missing_eos_latlon"<<endl);
1020 string eos_ll_attr_value = eos_ll_attr->value(0);
1022 VERBOSE(cerr<<
"eos_ll_attr_value: "<<eos_ll_attr_value <<endl);
1024 size_t space_pos = eos_ll_attr_value.find_last_of(
' ');
1025 if (space_pos ==string::npos) {
1026 err_msg =
"Attribute eos_latlon must have space inside";
1030 string grid_name = eos_ll_attr_value.substr(0,space_pos);
1031 string ll_name = eos_ll_attr_value.substr(space_pos+1);
1033 VERBOSE(cerr<<
"grid_name: "<<grid_name <<endl);
1034 VERBOSE(cerr<<
"ll_name: "<<ll_name<<endl);
1036 if (ll_name ==
"lon")
1039 int32 gridfd = GDopen(
const_cast < char *
>(filename.c_str()), DFACC_READ);
1041 err_msg =
"HDF-EOS: GDopen failed";
1044 int32 gridid = GDattach(gridfd,
const_cast<char *
>(grid_name.c_str()));
1046 err_msg =
"HDF-EOS: GDattach failed to attach " + grid_name;
1053 int32 projcode = -1;
1062 float64 lowright[2];
1064 if (GDprojinfo (gridid, &projcode, &zone, &sphere, params) <0) {
1067 err_msg =
"GDprojinfo failed for grid name: " + grid_name;
1072 if (GDgridinfo(gridid, &xdim, &ydim, upleft,
1076 err_msg =
"GDgridinfo failed for grid name: " + grid_name;
1083 intn r = GDpixreginfo (gridid, &pixreg);
1087 err_msg =
"GDpixreginfo failed for grid name: " + grid_name;
1093 r = GDorigininfo (gridid, &origin);
1097 err_msg =
"GDoriginfo failed for grid name: " + grid_name;
1105 rows.resize(xdim*ydim);
1106 cols.resize(xdim*ydim);
1107 lon.resize(xdim*ydim);
1108 lat.resize(xdim*ydim);
1123 for (k = j = 0; j < ydim; ++j) {
1124 for (i = 0; i < xdim; ++i) {
1132 r = GDij2ll (projcode, zone, params, sphere, xdim, ydim, upleft, lowright,
1133 xdim * ydim, rows.data(), cols.data(), lon.data(), lat.data(), pixreg, origin);
1138 err_msg =
"cannot calculate grid latitude and longitude for grid name: " + grid_name;
1142 VERBOSE(cerr<<
"The first value of longtitude: "<<lon[0]<<endl);
1143 VERBOSE(cerr<<
"The first value of latitude: "<<lat[0]<<endl);
1145 auto dc =
dynamic_cast<DmrppCommon *
>(btp);
1149 err_msg =
"Expected to find a DmrppCommon instance but did not in add_missing_eos_latlon";
1152 auto da =
dynamic_cast<DmrppArray *
>(btp);
1156 err_msg =
"Expected to find a DmrppArray instance but did not in add_missing_eos_latlon";
1160 da->set_missing_data(
true);
1164 if (projcode == GCTP_CEA || projcode == GCTP_GEO) {
1165 vector<float64>out_lat;
1166 out_lat.resize(ydim);
1168 for (i =0; i<xdim*ydim;i = i+xdim){
1169 out_lat[j] = lat[i];
1172 da->set_value(out_lat.data(),ydim);
1176 da->set_value(lat.data(),xdim*ydim);
1179 if (projcode == GCTP_CEA || projcode == GCTP_GEO) {
1180 vector<float64>out_lon;
1181 out_lon.resize(xdim);
1182 for (i =0; i<xdim;i++)
1183 out_lon[i] = lon[i];
1184 da->set_value(out_lon.data(),xdim);
1188 da->set_value(lon.data(),xdim*ydim);
1191 da->set_read_p(
true);
1194 size_t orig_buf_size = tmp_data.size()*
sizeof(double);
1195 uLong ssize = (uLong)orig_buf_size;
1196 uLongf csize = (uLongf)ssize*2;
1197 vector<Bytef> compressed_src;
1198 compressed_src.resize(orig_buf_size*2);
1200 int retval = compress(compressed_src.data(), &csize, (
const Bytef*)tmp_data.data(), ssize);
1202 cout<<
"Fail to compress the data"<<endl;
1206 string encoded = base64::Base64::encode(compressed_src.data(),(
int)csize);
1217bool add_missing_sp_latlon(BaseType *btp,
const D4Attribute *sp_ll_attr,
string &err_msg) {
1219 VERBOSE(cerr<<
"Coming to add_missing_sp_latlon"<<endl);
1221 string sp_ll_attr_value = sp_ll_attr->value(0);
1223 VERBOSE(cerr<<
"sp_ll_attr_value: "<<sp_ll_attr_value <<endl);
1224 size_t space_pos = sp_ll_attr_value.find(
' ');
1225 if (space_pos ==string::npos) {
1226 err_msg =
"Attribute sp_h4_ll must have space inside";
1229 string ll_name = sp_ll_attr_value.substr(0,space_pos);
1230 VERBOSE(cerr<<
"ll_name: "<<ll_name<<endl);
1232 size_t sec_space_pos = sp_ll_attr_value.find(
' ',space_pos+1);
1233 if (sec_space_pos ==string::npos) {
1234 err_msg =
"Attribute sp_h4_ll must have two spaces inside";
1237 string ll_start_str = sp_ll_attr_value.substr(space_pos+1,sec_space_pos-space_pos-1);
1238 VERBOSE(cerr<<
"ll_start: "<<ll_start_str<<endl);
1240 string ll_res_str = sp_ll_attr_value.substr(sec_space_pos);
1241 VERBOSE(cerr<<
"ll_res: "<<ll_res_str<<endl);
1243 float ll_start = stof(ll_start_str);
1244 float ll_res = stof(ll_res_str);
1246 auto dc =
dynamic_cast<DmrppCommon *
>(btp);
1248 err_msg =
"Expected to find a DmrppCommon instance but did not in add_missing_sp_latlon";
1251 auto da =
dynamic_cast<DmrppArray *
>(btp);
1253 err_msg =
"Expected to find a DmrppArray instance but did not in add_missing_sp_latlon";
1257 if (da->dimensions() !=1){
1258 err_msg =
"The number of dimensions of the array should be 1.";
1262 da->set_missing_data(
true);
1264 vector<float32> ll_value;
1265 ll_value.resize((
size_t)(da->length()));
1266 for (int64_t i = 0; i <da->length(); i++) {
1267 ll_value[i] = ll_start+ll_res/2+i*ll_res;
1270 da->set_value(ll_value.data(),da->length());
1280bool get_chunks_for_an_array(
const string& filename, int32 sd_id, int32 file_id, BaseType *btp,
bool disable_missing_data) {
1282 VERBOSE(cerr<<
"var name: "<<btp->name() <<endl);
1284 D4Attributes *d4_attrs = btp->attributes();
1286 close_hdf4_file_ids(sd_id,file_id);
1287 throw BESInternalError(
"Expected to find an DAP4 attribute list for " + btp->name() +
" but did not.",
1288 __FILE__, __LINE__);
1294 D4Attribute *attr = d4_attrs->find(
"dmr_sds_ref");
1296 bool is_sds =
false;
1300 attr = d4_attrs->find(
"dmr_vdata_ref");
1303 obj_ref = stoi(attr->value(0));
1305 if (
false == ingest_sds_info_to_chunk(sd_id, obj_ref,btp)) {
1306 close_hdf4_file_ids(sd_id,file_id);
1307 throw BESInternalError(
"Cannot retrieve SDS information correctly for " + btp->name() ,
1308 __FILE__, __LINE__);
1313 if (
false == ingest_vdata_info_to_chunk(file_id, obj_ref,btp)) {
1314 close_hdf4_file_ids(sd_id,file_id);
1315 throw BESInternalError(
"Cannot retrieve vdata information correctly for " + btp->name() ,
1316 __FILE__, __LINE__);
1320 else if (disable_missing_data ==
false){
1322 VERBOSE(cerr<<
"coming to eos_latlon block"<<endl);
1324 attr = d4_attrs->find(
"eos_latlon");
1327 bool ret_value = add_missing_eos_latlon(filename, btp, attr,err_msg);
1328 if (ret_value ==
false) {
1329 close_hdf4_file_ids(sd_id,file_id);
1330 throw BESInternalError(err_msg,__FILE__,__LINE__);
1335 attr = d4_attrs->find(
"sp_h4_ll");
1338 bool ret_value = add_missing_sp_latlon(btp, attr,err_msg);
1339 if (ret_value ==
false) {
1340 close_hdf4_file_ids(sd_id,file_id);
1341 throw BESInternalError(err_msg,__FILE__,__LINE__);
1345 attr = d4_attrs->find(
"eos_cf_grid");
1348 bool ret_value = add_missing_cf_grid(filename, btp, attr,err_msg);
1349 if (ret_value ==
false) {
1350 close_hdf4_file_ids(sd_id,file_id);
1351 throw BESInternalError(err_msg,__FILE__,__LINE__);
1356 close_hdf4_file_ids(sd_id,file_id);
1357 string error_msg =
"Expected to find an attribute that stores either HDF4 SDS reference or HDF4 Vdata reference or eos lat/lon or special HDF4 lat/lon or special cf grid for ";
1358 throw BESInternalError(error_msg + btp->name() +
" but did not.",__FILE__,__LINE__);
1369bool handle_chunks_for_none_array(BaseType *btp,
bool disable_missing_data,
string &err_msg) {
1371 bool ret_value =
false;
1373 VERBOSE(cerr<<
"For none_array: var name: "<<btp->name() <<endl);
1375 D4Attributes *d4_attrs = btp->attributes();
1376 if (d4_attrs->empty() ==
false && btp->type() == dods_byte_c) {
1378 auto attr = d4_attrs->find(
"eos_cf_grid_mapping");
1380 if (disable_missing_data ==
false) {
1385 auto dc =
dynamic_cast<DmrppCommon *
>(btp);
1387 err_msg =
"Expected to find a DmrppCommon instance but did not in handle_chunks_for_none_array";
1390 auto db =
dynamic_cast<DmrppByte *
>(btp);
1392 err_msg =
"Expected to find a DmrppByte instance but did not in handle_chunks_for_none_array";
1396 VERBOSE(cerr<<
"For none_array cf dummy grid variable: var name: "<<btp->name() <<endl);
1399 db->set_missing_data(
true);
1400 db->set_value((dods_byte)buf);
1401 db->set_read_p(
true);
1412bool get_chunks_for_a_variable(
const string& filename,int32 sd_id, int32 file_id, BaseType *btp,
bool disable_missing_data) {
1414 switch (btp->type()) {
1415 case dods_structure_c: {
1421 auto sp =
dynamic_cast<Structure *
>(btp);
1424 close_hdf4_file_ids(sd_id,file_id);
1425 throw BESInternalError(
"Structure scalar is not supported by DAP4 for HDF4 at this time.\n", __FILE__, __LINE__);
1427 case dods_sequence_c:
1428 VERBOSE(cerr << btp->FQN() <<
": Sequence is not supported by DMR++ for HDF4 at this time.\n");
1431 close_hdf4_file_ids(sd_id,file_id);
1432 throw BESInternalError(
"Grids are not supported by DAP4.", __FILE__, __LINE__);
1435 return get_chunks_for_an_array(filename,sd_id,file_id, btp,disable_missing_data);
1438 bool ret_value = handle_chunks_for_none_array(btp,disable_missing_data,err_msg);
1439 if (ret_value ==
false) {
1440 if (err_msg.empty() ==
false) {
1441 close_hdf4_file_ids(sd_id,file_id);
1442 throw BESInternalError(err_msg, __FILE__, __LINE__);
1445 VERBOSE(cerr << btp->FQN() <<
": " << btp->type_name() <<
" is not supported by DMR++ for HDF4 at this time.\n");
1459void get_chunks_for_all_variables(
const string& filename, int32 sd_id, int32 file_id, D4Group *group,
bool disable_missing_data) {
1462 for(
auto btp : group->variables()) {
1463 if (btp->type() != dods_group_c) {
1466 if (!get_chunks_for_a_variable(filename,sd_id,file_id, btp, disable_missing_data)) {
1467 ERROR(
"Could not include DMR++ metadata for variable " << btp->FQN());
1472 auto g =
dynamic_cast<D4Group*
>(btp);
1474 throw BESInternalError(
"Expected " + btp->name() +
" to be a D4Group but it is not.", __FILE__, __LINE__);
1475 get_chunks_for_all_variables(filename,sd_id,file_id, g, disable_missing_data);
1479 for (
auto g = group->grp_begin(), ge = group->grp_end(); g != ge; ++g) {
1480 get_chunks_for_all_variables(filename,sd_id,file_id, *g, disable_missing_data);
1490void add_chunk_information(
const string &h4_file_name, DMRpp *dmrpp,
bool disable_missing_data)
1493 int32 sd_id = SDstart(h4_file_name.c_str(), DFACC_READ);
1496 msg <<
"Error: HDF4 file '" << h4_file_name <<
"' cannot be opened." << endl;
1497 throw BESNotFoundError(msg.str(), __FILE__, __LINE__);
1500 int32 file_id = Hopen(h4_file_name.c_str(),DFACC_READ,0);
1503 msg <<
"Error: HDF4 file '" << h4_file_name <<
"' Hopen failed." << endl;
1504 throw BESNotFoundError(msg.str(), __FILE__, __LINE__);
1507 if (Vstart(file_id)<0) {
1509 msg <<
"Error: HDF4 file '" << h4_file_name <<
"' Vstart failed." << endl;
1510 throw BESNotFoundError(msg.str(), __FILE__, __LINE__);
1515 get_chunks_for_all_variables(h4_file_name, sd_id,file_id, dmrpp->root(),disable_missing_data);
1517 close_hdf4_file_ids(sd_id,file_id);
1535void qc_input_file(
const string &file_fqn)
1540 if (file_fqn.empty()) {
1542 msg <<
"HDF4 input file name must be provided (-f <input>) and be a fully qualified path name." << endl;
1543 throw BESInternalFatalError(msg.str(), __FILE__, __LINE__);
1546 std::ifstream file(file_fqn, ios::binary);
1547 auto errnum = errno;
1551 msg <<
"Encountered a Read/writing error when attempting to open the file: " << file_fqn << endl;
1552 msg <<
"* strerror(errno): " << strerror(errnum) << endl;
1553 msg <<
"* failbit: " << (((file.rdstate() & std::ifstream::failbit) != 0) ?
"true" :
"false") << endl;
1554 msg <<
"* badbit: " << (((file.rdstate() & std::ifstream::badbit) != 0) ?
"true" :
"false") << endl;
1555 msg <<
"Things to check:" << endl;
1556 msg <<
"* Does the file exist at expected location?" << endl;
1557 msg <<
"* Does your user have permission to read the file?" << endl;
1558 throw BESInternalFatalError(msg.str(), __FILE__, __LINE__);
1562 int status = Hishdf(file_fqn.c_str());
1567 msg <<
"The provided file: " << file_fqn <<
" - ";
1568 msg <<
"is not an HDF4 file" << endl;
1569 throw BESInternalFatalError(msg.str(), __FILE__, __LINE__);
1581static string recreate_cmdln_from_args(
int argc,
char *argv[])
1584 for(
int i=0; i<argc; i++) {
1597std::string what_time_is_it(){
1599 auto now = std::chrono::system_clock::now();
1602 auto time_t_now = std::chrono::system_clock::to_time_t(now);
1606 const std::tm* gmt_time = gmtime_r(&time_t_now, &tbuf);
1609 std::stringstream ss;
1610 ss << std::put_time(gmt_time,
"%Y-%m-%dT%H:%M:%SZ");
1624void inject_version_and_configuration_worker( DMRpp *dmrpp,
const string &bes_conf_doc,
const string &invocation)
1626 dmrpp->set_version(CVER);
1629 auto version_unique = make_unique<D4Attribute>(
"build_dmrpp_metadata", StringToD4AttributeType(
"container"));
1630 auto version = version_unique.get();
1632 auto creation_date_unique = make_unique<D4Attribute>(
"created", StringToD4AttributeType(
"string"));
1633 auto creation_date = creation_date_unique.get();
1634 creation_date->add_value(what_time_is_it());
1635 version->attributes()->add_attribute_nocopy(creation_date_unique.release());
1637 auto build_dmrpp_version_unique = make_unique<D4Attribute>(
"build_dmrpp", StringToD4AttributeType(
"string"));
1638 auto build_dmrpp_version = build_dmrpp_version_unique.get();
1639 build_dmrpp_version->add_value(CVER);
1640 version->attributes()->add_attribute_nocopy(build_dmrpp_version_unique.release());
1642 auto bes_version_unique = make_unique<D4Attribute>(
"bes", StringToD4AttributeType(
"string"));
1643 auto bes_version = bes_version_unique.get();
1644 bes_version->add_value(CVER);
1645 version->attributes()->add_attribute_nocopy(bes_version_unique.release());
1648 ldv << libdap_name() <<
"-" << libdap_version();
1649 auto libdap4_version_unique = make_unique<D4Attribute>(
"libdap", StringToD4AttributeType(
"string"));
1650 auto libdap4_version = libdap4_version_unique.get();
1651 libdap4_version->add_value(ldv.str());
1652 version->attributes()->add_attribute_nocopy(libdap4_version_unique.release());
1654 if(!bes_conf_doc.empty()) {
1656 auto config_unique = make_unique<D4Attribute>(
"configuration", StringToD4AttributeType(
"string"));
1657 auto config = config_unique.get();
1658 config->add_value(bes_conf_doc);
1659 version->attributes()->add_attribute_nocopy(config_unique.release());
1662 if(!invocation.empty()) {
1664 auto invoke_unique = make_unique<D4Attribute>(
"invocation", StringToD4AttributeType(
"string"));
1665 auto invoke = invoke_unique.get();
1666 invoke->add_value(invocation);
1667 version->attributes()->add_attribute_nocopy(invoke_unique.release());
1670 dmrpp->root()->attributes()->add_attribute_nocopy(version_unique.release());
1687 void inject_version_and_configuration(
int argc,
char **argv,
const string &bes_conf_file_used_to_create_dmr, DMRpp *dmrpp)
1689 string bes_configuration;
1691 if(!bes_conf_file_used_to_create_dmr.empty()) {
1697 invocation = recreate_cmdln_from_args(argc, argv);
1699 inject_version_and_configuration_worker(dmrpp, bes_configuration, invocation);
1713void inject_version_and_configuration(DMRpp *dmrpp)
1717 string bes_configuration;
1725 invocation = BESContextManager::TheManager()->
get_context(INVOCATION_CONTEXT, found);
1728 inject_version_and_configuration_worker(dmrpp, bes_configuration, invocation);
1743void build_dmrpp_from_dmr_file(
const string &dmrpp_href_value,
const string &dmr_filename,
const string &h4_file_fqn,
1744 bool add_production_metadata,
bool disable_missing_data,
const string &bes_conf_file_used_to_create_dmr,
int argc,
char *argv[])
1748 DmrppTypeFactory dtf;
1749 dmrpp.set_factory(&dtf);
1751 ifstream in(dmr_filename.c_str());
1752 D4ParserSax2 parser;
1753 parser.intern(in, &dmrpp,
false);
1755 add_chunk_information(h4_file_fqn, &dmrpp,disable_missing_data);
1757 if (add_production_metadata) {
1758 inject_version_and_configuration(argc,argv,bes_conf_file_used_to_create_dmr,&dmrpp);
1763 cout << writer.get_doc();
virtual std::string get_context(const std::string &name, bool &found)
retrieve the value of the specified context from the BES
std::string get_as_config() const
static TheBESKeys * TheKeys()
Access to the singleton.
static std::string ConfigFile
virtual void print_dmrpp(libdap::XMLWriter &xml, const std::string &href="", bool constrained=false, bool print_chunks=true)
Print the DMR++ response.