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

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

Commit pour sauvegarde - diverses corrections de bogues et améliorations du code.

File size: 9.8 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               CField* field = (*it);
153               const CField* bfield = (*it)->getBaseObject();
154
155               lonlat = !field->getGrid()->_hasAxis();
156
157               if (field->operation.hasValue())
158               { // Si une opération sur le champ est définie ...
159                  if (field->operation.getId().compare("once") == 0)
160                  {
161                     wtime = false;
162                     field->freq_op.setValue(NoneDu);
163                  }
164               }
165               else
166               { // Si aucune opération sur le champ n'est définie ...
167                  FieldOperation ope("inst");
168                  field->operation.setValue(ope);
169               }
170
171               // Si la fréquence d'opération n'est pas définie, on l'initialise à 0s.
172               // Une fréquence à 0s signifie que l'opération se fera à chaque écriture de données depuis la simulation.
173               if (!field->freq_op.hasValue())
174                  field->freq_op.setValue(NoneDu);
175               ((FieldOperation)field->operation).setFreqOp(Duration(field->freq_op));
176
177
178               tvar = ncFloat;
179               if (field->prec.hasValue())
180                  if (field->prec == 8) tvar = ncDouble;
181
182               if (wtime)
183               {
184                  if (lonlat) // 2D spatio + temps
185                  {
186                     if (!(var = dataFile->add_var(bfield->getId().c_str(), tvar,
187                        dataFile->get_dim("time"), dataFile->get_dim("lon"), dataFile->get_dim("lat"))))
188                        throw XMLIOUndefinedValueException("Impossible d'ajouter le champ "+ field->getId() +" !");
189                  }
190                  else // 3D spatio + temps
191                  {
192                     if (!(var = dataFile->add_var(bfield->getId().c_str(), tvar,
193                        dataFile->get_dim("time"), dataFile->get_dim("lon"), dataFile->get_dim("lat"),
194                        dataFile->get_dim(field->getGrid()->getRelAxis()->getId().c_str()))))
195                        throw XMLIOUndefinedValueException("Impossible d'ajouter le champ "+ field->getId() +" !");
196                  }
197               }
198               else
199               {
200                  if (lonlat) // 2D spatio sans temps
201                  {
202                     if (!(var = dataFile->add_var(bfield->getId().c_str(), tvar,
203                        dataFile->get_dim("lon"), dataFile->get_dim("lat"))))
204                        throw XMLIOUndefinedValueException("Impossible d'ajouter le champ "+ field->getId() +" !");
205                  }
206                  else // 3D spatio sans temps
207                  {
208                     if (!(var = dataFile->add_var(bfield->getId().c_str(), tvar,
209                        dataFile->get_dim("lon"), dataFile->get_dim("lat"),
210                        dataFile->get_dim(field->getGrid()->getRelAxis()->getId().c_str()))))
211                        throw XMLIOUndefinedValueException("Impossible d'ajouter le champ "+ field->getId() +" !");
212                  }
213               }
214
215               if (field->name.hasValue())        hm["standard_name"] = field->name ;
216               if (field->unit.hasValue())        hm["units"]         = field->unit;
217               if (field->description.hasValue()) hm["long_name"]     = field->description ;
218               addStringAttributesToVar(var, hm);
219               hm.clear();
220            }
221         }
222
223      private :
224
225         void addStringAttributesToVar(NcVar * var, const Poco::HashMap<string, string>& attr)
226         {
227            Poco::HashMap<string, string>::ConstIterator it;
228            for ( it = attr.begin() ; it != attr.end(); it++ )
229               if (!var->add_att((*it).first.c_str(), (*it).second.c_str()))
230                  throw XMLIOUndefinedValueException("Impossible d'ajouter l'attribut' "+ (*it).first +" à la variable "+ var->name() +" !");
231         }
232
233         NcFile* dataFile;
234
235   }; //class NetCDF4DataOutput
236
237}// namespace XMLIOSERVER
238
239#endif //__NETCDF4_DATA_OUTPUT__
Note: See TracBrowser for help on using the repository browser.