bes Updated for version 3.20.10
HDFEOS5CF.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
36
37#include "HDF5CF.h"
38#include "HDF5RequestHandler.h"
39#include "h5cfdaputil.h"
40#include "BESDebug.h"
41
42using namespace std;
43using namespace libdap;
44using namespace HDF5CF;
45
46// A constructor of EOS5CVar
47EOS5CVar::EOS5CVar(Var*var)
48{
49
50 newname = var->newname;
51 name = var->name;
52 fullpath = var->fullpath;
53 rank = var->rank;
54 total_elems = var->total_elems;
55 zero_storage_size = var->zero_storage_size;
56 dtype = var->dtype;
57 unsupported_attr_dtype = var->unsupported_attr_dtype;
58 unsupported_dspace = var->unsupported_dspace;
59 coord_attr_add_path = false;
60
61 for (vector<Attribute*>::iterator ira = var->attrs.begin(); ira != var->attrs.end(); ++ira) {
62 Attribute* attr = new Attribute();
63 attr->name = (*ira)->name;
64 attr->newname = (*ira)->newname;
65 attr->dtype = (*ira)->dtype;
66 attr->count = (*ira)->count;
67 attr->strsize = (*ira)->strsize;
68 attr->fstrsize = (*ira)->fstrsize;
69 attr->value = (*ira)->value;
70 attrs.push_back(attr);
71 }
72
73 for (vector<Dimension*>::iterator ird = var->dims.begin(); ird != var->dims.end(); ++ird) {
74 Dimension *dim = new Dimension((*ird)->size);
75 dim->name = (*ird)->name;
76 dim->newname = (*ird)->newname;
77 dim->unlimited_dim = (*ird)->unlimited_dim;
78 dims.push_back(dim);
79 }
80
81 // For the coordinate variable specific fields, we just fill in the default one in the ctr
82 // If needed, the caller of this function should fill in those information after calling this function.
83 eos_type = OTHERVARS;
84 is_2dlatlon = false;
85 point_lower = 0.0;
86 point_upper = 0.0;
87 point_left = 0.0;
88 point_right = 0.0;
89 xdimsize = 0;
90 ydimsize = 0;
91 eos5_pixelreg = HE5_HDFE_CENTER;
92 eos5_origin = HE5_HDFE_GD_UL;
93 eos5_projcode = HE5_GCTP_GEO;
94 zone = -1;
95 sphere = 0;
96 std::fill_n(param, 13, 0);
97
98}
99
100//This method will effectively remove any dimnames like
101// ???/XDim or ???/YDim from the dimension name set.
102// Use this function in caution.
103void EOS5CFGrid::Update_Dimnamelist()
104{
105
106 BESDEBUG("h5", "coming to Update_Dimnamelist" <<endl);
107
108 // If I put both "XDim" and "YDim" into one for loop, Mac g++ compiler
109 // gives segmentation fault, which doesn't make sense.
110 // I simply split them into two loops. It doesn't affect performance much.
111 // KY 2012-2-14
112 for (set<string>::iterator it = this->vardimnames.begin(); it != this->vardimnames.end(); ++it) {
113 string xydimname_candidate = HDF5CFUtil::obtain_string_after_lastslash(*it);
114 if ("XDim" == xydimname_candidate) {
115 this->vardimnames.erase(*it);
116 break;
117 }
118 }
119
120 for (set<string>::iterator it = this->vardimnames.begin(); it != this->vardimnames.end(); ++it) {
121 string xydimname_candidate = HDF5CFUtil::obtain_string_after_lastslash(*it);
122 if ("YDim" == xydimname_candidate) {
123 this->vardimnames.erase(*it);
124 break;
125 }
126 }
127
128}
129
130// A destructor of EOS5File
131EOS5File::~EOS5File()
132{
133 for (vector<EOS5CVar *>::const_iterator i = this->cvars.begin(); i != this->cvars.end(); ++i)
134 delete *i;
135
136 for (vector<EOS5CFGrid *>::const_iterator i = this->eos5cfgrids.begin(); i != this->eos5cfgrids.end(); ++i)
137 delete *i;
138
139 for (vector<EOS5CFSwath *>::const_iterator i = this->eos5cfswaths.begin(); i != this->eos5cfswaths.end(); ++i)
140 delete *i;
141
142 for (vector<EOS5CFZa *>::const_iterator i = this->eos5cfzas.begin(); i != this->eos5cfzas.end(); ++i)
143 delete *i;
144
145}
146
147// Helper function to make the name follow the CF conventions.
148string EOS5File::get_CF_string(string s)
149{
150
151 // We need to remove the first "/" from the full name.
152 if (s[0] != '/')
153 return File::get_CF_string(s);
154 else {
155 s.erase(0, 1);
156 return File::get_CF_string(s);
157 }
158}
159
160// Retrieve the HDF5 information for HDF-EOS5
161void EOS5File::Retrieve_H5_Info(const char *file_fullpath, hid_t file_id, bool /*include_attr*/)
162{
163 // Since we need to check the attribute info in order to determine if the file is augmented to netCDF-4,
164 // we need to retrieve the attribute info also.
165 File::Retrieve_H5_Info(file_fullpath, file_id, true);
166}
167
169{
170
171 for (vector<EOS5CVar *>::iterator ircv = this->cvars.begin(); ircv != this->cvars.end(); ++ircv) {
172
173 // When the coordinate variables exist in the file, retrieve the attribute values.
174 if ((CV_EXIST == (*ircv)->cvartype) || (CV_MODIFY == (*ircv)->cvartype)) {
175 for (vector<Attribute *>::iterator ira = (*ircv)->attrs.begin(); ira != (*ircv)->attrs.end(); ++ira)
176 Retrieve_H5_Attr_Value(*ira, (*ircv)->fullpath);
177
178 }
179 }
180
181}
182
183// Retrieve the attribute values for the HDF-EOS5
185{
186
188 for (vector<EOS5CVar *>::iterator ircv = this->cvars.begin(); ircv != this->cvars.end(); ++ircv) {
189
190 // When the coordinate variables exist in the file, retrieve the attribute values.
191 if ((CV_EXIST == (*ircv)->cvartype) || (CV_MODIFY == (*ircv)->cvartype)) {
192 for (vector<Attribute *>::iterator ira = (*ircv)->attrs.begin(); ira != (*ircv)->attrs.end(); ++ira)
193 Retrieve_H5_Attr_Value(*ira, (*ircv)->fullpath);
194
195 }
196 }
197}
198
199// Adjust attribute value
200void EOS5File::Adjust_H5_Attr_Value(Attribute *attr)
201{
202 // For future usage.
203
204}
205
206// Handle unsupported datatype
208{
209
210 if (true == check_ignored) {
211 Gen_Unsupported_Dtype_Info(include_attr);
212 }
213
214 File::Handle_Unsupported_Dtype(include_attr);
215 Handle_EOS5_Unsupported_Dtype(include_attr);
216}
217
218// Handle EOS5 unsupported datatype,add EOS5 coordinate variables
219void EOS5File::Handle_EOS5_Unsupported_Dtype(bool include_attr)
220{
221
222 for (vector<EOS5CVar *>::iterator ircv = this->cvars.begin(); ircv != this->cvars.end();) {
223 if (true == include_attr) {
224 for (vector<Attribute *>::iterator ira = (*ircv)->attrs.begin(); ira != (*ircv)->attrs.end();) {
225 H5DataType temp_dtype = (*ira)->getType();
226 if (false == HDF5CFUtil::cf_strict_support_type(temp_dtype,_is_dap4)) {
227 delete (*ira);
228 ira = (*ircv)->attrs.erase(ira);
229 }
230 else {
231 ++ira;
232
233 }
234 }
235 }
236
237 H5DataType temp_dtype = (*ircv)->getType();
238 if (!HDF5CFUtil::cf_strict_support_type(temp_dtype,_is_dap4)) {
239 delete (*ircv);
240 ircv = this->cvars.erase(ircv);
241 }
242 else {
243 ++ircv;
244 }
245 }
246}
247
248// Generate unsupported datatype information
249void EOS5File::Gen_Unsupported_Dtype_Info(bool include_attr)
250{
251
252 if (true == include_attr) {
253
254 File::Gen_Group_Unsupported_Dtype_Info();
255 File::Gen_Var_Unsupported_Dtype_Info();
256 Gen_VarAttr_Unsupported_Dtype_Info();
257
258 }
259
260}
261
262// Generate variable attribute datatype info.
263void EOS5File::Gen_VarAttr_Unsupported_Dtype_Info()
264{
265
266 // Dimension scale info for general variables
267 Gen_DimScale_VarAttr_Unsupported_Dtype_Info();
268
269 // HDF-EOS5 variable attribute unsupported datatype
270 Gen_EOS5_VarAttr_Unsupported_Dtype_Info();
271
272}
273
274void EOS5File::Gen_EOS5_VarAttr_Unsupported_Dtype_Info()
275{
276
277 for (vector<EOS5CVar *>::iterator irv = this->cvars.begin(); irv != this->cvars.end(); ++irv) {
278 // If the attribute REFERENCE_LIST comes with the attribut CLASS, the
279 // attribute REFERENCE_LIST is okay to ignore. No need to report.
280 bool is_ignored = ignored_dimscale_ref_list((*irv));
281 if (false == (*irv)->attrs.empty()) {
282 //if (true == (*irv)->unsupported_attr_dtype) {
283 for (vector<Attribute *>::iterator ira = (*irv)->attrs.begin(); ira != (*irv)->attrs.end(); ++ira) {
284 H5DataType temp_dtype = (*ira)->getType();
285 // TODO: check why 64-bit integer is included.
286 if (false == HDF5CFUtil::cf_strict_support_type(temp_dtype,_is_dap4) || (temp_dtype == H5INT64) ||(temp_dtype == H5UINT64)) {
287 // "DIMENSION_LIST" is okay to ignore and "REFERENCE_LIST"
288 // is okay to ignore if the variable has another attribute
289 // CLASS="DIMENSION_SCALE"
290 if (("DIMENSION_LIST" != (*ira)->name)
291 && ("REFERENCE_LIST" != (*ira)->name || true == is_ignored))
292 this->add_ignored_info_attrs(false, (*irv)->fullpath, (*ira)->name);
293 }
294 }
295 //}
296 }
297 }
298}
299
300// Handle unsupported data space.
302{
303
304 // Generate unsupported info.
305 if (true == check_ignored) {
306 Gen_Unsupported_Dspace_Info();
307 }
308
310 Handle_EOS5_Unsupported_Dspace(include_attr);
311
312}
313
314// Handle EOS5 unsupported data space.
315void EOS5File::Handle_EOS5_Unsupported_Dspace(bool include_attr)
316{
317
318 if (true == this->unsupported_var_dspace) {
319 for (vector<EOS5CVar *>::iterator ircv = this->cvars.begin(); ircv != this->cvars.end();) {
320 if (true == (*ircv)->unsupported_dspace) {
321 delete (*ircv);
322 ircv = this->cvars.erase(ircv);
323 }
324 else {
325 ++ircv;
326 }
327 }
328 }
329
330 if (true == include_attr) {
331 if (true == this->unsupported_var_attr_dspace) {
332 for (vector<EOS5CVar *>::iterator ircv = this->cvars.begin(); ircv != this->cvars.end(); ++ircv) {
333 if (false == (*ircv)->attrs.empty()) {
334 if (true == (*ircv)->unsupported_attr_dspace) {
335 for (vector<Attribute *>::iterator ira = (*ircv)->attrs.begin(); ira != (*ircv)->attrs.end();) {
336 if (0 == (*ira)->count) {
337 delete (*ira);
338 ira = (*ircv)->attrs.erase(ira);
339 }
340 else {
341 ++ira;
342 }
343 }
344 }
345 }
346 }
347 }
348 }
349}
350
351// Generating unsupported data space.
352void EOS5File::Gen_Unsupported_Dspace_Info()
353{
354
355 File::Gen_Unsupported_Dspace_Info();
356
357}
358
359// Handle other unsupported EOS5 information
361{
362
363 remove_netCDF_internal_attributes(include_attr);
364#if 0
365 if(true == include_attr) {
366 for (vector<Var *>::iterator irv = this->vars.begin();
367 irv != this->vars.end(); ++irv) {
368 for(vector<Attribute *>::iterator ira = (*irv)->attrs.begin();
369 ira != (*irv)->attrs.end();) {
370 if((*ira)->name == "CLASS") {
371 string class_value = Retrieve_Str_Attr_Value(*ira,(*irv)->fullpath);
372
373 // Compare the attribute "CLASS" value with "DIMENSION_SCALE". We only compare the string with the size of
374 // "DIMENSION_SCALE", which is 15.
375 if (0 == class_value.compare(0,15,"DIMENSION_SCALE")) {
376 delete((*ira));
377 ira = (*irv)->attrs.erase(ira);
378 }
379#if 0
380 else if(1) {// Add a BES key,also delete
381
382 }
383#endif
384 else {
385 ++ira;
386 }
387 }
388 //else if((*ira)->name == "NAME" && 1) {// Add a BES Key later if necessary
389 else if((*ira)->name == "NAME") {// Add a BES Key
390 string name_value = Retrieve_Str_Attr_Value(*ira,(*irv)->fullpath);
391 if( 0 == name_value.compare(0,(*irv)->name.size(),(*irv)->name)) {
392 delete((*ira));
393 ira =(*irv)->attrs.erase(ira);
394 }
395 else {
396 string netcdf_dim_mark= "This is a netCDF dimension but not a netCDF variable";
397 if( 0 == name_value.compare(0,netcdf_dim_mark.size(),netcdf_dim_mark)) {
398 delete((*ira));
399 ira =(*irv)->attrs.erase(ira);
400 }
401 else {
402 ++ira;
403 }
404 }
405
406 }
407 else if((*ira)->name == "_Netcdf4Dimid") {
408 delete((*ira));
409 ira =(*irv)->attrs.erase(ira);
410 }
411
412 else {
413 ++ira;
414 }
415 }
416 }
417#endif
418 if(true == include_attr) {
419 for (vector<EOS5CVar *>::iterator irv = this->cvars.begin();
420 irv != this->cvars.end(); ++irv) {
421 for(vector<Attribute *>::iterator ira = (*irv)->attrs.begin();
422 ira != (*irv)->attrs.end();) {
423 if((*ira)->name == "CLASS") {
424 string class_value = Retrieve_Str_Attr_Value(*ira,(*irv)->fullpath);
425
426 // Compare the attribute "CLASS" value with "DIMENSION_SCALE". We only compare the string with the size of
427 // "DIMENSION_SCALE", which is 15.
428 if (0 == class_value.compare(0,15,"DIMENSION_SCALE")) {
429 delete(*ira);
430 ira = (*irv)->attrs.erase(ira);
431 // Add another block to set a key
432 }
433 else {
434 ++ira;
435 }
436 }
437 else if((*ira)->name == "NAME") {// Add a BES Key later
438 delete(*ira);
439 ira=(*irv)->attrs.erase(ira);
440 //"NAME" attribute causes the file netCDF-4 failed.
441#if 0
442 string name_value = Retrieve_Str_Attr_Value(*ira,(*irv)->fullpath);
443 if( 0 == name_value.compare(0,(*irv)->name.size(),(*irv)->name)) {
444 delete(*ira);
445 ira =(*irv)->attrs.erase(ira);
446 }
447 else {
448 string netcdf_dim_mark= "This is a netCDF dimension but not a netCDF variable";
449 if( 0 == name_value.compare(0,netcdf_dim_mark.size(),netcdf_dim_mark)) {
450 delete(*ira);
451 ira =(*irv)->attrs.erase(ira);
452 }
453 else {
454 ++ira;
455 }
456 }
457#endif
458 }
459 else if((*ira)->name == "_Netcdf4Dimid") {
460 delete(*ira);
461 ira =(*irv)->attrs.erase(ira);
462 }
463
464 else {
465 ++ira;
466 }
467 }
468 }
469 }
470
471
472 // We cannot use the general routine from the base class since
473 // the information of ignored ECS metadata variables is transferred
474 // to DAS. The ignored ECS metadata variables should not be reported.
475 //File::Handle_Unsupported_Others(include_attr);
476 if (true == this->check_ignored && true == include_attr) {
477
478 // netCDF Java lifts the string size restriction for attributes. So comment out for the time being. KY 2018/08/10
479 if (true == HDF5RequestHandler::get_drop_long_string()) {
480#if 0
481 for (vector<Attribute *>::iterator ira = this->root_attrs.begin(); ira != this->root_attrs.end(); ++ira) {
482 if (H5FSTRING == (*ira)->dtype || H5VSTRING == (*ira)->dtype) {
483 if ((*ira)->getBufSize() > NC_JAVA_STR_SIZE_LIMIT) {
484 this->add_ignored_droplongstr_hdr();
485 this->add_ignored_grp_longstr_info("/", (*ira)->name);
486 }
487 }
488 }
489
490 for (vector<Group *>::iterator irg = this->groups.begin(); irg != this->groups.end(); ++irg) {
491 for (vector<Attribute *>::iterator ira = (*irg)->attrs.begin(); ira != (*irg)->attrs.end(); ++ira) {
492 if (H5FSTRING == (*ira)->dtype || H5VSTRING == (*ira)->dtype) {
493 if ((*ira)->getBufSize() > NC_JAVA_STR_SIZE_LIMIT) {
494 this->add_ignored_droplongstr_hdr();
495 this->add_ignored_grp_longstr_info((*irg)->path, (*ira)->name);
496 }
497 }
498
499 }
500 }
501#endif
502 for (vector<Var *>::iterator irv = this->vars.begin(); irv != this->vars.end(); ++irv) {
503 if (true == Check_DropLongStr((*irv), NULL)) {
504 string ecsmeta_grp = "/HDFEOS INFORMATION";
505 // Ignored ECS metadata should not be reported.
506 if ((*irv)->fullpath.find(ecsmeta_grp) != 0
507 || ((*irv)->fullpath.rfind("/") != ecsmeta_grp.size())) {
508 this->add_ignored_droplongstr_hdr();
509 this->add_ignored_var_longstr_info((*irv), NULL);
510 }
511 }
512#if 0
513 for (vector<Attribute *>::iterator ira = (*irv)->attrs.begin(); ira != (*irv)->attrs.end(); ++ira) {
514 if (true == Check_DropLongStr((*irv), (*ira))) {
515 this->add_ignored_droplongstr_hdr();
516 this->add_ignored_var_longstr_info((*irv), (*ira));
517 }
518 }
519#endif
520 }
521#if 0
522 for (vector<EOS5CVar *>::iterator irv = this->cvars.begin(); irv != this->cvars.end(); ++irv) {
523 for (vector<Attribute *>::iterator ira = (*irv)->attrs.begin(); ira != (*irv)->attrs.end(); ++ira) {
524 if (true == Check_DropLongStr((*irv), (*ira))) {
525 this->add_ignored_droplongstr_hdr();
526 this->add_ignored_var_longstr_info((*irv), (*ira));
527 }
528 }
529 }
530#endif
531 }
532 }
533
534 if (false == this->have_ignored) this->add_no_ignored_info();
535
536}
537
538// Adjust HDF-EOS5 dimension info.
540{
541
542 BESDEBUG("h5", "coming to Adjust_EOS5Dim_Info" <<endl);
543
544 // Condense redundant XDim, YDim in the grid/swath/za dimension list
545 for (unsigned int i = 0; i < strmeta_info->swath_list.size(); ++i) {
546 HE5Swath& he5s = strmeta_info->swath_list.at(i);
547
548 Adjust_EOS5Dim_List(he5s.dim_list);
549
550 // Correct the possible wrong dimension size,this only happens for the unlimited dimension,
551 // WE JUST NEED TO CORRECT the EOS group dimension size.
552 // STEPS:
553 // 1. Merge SWATH data_var_list and geo_var_list
554 // Function parameters will be the object dim. list(he5s.dim_list), EOS5Type(SWATH,GRID...) and varlist
555 // Need to use Obtain_Var_EOS5Type_GroupName to find var's group name and Get_Var_EOS5_Type(var) to find
556 // Var's EOS5Type.
557 // After checking group and type, check "if(he5v.name == var->name)" and change the he5v dim. size to var size.
558 if(this->have_udim == true) {
559 vector<HE5Var> svlist = he5s.geo_var_list;
560 svlist.insert(svlist.end(),he5s.data_var_list.begin(),he5s.data_var_list.end());
561 // Only apply when the unlimited dimension is found!! So we don't have to go over this for every file.
562 Adjust_EOS5DimSize_List(he5s.dim_list,svlist,SWATH,he5s.name);
563 }
564
565 for (unsigned int j = 0; j < he5s.geo_var_list.size(); ++j) {
566 Adjust_EOS5VarDim_Info((he5s.geo_var_list)[j].dim_list, he5s.dim_list, he5s.name, SWATH);
567 }
568 for (unsigned int j = 0; j < he5s.data_var_list.size(); ++j) {
569 Adjust_EOS5VarDim_Info((he5s.data_var_list)[j].dim_list, he5s.dim_list, he5s.name, SWATH);
570 }
571 }
572
573 for (unsigned int i = 0; i < strmeta_info->grid_list.size(); ++i) {
574
575 HE5Grid& he5g = strmeta_info->grid_list.at(i);
576
577 Adjust_EOS5Dim_List(he5g.dim_list);
578
579 // Correct possible wrong dimension size in the eosdim list.
580 if(this->have_udim == true) {
581 // Only apply when the unlimited dimension is found!! So we don't have to go over this for every file.
582 Adjust_EOS5DimSize_List(he5g.dim_list,he5g.data_var_list,GRID,he5g.name);
583 }
584
585 for (unsigned int j = 0; j < he5g.data_var_list.size(); ++j) {
586 Adjust_EOS5VarDim_Info((he5g.data_var_list)[j].dim_list, he5g.dim_list, he5g.name, GRID);
587 }
588 }
589
590 for (unsigned int i = 0; i < strmeta_info->za_list.size(); ++i) {
591 HE5Za& he5z = strmeta_info->za_list.at(i);
592
593 Adjust_EOS5Dim_List(he5z.dim_list);
594
595 // Correct possible wrong dimension size in the eosdim list.
596 if(this->have_udim == true) {
597 // Only apply when the unlimited dimension is found!! So we don't have to go over this for every file.
598 Adjust_EOS5DimSize_List(he5z.dim_list,he5z.data_var_list,ZA,he5z.name);
599 }
600
601 for (unsigned int j = 0; j < he5z.data_var_list.size(); ++j) {
602 Adjust_EOS5VarDim_Info((he5z.data_var_list)[j].dim_list, he5z.dim_list, he5z.name, ZA);
603 }
604 }
605}
606
607// Adjust HDF-EOS5 dimension list.
608void EOS5File::Adjust_EOS5Dim_List(vector<HE5Dim>& groupdimlist)
609{
610
611 BESDEBUG("h5", "Coming to Adjust_EOS5Dim_List"<<endl);
612
613 // The negative dimension sizes are found in some HDF-EOS5 files.
614 // We need to remove them.
615 Remove_NegativeSizeDims(groupdimlist);
616
617 // Condense redundant XDim, YDim in the grid/swath/za dimension list
618 Condense_EOS5Dim_List(groupdimlist);
619
620}
621
622// The negative dimension sizes are found in some HDF-EOS5 files.
623// We need to remove them.
624void EOS5File::Remove_NegativeSizeDims(vector<HE5Dim>& groupdimlist)
625{
626
627 BESDEBUG("h5", "Coming to Remove_NegativeSizeDims" <<endl);
628 vector<HE5Dim>::iterator id;
629
630 // We find one product has dimension with name: Unlimited, size: -1; this dimension
631 // will not be used by any variables. The "Unlimited" dimension is useful for extended
632 // datasets when data is written. It is not useful for data accessing as far as I know.
633 // So we will remove it from the list.
634 // This algoritm will also remove any dimension with size <=0. KY 2011-1-14
635 // Note: Unlimited dimension is supported by the handler but not by using this "Unlimited" name.
636 // For the unlimited dimension support, check class Dimension and function Retrieve_H5_VarDim.
637 for (id = groupdimlist.begin(); id != groupdimlist.end();) {
638 if ((*id).size <= 0) {
639 id = groupdimlist.erase(id);
640 }
641 else {
642 ++id;
643 }
644 }
645}
646
647// Condense redundant XDim, YDim in the grid/swath/za dimension list
648// Some products use Xdim rather XDim, Ydim rather than Ydim.
649// This is significant for grids. We need to make them "XDim" and "YDim".
650// See comments of function Adjust_EOS5VarDim_Info for the reason.
651void EOS5File::Condense_EOS5Dim_List(vector<HE5Dim>& groupdimlist)
652{
653
654 BESDEBUG("h5", "Coming to Condense_EOS5Dim_List"<<endl);
655 set<int> xdimsizes;
656 set<int> ydimsizes;
657 pair<set<int>::iterator, bool> setret;
658 vector<HE5Dim>::iterator id;
659
660 for (id = groupdimlist.begin(); id != groupdimlist.end();) {
661 if ("XDim" == (*id).name || "Xdim" == (*id).name) {
662 setret = xdimsizes.insert((*id).size);
663 if (false == setret.second) {
664 id = groupdimlist.erase(id);
665 }
666 else if ("Xdim" == (*id).name) {
667 (*id).name = "XDim";
668 ++id;
669 }
670 else {
671 ++id;
672 }
673
674 }
675 else {
676 ++id;
677 }
678 }
679
680 for (id = groupdimlist.begin(); id != groupdimlist.end();) {
681 if ("YDim" == (*id).name || "Ydim" == (*id).name) {
682 setret = ydimsizes.insert((*id).size);
683 if (false == setret.second) {
684 id = groupdimlist.erase(id);
685 }
686 else if ("Ydim" == (*id).name) {
687 (*id).name = "YDim";
688 ++id;
689 }
690 else {
691 ++id;
692 }
693 }
694 else {
695 ++id;
696 }
697 }
698}
699
700void EOS5File:: Adjust_EOS5DimSize_List(vector<HE5Dim>& eos5objdimlist,const vector<HE5Var> & eos5objvarlist,
701 const EOS5Type eos5type, const string & eos5objname)
702{
703
704 set<string>updated_dimlist;
705 pair<set<string>::iterator,bool> set_insert_ret;
706
707 for(unsigned int i = 0; i<eos5objvarlist.size();i++) {
708 HE5Var he5v = eos5objvarlist.at(i);
709 for(unsigned int j = 0; j<he5v.dim_list.size();j++) {
710 HE5Dim he5d = he5v.dim_list.at(j);
711 set_insert_ret = updated_dimlist.insert(he5d.name);
712 if(set_insert_ret.second == true) {
713 // Find out the index of this dimension in eos5objdimlist
714 unsigned int objdimlist_index = 9999;
715 bool has_objdimlist_index = false;
716 for(unsigned int k = 0; k <eos5objdimlist.size();k++) {
717 if(eos5objdimlist[k].name == he5d.name) {
718 objdimlist_index = k;
719 has_objdimlist_index = true;
720 break;
721 }
722 }
723 if(has_objdimlist_index == false)
724 throw2("Cannot find the dimension in the EOS5 object dimension list for the dimension ", he5d.name);
725 for (vector<Var *>::const_iterator irv = this->vars.begin(); irv != this->vars.end(); ++irv) {
726
727 EOS5Type vartype = Get_Var_EOS5_Type((*irv));
728 // Compare the EOS5 object type: SWATH,GRID or ZA
729 // eos5objvarlist only stores the variable name, not the path. So we have to ensure the path matches.
730 if(vartype == eos5type) {
731 string var_eos5gname = Obtain_Var_EOS5Type_GroupName((*irv),vartype);
732 // Compare the EOS5 object name
733 // Now we need to match the var name from eos5objvarlist with the var name.
734 if(var_eos5gname == eos5objname) {
735 if((*irv)->name == he5v.name) {
736 if (he5v.dim_list.size() != (*irv)->dims.size())
737 throw2("Number of dimensions don't match with the structmetadata for variable ", (*irv)->name);
738 // Change dimension size
739 (eos5objdimlist[objdimlist_index]).size = ((*irv)->dims[j])->size;
740 break;
741 }
742
743 }
744 }
745 }
746 }
747
748 }
749 // Don't need to go over every var, just find enough.
750 if(updated_dimlist.size() == eos5objdimlist.size())// Finish updating the eos5objdimlist
751 break;
752 }
753#if 0
754for(unsigned int k = 0; k <eos5objdimlist.size();k++) {
755 cerr<<"eos5 obj dim name is "<<eos5objdimlist[k].name << " Size is "<< eos5objdimlist[k].size << endl;
756}
757#endif
758}
759
760
761// Adjust HDF-EOS5 Variable,dimension information.
762void EOS5File::Adjust_EOS5VarDim_Info(vector<HE5Dim>& vardimlist, vector<HE5Dim>& groupdimlist,
763 const string & eos5_obj_name, EOS5Type eos5type)
764{
765
766 BESDEBUG("h5", "Coming to Adjust_EOS5VarDim_Info"<<endl);
767 set<string> dimnamelist;
768 pair<set<string>::iterator, bool> setret;
769
770 // For EOS5 Grids: Dimension names XDim and YDim are predefined.
771 // Even the data producers make a mistake to define "xdim", "ydim" etc in the grid
772 // dimension name list, the variable will still pick up "XDim" and "YDim" as their
773 // dimension names So we assume that 'xdim", "ydim" etc will never appear in the
774 // variable name list.
775 for (unsigned int i = 0; i < vardimlist.size(); ++i) {
776
777 HE5Dim& he5d = vardimlist.at(i);
778 bool dim_in_groupdimlist = false;
779 for (unsigned int j = 0; j < groupdimlist.size(); ++j) {
780 HE5Dim he5gd = groupdimlist.at(j);
781 if (he5gd.name == he5d.name) {
782 he5d.size = he5gd.size;
783 dim_in_groupdimlist = true;
784 break;
785 }
786 }
787
788 if (false == dim_in_groupdimlist)
789 throw2("The EOS5 group dimension name list doesn't include the dimension ", he5d.name);
790
791 // Some variables have data like float foo[nlevel= 10][nlevel= 10],need to make the dimname unique
792 // to ensure the coordinate variables to be generated correctly.
793 //
794 setret = dimnamelist.insert(he5d.name);
795 if (false == setret.second) {
796 int clash_index = 1;
797 string temp_clashname = he5d.name + '_';
798 HDF5CFUtil::gen_unique_name(temp_clashname, dimnamelist, clash_index);
799
800 string ori_dimname = he5d.name;
801
802 he5d.name = temp_clashname;
803
804 // We have to add this dim. to this dim. list if this dim doesn't exist in the dim. list.
805 bool dim_exist = false;
806 for (unsigned int j = 0; j < groupdimlist.size(); ++j) {
807 if (he5d.name == groupdimlist[j].name && he5d.size == groupdimlist[j].size) {
808 dim_exist = true;
809 break;
810 }
811 }
812
813 // Add the new dim. to the dim. list
814 if (false == dim_exist) {
815 ori_dimname = eos5_obj_name + "/" + ori_dimname;
816 string dup_dimname = eos5_obj_name + "/" + he5d.name;
817 if (GRID == eos5type) {
818 ori_dimname = "/GRIDS/" + ori_dimname;
819 dup_dimname = "/GRIDS/" + dup_dimname;
820 }
821 else if (SWATH == eos5type) {
822 ori_dimname = "/SWATHS/" + ori_dimname;
823 dup_dimname = "/SWATHS/" + dup_dimname;
824 }
825 else if (ZA == eos5type) {
826 ori_dimname = "/ZAS/" + ori_dimname;
827 dup_dimname = "/ZAS/" + dup_dimname;
828 }
829
830 // Need to remember the dimname and dupdimname relation in case the situation happens at other variables.
831 dimname_to_dupdimnamelist.insert(pair<string, string>(ori_dimname, dup_dimname));
832 groupdimlist.push_back(he5d);
833 }
834
835 } //"if(false == setret.second)"
836 } // "for (unsigned int i = 0; i <vardimlist.size(); ++i)"
837
838}
839
840// Add EOS5 FIle information
841void EOS5File::Add_EOS5File_Info(HE5Parser * strmeta_info, bool grids_mllcv)
842{
843
844 BESDEBUG("h5", "Coming to Add_EOS5File_Info"<<endl);
845 string fslash_str = "/";
846 string grid_str = "/GRIDS/";
847 string swath_str = "/SWATHS/";
848 string za_str = "/ZAS/";
849
850 // Assign the original number of grids. These number will be useful
851 // to generate the final DAP object names for grids/swaths/zas that don't have coordinate
852 // variables. For example, OMI level 2G product has latitude and longitude with 3-D arrays.
853 // There is no way to make the lat/lon become CF coordinate variables. To still follow the
854 // HDF-EOS5 object name conventions, the original number of grid is expected.
855 // Since this happens only for grids, we just keep the original number for grids now.
856 this->orig_num_grids = strmeta_info->grid_list.size();
857
858 //
859 for (unsigned int i = 0; i < strmeta_info->grid_list.size(); i++) {
860 HE5Grid he5g = strmeta_info->grid_list.at(i);
861 EOS5CFGrid * eos5grid = new EOS5CFGrid();
862 eos5grid->name = he5g.name;
863 eos5grid->dimnames.resize(he5g.dim_list.size());
864
865 for (unsigned int j = 0; j < he5g.dim_list.size(); j++) {
866
867 HE5Dim he5d = he5g.dim_list.at(j);
868 if ("XDim" == he5d.name) eos5grid->xdimsize = he5d.size;
869 if ("YDim" == he5d.name) eos5grid->ydimsize = he5d.size;
870
871 // Here we add the grid name connecting with "/" to
872 // adjust the dim names to assure the uniqueness of
873 // the dimension names for multiple grids.
874 // For single grid, we don't have to do that.
875 // However, considering the rare case that one
876 // can have one grid, one swath and one za, the dimnames
877 // without using the group names may cause the name clashings.
878 // so still add the group path.
879 string unique_dimname = grid_str + he5g.name + fslash_str + he5d.name;
880
881 (eos5grid->dimnames)[j] = unique_dimname;
882
883 pair<map<hsize_t, string>::iterator, bool> mapret1;
884 mapret1 = eos5grid->dimsizes_to_dimnames.insert(pair<hsize_t, string>((hsize_t) he5d.size, unique_dimname));
885
886 // Create the dimname to dimsize map. This will be used to create the missing coordinate
887 // variables. Based on our understanding, dimension names should be unique for
888 // grid/swath/zonal average. We will throw an error if we find the same dimension name used.
889 pair<map<string, hsize_t>::iterator, bool> mapret2;
890 mapret2 = eos5grid->dimnames_to_dimsizes.insert(pair<string, hsize_t>(unique_dimname, (hsize_t) he5d.size));
891 if (false == mapret2.second)
892 throw5("The dimension name ", unique_dimname, " with the dimension size ", he5d.size, "is not unique");
893
894 } // "for (int j=0; j <he5g.dim_list.size(); j++)"
895
896 // Check if having Latitude/Longitude. We will use those Latitude and Longitude as CVs if possible.
897 EOS5SwathGrid_Set_LatLon_Flags(eos5grid, he5g.data_var_list);
898
899 // Using map for possible the third-D CVs.
900 map<string, string> dnames_to_1dvnames;
901 EOS5Handle_nonlatlon_dimcvars(he5g.data_var_list, GRID, he5g.name, dnames_to_1dvnames);
902 eos5grid->dnames_to_1dvnames = dnames_to_1dvnames;
903 eos5grid->point_lower = he5g.point_lower;
904 eos5grid->point_upper = he5g.point_upper;
905 eos5grid->point_left = he5g.point_left;
906 eos5grid->point_right = he5g.point_right;
907
908 eos5grid->eos5_pixelreg = he5g.pixelregistration;
909 eos5grid->eos5_origin = he5g.gridorigin;
910 eos5grid->eos5_projcode = he5g.projection;
911
912 for (unsigned int k = 0; k < 13; k++)
913 eos5grid->param[k] = he5g.param[k];
914 eos5grid->zone = he5g.zone;
915 eos5grid->sphere = he5g.sphere;
916
917 this->eos5cfgrids.push_back(eos5grid);
918
919 } // "for(int i=0; i < strmeta_info->grid_list.size(); i++)"
920
921 // Adding this here seems a hack.
922 this->grids_multi_latloncvs = grids_mllcv;
923
924 // Second Swath
925 for (unsigned int i = 0; i < strmeta_info->swath_list.size(); i++) {
926
927 HE5Swath he5s = strmeta_info->swath_list.at(i);
928 EOS5CFSwath * eos5swath = new EOS5CFSwath();
929 eos5swath->name = he5s.name;
930 eos5swath->dimnames.resize(he5s.dim_list.size());
931
932 for (unsigned int j = 0; j < he5s.dim_list.size(); j++) {
933
934 HE5Dim he5d = he5s.dim_list.at(j);
935
936 // Here we add the swath name connecting with "/" to
937 // adjust the dim names to assure the uniqueness of
938 // the dimension names for multiple swaths.
939 // For single swath, we don't have to do that.
940 // However, considering the rare case that one
941 // can have one grid, one swath and one za, the dimnames
942 // without using the group names may cause the name clashings.
943 // so still add the group path.
944 string unique_dimname = swath_str + he5s.name + fslash_str + he5d.name;
945 (eos5swath->dimnames)[j] = unique_dimname;
946
947 // Create the dimsize to dimname map for those variables missing dimension names.
948 // Note: For different dimnames sharing the same dimsizes, we only pick up the first one.
949 pair<map<hsize_t, string>::iterator, bool> mapret1;
950 mapret1 = eos5swath->dimsizes_to_dimnames.insert(
951 pair<hsize_t, string>((hsize_t) he5d.size, unique_dimname));
952
953 // Create the dimname to dimsize map. This will be used to create the missing coordinate
954 // variables. Based on our understanding, dimension names should be unique for
955 // grid/swath/zonal average. We will throw an error if we find the same dimension name used.
956 pair<map<string, hsize_t>::iterator, bool> mapret2;
957 mapret2 = eos5swath->dimnames_to_dimsizes.insert(
958 pair<string, hsize_t>(unique_dimname, (hsize_t) he5d.size));
959 if (false == mapret2.second)
960 throw5("The dimension name ", unique_dimname, " with the dimension size ", he5d.size, "is not unique");
961
962 } // "for (int j=0; j <he5s.dim_list.size(); j++)"
963
964 // Check if having Latitude/Longitude.
965 EOS5SwathGrid_Set_LatLon_Flags(eos5swath, he5s.geo_var_list);
966
967 // Using map for possible the third-D CVs.
968 map<string, string> dnames_to_geo1dvnames;
969 EOS5Handle_nonlatlon_dimcvars(he5s.geo_var_list, SWATH, he5s.name, dnames_to_geo1dvnames);
970 eos5swath->dnames_to_geo1dvnames = dnames_to_geo1dvnames;
971 this->eos5cfswaths.push_back(eos5swath);
972 } // "for (int i=0; i < strmeta_info->swath_list.size(); i++)"
973
974 // Third Zonal average
975 for (unsigned int i = 0; i < strmeta_info->za_list.size(); i++) {
976
977 HE5Za he5z = strmeta_info->za_list.at(i);
978
979 EOS5CFZa * eos5za = new EOS5CFZa();
980 eos5za->name = he5z.name;
981 eos5za->dimnames.resize(he5z.dim_list.size());
982
983 for (unsigned int j = 0; j < he5z.dim_list.size(); j++) {
984
985 HE5Dim he5d = he5z.dim_list.at(j);
986
987 // Here we add the grid name connecting with "/" to
988 // adjust the dim names to assure the uniqueness of
989 // the dimension names for multiple grids.
990 // For single grid, we don't have to do that.
991 string unique_dimname = za_str + he5z.name + fslash_str + he5d.name;
992 (eos5za->dimnames)[j] = unique_dimname;
993 pair<map<hsize_t, string>::iterator, bool> mapret1;
994 mapret1 = eos5za->dimsizes_to_dimnames.insert(pair<hsize_t, string>((hsize_t) he5d.size, unique_dimname));
995
996 // Create the dimname to dimsize map. This will be used to create the missing coordinate
997 // variables. Based on our understanding, dimension names should be unique for
998 // grid/swath/zonal average. We will throw an error if we find the same dimension name used.
999 pair<map<string, hsize_t>::iterator, bool> mapret2;
1000 mapret2 = eos5za->dimnames_to_dimsizes.insert(pair<string, hsize_t>(unique_dimname, (hsize_t) he5d.size));
1001 if (false == mapret2.second)
1002 throw5("The dimension name ", unique_dimname, " with the dimension size ", he5d.size, "is not unique");
1003
1004 } // "for (int j=0; j <he5z.dim_list.size(); j++) "
1005
1006 // Using map for possible the third-D CVs.
1007 map<string, string> dnames_to_1dvnames;
1008 EOS5Handle_nonlatlon_dimcvars(he5z.data_var_list, ZA, he5z.name, dnames_to_1dvnames);
1009 eos5za->dnames_to_1dvnames = dnames_to_1dvnames;
1010 this->eos5cfzas.push_back(eos5za);
1011 } // "for(int i=0; i < strmeta_info->za_list.size(); i++)"
1012
1013// Debugging info,leave it here. They are very useful.
1014#if 0
1015 for (vector<EOS5CFGrid *>::iterator irg = this->eos5cfgrids.begin();
1016 irg != this->eos5cfgrids.end(); ++irg) {
1017
1018 cerr<<"grid name "<<(*irg)->name <<endl;
1019 cerr<<"eos5_pixelreg"<<(*irg)->eos5_pixelreg <<endl;
1020 cerr<<"eos5_origin"<<(*irg)->eos5_pixelreg <<endl;
1021 cerr<<"point_lower "<<(*irg)->point_lower <<endl;
1022 cerr<<"xdimsize "<<(*irg)->xdimsize <<endl;
1023
1024 if((*irg)->has_g2dlatlon) cerr<<"has g2dlatlon"<<endl;
1025 if((*irg)->has_2dlatlon) cerr<<"has 2dlatlon"<<endl;
1026 if((*irg)->has_1dlatlon) cerr<<"has 1dlatlon"<<endl;
1027 if((*irg)->has_nolatlon) cerr<<"has no latlon" <<endl;
1028 if(this->grids_multi_latloncvs) cerr<<"having multiple lat/lon from structmeta" <<endl;
1029 else cerr<<"no multiple lat/lon from structmeta" <<endl;
1030
1031// Dimension names
1032 "h5","number of dimensions "<<(*irg)->dimnames.size() <<endl;
1033 for (vector<string>::iterator irv = (*irg)->dimnames.begin();
1034 irv != (*irg)->dimnames.end(); ++irv)
1035 cerr<<"dim names" <<*irv <<endl;
1036
1037// mapping size to name
1038 for (map<hsize_t,string>::iterator im1 = (*irg)->dimsizes_to_dimnames.begin();
1039 im1 !=(*irg)->dimsizes_to_dimnames.end();++im1) {
1040 cerr<<"size to name "<< (int)((*im1).first) <<"=> "<<(*im1).second <<endl;
1041 }
1042
1043// mapping dime names to 1d varname
1044 for (map<string,string>::iterator im2 = (*irg)->dnames_to_1dvnames.begin();
1045 im2 !=(*irg)->dnames_to_1dvnames.end();++im2) {
1046 cerr<<"dimanme to 1d var name "<< (*im2).first <<"=> "<<(*im2).second <<endl;
1047 }
1048 }
1049
1050//Swath
1051 for (vector<EOS5CFSwath *>::iterator irg = this->eos5cfswaths.begin();
1052 irg != this->eos5cfswaths.end(); ++irg) {
1053
1054 cerr<<"swath name "<<(*irg)->name <<endl;
1055 if((*irg)->has_nolatlon) cerr<<"has no latlon" <<endl;
1056 if((*irg)->has_1dlatlon) cerr<<"has 1dlatlon"<<endl;
1057 if((*irg)->has_2dlatlon) cerr<<"has 2dlatlon"<<endl;
1058
1059// Dimension names
1060 for (vector<string>::iterator irv = (*irg)->dimnames.begin();
1061 irv != (*irg)->dimnames.end(); ++irv)
1062 cerr<<"dim names" <<*irv <<endl;
1063
1064// mapping size to name
1065 for (map<hsize_t,string>::iterator im1 = (*irg)->dimsizes_to_dimnames.begin();
1066 im1 !=(*irg)->dimsizes_to_dimnames.end();++im1) {
1067 cerr<<"size to name "<< (int)((*im1).first) <<"=> "<<(*im1).second <<endl;
1068 }
1069
1070// mapping dime names to 1d varname
1071 for (map<string,string>::iterator im2 = (*irg)->dnames_to_geo1dvnames.begin();
1072 im2 !=(*irg)->dnames_to_geo1dvnames.end();++im2) {
1073 cerr<<"dimname to 1d varname "<< (*im2).first <<"=> "<<(*im2).second <<endl;
1074 }
1075 }
1076
1077 for (vector<EOS5CFZa *>::iterator irg = this->eos5cfzas.begin();
1078 irg != this->eos5cfzas.end(); ++irg) {
1079
1080 cerr<<"za name now"<<(*irg)->name <<endl;
1081
1082// Dimension names
1083 for (vector<string>::iterator irv = (*irg)->dimnames.begin();
1084 irv != (*irg)->dimnames.end(); ++irv)
1085 cerr<<"dim names" <<*irv <<endl;
1086
1087// mapping size to name
1088 for (map<hsize_t,string>::iterator im1 = (*irg)->dimsizes_to_dimnames.begin();
1089 im1 !=(*irg)->dimsizes_to_dimnames.end();++im1) {
1090 cerr<<"size to name "<< (int)((*im1).first) <<"=> "<<(*im1).second <<endl;
1091 }
1092
1093// mapping dime names to 1d varname
1094 for (map<string,string>::iterator im2 = (*irg)->dnames_to_1dvnames.begin();
1095 im2 !=(*irg)->dnames_to_1dvnames.end();++im2) {
1096 cerr<<"dimname to 1d varname "<< (*im2).first <<"=> "<<(*im2).second <<endl;
1097 }
1098 }
1099#endif
1100
1101}
1102
1103// Check if EOS5 Swath and Grid hold Latitude and Longitude fields.
1104template<class T>
1105void EOS5File::EOS5SwathGrid_Set_LatLon_Flags(T* eos5gridswath, vector<HE5Var> &eos5varlist)
1106{
1107
1108 BESDEBUG("h5", "Coming to EOS5SwathGrid_Set_LatLon_Flags"<<endl);
1109 bool find_lat = false;
1110 bool find_lon = false;
1111 bool has_1dlat = false;
1112 bool has_1dlon = false;
1113 bool has_2dlat = false;
1114 string lat_xdimname;
1115 string lat_ydimname;
1116 string lon_xdimname;
1117 string lon_ydimname;
1118 bool has_2dlon = false;
1119 bool has_g2dlat = false;
1120 bool has_g2dlon = false;
1121
1122 for (unsigned int i = 0; i < eos5varlist.size(); ++i) {
1123 HE5Var he5v = eos5varlist.at(i);
1124 if ("Latitude" == he5v.name) {
1125 find_lat = true;
1126 int num_dims = he5v.dim_list.size();
1127 if (1 == num_dims)
1128 has_1dlat = true;
1129 else if (2 == num_dims) {
1130 lat_ydimname = (he5v.dim_list)[0].name;
1131 lat_xdimname = (he5v.dim_list)[1].name;
1132 has_2dlat = true;
1133 }
1134 else if (num_dims > 2)
1135 has_g2dlat = true;
1136 else
1137 throw1("The number of dimension should not be 0 for grids or swaths");
1138 } // "if ("Latitude" == he5v.name)"
1139
1140 if ("Longitude" == he5v.name) {
1141 find_lon = true;
1142 int num_dims = he5v.dim_list.size();
1143 if (1 == num_dims)
1144 has_1dlon = true;
1145 else if (2 == num_dims) {
1146 lon_ydimname = (he5v.dim_list)[0].name;
1147 lon_xdimname = (he5v.dim_list)[1].name;
1148 has_2dlon = true;
1149 }
1150 else if (num_dims > 2)
1151 has_g2dlon = true;
1152 else
1153 throw1("The number of dimension should not be 0 for grids or swaths");
1154 } // "if ("Longitude" == he5v.name)"
1155
1156 if (true == find_lat && true == find_lon) {
1157 if (true == has_1dlat && true == has_1dlon) eos5gridswath->has_1dlatlon = true;
1158
1159 // Make sure we have lat[YDIM][XDIM] and lon[YDIM][XDIM]
1160 if (true == has_2dlat && true == has_2dlon && lat_ydimname == lon_ydimname && lat_xdimname == lon_xdimname)
1161 eos5gridswath->has_2dlatlon = true;
1162
1163 if (true == has_g2dlat && true == has_g2dlon) eos5gridswath->has_g2dlatlon = true;
1164
1165 eos5gridswath->has_nolatlon = false;
1166 break;
1167 } // "if (true == find_lat && true == find_lon) "
1168 } // "for (unsigned int i = 0; i < eos5varlist.size(); ++i)"
1169}
1170
1171// This function builds up the map from dimension names to coordinate variables
1172// for non-latitude and longitude fields.
1173void EOS5File::EOS5Handle_nonlatlon_dimcvars(vector<HE5Var> & eos5varlist, EOS5Type eos5type, string groupname,
1174 map<string, string>& dnamesgeo1dvnames)
1175{
1176
1177 BESDEBUG("h5", "Coming to EOS5Handle_nonlatlon_dimcvars"<<endl);
1178
1179 set<string> nocvdimnames;
1180 string grid_str = "/GRIDS/";
1181 string xdim_str = "XDim";
1182 string ydim_str = "YDim";
1183 string fslash_str = "/";
1184 string eos5typestr;
1185
1186 if (GRID == eos5type) {
1187 string xdimname = grid_str + groupname + fslash_str + xdim_str;
1188 nocvdimnames.insert(xdimname);
1189 string ydimname = grid_str + groupname + fslash_str + ydim_str;
1190 nocvdimnames.insert(ydimname);
1191 eos5typestr = "/GRIDS/";
1192 }
1193 else if (SWATH == eos5type)
1194 eos5typestr = "/SWATHS/";
1195 else if (ZA == eos5type)
1196 eos5typestr = "/ZAS/";
1197 else
1198 throw1("Unsupported HDF-EOS5 type, this type is not swath, grid or zonal average");
1199
1200 // This assumption is pretty bold. It says: Any 1-D var that has a unique dim. name
1201 // in the var list is a 3rd-dim cv. We need to review this as time goes on. KY 2017-10-19
1202 pair<map<string, string>::iterator, bool> mapret;
1203 for (unsigned int i = 0; i < eos5varlist.size(); ++i) {
1204 HE5Var he5v = eos5varlist.at(i);
1205 if (1 == he5v.dim_list.size()) {
1206 HE5Dim he5d = he5v.dim_list.at(0);
1207 string dimname;
1208 dimname = eos5typestr + groupname + fslash_str + he5d.name;
1209 string varname; // using the new var name format
1210 varname = eos5typestr + groupname + fslash_str + he5v.name;
1211 mapret = dnamesgeo1dvnames.insert(pair<string, string>(dimname, varname));
1212
1213 // If another geo field already shares the same dimname, we need to
1214 // disqualify this geofield as the coordinate variable since it is not
1215 // unique anymore.
1216 if (false == mapret.second) nocvdimnames.insert(dimname);
1217 }
1218 }
1219
1220 // Manage the coordinate variables. We only want to leave fields that uniquely hold
1221 // the dimension name to be the possible cv candidate.
1222 set<string>::iterator itset;
1223 for (itset = nocvdimnames.begin(); itset != nocvdimnames.end(); ++itset)
1224 dnamesgeo1dvnames.erase(*itset);
1225}
1226
1227// Adjust variable names after obtain the parsing information.
1229{
1230
1231 BESDEBUG("h5", "Coming to Adjust_Var_NewName_After_Parsing"<<endl);
1232 for (vector<Var *>::iterator irv = this->vars.begin(); irv != this->vars.end(); ++irv) {
1233 Obtain_Var_NewName(*irv);
1234 }
1235}
1236
1237void EOS5File::Obtain_Var_NewName(Var *var)
1238{
1239
1240 BESDEBUG("h5", "Coming to Obtain_Var_NewName"<<endl);
1241 string fslash_str = "/";
1242 string eos5typestr = "";
1243
1244 EOS5Type vartype = Get_Var_EOS5_Type(var);
1245
1246 // Actually the newname is used to check if the we have the existing
1247 // third dimension coordinate variable. To avoid the check of
1248 // fullpath again, we will make newname to have the unique information
1249 // in the path to identify the objects(Essentially "HDFEOS" is removed).
1250 switch (vartype) {
1251 case GRID: {
1252 eos5typestr = "/GRIDS/";
1253 string eos5_groupname = Obtain_Var_EOS5Type_GroupName(var, vartype);
1254#if 0
1255 // var->newname = ((1 == num_grids)?var->name:
1256 // eos5typestr + eos5_groupname + fslash_str + var->name);
1257#endif
1258 var->newname = eos5typestr + eos5_groupname + fslash_str + var->name;
1259 }
1260 break;
1261
1262 case SWATH: {
1263 eos5typestr = "/SWATHS/";
1264 string eos5_groupname = Obtain_Var_EOS5Type_GroupName(var, vartype);
1265#if 0
1266 // var->newname = ((1 == num_swaths)?var->name:
1267 // eos5typestr + eos5_groupname + fslash_str + var->name);
1268#endif
1269 var->newname = eos5typestr + eos5_groupname + fslash_str + var->name;
1270 }
1271 break;
1272 case ZA: {
1273 eos5typestr = "/ZAS/";
1274 string eos5_groupname = Obtain_Var_EOS5Type_GroupName(var, vartype);
1275#if 0
1276 // var->newname = ((1 == num_zas)?var->name:
1277 // eos5typestr + eos5_groupname + fslash_str + var->name);
1278#endif
1279 var->newname = eos5typestr + eos5_groupname + fslash_str + var->name;
1280 }
1281 break;
1282 case OTHERVARS: {
1283 string eos5infopath = "/HDFEOS INFORMATION";
1284 if (var->fullpath.size() > eos5infopath.size()) {
1285 if (eos5infopath == var->fullpath.substr(0, eos5infopath.size())) var->newname = var->name;
1286 }
1287 else
1288 var->newname = var->fullpath;
1289 }
1290 break;
1291 default:
1292 throw1("Non-supported EOS type");
1293 } // "switch(vartype)"
1294}
1295
1296// Get the HDF-EOS5 type: The type is either grids, swaths or zonal average
1297EOS5Type EOS5File::Get_Var_EOS5_Type(Var* var)
1298{
1299
1300 BESDEBUG("h5", "Coming to Get_Var_EOS5_Type"<<endl);
1301
1302 string EOS5GRIDPATH = "/HDFEOS/GRIDS";
1303 string EOS5SWATHPATH = "/HDFEOS/SWATHS";
1304 string EOS5ZAPATH = "/HDFEOS/ZAS";
1305
1306 if (var->fullpath.size() >= EOS5GRIDPATH.size()) {
1307 if (EOS5GRIDPATH == var->fullpath.substr(0, EOS5GRIDPATH.size())) return GRID;
1308 }
1309 if (var->fullpath.size() >= EOS5SWATHPATH.size()) {
1310 if (EOS5SWATHPATH == var->fullpath.substr(0, EOS5SWATHPATH.size())) return SWATH;
1311 }
1312 if (var->fullpath.size() >= EOS5ZAPATH.size()) {
1313 if (EOS5ZAPATH == var->fullpath.substr(0, EOS5ZAPATH.size())) return ZA;
1314 }
1315 return OTHERVARS;
1316
1317}
1318
1319// Add dimension information from the parseing info.
1321{
1322
1323 BESDEBUG("h5", "Coming to Add_Dim_Name"<<endl);
1324 for (vector<Var *>::iterator irv = this->vars.begin(); irv != this->vars.end(); ++irv) {
1325 Obtain_Var_Dims(*irv, strmeta_info);
1326#if 0
1327 for (vector<Dimension *>::iterator ird = (*irv)->dims.begin();
1328 ird != (*irv)->dims.end();++ird) {
1329 cerr<<"dim name right after change "<<(*ird)->newname <<endl;
1330 }
1331#endif
1332
1333 }
1334}
1335
1336// CHECK if finding the same variables from the parser.
1337bool EOS5File::Obtain_Var_Dims(Var *var, HE5Parser * strmeta_info)
1338{
1339
1340 BESDEBUG("h5", "Coming to Obtain_Var_Dims"<<endl);
1341 string varname_from_parser = "";
1342 EOS5Type vartype = Get_Var_EOS5_Type(var);
1343
1344 if (GRID == vartype) {
1345 int num_grids = strmeta_info->grid_list.size();
1346 for (int i = 0; i < num_grids; ++i) {
1347 HE5Grid he5g = strmeta_info->grid_list.at(i);
1348 if (he5g.name == Obtain_Var_EOS5Type_GroupName(var, vartype)) {
1349 EOS5CFGrid *eos5cfgrid = (this->eos5cfgrids)[i];
1350 bool var_is_parsed = Set_Var_Dims(eos5cfgrid, var, he5g.data_var_list, he5g.name, num_grids, GRID);
1351 if (false == var_is_parsed) {
1352 map<hsize_t, string> dimsizes_to_dimnames = eos5cfgrid->dimsizes_to_dimnames;
1353 // Check if this grid includes data fields(variables) that don't have any dimension names.
1354 // This rarely happens. But we do find one NASA Aura product that has this problem. Although
1355 // this has been fixed, we should anticipiate that the similar problem may happen in the future.
1356 // So check here to avoid the potential problems. KY 2012-1-9
1357 Set_NonParse_Var_Dims(eos5cfgrid, var, dimsizes_to_dimnames, num_grids, vartype);
1358 }
1359 }
1360 }// "for (unsigned int i = 0; i < num_grids; ++i)"
1361 }// "if (GRID == vartype)"
1362 else if (SWATH == vartype) {
1363 int num_swaths = strmeta_info->swath_list.size();
1364 for (int i = 0; i < num_swaths; ++i) {
1365
1366 HE5Swath he5s = strmeta_info->swath_list.at(i);
1367
1368 if (he5s.name == Obtain_Var_EOS5Type_GroupName(var, vartype)) {
1369
1370 EOS5CFSwath *eos5cfswath = (this->eos5cfswaths)[i];
1371
1372 bool var_is_parsed = true;
1373 int swath_fieldtype_flag = Check_EOS5Swath_FieldType(var);
1374 if (1 == swath_fieldtype_flag)
1375 var_is_parsed = Set_Var_Dims(eos5cfswath, var, he5s.geo_var_list, he5s.name, num_swaths, SWATH);
1376 else if (0 == swath_fieldtype_flag)
1377 var_is_parsed = Set_Var_Dims(eos5cfswath, var, he5s.data_var_list, he5s.name, num_swaths, SWATH);
1378 else
1379 // Neither Geo nor Data(For example, added by the augmentation tool)
1380 var_is_parsed = false;
1381
1382 if (false == var_is_parsed) {
1383 map<hsize_t, string> dimsizes_to_dimnames = eos5cfswath->dimsizes_to_dimnames;
1384 Set_NonParse_Var_Dims(eos5cfswath, var, dimsizes_to_dimnames, num_swaths, vartype);
1385 }
1386 } // "if (he5s.name == Obtain_Var_EOS5Type_GroupName(var,vartype))"
1387 } // "for (unsigned int i = 0; i < num_swaths; ++i)"
1388 } // "else if (SWATH == vartype)"
1389
1390 else if (ZA == vartype) {
1391
1392 int num_zas = strmeta_info->za_list.size();
1393 for (int i = 0; i < num_zas; ++i) {
1394 HE5Za he5z = strmeta_info->za_list.at(i);
1395 if (he5z.name == Obtain_Var_EOS5Type_GroupName(var, vartype)) {
1396 EOS5CFZa *eos5cfza = (this->eos5cfzas)[i];
1397 bool var_is_parsed = Set_Var_Dims(eos5cfza, var, he5z.data_var_list, he5z.name, num_zas, ZA);
1398 if (false == var_is_parsed) {
1399 map<hsize_t, string> dimsizes_to_dimnames = eos5cfza->dimsizes_to_dimnames;
1400 Set_NonParse_Var_Dims(eos5cfza, var, dimsizes_to_dimnames, num_zas, vartype);
1401 }
1402 }
1403 }
1404 }
1405 return false;
1406}
1407
1408// Set dimension info.(dimension names and sizes) to variables.
1409template<class T>
1410bool EOS5File::Set_Var_Dims(T* eos5data, Var *var, vector<HE5Var> &he5var, const string& groupname, int num_groups,
1411 EOS5Type eos5type)
1412{
1413
1414 BESDEBUG("h5", "Coming to Set_Var_Dims"<<endl);
1415
1416 bool is_parsed = false;
1417 string eos5typestr = "";
1418 string fslash_str = "/";
1419
1420 if (GRID == eos5type)
1421 eos5typestr = "/GRIDS/";
1422 else if (SWATH == eos5type)
1423 eos5typestr = "/SWATHS/";
1424 else if (ZA == eos5type)
1425 eos5typestr = "/ZAS/";
1426 else
1427 throw1("Unsupported HDF-EOS5 type, this type is not swath, grid or zonal average");
1428
1429 for (unsigned int i = 0; i < he5var.size(); i++) {
1430
1431 HE5Var he5v = he5var.at(i);
1432
1433 if (he5v.name == var->name) {
1434 if (he5v.dim_list.size() != var->dims.size())
1435 throw2("Number of dimensions don't match with the structmetadata for variable ", var->name);
1436 is_parsed = true;
1437
1438 // Some variables have the same dim. names shared. For examples, we
1439 // see variables that have int foo[nlevels][nlevels]. To generate the CVs,
1440 // we have to make the dimension name unique for one variable. So we will
1441 // change the dimension names. The variable for the same example will be
1442 // int foo[nlevels][nlevels_1]. Note this is not required by CF conventions.
1443 // This is simply due to the missing of the third coordinate variable for some
1444 // NASA products. Another way is to totally ignore this kind of variables which
1445 // we will wait for users' responses.
1446
1447 // Here is the killer, if different dim. names share the same size,
1448 // Currently there are no ways to know which dimension name is corresponding to
1449 // which size. HDF-EOS model gives too much freedom to users. The DimList in
1450 // the StructMetadata doesn't reflect the order at all. See two example files
1451 // CH4 in TES-Aura_L3-CH4_r0000010410_F01_07.he5 and NO2DayColumn in
1452 // HIRDLS-Aura_L3SCOL_v06-00-00-c02_2005d022-2008d077.he5.
1453 // Fortunately it seems that it doesn't matter for us to make the mapping from
1454 // dimension names to coordinate variables.
1455 // KY 2012-1-10
1456
1457 // Dimension list of some OMI level 2 products doesn't include all dimension name and size
1458 // pairs. For example, Latitude[1644][60]. We have no way to find the dimension name of
1459 // the dimension with the size of 1644. The dimension name list of the variable also
1460 // includes the wrong dimension name. In this case, a dimension with the dimension size =1
1461 // is allocated in the latitude's dimension list. The latest version still has this bug.
1462 // To serve this kind of files, we create a fakedim name for the unmatched size.
1463 // KY 2012-1-13
1464
1465 set<hsize_t> dimsize_have_name_set;
1466 pair<set<hsize_t>::iterator, bool> setret1;
1467 set<string> thisvar_dimname_set;
1468 pair<set<string>::iterator, bool> setret2;
1469
1470 for (unsigned int j = 0; j < he5v.dim_list.size(); j++) {
1471 HE5Dim he5d = he5v.dim_list.at(j);
1472 for (vector<Dimension *>::iterator ird = var->dims.begin(); ird != var->dims.end(); ++ird) {
1473
1474 if ((hsize_t) (he5d.size) == (*ird)->size) {
1475 // This will assure that the same size dims be assigned to different dims
1476 if ("" == (*ird)->name) {
1477 string dimname_candidate = eos5typestr + groupname + fslash_str + he5d.name;
1478 setret2 = thisvar_dimname_set.insert(dimname_candidate);
1479 if (true == setret2.second) {
1480 (*ird)->name = dimname_candidate;
1481 // Should check in the future if the newname may cause potential inconsistency. KY:2012-3-9
1482 (*ird)->newname = (num_groups == 1) ? he5d.name : (*ird)->name;
1483 eos5data->vardimnames.insert((*ird)->name);
1484 // Since there is no way to figure out the unlimited dimension info. of an individual variable
1485 // from the dimension list. Here we just provide the dimnames to unlimited dimension mapping
1486 // based on the variable mapping. KY 2016-02-18
1487 eos5data->dimnames_to_unlimited[(*ird)->name] = (*ird)->unlimited_dim;
1488 }
1489 }
1490 }
1491 }
1492 } // "for (unsigned int j=0; j<he5v.dim_list.size();j++)"
1493
1494 // We have to go through the dimension list of this variable again to assure that every dimension has a name.
1495 // This is how that FakeDim is added. We still need it just in case. KY 2017-10-19
1496 for (vector<Dimension *>::iterator ird = var->dims.begin(); ird != var->dims.end(); ++ird) {
1497 if ("" == (*ird)->name)
1498 Create_Unique_DimName(eos5data, thisvar_dimname_set, *ird, num_groups, eos5type);
1499 }
1500 } // "if (he5v.name == var->name) "
1501 } // "for (unsigned int i = 0; i < he5var.size(); i++)"
1502 return is_parsed;
1503}
1504
1505// Create unique dimension names. Se the comments below.
1506template<class T>
1507void EOS5File::Create_Unique_DimName(T*eos5data, set<string>& thisvar_dimname_set, Dimension *dim, int num_groups,
1508 EOS5Type eos5type)
1509{
1510
1511 BESDEBUG("h5", "Coming to Create_Unique_DimName"<<endl);
1512 map<hsize_t, string>::iterator itmap1;
1513 map<string, hsize_t>::iterator itmap2;
1514 pair<set<string>::iterator, bool> setret2;
1515 itmap1 = (eos5data->dimsizes_to_dimnames).find(dim->size);
1516
1517 // Even if we find this dimension matches the dimsizes_to_dimnames map, we have to check if the dimension
1518 // name has been used for this size. This is to make sure each dimension has a unique name in a variable.
1519 // For example, float foo[100][100] can be float foo[nlevels = 100][nlevels_1 = 100].
1520 // Step 1: Check if there is a dimension name that matches the size
1521
1522 if (itmap1 != (eos5data->dimsizes_to_dimnames).end()) {
1523 string dimname_candidate = (eos5data->dimsizes_to_dimnames)[dim->size];
1524
1525 // First check local var dimname set
1526 setret2 = thisvar_dimname_set.insert(dimname_candidate);
1527
1528 if (false == setret2.second) {
1529
1530 // Will see if other dimension names have this size
1531 bool match_some_dimname = Check_All_DimNames(eos5data, dimname_candidate, dim->size);
1532
1533 if (false == match_some_dimname) {
1534
1535 // dimname_candidate is updated.
1536 Get_Unique_Name(eos5data->vardimnames, dimname_candidate);
1537 thisvar_dimname_set.insert(dimname_candidate);
1538
1539 // Finally generate a new dimension(new dim. name with a size);Update all information
1540 Insert_One_NameSizeMap_Element2(eos5data->dimnames_to_dimsizes, eos5data->dimnames_to_unlimited,
1541 dimname_candidate, dim->size, dim->unlimited_dim);
1542 eos5data->dimsizes_to_dimnames.insert(pair<hsize_t, string>(dim->size, dimname_candidate));
1543 eos5data->dimnames.push_back(dimname_candidate);
1544 }
1545 }
1546
1547 // The final dimname_candidate(may be updated) should be assigned to the name of this dimension
1548 dim->name = dimname_candidate;
1549 if (num_groups > 1)
1550 dim->newname = dim->name;
1551 else {
1552 string dname = HDF5CFUtil::obtain_string_after_lastslash(dim->name);
1553 if ("" == dname)
1554 throw3("The dimension name ", dim->name, " of the variable is not right");
1555 else
1556 dim->newname = dname;
1557 }
1558 }
1559
1560 else { // No dimension names match or close to march this dimension name, we will create a fakedim.
1561 // Check Add_One_FakeDim_Name in HDF5CF.cc Fakedimname must be as a string reference.
1562 string Fakedimname = Create_Unique_FakeDimName(eos5data, eos5type);
1563 thisvar_dimname_set.insert(Fakedimname);
1564
1565 // Finally generate a new dimension(new dim. name with a size);Update all information
1566 Insert_One_NameSizeMap_Element2(eos5data->dimnames_to_dimsizes, eos5data->dimnames_to_unlimited, Fakedimname,
1567 dim->size, dim->unlimited_dim);
1568 eos5data->dimsizes_to_dimnames.insert(pair<hsize_t, string>(dim->size, Fakedimname));
1569 eos5data->dimnames.push_back(Fakedimname);
1570 dim->name = Fakedimname;
1571 if (num_groups > 1)
1572 dim->newname = dim->name;
1573 else {
1574 string dname = HDF5CFUtil::obtain_string_after_lastslash(dim->name);
1575 if ("" == dname)
1576 throw3("The dimension name ", dim->name, " of the variable is not right");
1577 else
1578 dim->newname = dname;
1579 }
1580 }
1581}
1582
1583// Check all dim. names to see if this dim. size is used by another dim. name.
1584template<class T>
1585bool EOS5File::Check_All_DimNames(T* eos5data, string& dimname, hsize_t dimsize)
1586{
1587
1588 BESDEBUG("h5", "Coming to Check_All_DimNames"<<endl);
1589 bool ret_flag = false;
1590 for (map<string, hsize_t>::iterator im = eos5data->dimnames_to_dimsizes.begin();
1591 im != eos5data->dimnames_to_dimsizes.end(); ++im) {
1592 // dimname must not be the same one since the same one is rejected.
1593 if (dimsize == (*im).second && dimname != (*im).first) {
1594 dimname = (*im).first;
1595 ret_flag = true;
1596 break;
1597 }
1598 }
1599 return ret_flag;
1600}
1601
1602// Get a unique name.
1603void EOS5File::Get_Unique_Name(set<string> & nameset, string& dimname_candidate)
1604{
1605
1606 BESDEBUG("h5", "Coming to Get_Unique_Name"<<endl);
1607 int clash_index = 1;
1608 string temp_clashname = dimname_candidate + '_';
1609 HDF5CFUtil::gen_unique_name(temp_clashname, nameset, clash_index);
1610 dimname_candidate = temp_clashname;
1611}
1612
1613// We may need to generate a unique "fake" dim. name for dimensions that don't have any dimension names.
1614template<class T>
1615string EOS5File::Create_Unique_FakeDimName(T*eos5data, EOS5Type eos5type)
1616{
1617
1618 BESDEBUG("h5", "Coming to Create_Unique_FakeDimName"<<endl);
1619 string fslash_str = "/";
1620 string eos5typestr;
1621 if (GRID == eos5type)
1622 eos5typestr = "/GRIDS/";
1623 else if (SWATH == eos5type)
1624 eos5typestr = "/SWATHS/";
1625 else if (ZA == eos5type)
1626 eos5typestr = "/ZAS/";
1627 else
1628 throw1("Unsupported HDF-EOS5 type, this type is not swath, grid or zonal average");
1629
1630 stringstream sfakedimindex;
1631 sfakedimindex << eos5data->addeddimindex;
1632 string fakedimstr = "FakeDim";
1633 string added_dimname = eos5typestr + eos5data->name + fslash_str + fakedimstr + sfakedimindex.str();
1634
1635 pair<set<string>::iterator, bool> setret;
1636 setret = eos5data->vardimnames.insert(added_dimname);
1637 if (false == setret.second) Get_Unique_Name(eos5data->vardimnames, added_dimname);
1638 eos5data->addeddimindex = eos5data->addeddimindex + 1;
1639 return added_dimname;
1640}
1641
1642// Obtain the group name this variable belongs.
1643string EOS5File::Obtain_Var_EOS5Type_GroupName(Var*var, EOS5Type eos5type)
1644{
1645
1646 BESDEBUG("h5", "Coming to Obtain_Var_EOS5Type_GroupName"<<endl);
1647 string EOS5GRIDPATH = "/HDFEOS/GRIDS";
1648 string EOS5SWATHPATH = "/HDFEOS/SWATHS";
1649 string EOS5ZAPATH = "/HDFEOS/ZAS";
1650 size_t eostypename_start_pos = 0;
1651 size_t eostypename_end_pos;
1652 string groupname;
1653
1654 // The fullpath is like "HDFEOS/GRIDS/Temp/Data Fields/etc
1655 // To get "Temp", we obtain the position of "T" and the position of "p"
1656 // and then generate a substr.
1657
1658 if (GRID == eos5type)
1659 eostypename_start_pos = EOS5GRIDPATH.size() + 1;
1660 else if (SWATH == eos5type)
1661 eostypename_start_pos = EOS5SWATHPATH.size() + 1;
1662 else if (ZA == eos5type)
1663 eostypename_start_pos = EOS5ZAPATH.size() + 1;
1664 else
1665 throw2("Non supported eos5 type for var ", var->fullpath);
1666
1667 eostypename_end_pos = var->fullpath.find('/', eostypename_start_pos) - 1;
1668 groupname = var->fullpath.substr(eostypename_start_pos, eostypename_end_pos - eostypename_start_pos + 1);
1669
1670 BESDEBUG("h5", "In Obtain_Var_EOS5Type_GroupName(), the groupname is "<<groupname << endl);
1671
1672 return groupname;
1673}
1674
1675// Check whether this field belongs to "Geolocation Fields" or "Data Fields"
1676int EOS5File::Check_EOS5Swath_FieldType(Var*var)
1677{
1678
1679 string geofield_relative_path = "/Geolocation Fields/" + var->name;
1680 string datafield_relative_path = "/Data Fields/" + var->name;
1681
1682 int tempflag = -1;
1683
1684 if (var->fullpath.size() > datafield_relative_path.size()) {
1685 size_t field_pos_in_full_path = var->fullpath.size() - datafield_relative_path.size();
1686 if (var->fullpath.rfind(datafield_relative_path, field_pos_in_full_path) != string::npos) tempflag = 0;
1687 }
1688
1689 if (tempflag != 0 && (var->fullpath.size() > geofield_relative_path.size())) {
1690 size_t field_pos_in_full_path = var->fullpath.size() - geofield_relative_path.size();
1691 if (var->fullpath.rfind(geofield_relative_path, field_pos_in_full_path) != string::npos) tempflag = 1;
1692 }
1693 return tempflag;
1694}
1695
1696// An error will be thrown if we find a dimension size that doesn't match any dimension name
1697// in this EOS5 group.
1698template<class T>
1699void EOS5File::Set_NonParse_Var_Dims(T*eos5data, Var* var, map<hsize_t, string>& /*dimsizes_to_dimnames*/,
1700 int num_groups, EOS5Type eos5type)
1701{
1702
1703 BESDEBUG("h5", "Coming to Set_NonParse_Var_Dims"<<endl);
1704 map<hsize_t, string>::iterator itmap;
1705 set<string> thisvar_dimname_set;
1706
1707 for (vector<Dimension *>::iterator ird = var->dims.begin(); ird != var->dims.end(); ++ird) {
1708 if ("" == (*ird)->name)
1709 Create_Unique_DimName(eos5data, thisvar_dimname_set, *ird, num_groups, eos5type);
1710 else
1711 throw5("The dimension name ", (*ird)->name, " of the variable ", var->name, " is not right");
1712 }
1713}
1714
1715// Aura files don't use the CF attribute names for bunch of attributes. We need to make it right.
1717{
1718
1719 BESDEBUG("h5", "Coming to Check_Aura_Product_Status"<<endl);
1720 // Aura files will put an attribute called InStrumentName under /HDFEOS/ADDITIONAL/FILE_ATTRIBUTES
1721 // We just need to check that attribute.
1722 string eos5_fattr_group_name = "/HDFEOS/ADDITIONAL/FILE_ATTRIBUTES";
1723 string instrument_attr_name = "InstrumentName";
1724
1725 // Check if this file is an aura file
1726 for (vector<Group *>::iterator irg = this->groups.begin(); irg != this->groups.end(); ++irg) {
1727 if (eos5_fattr_group_name == (*irg)->path) {
1728 for (vector<Attribute *>::iterator ira = (*irg)->attrs.begin(); ira != (*irg)->attrs.end(); ++ira) {
1729 if (instrument_attr_name == (*ira)->name) {
1730 Retrieve_H5_Attr_Value(*ira, (*irg)->path);
1731 string attr_value((*ira)->value.begin(), (*ira)->value.end());
1732 if ("OMI" == attr_value) {
1733 this->isaura = true;
1734 this->aura_name = OMI;
1735 }
1736 else if ("MLS Aura" == attr_value) {
1737 this->isaura = true;
1738 this->aura_name = MLS;
1739 }
1740 else if ("TES" == attr_value) {
1741 this->isaura = true;
1742 this->aura_name = TES;
1743 }
1744 else if ("HIRDLS" == attr_value) {
1745 this->isaura = true;
1746 this->aura_name = HIRDLS;
1747 }
1748 break;
1749 }
1750 }
1751 }
1752 }
1753
1754 // Assign EOS5 to CF MAP values for Aura files
1755 if (true == this->isaura) {
1756 eos5_to_cf_attr_map["FillValue"] = "_FillValue";
1757 eos5_to_cf_attr_map["MissingValue"] = "missing_value";
1758 eos5_to_cf_attr_map["Units"] = "units";
1759 eos5_to_cf_attr_map["Offset"] = "add_offset";
1760 eos5_to_cf_attr_map["ScaleFactor"] = "scale_factor";
1761 eos5_to_cf_attr_map["ValidRange"] = "valid_range";
1762 eos5_to_cf_attr_map["Title"] = "title";
1763 }
1764
1765}
1766
1767// Handle Coordinate variables
1769{
1770
1771 BESDEBUG("h5", "Coming to Handle_CVar()"<<endl);
1772
1773 // If this file is augmented.
1774 bool is_augmented = Check_Augmentation_Status();
1775
1776#if 0
1777 if(is_augmented) cerr<<"The file is augmented "<<endl;
1778 else cerr<<"The file is not augmented "<<endl;
1779#endif
1780
1781 // Handle coordinate variables for grids.
1782 if (this->eos5cfgrids.size() > 0)
1783 Handle_Grid_CVar(is_augmented);
1784 if (this->eos5cfswaths.size() > 0)
1785 Handle_Swath_CVar(is_augmented);
1786 if (this->eos5cfzas.size() > 0)
1787 Handle_Za_CVar(is_augmented);
1788
1789#if 0
1790 for (vector<EOS5CVar *>::iterator irv = this->cvars.begin();
1791 irv != this->cvars.end(); irv++) {
1792 cerr<<"EOS5CVar name "<<(*irv)->name <<endl;
1793 cerr<<"EOS5CVar dimension name "<< (*irv)->cfdimname <<endl;
1794 cerr<<"EOS5CVar new name "<<(*irv)->newname <<endl;
1795 cerr<<"EOS5CVar type is "<<(*irv)->cvartype <<endl;
1796//cerr<<"EOS5CVar dtype is "<<(*irv)->dtype <<endl;
1797 }
1798#endif
1799
1800}
1801
1802// Handle Grid Coordinate variables
1803void EOS5File::Handle_Grid_CVar(bool is_augmented)
1804{
1805
1806 BESDEBUG("h5", "Coming to Handle_Grid_CVar"<<endl);
1807 if (true == is_augmented) {
1808 // Create latitude/longitude based on the first XDim and YDim
1809 Handle_Augmented_Grid_CVar();
1810 }
1811 else {
1812 Remove_MultiDim_LatLon_EOS5CFGrid();
1813 // If the grid size is 0, it must be a Grid file that cannot be handled
1814 // with the CF option, simply return with handling any coordinate variables.
1815 if (0 == this->eos5cfgrids.size()) return;
1816 if (1 == this->eos5cfgrids.size())
1817 Handle_Single_Nonaugment_Grid_CVar((this->eos5cfgrids)[0]);
1818 else
1819 Handle_Multi_Nonaugment_Grid_CVar();
1820 }
1821}
1822
1823// Check if this file is augmented. The current augmentation tool will
1824// add extra variables for every EOS5 object. This function will check
1825// if that is the case.
1826bool EOS5File::Check_Augmentation_Status()
1827{
1828
1829 BESDEBUG("h5", "Coming to Check_Augmentation_Status()"<<endl);
1830 bool aug_status = false;
1831 int num_aug_eos5grp = 0;
1832
1833 for (vector<EOS5CFGrid *>::iterator irg = this->eos5cfgrids.begin(); irg != this->eos5cfgrids.end(); ++irg) {
1834 for (vector<Var *>::iterator irv = this->vars.begin(); irv != this->vars.end(); ++irv) {
1835 bool is_augmented = Check_Augmented_Var_Candidate(*irg, *irv, GRID);
1836 if (true == is_augmented) {
1837 num_aug_eos5grp++;
1838 break;
1839 }
1840 }
1841 }
1842
1843 for (vector<EOS5CFSwath *>::iterator irg = this->eos5cfswaths.begin(); irg != this->eos5cfswaths.end(); ++irg) {
1844 for (vector<Var *>::iterator irv = this->vars.begin(); irv != this->vars.end(); ++irv) {
1845 bool is_augmented = Check_Augmented_Var_Candidate(*irg, *irv, SWATH);
1846 if (true == is_augmented) {
1847 num_aug_eos5grp++;
1848 break;
1849 }
1850
1851 }
1852 }
1853
1854 for (vector<EOS5CFZa *>::iterator irg = this->eos5cfzas.begin(); irg != this->eos5cfzas.end(); ++irg) {
1855 for (vector<Var *>::iterator irv = this->vars.begin(); irv != this->vars.end(); ++irv) {
1856 bool is_augmented = Check_Augmented_Var_Candidate(*irg, *irv, ZA);
1857 if (true == is_augmented) {
1858 num_aug_eos5grp++;
1859 break;
1860 }
1861 }
1862 }
1863
1864 int total_num_eos5grp = this->eos5cfgrids.size() + this->eos5cfswaths.size() + this->eos5cfzas.size();
1865//cerr<< "total_num_eos5grp "<<total_num_eos5grp <<endl;
1866//"h5","num_aug_eos5grp "<< num_aug_eos5grp <<endl;
1867
1868 if (num_aug_eos5grp == total_num_eos5grp) aug_status = true;
1869 return aug_status;
1870
1871}
1872
1873// This method is not used. Still keep it now since it may be useful in the future. KY 2012-3-09
1874// Don't remove the #if 0 #endif block.
1875#if 0
1876bool EOS5File::Check_Augmented_Var_Attrs(Var *var) {
1877
1878 // We will check whether the attribute "CLASS" and the attribute "REFERENCE_LIST" exist.
1879 // For the attribute "CLASS", we would like to check if the value is "DIMENSION_SCALE".
1880 bool has_dimscale_class = false;
1881 bool has_reflist = false;
1882 for (vector<Attribute *>::iterator ira = var->attrs.begin();
1883 ira != var->attrs.end(); ++ira) {
1884 if ("CLASS" == (*ira)->name) {
1885 Retrieve_H5_Attr_Value(*ira,var->fullpath);
1886 string class_value((*ira)->value.begin(),(*ira)->value.end());
1887 if ("DIMENSION_SCALE"==class_value)
1888 has_dimscale_class = true;
1889 }
1890
1891 if ("REFERENCE_LIST" == (*ira)->name)
1892 has_reflist = true;
1893 if (true == has_reflist && true == has_dimscale_class)
1894 break;
1895 }
1896
1897 if (true == has_reflist && true == has_dimscale_class)
1898 return true;
1899 else
1900 return false;
1901
1902}
1903#endif
1904
1905// Check if the variable candidate exists for the augmented case.
1906// The augmented variables have path like /HDFEOS/GRIDS/HIRDLS/nTimes
1907// The general HDF-EOS5 variables have path like /HDFEOS/GRIDS/HIRDLS/Data Fields/Times.
1908// So if we find the var name is the same as the string stripped from /HDFEOS/GRIDS/HIRDLS,
1909// then this file is augmented.
1910// Hope that no other hybrid-HDFEOS5 files fall to this category.
1911template<class T>
1912bool EOS5File::Check_Augmented_Var_Candidate(T *eos5data, Var *var, EOS5Type eos5type)
1913{
1914
1915 BESDEBUG("h5", "Coming to Check_Augmented_Var_Candidate"<<endl);
1916 bool augmented_var = false;
1917
1918 string EOS5DATAPATH = "";
1919 if (GRID == eos5type)
1920 EOS5DATAPATH = "/HDFEOS/GRIDS/";
1921 else if (ZA == eos5type)
1922 EOS5DATAPATH = "/HDFEOS/ZAS/";
1923 else if (SWATH == eos5type)
1924 EOS5DATAPATH = "/HDFEOS/SWATHS/";
1925 else
1926 throw1("Non supported EOS5 type");
1927
1928 string fslash_str = "/";
1929 string THIS_EOS5DATAPATH = EOS5DATAPATH + eos5data->name + fslash_str;
1930
1931 // Match the EOS5 type
1932 if (eos5type == Get_Var_EOS5_Type(var)) {
1933 string var_eos5data_name = Obtain_Var_EOS5Type_GroupName(var, eos5type);
1934 // Match the EOS5 group name
1935 if (var_eos5data_name == eos5data->name) {
1936 if (var->fullpath.size() > THIS_EOS5DATAPATH.size()) {
1937 // Obtain the var name from the full path
1938 string var_path_after_eos5dataname = var->fullpath.substr(THIS_EOS5DATAPATH.size());
1939 // Match the variable name
1940 if (var_path_after_eos5dataname == var->name) augmented_var = true;
1941 }
1942 }
1943 }
1944
1945 return augmented_var;
1946
1947}
1948
1949// Handle augmented grid coordinate variables.
1950void EOS5File::Handle_Augmented_Grid_CVar()
1951{
1952 BESDEBUG("h5", "Coming to Handle_Augmented_Grid_CVar()"<<endl);
1953 for (vector<EOS5CFGrid *>::iterator irv = this->eos5cfgrids.begin(); irv != this->eos5cfgrids.end(); ++irv)
1954 Handle_Single_Augment_CVar(*irv, GRID);
1955}
1956
1957// Handle the coordinate variables for the single HDF-EOS5 objects(grid,swath,zonal average) for an augmented file
1958template<class T>
1959void EOS5File::Handle_Single_Augment_CVar(T* cfeos5data, EOS5Type eos5type)
1960{
1961
1962 BESDEBUG("h5", "Coming to Handle_Single_Augment_CVar()"<<endl);
1963 set<string> tempvardimnamelist;
1964 tempvardimnamelist = cfeos5data->vardimnames;
1965 set<string>::iterator its;
1966 for (its = tempvardimnamelist.begin(); its != tempvardimnamelist.end(); ++its) {
1967 for (vector<Var *>::iterator irv = this->vars.begin(); irv != this->vars.end();) {
1968
1969 bool is_augmented = Check_Augmented_Var_Candidate(cfeos5data, *irv, eos5type);
1970
1971 if (true == is_augmented) {
1972
1973 // Since we have already checked if this file is augmented or not, we can safely
1974 // compare the dimension name with the var name now.
1975 string tempdimname = HDF5CFUtil::obtain_string_after_lastslash(*its);
1976
1977 // The added variable name is always the same as the dimension name.
1978 if (tempdimname == (*irv)->name) {
1979
1980 //Find it, create a coordinate variable.
1981 EOS5CVar *EOS5cvar = new EOS5CVar(*irv);
1982
1983 // Still keep the original dimension name to avoid the nameclashing when
1984 // one grid and one swath and one za occur in the same file
1985 EOS5cvar->cfdimname = *its;
1986 EOS5cvar->cvartype = CV_EXIST;
1987 EOS5cvar->eos_type = eos5type;
1988
1989 // Save this cv to the cv vector
1990 this->cvars.push_back(EOS5cvar);
1991
1992 // Remove this var from the var vector since it becomes a cv.
1993 delete (*irv);
1994 irv = this->vars.erase(irv);
1995 }
1996 else {
1997 ++irv;
1998 }
1999 } // "if (true == is_augmented)"
2000 else {
2001 ++irv;
2002 }
2003 } // "for (vector<Var *>::iterator irv = this->vars.begin();...."
2004 } // "for (its = tempvardimnamelist.begin(); its != tempvardimnamelist.end(); ++its)"
2005
2006 for (vector<EOS5CVar *>::iterator irv = this->cvars.begin(); irv != this->cvars.end(); ++irv) {
2007 its = tempvardimnamelist.find((*irv)->cfdimname);
2008 if (its != tempvardimnamelist.end()) tempvardimnamelist.erase(its);
2009 }
2010
2011 if (false == tempvardimnamelist.empty())
2012 throw1("Augmented files still need to provide more coordinate variables");
2013}
2014
2015//Currently we remove HDF-EOS5 grid if we find the latitude/longitude is >2D. This is a big question mark
2016// given some data producers just don't follow the HDF-EOS5 specification to generate the latitude/longitude.
2017// KY 2016-07-12
2018void EOS5File::Remove_MultiDim_LatLon_EOS5CFGrid()
2019{
2020
2021 BESDEBUG("h5", "Coming to Remove_MultiDim_LatLon_EOS5CFGrid()"<<endl);
2022 for (vector<EOS5CFGrid *>::iterator irg = this->eos5cfgrids.begin(); irg != this->eos5cfgrids.end();) {
2023
2024 // If number of dimension latitude/longitude is >=2, no cooridnate variables will be generated.
2025 // We will simply remove this grid from the vector eos5cfgrids.
2026 // In the future, we may consider supporting 2D latlon. KY 2012-1-17
2027 // I just find that new OMI level 3 data provide 2D lat/lon for geographic projection data.
2028 // The 2D lat/lon can be condensed to 1D lat/lon, which is the same calculated by the calculation of
2029 // the projection. So I don't remove this OMI grid from the grid list. KY 2012-2-9
2030 // However, I do remove the "Longitude" and "Latitude" fields since "Latitude" and "Longitude"
2031 // can be calculated.
2032
2033 bool irg_erase = false;
2034
2035 if (true == (*irg)->has_2dlatlon) {
2036
2037 if ((true == this->isaura) && (OMI == this->aura_name) && (HE5_GCTP_GEO == (*irg)->eos5_projcode))
2038
2039 { // We need to remove the redundant latitude and longitude fields
2040
2041 string EOS5GRIDPATH = "/HDFEOS/GRIDS/";
2042 string fslash_str = "/";
2043 string THIS_EOS5GRIDPATH = EOS5GRIDPATH + (*irg)->name + fslash_str;
2044 int catch_latlon = 0;
2045
2046 for (vector<Var *>::iterator irv = this->vars.begin(); (irv != this->vars.end()) && (catch_latlon != 2);
2047 ) {
2048 if (GRID == Get_Var_EOS5_Type(*irv) && ((*irv)->fullpath.size() > THIS_EOS5GRIDPATH.size())) {
2049
2050 string var_grid_name = Obtain_Var_EOS5Type_GroupName(*irv, GRID);
2051 if (var_grid_name == (*irg)->name) {
2052 if (("Longitude" == (*irv)->name) || ("Latitude" == (*irv)->name)) {
2053 catch_latlon++;
2054 // Remove this var from the var vector since it becomes a cv.
2055 delete (*irv);
2056 irv = this->vars.erase(irv);
2057 }
2058 else {
2059 ++irv;
2060 }
2061 }
2062 else {
2063 ++irv;
2064 }
2065 }
2066 else {
2067 ++irv;
2068 }
2069 } // "for (vector<Var *>::iterator irv = this->vars.begin() ..."
2070 if (2 == catch_latlon) {
2071 (*irg)->has_nolatlon = true;
2072 (*irg)->has_2dlatlon = false;
2073 }
2074
2075 } // "if ((true == this->isaura) ..."
2076 else { // remove this grid from the eos5cfgrids list.
2077 delete (*irg);
2078 irg = this->eos5cfgrids.erase(irg);
2079 irg_erase = true;
2080 }
2081 } // "if (true == (*irg) ..."
2082
2083 if (false == irg_erase) {
2084 ++irg;
2085 }
2086
2087 } // "for (vector <EOS5CFGrid *>::iterator irg = this->eos5cfgrids.begin() ..."
2088
2089 // Also remove >2d latlon grids.
2090 for (vector<EOS5CFGrid *>::iterator irg = this->eos5cfgrids.begin(); irg != this->eos5cfgrids.end();) {
2091
2092 if (true == (*irg)->has_g2dlatlon) {
2093 delete (*irg);
2094 irg = this->eos5cfgrids.erase(irg);
2095 }
2096 else {
2097 ++irg;
2098 }
2099 } // "for (vector <EOS5CFGrid *>::iterator irg = this->eos5cfgrids.begin() ..."
2100}
2101
2102// Handle single nonaugmented grid coordinate variables.
2103void EOS5File::Handle_Single_Nonaugment_Grid_CVar(EOS5CFGrid* cfgrid)
2104{
2105
2106 BESDEBUG("h5", "Coming to Handle_Single_Nonaugment_Grid_CVar()"<<endl);
2107 set<string> tempvardimnamelist;
2108 tempvardimnamelist = cfgrid->vardimnames;
2109
2110 // Handle Latitude and longitude
2111 bool use_own_latlon = false;
2112 if (true == cfgrid->has_1dlatlon)
2113 use_own_latlon = Handle_Single_Nonaugment_Grid_CVar_OwnLatLon(cfgrid, tempvardimnamelist);
2114#if 0
2115 if(use_own_latlon) "h5","using 1D latlon"<<endl;
2116 else "h5","use_own_latlon is false "<<endl;
2117#endif
2118
2119 if (false == use_own_latlon) {
2120 bool use_eos5_latlon = false;
2121 use_eos5_latlon = Handle_Single_Nonaugment_Grid_CVar_EOS5LatLon(cfgrid, tempvardimnamelist);
2122
2123 // If we cannot obtain lat/lon from the HDF-EOS5 library, no need to create other CVs. Simply return.
2124 if (false == use_eos5_latlon) return;
2125 }
2126
2127 // Else handling non-latlon grids
2128 Handle_NonLatLon_Grid_CVar(cfgrid, tempvardimnamelist);
2129
2130}
2131
2132// Handle single nonaugmented grid coordinate variables with its own lat/lon
2133bool EOS5File::Handle_Single_Nonaugment_Grid_CVar_OwnLatLon(EOS5CFGrid *cfgrid, set<string>& tempvardimnamelist)
2134
2135{
2136
2137 BESDEBUG("h5", "Coming to Handle_Single_Nonaugment_Grid_CVar_OwnLatLon()"<<endl);
2138 set<string>::iterator its;
2139 string EOS5GRIDPATH = "/HDFEOS/GRIDS/";
2140 string fslash_str = "/";
2141 string THIS_EOS5GRIDPATH = EOS5GRIDPATH + cfgrid->name + fslash_str;
2142
2143 // Handle latitude and longitude
2144 bool find_latydim = false;
2145 bool find_lonxdim = false;
2146
2147 for (vector<Var *>::iterator irv = this->vars.begin(); irv != this->vars.end(); ++irv) {
2148 if (GRID == Get_Var_EOS5_Type(*irv) && ((*irv)->fullpath.size() > THIS_EOS5GRIDPATH.size())) {
2149
2150 string var_grid_name = Obtain_Var_EOS5Type_GroupName(*irv, GRID);
2151 if ((var_grid_name == cfgrid->name) && ((*irv)->name == "Latitude")) {
2152
2153 string tempdimname = (((*irv)->dims)[0])->name;
2154
2155 if ("YDim" == HDF5CFUtil::obtain_string_after_lastslash(tempdimname)) {
2156 //Find it, create a coordinate variable.
2157 EOS5CVar *EOS5cvar = new EOS5CVar(*irv);
2158
2159 // Still keep the original dimension name to avoid the nameclashing when
2160 // one grid and one swath and one za occur in the same file
2161 EOS5cvar->cfdimname = tempdimname;
2162 EOS5cvar->cvartype = CV_EXIST;
2163 EOS5cvar->eos_type = GRID;
2164
2165 // Save this cv to the cv vector
2166 this->cvars.push_back(EOS5cvar);
2167
2168 // Remove this var from the var vector since it becomes a cv.
2169 delete (*irv);
2170 this->vars.erase(irv);
2171
2172 // No need to remove back the iterator since it will go out of the loop.
2173 find_latydim = true;
2174 break;
2175 } // <if ("YDim" == HDF5CFUtil::obtain_string_after_lastslash(tempdimname))>
2176 } // <if ((var_grid_name == cfgrid->name) && ((*irv)->name == "Latitude"))>
2177 } // <if (GRID == Get_Var_EOS5_Type(*irv) ...>
2178 } // <for (vector<Var *>::iterator irv = this->vars.begin() ...>
2179
2180 for (vector<Var *>::iterator irv = this->vars.begin(); irv != this->vars.end(); ++irv) {
2181
2182 if (GRID == Get_Var_EOS5_Type(*irv) && ((*irv)->fullpath.size() > THIS_EOS5GRIDPATH.size())) {
2183
2184 string var_grid_name = Obtain_Var_EOS5Type_GroupName(*irv, GRID);
2185
2186 if ((var_grid_name == cfgrid->name) && ((*irv)->name == "Longitude")) {
2187
2188 string tempdimname = (((*irv)->dims)[0])->name;
2189
2190 if ("XDim" == HDF5CFUtil::obtain_string_after_lastslash(tempdimname)) {
2191 //Find it, create a coordinate variable.
2192 EOS5CVar *EOS5cvar = new EOS5CVar(*irv);
2193
2194 // Still keep the original dimension name to avoid the nameclashing when
2195 // one grid and one swath and one za occur in the same file
2196 EOS5cvar->cfdimname = tempdimname;
2197 EOS5cvar->cvartype = CV_EXIST;
2198 EOS5cvar->eos_type = GRID;
2199
2200 // Save this cv to the cv vector
2201 this->cvars.push_back(EOS5cvar);
2202
2203 // Remove this var from the var vector since it becomes a cv.
2204 delete (*irv);
2205 this->vars.erase(irv);
2206 find_lonxdim = true;
2207 break;
2208 } // <if ("XDim" == HDF5CFUtil::obtain_string_after_lastslash(tempdimname))>
2209 } // "if ((var_grid_name == cfgrid->name) && ((*irv)->name == "Longitude"))"
2210 } // <if (GRID == Get_Var_EOS5_Type(*irv) ...>
2211 } // for (vector<Var *>::iterator irv = this->vars.begin() ...
2212
2213 for (vector<EOS5CVar *>::iterator irv = this->cvars.begin(); irv != this->cvars.end(); ++irv) {
2214 its = tempvardimnamelist.find((*irv)->cfdimname);
2215 if (its != tempvardimnamelist.end()) tempvardimnamelist.erase(its);
2216
2217 }
2218
2219#if 0
2220 for (its = tempvardimnamelist.begin(); its != tempvardimnamelist.end(); ++its)
2221 "h5","tempvardim "<<*its <<endl;
2222#endif
2223
2224 return (find_latydim == true && find_lonxdim == true);
2225}
2226
2227// Handle single non-augmented grid latitude/longitude coordinate variables.
2228bool EOS5File::Handle_Single_Nonaugment_Grid_CVar_EOS5LatLon(EOS5CFGrid *cfgrid, set<string>& tempvardimnamelist)
2229
2230{
2231
2232 BESDEBUG("h5", "Coming to Handle_Single_Nonaugment_Grid_CVar_EOS5LatLon()"<<endl);
2233
2234 // Handle latitude and longitude
2235 bool find_ydim = false;
2236 bool find_xdim = false;
2237 set<string>::iterator its;
2238
2239#if 0
2240 for (its = tempvardimnamelist.begin(); its != tempvardimnamelist.end(); ++its)
2241 cerr<<"dim names "<<(*its) <<endl;
2242#endif
2243
2244 string ydim_full_path;
2245 string xdim_full_path;
2246
2247 if (cfgrid->eos5_projcode != HE5_GCTP_GEO) {
2248
2249 for (its = tempvardimnamelist.begin(); its != tempvardimnamelist.end(); ++its) {
2250 if ("YDim" == HDF5CFUtil::obtain_string_after_lastslash(*its))
2251 ydim_full_path = *its;
2252 else if ("XDim" == HDF5CFUtil::obtain_string_after_lastslash(*its)) xdim_full_path = *its;
2253 }
2254 }
2255
2256
2257 for (its = tempvardimnamelist.begin(); its != tempvardimnamelist.end();) {
2258 if ("YDim" == HDF5CFUtil::obtain_string_after_lastslash(*its)) {
2259
2260 // Create EOS5 Latitude CV
2261 EOS5CVar *EOS5cvar = new EOS5CVar();
2262 EOS5cvar->name = "lat";
2263 Create_Added_Var_NewName_FullPath(GRID, cfgrid->name, EOS5cvar->name, EOS5cvar->newname,
2264 EOS5cvar->fullpath);
2265
2266 if (cfgrid->eos5_projcode != HE5_GCTP_GEO) {
2267 EOS5cvar->rank = 2;
2268 EOS5cvar->dtype = H5FLOAT64;
2269 }
2270 else {
2271 EOS5cvar->rank = 1;
2272 EOS5cvar->dtype = H5FLOAT32;
2273 }
2274
2275 Dimension* eos5cvar_dim = new Dimension((hsize_t) cfgrid->ydimsize);
2276 eos5cvar_dim->name = *its;
2277 eos5cvar_dim->newname = (this->eos5cfgrids.size() == 1) ? "YDim" : *its;
2278 EOS5cvar->dims.push_back(eos5cvar_dim);
2279 EOS5cvar->cfdimname = eos5cvar_dim->name;
2280
2281 if (EOS5cvar->rank == 2) {
2282
2283 eos5cvar_dim = new Dimension((hsize_t) cfgrid->xdimsize);
2284 eos5cvar_dim->name = xdim_full_path;
2285 eos5cvar_dim->newname = (this->eos5cfgrids.size() == 1) ? "XDim" : xdim_full_path;
2286 EOS5cvar->dims.push_back(eos5cvar_dim);
2287
2288 }
2289 EOS5cvar->cvartype = CV_LAT_MISS;
2290 EOS5cvar->eos_type = GRID;
2291 EOS5cvar->xdimsize = cfgrid->xdimsize;
2292 EOS5cvar->ydimsize = cfgrid->ydimsize;
2293
2294 //Special parameters for EOS5 Grid
2295 EOS5cvar->point_lower = cfgrid->point_lower;
2296 EOS5cvar->point_upper = cfgrid->point_upper;
2297 EOS5cvar->point_left = cfgrid->point_left;
2298 EOS5cvar->point_right = cfgrid->point_right;
2299 EOS5cvar->eos5_pixelreg = cfgrid->eos5_pixelreg;
2300 EOS5cvar->eos5_origin = cfgrid->eos5_origin;
2301 EOS5cvar->eos5_projcode = cfgrid->eos5_projcode;
2302
2303 for (unsigned int k = 0; k < 13; k++)
2304 EOS5cvar->param[k] = cfgrid->param[k];
2305
2306 EOS5cvar->zone = cfgrid->zone;
2307 EOS5cvar->sphere = cfgrid->sphere;
2308
2309 // Save this cv to the cv vector
2310 this->cvars.push_back(EOS5cvar);
2311 // erase the dimension name from the dimension name set
2312
2313 // This is the right way to make its platform-independent.
2314 tempvardimnamelist.erase(its++);
2315 find_ydim = true;
2316
2317 } // <if ("YDim" == HDF5CFUtil::obtain_string_after_lastslash(*its))>
2318 else if ("XDim" == HDF5CFUtil::obtain_string_after_lastslash(*its)) {
2319
2320 // Create EOS5 Latitude CV
2321 EOS5CVar *EOS5cvar = new EOS5CVar();
2322 EOS5cvar->name = "lon";
2323 Create_Added_Var_NewName_FullPath(GRID, cfgrid->name, EOS5cvar->name, EOS5cvar->newname,
2324 EOS5cvar->fullpath);
2325#if 0
2326 //EOS5cvar->newname = EOS5cvar->name;
2327 //EOS5cvar->fullpath = EOS5cvar->name;
2328#endif
2329 if (cfgrid->eos5_projcode != HE5_GCTP_GEO) {
2330 EOS5cvar->rank = 2;
2331 EOS5cvar->dtype = H5FLOAT64;
2332 }
2333 else {
2334 EOS5cvar->rank = 1;
2335 EOS5cvar->dtype = H5FLOAT32;
2336 }
2337
2338 Dimension* eos5cvar_dim = NULL;
2339 if (EOS5cvar->rank == 2) {
2340 eos5cvar_dim = new Dimension((hsize_t) cfgrid->ydimsize);
2341#if 0
2342 //eos5cvar_dim->name = EOS5cvar->name;
2343#endif
2344 eos5cvar_dim->name = ydim_full_path;
2345 eos5cvar_dim->newname = (this->eos5cfgrids.size() == 1) ? "YDim" : ydim_full_path;
2346 EOS5cvar->dims.push_back(eos5cvar_dim);
2347 }
2348
2349 eos5cvar_dim = new Dimension((hsize_t) cfgrid->xdimsize);
2350#if 0
2351 //eos5cvar_dim->name = EOS5cvar->name;
2352#endif
2353 eos5cvar_dim->name = *its;
2354 eos5cvar_dim->newname = (this->eos5cfgrids.size() == 1) ? "XDim" : *its;
2355 EOS5cvar->dims.push_back(eos5cvar_dim);
2356 EOS5cvar->cfdimname = eos5cvar_dim->name;
2357
2358 EOS5cvar->cvartype = CV_LON_MISS;
2359 EOS5cvar->eos_type = GRID;
2360 EOS5cvar->xdimsize = cfgrid->xdimsize;
2361 EOS5cvar->ydimsize = cfgrid->ydimsize;
2362
2363 //Special parameters for EOS5 Grid
2364 EOS5cvar->point_lower = cfgrid->point_lower;
2365 EOS5cvar->point_upper = cfgrid->point_upper;
2366 EOS5cvar->point_left = cfgrid->point_left;
2367 EOS5cvar->point_right = cfgrid->point_right;
2368 EOS5cvar->eos5_pixelreg = cfgrid->eos5_pixelreg;
2369 EOS5cvar->eos5_origin = cfgrid->eos5_origin;
2370 EOS5cvar->eos5_projcode = cfgrid->eos5_projcode;
2371 for (unsigned int k = 0; k < 13; k++)
2372 EOS5cvar->param[k] = cfgrid->param[k];
2373 EOS5cvar->zone = cfgrid->zone;
2374 EOS5cvar->sphere = cfgrid->sphere;
2375
2376 // Save this cv to the cv vector
2377 this->cvars.push_back(EOS5cvar);
2378
2379 // erase the dimension name from the dimension name set,platform independent way.
2380 tempvardimnamelist.erase(its++);
2381 find_xdim = true;
2382
2383 } // "else if ("XDim" == HDF5CFUtil::obtain_string_after_lastslash(*its))"
2384 else
2385 ++its;
2386 if (true == find_xdim && true == find_ydim) break;
2387 } // <for (its = tempvardimnamelist.begin(); its != tempvardimnamelist.end(); ++its)>
2388
2389 return (true == find_xdim && true == find_ydim);
2390}
2391
2392// Handle non-latitude/longitude grid coordinate variables.
2393void EOS5File::Handle_NonLatLon_Grid_CVar(EOS5CFGrid *cfgrid, set<string>& tempvardimnamelist)
2394{
2395
2396 // First check if we have existing coordinate variable
2397 set<string>::iterator its;
2398 int num_dimnames = tempvardimnamelist.size();
2399 bool has_dimnames = true;
2400
2401 for (its = tempvardimnamelist.begin(); its != tempvardimnamelist.end(); ++its) {
2402 if (cfgrid->dnames_to_1dvnames.find(*its) != cfgrid->dnames_to_1dvnames.end()) {
2403 for (vector<Var *>::iterator irv = this->vars.begin(); has_dimnames && (irv != this->vars.end());) {
2404 // We need to check if this var is a grid and use "newname"
2405 // of var to check the dnames_to_1dvnames since it is
2406 // possible to have name clashings for the "name" of a var.
2407 if (GRID == Get_Var_EOS5_Type(*irv) && (*irv)->newname == (cfgrid->dnames_to_1dvnames)[*its]) {
2408
2409 //Find it, create a coordinate variable.
2410 EOS5CVar *EOS5cvar = new EOS5CVar(*irv);
2411
2412 // Still keep the original dimension name to avoid the nameclashing when
2413 // one grid and one swath and one za occur in the same file
2414 EOS5cvar->cfdimname = *its;
2415 EOS5cvar->cvartype = CV_EXIST;
2416 EOS5cvar->eos_type = GRID;
2417
2418 // Save this cv to the cv vector
2419 this->cvars.push_back(EOS5cvar);
2420
2421 // Remove this var from the var vector since it becomes a cv.
2422 delete (*irv);
2423 irv = this->vars.erase(irv);
2424 num_dimnames--;
2425 if (0 == num_dimnames) has_dimnames = false;
2426 } // if (GRID == Get_Var_EOS5_Type(*irv) ...
2427 else {
2428 ++irv;
2429 }
2430 } // for (vector<Var *>::iterator irv = this->vars.begin(); ...
2431 } // if (cfgrid->dnames_to_1dvnames.find(*its) !=cfgrid->dnames_to_1dvnames.end())
2432 } // for (its = tempvardimnamelist.begin(); its != tempvardimnamelist.end(); ++its)
2433
2434 // Remove the dimension name that finds the cooresponding variables from the tempvardimlist.
2435 for (vector<EOS5CVar *>::iterator irv = this->cvars.begin(); irv != this->cvars.end(); ++irv) {
2436 its = tempvardimnamelist.find((*irv)->cfdimname);
2437 if (its != tempvardimnamelist.end()) tempvardimnamelist.erase(its);
2438 }
2439
2440 // Second: Some dimension names still need to find CVs, create the missing CVs
2441 for (its = tempvardimnamelist.begin(); its != tempvardimnamelist.end(); ++its) {
2442
2443 EOS5CVar *EOS5cvar = new EOS5CVar();
2444 Create_Missing_CV(cfgrid, EOS5cvar, *its, GRID, this->eos5cfgrids.size());
2445 this->cvars.push_back(EOS5cvar);
2446
2447 }
2448}
2449
2450// Handle none-augmented grid coordinate variables for mutliple grids.
2451void EOS5File::Handle_Multi_Nonaugment_Grid_CVar()
2452{
2453
2454 BESDEBUG("h5", "Coming to Handle_Multi_nonaugment_Grid_CVar()"<<endl);
2455
2456 // If the multiple grids don't share the same lat/lon according to the parameters
2457 // We then assume that each single grid has its own lat/lon, just loop through each grid.
2458 if (true == this->grids_multi_latloncvs) {
2459 for (vector<EOS5CFGrid *>::iterator irv = this->eos5cfgrids.begin(); irv != this->eos5cfgrids.end(); ++irv)
2460 Handle_Single_Nonaugment_Grid_CVar(*irv);
2461 }
2462
2463 // We would like to check if lat/lon pairs provide for all grids
2464 // If lat/lon pairs are provided for all grids, then we ASSUME that
2465 // all grids share the same lat/lon values. This is what happened with
2466 // Aura grids. We only apply this to Aura files.They provide a lat/lon pair for each grid. We will observe
2467 // if this assumption is true for the future products.
2468 // If lat/lon pairs are not provided for all grids, we assume that each grid
2469 // may still have its unique lat/lon.
2470 else {
2471 int num_1dlatlon_pairs = 0;
2472 for (vector<EOS5CFGrid *>::iterator irv = this->eos5cfgrids.begin(); irv != this->eos5cfgrids.end(); ++irv)
2473 if (true == (*irv)->has_1dlatlon) num_1dlatlon_pairs++;
2474
2475 bool use_eos5_latlon = false;
2476 if ((0 == num_1dlatlon_pairs)
2477 || ((num_1dlatlon_pairs == (int) (this->eos5cfgrids.size())) && (true == this->isaura))) {
2478 set<string> tempvardimnamelist = ((this->eos5cfgrids)[0])->vardimnames;
2479 if (0 == num_1dlatlon_pairs) {
2480 use_eos5_latlon = Handle_Single_Nonaugment_Grid_CVar_EOS5LatLon((this->eos5cfgrids)[0],
2481 tempvardimnamelist);
2482
2483 if (false == use_eos5_latlon) return;
2484 }
2485
2486 else {
2487 // One lat/lon for all grids
2488 bool use_own_latlon = false;
2489 use_own_latlon = Handle_Single_Nonaugment_Grid_CVar_OwnLatLon((this->eos5cfgrids)[0],
2490 tempvardimnamelist);
2491 if (false == use_own_latlon) {
2492 use_eos5_latlon = Handle_Single_Nonaugment_Grid_CVar_EOS5LatLon((this->eos5cfgrids)[0],
2493 tempvardimnamelist);
2494 if (false == use_eos5_latlon) return;
2495 }
2496 }
2497
2498 // We need to handle the first grid differently since it will include "XDim" and "YDim".
2499 Handle_NonLatLon_Grid_CVar((this->eos5cfgrids)[0], tempvardimnamelist);
2500
2501 // Updating the dimension name sets for other grids
2502 for (unsigned j = 1; j < this->eos5cfgrids.size(); j++)
2503 (this->eos5cfgrids)[j]->Update_Dimnamelist();
2504
2505 // Adjusting the XDim and YDim dimension names for all vars
2506 Adjust_EOS5GridDimNames((this->eos5cfgrids)[0]);
2507
2508 // Now we can safely handle the rest grids
2509 for (unsigned j = 1; j < this->eos5cfgrids.size(); j++) {
2510 tempvardimnamelist = (this->eos5cfgrids)[j]->vardimnames;
2511 Handle_NonLatLon_Grid_CVar((this->eos5cfgrids)[j], tempvardimnamelist);
2512 tempvardimnamelist.clear();
2513 }
2514 } // if (( 0 == num_1dlatlon_pairs) || .....
2515 // No unique lat/lon, just loop through.
2516 else {
2517
2518 this->grids_multi_latloncvs = true;
2519 for (vector<EOS5CFGrid *>::iterator irv = this->eos5cfgrids.begin(); irv != this->eos5cfgrids.end(); ++irv)
2520 Handle_Single_Nonaugment_Grid_CVar(*irv);
2521 }
2522 }
2523}
2524
2525// Adjust the HDF-EOS5 grid dimension names for XDim and YDim, we need to remember the grid path
2526// Note this function is used under the assumption that only one lat/lon pair is used for all grids.
2527// This is the case for Aura.
2528void EOS5File::Adjust_EOS5GridDimNames(EOS5CFGrid *cfgrid)
2529{
2530
2531 BESDEBUG("h5", "Coming to Adjust_EOS5GridDimNames()"<<endl);
2532 string xdimname;
2533 string ydimname;
2534 bool find_xdim = false;
2535 bool find_ydim = false;
2536
2537 for (set<string>::iterator it = cfgrid->vardimnames.begin(); it != cfgrid->vardimnames.end(); ++it) {
2538 string xydimname_candidate = HDF5CFUtil::obtain_string_after_lastslash(*it);
2539 if ("XDim" == xydimname_candidate) {
2540 find_xdim = true;
2541 xdimname = *it;
2542 }
2543 else if ("YDim" == xydimname_candidate) {
2544 find_ydim = true;
2545 ydimname = *it;
2546 }
2547 if (find_xdim && find_ydim) break;
2548 } // for (set<string>::iterator it = cfgrid->vardimnames.begin() ...
2549
2550 if (false == find_xdim || false == find_ydim)
2551 throw2("Cannot find Dimension name that includes XDim or YDim in the grid ", cfgrid->name);
2552
2553 for (vector<Var *>::iterator irv = this->vars.begin(); irv != this->vars.end(); ++irv) {
2554 if (GRID == Get_Var_EOS5_Type(*irv)) {
2555 for (vector<Dimension *>::iterator id = (*irv)->dims.begin(); id != (*irv)->dims.end(); ++id) {
2556 string xydimname_candidate = HDF5CFUtil::obtain_string_after_lastslash((*id)->name);
2557 if ("XDim" == xydimname_candidate)
2558 (*id)->name = xdimname;
2559 else if ("YDim" == xydimname_candidate) (*id)->name = ydimname;
2560 }
2561 }
2562 }
2563}
2564
2565// Handle Swath Coordinate variables.
2566void EOS5File::Handle_Swath_CVar(bool isaugmented)
2567{
2568
2569 BESDEBUG("h5", "Coming to Handle_Swath_CVar()"<<endl);
2570 // In this version, we will not use the augmented option for coordinate variables of swath
2571 // since MLS products don't use the recent version of the augmentation tool to allocate their
2572 // coordinate variables.
2573 for (vector<EOS5CFSwath *>::iterator irs = this->eos5cfswaths.begin(); irs != this->eos5cfswaths.end();) {
2574 if ((*irs)->has_1dlatlon) {
2575 Handle_Single_1DLatLon_Swath_CVar(*irs, isaugmented);
2576 ++irs;
2577 }
2578 else if ((*irs)->has_2dlatlon) {
2579 Handle_Single_2DLatLon_Swath_CVar(*irs, isaugmented);
2580 ++irs;
2581 }
2582 // If number of dimension latitude/longitude is >2 or no lat/lon,
2583 // no cooridnate variables will be generated.
2584 // We will simply remove this swath from the vector eos5cfswaths.
2585 // In the future, we may consider supporting non "Latitude", "Longitude" naming swaths.
2586 // KY 2011-1-20
2587 else {
2588 delete (*irs);
2589 irs = this->eos5cfswaths.erase(irs);
2590 }
2591 } // for (vector <EOS5CFSwath *>::iterator irs = this->eos5cfswaths.begin();
2592}
2593
2594// Handle single 1D LatLon Swath Coordinate variables.
2595void EOS5File::Handle_Single_1DLatLon_Swath_CVar(EOS5CFSwath *cfswath, bool is_augmented)
2596{
2597
2598 BESDEBUG("h5", "Coming to Handle_Single_1DLatLon_Swath_CVar"<<endl);
2599 // For 1DLatLon, we will use latitude as the coordinate variable
2600 set<string>::iterator its;
2601 set<string> tempvardimnamelist = cfswath->vardimnames;
2602 string EOS5SWATHPATH = "/HDFEOS/SWATHS/";
2603 string fslash_str = "/";
2604 string THIS_EOS5SWATHPATH = EOS5SWATHPATH + cfswath->name + fslash_str;
2605#if 0
2606 for (its = tempvardimnamelist.begin(); its != tempvardimnamelist.end(); ++its)
2607 cerr<<"Dimension name befor latitude " << *its << endl;
2608#endif
2609
2610 // Find latitude and assign to the coordinate variable
2611 // (*irv)->fullpath.size() > THIS_EOS5SWATHPATH.size() is necessary to handle the augmented variables.
2612 for (vector<Var *>::iterator irv = this->vars.begin(); irv != this->vars.end(); ++irv) {
2613 if (SWATH == Get_Var_EOS5_Type(*irv) && ((*irv)->fullpath.size() > THIS_EOS5SWATHPATH.size())) {
2614
2615 string var_swath_name = Obtain_Var_EOS5Type_GroupName(*irv, SWATH);
2616 if ((var_swath_name == cfswath->name) && ((*irv)->name == "Latitude")) {
2617
2618 //Find it, create a coordinate variable.
2619 EOS5CVar *EOS5cvar = new EOS5CVar(*irv);
2620
2621 // Still keep the original dimension name to avoid the nameclashing when
2622 // one grid and one swath and one za occur in the same file
2623 EOS5cvar->cfdimname = ((*irv)->dims)[0]->name;
2624 EOS5cvar->cvartype = CV_EXIST;
2625 EOS5cvar->eos_type = SWATH;
2626
2627 // Save this cv to the cv vector
2628 this->cvars.push_back(EOS5cvar);
2629
2630 // Remove this var from the var vector since it becomes a cv.
2631 delete (*irv);
2632 this->vars.erase(irv);
2633 //irv--;
2634 // find_lat = true;
2635 break;
2636 } // if ((var_swath_name == cfswath->name) && ...
2637 } // if (SWATH == Get_Var_EOS5_Type(*irv) &&
2638 } // for (vector<Var *>::iterator irv = this->vars.begin() ...
2639
2640 // Finish this variable, remove it from the list.
2641
2642 bool find_lat_dim = false;
2643 for (its = tempvardimnamelist.begin(); its != tempvardimnamelist.end(); ++its) {
2644
2645 for (vector<EOS5CVar *>::iterator irv = this->cvars.begin(); irv != this->cvars.end(); ++irv) {
2646 if (((*irv)->name == "Latitude") && (*irv)->cfdimname == (*its)) {
2647 tempvardimnamelist.erase(its);
2648 find_lat_dim = true;
2649 break;
2650 }
2651 }
2652
2653 if (true == find_lat_dim) break;
2654 }
2655
2656#if 0
2657 for (its = tempvardimnamelist.begin(); its != tempvardimnamelist.end(); ++its)
2658 cerr<<"Dimension name afte latitude " << *its << endl;
2659#endif
2660
2661 Handle_NonLatLon_Swath_CVar(cfswath, tempvardimnamelist);
2662
2663 // Remove the added variables during the augmentation process
2664 if (true == is_augmented) {
2665 for (vector<Var *>::iterator irv = this->vars.begin(); irv != this->vars.end();) {
2666
2667 if (SWATH == Get_Var_EOS5_Type(*irv)) {
2668#if 0
2669 string my_swath_short_path = (*irv)->fullpath.substr(EOS5SWATHPATH.size());
2670 size_t first_fslash_pos = my_swath_short_path.find_first_of("/");
2671 string my_swath_name = my_swath_short_path.substr(0,first_fslash_pos);
2672#endif
2673 // Need to find the swath for this variable
2674 string my_swath_name = Obtain_Var_EOS5Type_GroupName(*irv, SWATH);
2675
2676 if (my_swath_name == cfswath->name) {
2677 string var_path_after_swathname = (*irv)->fullpath.substr(THIS_EOS5SWATHPATH.size());
2678 if (var_path_after_swathname == (*irv)->name) {
2679 delete (*irv);
2680 irv = this->vars.erase(irv);
2681 }
2682 else {
2683 ++irv;
2684 }
2685 }
2686 else {
2687 ++irv;
2688 }
2689 }
2690 else {
2691 ++irv;
2692 }
2693 } // for (vector<Var*>::iterator irv =
2694 } // if (true == is_augmented)
2695}
2696
2697// Handle Single 2D lat/lon Coordinate variables for Swath
2698void EOS5File::Handle_Single_2DLatLon_Swath_CVar(EOS5CFSwath *cfswath, bool is_augmented)
2699{
2700
2701 BESDEBUG("h5", "Coming to Handle_Single_2DLatLon_Swath_CVar()"<<endl);
2702 // For 2DLatLon, we will use both latitude and longitude as the coordinate variables
2703 set<string>::iterator its;
2704 set<string> tempvardimnamelist = cfswath->vardimnames;
2705 string EOS5SWATHPATH = "/HDFEOS/SWATHS/";
2706 string fslash_str = "/";
2707 string THIS_EOS5SWATHPATH = EOS5SWATHPATH + cfswath->name + fslash_str;
2708 bool find_lat = false;
2709 bool find_lon = false;
2710
2711#if 0
2712 for (its = tempvardimnamelist.begin(); its != tempvardimnamelist.end(); ++its)
2713 cerr<<"Dimension name befor latitude " << *its << endl;
2714#endif
2715
2716 // Find latitude and assign to the coordinate variable
2717 for (vector<Var *>::iterator irv = this->vars.begin(); irv != this->vars.end();) {
2718 if (SWATH == Get_Var_EOS5_Type(*irv) && ((*irv)->fullpath.size() > THIS_EOS5SWATHPATH.size())) {
2719 string var_swath_name = Obtain_Var_EOS5Type_GroupName(*irv, SWATH);
2720 if ((var_swath_name == cfswath->name) && ((*irv)->name == "Latitude")) {
2721
2722 //Find it, create a coordinate variable.
2723 EOS5CVar *EOS5cvar = new EOS5CVar(*irv);
2724
2725 // Still keep the original dimension name to avoid the nameclashing when
2726 // one grid and one swath and one za occur in the same file
2727 EOS5cvar->cfdimname = ((*irv)->dims)[0]->name;
2728 EOS5cvar->cvartype = CV_EXIST;
2729 EOS5cvar->eos_type = SWATH;
2730 EOS5cvar->is_2dlatlon = true;
2731
2732 // Save this cv to the cv vector
2733 this->cvars.push_back(EOS5cvar);
2734
2735 // Remove this var from the var vector since it becomes a cv.
2736 delete (*irv);
2737 irv = this->vars.erase(irv);
2738 find_lat = true;
2739 } // if ( (var_swath_name == cfswath->name) && ...
2740 else if ((var_swath_name == cfswath->name) && ((*irv)->name == "Longitude")) {
2741
2742 //Find it, create a coordinate variable.
2743 EOS5CVar *EOS5cvar = new EOS5CVar(*irv);
2744
2745 // Still keep the original dimension name to avoid the nameclashing when
2746 // one grid and one swath and one za occur in the same file
2747 EOS5cvar->cfdimname = ((*irv)->dims)[1]->name;
2748 EOS5cvar->cvartype = CV_EXIST;
2749 EOS5cvar->eos_type = SWATH;
2750 EOS5cvar->is_2dlatlon = true;
2751
2752 // Save this cv to the cv vector
2753 this->cvars.push_back(EOS5cvar);
2754
2755 // Remove this var from the var vector since it becomes a cv.
2756 delete (*irv);
2757 irv = this->vars.erase(irv);
2758 find_lon = true;
2759
2760 } // else if ( (var_swath_name == cfswath->name) && ...
2761 else {
2762 ++irv;
2763 }
2764 } // if (SWATH == Get_Var_EOS5_Type(*irv) && ...
2765 else {
2766 ++irv;
2767 }
2768
2769 if (true == find_lat && true == find_lon) break;
2770 } // for (vector<Var *>::iterator irv = this->vars.begin();
2771
2772 // Remove the dim. of latitude
2773 find_lat = false;
2774 for (its = tempvardimnamelist.begin(); its != tempvardimnamelist.end(); ++its) {
2775 for (vector<EOS5CVar *>::iterator irv = this->cvars.begin(); irv != this->cvars.end(); ++irv) {
2776 if (((*irv)->name == "Latitude") && (*irv)->cfdimname == (*its)) {
2777 tempvardimnamelist.erase(its);
2778 find_lat = true;
2779 break;
2780 }
2781 }
2782
2783 if (true == find_lat) break;
2784 }
2785
2786 // Remove the dim. of longitude
2787 find_lon = false;
2788 for (its = tempvardimnamelist.begin(); its != tempvardimnamelist.end(); ++its) {
2789
2790 for (vector<EOS5CVar *>::iterator irv = this->cvars.begin(); irv != this->cvars.end(); ++irv) {
2791
2792 if (((*irv)->name == "Longitude") && (*irv)->cfdimname == (*its)) {
2793 tempvardimnamelist.erase(its);
2794 find_lon = true;
2795 break;
2796 }
2797 }
2798
2799 if (true == find_lon) break;
2800 }
2801
2802#if 0
2803 for (its = tempvardimnamelist.begin(); its != tempvardimnamelist.end(); ++its)
2804 cerr<<"Dimension name afte latitude " << *its << endl;
2805#endif
2806
2807 Handle_NonLatLon_Swath_CVar(cfswath, tempvardimnamelist);
2808
2809 // Remove the added variables during the augmentation process
2810 // For Swath, we don't want to keep the augmented files. This is because
2811 // some aura files assign the dimensional scale as zero.
2812 // We will actively check the new NASA HDF-EOS5 products and will
2813 // revise the following section as needed. KY 2012-03-09
2814 if (true == is_augmented) {
2815 for (vector<Var *>::iterator irv = this->vars.begin(); irv != this->vars.end();) {
2816
2817 if (SWATH == Get_Var_EOS5_Type(*irv)) {
2818
2819 string my_swath_name = Obtain_Var_EOS5Type_GroupName(*irv, SWATH);
2820 if (my_swath_name == cfswath->name) {
2821 string var_path_after_swathname = (*irv)->fullpath.substr(THIS_EOS5SWATHPATH.size());
2822 if (var_path_after_swathname == (*irv)->name) {
2823 delete (*irv);
2824 irv = this->vars.erase(irv);
2825 }
2826 else {
2827 ++irv;
2828 }
2829 }
2830 else {
2831 ++irv;
2832 }
2833 }
2834 else {
2835 ++irv;
2836 }
2837 } // for (vector<Var *>::iterator irv
2838 }
2839}
2840
2841// Handle non-lat/lon Swath coordinate variables.
2842void EOS5File::Handle_NonLatLon_Swath_CVar(EOS5CFSwath *cfswath, set<string>& tempvardimnamelist)
2843{
2844
2845 BESDEBUG("h5", "Coming to Handle_NonLatLon_Swath_CVar()"<<endl);
2846 // First check if we have existing coordinate variable
2847 set<string>::iterator its;
2848 int num_dimnames = tempvardimnamelist.size();
2849 bool has_dimnames = true;
2850 for (its = tempvardimnamelist.begin(); its != tempvardimnamelist.end(); ++its) {
2851 if (cfswath->dnames_to_geo1dvnames.find(*its) != cfswath->dnames_to_geo1dvnames.end()) {
2852 for (vector<Var *>::iterator irv = this->vars.begin(); has_dimnames && (irv != this->vars.end());) {
2853
2854 // We need to check if this var is a swath and use "newname"
2855 // of var to check the dnames_to_1dvnames since it is
2856 // possible to have name clashings for the "name" of a var.
2857 if (SWATH == Get_Var_EOS5_Type(*irv) && (*irv)->newname == (cfswath->dnames_to_geo1dvnames)[*its]) {
2858
2859 //Find it, create a coordinate variable.
2860 EOS5CVar *EOS5cvar = new EOS5CVar(*irv);
2861
2862 // Still keep the original dimension name to avoid the nameclashing when
2863 // one grid and one swath and one za occur in the same file
2864 EOS5cvar->cfdimname = *its;
2865 EOS5cvar->cvartype = CV_EXIST;
2866 EOS5cvar->eos_type = SWATH;
2867
2868 // Save this cv to the cv vector
2869 this->cvars.push_back(EOS5cvar);
2870
2871 // Remove this var from the var vector since it becomes a cv.
2872 delete (*irv);
2873 irv = this->vars.erase(irv);
2874 //irv--;
2875 num_dimnames--;
2876 if (0 == num_dimnames) has_dimnames = false;
2877 } // if (SWATH == Get_Var_EOS5_Type(*irv) && ...)
2878 else {
2879 ++irv;
2880 }
2881 } // for (vector<Var *>::iterator irv = this->vars.begin(); ...
2882 } // if (cfswath->dnames_to_geo1dvnames.find(*its) ....
2883 } // for (its = tempvardimnamelist.begin()...
2884
2885 // Remove the dimension name that finds the cooresponding variables from the tempvardimlist.
2886 for (vector<EOS5CVar *>::iterator irv = this->cvars.begin(); irv != this->cvars.end(); ++irv) {
2887 its = tempvardimnamelist.find((*irv)->cfdimname);
2888 if (its != tempvardimnamelist.end()) tempvardimnamelist.erase(its);
2889 }
2890
2891 // Check if some attributes have CV information for some special products
2892 // Currently TES needs to be handled carefully
2893 Handle_Special_NonLatLon_Swath_CVar(cfswath, tempvardimnamelist);
2894
2895 // Remove the dimension name that finds the cooresponding variables from the tempvardimlist.
2896 for (vector<EOS5CVar *>::iterator irv = this->cvars.begin(); irv != this->cvars.end(); ++irv) {
2897 its = tempvardimnamelist.find((*irv)->cfdimname);
2898 if (its != tempvardimnamelist.end()) tempvardimnamelist.erase(its);
2899 }
2900
2901 // Second: Some dimension names still need to find CVs, create the missing CVs
2902 for (its = tempvardimnamelist.begin(); its != tempvardimnamelist.end(); ++its) {
2903
2904 EOS5CVar *EOS5cvar = new EOS5CVar();
2905 Create_Missing_CV(cfswath, EOS5cvar, *its, SWATH, this->eos5cfswaths.size());
2906 this->cvars.push_back(EOS5cvar);
2907
2908 }
2909}
2910
2911// Handle special non-lat/lon coordinate variables for swath.
2912void EOS5File::Handle_Special_NonLatLon_Swath_CVar(EOS5CFSwath *cfswath, set<string>& tempvardimnamelist)
2913
2914{
2915
2916 BESDEBUG("h5", "Handle_Special_NonLatLon_Swath_CVar()"<<endl);
2917 // We have no choice but hard-code this one.
2918 // TES swath puts "Pressure" as the VerticalCoordinate but doesn't provide "Pressure" values.
2919 // Moreover, the number of pressure level(66) is one less than the total number of corresponding dimension size(67)
2920 // most probably due to the missing pressure level on the ground. To make the handler visualize some
2921 // TES variables and to follow the general physical sense. We have to add a pressure level by linear interpolation.
2922 // KY 2012-1-27
2923 if (true == this->isaura && TES == this->aura_name) {
2924
2925 string eos5_swath_group_name = "/HDFEOS/SWATHS/" + cfswath->name;
2926 string eos5_vc_attr_name = "VerticalCoordinate";
2927 string eos5_pre_attr_name = "Pressure";
2928 bool has_vc_attr = false;
2929 Group *vc_group = NULL;
2930
2931 // 1. Check if having the "VerticalCoordinate" attribute in this swath and the attribute is "Pressure".
2932 for (vector<Group *>::iterator irg = this->groups.begin(); irg != this->groups.end(); ++irg) {
2933 if (eos5_swath_group_name == (*irg)->path) {
2934 for (vector<Attribute *>::iterator ira = (*irg)->attrs.begin(); ira != (*irg)->attrs.end(); ++ira) {
2935 if (eos5_vc_attr_name == (*ira)->name) {
2936 Retrieve_H5_Attr_Value(*ira, (*irg)->path);
2937 string attr_value((*ira)->value.begin(), (*ira)->value.end());
2938 if (eos5_pre_attr_name == attr_value) {
2939 has_vc_attr = true;
2940 vc_group = *irg;
2941 break;
2942 }
2943 }
2944 } // for (vector<Attribute *>:: iterator ira =(*irg)->attrs.begin(); ...
2945 if (true == has_vc_attr) break;
2946 } // if (eos5_swath_group_name ==(*irg)->path)
2947 } // for (vector<Group *>::iterator irg = this->groups.begin(); ...
2948
2949 // 2. Check if having the "Pressure" attribute and if the attribute size is 1 less than
2950 // the dimension size of "nLevels". If yes,
2951 // add one pressure value by using the nearest neighbor value. This value should be the first value
2952 // of the "Pressure" attribute.
2953 // Another special part of the TES file is that dimension name nLevels is used twice in some variables
2954 // float foo[...][nLevels][nLevels]. To make the variable visualized by tools, the dimension name
2955 // needs to be changed and the coordinate variable needs to separately created. Note this is not
2956 // against CF conventions. However, the popular tools are not happy with the duplicate dimension names
2957 // in a variable.
2958 // Though may not cover 100% cases, searching the string after the last forward slash and see if
2959 // it contains nLevels should catch 99% memebers of the "nLevels" family. We will then create the
2960 // corresponding coordinate variables.
2961
2962 // 2.1. Check if we have the dimension name called "nLevels" for this swath
2963 if (true == has_vc_attr) {
2964 string dimname_candidate = "/SWATHS/" + cfswath->name + "/nLevels";
2965 set<string>::iterator it;
2966 for (it = tempvardimnamelist.begin(); it != tempvardimnamelist.end(); ++it) {
2967 if ((*it).find(dimname_candidate) != string::npos) {
2968 hsize_t dimsize_candidate = 0;
2969 if ((cfswath->dimnames_to_dimsizes).find(*it) != (cfswath->dimnames_to_dimsizes).end())
2970 dimsize_candidate = cfswath->dimnames_to_dimsizes[*it];
2971 else
2972 throw2("Cannot find the dimension size of the dimension name ", *it);
2973
2974 // Note: we don't have to use two loops to create the coordinate variables.
2975 // However, there are only 3-4 attributes for this group and so far TES has only
2976 // one additional nLevels.
2977 // So essentially the following loop doesn't hurt the performance.
2978 // KY 2012-2-1
2979 for (vector<Attribute *>::iterator ira = vc_group->attrs.begin(); ira != vc_group->attrs.end();
2980 ++ira) {
2981 if ((eos5_pre_attr_name == (*ira)->name) && ((*ira)->count == (dimsize_candidate - 1))) {
2982
2983 // Should change the attr_value from char type to float type when reading the data
2984 // Here just adding a coordinate variable by using this name.
2985 EOS5CVar *EOS5cvar = new EOS5CVar();
2986 string reduced_dimname = HDF5CFUtil::obtain_string_after_lastslash(*it);
2987 string orig_dimname = "nLevels";
2988 if ("nLevels" == reduced_dimname)
2989 EOS5cvar->name = eos5_pre_attr_name + "_CV";
2990 else
2991 // the dimname will be ..._CV_1 etc.
2992 EOS5cvar->name = eos5_pre_attr_name + "_CV"
2993 + reduced_dimname.substr(orig_dimname.size());
2994 Create_Added_Var_NewName_FullPath(SWATH, cfswath->name, EOS5cvar->name, EOS5cvar->newname,
2995 EOS5cvar->fullpath);
2996 EOS5cvar->rank = 1;
2997 EOS5cvar->dtype = (*ira)->dtype;
2998 Dimension *eos5cvar_dim = new Dimension(dimsize_candidate);
2999 eos5cvar_dim->name = *it;
3000 if (1 == this->eos5cfswaths.size())
3001 eos5cvar_dim->newname = reduced_dimname;
3002 else
3003 eos5cvar_dim->newname = eos5cvar_dim->name;
3004
3005 EOS5cvar->dims.push_back(eos5cvar_dim);
3006 EOS5cvar->cvartype = CV_SPECIAL;
3007 EOS5cvar->cfdimname = eos5cvar_dim->name;
3008 EOS5cvar->eos_type = SWATH;
3009
3010 // Save this cv to the cv vector
3011 this->cvars.push_back(EOS5cvar);
3012 } // if ((eos5_pre_attr_name == (*ira)->name) && ...
3013 } // for (vector<Attribute *>::iterator ira = vc_group->attrs.begin();
3014 } // if ((*it).find(dimname_candidate) != string::npos)
3015 } // for (it = tempvardimnamelist.begin(); ...
3016 } // if (true == has_vc_attr) ...
3017 } // if (true == this->isaura && ...
3018}
3019
3020// Handle Zonal average coordinate variables.
3021void EOS5File::Handle_Za_CVar(bool isaugmented)
3022{
3023
3024 BESDEBUG("h5", "Coming to Handle_Za_CVar()"<<endl);
3025 // We are not supporting non-augmented zonal average HDF-EOS5 product now. KY:2012-1-20
3026 if (false == isaugmented) return;
3027
3028 for (vector<EOS5CFZa *>::iterator irv = this->eos5cfzas.begin(); irv != this->eos5cfzas.end(); ++irv)
3029 Handle_Single_Augment_CVar(*irv, ZA);
3030
3031}
3032
3033// Adjust the newname(final names appeared at DDS) for variable and dimensions before flattening.
3035{
3036
3037 BESDEBUG("h5", "Coming to Adjust_Var_Dim_NewName_Before_Flattening()"<<endl);
3038 int num_grids = this->eos5cfgrids.size();
3039 int num_swaths = this->eos5cfswaths.size();
3040 int num_zas = this->eos5cfzas.size();
3041
3042 bool mixed_eos5typefile = false;
3043
3044 // Check if this file mixes grid,swath and zonal average
3045 if (((num_grids > 0) && (num_swaths > 0)) || ((num_grids > 0) && (num_zas > 0))
3046 || ((num_swaths > 0) && (num_zas > 0))) mixed_eos5typefile = true;
3047
3048 // This file doesn't mix swath, grid and zonal average
3049 for (vector<Var *>::iterator irv = this->vars.begin(); irv != this->vars.end(); ++irv)
3050 Adjust_Per_Var_Dim_NewName_Before_Flattening(*irv, mixed_eos5typefile, num_grids, num_swaths, num_zas);
3051
3052 for (vector<EOS5CVar *>::iterator irv = this->cvars.begin(); irv != this->cvars.end(); ++irv)
3053 Adjust_Per_Var_Dim_NewName_Before_Flattening(*irv, mixed_eos5typefile, num_grids, num_swaths, num_zas);
3054#if 0
3055 for (vector<EOS5CVar *>::iterator irv = this->cvars.begin();
3056 irv != this->cvars.end(); ++irv) {
3057 cerr<<"eos5svar var new name "<<(*irv)->newname <<endl;
3058 for (vector<Dimension *>::iterator ird = (*irv)->dims.begin();
3059 ird !=(*irv)->dims.end(); ++ird) {
3060 cerr<<"eos5svar dimension new name "<<(*ird)->newname <<endl;
3061 }
3062 }
3063#endif
3064 // If (lat,lon) is shared for grids, more consideration for the names
3065 Adjust_SharedLatLon_Grid_Var_Dim_Name();
3066
3067}
3068
3069// Adjust the final name of one variable or dim. before flattening the names
3070template<class T>
3071void EOS5File::Adjust_Per_Var_Dim_NewName_Before_Flattening(T* var, bool mixed_eos5type, int num_grids, int num_swaths,
3072 int num_zas)
3073{
3074
3075 BESDEBUG("h5", "Coming to Adjust_Per_Var_Dim_NewName_Before_Flattening()"<<endl);
3076
3077 string eos5typestr;
3078 EOS5Type vartype = Get_Var_EOS5_Type(var);
3079 switch (vartype) {
3080
3081 case GRID: {
3082 eos5typestr = "/GRIDS/";
3083 if (false == mixed_eos5type) {
3084 if (0 == num_grids)
3085 var->newname = ((1 == this->orig_num_grids) ? var->name : var->newname.substr(eos5typestr.size()));
3086 else
3087 var->newname = ((1 == num_grids) ? var->name : var->newname.substr(eos5typestr.size()));
3088 // Dimension newname is unlike Var newname, when num_grids is equal to 1, the
3089 // newname is Dimension name already. So we don't need to do anything with
3090 // the dimension newname when the num_grids is 1. The main reason we handle
3091 // the var newname and the dimension newname differently is that the variable name is
3092 // more critical for users to pick up the meanings of that variable. So we would like
3093 // to work hard to keep the original form. However, the dimension name is mainly used to
3094 // generate the coordinate variables. So the different usage makes us relax the dimension
3095 // name a little bit. This is an example of end-user priority driven implementation.
3096 // KY 2012-1-24
3097 // Just receive a user request: the dimension name is also very important.
3098 // So a bunch of code has been updated. For number of grid/swath/za = 1, I still maintain
3099 // the newname to be the same as the last part of the dim name. Hopefully this
3100 // will handle the current HDF-EOS5 products. Improvement for complicate HDF-EOS5 products
3101 // will be supported as demanded in the future. KY 2012-1-26
3102 if (num_grids > 1) {
3103 for (vector<Dimension *>::iterator ird = var->dims.begin(); ird != var->dims.end(); ird++) {
3104 if ((*ird)->newname.size() <= eos5typestr.size())
3105 throw5("The size of the dimension new name ", (*ird)->newname, "of variable ", var->newname,
3106 " is too small");
3107 (*ird)->newname = (*ird)->newname.substr(eos5typestr.size());
3108 }
3109 }
3110 } // if(false == mixed_eos5type)
3111 else {
3112 // No need to set the dimension newname for the reason listed above.
3113 var->newname = ((1 == num_grids) ? (eos5typestr + var->name) : var->newname);
3114 }
3115 }
3116 break;
3117
3118 case SWATH: {
3119 eos5typestr = "/SWATHS/";
3120 if (false == mixed_eos5type) {
3121 var->newname = ((1 == num_swaths) ? var->name : var->newname.substr(eos5typestr.size()));
3122 if (num_swaths > 1) {
3123 for (vector<Dimension *>::iterator ird = var->dims.begin(); ird != var->dims.end(); ird++) {
3124 if ((*ird)->newname.size() <= eos5typestr.size())
3125 throw5("The size of the dimension new name ", (*ird)->newname, "of variable ", var->newname,
3126 " is too small");
3127 (*ird)->newname = (*ird)->newname.substr(eos5typestr.size());
3128 }
3129 }
3130 }
3131 else {
3132 var->newname = ((1 == num_swaths) ? (eos5typestr + var->name) : var->newname);
3133 }
3134 }
3135 break;
3136
3137 case ZA: {
3138 eos5typestr = "/ZAS/";
3139 if (false == mixed_eos5type) {
3140 var->newname = ((1 == num_zas) ? var->name : var->newname.substr(eos5typestr.size()));
3141 if (num_zas > 1) {
3142 for (vector<Dimension *>::iterator ird = var->dims.begin(); ird != var->dims.end(); ird++) {
3143 if ((*ird)->newname.size() <= eos5typestr.size())
3144 throw5("The size of the dimension new name ", (*ird)->newname, "of variable ", var->newname,
3145 " is too small");
3146 (*ird)->newname = (*ird)->newname.substr(eos5typestr.size());
3147 }
3148 }
3149 }
3150 else {
3151 var->newname = ((1 == num_zas) ? (eos5typestr + var->name) : var->newname);
3152 }
3153 }
3154 break;
3155 case OTHERVARS:
3156 break;
3157 default:
3158 throw1("Non-supported EOS type");
3159 } // switch(vartype)
3160
3161}
3162
3163// Adjust shared var and dim names for shared lat/lon grid case.
3164void EOS5File::Adjust_SharedLatLon_Grid_Var_Dim_Name()
3165{
3166
3167 BESDEBUG("h5", "Adjust_SharedLatLon_Grid_Var_Dim_Name()"<<endl);
3168 // Remove the EOS5 type string("GRIDS") and the GRID Name from
3169 // the variable newname and the dimension newname
3170 // This case won't happen for the current version, but may occur
3171 // if curviliner grid exists in the file. KY 2012-1-26
3172 if ((this->eos5cfgrids.size() > 1) && (0 == this->eos5cfswaths.size()) && (0 == this->eos5cfzas.size())
3173 && (false == this->grids_multi_latloncvs)) {
3174
3175 // We would like to condense the dimension name and the coordinate variable name for lat/lon.
3176 string lat_dimname;
3177 string lat_dimnewname;
3178 string lon_dimname;
3179 string lon_dimnewname;
3180 for (vector<EOS5CVar *>::iterator irv = this->cvars.begin(); irv != this->cvars.end(); ++irv) {
3181 if ("lat" == (*irv)->name || "Latitude" == (*irv)->name) {
3182 (*irv)->newname = (*irv)->name;
3183 lat_dimnewname = (((*irv)->dims)[0])->newname;
3184 lat_dimnewname = HDF5CFUtil::obtain_string_after_lastslash(lat_dimnewname);
3185 if ("" == lat_dimnewname)
3186 throw2("/ is not included in the dimension new name ", (((*irv)->dims)[0])->newname);
3187 (((*irv)->dims)[0])->newname = lat_dimnewname;
3188 lat_dimname = (*irv)->cfdimname;
3189 }
3190 else if ("lon" == (*irv)->name || "Longitude" == (*irv)->name) {
3191 (*irv)->newname = (*irv)->name;
3192 lon_dimnewname = (((*irv)->dims)[0])->newname;
3193 lon_dimnewname = HDF5CFUtil::obtain_string_after_lastslash(lon_dimnewname);
3194 if ("" == lon_dimnewname)
3195 throw2("/ is not included in the dimension new name ", (((*irv)->dims)[0])->newname);
3196 (((*irv)->dims)[0])->newname = lon_dimnewname;
3197 lon_dimname = (*irv)->cfdimname;
3198 }
3199 } // for (vector<EOS5CVar *>::iterator irv = this->cvars.begin(); ...
3200
3201 for (vector<Var *>::iterator irv = this->vars.begin(); irv != this->vars.end(); ++irv) {
3202 for (vector<Dimension *>::iterator ird = (*irv)->dims.begin(); ird != (*irv)->dims.end(); ++ird) {
3203 if ((*ird)->name == lat_dimname)
3204 (*ird)->newname = lat_dimnewname;
3205 else if ((*ird)->name == lon_dimname) (*ird)->newname = lon_dimnewname;
3206 }
3207 }
3208 } // if ((this->eos5cfgrids.size() > 1) && ...
3209}
3210
3211// Flatten the object names.
3212void EOS5File::Flatten_Obj_Name(bool include_attr)
3213{
3214
3215 BESDEBUG("h5", "Coming to Flatten_Obj_Name()"<<endl);
3216 File::Flatten_Obj_Name(include_attr);
3217
3218 for (vector<EOS5CVar *>::iterator irv = this->cvars.begin(); irv != this->cvars.end(); ++irv) {
3219 (*irv)->newname = get_CF_string((*irv)->newname);
3220
3221 for (vector<Dimension *>::iterator ird = (*irv)->dims.begin(); ird != (*irv)->dims.end(); ++ird) {
3222 (*ird)->newname = get_CF_string((*ird)->newname);
3223 }
3224
3225 if (true == include_attr) {
3226 for (vector<Attribute *>::iterator ira = (*irv)->attrs.begin(); ira != (*irv)->attrs.end(); ++ira) {
3227 (*ira)->newname = File::get_CF_string((*ira)->newname);
3228 }
3229 }
3230 } // for (vector<EOS5CVar *>::iterator irv = this->cvars.begin(); ...
3231}
3232
3233// Handle Object Name clashing
3235{
3236
3237 BESDEBUG("h5", "Coming to Handle_Obj_NameClashing()"<<endl);
3238 // objnameset will be filled with all object names that we are going to check the name clashing.
3239 // For example, we want to see if there are any name clashings for all variable names in this file.
3240 // objnameset will include all variable names. If a name clashing occurs, we can figure out from the set operation immediately.
3241 set<string> objnameset;
3242 Handle_EOS5CVar_NameClashing(objnameset);
3243 File::Handle_GeneralObj_NameClashing(include_attr, objnameset);
3244 if (true == include_attr) {
3245 Handle_EOS5CVar_AttrNameClashing();
3246 }
3247#if 0
3248 //if (this->cvars.size() >0)
3249 // Handle_DimNameClashing();
3250#endif
3251}
3252
3253// Handle EOS5 coordinate variable name clashing
3254void EOS5File::Handle_EOS5CVar_NameClashing(set<string> &objnameset)
3255{
3256
3257 BESDEBUG("h5", "Coming to Handle_EOS5CVar_NameClashing()"<<endl);
3258 EOS5Handle_General_NameClashing(objnameset, this->cvars);
3259}
3260
3261// Handle EOS5 coordinate varaible attribute name clashing
3262void EOS5File::Handle_EOS5CVar_AttrNameClashing()
3263{
3264
3265 BESDEBUG("h5", "Coming to Handle_EOS5CVar_AttrNameClashing()"<<endl);
3266 set<string> objnameset;
3267
3268 for (vector<EOS5CVar *>::iterator irv = this->cvars.begin(); irv != this->cvars.end(); ++irv) {
3269 Handle_General_NameClashing(objnameset, (*irv)->attrs);
3270 objnameset.clear();
3271 }
3272}
3273// The routine to handle general name clashing
3274//class T must have member string newname
3275template<class T> void EOS5File::EOS5Handle_General_NameClashing(set<string>&objnameset, vector<T*>& objvec)
3276
3277{
3278
3279 BESDEBUG("h5", "Coming to EOS5Handle_General_NameClashing()"<<endl);
3280 pair<set<string>::iterator, bool> setret;
3281 set<string>::iterator iss;
3282
3283 vector<string> clashnamelist;
3284 vector<string>::iterator ivs;
3285
3286 map<int, int> cl_to_ol;
3287 int ol_index = 0;
3288 int cl_index = 0;
3289
3290 typename vector<T*>::iterator irv;
3291
3292 for (irv = objvec.begin(); irv != objvec.end(); ++irv) {
3293
3294 setret = objnameset.insert((*irv)->newname);
3295 if (!setret.second) {
3296 clashnamelist.insert(clashnamelist.end(), (*irv)->newname);
3297 cl_to_ol[cl_index] = ol_index;
3298 cl_index++;
3299 }
3300 ol_index++;
3301 }
3302
3303 // Now change the clashed elements to unique elements;
3304 // Generate the set which has the same size as the original vector.
3305 for (ivs = clashnamelist.begin(); ivs != clashnamelist.end(); ++ivs) {
3306 int clash_index = 1;
3307 string temp_clashname = *ivs + '_';
3308 HDF5CFUtil::gen_unique_name(temp_clashname, objnameset, clash_index);
3309 *ivs = temp_clashname;
3310 }
3311
3312 // Now go back to the original vector, make it unique.
3313 for (unsigned int i = 0; i < clashnamelist.size(); i++)
3314 objvec[cl_to_ol[i]]->newname = clashnamelist[i];
3315
3316}
3317
3318// Handle Dimension name clashing
3320{
3321
3322 BESDEBUG("h5", "Coming to Handle_DimNameClashing()"<<endl);
3323 map<string, string> dimname_to_dimnewname;
3324 pair<map<string, string>::iterator, bool> mapret;
3325 set<string> dimnameset;
3326 vector<Dimension*> vdims;
3327 set<string> dimnewnameset;
3328 pair<set<string>::iterator, bool> setret;
3329
3330 // First: Generate the dimset/dimvar based on coordinate variables.
3331 for (vector<EOS5CVar *>::iterator irv = this->cvars.begin(); irv != this->cvars.end(); ++irv) {
3332 for (vector<Dimension *>::iterator ird = (*irv)->dims.begin(); ird != (*irv)->dims.end(); ++ird) {
3333#if 0
3334 //setret = dimnameset.insert((*ird)->newname);
3335#endif
3336 setret = dimnameset.insert((*ird)->name);
3337 if (setret.second) vdims.push_back(*ird);
3338 }
3339 }
3340
3341 // For some cases, dimension names are provided but there are no corresponding coordinate
3342 // variables. For now, we will assume no such cases.
3343 // Actually, we find such a case in our fake testsuite. So we need to fix it.
3344
3345 for (vector<Var *>::iterator irv = this->vars.begin(); irv != this->vars.end(); ++irv) {
3346 for (vector<Dimension *>::iterator ird = (*irv)->dims.begin(); ird != (*irv)->dims.end(); ++ird) {
3347#if 0
3348 //setret = dimnameset.insert((*ird)->newname);
3349#endif
3350 setret = dimnameset.insert((*ird)->name);
3351 if (setret.second) vdims.push_back(*ird);
3352 }
3353 }
3354
3355#if 0
3356 for (vector<Dimension*>::iterator ird=vdims.begin();ird!=vdims.end();++ird)
3357 cerr<<"dimension name "<<(*ird)->name <<endl;
3358#endif
3359
3360 // For some cases, dimension names are provided but there are no corresponding coordinate
3361 // variables. For now, we will assume no such cases.
3362 EOS5Handle_General_NameClashing(dimnewnameset, vdims);
3363
3364 // Third: Make dimname_to_dimnewname map
3365 for (vector<Dimension*>::iterator ird = vdims.begin(); ird != vdims.end(); ++ird) {
3366 mapret = dimname_to_dimnewname.insert(pair<string, string>((*ird)->name, (*ird)->newname));
3367 if (false == mapret.second)
3368 throw4("The dimension name ", (*ird)->name, " should map to ", (*ird)->newname);
3369 }
3370
3371 // Fourth: Change the original dimension new names to the unique dimension new names
3372 for (vector<EOS5CVar *>::iterator irv = this->cvars.begin(); irv != this->cvars.end(); ++irv)
3373 for (vector<Dimension *>::iterator ird = (*irv)->dims.begin(); ird != (*irv)->dims.end(); ++ird)
3374 (*ird)->newname = dimname_to_dimnewname[(*ird)->name];
3375
3376 for (vector<Var *>::iterator irv = this->vars.begin(); irv != this->vars.end(); ++irv)
3377 for (vector<Dimension *>::iterator ird = (*irv)->dims.begin(); ird != (*irv)->dims.end(); ++ird)
3378 (*ird)->newname = dimname_to_dimnewname[(*ird)->name];
3379
3380}
3381
3382// Set COARDS Status, if we can follow COARDS, we should follow COARDS.
3383// http://ferret.wrc.noaa.gov/noaa_coop/coop_cdf_profile.html
3385{
3386
3387 BESDEBUG("h5", "Coming to Set_COARDS_Status()"<<endl);
3388 iscoard = true;
3389 for (vector<EOS5CFGrid *>::iterator irg = this->eos5cfgrids.begin(); irg != this->eos5cfgrids.end(); ++irg) {
3390 if (false == (*irg)->has_1dlatlon) {
3391 if (false == (*irg)->has_nolatlon || (HE5_GCTP_GEO != (*irg)->eos5_projcode)) iscoard = false;
3392 break;
3393 }
3394 }
3395
3396 if (true == iscoard) {
3397 for (vector<EOS5CFSwath *>::iterator irg = this->eos5cfswaths.begin(); irg != this->eos5cfswaths.end(); ++irg) {
3398 if (false == (*irg)->has_1dlatlon) {
3399 iscoard = false;
3400 break;
3401 }
3402 }
3403 }
3404}
3405
3406// Adjust attribute info., mostly for CF name correction of Aura files.
3408{
3409
3410 BESDEBUG("h5", "Coming to Adjust_Attr_Info()"<<endl);
3411 if (true == this->isaura) {
3412 Adjust_Aura_Attr_Name();
3413 Adjust_Aura_Attr_Value();
3414 }
3415 else {
3416 Handle_EOS5CVar_Unit_Attr();
3417 Add_EOS5_Grid_CF_Attr();
3418 }
3419}
3420
3421// Adjust Attribute Name, mostly for Aura files.
3422void EOS5File::Adjust_Aura_Attr_Name()
3423{
3424
3425 BESDEBUG("h5", "Coming to Adjust_Attr_Name() for Aura"<<endl);
3426 for (vector<Var*>::iterator irv = this->vars.begin(); irv != this->vars.end(); ++irv) {
3427 for (vector<Attribute*>::iterator ira = (*irv)->attrs.begin(); ira != (*irv)->attrs.end(); ++ira) {
3428 if (eos5_to_cf_attr_map.find((*ira)->name) != eos5_to_cf_attr_map.end()) (*ira)->newname =
3429 eos5_to_cf_attr_map[(*ira)->name];
3430
3431 }
3432 }
3433
3434 for (vector<EOS5CVar *>::iterator irv = this->cvars.begin(); irv != this->cvars.end(); ++irv) {
3435 for (vector<Attribute*>::iterator ira = (*irv)->attrs.begin(); ira != (*irv)->attrs.end(); ++ira) {
3436 if (eos5_to_cf_attr_map.find((*ira)->name) != eos5_to_cf_attr_map.end()) (*ira)->newname =
3437 eos5_to_cf_attr_map[(*ira)->name];
3438
3439 }
3440 }
3441}
3442
3443void EOS5File::Adjust_Aura_Attr_Value()
3444{
3445
3446 BESDEBUG("h5", "Coming to Adjust_Attr_Value() for Aura"<<endl);
3447 // Handle Units
3448 Handle_EOS5CVar_Unit_Attr();
3449 Handle_Aura_Special_Attr();
3450
3451 // Handle Time. This is just for Aura files.
3452 // This is for speical NASA requests only for Aura.
3453 // We need to pay attention if things get changed later.
3454 string time_cf_units_value = "seconds since 1993-01-01";
3455 for (vector<Var*>::iterator irv = this->vars.begin(); irv != this->vars.end(); irv++) {
3456 if (((*irv)->name == "Time") || ((*irv)->name == "nTimes")) {
3457 for (vector<Attribute*>::iterator ira = (*irv)->attrs.begin(); ira != (*irv)->attrs.end(); ira++) {
3458 if ("units" == (*ira)->name) {
3459 Retrieve_H5_Attr_Value(*ira, (*irv)->fullpath);
3460 string units_value((*ira)->value.begin(), (*ira)->value.end());
3461 if (time_cf_units_value != units_value) {
3462
3463 units_value = time_cf_units_value;
3464 (*ira)->value.resize(units_value.size());
3465 if (H5FSTRING == (*ira)->dtype) (*ira)->fstrsize = units_value.size();
3466 // strsize is used by both fixed and variable length strings.
3467 (*ira)->strsize.resize(1);
3468 (*ira)->strsize[0] = units_value.size();
3469
3470 copy(units_value.begin(), units_value.end(), (*ira)->value.begin());
3471 }
3472 break;
3473 } // if ("units" == (*ira)->name)
3474 } // for(vector <Attribute*>::iterator ira = (*irv)->attrs.begin();
3475 } // if(((*irv)->name == "Time") || ((*irv)->name == "nTimes"))
3476 } // for (vector<Var*>::iterator irv = this->vars.begin()...
3477}
3478
3479// Handle EOS5 coordinate variable special attributes.
3480void EOS5File::Handle_Aura_Special_Attr()
3481{
3482
3483 BESDEBUG("h5", "Coming to Handle_Aura_Special_Attr()"<<endl);
3484 // Need to handle MLS aura file specially.
3485 if (true == this->isaura && MLS == this->aura_name) {
3486
3487 const string File_attr_group_path = "/HDFEOS/ADDITIONAL/FILE_ATTRIBUTES";
3488 const string PCF1_attr_name = "PCF1";
3489 bool find_group = false;
3490 bool find_attr = false;
3491 for (vector<Group*>::iterator it_g = this->groups.begin(); it_g != this->groups.end(); ++it_g) {
3492 if (File_attr_group_path == (*it_g)->path) {
3493 find_group = true;
3494 for (vector<Attribute *>::iterator ira = (*it_g)->attrs.begin(); ira != (*it_g)->attrs.end(); ++ira) {
3495 if (PCF1_attr_name == (*ira)->name) {
3496 Retrieve_H5_Attr_Value(*ira, (*it_g)->path);
3497 string pcf_value((*ira)->value.begin(), (*ira)->value.end());
3498 HDF5CFDAPUtil::replace_double_quote(pcf_value);
3499 (*ira)->value.resize(pcf_value.size());
3500 if (H5FSTRING == (*ira)->dtype) (*ira)->fstrsize = pcf_value.size();
3501 // strsize is used by both fixed and variable length strings.
3502 (*ira)->strsize.resize(1);
3503 (*ira)->strsize[0] = pcf_value.size();
3504
3505 copy(pcf_value.begin(), pcf_value.end(), (*ira)->value.begin());
3506 find_attr = true;
3507 break;
3508 } // if (PCF1_attr_name == (*ira)->name)
3509 } // for (vector<Attribute *>::iterator ira = (*it_g)->attrs.begin()
3510 } // if (File_attr_group_path == (*it_g)->path)
3511 if (true == find_group && true == find_attr) break;
3512 } // for (vector<Group*>::iterator it_g = this->groups.begin() ...
3513 } // if (true == this->isaura && MLS == this->aura_name)
3514}
3515
3516// Handle coordinate variable units attribute
3517void EOS5File::Handle_EOS5CVar_Unit_Attr()
3518{
3519
3520 BESDEBUG("h5", "Coming to Handle_EOS5CVar_Unit_Attr()"<<endl);
3521 string unit_attrname = "units";
3522 string nonll_cf_level_attrvalue = "level";
3523 string lat_cf_unit_attrvalue = "degrees_north";
3524 string lon_cf_unit_attrvalue = "degrees_east";
3525 string tes_cf_pre_attrvalue = "hPa";
3526
3527 for (vector<EOS5CVar *>::iterator irv = this->cvars.begin(); irv != this->cvars.end(); ++irv) {
3528 switch ((*irv)->cvartype) {
3529 case CV_EXIST:
3530 case CV_MODIFY: {
3531 for (vector<Attribute*>::iterator ira = (*irv)->attrs.begin(); ira != (*irv)->attrs.end(); ++ira) {
3532 if ((*ira)->newname == unit_attrname) {
3533 Retrieve_H5_Attr_Value(*ira, (*irv)->fullpath);
3534 string units_value((*ira)->value.begin(), (*ira)->value.end());
3535 if ((lat_cf_unit_attrvalue != units_value)
3536 && (((*irv)->name == "Latitude") || ((this->eos5cfzas.size() > 0) && ((*irv)->name == "nLats")))) {
3537 units_value = lat_cf_unit_attrvalue;
3538#if 0
3539//cerr<<"coming to obtain the correct units_value: "<<units_value <<endl;
3540//cerr<<"cvar name is "<<(*irv)->newname <<endl;
3541#endif
3542 (*ira)->value.resize(units_value.size());
3543 if (H5FSTRING == (*ira)->dtype) (*ira)->fstrsize = units_value.size();
3544 // strsize is used by both fixed and variable length strings.
3545 (*ira)->strsize.resize(1);
3546 (*ira)->strsize[0] = units_value.size();
3547 copy(units_value.begin(), units_value.end(), (*ira)->value.begin());
3548 }
3549 else if ((lon_cf_unit_attrvalue != units_value) && (*irv)->name == "Longitude") {
3550 units_value = lon_cf_unit_attrvalue;
3551 (*ira)->value.resize(units_value.size());
3552 if (H5FSTRING == (*ira)->dtype) (*ira)->fstrsize = units_value.size();
3553 // strsize is used by both fixed and variable length strings.
3554 (*ira)->strsize.resize(1);
3555 (*ira)->strsize[0] = units_value.size();
3556
3557 copy(units_value.begin(), units_value.end(), (*ira)->value.begin());
3558 }
3559 break;
3560 } // if ((*ira)->newname ==unit_attrname)
3561 }
3562 }
3563 break;
3564
3565 case CV_LAT_MISS: {
3566 Attribute * attr = new Attribute();
3567 Add_Str_Attr(attr, unit_attrname, lat_cf_unit_attrvalue);
3568 (*irv)->attrs.push_back(attr);
3569 }
3570 break;
3571
3572 case CV_LON_MISS: {
3573 Attribute * attr = new Attribute();
3574 Add_Str_Attr(attr, unit_attrname, lon_cf_unit_attrvalue);
3575 (*irv)->attrs.push_back(attr);
3576 }
3577 break;
3578
3579 case CV_NONLATLON_MISS: {
3580 Attribute * attr = new Attribute();
3581 Add_Str_Attr(attr, unit_attrname, nonll_cf_level_attrvalue);
3582 (*irv)->attrs.push_back(attr);
3583 }
3584 break;
3585 case CV_SPECIAL: {
3586 if (true == this->isaura && TES == this->aura_name) {
3587 Attribute * attr = new Attribute();
3588 Add_Str_Attr(attr, unit_attrname, tes_cf_pre_attrvalue);
3589 (*irv)->attrs.push_back(attr);
3590 }
3591 }
3592 break;
3593 default:
3594 throw1("Non-supported Coordinate Variable Type.");
3595 } // switch((*irv)->cvartype)
3596 } // for (vector<EOS5CVar *>::iterator irv = this->cvars.begin() ...
3597}
3598
3599void EOS5File::Add_EOS5_Grid_CF_Attr()
3600{
3601 BESDEBUG("h5", "Coming to Add_EOS5_Grid_CF_Attr()"<<endl);
3602
3603 bool has_eos5_grid_nongeo_proj = false;
3604
3605 // Check if we have EOS5 grids that are not using the geographic projection.
3606 for (vector<EOS5CVar *>::iterator irv = this->cvars.begin(); irv != this->cvars.end(); ++irv) {
3607 if ((*irv)->cvartype == CV_LAT_MISS) {
3608 if((*irv)->eos5_projcode !=HE5_GCTP_GEO) {
3609 has_eos5_grid_nongeo_proj = true;
3610 break;
3611 }
3612 }
3613 }
3614
3615 // We would like to add the CF conventions mark if the mark is not there.
3616 if(true == has_eos5_grid_nongeo_proj) {
3617 string conventions_attrname = "Conventions";
3618 string conventions_attrvalue = "CF-1.7";
3619 bool has_conventions_attr=false;
3620 for(vector<HDF5CF::Attribute *>::const_iterator it_ra=this->root_attrs.begin();
3621 it_ra!=this->root_attrs.end();it_ra++) {
3622 if((*it_ra)->name==conventions_attrname){
3623 has_conventions_attr = true;
3624 break;
3625 }
3626
3627 }
3628 if(false==has_conventions_attr) {
3629 Attribute * attr = new Attribute();
3630 Add_Str_Attr(attr,conventions_attrname,conventions_attrvalue);
3631 this->root_attrs.push_back(attr);
3632 }
3633 }
3634
3635}
3636
3637
3638
3639// Adjust Dimension name
3641{
3642
3643 BESDEBUG("h5", "Coming to Adjust_Dim_Name()"<<endl);
3644 // No need if this is following COARDS.
3645 if (false == this->iscoard)
3646 return;
3647 else {
3648 for (vector<EOS5CVar *>::iterator irv = this->cvars.begin(); irv != this->cvars.end(); irv++) {
3649 if ((*irv)->dims.size() != 1)
3650 throw3("Coard coordinate variable ", (*irv)->name, "is not 1D");
3651 if ((*irv)->newname != (((*irv)->dims)[0]->newname)) {
3652 ((*irv)->dims)[0]->newname = (*irv)->newname;
3653
3654 // For all variables that have this dimension,the dimension newname should also change.
3655 for (vector<Var*>::iterator irv2 = this->vars.begin(); irv2 != this->vars.end(); irv2++) {
3656 for (vector<Dimension *>::iterator ird = (*irv2)->dims.begin(); ird != (*irv2)->dims.end(); ird++) {
3657 // This is the key, the dimension name of this dimension
3658 // should be equal to the dimension name of the coordinate variable.
3659 // Then the dimension name matches and the dimension name should be changed to
3660 // the new dimension name.
3661 if ((*ird)->name == ((*irv)->dims)[0]->name) (*ird)->newname = ((*irv)->dims)[0]->newname;
3662 }
3663 }
3664 } // if ((*irv)->newname != (((*irv)->dims)[0]->newname))
3665 } // for (vector<EOS5CVar *>::iterator irv = this->cvars.begin();
3666 } // else
3667}
3668
3669// Add supplemental attributes such as origname and fullpath.
3671{
3672
3673 BESDEBUG("h5", "Coming to Add_Supplement_Attrs()"<<endl);
3674 if (true == add_path) {
3675
3677
3678 // Adding variable original name(origname) and full path(fullpath)
3679 for (vector<EOS5CVar *>::iterator irv = this->cvars.begin(); irv != this->cvars.end(); ++irv) {
3680 if (((*irv)->cvartype == CV_EXIST) || ((*irv)->cvartype == CV_MODIFY)) {
3681 Attribute * attr = new Attribute();
3682 const string varname = (*irv)->name;
3683 const string attrname = "origname";
3684 Add_Str_Attr(attr, attrname, varname);
3685 (*irv)->attrs.push_back(attr);
3686 }
3687 }
3688
3689 for (vector<EOS5CVar *>::iterator irv = this->cvars.begin(); irv != this->cvars.end(); ++irv) {
3690 if (((*irv)->cvartype == CV_EXIST) || ((*irv)->cvartype == CV_MODIFY)) {
3691 // Turn off the fullnamepath attribute when zero_storage_size is 0.
3692 // Use the BES key since quite a few testing cases will be affected.
3693 // KY 2020-03-23
3694 if((*irv)->zero_storage_size==false
3695 || HDF5RequestHandler::get_no_zero_size_fullnameattr() == false) {
3696 Attribute * attr = new Attribute();
3697 const string varname = (*irv)->fullpath;
3698 const string attrname = "fullnamepath";
3699 Add_Str_Attr(attr, attrname, varname);
3700 (*irv)->attrs.push_back(attr);
3701 }
3702 }
3703 }
3704 } // if(true == add_path)
3705
3706 if (true == this->iscoard) {
3707 for (vector<EOS5CVar *>::iterator irv = this->cvars.begin(); irv != this->cvars.end(); ++irv) {
3708 if (((*irv)->cvartype == CV_EXIST) || ((*irv)->cvartype == CV_MODIFY)) {
3709 Attribute * attr = new Attribute();
3710 const string attrname = "orig_dimname";
3711 string orig_dimname = (((*irv)->dims)[0])->name;
3712 orig_dimname = HDF5CFUtil::obtain_string_after_lastslash(orig_dimname);
3713 if ("" == orig_dimname)
3714 throw2("wrong dimension name ", orig_dimname);
3715 if (orig_dimname.find("FakeDim") != string::npos) orig_dimname = "";
3716 Add_Str_Attr(attr, attrname, orig_dimname);
3717 (*irv)->attrs.push_back(attr);
3718 }
3719 } // for (vector<EOS5CVar *>::iterator irv = this->cvars.begin()
3720
3721 for (vector<Var *>::iterator irv = this->vars.begin(); irv != this->vars.end(); ++irv) {
3722
3723 if ((*irv)->dims.size() > 0) {
3724 Attribute * attr = new Attribute();
3725 if (1 == (*irv)->dims.size()) {
3726 const string attrname = "orig_dimname";
3727 string orig_dimname = (((*irv)->dims)[0])->name;
3728 if ("" == orig_dimname)
3729 orig_dimname = "NoDimName";
3730 else
3731 orig_dimname = HDF5CFUtil::obtain_string_after_lastslash(orig_dimname);
3732 if (orig_dimname.find("FakeDim") != string::npos) orig_dimname = "NoDimName";
3733 Add_Str_Attr(attr, attrname, orig_dimname);
3734 }
3735 else {
3736 const string attrname = "orig_dimname_list";
3737 string orig_dimname_list;
3738 for (vector<Dimension *>::iterator ird = (*irv)->dims.begin(); ird != (*irv)->dims.end(); ++ird) {
3739 string orig_dimname = (*ird)->name;
3740 if ("" == orig_dimname)
3741 orig_dimname = "NoDimName";
3742 else
3743 orig_dimname = HDF5CFUtil::obtain_string_after_lastslash((*ird)->name);
3744 if (orig_dimname.find("FakeDim") != string::npos) orig_dimname = "NoDimName";
3745 if ("" == orig_dimname_list)
3746 orig_dimname_list = orig_dimname;
3747 else
3748 orig_dimname_list = orig_dimname_list + " " + orig_dimname;
3749// orig_dimname_list = orig_dimname_list + " ";
3750 }
3751 Add_Str_Attr(attr, attrname, orig_dimname_list);
3752 }
3753 (*irv)->attrs.push_back(attr);
3754 } // if ((*irv)->dims.size() >0 )
3755 } // for (vector<Var *>::iterator irv = this->vars.begin();
3756 } // if(true == this->iscoard )
3757
3758}
3759
3760// Handle coordinate attributes.
3762{
3763
3764 BESDEBUG("h5", "Coming to Handle_Coor_Attr()"<<endl);
3765 string co_attrname = "coordinates";
3766 string co_attrvalue = "";
3767
3768 if (iscoard) return;
3769
3770 for (vector<Var *>::iterator irv = this->vars.begin(); irv != this->vars.end(); ++irv) {
3771
3772 for (vector<Dimension *>::iterator ird = (*irv)->dims.begin(); ird != (*irv)->dims.end(); ++ird) {
3773 for (vector<EOS5CVar *>::iterator ircv = this->cvars.begin(); ircv != this->cvars.end(); ++ircv) {
3774 if ((*ird)->name == (*ircv)->cfdimname)
3775 co_attrvalue = (co_attrvalue.empty()) ? (*ircv)->newname : co_attrvalue + " " + (*ircv)->newname;
3776 }
3777 }
3778 if (false == co_attrvalue.empty()) {
3779 Attribute * attr = new Attribute();
3780 Add_Str_Attr(attr, co_attrname, co_attrvalue);
3781 (*irv)->attrs.push_back(attr);
3782 }
3783 co_attrvalue.clear();
3784 } // for (vector<Var *>::iterator irv = this->vars.begin(); ...
3785
3786 // We will check if 2dlatlon coordinate variables exist
3787 bool has_2dlatlon_cv = false;
3788 for (vector<EOS5CVar *>::iterator ircv = this->cvars.begin(); ircv != this->cvars.end(); ++ircv) {
3789 if (true == (*ircv)->is_2dlatlon) {
3790 has_2dlatlon_cv = true;
3791 break;
3792 }
3793 }
3794
3795 if (true == has_2dlatlon_cv) {
3796
3797 string dimname1;
3798 string dimname2;
3799 for (vector<EOS5CVar *>::iterator ircv = this->cvars.begin(); ircv != this->cvars.end(); ++ircv) {
3800 if (true == (*ircv)->is_2dlatlon) {
3801 dimname1 = (((*ircv)->dims)[0])->name;
3802 dimname2 = (((*ircv)->dims)[1])->name;
3803 break;
3804 }
3805 }
3806
3807 int num_latlondims = 0;
3808
3809 for (vector<Var *>::iterator irv = this->vars.begin(); irv != this->vars.end(); ++irv) {
3810 for (vector<Dimension *>::iterator ird = (*irv)->dims.begin(); ird != (*irv)->dims.end(); ++ird) {
3811 if (dimname1 == (*ird)->name) num_latlondims++;
3812 if (dimname2 == (*ird)->name) num_latlondims++;
3813 }
3814 if ((num_latlondims != 0) && (num_latlondims != 2)) {
3815 // need to remove the coordinates attribute.
3816 for (vector<Attribute *>::iterator ira = (*irv)->attrs.begin(); ira != (*irv)->attrs.end(); ++ira) {
3817 if (co_attrname == (*ira)->name) {
3818 delete (*ira);
3819 (*irv)->attrs.erase(ira);
3820 break;
3821 }
3822 }
3823 }
3824 num_latlondims = 0;
3825 } // for (vector<Var *>::iterator irv = this->vars.begin();
3826 } // if (true == has_2dlatlon_cv)
3827}
3828
3829// This function is from the original requirement of NASA, then
3830// NASA changes the requirment. Still leave it here for future usage.
3831#if 0
3832void EOS5File::Adjust_Special_EOS5CVar_Name() {
3833
3834 int num_grids =this->eos5cfgrids.size();
3835 int num_swaths = this->eos5cfswaths.size();
3836 int num_zas = this->eos5cfzas.size();
3837
3838 bool mixed_eos5typefile = false;
3839
3840 // Check if this file mixes grid,swath and zonal average
3841 if (((num_grids > 0) && (num_swaths > 0)) ||
3842 ((num_grids > 0) && (num_zas > 0)) ||
3843 ((num_swaths >0) && (num_zas > 0)))
3844 mixed_eos5typefile = true;
3845
3846 if (false == mixed_eos5typefile) {
3847
3848 // Grid is very special since all grids may share the same lat/lon.
3849 // so we also consider this case.
3850
3851 if ((1 == num_swaths) || ( 1 == num_zas) ||
3852 (1 == num_grids) || ((num_grids >1) && (this->grids_multi_latloncvs))) {
3853
3854 string unit_attrname = "units";
3855 string nonll_cf_level_attralue ="level";
3856 string lat_cf_unit_attrvalue ="degrees_north";
3857 string lon_cf_unit_attrvalue ="degrees_east";
3858
3859 for (vector<EOS5CVar *>::iterator irv = this->cvars.begin();
3860 irv != this->cvars.end(); irv++) {
3861 switch((*irv)->eos_type) {
3862 case CV_EXIST:
3863 case CV_MODIFY:
3864 case CV_LAT_MISS:
3865 case CV_LON_MISS:
3866 {
3867 for(vector <Attribute*>::iterator ira = (*irv)->attrs.begin();
3868 ira != (*irv)->attrs.end(); ira++) {
3869 if ((*ira)->name ==unit_attrname) {
3870 if ((*ira)->value.size() > 0) {
3871 string units_value((*ira)->value.begin(),(*ira)->value.end());
3872 if (lat_cf_unit_attrvalue ==units_value) (*irv)->newname = "lat";
3873 if (lon_cf_unit_attrvalue ==units_value) (*irv)->newname = "lon";
3874 }
3875 }
3876 }
3877 }
3878 break;
3879 case CV_NONLATLON_MISS:
3880 {
3881 for(vector <Attribute*>::iterator ira = (*irv)->attrs.begin();
3882 ira != (*irv)->attrs.end(); ira++) {
3883 if ((*ira)->name ==unit_attrname) {
3884 if ((*ira)->value.size() > 0) {
3885 string units_value((*ira)->value.begin(),(*ira)->value.end());
3886 if (nonll_cf_level_attralue ==units_value) {
3887 (*irv)->newname = "lev";
3888 break;
3889 }
3890 }
3891 }
3892 }
3893 }
3894 break;
3895 default:
3896 throw1("Non-supported coordinate variable type");
3897 }
3898 }
3899 }
3900 }
3901}
3902#endif
3903
3904// Create missing coordinate variables. Some NASA files don't provide coordinate
3905// variables for some dimensions. To make the visualization tools plot the data,
3906// we provide index number as coordinate variable values for these missing coordinate variables.
3907// These missing coordinate variables are all 1-D.
3908template<class T>
3909void EOS5File::Create_Missing_CV(T* eos5data, EOS5CVar *EOS5cvar, const string& dimname, EOS5Type eos5type,
3910 int num_eos5data)
3911{
3912
3913 BESDEBUG("h5", "Coming to Create_Missing_CV()"<<endl);
3914 string reduced_dimname = HDF5CFUtil::obtain_string_after_lastslash(dimname);
3915 if ("" == reduced_dimname) throw2("wrong dimension name ", dimname);
3916 EOS5cvar->name = reduced_dimname;
3917 Create_Added_Var_NewName_FullPath(eos5type, eos5data->name, EOS5cvar->name, EOS5cvar->newname, EOS5cvar->fullpath);
3918 EOS5cvar->rank = 1;
3919 EOS5cvar->dtype = H5INT32;
3920 hsize_t eos5cvar_dimsize = (eos5data->dimnames_to_dimsizes)[dimname];
3921 Dimension* eos5cvar_dim = new Dimension(eos5cvar_dimsize);
3922 eos5cvar_dim->name = dimname;
3923 eos5cvar_dim->unlimited_dim = (eos5data->dimnames_to_unlimited)[dimname];
3924 if (1 == num_eos5data)
3925 eos5cvar_dim->newname = reduced_dimname;
3926 else
3927 eos5cvar_dim->newname = dimname;
3928
3929 EOS5cvar->dims.push_back(eos5cvar_dim);
3930 EOS5cvar->cfdimname = dimname;
3931 EOS5cvar->cvartype = CV_NONLATLON_MISS;
3932 EOS5cvar->eos_type = eos5type;
3933}
3934
3935// Helper function for Create_Missing_CV
3936void EOS5File::Create_Added_Var_NewName_FullPath(EOS5Type eos5type, const string& eos5_groupname, const string& varname,
3937 string &var_newname, string &var_fullpath)
3938{
3939
3940 BESDEBUG("h5", "Coming to Create_Added_Var_NewName_FullPath()"<<endl);
3941 string fslash_str = "/";
3942 string eos5typestr = "";
3943 string top_eos5_groupname = "/HDFEOS";
3944
3945 switch (eos5type) {
3946 case GRID: {
3947 eos5typestr = "/GRIDS/";
3948 var_newname = eos5typestr + eos5_groupname + fslash_str + varname;
3949 var_fullpath = top_eos5_groupname + eos5typestr + eos5_groupname + fslash_str + varname;
3950 }
3951 break;
3952
3953 case SWATH: {
3954 eos5typestr = "/SWATHS/";
3955 var_newname = eos5typestr + eos5_groupname + fslash_str + varname;
3956 var_fullpath = top_eos5_groupname + eos5typestr + eos5_groupname + fslash_str + varname;
3957
3958 }
3959 break;
3960
3961 case ZA: {
3962 eos5typestr = "/ZAS/";
3963 var_newname = eos5typestr + eos5_groupname + fslash_str + varname;
3964 var_fullpath = top_eos5_groupname + eos5typestr + eos5_groupname + fslash_str + varname;
3965
3966 }
3967 break;
3968 case OTHERVARS:
3969 default:
3970 throw1("Non-supported EOS type");
3971 }
3972}
3973
3974// Handle special variables, various speical cases are handled here.
3976{
3977
3978 BESDEBUG("h5", "Coming to Handle_SpVar()"<<endl);
3979 if (true == this->isaura && TES == this->aura_name) {
3980 const string ProHist_full_path = "/HDFEOS/ADDITIONAL/FILE_ATTRIBUTES/ProductionHistory";
3981 for (vector<Var *>::iterator irv = this->vars.begin(); irv != this->vars.end(); ++irv) {
3982 if (ProHist_full_path == (*irv)->fullpath) {
3983 delete (*irv);
3984 this->vars.erase(irv);
3985 break;
3986 }
3987 }
3988 }
3989
3990 // First, if the duplicate dimension exists,
3991 if (dimname_to_dupdimnamelist.size() > 0) {
3992 for (vector<EOS5CVar *>::iterator ircv = this->cvars.begin(); ircv != this->cvars.end(); ircv++) {
3993 if ((*ircv)->cvartype == CV_EXIST) {
3994 pair<multimap<string, string>::iterator, multimap<string, string>::iterator> mm_er_ret;
3995 multimap<string, string>::iterator itmm;
3996 for (itmm = dimname_to_dupdimnamelist.begin(); itmm != dimname_to_dupdimnamelist.end(); ++itmm) {
3997
3998 // Find the original dimension(the coordinate variable)
3999 if ((*ircv)->cfdimname == (*itmm).first) {
4000
4001 // Loop through the cv again,this time just check CV_NONLATLON_MISS
4002 for (vector<EOS5CVar *>::iterator irv2 = this->cvars.begin(); irv2 != this->cvars.end();
4003 irv2++) {
4004 if ((*irv2)->cvartype == CV_NONLATLON_MISS) {
4005 //cerr<<"the duplicate cf dimension name "<<(*irv2)->cfdimname <<endl;
4006 // Obtain the fake CV that has the duplicate dimension.
4007 //if((*irv2)->cfdimname == (*ircv)->cfdimname) {
4008 if ((*irv2)->cfdimname == (*itmm).second) {
4009
4010 //find the duplicate dimension name
4011 string dup_var_name = (*irv2)->newname;
4012 Replace_Var_Info((*ircv), (*irv2));
4013 // The following two lines are key to make sure duplicate CV
4014 // using a different name but keep all other info.
4015 (*irv2)->newname = dup_var_name;
4016 (*irv2)->getDimensions()[0]->newname = dup_var_name;
4017 }
4018 }
4019 }
4020 }
4021 }
4022 }
4023 }
4024 }
4025
4026 // No need to loop through the variables. We just need to loop through the coordinate variables and check cfdimname.
4027#if 0
4028 // For the EOS case, Loop through every variable that has a >=2 rank,
4029 for (vector<Var *>::iterator irv = this->vars.begin();
4030 irv != this->vars.end(); ++irv) {
4031
4032 // Check if having the duplicate dimensions.
4033 if((*irv)->rank >=2) {
4034 // Loop through the dimensions
4035 for (vector<Dimension *>::iterator ird = (*irv)->dims.begin();
4036 ird != (*irv)->dims.end(); ++ ird) {
4037 pair<multimap<string,string>::iterator,multimap<string,string>::iterator> mm_er_ret;
4038 multimap<string,string>::iterator itmm;
4039 for (itmm = dimname_to_dupdimnamelist.begin(); itmm!=dimname_to_dupdimnamelist.end();++itmm) {
4040//cerr<<"the original dim. name is "<<(*itmm).first <<endl;
4041//cerr<<"the duplicate dim. name is "<<(*itmm).second <<endl;
4042//if((*irv)->name == "RetrievalAveragingKernelMatrixDay")
4043 cerr<<"duplicate dimension name of a variable is "<<(*ird)->name <<endl;
4044 // Find the duplicated dim name in the dimname_to_dupdimnamelist,
4045 // Now retrieve the dim. name and loop through all CV_EXIST variable to see if
4046 // one CV_EXIST variable has a dimension of which name is the dim. name.
4047 // If yes, loop through all CV_NONLLMISS variables and find the CV variable that has the
4048 // duplicate dim. name. If found, replace this variable's information(except name and newname) with the
4049 // fullpath of the CV_EXIST variable. In this way, the duplicate CV variable will read
4050 // correctly the existing CV values and other information. This is the most complicate process.
4051
4052// if((*itmm).second == HDF5CFUtil::obtain_string_after_lastslash((*ird)->name)) {
4053 if((*itmm).second == (*ird)->name) {
4054 cerr<<"coming to find the duplicate dim. name "<<endl;
4055 for (vector<EOS5CVar *>::iterator ircv = this->cvars.begin();
4056 ircv != this->cvars.end(); ircv++) {
4057 if((*ircv)->cvartype == CV_EXIST) {
4058 cerr<<"cf dim. name is "<<(*ircv)->cfdimname <<endl;
4059 // Find the original dimension(the coordinate variable)
4060 if((*ircv)->cfdimname == (*itmm).first) {
4061 // Loop through the cv again,this time just check CV_NONLATLON_MISS
4062 for (vector<EOS5CVar *>::iterator irv2 = this->cvars.begin();
4063 irv2 != this->cvars.end(); irv2++) {
4064 if((*irv2)->cvartype == CV_NONLATLON_MISS) {
4065 // Obtain the fake CV that has the duplicate dimension.
4066 if((*irv2)->cfdimname == (*itmm).second) {
4067 string dup_var_name = (*irv2)->newname;
4068 Replace_Var_Info((*ircv),(*irv2));
4069 (*irv2)->newname = dup_var_name;
4070 (*irv2)->getDimensions()[0]->newname = dup_var_name;
4071 }
4072
4073 }
4074 }
4075
4076 }
4077
4078 }
4079
4080 }
4081
4082 }
4083
4084 }
4085
4086 }
4087
4088 }
4089 }
4090
4091}
4092#endif
4093}
4094
4095// Handle special variable attributes
4097{
4098
4099 BESDEBUG("h5", "Coming to Handle_SpVar_Attr()"<<endl);
4100
4101 // First, if the duplicate dimension exists,
4102 if (dimname_to_dupdimnamelist.size() > 0) {
4103
4104 pair<multimap<string, string>::iterator, multimap<string, string>::iterator> mm_er_ret;
4105 multimap<string, string>::iterator itmm;
4106 for (itmm = dimname_to_dupdimnamelist.begin(); itmm != dimname_to_dupdimnamelist.end(); ++itmm) {
4107 for (vector<EOS5CVar *>::iterator ircv = this->cvars.begin(); ircv != this->cvars.end(); ircv++) {
4108 // The duplicated CV must share with an existing coordinate variable
4109 if ((*ircv)->cvartype == CV_EXIST) {
4110
4111 // Find the original dimension(the coordinate variable)
4112 if ((*ircv)->cfdimname == (*itmm).first) {
4113
4114 // Loop through the cv again,this time just check CV_NONLATLON_MISS
4115 // The duplciated CV must be CV_NONLATLON_MISS.
4116 for (vector<EOS5CVar *>::iterator irv2 = this->cvars.begin(); irv2 != this->cvars.end();
4117 irv2++) {
4118 if ((*irv2)->cvartype == CV_NONLATLON_MISS) {
4119
4120 // Obtain the fake CV that has the duplicate dimension.
4121 //if((*irv2)->cfdimname == (*ircv)->cfdimname)
4122 if ((*irv2)->cfdimname == (*itmm).second) Replace_Var_Attrs((*ircv), (*irv2));
4123
4124 }
4125 }
4126 } // if((*ircv)->cfdimname == (*itmm).first)
4127 } // if((*ircv)->cvartype == CV_EXIST)
4128 } // for (vector<EOS5CVar *>::iterator ircv = this->cvars.begin()
4129 } // for (itmm = dimname_to_dupdimnamelist.begin();
4130 } // if(dimname_to_dupdimnamelist.size() > 0)
4131}
4132
4133// Handle special variables, various speical cases are handled here.
4135{
4136
4137 BESDEBUG("h5", "Coming to Handle_SpVar_DMR()"<<endl);
4138 if (true == this->isaura && TES == this->aura_name) {
4139 const string ProHist_full_path = "/HDFEOS/ADDITIONAL/FILE_ATTRIBUTES/ProductionHistory";
4140 for (vector<Var *>::iterator irv = this->vars.begin(); irv != this->vars.end(); ++irv) {
4141 if (ProHist_full_path == (*irv)->fullpath) {
4142 delete (*irv);
4143 this->vars.erase(irv);
4144 break;
4145 }
4146 }
4147 }
4148
4149 // First, if the duplicate dimension exists,
4150 if (dimname_to_dupdimnamelist.size() > 0) {
4151 for (vector<EOS5CVar *>::iterator ircv = this->cvars.begin(); ircv != this->cvars.end(); ircv++) {
4152 if ((*ircv)->cvartype == CV_EXIST) {
4153 pair<multimap<string, string>::iterator, multimap<string, string>::iterator> mm_er_ret;
4154 multimap<string, string>::iterator itmm;
4155 for (itmm = dimname_to_dupdimnamelist.begin(); itmm != dimname_to_dupdimnamelist.end(); ++itmm) {
4156
4157 // Find the original dimension(the coordinate variable)
4158 if ((*ircv)->cfdimname == (*itmm).first) {
4159
4160 // Loop through the cv again,this time just check CV_NONLATLON_MISS
4161 for (vector<EOS5CVar *>::iterator irv2 = this->cvars.begin(); irv2 != this->cvars.end();
4162 irv2++) {
4163 if ((*irv2)->cvartype == CV_NONLATLON_MISS) {
4164 //cerr<<"the duplicate cf dimension name "<<(*irv2)->cfdimname <<endl;
4165 // Obtain the fake CV that has the duplicate dimension.
4166 //if((*irv2)->cfdimname == (*ircv)->cfdimname) {
4167 if ((*irv2)->cfdimname == (*itmm).second) {
4168
4169 Replace_Var_Attrs((*ircv), (*irv2));
4170 //find the duplicate dimension name
4171 string dup_var_name = (*irv2)->newname;
4172 Replace_Var_Info((*ircv), (*irv2));
4173
4174 // The following two lines are key to make sure duplicate CV
4175 // using a different name but keep all other info.
4176 (*irv2)->newname = dup_var_name;
4177 (*irv2)->getDimensions()[0]->newname = dup_var_name;
4178 }
4179 }
4180 }
4181 }
4182 }
4183 }
4184 }
4185 }
4186
4187}
4188
4189
4191{
4192 //Intentionally unimplemented, may have use cases for the future.
4193}
4194
4197}
4200}
4201
4202
4203// Sometimes need to replace informaton of a variable with the information of another variable.
4204void EOS5File::Replace_Var_Info(EOS5CVar *src, EOS5CVar*target)
4205{
4206
4207 BESDEBUG("h5", "Coming to Replace_Var_Info()"<<endl);
4208 File::Replace_Var_Info(src, target);
4209 target->cfdimname = src->cfdimname;
4210 target->cvartype = src->cvartype;
4211 target->eos_type = src->eos_type;
4212 target->total_elems = src->total_elems;
4213
4214}
4215
4216//Sometimes the attributes of a variable need to replace with the attribute of another variable.
4217void EOS5File::Replace_Var_Attrs(EOS5CVar *src, EOS5CVar*target)
4218{
4219
4220 BESDEBUG("h5", "Coming to Replace_Var_Attrs()"<<endl);
4221 File::Replace_Var_Attrs(src, target);
4222
4223}
4224
4225#if 0
4226void
4227EOS5File:: add_ignored_info_attrs(bool is_grp,bool is_first) {
4228
4229}
4230void
4231EOS5File:: add_ignored_info_objs(bool is_dim_related, bool is_first) {
4232
4233}
4234#endif
4235
This class specifies the core engineering of mapping HDF5 to DAP by following CF.
#define throw1(a1)
The followings are convenient functions to throw exceptions with different.
Definition: HDF5CF.h:128
include the entry functions to execute the handlers
This class represents one attribute.
Definition: HDF5CF.h:189
This class repersents one dimension of an HDF5 dataset(variable).
Definition: HDF5CF.h:145
This class simulates an HDF-EOS5 Grid. Currently only geographic projection is supported.
Definition: HDF5CF.h:1082
This class simulates an HDF-EOS5 Swath.
Definition: HDF5CF.h:1140
This class simulates an HDF-EOS5 Zonal average object.
Definition: HDF5CF.h:1174
This class is a derived class of CVar. It represents a coordinate variable for HDF-EOS5 files.
Definition: HDF5CF.h:450
void Add_EOS5File_Info(HE5Parser *, bool)
Add HDF-EOS5 dimension and coordinate variable related info. to EOS5Grid,EOS5Swath etc.
Definition: HDFEOS5CF.cc:841
virtual void Handle_Grid_Mapping_Vars()
Handle Grid Mapping Vars.
Definition: HDFEOS5CF.cc:4198
void Set_COARDS_Status()
Set COARDS flag.
Definition: HDFEOS5CF.cc:3384
virtual void Handle_Unsupported_Dtype(bool)
Handle unsupported HDF5 datatypes for HDF-EOS5 products.
Definition: HDFEOS5CF.cc:207
void Adjust_Var_Dim_NewName_Before_Flattening()
Adjust variable dimension names before the flattening for HDF-EOS5 files.
Definition: HDFEOS5CF.cc:3034
void Adjust_Attr_Info()
Adjust the attribute info for HDF-EOS5 products.
Definition: HDFEOS5CF.cc:3407
virtual void Handle_SpVar_DMR()
Handle special variables and attributes for HDF-EOS5 files(for DMR)
Definition: HDFEOS5CF.cc:4134
void Handle_Obj_NameClashing(bool)
Handle the object name clashing for HDF-EOS5 products.
Definition: HDFEOS5CF.cc:3234
virtual void Retrieve_H5_CVar_Supported_Attr_Values()
Retrieve coordinate variable attributes.
Definition: HDFEOS5CF.cc:168
virtual bool Have_Grid_Mapping_Attrs()
Check if having Grid Mapping Attrs.
Definition: HDFEOS5CF.cc:4195
virtual void Adjust_Obj_Name()
This method is a no-op operation. Leave here since the method in the base class is pure virtual.
Definition: HDFEOS5CF.cc:4190
virtual void Handle_SpVar()
Handle special variables for HDF-EOS5 files.
Definition: HDFEOS5CF.cc:3975
virtual void Retrieve_H5_Info(const char *path, hid_t file_id, bool include_attr)
Retrieve DDS information from the HDF5 file; a real implementation for HDF-EOS5 products.
Definition: HDFEOS5CF.cc:161
virtual void Handle_DimNameClashing()
Definition: HDFEOS5CF.cc:3319
virtual void Handle_CVar()
Handle coordinate variable for HDF-EOS5 files.
Definition: HDFEOS5CF.cc:1768
virtual void Handle_SpVar_Attr()
Handle special variables for HDF-EOS5 files.
Definition: HDFEOS5CF.cc:4096
virtual void Retrieve_H5_Supported_Attr_Values()
Retrieve attribute values for the supported HDF5 datatypes for HDF-EOS5 products.
Definition: HDFEOS5CF.cc:184
virtual void Handle_Coor_Attr()
Handle the coordinates attribute for HDF-EOS5 products.
Definition: HDFEOS5CF.cc:3761
void Adjust_Var_NewName_After_Parsing()
Adjust variable names for HDF-EOS5 files.
Definition: HDFEOS5CF.cc:1228
virtual void Add_Supplement_Attrs(bool)
Add the supplemental attributes for HDF-EOS5 products.
Definition: HDFEOS5CF.cc:3670
void Add_Dim_Name(HE5Parser *)
Add the dimension name for HDF-EOS5 files.
Definition: HDFEOS5CF.cc:1320
virtual void Handle_Unsupported_Others(bool)
Handle other unmapped objects/attributes for HDF-EOS5 products.
Definition: HDFEOS5CF.cc:360
virtual void Flatten_Obj_Name(bool include_attr)
Flatten the object name for HDF-EOS5 files.
Definition: HDFEOS5CF.cc:3212
virtual void Adjust_Dim_Name()
Adjust the dimension name for HDF-EOS5 products.
Definition: HDFEOS5CF.cc:3640
virtual void Handle_Unsupported_Dspace(bool)
Handle unsupported HDF5 dataspaces for HDF-EOS5 products.
Definition: HDFEOS5CF.cc:301
void Check_Aura_Product_Status()
Check if the HDF-EOS5 file is an Aura file. Special CF operations need to be used.
Definition: HDFEOS5CF.cc:1716
virtual void Adjust_EOS5Dim_Info(HE5Parser *strmeta_info)
Adjust HDF-EOS5 dimension information.
Definition: HDFEOS5CF.cc:539
std::vector< Group * > groups
Non-root group vectors.
Definition: HDF5CF.h:816
virtual void Handle_Unsupported_Dspace(bool)
Handle unsupported HDF5 dataspaces for datasets.
Definition: HDF5CF.cc:1275
virtual void Handle_Grid_Mapping_Vars()
Handle Grid Mapping Vars.
Definition: HDF5CF.cc:2151
virtual void Retrieve_H5_Supported_Attr_Values()
Retrieve attribute values for the supported HDF5 datatypes.
Definition: HDF5CF.cc:729
std::vector< Var * > vars
Var vectors.
Definition: HDF5CF.h:810
virtual void Add_Supplement_Attrs(bool)
Add supplemental attributes such as fullpath and original name.
Definition: HDF5CF.cc:1970
virtual void Retrieve_H5_Info(const char *path, hid_t file_id, bool)
Definition: HDF5CF.cc:171
std::vector< Attribute * > root_attrs
Root attribute vectors.
Definition: HDF5CF.h:813
virtual void Handle_Unsupported_Dtype(bool)
Handle unsupported HDF5 datatypes.
Definition: HDF5CF.cc:918
virtual void Flatten_Obj_Name(bool)
Flatten the object name.
Definition: HDF5CF.cc:1372
virtual bool Have_Grid_Mapping_Attrs()
Check if having Grid Mapping Attrs.
Definition: HDF5CF.cc:2131
This class represents an HDF5 group. The group will be flattened according to the CF conventions.
Definition: HDF5CF.h:552
This class represents one HDF5 dataset(CF variable)
Definition: HDF5CF.h:259
Helper functions for generating DAS attributes and a function to check BES Key.
Definition: HE5Dim.h:7
double point_right
The rightmost coordinate value of a Grid.
Definition: HE5Grid.h:25
double point_upper
The top coordinate value of a Grid.
Definition: HE5Grid.h:21
double point_left
The leftmost coordinate value of a Grid.
Definition: HE5Grid.h:23
double point_lower
The bottom coordinate value of a Grid.
Definition: HE5Grid.h:19
Definition: HE5Var.h:8
Definition: HE5Za.h:6