/** * StatisticOutput.cc * * Created on: 04 nov. 2014 * Author: AKKA */ #include "StatisticOutput.hh" #include "ServicesServer.hh" #include "TimeUtil.hh" #include "AMDA-Kernel_Config.hh" #include "Parameter.hh" #include "ParamMgr.hh" #include "MissionMgr.hh" #include "InstrumentMgr.hh" #include #include namespace AMDA { namespace ParamOutputImpl { /** * @brief Implementation of a ParamOutput to apply statistic processes on parameters. */ namespace Statistic { StatisticOutput::StatisticOutput(AMDA::Parameters::ParameterManager& pParameterManager) : ParamOutput(pParameterManager), _statisticProperties(), _currentIntervalIndex(0) { } StatisticOutput::~StatisticOutput() { } /** * @overload DataClient::establishConnection() */ void StatisticOutput::establishConnection() { LOG4CXX_DEBUG(_logger,"StatisticOutput::establishConnection"); for (auto paramProp : _statisticProperties.getParamPropertiesList()) { try { AMDA::Parameters::ParameterSPtr param = _parameterManager.getParameter( paramProp->getId()); for (auto statisticFunc : paramProp->getFunctionPropertiesList()) { ProcessDescription procDesc; procDesc._paramId = paramProp->getId(); procDesc._functionName = statisticFunc->getName(); procDesc._index = paramProp->getIndex(); procDesc._statisticProcesSPtr.reset(AMDA::Parameters::ServicesServer::getInstance()->getStatisticProcess(statisticFunc->getName(), *param.get(), paramProp->getIndex())); procDesc._statisticProcesSPtr->setArguments(statisticFunc->getArgumentMap()); _processDescriptionList.push_back(procDesc); procDesc._statisticProcesSPtr->establishConnection(); } } catch (...) { LOG4CXX_ERROR(_logger, "StatisticOutput::establishConnection - It's impossible to create statistic process for parameter " << paramProp->getId()); throw; } } } /** * @overload ParamOutput::init() */ void StatisticOutput::init() { LOG4CXX_DEBUG(_logger,"StatisticOutput::init"); //init all needed parameters for (auto procDesc : _processDescriptionList) { try { procDesc._statisticProcesSPtr->init(_timeIntervalList); } catch (...) { LOG4CXX_ERROR(_logger, "StatisticOutput::init - It's impossible to init a statistic process"); throw; } } } /** * @overload ParamOutput::apply() */ void StatisticOutput::apply() { LOG4CXX_DEBUG(_logger,"StatisticOutput::apply"); try { bool isFirstInterval = true; //Intervals loop while (_currentTimeInterval != _timeIntervalList->end()) { //select output structure switch (_statisticProperties.getOutputStructure()) { case OutputStructure::ONE_FILE : applyOneFile(isFirstInterval); break; case OutputStructure::ONE_FILE_PER_PARAMETER : applyOneFilePerParameter(isFirstInterval); break; default : LOG4CXX_WARN(_logger, "StatisticOutput::apply - output structure not implemented => use ONE-FILE"); } //go to next time interval ++_currentTimeInterval; ++_currentIntervalIndex; isFirstInterval = false; } //write catalog for (auto catalog : _statisticCatalogMap) { std::string filePath = catalog.second.write(_workPath, _statisticProperties.getFileFormatKey()); if (!filePath.empty()) _files.push_back(filePath); } } catch (...) { LOG4CXX_ERROR(_logger, "StatisticOutput::apply : Error to apply output"); throw; } } void StatisticOutput::applyOneFile(bool isFirstInterval) { //init catalog if need if (isFirstInterval) initCatalog(""); //create catalog interval TimeTableCatalog::TimeInterval newInt(_currentTimeInterval->_startTime,_currentTimeInterval->_stopTime); //compute statistic result for current interval for (auto &procDesc : _processDescriptionList) { try { std::vector crtResult; std::vector crtCoverage; procDesc._statisticProcesSPtr->compute(crtResult,crtCoverage); if (isFirstInterval) addProcessDescriptionInCatalog(&_statisticCatalogMap[""], &procDesc); newInt.addParameterData(procDesc._dataKey, crtResult); newInt.addParameterData(procDesc._coverageKey, crtCoverage); } catch (...) { LOG4CXX_ERROR(_logger, "StatisticOutput::applyOneFile - It's impossible to apply a statistic process"); throw; } } _statisticCatalogMap[""].addInterval(newInt); } void StatisticOutput::applyOneFilePerParameter(bool isFirstInterval) { std::map intMap; for (auto &procDesc : _processDescriptionList) { try { std::vector crtResult; std::vector crtCoverage; procDesc._statisticProcesSPtr->compute(crtResult,crtCoverage); //init catalog if need if (isFirstInterval) initCatalog(procDesc._paramId); //create new interval if need if (intMap[procDesc._paramId] == NULL) { //init new interval intMap[procDesc._paramId] = new TimeTableCatalog::TimeInterval(_currentTimeInterval->_startTime,_currentTimeInterval->_stopTime); } //add process description in catalog if (isFirstInterval) addProcessDescriptionInCatalog(&_statisticCatalogMap[procDesc._paramId], &procDesc); //add process data and coverage in catalog intMap[procDesc._paramId]->addParameterData(procDesc._dataKey, crtResult); intMap[procDesc._paramId]->addParameterData(procDesc._coverageKey, crtCoverage); } catch (...) { LOG4CXX_ERROR(_logger, "StatisticOutput::applyOneFilePerParameter - It's impossible to apply a statistic process"); throw; } } //add intervals in corresponding catalog for (auto intervalDef : intMap) { _statisticCatalogMap[intervalDef.first].addInterval(*intervalDef.second); delete intervalDef.second; } } void StatisticOutput::initCatalog(std::string paramId) { if (_statisticCatalogMap.find(paramId) != _statisticCatalogMap.end()) //already exist => nothing to do return; _statisticCatalogMap[paramId]._timeFormat = _statisticProperties.getTimeFormat(); _statisticCatalogMap[paramId]._name = getCatalogName(paramId); if(getenv("HIDE_AMDA_DATE") != NULL) _statisticCatalogMap[paramId]._creationDate = 0; else _statisticCatalogMap[paramId]._creationDate = std::time(0); _statisticCatalogMap[paramId]._description.push_back("Generated by CDPP/AMDA Statistic Module"); //adding other infomation for (ProcessDescription processDes: _processDescriptionList) { std::stringstream statInfo; AMDA::Info::ParamInfoSPtr paramInfo = AMDA::Info::ParamMgr::getInstance()->getParamInfoFromId(processDes._paramId); //AMDA::Info::MissionInfoSPtr missionInfo = AMDA::Info::MissionMgr::getInstance()->getMissionInfoFromId(processDes._paramId); if(processDes._index == _processDescriptionList.front()._index) statInfo<<"by using params: \n"; if(paramInfo->getInstrumentId() !="") { AMDA::Info::InstrumentInfoSPtr instrumentInfo = AMDA::Info::InstrumentMgr::getInstance()->getInstrumentInfoFromId(paramInfo->getInstrumentId()); if (instrumentInfo.get() != nullptr) { if(instrumentInfo->getMissionId() != ""){ AMDA::Info::MissionInfoSPtr missionInfo = AMDA::Info::MissionMgr::getInstance()->getMissionInfoFromId(instrumentInfo->getMissionId()); if (missionInfo.get() != nullptr) { statInfo<< missionInfo->getName()<<"/"; } } statInfo<getName()<<"/"; } } statInfo<size() ==1 && _timeIntervalList->front()._ttPath.empty() && _timeIntervalList->front()._ttName.empty()) { if(processDes._index == _processDescriptionList.back()._index){ statInfo<<"\nwith interval : "; statInfo<front()._startTime)<<" - "; statInfo<front()._stopTime); } }else{ statInfo<<"\nfrom TimeTable/Catalog: "; if(_currentTimeInterval->_ttName.empty()) { statInfo<<_currentTimeInterval->_ttPath; }else{ statInfo<< _currentTimeInterval->_ttName; } } _statisticCatalogMap[paramId]._description.push_back(statInfo.str()); } } void StatisticOutput::addProcessDescriptionInCatalog(TimeTableCatalog::Catalog* pCatalog, ProcessDescription* pProcDesc) { //two parameters are created in a catalog for each process (for data and coverage). int indexOfDesc = pCatalog->getParameterDescriptions().size() / 2; //add catalog description for this process //data name std::stringstream dataName; dataName << pProcDesc->_functionName; dataName << "("; dataName << pProcDesc->_paramId; if (pProcDesc->_index >= 0) { dataName << "["; dataName << pProcDesc->_index; dataName << "]"; } dataName << ")"; //data key std::stringstream dataKey; dataKey << "stat_data_" << indexOfDesc; pProcDesc->_dataKey = dataKey.str(); TimeTableCatalog::ParameterDescription desc( pProcDesc->_dataKey, dataName.str(), pProcDesc->_statisticProcesSPtr->getResultDimDefinition(), TimeTableCatalog::ParameterDescription::ParameterType::Double, "", "Statistic result computed by CDPP/AMDA", "", pProcDesc->_statisticProcesSPtr->getUCD(), "" ); pCatalog->addParameterDescription(desc); //coverage name std::stringstream covName; covName << "Coverage of "; covName << dataName.str(); pProcDesc->_coverageKey = covName.str(); //coverage key std::stringstream covKey; covKey << "stat_cov_" << indexOfDesc; pProcDesc->_coverageKey = covKey.str(); TimeTableCatalog::ParameterDescription coverageDesc( pProcDesc->_coverageKey, covName.str(), pProcDesc->_statisticProcesSPtr->getResultDimDefinition(true), TimeTableCatalog::ParameterDescription::ParameterType::Double, "", "Coverage of the statistic result computed by CDPP/AMDA", "", "meta.code.qual", "" ); pCatalog->addParameterDescription(coverageDesc); } std::string StatisticOutput::getCatalogName(std::string paramId) { std::stringstream fileName; if (_statisticProperties.getFileName().empty()) { std::stringstream fileNameSuffix; if (_currentTimeInterval->_ttName.empty()) { //add start time double lStartTime = _currentTimeInterval->_startTime; char buffer[TIMELENGTH]; Double2DD_Time(buffer, lStartTime); fileNameSuffix << "-" << buffer; } else { //add TT name fileNameSuffix << "-" << _currentTimeInterval->_ttName; } fileName << "statistic-"; if (_statisticProperties.getOutputStructure() == OutputStructure::ONE_FILE_PER_PARAMETER) { fileName << paramId; } else { int crtFileNameSize = fileName.str().size() + fileNameSuffix.str().size(); bool isFirst = true; for (auto paramProp : _statisticProperties.getParamPropertiesList()) { std::stringstream paramPart; if (!isFirst) { paramPart << "-" ; } isFirst = false; for (auto statisticFunc : paramProp->getFunctionPropertiesList()) { paramPart << statisticFunc->getName() << "_"; } paramPart << paramProp->getId(); if (paramProp->getIndex() >= 0) { paramPart << "_" << paramProp->getIndex(); } if (crtFileNameSize + paramPart.str().size() > 247) { //Filename is limited to 255 characters by Linux //+ we keep 4 characters for extension //+ we keep 3 characters for "etc" fileName << "_etc"; break; } crtFileNameSize += paramPart.str().size(); fileName << paramPart.str(); } } fileName << fileNameSuffix.str(); } else fileName << _statisticProperties.getFileName(); return fileName.str(); } } /* namespace Statistic */ } /* namespace ParamOutputImpl */ } /* namespace AMDA */