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