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