#ifndef __NETCDF4_DATA_OUTPUT__ #define __NETCDF4_DATA_OUTPUT__ #include namespace XMLIOSERVER { class NetCDF4DataOutput : public AbstractDataOutput { public : NetCDF4DataOutput(CFile* const _file) : AbstractDataOutput(_file), dataFile(NULL) { /* Ne rien faire de plus */ } const NcFile* getDataFile(void) const { return (dataFile); } virtual ~NetCDF4DataOutput() { if (dataFile != NULL) delete dataFile; } protected : Poco::HashMap getAllLimitedDim(void) { Poco::HashMap dims; const std::set sdom = getRelFile()->getEnabledDomains(); const std::set saxis = getRelFile()->getEnabledAxis(); const CDomain* pdom = *sdom.begin(); // TODO Améliorer ci-dessous -> un seul domaine pris en compte pour le moment dims["lon"] = pdom->nj; dims["lat"] = pdom->ni; std::set::const_iterator it; for ( it = saxis.begin() ; it != saxis.end(); it++ ) dims[(*it)->getId()] = (*it)->size; return (dims); } std::string getFileName(void) { return ((getRelFile()->name.hasValue()) ? string(getRelFile()->name): getRelFile()->name.getId()); } std::string getTimeStamp(void) { time_t rawtime; struct tm * timeinfo; char buffer [100]; time ( &rawtime ); timeinfo = localtime ( &rawtime ); strftime (buffer, 100, "%Y-%b-%d %H:%M:%S %Z", timeinfo); return (string(buffer)); } virtual void initFile(void) { string filename = getFileName(); // Création du fichier ou remplacement si celui-ci existe déjà. dataFile = new NcFile(filename.c_str(), NcFile::Replace); if(!dataFile->is_valid()) throw XMLIOUndefinedValueException("Impossible d'ouvrir le fichier '"+ filename +"' pour l'écriture des données' !"); // Ajout de quelques attributs globaux. dataFile->add_att("conventions", "CF-1.1"); dataFile->add_att("file_name" , getFileName().c_str()); if (getRelFile()->description.hasValue()) dataFile->add_att("file_desc" , string(getRelFile()->description).c_str()); dataFile->add_att("production" , "An IPSL model"); dataFile->add_att("timeStamp" , getTimeStamp().c_str()) ; } virtual void setDims(void) { bool withTime = true; const Poco::HashMap& allDim = getAllLimitedDim(); Poco::HashMap::ConstIterator it; // Ajout des dimensions limitées. for (it = allDim.begin() ; it != allDim.end(); it++) if (NULL == dataFile->add_dim((*it).first.c_str(), (*it).second)) throw XMLIOUndefinedValueException("Impossible d'ajouter la dimension "+ (*it).first +" !"); // Ajout de la dimension temporelle non limitée. if (withTime) if (NULL == dataFile->add_dim("time")) throw XMLIOUndefinedValueException("Impossible d'ajouter la dimension temporelle !"); } virtual void setCoords(void) { NcVar *latVar = NULL, // variable de latitude. *lonVar = NULL, // variable de longitude. *othvar = NULL; // toute autre variable. Poco::HashMap hm; const std::set sdom = getRelFile()->getEnabledDomains(); const std::set saxis = getRelFile()->getEnabledAxis(); if (!(latVar = dataFile->add_var("lat", ncFloat, dataFile->get_dim("lat")))) throw XMLIOUndefinedValueException("Impossible d'ajouter la variable de latitude !"); if (!(lonVar = dataFile->add_var("lon", ncFloat, dataFile->get_dim("lon")))) throw XMLIOUndefinedValueException("Impossible d'ajouter la variable de longitude !"); // Attribut de latitude. hm["axis"] = "Y" ; hm["standard_name"] = "latitude" ; hm["units"] = "degrees_north"; hm["long_name"] = "Latitude" ; addStringAttributesToVar(latVar, hm); hm.clear(); // Attribut de longitude. hm["axis"] = "X" ; hm["standard_name"] = "longitude" ; hm["units"] = "degrees_east"; hm["long_name"] = "Longitude" ; addStringAttributesToVar(lonVar, hm); hm.clear(); // Attribut des autres coordonnées. std::set::const_iterator it; for ( it = saxis.begin() ; it != saxis.end(); it++ ) { if (!(othvar = dataFile->add_var((*it)->getId().c_str(), ncFloat, dataFile->get_dim((*it)->getId().c_str())))) throw XMLIOUndefinedValueException("Impossible d'ajouter la variable "+ (*it)->getId() +" !"); hm["axis"] = "Z" ; if ((*it)->name.hasValue()) hm["standard_name"] = (*it)->name ; if ((*it)->unit.hasValue()) hm["units"] = (*it)->unit; if ((*it)->description.hasValue()) hm["long_name"] = (*it)->description ; addStringAttributesToVar(othvar, hm); hm.clear(); } } virtual void setVars(void) { NcType tvar; NcVar *var = NULL; Poco::HashMap hm; bool lonlat = false, wtime = true; const std::vector& enabledFields = getRelFile()->getEnabledFields(); std::vector::const_iterator it; for ( it = enabledFields.begin() ; it != enabledFields.end(); it++ ) { const CField* field = (*it); const CField* bfield = (*it)->getBaseObject(); lonlat = !field->getGrid()->_hasAxis(); if (field->operation.hasValue()) if (string(field->operation).compare("once") == 0) wtime = false; tvar = ncFloat; if (field->prec.hasValue()) if (field->prec == 8) tvar = ncDouble; if (wtime) { if (lonlat) // 2D spatio + temps { if (!(var = dataFile->add_var(bfield->getId().c_str(), tvar, dataFile->get_dim("time"), dataFile->get_dim("lon"), dataFile->get_dim("lat")))) throw XMLIOUndefinedValueException("Impossible d'ajouter le champ "+ field->getId() +" !"); } else // 3D spatio + temps { if (!(var = dataFile->add_var(bfield->getId().c_str(), tvar, dataFile->get_dim("time"), dataFile->get_dim("lon"), dataFile->get_dim("lat"), dataFile->get_dim(field->getGrid()->getRelAxis()->getId().c_str())))) throw XMLIOUndefinedValueException("Impossible d'ajouter le champ "+ field->getId() +" !"); } } else { if (lonlat) // 2D spatio sans temps { if (!(var = dataFile->add_var(bfield->getId().c_str(), tvar, dataFile->get_dim("lon"), dataFile->get_dim("lat")))) throw XMLIOUndefinedValueException("Impossible d'ajouter le champ "+ field->getId() +" !"); } else // 3D spatio sans temps { if (!(var = dataFile->add_var(bfield->getId().c_str(), tvar, dataFile->get_dim("lon"), dataFile->get_dim("lat"), dataFile->get_dim(field->getGrid()->getRelAxis()->getId().c_str())))) throw XMLIOUndefinedValueException("Impossible d'ajouter le champ "+ field->getId() +" !"); } } if (field->name.hasValue()) hm["standard_name"] = field->name ; if (field->unit.hasValue()) hm["units"] = field->unit; if (field->description.hasValue()) hm["long_name"] = field->description ; addStringAttributesToVar(var, hm); hm.clear(); } } private : void addStringAttributesToVar(NcVar * var, const Poco::HashMap& attr) { Poco::HashMap::ConstIterator it; for ( it = attr.begin() ; it != attr.end(); it++ ) if (!var->add_att((*it).first.c_str(), (*it).second.c_str())) throw XMLIOUndefinedValueException("Impossible d'ajouter l'attribut' "+ (*it).first +" à la variable "+ var->name() +" !"); } NcFile* dataFile; }; //class NetCDF4DataOutput }// namespace XMLIOSERVER #endif //__NETCDF4_DATA_OUTPUT__