bes Updated for version 3.20.13
HDF5GMCFMissLLArray.cc
Go to the documentation of this file.
1// This file is part of the hdf5_handler implementing for the CF-compliant
2// Copyright (c) 2011-2016 The HDF Group, Inc. and OPeNDAP, Inc.
3//
4// This is free software; you can redistribute it and/or modify it under the
5// terms of the GNU Lesser General Public License as published by the Free
6// Software Foundation; either version 2.1 of the License, or (at your
7// option) any later version.
8//
9// This software is distributed in the hope that it will be useful, but
10// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
12// License for more details.
13//
14// You should have received a copy of the GNU Lesser General Public
15// License along with this library; if not, write to the Free Software
16// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17//
18// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
19// You can contact The HDF Group, Inc. at 1800 South Oak Street,
20// Suite 203, Champaign, IL 61820
21
31
32#include "config_hdf5.h"
33#include <iostream>
34#include <sstream>
35#include <cassert>
36#include <BESDebug.h>
37#include <libdap/InternalErr.h>
38#include "HDF5RequestHandler.h"
39#include "HDF5GMCFMissLLArray.h"
40#include "h5apicompatible.h"
41
42using namespace std;
43using namespace libdap;
44
45static int visit_obj_cb(hid_t group_id, const char *name, const H5O_info_t *oinfo, void *_op_data);
46static herr_t attr_info(hid_t loc_id, const char *name, const H5A_info_t *ainfo, void *_op_data);
47
48BaseType *HDF5GMCFMissLLArray::ptr_duplicate()
49{
50 return new HDF5GMCFMissLLArray(*this);
51}
52
53bool HDF5GMCFMissLLArray::read()
54{
55
56 BESDEBUG("h5", "Coming to HDF5GMCFMissLLArray read "<<endl);
57
58 if (nullptr == HDF5RequestHandler::get_lrdata_mem_cache())
59 read_data_NOT_from_mem_cache(false, nullptr);
60
61 else {
62
63 vector<string> cur_lrd_non_cache_dir_list;
64 HDF5RequestHandler::get_lrd_non_cache_dir_list(cur_lrd_non_cache_dir_list);
65
66 string cache_key;
67
68 // Check if this file is included in the non-cache directory
69 if ((cur_lrd_non_cache_dir_list.empty())
70 || ("" == check_str_sect_in_list(cur_lrd_non_cache_dir_list, filename, '/'))) {
71 short cache_flag = 2;
72 vector<string> cur_cache_dlist;
73 HDF5RequestHandler::get_lrd_cache_dir_list(cur_cache_dlist);
74 string cache_dir = check_str_sect_in_list(cur_cache_dlist, filename, '/');
75 if (cache_dir != "") {
76 cache_flag = 3;
77 cache_key = cache_dir + varname;
78 }
79 else
80 cache_key = filename + varname;
81
82 // Need to obtain the total number of elements.
83 // Obtain dimension size info.
84 vector<size_t> dim_sizes;
85 Dim_iter i_dim = dim_begin();
86 Dim_iter i_enddim = dim_end();
87 while (i_dim != i_enddim) {
88 dim_sizes.push_back(dimension_size(i_dim));
89 ++i_dim;
90 }
91
92 size_t total_elems = 1;
93 for (unsigned int i = 0; i < dim_sizes.size(); i++)
94 total_elems = total_elems * dim_sizes[i];
95
96 handle_data_with_mem_cache(dtype, total_elems, cache_flag, cache_key,false);
97 }
98 else
99 read_data_NOT_from_mem_cache(false, nullptr);
100 }
101 return true;
102}
103
104// Obtain latitude and longitude for Aquarius and OBPG level 3 products
105void HDF5GMCFMissLLArray::obtain_aqu_obpg_l3_ll(int* offset, int* step, int nelms, bool add_cache, void* buf)
106{
107
108 BESDEBUG("h5", "Coming to obtain_aqu_obpg_l3_ll read "<<endl);
109
110 // Read File attributes
111 // Latitude Step, SW Point Latitude, Number of Lines
112 // Longitude Step, SW Point Longitude, Number of Columns
113 if (1 != rank)
114 throw InternalErr(__FILE__, __LINE__, "The number of dimension for Aquarius Level 3 map data must be 1");
115
116 bool check_pass_fileid_key = HDF5RequestHandler::get_pass_fileid();
117 if (false == check_pass_fileid_key) {
118 if ((fileid = H5Fopen(filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) {
119 ostringstream eherr;
120 eherr << "HDF5 File " << filename << " cannot be opened. " << endl;
121 throw InternalErr(__FILE__, __LINE__, eherr.str());
122 }
123 }
124
125 hid_t rootid = -1;
126 if ((rootid = H5Gopen(fileid, "/", H5P_DEFAULT)) < 0) {
127 HDF5CFUtil::close_fileid(fileid, check_pass_fileid_key);
128 ostringstream eherr;
129 eherr << "HDF5 dataset " << varname << " cannot be opened. " << endl;
130 throw InternalErr(__FILE__, __LINE__, eherr.str());
131 }
132
133 float LL_first_point = 0.0;
134 float LL_step = 0.0;
135 int LL_total_num = 0;
136
137 if (CV_LAT_MISS == cvartype) {
138 string Lat_SWP_name = (Aqu_L3 == product_type) ? "SW Point Latitude" : "sw_point_latitude";
139 string Lat_step_name = (Aqu_L3 == product_type) ? "Latitude Step" : "latitude_step";
140 string Num_lines_name = (Aqu_L3 == product_type) ? "Number of Lines" : "number_of_lines";
141 float Lat_SWP = 0.0;
142 float Lat_step = 0.0;
143 int Num_lines = 0;
144 vector<char> dummy_str;
145
146 obtain_ll_attr_value(fileid, rootid, Lat_SWP_name, Lat_SWP, dummy_str);
147 obtain_ll_attr_value(fileid, rootid, Lat_step_name, Lat_step, dummy_str);
148 obtain_ll_attr_value(fileid, rootid, Num_lines_name, Num_lines, dummy_str);
149 if (Num_lines <= 0) {
150 H5Gclose(rootid);
151 HDF5CFUtil::close_fileid(fileid, check_pass_fileid_key);
152 throw InternalErr(__FILE__, __LINE__, "The number of line must be >0");
153 }
154
155 // The first number of the latitude is at the north west corner
156 LL_first_point = Lat_SWP + (Num_lines - 1) * Lat_step;
157 LL_step = (float)(Lat_step * (-1.0));
158 LL_total_num = Num_lines;
159 }
160
161 if (CV_LON_MISS == cvartype) {
162
163 string Lon_SWP_name = (Aqu_L3 == product_type) ? "SW Point Longitude" : "sw_point_longitude";
164 string Lon_step_name = (Aqu_L3 == product_type) ? "Longitude Step" : "longitude_step";
165 string Num_columns_name = (Aqu_L3 == product_type) ? "Number of Columns" : "number_of_columns";
166 float Lon_SWP = 0.0;
167 float Lon_step = 0.0;
168 int Num_cols = 0;
169
170 vector<char> dummy_str_value;
171
172 obtain_ll_attr_value(fileid, rootid, Lon_SWP_name, Lon_SWP, dummy_str_value);
173 obtain_ll_attr_value(fileid, rootid, Lon_step_name, Lon_step, dummy_str_value);
174 obtain_ll_attr_value(fileid, rootid, Num_columns_name, Num_cols, dummy_str_value);
175 if (Num_cols <= 0) {
176 H5Gclose(rootid);
177 HDF5CFUtil::close_fileid(fileid, check_pass_fileid_key);
178 throw InternalErr(__FILE__, __LINE__, "The number of line must be >0");
179 }
180
181 // The first number of the latitude is at the north west corner
182 LL_first_point = Lon_SWP;
183 LL_step = Lon_step;
184 LL_total_num = Num_cols;
185 }
186
187 vector<float> val;
188 val.resize(nelms);
189
190 if (nelms > LL_total_num) {
191 H5Gclose(rootid);
192 HDF5CFUtil::close_fileid(fileid, check_pass_fileid_key);
193 throw InternalErr(__FILE__, __LINE__,
194 "The number of elements exceeds the total number of Latitude or Longitude");
195 }
196
197 for (int i = 0; i < nelms; ++i)
198 val[i] = LL_first_point + (offset[0] + i * step[0]) * LL_step;
199
200 if (true == add_cache) {
201 vector<float> total_val;
202 total_val.resize(LL_total_num);
203 for (int total_i = 0; total_i < LL_total_num; total_i++)
204 total_val[total_i] = LL_first_point + total_i * LL_step;
205 memcpy(buf, total_val.data(), 4 * LL_total_num);
206 }
207
208 set_value((dods_float32 *) val.data(), nelms);
209 H5Gclose(rootid);
210 HDF5CFUtil::close_fileid(fileid, check_pass_fileid_key);
211}
212
213// Obtain lat/lon for GPM level 3 products
214void HDF5GMCFMissLLArray::obtain_gpm_l3_ll(int* offset, int* step, int nelms, bool add_cache, void*buf)
215{
216
217 if (1 != rank)
218 throw InternalErr(__FILE__, __LINE__, "The number of dimension for GPM Level 3 map data must be 1");
219
220 bool check_pass_fileid_key = HDF5RequestHandler::get_pass_fileid();
221
222 if (false == check_pass_fileid_key) {
223 if ((fileid = H5Fopen(filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) {
224 ostringstream eherr;
225 eherr << "HDF5 File " << filename << " cannot be opened. " << endl;
226 throw InternalErr(__FILE__, __LINE__, eherr.str());
227 }
228 }
229
230 vector<char> grid_info_value;
231 float lat_start = 0;
232 float lon_start = 0.;
233 float lat_res = 0.;
234 float lon_res = 0.;
235
236 int latsize = 0;
237 int lonsize = 0;
238
239
240 if(GPMM_L3 == product_type || GPMS_L3 == product_type) {
241 hid_t grid_grp_id = -1;
242 string grid_grp_name;
243
244 if ((name() == "nlat") || (name() == "nlon")) {
245
246 string temp_grid_grp_name(GPM_GRID_GROUP_NAME1, strlen(GPM_GRID_GROUP_NAME1));
247 temp_grid_grp_name = "/" + temp_grid_grp_name;
248 if (H5Lexists(fileid, temp_grid_grp_name.c_str(), H5P_DEFAULT) > 0)
249 grid_grp_name = temp_grid_grp_name;
250 else {
251 string temp_grid_grp_name2(GPM_GRID_GROUP_NAME2, strlen(GPM_GRID_GROUP_NAME2));
252 temp_grid_grp_name2 = "/" + temp_grid_grp_name2;
253 if (H5Lexists(fileid, temp_grid_grp_name2.c_str(), H5P_DEFAULT) > 0)
254 grid_grp_name = temp_grid_grp_name2;
255 else
256 throw InternalErr(__FILE__, __LINE__, "Unknown GPM grid group name ");
257
258 }
259 }
260
261 else {
262 string temp_grids_group_name(GPM_GRID_MULTI_GROUP_NAME, strlen(GPM_GRID_MULTI_GROUP_NAME));
263 if (name() == "lnH" || name() == "ltH")
264 grid_grp_name = temp_grids_group_name + "/G2";
265 else if (name() == "lnL" || name() == "ltL") grid_grp_name = temp_grids_group_name + "/G1";
266 }
267// varname is supposed to include the full path. However, it takes too much effort to obtain the full path
268// for a created coordiate variable based on the dimension name only. Since GPM has a fixed group G1
269// for lnL and ltL and another fixed group G2 for lnH and ltH. We just use these names. These information
270// is from GPM file specification.
271#if 0
272 if(name() == "lnH" || name() == "ltH" ||
273 name() == "lnL" || name() == "ltL") {
274 string temp_grids_group_name(GPM_GRID_MULTI_GROUP_NAME,strlen(GPM_GRID_MULTI_GROUP_NAME));
275
276//cerr<<"varname is "<<varname <<endl;
277 size_t grids_group_pos = varname.find(temp_grids_group_name);
278 if(string::npos == grids_group_pos) {
279 throw InternalErr (__FILE__, __LINE__,
280 "Cannot find group Grids.");
281 }
282
283 string grids_cgroup_path = varname.substr(grids_group_pos+1);
284 size_t grids_cgroup_pos = varname.find_first_of("/");
285 if(string::npos == grids_cgroup_pos) {
286 throw InternalErr (__FILE__, __LINE__,
287 "Cannot find child group of group Grids.");
288 }
289
290 string temp_sub_grp_name = grids_cgroup_path.substr(0,grids_cgroup_pos);
291 if(name() == "lnH" || name() == "ltH")
292 sub_grp1_name = temp_sub_grp_name;
293 else if(name() == "lnL" || name() == "ltL")
294 sub_grp2_name = temp_sub_grp_name;
295
296 grid_grp_name = temp_grids_group_name + "/" + temp_sub_grp_name;
297
298 }
299#endif
300
301 if ((grid_grp_id = H5Gopen(fileid, grid_grp_name.c_str(), H5P_DEFAULT)) < 0) {
302 HDF5CFUtil::close_fileid(fileid, check_pass_fileid_key);
303 ostringstream eherr;
304 eherr << "HDF5 dataset " << varname << " cannot be opened. " << endl;
305 throw InternalErr(__FILE__, __LINE__, eherr.str());
306 }
307
308 // GPMDPR: update grid_info_name.
309 string grid_info_name(GPM_ATTR2_NAME, strlen(GPM_ATTR2_NAME));
310 if (name() == "lnL" || name() == "ltL")
311 grid_info_name = "G1_" + grid_info_name;
312 else if (name() == "lnH" || name() == "ltH") grid_info_name = "G2_" + grid_info_name;
313
314 float dummy_value = 0.0;
315 try {
316 obtain_ll_attr_value(fileid, grid_grp_id, grid_info_name, dummy_value, grid_info_value);
317 HDF5CFUtil::parser_gpm_l3_gridheader(grid_info_value, latsize, lonsize, lat_start, lon_start, lat_res, lon_res,
318 false);
319
320 H5Gclose(grid_grp_id);
321 }
322 catch (...) {
323 H5Gclose(grid_grp_id);
324 H5Fclose(fileid);
325 throw;
326
327 }
328
329
330}
331 else {
332 vector<char> grid_info_value1;
333 vector<char> grid_info_value2;
334 obtain_gpm_l3_new_grid_info(fileid,grid_info_value1,grid_info_value2);
335 obtain_lat_lon_info(grid_info_value1,grid_info_value2,latsize,lonsize,lat_start,lon_start,lat_res,lon_res);
336 }
337
338 HDF5CFUtil::close_fileid(fileid, check_pass_fileid_key);
339
340 try {
341 send_gpm_l3_ll_to_dap(latsize,lonsize,lat_start,lon_start,lat_res,lon_res,offset,step,nelms,add_cache, buf);
342 }
343 catch (...) {
344 throw;
345 }
346#if 0
347 float lat_start = 0;
348 float lon_start = 0.;
349 float lat_res = 0.;
350 float lon_res = 0.;
351
352 int latsize = 0;
353 int lonsize = 0;
354
355 HDF5CFUtil::parser_gpm_l3_gridheader(grid_info_value, latsize, lonsize, lat_start, lon_start, lat_res, lon_res,
356 false);
357
358 if (0 == latsize || 0 == lonsize) {
359 HDF5CFUtil::close_fileid(fileid, check_pass_fileid_key);
360 throw InternalErr(__FILE__, __LINE__, "Either latitude or longitude size is 0. ");
361 }
362
363 vector<float> val;
364 val.resize(nelms);
365
366 if (CV_LAT_MISS == cvartype) {
367
368 if (nelms > latsize) {
369 H5Gclose(grid_grp_id);
370 HDF5CFUtil::close_fileid(fileid, check_pass_fileid_key);
371 throw InternalErr(__FILE__, __LINE__, "The number of elements exceeds the total number of Latitude ");
372
373 }
374 for (int i = 0; i < nelms; ++i)
375 val[i] = lat_start + offset[0] * lat_res + lat_res / 2 + i * lat_res * step[0];
376
377 if (add_cache == true) {
378 vector<float> total_val;
379 total_val.resize(latsize);
380 for (int total_i = 0; total_i < latsize; total_i++)
381 total_val[total_i] = lat_start + lat_res / 2 + total_i * lat_res;
382 memcpy(buf, total_val.data(), 4 * latsize);
383 }
384 }
385 else if (CV_LON_MISS == cvartype) {
386
387 if (nelms > lonsize) {
388 H5Gclose(grid_grp_id);
389 HDF5CFUtil::close_fileid(fileid, check_pass_fileid_key);
390 throw InternalErr(__FILE__, __LINE__, "The number of elements exceeds the total number of Longitude");
391
392 }
393
394 for (int i = 0; i < nelms; ++i)
395 val[i] = lon_start + offset[0] * lon_res + lon_res / 2 + i * lon_res * step[0];
396
397 if (add_cache == true) {
398 vector<float> total_val;
399 total_val.resize(lonsize);
400 for (int total_i = 0; total_i < lonsize; total_i++)
401 total_val[total_i] = lon_start + lon_res / 2 + total_i * lon_res;
402 memcpy(buf, total_val.data(), 4 * lonsize);
403 }
404
405 }
406
407 set_value((dods_float32 *) val.data(), nelms);
408
409 H5Gclose(grid_grp_id);
410 HDF5CFUtil::close_fileid(fileid, check_pass_fileid_key);
411#endif
412
413#if 0
414
415 vector<float>val;
416 val.resize(nelms);
417
418 if (nelms > LL_total_num) {
419 H5Gclose(rootid);
420 //H5Fclose(fileid);
421 throw InternalErr (__FILE__, __LINE__,
422 "The number of elements exceeds the total number of Latitude or Longitude");
423 }
424
425 for (int i = 0; i < nelms; ++i)
426 val[i] = LL_first_point + (offset[0] + i*step[0])*LL_step;
427
428 set_value ((dods_float32 *) val.data(), nelms);
429 H5Gclose(rootid);
430 //H5Fclose(fileid);
431#endif
432
433}
434
435
436// Obtain latitude/longitude attribute values
437//template<class T>
438template<typename T>
439void HDF5GMCFMissLLArray::obtain_ll_attr_value(hid_t /*file_id*/, hid_t s_root_id, const string & s_attr_name,
440 T& attr_value, vector<char> & str_attr_value)
441{
442
443 BESDEBUG("h5", "Coming to obtain_ll_attr_value"<<endl);
444 hid_t s_attr_id = -1;
445 if ((s_attr_id = H5Aopen_by_name(s_root_id, ".", s_attr_name.c_str(),
446 H5P_DEFAULT, H5P_DEFAULT)) < 0) {
447 string msg = "Cannot open the HDF5 attribute ";
448 msg += s_attr_name;
449 H5Gclose(s_root_id);
450 throw InternalErr(__FILE__, __LINE__, msg);
451 }
452
453 hid_t attr_type = -1;
454 if ((attr_type = H5Aget_type(s_attr_id)) < 0) {
455 string msg = "cannot get the attribute datatype for the attribute ";
456 msg += s_attr_name;
457 H5Aclose(s_attr_id);
458 H5Gclose(s_root_id);
459 throw InternalErr(__FILE__, __LINE__, msg);
460 }
461
462 hid_t attr_space = -1;
463 if ((attr_space = H5Aget_space(s_attr_id)) < 0) {
464 string msg = "cannot get the hdf5 dataspace id for the attribute ";
465 msg += s_attr_name;
466 H5Tclose(attr_type);
467 H5Aclose(s_attr_id);
468 H5Gclose(s_root_id);
469 throw InternalErr(__FILE__, __LINE__, msg);
470 }
471
472 hssize_t num_elm = H5Sget_simple_extent_npoints(attr_space);
473
474 if (0 == num_elm) {
475 string msg = "cannot get the number for the attribute ";
476 msg += s_attr_name;
477 H5Tclose(attr_type);
478 H5Aclose(s_attr_id);
479 H5Sclose(attr_space);
480 H5Gclose(s_root_id);
481 throw InternalErr(__FILE__, __LINE__, msg);
482 }
483
484 if (1 != num_elm) {
485 string msg = "The number of attribute must be 1 for Aquarius level 3 data ";
486 msg += s_attr_name;
487 H5Tclose(attr_type);
488 H5Aclose(s_attr_id);
489 H5Sclose(attr_space);
490 H5Gclose(s_root_id);
491 throw InternalErr(__FILE__, __LINE__, msg);
492 }
493
494 size_t atype_size = H5Tget_size(attr_type);
495 if (atype_size <= 0) {
496 string msg = "cannot obtain the datatype size of the attribute ";
497 msg += s_attr_name;
498 H5Tclose(attr_type);
499 H5Aclose(s_attr_id);
500 H5Sclose(attr_space);
501 H5Gclose(s_root_id);
502 throw InternalErr(__FILE__, __LINE__, msg);
503 }
504
505 if (H5T_STRING == H5Tget_class(attr_type)) {
506 if (H5Tis_variable_str(attr_type)) {
507 H5Tclose(attr_type);
508 H5Aclose(s_attr_id);
509 H5Sclose(attr_space);
510 H5Gclose(s_root_id);
511 throw InternalErr(__FILE__, __LINE__,
512 "Currently we assume the attributes we use to retrieve lat and lon are NOT variable length string.");
513 }
514 else {
515 str_attr_value.resize(atype_size);
516 if (H5Aread(s_attr_id, attr_type, str_attr_value.data()) < 0) {
517 string msg = "cannot retrieve the value of the attribute ";
518 msg += s_attr_name;
519 H5Tclose(attr_type);
520 H5Aclose(s_attr_id);
521 H5Sclose(attr_space);
522 H5Gclose(s_root_id);
523 throw InternalErr(__FILE__, __LINE__, msg);
524
525 }
526 }
527 }
528
529 else if (H5Aread(s_attr_id, attr_type, &attr_value) < 0) {
530 string msg = "cannot retrieve the value of the attribute ";
531 msg += s_attr_name;
532 H5Tclose(attr_type);
533 H5Aclose(s_attr_id);
534 H5Sclose(attr_space);
535 H5Gclose(s_root_id);
536 throw InternalErr(__FILE__, __LINE__, msg);
537
538 }
539
540 H5Tclose(attr_type);
541 H5Sclose(attr_space);
542 H5Aclose(s_attr_id);
543}
544
545void HDF5GMCFMissLLArray::obtain_gpm_l3_new_grid_info(hid_t file,
546 vector<char>& grid_info_value1,
547 vector<char>& grid_info_value2){
548
549 typedef struct {
550 char* name;
551 char* value;
552 } attr_info_t;
553
554 attr_info_t attr_na;
555 attr_na.name = nullptr;
556 attr_na.value = nullptr;
557
558 herr_t ret_o= H5OVISIT(file, H5_INDEX_NAME, H5_ITER_INC, visit_obj_cb, (void*)&attr_na);
559 if(ret_o < 0){
560 H5Fclose(file);
561 throw InternalErr(__FILE__, __LINE__, "H5OVISIT failed. ");
562 }
563 else if(ret_o >0) {
564#if 0
565 //printf("Found the attribute.\n");
566 //string grid_info_name_1(attr_na.name);
567 //string grid_info_name_2;
568
569 //string grid_info_value_1(attr_na.value);
570
571 vector<char> grid_info_value_1(attr_na.value,attr_na.value+strlen(attr_na.value));
572 vector<char> grid_info_value_2;
573 //grid_info_value1(attr_na.value,attr_na.value+strlen(attr_na.value));
574#endif
575 BESDEBUG("h5","Found the GPM level 3 Grid_info attribute."<<endl);
576 grid_info_value1.resize(strlen(attr_na.value));
577 memcpy(grid_info_value1.data(),attr_na.value,strlen(attr_na.value));
578#if 0
579 string tv(grid_info_value1.begin(),grid_info_value1.end());
580 cerr<<"grid_info_value1 is "<<tv <<endl;
581 printf("attr_name 1st is %s\n",attr_na.name);
582 printf("attr_value 1st is %s\n",attr_na.value);
583#endif
584 // Find the grid_info_value of the second grid.
585 // Note: the memory allocated for the first grid info is released
586 // by the attribute callback function.
587 // In this round, we need to release the memory allocated for the second grid info.
588 herr_t ret_o2= H5OVISIT(file, H5_INDEX_NAME, H5_ITER_INC, visit_obj_cb, (void*)&attr_na);
589 if(ret_o2 < 0) {
590 H5Fclose(file);
591 throw InternalErr(__FILE__, __LINE__, "H5OVISIT failed again. ");
592 }
593 else if(ret_o2>0) {
594 if(attr_na.name) {
595#if 0
596 //printf("attr_name second is %s\n",attr_na.name);
597#endif
598 free(attr_na.name);
599 }
600 if(attr_na.value) {
601#if 0
602 //printf("attr_value second is %s\n",attr_na.value);
603 //grid_info_value2(attr_na.value,attr_na.value+strlen(attr_na.value));
604#endif
605 grid_info_value2.resize(strlen(attr_na.value));
606 memcpy(grid_info_value2.data(),attr_na.value,strlen(attr_na.value));
607#if 0
608 string tv(grid_info_value2.begin(),grid_info_value2.end());
609 //cerr<<"grid_info_value2 is "<<tv <<endl;
610#endif
611 free(attr_na.value);
612 }
613 }
614 }
615}
616
617void HDF5GMCFMissLLArray::obtain_lat_lon_info(const vector<char>& grid_info_value1,
618 const vector<char>& grid_info_value2,
619 int& latsize,int& lonsize,
620 float& lat_start,float& lon_start,
621 float& lat_res,float& lon_res){
622
623 float lat1_start = 0;
624 float lon1_start = 0.;
625 float lat1_res = 0.;
626 float lon1_res = 0.;
627 int lat1size = 0;
628 int lon1size = 0;
629
630 float lat2_start = 0;
631 float lon2_start = 0.;
632 float lat2_res = 0.;
633 float lon2_res = 0.;
634 int lat2size = 0;
635 int lon2size = 0;
636
637 HDF5CFUtil::parser_gpm_l3_gridheader(grid_info_value1, lat1size, lon1size, lat1_start, lon1_start,
638 lat1_res, lon1_res,false);
639
640 HDF5CFUtil::parser_gpm_l3_gridheader(grid_info_value2, lat2size, lon2size, lat2_start, lon2_start,
641 lat2_res, lon2_res,false);
642
643 bool pick_gv1 = true;
644
645 // We use the resolution (the smaller value is high resolution) to distinguish the two lat/lons.
646 if (name() == "lnL" || name() == "ltL") {
647 if(lat1_res <lat2_res)
648 pick_gv1 = false;
649 }
650 else if (name() == "lnH" || name() == "ltH") {
651 if(lat1_res >lat2_res)
652 pick_gv1 = false;
653 }
654
655 if(true == pick_gv1) {
656 latsize = lat1size;
657 lonsize = lon1size;
658 lat_start = lat1_start;
659 lon_start = lon1_start;
660 lat_res = lat1_res;
661 lon_res = lon1_res;
662 }
663 else {
664 latsize = lat2size;
665 lonsize = lon2size;
666 lat_start = lat2_start;
667 lon_start = lon2_start;
668 lat_res = lat2_res;
669 lon_res = lon2_res;
670 }
671}
672
673//Callback function to retrieve the grid information.
674static herr_t
675attr_info(hid_t loc_id, const char *name, const H5A_info_t *ainfo, void *_op_data)
676{
677
678 typedef struct {
679 char* name;
680 char* value;
681 } attr_info_t;
682
683 herr_t ret = 0;
684 attr_info_t *op_data = (attr_info_t *)_op_data;
685
686 // Attribute name is GridHeader
687 if(strstr(name,GPM_ATTR2_NAME)!=nullptr) {
688 hid_t attr;
689 hid_t atype;
690 attr = H5Aopen(loc_id, name, H5P_DEFAULT);
691 if(attr<0)
692 return -1;
693 atype = H5Aget_type(attr);
694 if(atype <0) {
695 H5Aclose(attr);
696 return -1;
697 }
698 if(H5T_STRING == H5Tget_class(atype)){
699 // Note here: we find that the HDF5 API H5Tis_variable_str() causes seg. fault
700 // when checking if this is a variable length string. A ticket has been submitted
701 // to the HDF group. For GPM, only the fixed-size string is used. So it won't affect
702 // here. When the bug is fixed. We should add a check here to avoid the crash of the prog.
703 if(op_data->name) {
704 if(strncmp(name,op_data->name,strlen(name))!=0) {
705 hid_t aspace = H5Aget_space(attr);
706 if(aspace <0) {
707 H5Aclose(attr);
708 H5Tclose(atype);
709 return -1;
710 }
711 hsize_t num_elms = H5Tget_size(atype)*H5Sget_simple_extent_npoints(aspace);
712#if 0
713 char *attr_value = op_data->value;
714 attr_value = malloc(num_elms+1);
715 H5Aread(attr,atype,attr_value);
716 printf("attr_value is %s\n",attr_value);
717#endif
718 char *cur_attr_value = (char*)malloc(num_elms+1);
719 if(H5Aread(attr,atype,(void*)cur_attr_value)<0) {
720 H5Aclose(attr);
721 H5Sclose(aspace);
722 H5Tclose(atype);
723 free(cur_attr_value);
724 return -1;
725 }
726
727 // There are two grids in the file. This "if clause" is for the second one.
728 if(strncmp(cur_attr_value,op_data->value,strlen(op_data->value))!=0) {
729 free(op_data->name);
730 op_data->name = nullptr;
731 op_data->name = (char*)malloc(strlen(name)+1);
732 strncpy(op_data->name,name,strlen(name));
733 if(op_data->value)
734 free(op_data->value);
735 op_data->value = nullptr;
736 op_data->value=(char*)malloc(num_elms+1);
737 strncpy(op_data->value,cur_attr_value,strlen(cur_attr_value));
738 ret = 1;
739 }
740 free(cur_attr_value);
741 H5Sclose(aspace);
742 }
743 }
744 else {
745 hid_t aspace = H5Aget_space(attr);
746 if(aspace <0) {
747 H5Aclose(attr);
748 H5Tclose(atype);
749 return -1;
750 }
751
752 hsize_t num_elms = H5Tget_size(atype)*H5Sget_simple_extent_npoints(aspace);
753 op_data->name = (char*)malloc(strlen(name)+1);
754 strncpy(op_data->name,name,strlen(name));
755
756#if 0
757 char *attr_value = op_data->value;
758 attr_value = malloc(num_elms+1);
759 H5Aread(attr,atype,attr_value);
760 printf("attr_value is %s\n",attr_value);
761#endif
762 op_data->value = (char*)malloc(num_elms+1);
763 if(H5Aread(attr,atype,(void*)op_data->value)<0) {
764 H5Aclose(attr);
765 H5Sclose(aspace);
766 H5Tclose(atype);
767 free(op_data->value);
768 }
769 H5Sclose(aspace);
770 ret =1;
771 }
772 }
773 H5Tclose(atype);
774 H5Aclose(attr);
775 }
776 return ret;
777
778}
779
780// The callback function to iterate every HDF5 object(including groups and datasets)
781// Checked the internal HDF5 functions. The object type is used to obtain different
782// objects in the internal function. So performance-wise, this routine should be
783// the same as the routine that uses the H5Literate.
784//
785static int
786visit_obj_cb(hid_t group_id, const char *name, const H5O_info_t *oinfo,
787 void *_op_data)
788{
789 typedef struct {
790 char* name;
791 char* value;
792 } attr_info_t;
793
794
795#if 0
796 //lvisit_ud_t *op_data = (lvisit_ud_t *)_op_data;
797#endif
798
799 attr_info_t *op_data = (attr_info_t *)_op_data;
800 herr_t ret = 0;
801
802 if(oinfo->type == H5O_TYPE_GROUP) {
803
804 hid_t grp = -1;
805 grp = H5Gopen2(group_id,name,H5P_DEFAULT);
806 if(grp < 0)
807 return -1;
808 ret = H5Aiterate2(grp, H5_INDEX_NAME, H5_ITER_INC, nullptr, attr_info, op_data);
809#if 0
810 if(ret > 0) {
811 printf("object: attr name is %s\n",op_data->name);
812 printf("object: attr value is %s\n",op_data->value);
813 }
814#endif
815 if(ret <0){
816 H5Gclose(grp);
817 return -1;
818 }
819 H5Gclose(grp);
820 }
821 return ret;
822
823}
824
825
826
827#if 0
828void HDF5GMCFMissLLArray::send_gpm_l3_ll_to_dap(const vector<char>& grid_info_value,int* offset,int* step,
829 int nelms,bool add_cache, void*buf) {
830
831 float lat_start = 0;
832 float lon_start = 0.;
833 float lat_res = 0.;
834 float lon_res = 0.;
835
836 int latsize = 0;
837 int lonsize = 0;
838#endif
839
840void HDF5GMCFMissLLArray::send_gpm_l3_ll_to_dap(const int latsize,const int lonsize,const float lat_start,const float lon_start,
841 const float lat_res,const float lon_res, const int* offset,const int* step,
842 const int nelms,const bool add_cache, void*buf) {
843
844
845 if (0 == latsize || 0 == lonsize) {
846 throw InternalErr(__FILE__, __LINE__, "Either latitude or longitude size is 0. ");
847 }
848
849 vector<float> val;
850 val.resize(nelms);
851
852 if (CV_LAT_MISS == cvartype) {
853
854 if (nelms > latsize) {
855 throw InternalErr(__FILE__, __LINE__, "The number of elements exceeds the total number of Latitude ");
856
857 }
858 for (int i = 0; i < nelms; ++i)
859 val[i] = lat_start + offset[0] * lat_res + lat_res / 2 + i * lat_res * step[0];
860
861 if (add_cache == true) {
862 vector<float> total_val;
863 total_val.resize(latsize);
864 for (int total_i = 0; total_i < latsize; total_i++)
865 total_val[total_i] = lat_start + lat_res / 2 + total_i * lat_res;
866 memcpy(buf, total_val.data(), 4 * latsize);
867 }
868 }
869 else if (CV_LON_MISS == cvartype) {
870
871#if 0
872//cerr<<"nelms is "<<nelms <<endl;
873//cerr<<"lonsize is "<<lonsize <<endl;
874#endif
875 if (nelms > lonsize) {
876 throw InternalErr(__FILE__, __LINE__, "The number of elements exceeds the total number of Longitude");
877 }
878
879 for (int i = 0; i < nelms; ++i)
880 val[i] = lon_start + offset[0] * lon_res + lon_res / 2 + i * lon_res * step[0];
881
882 if (add_cache == true) {
883 vector<float> total_val;
884 total_val.resize(lonsize);
885 for (int total_i = 0; total_i < lonsize; total_i++)
886 total_val[total_i] = lon_start + lon_res / 2 + total_i * lon_res;
887 memcpy(buf, total_val.data(), 4 * lonsize);
888 }
889
890 }
891
892 set_value((dods_float32 *) val.data(), nelms);
893
894}
895
896void HDF5GMCFMissLLArray::read_data_NOT_from_mem_cache(bool add_cache, void*buf)
897{
898
899 BESDEBUG("h5", "Coming to HDF5GMCFMissLLArray: read_data_NOT_from_mem_cache "<<endl);
900
901 // Here we still use vector just in case we need to tackle "rank>1" in the future.
902 // Also we would like to keep it consistent with other similar handlings.
903 vector<int> offset;
904 vector<int> count;
905 vector<int> step;
906
907 offset.resize(rank);
908 count.resize(rank);
909 step.resize(rank);
910
911 int nelms = format_constraint(offset.data(), step.data(), count.data());
912
913 if (GPMM_L3 == product_type || GPMS_L3 == product_type || GPM_L3_New == product_type)
914 obtain_gpm_l3_ll(offset.data(), step.data(), nelms, add_cache, buf);
915 else if (Aqu_L3 == product_type || OBPG_L3 == product_type) // Aquarious level 3
916 obtain_aqu_obpg_l3_ll(offset.data(), step.data(), nelms, add_cache, buf);
917
918 return;
919
920}
921
This class specifies the retrieval of the missing lat/lon values for general HDF5 products.
include the entry functions to execute the handlers