source: XMLIO_V2/dev/dev_rv/src/XMLIO/NetCDF4_data_output.hpp @ 123

Last change on this file since 123 was 123, checked in by hozdoba, 14 years ago

Début de gestion des opérations sur les champs + quelques modifications

File size: 9.1 KB
Line 
1#ifndef __NETCDF4_DATA_OUTPUT__
2#define __NETCDF4_DATA_OUTPUT__
3
4#include <netcdfcpp.h>
5
6namespace XMLIOSERVER
7{
8   class NetCDF4DataOutput : public AbstractDataOutput
9   {
10      public :
11
12         NetCDF4DataOutput(CFile* const _file) : AbstractDataOutput(_file), dataFile(NULL)
13         { /* Ne rien faire de plus */ }
14
15         const NcFile* getDataFile(void) const { return (dataFile); }
16
17         virtual ~NetCDF4DataOutput()
18         { if (dataFile != NULL) delete dataFile; }
19
20      protected :
21
22         Poco::HashMap<string, int> getAllLimitedDim(void)
23         {
24            Poco::HashMap<string, int> dims;
25            const std::set<const CDomain*> sdom = getRelFile()->getEnabledDomains();
26            const std::set<const CAxis*> saxis = getRelFile()->getEnabledAxis();
27
28            const CDomain* pdom = *sdom.begin();
29
30            // TODO Améliorer ci-dessous -> un seul domaine pris en compte pour le moment
31            dims["lon"] = pdom->nj;
32            dims["lat"] = pdom->ni;
33
34            std::set<const CAxis*>::const_iterator it;
35            for ( it = saxis.begin() ; it != saxis.end(); it++ )
36               dims[(*it)->getId()] = (*it)->size;
37
38            return (dims);
39         }
40
41         std::string getFileName(void)
42         { return ((getRelFile()->name.hasValue()) ? string(getRelFile()->name): getRelFile()->name.getId()); }
43
44         std::string getTimeStamp(void)
45         {
46              time_t rawtime;
47              struct tm * timeinfo;
48              char buffer [100];
49
50              time ( &rawtime );
51              timeinfo = localtime ( &rawtime );
52
53              strftime (buffer, 100, "%Y-%b-%d %H:%M:%S %Z", timeinfo);
54
55              return (string(buffer));
56         }
57
58         virtual void initFile(void)
59         {
60            string filename = getFileName();
61
62            // Création du fichier ou remplacement si celui-ci existe déjà.
63            dataFile = new NcFile(filename.c_str(), NcFile::Replace);
64            if(!dataFile->is_valid())
65               throw XMLIOUndefinedValueException("Impossible d'ouvrir le fichier '"+ filename +"' pour l'écriture des données' !");
66
67            // Ajout de quelques attributs globaux.
68            dataFile->add_att("conventions", "CF-1.1");
69            dataFile->add_att("file_name"  , getFileName().c_str());
70            if (getRelFile()->description.hasValue())
71               dataFile->add_att("file_desc" , string(getRelFile()->description).c_str());
72            dataFile->add_att("production" , "An IPSL model");
73            dataFile->add_att("timeStamp"  , getTimeStamp().c_str()) ;
74         }
75
76         virtual void setDims(void)
77         {
78            bool withTime = true;
79            const Poco::HashMap<string, int>& allDim = getAllLimitedDim();
80            Poco::HashMap<string, int>::ConstIterator it;
81
82            // Ajout des dimensions limitées.
83            for (it = allDim.begin() ; it != allDim.end(); it++)
84               if (NULL == dataFile->add_dim((*it).first.c_str(), (*it).second))
85                  throw XMLIOUndefinedValueException("Impossible d'ajouter la dimension "+ (*it).first +" !");
86
87            // Ajout de la dimension temporelle non limitée.
88            if (withTime)
89               if (NULL == dataFile->add_dim("time"))
90                  throw XMLIOUndefinedValueException("Impossible d'ajouter la dimension temporelle !");
91         }
92
93         virtual void setCoords(void)
94         {
95            NcVar *latVar = NULL, // variable de latitude.
96                  *lonVar = NULL, // variable de longitude.
97                  *othvar = NULL; // toute autre variable.
98
99            Poco::HashMap<string, string> hm;
100
101            const std::set<const CDomain*> sdom = getRelFile()->getEnabledDomains();
102            const std::set<const CAxis*> saxis = getRelFile()->getEnabledAxis();
103
104            if (!(latVar = dataFile->add_var("lat", ncFloat, dataFile->get_dim("lat"))))
105               throw XMLIOUndefinedValueException("Impossible d'ajouter la variable de latitude !");
106            if (!(lonVar = dataFile->add_var("lon", ncFloat, dataFile->get_dim("lon"))))
107               throw XMLIOUndefinedValueException("Impossible d'ajouter la variable de longitude !");
108
109            // Attribut de latitude.
110            hm["axis"]          = "Y" ;
111            hm["standard_name"] = "latitude" ;
112            hm["units"]         = "degrees_north";
113            hm["long_name"]     = "Latitude" ;
114            addStringAttributesToVar(latVar, hm);
115            hm.clear();
116
117            // Attribut de longitude.
118            hm["axis"]           = "X" ;
119            hm["standard_name"]  = "longitude" ;
120            hm["units"]          = "degrees_east";
121            hm["long_name"]      = "Longitude" ;
122            addStringAttributesToVar(lonVar, hm);
123            hm.clear();
124
125            // Attribut des autres coordonnées.
126            std::set<const CAxis*>::const_iterator it;
127            for ( it = saxis.begin() ; it != saxis.end(); it++ )
128            {
129               if (!(othvar = dataFile->add_var((*it)->getId().c_str(), ncFloat, dataFile->get_dim((*it)->getId().c_str()))))
130                  throw XMLIOUndefinedValueException("Impossible d'ajouter la variable "+ (*it)->getId() +" !");
131
132               hm["axis"] = "Z" ;
133               if ((*it)->name.hasValue())        hm["standard_name"] = (*it)->name ;
134               if ((*it)->unit.hasValue())        hm["units"]         = (*it)->unit;
135               if ((*it)->description.hasValue()) hm["long_name"]     = (*it)->description ;
136               addStringAttributesToVar(othvar, hm);
137               hm.clear();
138            }
139         }
140
141         virtual void setVars(void)
142         {
143            NcType tvar;
144            NcVar *var  = NULL;
145            Poco::HashMap<string, string> hm;
146            bool lonlat = false, wtime = true;
147            const std::vector<CField*>& enabledFields = getRelFile()->getEnabledFields();
148
149            std::vector<CField*>::const_iterator it;
150            for ( it = enabledFields.begin() ; it != enabledFields.end(); it++ )
151            {
152               const CField* field = (*it);
153               const CField* bfield = (*it)->getBaseObject();
154
155               lonlat = !field->getGrid()->_hasAxis();
156               if (field->operation.hasValue())
157                  if (string(field->operation).compare("once") == 0) wtime = false;
158
159               tvar = ncFloat;
160               if (field->prec.hasValue())
161                  if (field->prec == 8) tvar = ncDouble;
162
163               if (wtime)
164               {
165                  if (lonlat) // 2D spatio + temps
166                  {
167                     if (!(var = dataFile->add_var(bfield->getId().c_str(), tvar,
168                        dataFile->get_dim("time"), dataFile->get_dim("lon"), dataFile->get_dim("lat"))))
169                        throw XMLIOUndefinedValueException("Impossible d'ajouter le champ "+ field->getId() +" !");
170                  }
171                  else // 3D spatio + temps
172                  {
173                     if (!(var = dataFile->add_var(bfield->getId().c_str(), tvar,
174                        dataFile->get_dim("time"), dataFile->get_dim("lon"), dataFile->get_dim("lat"),
175                        dataFile->get_dim(field->getGrid()->getRelAxis()->getId().c_str()))))
176                        throw XMLIOUndefinedValueException("Impossible d'ajouter le champ "+ field->getId() +" !");
177                  }
178               }
179               else
180               {
181                  if (lonlat) // 2D spatio sans temps
182                  {
183                     if (!(var = dataFile->add_var(bfield->getId().c_str(), tvar,
184                        dataFile->get_dim("lon"), dataFile->get_dim("lat"))))
185                        throw XMLIOUndefinedValueException("Impossible d'ajouter le champ "+ field->getId() +" !");
186                  }
187                  else // 3D spatio sans temps
188                  {
189                     if (!(var = dataFile->add_var(bfield->getId().c_str(), tvar,
190                        dataFile->get_dim("lon"), dataFile->get_dim("lat"),
191                        dataFile->get_dim(field->getGrid()->getRelAxis()->getId().c_str()))))
192                        throw XMLIOUndefinedValueException("Impossible d'ajouter le champ "+ field->getId() +" !");
193                  }
194               }
195
196               if (field->name.hasValue())        hm["standard_name"] = field->name ;
197               if (field->unit.hasValue())        hm["units"]         = field->unit;
198               if (field->description.hasValue()) hm["long_name"]     = field->description ;
199               addStringAttributesToVar(var, hm);
200               hm.clear();
201            }
202         }
203
204      private :
205
206         void addStringAttributesToVar(NcVar * var, const Poco::HashMap<string, string>& attr)
207         {
208            Poco::HashMap<string, string>::ConstIterator it;
209            for ( it = attr.begin() ; it != attr.end(); it++ )
210               if (!var->add_att((*it).first.c_str(), (*it).second.c_str()))
211                  throw XMLIOUndefinedValueException("Impossible d'ajouter l'attribut' "+ (*it).first +" à la variable "+ var->name() +" !");
212         }
213
214         NcFile* dataFile;
215
216   }; //class NetCDF4DataOutput
217
218}// namespace XMLIOSERVER
219
220#endif //__NETCDF4_DATA_OUTPUT__
Note: See TracBrowser for help on using the repository browser.