/* * StatusBarDecorator.cc * * Created on: Jan 12, 2015 * Author: AKKA */ #include "StatusBarDecorator.hh" #include #include #include #include "log4cxx/logger.h" #include "plplot/plplot.h" #include "plplot/plplotP.h" #include "boost/exception/all.hpp" #include "PlotLogger.hh" #include "TimeAxis.hh" #include "Page.hh" #include "Time/TimePlot.hh" #include "StatusPlot.hh" #include "ColormapManager.hh" #include "ParamMgr.hh" #include "PlPlotUtil.hh" #include "CommonNode.hh" #define BAR_HEIGHT 0.02 #define BAR_SPACE 0.005 namespace plot { log4cxx::LoggerPtr StatusBarDecorator::_logger( log4cxx::Logger::getLogger("AMDA-Kernel.Plot.Time.StatusBarDecorator")); StatusBarDecorator::StatusBarDecorator (AMDA::Parameters::ParameterManager& manager, PanelPlotOutput* decoratorPlot) : DefaultTimeAxisDecorator(), _parameterManager(manager), _colorMapIndex(ColormapManager::getInstance()._defaultColorAxis), _barPosition(PlotCommon::Position::POS_TOP), _decoratorPlot(decoratorPlot){ } StatusBarDecorator::StatusBarDecorator(const StatusBarDecorator& ref_) : DefaultTimeAxisDecorator(ref_), _parameterManager( ref_._parameterManager), _barInfoList( ref_._barInfoList), _colorMapIndex(ref_._colorMapIndex), _barPosition(ref_._barPosition), _decoratorPlot(ref_._decoratorPlot) { } StatusBarDecorator& StatusBarDecorator::operator=(const StatusBarDecorator& ref_) { _parameterManager = ref_._parameterManager; _barInfoList = ref_._barInfoList; _colorMapIndex = ref_._colorMapIndex; _barPosition = ref_._barPosition; _decoratorPlot = ref_._decoratorPlot; return *this; } StatusBarDecorator::~StatusBarDecorator() { } void StatusBarDecorator::updatePlotArea(PanelPlotOutput* pplot_, Axis* axis_, const Bounds& panelBounds_, Bounds& bounds_) { //Space for time axis DefaultTimeAxisDecorator::updatePlotArea(pplot_, axis_, panelBounds_, bounds_); LOG4CXX_DEBUG(_logger, "StatusBarDecorator Updating plot area : "<_legend.getFont()); Font panelFont(pplot_->_panel->getFont()); if (!legendFont.isSet()) { legendFont = panelFont; } PlPlotUtil::setPlFont(legendFont); CharSize legendSize = PlPlotUtil::getCharacterSizeInPlPage(pplot_->_panel->_page); double barSpace = 0; // reserve space for all series bar : barSpace += ((BAR_HEIGHT + BAR_SPACE + 1.5*legendSize.second) * _barInfoList.size()); if ((_barPosition == pAxis->_position) && (_barPosition == PlotCommon::POS_BOTTOM)) //one additional space to not draw the bar too close to the date barSpace += legendSize.second; // to take into account bar space. bounds_._height -= barSpace; if (_decoratorPlot->isStandalone()) bounds_._height = BAR_SPACE; // specific case when axis labels are displayed at bottom of the graph. Needs to update y. if (_barPosition == PlotCommon::POS_BOTTOM) { bounds_._y += barSpace; } } double StatusBarDecorator::computeStartDateWidth(PanelPlotOutput* pplot_, TimeAxis* pAxis_) { // not very efficient ... long int lTime = static_cast(pAxis_->getRange().getMin()); tm * lTimeTm = gmtime(&lTime); char lTimeChr[80]; // Format date. size_t datelen = strftime(lTimeChr, 80, getPlStartTimeFormat(pAxis_->_timeFormat, pAxis_->getRange().getMin(), pAxis_->getRange().getMax()).c_str(), lTimeTm); PlPlotUtil::setPlFont(pplot_->_panel->getFont()); CharSize fontSize = PlPlotUtil::getCharacterSizeInPlPage(pplot_->_panel->_page); return fontSize.first * datelen; } void StatusBarDecorator::configure(PanelPlotOutput* pplot_, Axis* axis_, double start_, double stop_, std::map *pParameterValues) { TimeAxis* pTimeAxis = (TimeAxis*) axis_; if (_decoratorPlot->isStandalone()) pTimeAxis->setOnlyTickmarks(true); DefaultTimeAxisDecorator::configure(pplot_,axis_,start_,stop_,pParameterValues); LOG4CXX_DEBUG(_logger, "StatusBarDecorator::configure"); buildBarList(); } void StatusBarDecorator::draw(PanelPlotOutput* pplot_, Axis* axis_, std::shared_ptr pls_) { DefaultTimeAxisDecorator::draw(pplot_,axis_,pls_); // draw a virtual axis for each entry // take into account plot orientation TimeAxis* pAxis = (TimeAxis*) axis_; // Get plot area viewport. Bounds vpBounds; PLFLT lXMin, lXMax, lYMin, lYMax; pls_->gvpd(lXMin, lXMax, lYMin, lYMax); vpBounds._x = lXMin; vpBounds._y = lYMin; vpBounds._width = lXMax - lXMin; vpBounds._height = lYMax - lYMin; // get windows Bounds winBounds; PLFLT xwmin, xwmax, ywmin, ywmax; pls_->gvpw(xwmin, xwmax, ywmin, ywmax); winBounds._x = xwmin; winBounds._y = ywmin; winBounds._width = xwmax - xwmin; winBounds._height = ywmax - ywmin; LOG4CXX_DEBUG(_logger, " viewport :"<_color, pplot_->_panel->_page->_mode); // Set font to draw axes. std::vector panelStyles; Font panelFont(pplot_->_panel->getFont()); Font legendFont(pAxis->_legend.getFont()); if (!legendFont.isSet()) { // font has not been defined for that axis, used default panel font : legendFont = panelFont; } // viewport translation only along y direction: we translate about n charHeight. So, gets panel character height. PlPlotUtil::setPlFont(panelFont); CharSize panelCharSize = PlPlotUtil::getCharacterSizeInPlPage(pplot_->_panel->_page); PlPlotUtil::setPlFont(legendFont); CharSize legendCharSize = PlPlotUtil::getCharacterSizeInPlPage(pplot_->_panel->_page); double delta = BAR_SPACE; //add space for tick if necessary if (pAxis->_visible && pAxis->_showTickMark && !_decoratorPlot->isStandalone() && (pAxis->_tick._position == Tick::TickPosition::OUTWARDS)) delta += getVerticalTickLength(pAxis, panelCharSize.second); //add space for time axis if (pAxis->_visible && (_barPosition == pAxis->_position) && pAxis->_showLegend && !pAxis->_legend.isEmpty()) { delta += 3*panelCharSize.second; } //keep status bar order int first = 0; int end = _barInfoList.size(); int dir = 1; if (_barPosition == PlotCommon::Position::POS_TOP) { first = _barInfoList.size()-1; end = -1; dir = -1; } //add status bar for (int i = first; i != end; i+=dir) { LOG4CXX_DEBUG(_logger, "statusbar["<slabelfunc(generateNoTimeLabel, NULL); // translate viewport : if (_barPosition == PlotCommon::Position::POS_BOTTOM) { pls_->vpor(vpBounds._x, vpBounds._x + vpBounds._width, vpBounds._y - delta - 1.5*legendCharSize.second - BAR_HEIGHT, vpBounds._y - delta - 1.5*legendCharSize.second); } else { pls_->vpor(vpBounds._x, vpBounds._x + vpBounds._width, vpBounds._y + vpBounds._height + delta , vpBounds._y + vpBounds._height + delta + BAR_HEIGHT); } // sets windows for new viewport : pls_->wind(winBounds._x, winBounds._x + winBounds._width, 0, 1); ParamInfoSPtr paramInfo = _barInfoList[i]._paramInfoSPtr; //Working list of pair used to build the legend std::vector> legend; // legend configuration if ((paramInfo != nullptr) && !paramInfo->getStatusDef().empty()) { for (int s = 0; s < (int)paramInfo->getStatusDef().size(); ++s) { std::string colorStr = paramInfo->getStatusDef()[s].getColor(); if (_barInfoList[i]._color.isSet()) // we use the color set by the user { Color color; color = _barInfoList[i]._color; legend.push_back(std::make_pair(color, paramInfo->getStatusDef()[s].getName())); } else if (!colorStr.empty()) // if the color is not set by the user we take the StatusDef { Color color; createColor(color, colorStr); legend.push_back(std::make_pair(color, paramInfo->getStatusDef()[s].getName())); } else // if none of them is given, we set the colorMapIndex color { Color color(_colorMapIndex, s); legend.push_back(std::make_pair(color, paramInfo->getStatusDef()[s].getName())); } } } // set color map pls_->spal1( ColormapManager::getInstance().getColorAxis(_colorMapIndex).c_str(), true); Color lInitialColor; pls_->gcol0(0, lInitialColor._red, lInitialColor._green, lInitialColor._blue); // Draw Status data PLFLT x[4], y[4]; for (int t = 0; t < _barInfoList[i]._dataPtr->getSize() - 1; ++t) { x[0] = _barInfoList[i]._dataPtr->getTimes()[t]; x[1] = _barInfoList[i]._dataPtr->getTimes()[t]; x[2] = _barInfoList[i]._dataPtr->getTimes()[t + 1]; x[3] = _barInfoList[i]._dataPtr->getTimes()[t + 1]; y[0] = 0.; y[1] = 1.; y[2] = 1.; y[3] = 0.; double paramValue = _barInfoList[i]._dataPtr->getValues(_barInfoList[i]._index)[t]; if (isNAN(paramValue)) { continue; } if ((paramInfo != nullptr) && !paramInfo->getStatusDef().empty()) { for (int s = 0; s < (int)paramInfo->getStatusDef().size(); ++s) { if ((paramValue >= paramInfo->getStatusDef()[s].getMinValue()) && (paramValue <= paramInfo->getStatusDef()[s].getMaxValue())) { std::string colorStr = paramInfo->getStatusDef()[s].getColor(); if (_barInfoList[i]._color.isSet()) // we use the color set by the user { restoreColor(pls_, _barInfoList[i]._color, pplot_->_panel->_page->_mode); pls_->fill(4, x, y); pls_->spal1(ColormapManager::getInstance().getColorAxis(_colorMapIndex).c_str(), true); } else if (!colorStr.empty()) // if the color is not set by the user we take the StatusDef { Color color; createColor(color, colorStr); restoreColor(pls_, color, pplot_->_panel->_page->_mode); pls_->fill(4, x, y); pls_->spal1(ColormapManager::getInstance().getColorAxis(_colorMapIndex).c_str(), true); } else // if none of them is given, we set the colorMapIndex color { Color dataValueColor(_colorMapIndex, s); restoreColor(pls_, dataValueColor, pplot_->_panel->_page->_mode); pls_->fill(4, x, y); pls_->spal1(ColormapManager::getInstance().getColorAxis(_colorMapIndex).c_str(), true); } break; } } } } // restore to initial color context pls_->spal1( ColormapManager::getInstance().get(pplot_->_panel->_page->_mode, ColormapManager::DEFAULT_COLORMAP_1) .c_str(), true); pls_->scol0(0, lInitialColor._red, lInitialColor._green, lInitialColor._blue); // Restore color. restoreColor(pls_, lInitialColor, pplot_->_panel->_page->_mode); // draw bar box pls_->box("bc", 0, 0, "bc", 0, 0); // draw legend PlPlotUtil::setPlFont(legendFont); std::string legendText = _barInfoList[i]._name; legendText += ": "; // plot parameter name pls_->mtex("t", 1, 0, 0, legendText.c_str()); PLFLT xmin2, xmax2, ymin2, ymax2; pls_->gspa(xmin2, xmax2, ymin2, ymax2); double textFactor = (xmax2 - xmin2) * vpBounds._width; double legendPos = plstrl(legendText.c_str()) / textFactor; std::string separator = ", "; // plot each status name with the associated color for (int p = 0; p < (int)legend.size(); ++p) { Color initColor = changeColor(pls_, legend[p].first, pplot_->_panel->_page->_mode); pls_->mtex("t", 1, legendPos, 0, legend[p].second.c_str()); legendPos += plstrl(legend[p].second.c_str()) / textFactor; restoreColor(pls_, initColor, pplot_->_panel->_page->_mode); if (p != (int)legend.size() - 1) { pls_->mtex("t", 1, legendPos, 0, separator.c_str()); legendPos += plstrl(separator.c_str()) / textFactor; } } delta += (BAR_HEIGHT + BAR_SPACE + 1.5 * legendCharSize.second); } // restore viewport. pls_->vpor(vpBounds._x, vpBounds._x + vpBounds._width, vpBounds._y, vpBounds._y + vpBounds._height); // restore window pls_->wind(winBounds._x, winBounds._x + winBounds._width, winBounds._y, winBounds._y + winBounds._height); // Restore initial color. restoreColor(pls_, lInitialColor, pplot_->_panel->_page->_mode); } void StatusBarDecorator::buildBarList() { LOG4CXX_DEBUG(_logger, "StatusBarDecorator::buildBarList"); // Retrieve ParamInfo Manager ParamMgr *piMgr =ParamMgr::getInstance(); _barInfoList.clear(); for (auto p : _decoratorPlot->_parameterAxesList) { ParameterSPtr param = _parameterManager.getParameter(p._originalParamId); ParamInfoSPtr paramInfo = piMgr->getParamInfoFromId(param->getInfoId()); std::string name; if ((paramInfo == nullptr) || (paramInfo->getShortName().empty())) name = p._originalParamId; else name = paramInfo->getShortName(); LOG4CXX_DEBUG(_logger, " inspecting parameter : " << name); // list asked series : for(auto lSeriesProperties : p.getYSeriePropertiesList()) { for (auto index : lSeriesProperties.getIndexList(_pParameterValues)) { BarInfo barInfo; std::ostringstream osstr; osstr << name; // display index only if non scalar if(index.getDim1Index() != -1){ osstr << "[" << index.getDim1Index() ; if (index.getDim2Index() != -1) osstr << "," << index.getDim2Index(); osstr << "]"; } LOG4CXX_DEBUG(_logger, " Display name : " << osstr.str()); barInfo._name = osstr.str(); barInfo._index = index; barInfo._dataPtr = &(*_pParameterValues)[lSeriesProperties.getParamId()]; barInfo._paramInfoSPtr = paramInfo; barInfo._color = lSeriesProperties.getColor(); _barInfoList.push_back(barInfo); } } } } } /* namespace plot */