/** * FileWriterCDF.cc * * Created on: 08 oct. 2014 * Author: AKKA */ #include "FileWriterCDF.hh" #include "TimeUtil.hh" #include "FileWriter.hh" #include "ParamMgr.hh" #include "DataSetMgr.hh" #include "InstrumentMgr.hh" #include "MissionMgr.hh" #include #include #include #include namespace AMDA { namespace ParamOutputImpl { namespace Download { namespace FileWriter { #define CDF_TIME_VAR "AMDA_TIME" using namespace AMDA::Info; FileWriterCDF::FileWriterCDF(AMDA::Parameters::ParameterManager& pParameterManager) : FileWriter(pParameterManager), _cdfid(NULL) { } FileWriterCDF::~FileWriterCDF(void) { } std::string FileWriterCDF::getExtension(void) { return "cdf"; } void FileWriterCDF::closeFile(void) { boost::mutex::scoped_lock scoped_lock(ParameterManager::mutexCDFLib); if (_cdfid != NULL) CDFcloseCDF(_cdfid); _cdfid = NULL; } bool FileWriterCDF::createNewFile(std::string filePath) { boost::mutex::scoped_lock scoped_lock(ParameterManager::mutexCDFLib); CDFstatus status; if (_cdfid != NULL) { status = CDFcloseCDF(_cdfid); if (status != CDF_OK) return false; _cdfid = NULL; _cdfVarMap.clear(); } //remove old file if exist remove(filePath.c_str()); //CDFcreateCDF add automatically ".cdf" extension status = CDFcreateCDF((char*)filePath.c_str(),&_cdfid); return (status == CDF_OK); } bool FileWriterCDF::addParameter(ParamProperties* paramProp, AMDA::Common::ParameterIndexComponentList &indexList, FileDataType type, bool isFirstParam, int dim1Size, int dim2Size) { if (isFirstParam) { if (!createCDFVar(CDF_TIME_VAR, DT_TIME, 1, 1, _cdfVarMap[CDF_TIME_VAR])) return false; } return addCDFParameter(paramProp->getOutputId(), indexList, type, dim1Size, dim2Size); } bool FileWriterCDF::addCDFParameter(std::string outputId, AMDA::Common::ParameterIndexComponentList &indexList, FileDataType type, int dim1Size, int dim2Size) { std::stringstream paramIdStream; paramIdStream << outputId; int varDim1Size = dim1Size; int varDim2Size = dim2Size; if ((type != DT_TIME) && !indexList.empty() && (dim1Size*dim2Size != (int)indexList.size())) { paramIdStream << "_" << indexList.size(); varDim1Size = indexList.size(); varDim2Size = 1; } std::map::iterator it = _cdfVarMap.find(outputId); if (it != _cdfVarMap.end()) return true; //already exist return createCDFVar(paramIdStream.str().c_str(), type, varDim1Size, varDim2Size, _cdfVarMap[outputId]); } bool FileWriterCDF::createCDFVar(const char *name, FileDataType type, long varDim1Size, long varDim2Size, ParamCDFVar& cdfVar) { boost::mutex::scoped_lock scoped_lock(ParameterManager::mutexCDFLib); if (_cdfid == NULL) return false; cdfVar.dim1Size = varDim1Size; cdfVar.dim2Size = varDim2Size; switch (type) { case DT_FLOAT : cdfVar.type = CDF_FLOAT; break; case DT_SHORT : cdfVar.type = CDF_INT2; break; case DT_INT : cdfVar.type = CDF_INT4; break; case DT_DOUBLE : case DT_LONGDOUBLE : cdfVar.type = CDF_DOUBLE; break; case DT_LOGICAL : cdfVar.type = CDF_UINT2; break; case DT_TIME : cdfVar.type = CDF_EPOCH; break; case DT_NONE : cdfVar.type = CDF_CHAR; break; default: return false; } cdfVar.recNum = 0; long numDims; long* dimSizes = NULL; long* dimVarys = NULL; if (varDim2Size > 1) { numDims = 2L; dimSizes = new long[2]; dimSizes[0] = varDim1Size; dimSizes[1] = varDim2Size; dimVarys = new long[2]; dimVarys[0] = VARY; dimVarys[1] = VARY; } else { numDims = (varDim1Size > 1) ? 1L : 0L; dimSizes = new long[1]; dimSizes[0] = varDim1Size; dimVarys = new long[1]; dimVarys[0] = VARY; } long recVary = {VARY}; long numElts = 1; CDFstatus status; status = CDFcreatezVar (_cdfid, name, cdfVar.type, numElts, numDims, dimSizes, recVary, dimVarys, &cdfVar.varNum); delete[] dimSizes; delete[] dimVarys; return (status == CDF_OK); } bool FileWriterCDF::isInfoInSeparateFile(bool /* onlyOneInterval */, OutputStructure /* outputStructure */) { return false; } bool FileWriterCDF::writeError(std::string msg) { addAttribute("AMDA_ERROR", msg, GLOBAL_SCOPE); return true; } bool FileWriterCDF::writeAMDAInfo(std::string version, std::string createdby, std::string acknowledgement) { addAttribute(AMDA_ABOUT, createdby, GLOBAL_SCOPE); addAttribute(AMDA_VERSION, version, GLOBAL_SCOPE); addAttribute(AMDA_ACKNOWLEDGEMENT, acknowledgement, GLOBAL_SCOPE); return true; } bool FileWriterCDF::writeRequestInfo(std::string structure, std::string /* timeFormat */, int timeResolution, std::string outputParams, std::string ttPath) { addAttribute(REQUEST_STRUCTURE, structure, GLOBAL_SCOPE); addAttribute(REQUEST_TIMEFORMAT, "EPOCH", GLOBAL_SCOPE); if (timeResolution > 0) { std::stringstream timeRes; timeRes << timeResolution; addAttribute(REQUEST_TIMERES, timeRes.str(), GLOBAL_SCOPE); } addAttribute(REQUEST_OUTPUTPARAMS, outputParams, GLOBAL_SCOPE); if (!ttPath.empty()) addAttribute(REQUEST_TTPATH, ttPath, GLOBAL_SCOPE); return true; } bool FileWriterCDF::writeMissionInfo(MissionInfoSPtr missionInfo, long varNum) { if (missionInfo == nullptr) return false; //write info about mission std::vector> infoMap = missionInfo->getInfoMap(); for (auto info : infoMap) addAttribute(info.first, info.second, VARIABLE_SCOPE, varNum); return true; } bool FileWriterCDF::writeInstrumentInfo(InstrumentInfoSPtr instrumentInfo, long varNum) { if (instrumentInfo == nullptr) return false; //write info about instrument std::vector> infoMap = instrumentInfo->getInfoMap(); for (auto info : infoMap) addAttribute(info.first, info.second, VARIABLE_SCOPE, varNum); MissionInfoSPtr mission = MissionMgr::getInstance()->getMissionInfoFromId(instrumentInfo->getMissionId()); writeMissionInfo(mission, varNum); return true; } bool FileWriterCDF::writeDatasetInfo(DataSetInfoSPtr datasetInfo, long varNum) { if (datasetInfo == nullptr) return false; //write info about datasetId std::vector> infoMap = datasetInfo->getInfoMap(); for (auto info : infoMap) addAttribute(info.first, info.second, VARIABLE_SCOPE, varNum); InstrumentInfoSPtr instrumentInfo = InstrumentMgr::getInstance()->getInstrumentInfoFromId(datasetInfo->getInstrumentId()); writeInstrumentInfo(instrumentInfo, varNum); return true; } bool FileWriterCDF::writeParameterInfo(ParamInfoSPtr parameterInfo, long varNum) { if (parameterInfo == nullptr) return false; std::vector> infoMap = parameterInfo->getInfoMap(&_parameterManager); for (auto info : infoMap) addAttribute(info.first, info.second, VARIABLE_SCOPE, varNum); DataSetInfoSPtr dataSetInfo = DataSetMgr::getInstance()->getDataSetInfoFromId(parameterInfo->getDatasetId()); writeDatasetInfo(dataSetInfo, varNum); return true; } bool FileWriterCDF::writeParamsInfo(ParamPropertiesList& paramPropertiesList, OutputStructure outputStructure, std::string currentParamId) { std::set,FileWriter::cmpParamInfoStruct> baseParamsInfoList; std::set,FileWriter::cmpParamInfoStruct> derivedParamsInfoList; //sort parameters info for (auto paramProperties : paramPropertiesList) { if ((outputStructure == ONE_FILE_PER_PARAMETER_PER_INTERVAL) && (currentParamId != paramProperties->getOutputId())) //add info only for current parameter continue; sortParametersInfoByType(paramProperties->getOutputId(), baseParamsInfoList, derivedParamsInfoList); } //write derived parameters info for (auto paramInfo : derivedParamsInfoList) { std::map::iterator it = _cdfVarMap.find(paramInfo.first); if (it == _cdfVarMap.end()) { createCDFVar(paramInfo.first.c_str(), DT_NONE, 1, 1, _cdfVarMap[paramInfo.first]); addAttribute("AMDA_INFO", "Derived parameter description. No data output.", VARIABLE_SCOPE, _cdfVarMap[paramInfo.first].varNum); } writeParameterInfo(paramInfo.second,_cdfVarMap[paramInfo.first].varNum); } //write base parameters info for (auto paramInfo : baseParamsInfoList) { std::map::iterator it = _cdfVarMap.find(paramInfo.first); if (it == _cdfVarMap.end()) { createCDFVar(paramInfo.first.c_str(), DT_NONE, 1, 1, _cdfVarMap[paramInfo.first]); addAttribute("AMDA_INFO", "Base parameter description. No data output.", VARIABLE_SCOPE, _cdfVarMap[paramInfo.first].varNum); } writeParameterInfo(paramInfo.second,_cdfVarMap[paramInfo.first].varNum); } return true; } bool FileWriterCDF::writeIntervalInfo(std::string startTime, std::string stopTime) { addAttribute(INTERVAL_START, startTime, GLOBAL_SCOPE); addAttribute(INTERVAL_STOP, stopTime, GLOBAL_SCOPE); return true; } bool FileWriterCDF::addAttribute(std::string attName, std::string attVal, long scope, long varNum) { boost::mutex::scoped_lock scoped_lock(ParameterManager::mutexCDFLib); if (_cdfid == NULL) return false; CDFstatus status; long attNum = CDFgetAttrNum(_cdfid, (char *)attName.c_str()); if (attNum < 0) { status = CDFcreateAttr(_cdfid, (char *)attName.c_str(), scope, &attNum); if (status != CDF_OK) return false; } if (scope == GLOBAL_SCOPE) status = CDFputAttrgEntry (_cdfid, attNum, 0, CDF_CHAR, attVal.size(), (void *)attVal.c_str()); else status = CDFputAttrzEntry (_cdfid, attNum, varNum, CDF_CHAR, attVal.size(), (void *)attVal.c_str()); return (status == CDF_OK); } bool FileWriterCDF::writeTimeData(std::string /* paramId */, double data, OutputFormatTime /* timeFormat */, bool isFirstParam) { boost::mutex::scoped_lock scoped_lock(ParameterManager::mutexCDFLib); if (_cdfid == NULL) return false; if (!isFirstParam) return true; std::stringstream isoTime; TimeUtil::formatTimeDateInIso(data, isoTime); char epString[EPOCH4_STRING_LEN+1]; memset(&epString,0,sizeof(epString)); if (!isoTime.str().empty()) strncpy(epString,isoTime.str().c_str(),EPOCH4_STRING_LEN); double epochTime = parseEPOCH4(epString); CDFstatus status = CDFputzVarRecordData(_cdfid, _cdfVarMap[CDF_TIME_VAR].varNum, _cdfVarMap[CDF_TIME_VAR].recNum, &epochTime); ++_cdfVarMap[CDF_TIME_VAR].recNum; return (status == CDF_OK); } bool FileWriterCDF::writeOneData(std::string paramId, int varIndex, void *data) { boost::mutex::scoped_lock scoped_lock(ParameterManager::mutexCDFLib); if (_cdfid == NULL) return false; if (_cdfVarMap[paramId].varNum <= 0) return false; long indices[2]; if (_cdfVarMap[paramId].dim2Size > 1) { indices[0] = varIndex/_cdfVarMap[paramId].dim2Size; indices[1] = varIndex%_cdfVarMap[paramId].dim2Size; } else indices[0] = varIndex; CDFstatus status = CDFputzVarData(_cdfid, _cdfVarMap[paramId].varNum, _cdfVarMap[paramId].recNum, indices, data); return (status == CDF_OK); } bool FileWriterCDF::writeFloatData(std::string paramId, int varIndex, float data, bool /* precision */) { return writeOneData(paramId, varIndex, &data); } bool FileWriterCDF::writeShortData(std::string paramId, int varIndex, short data, bool /* precision */) { return writeOneData(paramId, varIndex, &data); } bool FileWriterCDF::writeIntData(std::string paramId, int varIndex, int data, bool /* precision */) { return writeOneData(paramId, varIndex, &data); } bool FileWriterCDF::writeDoubleData(std::string paramId, int varIndex, double data, bool /* precision */) { return writeOneData(paramId, varIndex, &data); } bool FileWriterCDF::writeLongDoubleData(std::string paramId, int varIndex, long double data, bool /* precision */) { //convert long double to double double doubleData = boost::numeric_cast(data); return writeOneData(paramId, varIndex, &doubleData); } bool FileWriterCDF::writeLogicalData(std::string paramId, int varIndex, AMDA::Parameters::LogicalData data, bool /* precision */) { //convert LogicalData to 2-byte unsigned integer unsigned short uShortData; switch (data) { case AMDA::Parameters::LogicalData::False : uShortData = 0; break; case AMDA::Parameters::LogicalData::True : uShortData = 1; break; case AMDA::Parameters::LogicalData::NaN : uShortData = 2; break; default : return false; } return writeOneData(paramId, varIndex, &uShortData); } bool FileWriterCDF::goToNextRecord(std::string paramId) { ++_cdfVarMap[paramId].recNum; return true; } bool FileWriterCDF::finalize(bool /* isInfoFile */ ) { //nothing to do return true; } } /* namespace FileWriter */ } /* namespace Download */ } /* namespace ParamOutputImpl */ } /* namespace AMDA */