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