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