#include #include #include #include "AxesNode.hh" #include "AxisLegendManager.hh" #include "ParamMgr.hh" #include "ParamsNode.hh" #include "PlPlotUtil.hh" #include "PlotFunction.hh" #include "PlotLogger.hh" #include "PlotOutput.hh" #include "TimeUtil.hh" #include "fonctions/fourier/DiscreteFourierTransform.cc" #include "fonctions/fourier/DiscreteFourierTransform.hh" #include #include #include #include "DefaultTimeAxisDecorator.hh" #include "TimeAxisDecorator.hh" using namespace AMDA::Parameters; using namespace AMDA::Info; namespace plot { QSASConfig *PlotFunction::qsasconfig = NULL; PlotFunction::PlotFunction(AMDA::Parameters::ParameterManager &manager, boost::shared_ptr panel, TimeAxisDecorator *timeAxisDecorator) : PanelPlotOutput(manager, panel), function(PlotFunction::Function::NONE), abscisse("Time. ", "(s)", Abscisse::Abscisse_Type::TIME) { LOG4CXX_DEBUG(gLogger, "Function to apply " << function); setTimeAxisDecorator(std::shared_ptr(timeAxisDecorator)); } PlotFunction::~PlotFunction() { if (qsasconfig != NULL) { free(qsasconfig); qsasconfig = nullptr; } } void PlotFunction::drawSeries(double startDate, double stopDate, int intervalIndex, std::string pParamId, SeriesProperties &pSerie, AMDA::Common::ParameterIndexComponent pParamIndex, ParameterAxes ¶m, bool moreThanOneSerieForAxis) { std::string id = std::to_string(pSerie.getId()) + "_" + pSerie.getParamId() + "_" + std::to_string(pParamIndex.getDim1Index()); std::vector xValues = xValuesMap[id]; std::vector yValues = yValuesMap[id]; double *coloredComputedValues = NULL; int nbValues = yValues.size(); double *yValuesTemp = &yValues[0]; double *xValuesTemp = &xValues[0]; pSerie.setXAxisId(X_AXIS_ID); pSerie.setYAxisId(Y_AXIS_ID); PanelPlotOutput::drawSeries(startDate, stopDate, intervalIndex, pParamId, pSerie, pParamIndex, param, moreThanOneSerieForAxis); // draw serie Color lineColor = getSerieLineColor(pSerie, moreThanOneSerieForAxis); Color symbolColor = getSerieSymbolColor(pSerie, lineColor); drawSymbols( pSerie.getSymbolProperties().getType(), pSerie.getSymbolProperties().getSize(), 1., symbolColor, nbValues, xValuesTemp, yValuesTemp, coloredComputedValues); drawLines( pSerie.getLineProperties().getType(), pSerie.getLineProperties().getStyle(), pSerie.getLineProperties().getWidth(), lineColor, nbValues, xValuesTemp, yValuesTemp, coloredComputedValues); } void PlotFunction::configureSeriesAxis() { //_panel->_leftMargin = 10; //_panel->_rightMargin = 5; //_panel->_bottomMargin = 4; SeriesProperties lSeries; for (auto parameter : _parameterAxesList) { for (auto lSeries : parameter.getYSeriePropertiesList()) { for (auto lIndex : lSeries.getIndexList(_pParameterValues)) { std::string id = std::to_string(lSeries.getId()) + "_" + lSeries.getParamId() + "_" + std::to_string(lIndex.getDim1Index()); plot::ParameterData data = (*_pParameterValues)[lSeries.getParamId()]; PlotFunction::compute(lIndex, data, id, lSeries.getParamId()); } } } PlotFunction::createXAxis(); PlotFunction::createYAxis(); } void PlotFunction::createXAxis() { double minValue = 0; double maxValue = 0; PlotFunction::getMinMax(xValuesMap, &minValue, &maxValue); // Create X axis boost::shared_ptr lXAxis(new TimeAxis()); lXAxis.get()->_timeFormat = "%H:%M"; plot::Range range_x = Range(minValue, maxValue); lXAxis.get()->setRange(range_x); lXAxis.get()->_drawn = false; lXAxis.get()->_position = PlotCommon::Position::POS_BOTTOM; Label label1 = Label(); // lXAxis.get()->setLegendOffset(0.03); label1._text = abscisse.getLabel() + abscisse.getUnit(); lXAxis.get()->_legend.pushLabel(label1); lXAxis.get()->_scale = abscisseScale; lXAxis.get()->_showLegend = true; lXAxis.get()->_showTickMark = true; lXAxis.get()->_used = true; // add X Axis to panel _panel->addAxis(X_AXIS_ID, lXAxis); } void PlotFunction::createYAxis() { std::string y_label = ""; if (function == PlotFunction::Function::AVG) y_label = "AVG"; else y_label = "Amplitude"; double minValue = 0; double maxValue = 0; PlotFunction::getMinMax(yValuesMap, &minValue, &maxValue); // Create X axis boost::shared_ptr lYAxis(new Axis(false)); plot::Range range_x = Range(minValue - abs(minValue) * 0.10, maxValue + abs(maxValue) * 0.1); lYAxis.get()->setRange(range_x); lYAxis.get()->_drawn = false; lYAxis.get()->_position = PlotCommon::Position::POS_LEFT; Label label1 = Label(); // lYAxis.get()->setLegendOffset(0.05); label1._text = y_label; lYAxis.get()->_legend.pushLabel(label1); lYAxis.get()->_scale = ordonneeScale; lYAxis.get()->_showLegend = true; lYAxis.get()->_showTickMark = true; lYAxis.get()->_used = true; // add X Axis to panel _panel->addAxis(Y_AXIS_ID, lYAxis); } void PlotFunction::getMinMax(std::map> dataMap, double *minToFill, double *maxToFill) { double maxValue = INT_MIN; double minValue = INT_MAX; std::map>::iterator it; for (it = dataMap.begin(); it != dataMap.end(); it++) { std::vector data = it->second; double max_x = *max_element(data.begin(), data.end()); double min_x = *min_element(data.begin(), data.end()); if (max_x > maxValue) maxValue = max_x; if (min_x < minValue) minValue = min_x; } *minToFill = minValue; *maxToFill = maxValue; } void PlotFunction::compute(AMDA::Common::ParameterIndexComponent pParamIndex, plot::ParameterData data, std::string id, std::string param_id) { double samplingValue = 60.0; int nb_points = data.getSize(); auto it = find(paramsNbPoints.begin(), paramsNbPoints.end(), param_id); // If parameter was found if (it != paramsNbPoints.end()) { int index = it - paramsNbPoints.begin(); samplingValue = stod(paramsNbPoints[index + 1]); nb_points = stoi(paramsNbPoints[index + 2]); } else { std::stringstream lError; lError << "PlotFunction::compute" << ": param with id " << param_id << " is not found in param_nb_points xml node."; LOG4CXX_DEBUG(gLogger, lError.str()); BOOST_THROW_EXCEPTION(PanelPlotOutputException() << AMDA::errno_code(AMDA_ERROR_PLOTFUNCTION_PARAM_NOT_FOUND) << AMDA::ex_msg(lError.str())); } double *values = data.getValues(pParamIndex, 0); double *timeValues = &data.getTimes()[0]; std::vector signal; for (int i = 0; i < data.getSize(); i++) signal.push_back(values[i]); std::vector xValues; std::vector yValues; if (function == PlotFunction::Function::AVG) { double sum = std::accumulate(signal.begin(), signal.end(), 0); for (int i = 0; i < data.getSize(); i++) { yValues.push_back(sum / data.getSize()); xValues.push_back(timeValues[i]); } } else { DiscreteFourierTransform DFT(std::min(nb_points, data.getSize()), signal, 1 / samplingValue); DFT.compute(); yValues = DFT.getAmplitudes(); if (abscisse.getType() == Abscisse::Abscisse_Type::FREQUENCY) xValues = DFT.getFrequences(); else xValues = DFT.getPeriodes(); } if (ordonneeScale == Axis::Scale::LOGARITHMIC) { std::for_each(yValues.begin(), yValues.end(), [&](double &i) { return log10(i); }); } if (abscisseScale == Axis::Scale::LOGARITHMIC) { std::for_each(xValues.begin(), xValues.end(), [&](double &i) { return log10(i); }); } PlotFunction::xValuesMap[id] = xValues; PlotFunction::yValuesMap[id] = yValues; } void PlotFunction::configureAxisLegend() { // Y axis AxisLegendManager::configureYAxisLegendForSpectro(this); AxisLegendManager::configureYAxisLegendForSeries(this); // Z axis AxisLegendManager::configureColorAxisLegendForSpectro(this); AxisLegendManager::configureColorAxisLegendForSeries(this); } void PlotFunction::drawStartDate(std::string _timeFormat, double startTime, double stopTime) { Font font(_panel->getFont()); Bounds lPanelBounds(_panel->getBoundsInPlPage()); PLFLT lXMin, lXMax, lYMin, lYMax; _pls->gvpd(lXMin, lXMax, lYMin, lYMax); float lPosition = 0.0; // display it one line above the main panel bottom border : float disp = -1; long int lTime = static_cast(startTime); tm *lTimeTm = gmtime(&lTime); char lTimeChr[80]; // Format date. strftime(lTimeChr, 80, getPlStartTimeFormat(_timeFormat, startTime, stopTime) .c_str(), lTimeTm); PLFLT mxmin, mxmax, mymin, mymax; plgspa(&mxmin, &mxmax, &mymin, &mymax); float x_subpage_per_mm = 1. / (mxmax - mxmin); LOG4CXX_DEBUG(gLogger, "Start date to draw : " << lTimeChr); // Set font PlPlotUtil::setPlFont(font); PLFLT dateWidthInMm; dateWidthInMm = plstrl(lTimeChr); // set viewport for start date : _pls->vpor(lXMin, lXMax, lPanelBounds._y, lPanelBounds._y + lPanelBounds._height); lPosition = 0.; if (dateWidthInMm * x_subpage_per_mm > lXMin - lPanelBounds._x) lPosition = (dateWidthInMm * x_subpage_per_mm - lXMin + lPanelBounds._x) / (lXMax - lXMin); _pls->mtex("b", disp, lPosition, 1., lTimeChr); // restore viewport : _pls->vpor(lXMin, lXMax, lYMin, lYMax); } void PlotFunction::preparePlotArea(double startTime, double stopTime, int intervalIndex) { PlotFunction::configureSeriesAxis(); if (abscisse.getType() == Abscisse::TIME) { boost::shared_ptr xAxis = _panel->getAxis(X_AXIS_ID); getTimeAxisDecorator()->configure(this, dynamic_cast(xAxis.get()), startTime, stopTime, _pParameterValues); _pls->timefmt(getTimeAxisDecorator()->getPlFormat().c_str()); } PanelPlotOutput::preparePlotArea(startTime, stopTime, intervalIndex); } void PlotFunction::createParameters(std::list &usedParametersId_) { for (ParameterAxesList::iterator it = _parameterAxesList.begin(); it != _parameterAxesList.end(); ++it) { AMDA::Parameters::ParameterSPtr originalParam = _parameterManager.getParameter(it->_originalParamId); // For each series std::vector::iterator ity; for (ity = it->getYSeriePropertiesList().begin(); ity != it->getYSeriePropertiesList().end(); ++ity) { // Add parameter to parameters list if (std::find(usedParametersId_.begin(), usedParametersId_.end(), originalParam->getId()) == usedParametersId_.end()) usedParametersId_.push_back(originalParam->getId()); // link this paramter to the serie ity->setParamId(originalParam->getId()); } } } /** * @brief draw the plot for the current time interval */ bool PlotFunction::draw(double startTime, double stopTime, int intervalIndex, bool isFirstInterval, bool isLastInterval) { bool out = PanelPlotOutput::draw(startTime, stopTime, intervalIndex, isFirstInterval, isLastInterval); if (abscisse.getType() == Abscisse::TIME) { std::string _timeFormat = "hh:mm:ss"; PlotFunction::drawStartDate(_timeFormat, startTime, stopTime); } return out; } }