wuihlpgraphmatplotlib.py revision cf22150eaeeb72431bf1cf65c309a431454fb22b
af062818b47340eef15700d2f0211576ba3506eevboxsync# -*- coding: utf-8 -*-
af062818b47340eef15700d2f0211576ba3506eevboxsync# $Id$
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync"""
af062818b47340eef15700d2f0211576ba3506eevboxsyncTest Manager Web-UI - Graph Helpers - Implemented using matplotlib.
af062818b47340eef15700d2f0211576ba3506eevboxsync"""
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync__copyright__ = \
af062818b47340eef15700d2f0211576ba3506eevboxsync"""
af062818b47340eef15700d2f0211576ba3506eevboxsyncCopyright (C) 2012-2014 Oracle Corporation
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsyncThis file is part of VirtualBox Open Source Edition (OSE), as
af062818b47340eef15700d2f0211576ba3506eevboxsyncavailable from http://www.virtualbox.org. This file is free software;
af062818b47340eef15700d2f0211576ba3506eevboxsyncyou can redistribute it and/or modify it under the terms of the GNU
af062818b47340eef15700d2f0211576ba3506eevboxsyncGeneral Public License (GPL) as published by the Free Software
af062818b47340eef15700d2f0211576ba3506eevboxsyncFoundation, in version 2 as it comes in the "COPYING" file of the
af062818b47340eef15700d2f0211576ba3506eevboxsyncVirtualBox OSE distribution. VirtualBox OSE is distributed in the
af062818b47340eef15700d2f0211576ba3506eevboxsynchope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
af062818b47340eef15700d2f0211576ba3506eevboxsync
b955672b950093ff7416d1269dd4d3b69983bd8fvboxsyncThe contents of this file may alternatively be used under the terms
4b9d6701570cb98fd36e209314239d104ec584d3vboxsyncof the Common Development and Distribution License Version 1.0
4b9d6701570cb98fd36e209314239d104ec584d3vboxsync(CDDL) only, as it comes in the "COPYING.CDDL" file of the
b955672b950093ff7416d1269dd4d3b69983bd8fvboxsyncVirtualBox OSE distribution, in which case the provisions of the
b955672b950093ff7416d1269dd4d3b69983bd8fvboxsyncCDDL are applicable instead of those of the GPL.
b955672b950093ff7416d1269dd4d3b69983bd8fvboxsync
b955672b950093ff7416d1269dd4d3b69983bd8fvboxsyncYou may elect to license modified versions of this file under the
b955672b950093ff7416d1269dd4d3b69983bd8fvboxsyncterms and conditions of either the GPL or the CDDL or both.
b955672b950093ff7416d1269dd4d3b69983bd8fvboxsync"""
af062818b47340eef15700d2f0211576ba3506eevboxsync__version__ = "$Revision$"
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync# Standard Python Import and extensions installed on the system.
af062818b47340eef15700d2f0211576ba3506eevboxsyncimport re;
af062818b47340eef15700d2f0211576ba3506eevboxsyncimport StringIO;
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsyncimport matplotlib; # pylint: disable=F0401
af062818b47340eef15700d2f0211576ba3506eevboxsyncmatplotlib.use('Agg'); # Force backend.
af062818b47340eef15700d2f0211576ba3506eevboxsyncimport matplotlib.pyplot; # pylint: disable=F0401
af062818b47340eef15700d2f0211576ba3506eevboxsyncfrom numpy import arange as numpy_arange; # pylint: disable=E0611
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync# Validation Kit imports.
af062818b47340eef15700d2f0211576ba3506eevboxsyncfrom testmanager.webui.wuihlpgraphbase import WuiHlpGraphBase;
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsyncclass WuiHlpGraphMatplotlibBase(WuiHlpGraphBase):
af062818b47340eef15700d2f0211576ba3506eevboxsync """ Base class for the matplotlib graphs. """
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync def __init__(self, sId, oData, oDisp):
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync WuiHlpGraphBase.__init__(self, sId, oData, oDisp);
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync self._fXkcdStyle = True;
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync def setXkcdStyle(self, fEnabled = True):
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync """ Enables xkcd style graphs for implementations that supports it. """
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync self._fXkcdStyle = fEnabled;
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync return True;
af062818b47340eef15700d2f0211576ba3506eevboxsync
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync def _createFigure(self):
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync """
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync Wrapper around matplotlib.pyplot.figure that feeds the figure the
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync basic graph configuration.
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync """
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync if self._fXkcdStyle and matplotlib.__version__ > '1.2.9':
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync matplotlib.pyplot.xkcd(); # pylint: disable=E1101
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync matplotlib.rcParams.update({'font.size': self._cPtFont});
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync oFigure = matplotlib.pyplot.figure(figsize = (float(self._cxGraph) / self._cDpiGraph,
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync float(self._cyGraph) / self._cDpiGraph),
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync dpi = self._cDpiGraph);
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync return oFigure;
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync def _produceSvg(self, oFigure, fTightLayout = True):
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync """ Creates an SVG string from the given figure. """
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync oOutput = StringIO.StringIO();
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync if fTightLayout:
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync oFigure.tight_layout();
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync oFigure.savefig(oOutput, format = 'svg');
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync if self._oDisp and self._oDisp.isBrowserGecko('20100101'):
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync # This browser will stretch images to fit if no size or width is given.
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync sSubstitute = r'\1 \3 reserveAspectRatio="xMidYMin meet"';
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync else:
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync # Chrome and IE likes to have the sizes as well as the viewBox.
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync sSubstitute = r'\1 \3 reserveAspectRatio="xMidYMin meet" \2 \4';
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync return re.sub(r'(<svg) (height="\d+pt") (version="\d+.\d+" viewBox="\d+ \d+ \d+ \d+") (width="\d+pt")',
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync sSubstitute,
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync oOutput.getvalue().decode('utf8'),
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync count = 1);
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsyncclass WuiHlpBarGraph(WuiHlpGraphMatplotlibBase):
af062818b47340eef15700d2f0211576ba3506eevboxsync """
af062818b47340eef15700d2f0211576ba3506eevboxsync Bar graph.
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync """
5112e32d7072e280613921c982a6672f2c859cf3vboxsync
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync def __init__(self, sId, oData, oDisp = None):
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync WuiHlpGraphMatplotlibBase.__init__(self, sId, oData, oDisp);
5112e32d7072e280613921c982a6672f2c859cf3vboxsync self.fpMax = None;
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync self.fpMin = 0;
5112e32d7072e280613921c982a6672f2c859cf3vboxsync self.cxBarWidth = None;
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync def setRangeMax(self, fpMax):
af062818b47340eef15700d2f0211576ba3506eevboxsync """ Sets the max range."""
5112e32d7072e280613921c982a6672f2c859cf3vboxsync self.fpMax = float(fpMax);
5112e32d7072e280613921c982a6672f2c859cf3vboxsync return None;
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync def renderGraph(self): # pylint: disable=R0914
5112e32d7072e280613921c982a6672f2c859cf3vboxsync aoTable = self._oData.aoTable;
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync
5112e32d7072e280613921c982a6672f2c859cf3vboxsync #
5112e32d7072e280613921c982a6672f2c859cf3vboxsync # Extract/structure the required data.
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync #
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync aoSeries = list();
5112e32d7072e280613921c982a6672f2c859cf3vboxsync for j in range(len(aoTable[1].aoValues)):
5112e32d7072e280613921c982a6672f2c859cf3vboxsync aoSeries.append(list());
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync asNames = list();
5112e32d7072e280613921c982a6672f2c859cf3vboxsync oXRange = numpy_arange(self._oData.getGroupCount());
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync fpMin = self.fpMin;
5112e32d7072e280613921c982a6672f2c859cf3vboxsync fpMax = self.fpMax;
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync if self.fpMax is None:
5112e32d7072e280613921c982a6672f2c859cf3vboxsync fpMax = float(aoTable[1].aoValues[0]);
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync for i in range(1, len(aoTable)):
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync asNames.append(aoTable[i].sName);
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync for j in range(len(aoTable[i].aoValues)):
5112e32d7072e280613921c982a6672f2c859cf3vboxsync fpValue = float(aoTable[i].aoValues[j]);
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync aoSeries[j].append(fpValue);
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync if fpValue < fpMin:
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync fpMin = fpValue;
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync if fpValue > fpMax:
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync fpMax = fpValue;
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync fpMid = fpMin + (fpMax - fpMin) / 2.0;
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync if self.cxBarWidth is None:
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync self.cxBarWidth = 1.0 / (len(aoTable[0].asValues) + 1.1);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync # Render the PNG.
af062818b47340eef15700d2f0211576ba3506eevboxsync oFigure = self._createFigure();
af062818b47340eef15700d2f0211576ba3506eevboxsync oSubPlot = oFigure.add_subplot(1, 1, 1);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync aoBars = list();
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync for i in range(len(aoSeries)):
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync sColor = self.calcSeriesColor(i);
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync aoBars.append(oSubPlot.bar(oXRange + self.cxBarWidth * i,
5112e32d7072e280613921c982a6672f2c859cf3vboxsync aoSeries[i],
5112e32d7072e280613921c982a6672f2c859cf3vboxsync self.cxBarWidth,
5112e32d7072e280613921c982a6672f2c859cf3vboxsync color = sColor,
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync align = 'edge'));
5112e32d7072e280613921c982a6672f2c859cf3vboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync #oSubPlot.set_title('Title')
af062818b47340eef15700d2f0211576ba3506eevboxsync #oSubPlot.set_xlabel('X-axis')
af062818b47340eef15700d2f0211576ba3506eevboxsync #oSubPlot.set_xticks(oXRange + self.cxBarWidth);
af062818b47340eef15700d2f0211576ba3506eevboxsync oSubPlot.set_xticks(oXRange);
af062818b47340eef15700d2f0211576ba3506eevboxsync oLegend = oSubPlot.legend(aoTable[0].asValues, loc = 'best', fancybox = True);
af062818b47340eef15700d2f0211576ba3506eevboxsync oLegend.get_frame().set_alpha(0.5);
af062818b47340eef15700d2f0211576ba3506eevboxsync oSubPlot.set_xticklabels(asNames, ha = "left");
af062818b47340eef15700d2f0211576ba3506eevboxsync #oSubPlot.set_ylabel('Y-axis')
af062818b47340eef15700d2f0211576ba3506eevboxsync oSubPlot.set_yticks(numpy_arange(fpMin, fpMax + (fpMax - fpMin) / 10 * 0, fpMax / 10));
af062818b47340eef15700d2f0211576ba3506eevboxsync oSubPlot.grid(True);
af062818b47340eef15700d2f0211576ba3506eevboxsync fpPadding = (fpMax - fpMin) * 0.02;
af062818b47340eef15700d2f0211576ba3506eevboxsync for i in range(len(aoBars)):
af062818b47340eef15700d2f0211576ba3506eevboxsync aoRects = aoBars[i]
af062818b47340eef15700d2f0211576ba3506eevboxsync for j in range(len(aoRects)):
af062818b47340eef15700d2f0211576ba3506eevboxsync oRect = aoRects[j];
af062818b47340eef15700d2f0211576ba3506eevboxsync fpValue = float(aoTable[j + 1].aoValues[i]);
af062818b47340eef15700d2f0211576ba3506eevboxsync if fpValue <= fpMid:
af062818b47340eef15700d2f0211576ba3506eevboxsync oSubPlot.text(oRect.get_x() + oRect.get_width() / 2.0,
af062818b47340eef15700d2f0211576ba3506eevboxsync oRect.get_height() + fpPadding,
af062818b47340eef15700d2f0211576ba3506eevboxsync aoTable[j + 1].asValues[i],
af062818b47340eef15700d2f0211576ba3506eevboxsync ha = 'center', va = 'bottom', rotation = 'vertical', alpha = 0.6, fontsize = 'small');
af062818b47340eef15700d2f0211576ba3506eevboxsync else:
af062818b47340eef15700d2f0211576ba3506eevboxsync oSubPlot.text(oRect.get_x() + oRect.get_width() / 2.0,
af062818b47340eef15700d2f0211576ba3506eevboxsync oRect.get_height() - fpPadding,
af062818b47340eef15700d2f0211576ba3506eevboxsync aoTable[j + 1].asValues[i],
af062818b47340eef15700d2f0211576ba3506eevboxsync ha = 'center', va = 'top', rotation = 'vertical', alpha = 0.6, fontsize = 'small');
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync return self._produceSvg(oFigure);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsyncclass WuiHlpLineGraph(WuiHlpGraphMatplotlibBase):
af062818b47340eef15700d2f0211576ba3506eevboxsync """
af062818b47340eef15700d2f0211576ba3506eevboxsync Line graph.
af062818b47340eef15700d2f0211576ba3506eevboxsync """
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync def __init__(self, sId, oData, oDisp = None, fErrorBarY = False):
af062818b47340eef15700d2f0211576ba3506eevboxsync # oData must be a WuiHlpGraphDataTableEx like object.
af062818b47340eef15700d2f0211576ba3506eevboxsync WuiHlpGraphMatplotlibBase.__init__(self, sId, oData, oDisp);
af062818b47340eef15700d2f0211576ba3506eevboxsync self._cMaxErrorBars = 12;
af062818b47340eef15700d2f0211576ba3506eevboxsync self._fErrorBarY = fErrorBarY;
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync def setErrorBarY(self, fEnable):
af062818b47340eef15700d2f0211576ba3506eevboxsync """ Enables or Disables error bars, making this work like a line graph. """
af062818b47340eef15700d2f0211576ba3506eevboxsync self._fErrorBarY = fEnable;
af062818b47340eef15700d2f0211576ba3506eevboxsync return True;
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync def renderGraph(self): # pylint: disable=R0914
af062818b47340eef15700d2f0211576ba3506eevboxsync aoSeries = self._oData.aoSeries;
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync oFigure = self._createFigure();
af062818b47340eef15700d2f0211576ba3506eevboxsync oSubPlot = oFigure.add_subplot(1, 1, 1);
af062818b47340eef15700d2f0211576ba3506eevboxsync if self._oData.sYUnit is not None:
af062818b47340eef15700d2f0211576ba3506eevboxsync oSubPlot.set_ylabel(self._oData.sYUnit);
af062818b47340eef15700d2f0211576ba3506eevboxsync if self._oData.sXUnit is not None:
af062818b47340eef15700d2f0211576ba3506eevboxsync oSubPlot.set_xlabel(self._oData.sXUnit);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync cSeriesNames = 0;
af062818b47340eef15700d2f0211576ba3506eevboxsync cYMin = 1000;
af062818b47340eef15700d2f0211576ba3506eevboxsync cYMax = 0;
af062818b47340eef15700d2f0211576ba3506eevboxsync for iSeries, oSeries in enumerate(aoSeries):
af062818b47340eef15700d2f0211576ba3506eevboxsync sColor = self.calcSeriesColor(iSeries);
af062818b47340eef15700d2f0211576ba3506eevboxsync cYMin = min(cYMin, min(oSeries.aoYValues));
af062818b47340eef15700d2f0211576ba3506eevboxsync cYMax = max(cYMax, max(oSeries.aoYValues));
af062818b47340eef15700d2f0211576ba3506eevboxsync if not self._fErrorBarY:
af062818b47340eef15700d2f0211576ba3506eevboxsync oSubPlot.errorbar(oSeries.aoXValues, oSeries.aoYValues, color = sColor);
af062818b47340eef15700d2f0211576ba3506eevboxsync elif len(oSeries.aoXValues) > self._cMaxErrorBars:
af062818b47340eef15700d2f0211576ba3506eevboxsync if matplotlib.__version__ < '1.3.0':
af062818b47340eef15700d2f0211576ba3506eevboxsync oSubPlot.errorbar(oSeries.aoXValues, oSeries.aoYValues, color = sColor);
af062818b47340eef15700d2f0211576ba3506eevboxsync else:
af062818b47340eef15700d2f0211576ba3506eevboxsync oSubPlot.errorbar(oSeries.aoXValues, oSeries.aoYValues,
af062818b47340eef15700d2f0211576ba3506eevboxsync yerr = [oSeries.aoYErrorBarBelow, oSeries.aoYErrorBarAbove],
af062818b47340eef15700d2f0211576ba3506eevboxsync errorevery = len(oSeries.aoXValues) / self._cMaxErrorBars,
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync color = sColor );
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync else:
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync oSubPlot.errorbar(oSeries.aoXValues, oSeries.aoYValues,
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync yerr = [oSeries.aoYErrorBarBelow, oSeries.aoYErrorBarAbove],
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync color = sColor);
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync cSeriesNames += oSeries.sName is not None;
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync if cYMin != 0 or cYMax != 0:
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync oSubPlot.set_ylim(bottom = 0);
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync if cSeriesNames > 0:
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync oLegend = oSubPlot.legend([oSeries.sName for oSeries in aoSeries], loc = 'best', fancybox = True);
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync oLegend.get_frame().set_alpha(0.5);
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync if self._sTitle is not None:
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync oSubPlot.set_title(self._sTitle);
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync if self._cxGraph >= 256:
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync oSubPlot.minorticks_on();
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync oSubPlot.grid(True, 'major', axis = 'both');
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync oSubPlot.grid(True, 'both', axis = 'x');
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync if True:
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync # oSubPlot.axis('off');
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync #oSubPlot.grid(True, 'major', axis = 'none');
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync #oSubPlot.grid(True, 'both', axis = 'none');
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync matplotlib.pyplot.setp(oSubPlot, xticks = [], yticks = []);
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync return self._produceSvg(oFigure);
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsyncclass WuiHlpLineGraphErrorbarY(WuiHlpLineGraph):
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync """
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync Line graph with an errorbar for the Y axis.
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync """
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync def __init__(self, sId, oData, oDisp = None):
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync WuiHlpLineGraph.__init__(self, sId, oData, fErrorBarY = True);
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsyncclass WuiHlpMiniSuccessRateGraph(WuiHlpGraphMatplotlibBase):
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync """
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync Mini rate graph.
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync """
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync def __init__(self, sId, oData, oDisp = None):
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync """
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync oData must be a WuiHlpGraphDataTableEx like object, but only aoSeries,
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync aoSeries[].aoXValues, and aoSeries[].aoYValues will be used. The
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync values are expected to be a percentage, i.e. values between 0 and 100.
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync """
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync WuiHlpGraphMatplotlibBase.__init__(self, sId, oData, oDisp);
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync self.setFontSize(6);
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync def renderGraph(self): # pylint: disable=R0914
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync assert len(self._oData.aoSeries) == 1;
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync oSeries = self._oData.aoSeries[0];
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync # hacking
af062818b47340eef15700d2f0211576ba3506eevboxsync #self.setWidth(512);
af062818b47340eef15700d2f0211576ba3506eevboxsync #self.setHeight(128);
af062818b47340eef15700d2f0211576ba3506eevboxsync # end
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync oFigure = self._createFigure();
af062818b47340eef15700d2f0211576ba3506eevboxsync from mpl_toolkits.axes_grid.axislines import SubplotZero;
af062818b47340eef15700d2f0211576ba3506eevboxsync oAxis = SubplotZero(oFigure, 111);
af062818b47340eef15700d2f0211576ba3506eevboxsync oFigure.add_subplot(oAxis);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync # Disable all the normal axis.
af062818b47340eef15700d2f0211576ba3506eevboxsync oAxis.axis['right'].set_visible(False)
af062818b47340eef15700d2f0211576ba3506eevboxsync oAxis.axis['top'].set_visible(False)
af062818b47340eef15700d2f0211576ba3506eevboxsync oAxis.axis['bottom'].set_visible(False)
af062818b47340eef15700d2f0211576ba3506eevboxsync oAxis.axis['left'].set_visible(False)
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync # Use the zero axis instead.
af062818b47340eef15700d2f0211576ba3506eevboxsync oAxis.axis['yzero'].set_axisline_style('-|>');
af062818b47340eef15700d2f0211576ba3506eevboxsync oAxis.axis['yzero'].set_visible(True);
af062818b47340eef15700d2f0211576ba3506eevboxsync oAxis.axis['xzero'].set_axisline_style('-|>');
af062818b47340eef15700d2f0211576ba3506eevboxsync oAxis.axis['xzero'].set_visible(True);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync if oSeries.aoYValues[-1] == 100:
af062818b47340eef15700d2f0211576ba3506eevboxsync sColor = 'green';
af062818b47340eef15700d2f0211576ba3506eevboxsync elif oSeries.aoYValues[-1] > 75:
af062818b47340eef15700d2f0211576ba3506eevboxsync sColor = 'yellow';
af062818b47340eef15700d2f0211576ba3506eevboxsync else:
af062818b47340eef15700d2f0211576ba3506eevboxsync sColor = 'red';
af062818b47340eef15700d2f0211576ba3506eevboxsync oAxis.plot(oSeries.aoXValues, oSeries.aoYValues, '.-', color = sColor, linewidth = 3);
af062818b47340eef15700d2f0211576ba3506eevboxsync oAxis.fill_between(oSeries.aoXValues, oSeries.aoYValues, facecolor = sColor, alpha = 0.5)
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync oAxis.set_xlim(left = -0.01);
af062818b47340eef15700d2f0211576ba3506eevboxsync oAxis.set_xticklabels([]);
af062818b47340eef15700d2f0211576ba3506eevboxsync oAxis.set_xmargin(1);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync oAxis.set_ylim(bottom = 0, top = 100);
af062818b47340eef15700d2f0211576ba3506eevboxsync oAxis.set_yticks([0, 50, 100]);
af062818b47340eef15700d2f0211576ba3506eevboxsync oAxis.set_ylabel('%');
af062818b47340eef15700d2f0211576ba3506eevboxsync #oAxis.set_yticklabels([]);
af062818b47340eef15700d2f0211576ba3506eevboxsync oAxis.set_yticklabels(['', '%', '']);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync return self._produceSvg(oFigure, False);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync