source: XIOS/trunk/src/io/inetcdf4.cpp @ 2342

Last change on this file since 2342 was 2280, checked in by ymipsl, 3 years ago

Improve file reading reading

  • add_offset and scaling_factor attributes are set when present in reading file
  • Add new attribute for axis to scale axis_value when read from file : convert_from_factor
  • fix bugs when time dimension in reading file is not unlimited

YM

  • Property copyright set to
    Software name : XIOS (Xml I/O Server)
    http://forge.ipsl.jussieu.fr/ioserver
    Creation date : January 2009
    Licence : CeCCIL version2
    see license file in root directory : Licence_CeCILL_V2-en.txt
    or http://www.cecill.info/licences/Licence_CeCILL_V2-en.html
    Holder : CEA/LSCE (Laboratoire des Sciences du CLimat et de l'Environnement)
    CNRS/IPSL (Institut Pierre Simon Laplace)
    Project Manager : Yann Meurdesoif
    yann.meurdesoif@cea.fr
File size: 28.9 KB
RevLine 
[219]1#include "inetcdf4.hpp"
[599]2#include "netCdfInterface.hpp"
[782]3#include "netCdf_cf_constant.hpp"
[219]4
5#include <boost/algorithm/string.hpp>
6
[335]7namespace xios
[219]8{
[1639]9  CINetCDF4::CINetCDF4(const StdString& filename, const MPI_Comm* comm /*= NULL*/, bool multifile /*= true*/,
[1485]10                       bool readMetaDataPar /*= false*/, const StdString& timeCounterName /*= "time_counter"*/)
[599]11  {
[736]12    // Don't use parallel mode if there is only one process
13    if (comm)
[599]14    {
[736]15      int commSize = 0;
[1639]16      MPI_Comm_size(*comm, &commSize);
[736]17      if (commSize <= 1)
18        comm = NULL;
[599]19    }
[1485]20    mpi = comm && !multifile && readMetaDataPar;
[736]21
22    // The file format will be detected automatically by NetCDF, it is safe to always set NC_MPIIO
23    // even if Parallel NetCDF ends up being used.
24    if (mpi)
[1639]25      CNetCdfInterface::openPar(filename, NC_NOWRITE | NC_MPIIO, *comm, MPI_INFO_NULL, this->ncidp);
[736]26    else
27      CNetCdfInterface::open(filename, NC_NOWRITE, this->ncidp);
[802]28
29    this->timeCounterName = timeCounterName;
[2280]30
[811]31    if (!CNetCdfInterface::isDimExisted(this->ncidp, this->timeCounterName)) this->timeCounterName=this->getUnlimitedDimensionName() ;
[825]32
[599]33  }
[219]34
[599]35  CINetCDF4::~CINetCDF4(void)
36  { /* Nothing to do */ }
[219]37
[599]38  //---------------------------------------------------------------
[219]39
[599]40  void CINetCDF4::close(void)
41  {
[686]42    CNetCdfInterface::close(this->ncidp);
[599]43  }
[219]44
[599]45  //---------------------------------------------------------------
[219]46
[599]47  int CINetCDF4::getGroup(const CVarPath* const path)
48  {
49    int retvalue = this->ncidp;
50    if (path == NULL) return retvalue;
51    CVarPath::const_iterator it = path->begin(), end = path->end();
[219]52
[599]53    for (; it != end; it++)
54    {
55      const StdString& groupid = *it;
[686]56      CNetCdfInterface::inqNcId(retvalue, groupid, retvalue);
[599]57    }
[219]58
[599]59    return retvalue;
60  }
[219]61
[599]62  int CINetCDF4::getVariable(const StdString& varname,
63                             const CVarPath* const path)
64  {
65    int varid = 0;
66    int grpid = this->getGroup(path);
[825]67    if (this->hasVariable(varname, path))
68      CNetCdfInterface::inqVarId(grpid, varname, varid);
[599]69    return varid;
70  }
[219]71
[599]72  int CINetCDF4::getDimension(const StdString& dimname,
73                              const CVarPath* const path)
74  {
75    int dimid = 0;
76    int grpid = this->getGroup(path);
[686]77    CNetCdfInterface::inqDimId(grpid, dimname, dimid);
[599]78    return dimid;
79  }
[219]80
[599]81  std::pair<nc_type, StdSize> CINetCDF4::getAttribute(const StdString& attname,
82                                                      const StdString* const var,
83                                                      const CVarPath* const path)
84  {
85    std::pair<nc_type, StdSize> retvalue;
86    int grpid = this->getGroup(path);
[1447]87    int varid = (var != NULL && this->hasVariable(*var, path)) ? this->getVariable(*var, path) : NC_GLOBAL;
[686]88    CNetCdfInterface::inqAtt(grpid, varid, attname, retvalue.first, retvalue.second);
[599]89    return retvalue;
90  }
[219]91
[2280]92 
93  bool CINetCDF4::hasUnlimitedDimension(const CVarPath* const path)
94  {
95    int dimid = 0;
96    int grpid = this->getGroup(path);
97    CNetCdfInterface::inqUnLimDim(grpid, dimid);
98    if (dimid==-1) return false ;
99    else return true ;
100  }
101
[599]102  int CINetCDF4::getUnlimitedDimension(const CVarPath* const path)
103  {
104    int dimid = 0;
105    int grpid = this->getGroup(path);
[686]106    CNetCdfInterface::inqUnLimDim(grpid, dimid);
[599]107    return dimid;
108  }
[219]109
[599]110  StdString CINetCDF4::getUnlimitedDimensionName(const CVarPath* const path)
111  {
112    int grpid = this->getGroup(path);
113    int dimid = this->getUnlimitedDimension(path);
[219]114
[686]115    StdString dimname;
116    if (dimid != -1)
117      CNetCdfInterface::inqDimName(grpid, dimid, dimname);
[599]118    return dimname;
119  }
[219]120
[599]121  //---------------------------------------------------------------
[686]122
[599]123  StdSize CINetCDF4::getNbVertex(const StdString& name,
124                                 const CVarPath* const path)
125  {
[219]126
[599]127    if (this->isRectilinear(name, path) ||
128       this->isCurvilinear(name, path))
129    {
130      if (this->is3Dim(name, path)) return 8;
131      else return 4;
132    }
133    if (this->isUnstructured(name, path))
134    {
135      StdString bound = this->getBoundsId
136            (this->getCoordinatesIdList(name, path).back(), path);
137      StdString dim = this->getDimensionsList(&bound, path).back();
[686]138      return this->getDimensions(&bound, path)[dim];
[599]139    }
140    return size_t(-1);
141  }
[219]142
[599]143  //---------------------------------------------------------------
[219]144
[599]145  std::list<StdString> CINetCDF4::getGroups(const CVarPath* const path)
146  {
147    int nbgroup = 0, *groupid = NULL;
148    int grpid = this->getGroup(path);
149    std::list<StdString> retvalue;
[219]150
[686]151    CNetCdfInterface::inqGrpIds(grpid, nbgroup, NULL);
[599]152    groupid = new int[nbgroup]();
[686]153    CNetCdfInterface::inqGrpIds(grpid, nbgroup, groupid);
[219]154
[599]155    for (int i = 0; i < nbgroup; i++)
156    {
[686]157      StdString fullGrpName;
158      CNetCdfInterface::inqGrpFullName(groupid[i], fullGrpName);
159      retvalue.push_back(fullGrpName);
[599]160    }
[219]161
[599]162    delete [] groupid;
163    return retvalue;
164  }
[219]165
[599]166  std::list<StdString> CINetCDF4::getVariables(const CVarPath* const path)
167  {
168    int nbvar = 0, *varid = NULL;
169    int grpid = this->getGroup(path);
170    std::list<StdString> retvalue;
[219]171
[686]172    CNetCdfInterface::inqVarIds(grpid, nbvar, NULL);
[599]173    varid = new int[nbvar]();
[686]174    CNetCdfInterface::inqVarIds(grpid, nbvar, varid);
[219]175
[599]176    for (int i = 0; i < nbvar; i++)
177    {
[686]178      StdString varName;
179      CNetCdfInterface::inqVarName(grpid, varid[i], varName);
180      retvalue.push_back(varName);
[599]181    }
182
183    delete [] varid;
184    return retvalue;
185  }
186
187  std::set<StdString> CINetCDF4::getBoundVariables(const CVarPath* const path)
188  {
189    std::set<StdString> retvalue;
190    std::list<StdString> variables = this->getVariables(path);
191    std::list<StdString>::const_iterator it = variables.begin(), end = variables.end();
192    for (; it != end; it++)
193    {
194      const StdString& var = *it;
195      if (this->hasBounds(var, path))
196        retvalue.insert(retvalue.end(), this->getBoundsId(var, path));
197    }
198    return retvalue;
199  }
200
201  std::set<StdString> CINetCDF4::getCoordVariables(const CVarPath* const path)
202  {
203    std::set<StdString> retvalue;
204    std::list<StdString> variables = this->getVariables(path);
205    std::list<StdString>::const_iterator it = variables.begin(), end = variables.end();
206    for (; it != end; it++)
207    {
208      const StdString& var = *it;
209      std::list<StdString> coords = this->getCoordinatesIdList(var, path);
210      std::list<StdString>::const_iterator it = coords.begin(), end = coords.end();
211      for (; it != end; it++)
[219]212      {
[599]213        const StdString& coord = *it;
214        if (this->hasVariable(coord, path))
215          retvalue.insert(retvalue.end(), coord);
[219]216      }
[599]217    }
218    return retvalue;
219  }
[219]220
[599]221  std::list<StdString> CINetCDF4::getDimensionsList(const StdString* const var, const CVarPath* const path)
222  {
223    int nbdim = 0, *dimid = NULL;
224    int grpid = this->getGroup(path);
[1447]225    int varid = (var != NULL && this->hasVariable(*var, path)) ? this->getVariable(*var, path) : NC_GLOBAL;
[599]226    std::list<StdString> retvalue;
[219]227
[1447]228    if (var != NULL && this->hasVariable(*var, path))
[599]229    {
[686]230      CNetCdfInterface::inqVarNDims(grpid, varid, nbdim);
[599]231      dimid = new int[nbdim]();
[686]232      CNetCdfInterface::inqVarDimId(grpid, varid, dimid);
[599]233    }
234    else
235    {
[686]236      CNetCdfInterface::inqDimIds(grpid, nbdim, NULL, 1);
[599]237      dimid = new int[nbdim]();
[686]238      CNetCdfInterface::inqDimIds(grpid, nbdim, dimid, 1);
[599]239    }
[219]240
[599]241    for (int i = 0; i < nbdim; i++)
242    {
[686]243      std::string dimname;
244      CNetCdfInterface::inqDimName(grpid, dimid[i], dimname);
[599]245      retvalue.push_back(dimname);
246    }
247    delete [] dimid;
[219]248
[599]249    return retvalue;
250  }
[219]251
[599]252  std::map<StdString, StdSize> CINetCDF4::getDimensions(const StdString* const var, const CVarPath* const path)
253  {
254    int nbdim = 0, *dimid = NULL;
255    int grpid = this->getGroup(path);
[1447]256    int varid = (var != NULL && this->hasVariable(*var, path)) ? this->getVariable(*var, path) : NC_GLOBAL;
[599]257    std::map<StdString, StdSize> retvalue;
[219]258
[1447]259    if (var != NULL && this->hasVariable(*var, path))
[599]260    {
[686]261      CNetCdfInterface::inqVarNDims(grpid, varid, nbdim);
[599]262      dimid = new int[nbdim]();
[686]263      CNetCdfInterface::inqVarDimId(grpid, varid, dimid);
[599]264    }
265    else
266    {
[686]267      CNetCdfInterface::inqDimIds(grpid, nbdim, NULL, 1);
[599]268      dimid = new int[nbdim]();
[686]269      CNetCdfInterface::inqDimIds(grpid, nbdim, dimid, 1);
[599]270    }
[219]271
[599]272    for (int i = 0; i < nbdim; i++)
273    {
[686]274      std::string dimname;
275      CNetCdfInterface::inqDimName(grpid, dimid[i], dimname);
276      StdSize size = 0;
277      CNetCdfInterface::inqDimLen(grpid, dimid[i], size);
[219]278
[599]279      retvalue.insert(retvalue.end(), std::make_pair(dimname, size));
280    }
281    delete [] dimid;
[219]282
[599]283    return retvalue;
284  }
[219]285
[686]286  std::list<StdString> CINetCDF4::getAttributes(const StdString* const var, const CVarPath* const path)
[599]287  {
288    int nbatt = 0;
289    std::list<StdString> retvalue;
290    int grpid = this->getGroup(path);
[1447]291    int varid = (var != NULL && this->hasVariable(*var, path)) ? this->getVariable(*var, path) : NC_GLOBAL;
[219]292
[1447]293    if (var != NULL && this->hasVariable(*var, path))
[686]294      CNetCdfInterface::inqVarNAtts(grpid, varid, nbatt);
[599]295    else
[686]296      CNetCdfInterface::inqNAtts(grpid, nbatt);
[219]297
[599]298    for (int i = 0; i < nbatt; i++)
299    {
[686]300      StdString attname;
301      CNetCdfInterface::inqAttName(grpid, varid, i, attname);
[599]302      retvalue.push_back(attname);
303    }
304    return retvalue;
305  }
[219]306
[599]307  int CINetCDF4::getAttributeId(const StdString& name,
308                                const StdString* const var,
309                                const CVarPath* const path)
310  {
311    int retvalue = 0;
312    std::list<StdString> atts = this->getAttributes(var, path);
313    std::list<StdString>::const_iterator it = atts.begin(), end = atts.end();
314    for (; it != end; it++)
315    {
316      const StdString& attname = *it;
[782]317      if (attname.compare(0, name.size(), name) == 0)
[599]318        return retvalue;
319      retvalue++;
320    }
321    return -1;
322  }
[219]323
[599]324  //---------------------------------------------------------------
[219]325
[599]326  bool CINetCDF4::hasMissingValue(const StdString& name,
327                                  const CVarPath* const path)
328  {
[686]329    return (this->hasAttribute("missing_value", &name, path) || this->hasAttribute("_FillValue", &name, path));
[599]330  }
[219]331
[599]332  bool CINetCDF4::hasAttribute(const StdString& name,
333                               const StdString* const var ,
334                               const CVarPath* const path)
335  {
336    std::list<StdString> atts = this->getAttributes(var, path);
337    std::list<StdString>::const_iterator it = atts.begin(), end = atts.end();
338    for (; it != end; it++)
339    {
340      const StdString& attname = *it;
[782]341      if (attname.compare(0, name.size(), name) == 0) return true;
[599]342    }
343    return false;
344  }
[219]345
[2280]346  template <class T>
347  bool CINetCDF4::hasAttribute(const StdString& name, const StdString* const var, const CVarPath* const path)
348  {
349    std::list<StdString> atts = this->getAttributes(var, path);
350    std::list<StdString>::const_iterator it = atts.begin(), end = atts.end();
351    for (; it != end; it++)
352    {
353      const StdString& attname = *it;
354      if (attname.compare(0, name.size(), name) == 0)
355      { 
356        std::pair<nc_type , StdSize> attinfos = this->getAttribute(name, var, path);
357        std::vector<T> retvalue(attinfos.second);
358        nc_type type = CNetCdfInterface::getNcType<T>();
359        if (attinfos.first == type) return true;
360        else return false ;
361      }
362    }
363    return false;
364  }
365 
366  template bool  CINetCDF4::hasAttribute<double>(const StdString& name, const StdString* const var, const CVarPath* const path);
367  template bool  CINetCDF4::hasAttribute<float>(const StdString& name, const StdString* const var, const CVarPath* const path);
368  template bool  CINetCDF4::hasAttribute<int>(const StdString& name, const StdString* const var, const CVarPath* const path);
369  template bool  CINetCDF4::hasAttribute<char>(const StdString& name, const StdString* const var, const CVarPath* const path);
370 
371
[599]372  bool CINetCDF4::hasVariable(const StdString& name,
373                              const CVarPath* const path)
374  {
375    std::list<StdString> variables = this->getVariables(path);
376    std::list<StdString>::const_iterator it = variables.begin(), end = variables.end();
377    for (; it != end; it++)
378    {
379      const StdString& varname = *it;
[825]380      if ((varname.compare(0, name.size(), name) == 0) && (0 != name.size()))  return true;
[599]381    }
382    return false;
383  }
[219]384
[599]385  bool CINetCDF4::hasCoordinates(const StdString& name,
386                                 const CVarPath* const path)
387  {
[782]388    return this->hasAttribute(CCFKeywords::XIOS_CF_coordinates, &name, path);
[599]389  }
[219]390
[599]391  bool CINetCDF4::hasBounds(const StdString& name,
392                            const CVarPath* const path)
393  {
[782]394    return this->hasAttribute(CCFKeywords::XIOS_CF_bounds, &name, path);
[599]395  }
[219]396
[599]397  bool CINetCDF4::hasTemporalDim(const CVarPath* const path)
398  {
[802]399    std::list<StdString> dims = this->getDimensionsList(NULL, path);
400    return (std::find(dims.begin(), dims.end(), timeCounterName) != dims.end());
[599]401  }
[219]402
[599]403  //---------------------------------------------------------------
[219]404
[686]405  template <class T>
406  std::vector<T> CINetCDF4::getAttributeValue(const StdString& name,
407                                              const StdString* const var,
408                                              const CVarPath* const path)
409  {
410    int grpid = this->getGroup(path);
[1447]411    int varid = (var != NULL && this->hasVariable(*var, path)) ? this->getVariable(*var, path) : NC_GLOBAL;
[686]412    std::pair<nc_type , StdSize> attinfos = this->getAttribute(name, var, path);
413    std::vector<T> retvalue(attinfos.second);
414    nc_type type = CNetCdfInterface::getNcType<T>();
415    if (attinfos.first != type)
416      ERROR("CINetCDF4::getAttributeValue<T>(name, var, path)",
417            << "[ name : " << name
418            << ", type requested :" << attinfos.first
419            << ", type stored : " << type << "]"
420            << " Invalid type !");
421    CNetCdfInterface::getAttType(grpid, varid, name.c_str(), &retvalue[0]);
422    return retvalue;
[599]423  }
[219]424
[686]425  template std::vector<double> CINetCDF4::getAttributeValue(const StdString& name,
426                                                            const StdString* const var,
427                                                            const CVarPath* const path);
428  template std::vector<float> CINetCDF4::getAttributeValue(const StdString& name,
429                                                           const StdString* const var,
430                                                           const CVarPath* const path);
431  template std::vector<int> CINetCDF4::getAttributeValue(const StdString& name,
432                                                         const StdString* const var,
433                                                         const CVarPath* const path);
434  template std::vector<char> CINetCDF4::getAttributeValue(const StdString& name,
435                                                          const StdString* const var,
436                                                          const CVarPath* const path);
[219]437
[599]438  StdString CINetCDF4::getAttributeValue(const StdString& name,
439                                         const StdString* const var,
440                                         const CVarPath* const path)
441  {
[686]442    std::vector<char> data = this->getAttributeValue<char>(name, var, path);
[219]443
[686]444    return StdString(data.begin(), data.end());
[599]445  }
[219]446
[686]447  template <class T>
448  T CINetCDF4::getMissingValue(const StdString& name, const CVarPath* const path)
[599]449  {
450    if (this->hasAttribute("missing_value", &name, path))
[686]451      return this->getAttributeValue<T>("missing_value", &name, path)[0];
[599]452    if (this->hasAttribute("_FillValue", &name, path))
[686]453      return this->getAttributeValue<T>("_FillValue", &name, path)[0];
[599]454    return 0;
455  }
[219]456
[686]457  template double CINetCDF4::getMissingValue(const StdString& name, const CVarPath* const path);
458  template float CINetCDF4::getMissingValue(const StdString& name, const CVarPath* const path);
459  template int CINetCDF4::getMissingValue(const StdString& name, const CVarPath* const path);
460  template char CINetCDF4::getMissingValue(const StdString& name, const CVarPath* const path);
[219]461
[599]462  //---------------------------------------------------------------
[219]463
[599]464  std::list<StdString> CINetCDF4::getCoordinatesIdList(const StdString& name, const CVarPath* const path)
465  {
466    std::list<StdString> retvalue;
467    StdString value = this->getCoordinatesId(name, path);
[219]468
[599]469    boost::split(retvalue, value, boost::is_any_of(" "));
[219]470
[599]471    std::list<StdString>::iterator it = retvalue.begin(), end = retvalue.end();
472    for (; it != end; it++)
473    {
474      StdString& coord = *it;
475      coord.assign(coord.data());
476    }
477    return retvalue;
478  }
[219]479
[599]480  StdString CINetCDF4::getCoordinatesId(const StdString& name, const CVarPath* const path)
481  {
482    StdString retvalue;
[782]483    if (this->hasAttribute(CCFKeywords::XIOS_CF_coordinates, &name, path))
[599]484    {
[782]485      return this->getAttributeValue(CCFKeywords::XIOS_CF_coordinates, &name, path);
[599]486    }
487    else
488    {
489      std::list<StdString> dims = this->getDimensionsList(&name, path);
490      std::list<StdString>::const_iterator it = dims.begin(), end = dims.end();
491      for (; it != end; it++)
[219]492      {
[599]493        const StdString& value = *it;
494        retvalue.append(value).push_back(' ');
[219]495      }
[599]496      retvalue.erase(retvalue.end() - 1) ;
497    }
[219]498
[599]499    return retvalue;
500  }
501
502  StdString CINetCDF4::getBoundsId(const StdString& name,
503                                   const CVarPath* const path)
504  {
505    StdString retvalue;
[782]506    if (this->hasAttribute(CCFKeywords::XIOS_CF_bounds, &name, path))
507      retvalue = this->getAttributeValue(CCFKeywords::XIOS_CF_bounds, &name, path);
[599]508    return retvalue;
509  }
510
511  //---------------------------------------------------------------
512
513  bool CINetCDF4::isBound(const StdString& name,
514                          const CVarPath* const path)
515  {
516    std::set<StdString> bounds = this->getBoundVariables(path);
517    return (bounds.find(name) != bounds.end());
518  }
519
520  bool CINetCDF4::isCoordinate(const StdString& name,
521                               const CVarPath* const path)
522  {
523    std::set<StdString> coords = this->getCoordVariables(path);
524    return (coords.find(name) != coords.end());
525  }
526
527  bool CINetCDF4::isRectilinear(const StdString& name, const CVarPath* const path)
528  {
[1447]529    std::list<StdString> varCoords = this->getCoordinatesIdList(name, path);
530    std::list<StdString> varDims = this->getDimensionsList(&name, path);
531    std::list<StdString>::const_iterator it = varCoords.begin(), end = varCoords.end();
532    std::set<StdString> varDims1D;
[1432]533
[1447]534    // Firstly, loop over coordinate list
[599]535    for (; it != end; it++)
536    {
537      const StdString& coord = *it;
[1447]538      if (this->hasVariable(coord, path) && !this->isTemporal(coord, path) )
[219]539      {
[1447]540        std::map<StdString, StdSize> coordDims = this->getDimensions(&coord, path);
541        for (std::map<StdString, StdSize>::const_iterator itTmp = coordDims.begin(); itTmp != coordDims.end(); itTmp++)
[1432]542        {
[1447]543          varDims.remove(itTmp->first);
544        }
545        if (this->isLonOrLat(coord, path) && coordDims.size() == 1)
546        {
547          varDims1D.insert(coordDims.begin()->first);
[1445]548          continue;
[1432]549        }
[219]550      }
[599]551    }
[1447]552    // Secondly, loop over remaining dimensions
553    for (it= varDims.begin(); it != varDims.end(); it++)
554    {
555      const StdString& coord = *it;
556      std::map<StdString, StdSize> coordDims = this->getDimensions(&coord, path);
557      if (this->hasVariable(coord, path) && !this->isTemporal(coord, path) )
558      {
559        if (this->isLonOrLat(coord, path) && coordDims.size() == 1)
560        {
561          varDims1D.insert(coordDims.begin()->first);
562          continue;
563        }
564      }
565    }
566
567    return (varDims1D.size() == 2);
[599]568  }
[219]569
[599]570  bool CINetCDF4::isCurvilinear(const StdString& name, const CVarPath* const path)
571  {
572    if (this->isRectilinear(name, path) || !this->hasCoordinates(name, path))
573      return false;
574
[782]575    bool isCurVi = true;
576    unsigned int nbLonLat = 0;
[599]577    std::list<StdString> coords = this->getCoordinatesIdList(name, path);
578    std::list<StdString>::const_iterator it = coords.begin(), end = coords.end();
579    for (; it != end; it++)
580    {
581      const StdString& coord = *it;
[1445]582      if (this->hasVariable(coord, path) && !this->isTemporal(coord, path) && this->isLonOrLat(coord, path))
[219]583      {
[599]584        std::map<StdString, StdSize> dimvar = this->getDimensions(&coord, path);
[782]585        if (2 == dimvar.size()) ++nbLonLat;
[219]586      }
[599]587    }
[782]588    if (2 != nbLonLat) isCurVi = false;
589
590    return isCurVi;
[599]591  }
[219]592
[599]593  bool CINetCDF4::isUnstructured(const StdString& name, const CVarPath* const path)
594  {
595    if (this->isRectilinear(name, path) ||
596        this->isCurvilinear(name, path) ||
597        !this->hasCoordinates(name, path))
598       return false;
[948]599    else return true ;
600   
601// check this part above   
[599]602    StdString dimname = this->getDimensionsList(&name, path).back();
[219]603
[599]604    std::list<StdString> coords = this->getCoordinatesIdList(name, path);
605    std::list<StdString>::const_iterator it = coords.begin(), end = coords.end();
606    for (; it != end; it++)
607    {
608      const StdString& coord = *it;
[1445]609      if (this->hasVariable(coord, path) && !this->isTemporal(coord, path) && this->isLonOrLat(coord, path))
[219]610      {
[599]611        std::map<StdString, StdSize> dimvar = this->getDimensions(&coord, path);
612        if ((dimvar.size() == 1) &&
613            (dimvar.find(dimname) != dimvar.end()))
614          continue;
615        else
616          return false;
617      }
618    }
[219]619
[599]620    return true;
621  }
[219]622
[599]623  bool CINetCDF4::isUnknown(const StdString& name, const CVarPath* const path)
624  {
625    return !(this->isRectilinear(name, path) || this->isCurvilinear(name, path) || this->isUnstructured(name, path));
626  }
[219]627
[599]628  bool CINetCDF4::isTemporal(const StdString& name, const CVarPath* const path)
629  {
[802]630    std::list<StdString> dims = this->getDimensionsList(&name, path);
631    return (std::find(dims.begin(), dims.end(), timeCounterName) != dims.end());
[599]632  }
[219]633
[599]634  bool CINetCDF4::is3Dim(const StdString& name, const CVarPath* const path)
635  {
636    int i = 0;
637    std::list<StdString> coords = this->getCoordinatesIdList(name, path);
638    std::list<StdString>::const_iterator it = coords.begin(), end = coords.end();
639    for (; it != end; it++)
640    {
641      const StdString& coord = *it;
642      if (this->hasVariable(coord, path))
[219]643      {
[599]644        if (this->isTemporal(coord, path))
645          continue;
646        i++;
[219]647      }
[599]648      else
[219]649      {
[782]650        StdString unlimitedDimName = this->getUnlimitedDimensionName();
651        if (coord.compare(0, unlimitedDimName.size(), unlimitedDimName) == 0)
[599]652          continue;
653        i++;
[219]654      }
[599]655    }
656    return (i == 3);
657  }
[219]658
[599]659  bool CINetCDF4::isCellGrid(const StdString& name, const CVarPath* const path)
660  {
661    if (this->isCoordinate(name, path))
662    {
[686]663      return this->hasBounds(name, path);
[599]664    }
665    else
666    {
667      std::list<StdString> coords = this->getCoordinatesIdList(name, path);
668      std::list<StdString>::const_iterator it = coords.begin(), end = coords.end();
669      for (; it != end; it++)
[219]670      {
[599]671        const StdString& coord = *it;
672        if (this->hasVariable(coord, path))
673        {
674          if (this->isTemporal(coord, path))
675            continue;
676          if (this->isCellGrid(coord, path))
677            continue;
678          return false;
679        }
680        else
681        {
[782]682          StdString unlimitedDimName = this->getUnlimitedDimensionName();
683          if (coord.compare(0, unlimitedDimName.size(), unlimitedDimName) == 0)
[599]684            continue;
685          return false;
686        }
[219]687      }
[599]688    }
[219]689
[599]690    return true;
691  }
[219]692
[599]693  //---------------------------------------------------------------
[219]694
[599]695  std::list<StdString> CINetCDF4::getDataVariables(bool _is3D,       bool _isRecti,
696                                                   bool _isCurvi,    bool _isUnstr,
697                                                   bool _isCellData, bool _isTemporal,
698                                                   const CVarPath* const path)
699  {
700    std::list<StdString> retvalue;
701    std::list<StdString> allvars  = this->getVariables(path);
702    std::set<StdString> allcoords = this->getCoordVariables(path);
[219]703
[599]704    std::list<StdString>::const_iterator it = allvars.begin(), end = allvars.end();
705    for (; it != end; it++)
706    {
707      const StdString& var = *it;
708      if (this->isCoordinate(var, path)) continue;
[219]709
[599]710      if (!_isRecti && this->isRectilinear(var, path))  continue;
711      if (!_isCurvi && this->isCurvilinear(var, path))  continue;
712      if (!_isUnstr && this->isUnstructured(var, path)) continue;
[219]713
[599]714      if (!_isTemporal && this->isTemporal(var, path)) continue;
715      if (!_is3D       && this->is3Dim(var, path))     continue;
716      if (!_isCellData && this->isCellGrid(var, path)) continue;
[219]717
[599]718      if (this->isUnknown(var, path)) continue;
[219]719
[599]720      retvalue.push_back(var);
721    }
722    return retvalue;
723  }
[219]724
[599]725  //---------------------------------------------------------------
[219]726
[599]727  void CINetCDF4::getDataInfo(const StdString& var, const CVarPath* const path, StdSize record,
728                              std::vector<StdSize>& sstart, std::vector<StdSize>& scount, StdSize& array_size,
729                              const std::vector<StdSize>* start /*= NULL*/, const std::vector<StdSize>* count /*= NULL*/)
730  {
731    std::list<StdString> dimlist = this->getDimensionsList(&var, path);
732    std::map<StdString, StdSize> dimmap = this->getDimensions(&var, path);
733    std::list<StdString>::iterator it = dimlist.begin();
734    if (this->isTemporal(var, path))
735    {
736      if (record != UNLIMITED_DIM)
737        sstart.push_back(record);
738      else
739        sstart.push_back(0);
740      scount.push_back(1);
741      it++;
742    }
743    for (int i = 0; it != dimlist.end(); it++, i++)
744    {
745      if (start && count)
[219]746      {
[599]747        sstart.push_back((*start)[i]);
748        scount.push_back((*count)[i]);
749        array_size *= (*count)[i];
[219]750      }
[599]751      else
[219]752      {
[599]753        sstart.push_back(0);
754        scount.push_back(dimmap[*it]);
755        array_size *= dimmap[*it];
[219]756      }
[599]757    }
758  }
[219]759
[686]760  template <class T>
761  void CINetCDF4::getData(CArray<T, 1>& data, const StdString& var,
[599]762                          const CVarPath* const path, StdSize record)
763  {
764    std::vector<StdSize> start, count;
765    int grpid = this->getGroup(path);
766    int varid = this->getVariable(var, path);
767    StdSize array_size = 1;
768    this->getDataInfo(var, path, record, start, count, array_size);
769    data.resize(array_size);
[686]770    CNetCdfInterface::getVaraType(grpid, varid, &start[0], &count[0], data.dataFirst());
[599]771  }
[219]772
[599]773  template <>
[686]774  void CINetCDF4::getData(CArray<int, 1>& data, const StdString& var,
775                          const CVarPath* const path, StdSize record);
776  template <>
[599]777  void CINetCDF4::getData(CArray<double, 1>& data, const StdString& var,
[686]778                          const CVarPath* const path, StdSize record);
[599]779  template <>
780  void CINetCDF4::getData(CArray<float, 1>& data, const StdString& var,
[686]781                          const CVarPath* const path, StdSize record);
[219]782
[599]783  //---------------------------------------------------------------
784
785  StdString CINetCDF4::getLonCoordName(const StdString& varname,
786                                       const CVarPath* const path)
787  {
[825]788    StdString lonName;
[782]789    std::list<StdString>::const_iterator itbList, itList, iteList;
[599]790    std::list<StdString> clist = this->getCoordinatesIdList(varname, path);
[782]791    itbList = clist.begin(); iteList = clist.end();
792    for (itList = itbList; itList != iteList; ++itList)
793    {
794      if (this->hasAttribute(CCFKeywords::XIOS_CF_units, &(*itList), path))
795      {
796        StdString unit = this->getAttributeValue(CCFKeywords::XIOS_CF_units, &(*itList), path);
797        if (CCFConvention::XIOS_CF_Longitude_units.end() != CCFConvention::XIOS_CF_Longitude_units.find(unit))
[825]798        {
799          lonName = *itList;
800          return lonName;
801        }
[782]802      }
803    }
[825]804    return lonName;
[599]805  }
806
807  StdString CINetCDF4::getLatCoordName(const StdString& varname,
808                                       const CVarPath* const path)
809  {
[825]810    StdString latName;
[782]811    std::list<StdString>::const_iterator itbList, itList, iteList;
[599]812    std::list<StdString> clist = this->getCoordinatesIdList(varname, path);
[782]813    itbList = clist.begin(); iteList = clist.end();
814    for (itList = itbList; itList != iteList; ++itList)
815    {
816      if (this->hasAttribute(CCFKeywords::XIOS_CF_units, &(*itList), path))
817      {
818        StdString unit = this->getAttributeValue(CCFKeywords::XIOS_CF_units, &(*itList), path);
819        if (CCFConvention::XIOS_CF_Latitude_units.end() != CCFConvention::XIOS_CF_Latitude_units.find(unit))
[825]820        {
821          latName = *itList;
822          return latName;
823        }
[782]824      }
825    }
[825]826    return latName;
[599]827  }
828
829  StdString CINetCDF4::getVertCoordName(const StdString& varname,
830                                        const CVarPath* const path)
831  {
832    if (!this->is3Dim(varname, path)) return "";
833    std::list<StdString> clist = this->getCoordinatesIdList(varname, path);
834    if (this->hasCoordinates(varname, path))
[686]835      return *(++(++clist.begin()));
[599]836    else
[686]837      return *(++(++clist.rbegin()));
[599]838  }
[1445]839
840  bool CINetCDF4::isLonOrLat(const StdString& varname, const CVarPath* const path)
841  {
[1534]842    if (this->hasAttribute(CCFKeywords::XIOS_CF_units, &varname, path))
843    {
844      StdString unit = this->getAttributeValue(CCFKeywords::XIOS_CF_units, &varname, path);
845      return      (CCFConvention::XIOS_CF_Latitude_units.end() != CCFConvention::XIOS_CF_Latitude_units.find(unit)
846                || CCFConvention::XIOS_CF_Longitude_units.end() != CCFConvention::XIOS_CF_Longitude_units.find(unit));
[1445]847    }
[1534]848    else return false ;
[1445]849  }
850
[335]851} // namespace xios
Note: See TracBrowser for help on using the repository browser.