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