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

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

Amélioration de quelques portions de code.
Ajout de contructeurs par copie.

File size: 12.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)
13            : AbstractDataOutput(_file), dataFile(NULL)
14         { /* Ne rien faire de plus */ }
15
16         const NcFile* getDataFile(void) const { return (dataFile); }
17
18         void writeVarData(const string& id, const Array<float, 1>& vdata)
19         {
20            //if (!latVar->put(lats, NLAT))
21            //   return NC_ERR;
22         }
23
24         virtual ~NetCDF4DataOutput()
25         { if (dataFile != NULL) delete dataFile; }
26
27      protected :
28
29         Poco::HashMap<string, int> getAllLimitedDim(void) const
30         {
31            Poco::HashMap<string, int> dims;
32            const std::set<const CDomain*> sdom = this->getRelFile()->getEnabledDomains();
33            const std::set<const CAxis*>  saxis = this->getRelFile()->getEnabledAxis();
34
35            // std::cout << "Nombre de domaines disponibles pour le fichier : " << sdom.size()  << std::endl;
36            // std::cout << "Nombre d'axes disponibles pour le fichier : "      << saxis.size() << std::endl;
37
38            std::set<const CDomain*>::const_iterator itt;
39            std::set<const CAxis*>::const_iterator it;
40
41            for ( itt = sdom.begin() ; itt != sdom.end(); itt++ )
42            {
43               string domid = ((*itt)->name.hasValue()) ? (string)(*itt)->name : (*itt)->getId();
44               string lonid = string("lon_").append(domid);
45               string latid = string("lat_").append(domid);
46               dims[lonid]  = (*itt)->ni;
47               dims[latid]  = (*itt)->nj;
48            }
49
50            for ( it = saxis.begin() ; it != saxis.end(); it++ )
51            {
52               string axisid = ((*it)->name.hasValue()) ? (string)(*it)->name : (*it)->getId();
53               dims[axisid]  = (*it)->size;
54            }
55
56            return (dims);
57         }
58
59         std::string getFileName(void)
60         { return ((getRelFile()->name.hasValue()) ? string(getRelFile()->name): getRelFile()->name.getId()); }
61
62         std::string getTimeStamp(void)
63         {
64            const int buffer_size = 100;
65            time_t rawtime;
66            struct tm * timeinfo = NULL;
67            char buffer [buffer_size];
68
69            time ( &rawtime );
70            timeinfo = localtime ( &rawtime );
71            strftime (buffer, buffer_size, "%Y-%b-%d %H:%M:%S %Z", timeinfo);
72
73            return (string(buffer));
74         }
75
76         void writeCoords(const string& id, const Array<float, 1>& cdata)
77         {
78            NcVar *cVar = dataFile->get_var(id.c_str());
79
80            if (!cVar->put(cdata.dataFirst(), cdata.size()))
81               throw XMLIOUndefinedValueException("Impossible d'écrire les valeurs de coordonnées "+ id +" !");
82         }
83
84      protected : /* virtual */
85
86         virtual void initFile(void)
87         {
88            string filename = this->getFileName();
89
90            // Création du fichier ou remplacement si celui-ci existe déjà.
91            dataFile = new NcFile(filename.c_str(), NcFile::Replace);
92            if(!dataFile->is_valid())
93               throw XMLIOUndefinedValueException("Impossible d'ouvrir le fichier '"+ filename +"' pour l'écriture des données' !");
94
95            // Ajout de quelques attributs globaux.
96            dataFile->add_att("conventions", "CF-1.1");
97            dataFile->add_att("file_name"  , getFileName().c_str());
98            if (getRelFile()->description.hasValue())
99               dataFile->add_att("file_desc" , string(getRelFile()->description).c_str());
100            dataFile->add_att("production" , "An IPSL model");
101            dataFile->add_att("timeStamp"  , getTimeStamp().c_str()) ;
102         }
103
104         virtual void setDims(void)
105         {
106            bool withTime = true;
107            const Poco::HashMap<string, int>& allDim = this->getAllLimitedDim();
108            Poco::HashMap<string, int>::ConstIterator it;
109
110            // Ajout des dimensions limitées.
111            for (it = allDim.begin() ; it != allDim.end(); it++)
112               if (NULL == dataFile->add_dim((*it).first.c_str(), (*it).second))
113                  throw XMLIOUndefinedValueException("Impossible d'ajouter la dimension "+ (*it).first +" !");
114
115            // Ajout de la dimension temporelle non limitée.
116            if (withTime)
117               if (NULL == dataFile->add_dim("time"))
118                  throw XMLIOUndefinedValueException("Impossible d'ajouter la dimension temporelle !");
119         }
120
121         virtual void setCoords(void)
122         {
123            NcVar *latVar = NULL, // variable de latitude.
124                  *lonVar = NULL, // variable de longitude.
125                  *othvar = NULL; // toute autre variable.
126
127            Poco::HashMap<string, string> hm;
128
129            const std::set<const CDomain*> sdom = this->getRelFile()->getEnabledDomains();
130            const std::set<const CAxis*>  saxis = this->getRelFile()->getEnabledAxis();
131
132            std::set<const CDomain*>::const_iterator itt;
133            for ( itt = sdom.begin() ; itt != sdom.end(); itt++ )
134            {
135               string domid = ((*itt)->name.hasValue()) ? (string)(*itt)->name : (*itt)->getId();
136               string lonid = string("lon_").append(domid);
137               string latid = string("lat_").append(domid);
138
139               if (!(latVar = dataFile->add_var(latid.c_str(), ncFloat, dataFile->get_dim(latid.c_str()))))
140                  throw XMLIOUndefinedValueException("Impossible d'ajouter la variable de latitude !");
141               if (!(lonVar = dataFile->add_var(lonid.c_str(), ncFloat, dataFile->get_dim(lonid.c_str()))))
142                  throw XMLIOUndefinedValueException("Impossible d'ajouter la variable de longitude !");
143
144               // Attribut de latitude.
145               hm["axis"]          = "Y" ;
146               hm["standard_name"] = "latitude" ;
147               hm["units"]         = "degrees_north";
148               hm["long_name"]     = "Latitude" ;
149               addStringAttributesToVar(latVar, hm);
150               hm.clear();
151
152               // Attribut de longitude.
153               hm["axis"]           = "X" ;
154               hm["standard_name"]  = "longitude" ;
155               hm["units"]          = "degrees_east";
156               hm["long_name"]      = "Longitude" ;
157               addStringAttributesToVar(lonVar, hm);
158               hm.clear();
159            }
160
161            // Attribut des autres coordonnées.
162            std::set<const CAxis*>::const_iterator it;
163            for ( it = saxis.begin() ; it != saxis.end(); it++ )
164            {
165               string axisid = ((*it)->name.hasValue()) ? (string)(*it)->name : (*it)->getId();
166               if (!(othvar = dataFile->add_var(axisid.c_str(), ncFloat, dataFile->get_dim(axisid.c_str()))))
167                  throw XMLIOUndefinedValueException("Impossible d'ajouter la variable "+ (*it)->getId() +" !");
168
169               hm["axis"] = "Z" ;
170               if ((*it)->standard_name.hasValue())hm["standard_name"] = (*it)->standard_name ;
171               if ((*it)->long_name.hasValue())    hm["long_name"]     = (*it)->long_name ;
172               if ((*it)->unit.hasValue())         hm["units"]         = (*it)->unit;
173               addStringAttributesToVar(othvar, hm);
174               hm.clear();
175            }
176         }
177
178         virtual void setVars(void)
179         {
180            NcType tvar = ncFloat;
181            NcVar *var  = NULL;
182            Poco::HashMap<string, string> hm;
183            bool lonlat = false, wtime = true;
184            const std::vector<CField*>& enabledFields = getRelFile()->getEnabledFields();
185
186            std::vector<CField*>::const_iterator it;
187
188            for ( it = enabledFields.begin() ; it != enabledFields.end(); it++ )
189            {
190                     CField*  field = (*it);
191               const CField* bfield = (*it)->getBaseObject();
192               const CDomain*  rdom = field->getGrid()->getRelDomain();
193               const CAxis*   raxis = field->getGrid()->getRelAxis();
194
195               string fieldid = (field->name.hasValue()) ? (string)field->name : bfield->getId();
196               string domid   = (rdom ->name.hasValue()) ? (string)rdom ->name : rdom  ->getId();
197               string axisid  = (raxis->name.hasValue()) ? (string)raxis->name : raxis ->getId();
198
199               string lonid = string("lon_").append(domid); // Nom de la coordonnée longitudinale associée.
200               string latid = string("lat_").append(domid); // Nom de la coordonnée latitudinale  associée.
201
202               lonlat = !field->getGrid()->_hasAxis();
203
204               if (field->operation.hasValue())
205               { // Si une opération sur le champ est définie ...
206                  if (field->operation.getId().compare("once") == 0)
207                  { wtime = false; field->freq_op.setValue(NoneDu); }
208               }
209               else
210               { // Si aucune opération sur le champ n'est définie ...
211                  FieldOperation ope("inst");
212                  field->operation.setValue(ope);
213               }
214
215               // Si la fréquence d'opération n'est pas définie, on l'initialise à 0s.
216               // Une fréquence à 0s signifie que l'opération se fera à chaque écriture de données depuis la simulation.
217               if (!field->freq_op.hasValue())
218                  field->freq_op.setValue(NoneDu);
219               ((FieldOperation)field->operation).setFreqOp(Duration(field->freq_op));
220
221               tvar = ncFloat;
222               if (field->prec.hasValue())
223                  if (field->prec == 8) tvar = ncDouble;
224
225               if (wtime)
226               {
227                  if (lonlat) // 2D spatio + temps
228                  {
229                     if (!(var = dataFile->add_var(fieldid.c_str(), tvar,
230                        dataFile->get_dim("time"), dataFile->get_dim(latid.c_str()), dataFile->get_dim(lonid.c_str()))))
231                        throw XMLIOUndefinedValueException("Impossible d'ajouter le champ "+ field->getId() +" !");
232                  }
233                  else // 3D spatio + temps
234                  {
235                     if (!(var = dataFile->add_var(fieldid.c_str(), tvar,
236                        dataFile->get_dim("time"), dataFile->get_dim(axisid.c_str()),
237                        dataFile->get_dim(latid.c_str()), dataFile->get_dim(lonid.c_str()))))
238                        throw XMLIOUndefinedValueException("Impossible d'ajouter le champ "+ field->getId() +" !");
239                  }
240               }
241               else
242               {
243                  if (lonlat) // 2D spatio sans temps
244                  {
245                     if (!(var = dataFile->add_var(fieldid.c_str(), tvar,
246                        dataFile->get_dim(latid.c_str()), dataFile->get_dim(lonid.c_str()))))
247                        throw XMLIOUndefinedValueException("Impossible d'ajouter le champ "+ field->getId() +" !");
248                  }
249                  else // 3D spatio sans temps
250                  {
251                     if (!(var = dataFile->add_var(fieldid.c_str(), tvar, dataFile->get_dim(axisid.c_str()),
252                        dataFile->get_dim(latid.c_str()), dataFile->get_dim(lonid.c_str()))))
253                        throw XMLIOUndefinedValueException("Impossible d'ajouter le champ "+ field->getId() +" !");
254                  }
255               }
256
257               if (field->standard_name.hasValue())hm["standard_name"] = field->standard_name ;
258               if (field->long_name.hasValue())    hm["long_name"]     = field->long_name ;
259               if (field->unit.hasValue())         hm["units"]         = field->unit;
260               addStringAttributesToVar(var, hm);
261               hm.clear();
262            }
263         }
264
265      private :
266
267         void addStringAttributesToVar(NcVar * var, const Poco::HashMap<string, string>& attr)
268         {
269            Poco::HashMap<string, string>::ConstIterator it;
270
271            for ( it = attr.begin() ; it != attr.end(); it++ )
272               if (!var->add_att((*it).first.c_str(), (*it).second.c_str()))
273                  throw XMLIOUndefinedValueException("Impossible d'ajouter l'attribut' "+ (*it).first +" à la variable "+ var->name() +" !");
274         }
275
276         NcFile* dataFile;
277
278   }; //class NetCDF4DataOutput
279
280}// namespace XMLIOSERVER
281
282#endif //__NETCDF4_DATA_OUTPUT__
Note: See TracBrowser for help on using the repository browser.