source: XMLIO_V2/dev/dev_rv/src4/xmlio/netcdf/inetcdf4_adv.cpp @ 241

Last change on this file since 241 was 241, checked in by hozdoba, 11 years ago
File size: 14.5 KB
Line 
1/* ************************************************************************** *
2 *      Copyright © IPSL/LSCE, XMLIOServer, Avril 2010 - Octobre 2011         *
3 * ************************************************************************** */
4
5/**
6 * \file    inetcdf4_adv.hpp
7 * \brief   Lecture des fichiers de données au format netCDF-4, fonctionnalités avancées (implémentation).
8 * \author  Hervé Ozdoba
9 * \version 0.4
10 * \date    15 Juin 2011
11 */
12
13#ifndef __XIOS_NO_EXTERN
14
15// Boost headers
16#include <boost/algorithm/string.hpp>
17
18#endif // __XIOS_NO_EXTERN
19
20// XMLIOServer headers
21#include "inetcdf4_adv.hpp"
22#include "inetcdf4_adv_impl.hpp"
23
24
25// /////////////////////////////// Définitions ////////////////////////////// //
26
27namespace xmlioserver {
28namespace io {
29   
30   CINetCDF4Adv::CINetCDF4Adv(const std::string & filename)
31        : CINetCDF4(filename)
32   { /* Ne rien faire de plus */ }
33
34   CINetCDF4Adv::~CINetCDF4Adv(void)
35   { /* Ne rien faire de plus */ }
36   
37   bool CINetCDF4Adv::hasAttribute(const std::string & name,
38                                   const std::string * const _varname)
39   {
40      std::vector<std::string > atts = this->getAttributes(_varname);
41      std::vector<std::string >::const_iterator it = atts.begin(), end = atts.end();
42      for (; it != end; it++)
43      {
44         const std::string  & attname = *it;
45         if (attname.compare(name) == 0) return (true);
46      }
47      return (false);
48   }
49   
50   bool CINetCDF4Adv::hasVariable    (const std::string & _varname)
51   {
52       return (SuperClass::varExist(_varname));
53   }
54   
55   bool CINetCDF4Adv::hasMissingValue(const std::string & _varname)
56   {
57      return (this->hasAttribute("missing_value", &_varname) ||
58              this->hasAttribute("_FillValue", &_varname));
59   }
60   
61   bool CINetCDF4Adv::hasCoordinates (const std::string & _varname)
62   {
63      return (this->hasAttribute("coordinates", &_varname));
64   }
65   
66   bool CINetCDF4Adv::hasBounds      (const std::string & _varname)
67   {
68      return (this->hasAttribute("bounds", &_varname));
69   }
70
71   bool CINetCDF4Adv::hasTemporalDim(void)
72   {
73      return (this->getUnlimitedDimension() != -1);
74   }
75
76   bool CINetCDF4Adv::isBound(const std::string & _varname)
77   {
78      std::set<std::string> bounds = this->getBoundVariables();
79      return (bounds.find(_varname) != bounds.end());
80   }
81   
82   bool CINetCDF4Adv::isCoordinate(const std::string & _varname)
83   {
84      std::set<std::string> coords = this->getCoordVariables();
85      return (coords.find(_varname) != coords.end());
86   }
87   
88   bool CINetCDF4Adv::isRectilinear(const std::string & _varname)
89   {
90      std::vector<std::string> coords = this->getCoordinatesIdList(_varname);
91      std::vector<std::string>::const_iterator it = coords.begin(), end = coords.end();
92      for (; it != end; it++)
93      {
94         const std::string & coord = *it;
95         if (this->hasVariable(coord) && !this->isTemporal(coord))
96         {
97            std::map<std::string, std::size_t> dimvar = this->getDimensions(&coord);
98            if ((dimvar.size() == 1) && (dimvar.find(coord) != dimvar.end()))
99               continue;
100            else
101               return (false);
102         }
103      }
104      return (true);
105   }
106   
107   bool CINetCDF4Adv::isCurvilinear(const std::string & _varname)
108   {
109      if (this->isRectilinear(_varname) ||
110         !this->hasCoordinates(_varname))
111         return (false);
112
113      std::vector<std::string> coords = this->getCoordinatesIdList(_varname);
114      std::vector<std::string>::const_iterator it = coords.begin(), end = coords.end();
115      for (; it != end; it++)
116      {
117         const std::string & coord = *it;
118         if (this->hasVariable(coord))
119         {
120            std::map<std::string, std::size_t> dimvar = this->getDimensions(&coord);
121            if (dimvar.size() != 2) return (false);
122         }
123         else return (false);
124      }
125      return (true);
126   }
127   
128   bool CINetCDF4Adv::isUnknown(const std::string & _varname)
129   {
130      return !(this->isRectilinear(_varname) ||
131               this->isCurvilinear(_varname) ||
132               this->isUnstructured(_varname));
133   }
134   
135   bool CINetCDF4Adv::isUnstructured(const std::string & _varname)
136   {
137      if (this->isRectilinear(_varname)    ||
138          this->isCurvilinear(_varname)    ||
139         !this->hasCoordinates(_varname))
140          return (false);
141
142      std::string dimname = this->getDimensionsIdList(&_varname).back();
143
144      std::vector<std::string> coords = this->getCoordinatesIdList(_varname);
145      std::vector<std::string>::const_iterator it = coords.begin(), end = coords.end();
146      for (; it != end; it++)
147      {
148         const std::string & coord = *it;
149         if (this->hasVariable(coord))
150         {
151            std::map<std::string, std::size_t> dimvar = this->getDimensions(&coord);
152            if ((dimvar.size() == 1) &&
153                (dimvar.find(dimname) != dimvar.end()))
154               continue;
155            else
156               return (false);
157         }
158            else return (false);
159      }
160
161      return (true);
162   }
163   
164   bool CINetCDF4Adv::isTemporal(const std::string & _varname)
165   {
166      if (!this->hasTemporalDim()) return (false);
167      std::map<std::string, std::size_t> dims = this->getDimensions(&_varname);
168      if (dims.find(this->getUnlimitedDimensionName()) != dims.end())
169         return (true);
170      return (false);
171   }
172   
173   bool CINetCDF4Adv::is3Dim(const std::string & _varname)
174   {
175      int i = 0;
176      std::vector<std::string> coords = this->getCoordinatesIdList(_varname);
177      std::vector<std::string>::const_iterator it = coords.begin(), end = coords.end();
178      for (; it != end; it++)
179      {
180         const std::string & coord = *it;
181         if (this->hasVariable(coord))
182         {
183            if (this->isTemporal(coord))
184               continue;
185            i++;
186         }
187         else
188         {
189            if (coord.compare(this->getUnlimitedDimensionName()) == 0)
190               continue;
191            i++;
192         }
193      }
194      return (i == 3);
195   }
196   
197   bool CINetCDF4Adv::isCellGrid(const std::string & _varname)
198   {
199      if (this->isCoordinate(_varname))
200      {
201         return (this->hasBounds(_varname));
202      }
203      else
204      {
205         std::vector<std::string> coords = this->getCoordinatesIdList(_varname);
206         std::vector<std::string>::const_iterator it = coords.begin(), end = coords.end();
207         for (; it != end; it++)
208         {
209            const std::string & coord = *it;
210            if (this->hasVariable(coord))
211            {
212               if (this->isTemporal(coord))
213                  continue;
214               if (this->isCellGrid(coord))
215                  continue;
216               return (false);
217            }
218            else
219            {
220               if (coord.compare(this->getUnlimitedDimensionName()) == 0)
221                  continue;
222               return (false);
223            }
224         }
225      }
226
227      return (true);
228   }
229   
230   std::size_t CINetCDF4Adv::getNbVertex(const std::string & _varname)
231   {
232      if (this->isRectilinear(_varname) ||
233          this->isCurvilinear(_varname))
234      {
235         if (this->is3Dim(_varname)) return (8);
236         else return (4);
237      }
238      if (this->isUnstructured(_varname))
239      {
240         std::string bound = this->getBoundsId
241                  (this->getCoordinatesIdList(_varname).back());
242         std::string dim = this->getDimensionsIdList(&bound).back();
243         return (this->getDimensions(&bound)[dim]);
244      }
245      return ((size_t)(-1));
246   }
247             
248   std::set<std::string> CINetCDF4Adv::getCoordVariables(void)
249   {
250      std::set<std::string> retvalue;
251      std::vector<std::string> variables = this->getVariables();
252      std::vector<std::string>::const_iterator it = variables.begin(), end = variables.end();
253      for (; it != end; it++)
254      {
255         const std::string & var = *it;
256         std::vector<std::string> coords = this->getCoordinatesIdList(var);
257         std::vector<std::string>::const_iterator it = coords.begin(), end = coords.end();
258         for (; it != end; it++)
259         {
260            const std::string & coord = *it;
261            if (this->hasVariable(coord))
262               retvalue.insert(retvalue.end(), coord);
263         }
264      }
265      return (retvalue);
266   }
267   
268   std::set<std::string> CINetCDF4Adv::getBoundVariables(void)
269   {
270      std::set<std::string> retvalue;         
271      std::vector<std::string> variables = this->getVariables();
272      std::vector<std::string>::const_iterator it = variables.begin(), end = variables.end();
273      for (; it != end; it++)
274      {
275         const std::string & var = *it;
276         if (this->hasBounds(var))
277            retvalue.insert(retvalue.end(), this->getBoundsId(var));
278      }
279      return (retvalue);
280   }
281           
282   std::string CINetCDF4Adv::getCoordinatesId(const std::string & _varname)
283   {
284         std::string retvalue;
285         if (this->hasAttribute("coordinates", &_varname))
286         {
287            this->readAttribute("coordinates", retvalue, &_varname);
288            return (retvalue);
289         }
290         else
291         {
292            std::vector<std::string> dims = this->getDimensionsIdList(&_varname);
293            std::vector<std::string>::const_iterator it = dims.begin(), end = dims.end();
294            for (; it != end; it++)
295            {
296               const std::string & value = *it;               
297               retvalue.append(value).push_back(' ');
298            }
299            retvalue.erase (retvalue.end()-1) ;
300         }
301
302         return (retvalue);
303   }
304   
305   std::string CINetCDF4Adv::getBoundsId (const std::string & _varname)
306   {
307      std::string retvalue;
308      if (this->hasAttribute("bounds", &_varname))
309            this->readAttribute("bounds", retvalue, &_varname);
310
311      return (retvalue);
312   }
313           
314           
315   std::vector<std::string> CINetCDF4Adv::getCoordinatesIdList(const std::string & _varname)
316   {
317      std::vector<std::string> retvalue;
318      std::string value = this->getCoordinatesId(_varname);
319         
320      boost::split(retvalue, value, boost::is_any_of(" "));
321         
322      std::vector<std::string>::iterator it = retvalue.begin(), end = retvalue.end();
323      for (; it != end; it++)
324      {
325         std::string & coord = *it;
326         coord.assign(coord.data());
327      }
328      return (retvalue);
329   }
330   
331   std::vector<std::string> CINetCDF4Adv::getDataVariables
332        (bool _is3D, bool _isRecti, bool _isCurvi, bool _isUnstr, bool _isCellData, bool _isTemporal)
333   {
334      std::vector<std::string> retvalue;
335      std::vector<std::string> allvars  = this->getVariables();
336
337      std::vector<std::string>::const_iterator it = allvars.begin(), end = allvars.end();
338      for (; it != end; it++)
339      {
340         const std::string & var = *it;
341         if (this->isCoordinate(var)) continue;
342
343         if (!_isRecti && this->isRectilinear(var) ) continue;
344         if (!_isCurvi && this->isCurvilinear(var) ) continue;
345         if (!_isUnstr && this->isUnstructured(var)) continue;
346
347         if (!_isTemporal && this->isTemporal(var)) continue;
348         if (!_is3D       && this->is3Dim(var)    ) continue;
349         if (!_isCellData && this->isCellGrid(var)) continue;
350
351         if (this->isUnknown(var)) continue;
352
353         retvalue.push_back(var);
354      }
355      return (retvalue);
356    }
357   
358    std::string CINetCDF4Adv::getLonCoordName (const std::string & _varname)
359    {
360       std::vector<std::string> clist = this->getCoordinatesIdList(_varname);
361       std::vector<std::string>::const_iterator it = clist.begin(), end = clist.end();
362       if (this->hasCoordinates(_varname))
363       {
364          for (; it != end; it++)
365          {
366              const std::string & var = *it;
367              if (this->hasVariable(var) && this->hasAttribute("axis", &var))
368              {
369                  std::string axis_name;
370                  this->readAttribute("axis", axis_name, &var);
371                  if (axis_name.compare("X") == 0)
372                      return (var);
373              }
374          }
375          return (*clist.begin());
376       }
377       else
378          return (*clist.rbegin());
379    }
380           
381    std::string CINetCDF4Adv::getLatCoordName (const std::string & _varname)
382    {
383       std::vector<std::string> clist = this->getCoordinatesIdList(_varname);
384       std::vector<std::string>::const_iterator it = clist.begin(), end = clist.end();
385       if (this->hasCoordinates(_varname))
386       {
387          for (; it != end; it++)
388          {
389              const std::string & var = *it;
390              if (this->hasVariable(var) && this->hasAttribute("axis", &var))
391              {
392                  std::string axis_name;
393                  this->readAttribute("axis", axis_name, &var);
394                  if (axis_name.compare("Y") == 0)
395                      return (var);
396              }
397          }
398          return (*(++clist.begin()));
399       }
400       else
401          return (*(++clist.rbegin()));
402    }
403           
404    std::string CINetCDF4Adv::getVertCoordName(const std::string & _varname)
405    {
406       if (!this->is3Dim(_varname)) return (std::string());
407       std::vector<std::string> clist = this->getCoordinatesIdList(_varname);
408       std::vector<std::string>::const_iterator it = clist.begin(), end = clist.end();
409       if (this->hasCoordinates(_varname))
410       {
411          for (; it != end; it++)
412          {
413              const std::string & var = *it;
414              if (this->hasVariable(var) && this->hasAttribute("axis", &var))
415              {
416                  std::string axis_name;
417                  this->readAttribute("axis", axis_name, &var);
418                  if (axis_name.compare("Z") == 0)
419                      return (var);
420              }
421          }
422          return (*(++(++clist.begin())));
423       }
424       else
425          return (*(++(++clist.rbegin())));
426    }
427   
428   std::string CINetCDF4Adv::getTimeCoordName(const std::string & _varname)
429   {
430      if (!this->isTemporal(_varname)) return (std::string());
431       std::vector<std::string> clist = this->getCoordinatesIdList(_varname);
432       std::vector<std::string>::const_iterator it = clist.begin(), end = clist.end();
433       if (this->hasCoordinates(_varname))
434       {
435          for (; it != end; it++)
436          {
437              const std::string & var = *it;
438              if (this->hasVariable(var) && this->hasAttribute("standard_name", &var))
439              {
440                  std::string time_name;
441                  this->readAttribute("standard_name", time_name, &var);
442                  if (time_name.compare("time") == 0)
443                      return (var);
444              }
445          }
446          return (this->getUnlimitedDimensionName());
447       }
448       else
449          return (*(clist.begin()));
450   }
451   
452   
453} // namespace io
454} // namespace xmlioserver
Note: See TracBrowser for help on using the repository browser.