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