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