Source code for pygal.graph.solidgauge

# -*- coding: utf-8 -*-
# This file is part of pygal
#
# A python svg graph plotting library
# Copyright © 2012-2016 Kozea
#
# This library is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# This library is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with pygal. If not, see <http://www.gnu.org/licenses/>.


"""
Solid Guage
For each series a solid guage is shown on the plot area.
"""
from __future__ import division


from math import pi, sqrt

from pygal.graph.graph import Graph
from pygal.util import alter, decorate


[docs]class SolidGauge(Graph):
[docs] def gaugify(self, serie, squares, sq_dimensions, current_square): serie_node = self.svg.serie(serie) if self.half_pie: start_angle = 3*pi/2 center = ( (current_square[1]*sq_dimensions[0]) - (sq_dimensions[0] / 2.), (current_square[0]*sq_dimensions[1]) - (sq_dimensions[1] / 4)) end_angle = pi / 2 else: start_angle = 0 center = ( (current_square[1]*sq_dimensions[0]) - (sq_dimensions[0] / 2.), (current_square[0]*sq_dimensions[1]) - (sq_dimensions[1] / 2.)) end_angle = 2 * pi max_value = serie.metadata.get(0, {}).get('max_value', 100) radius = min([sq_dimensions[0]/2, sq_dimensions[1]/2]) * .9 small_radius = radius * serie.inner_radius self.svg.gauge_background( serie_node, start_angle, center, radius, small_radius, end_angle, self.half_pie, self._serie_format(serie, max_value)) sum_ = 0 for i, value in enumerate(serie.values): if value is None: continue ratio = min(value, max_value) / max_value if self.half_pie: angle = 2 * pi * ratio / 2 else: angle = 2 * pi * ratio val = self._format(serie, i) metadata = serie.metadata.get(i) gauge_ = decorate( self.svg, self.svg.node(serie_node['plot'], class_="gauge"), metadata) alter( self.svg.solid_gauge( serie_node, gauge_, radius, small_radius, angle, start_angle, center, val, i, metadata, self.half_pie, end_angle, self._serie_format(serie, max_value)), metadata) start_angle += angle sum_ += value x, y = center self.svg.node( serie_node['text_overlay'], 'text', class_='value gauge-sum', x=x, y=y + self.style.value_font_size / 3, attrib={'text-anchor': 'middle'} ).text = self._serie_format(serie, sum_)
def _compute_x_labels(self): pass def _compute_y_labels(self): pass def _plot(self): """Draw all the serie slices""" squares = self._squares() sq_dimensions = self.add_squares(squares) for index, serie in enumerate(self.series): current_square = self._current_square(squares, index) self.gaugify( serie, squares, sq_dimensions, current_square) def _squares(self): n_series_ = len(self.series) i = 2 if sqrt(n_series_).is_integer(): _x = int(sqrt(n_series_)) _y = int(sqrt(n_series_)) else: while i * i < n_series_: while n_series_ % i == 0: n_series_ = n_series_ / i i = i + 1 _y = int(n_series_) _x = int(n_series_ / len(self.series)) if len(self.series) == 5: _x, _y = 2, 3 if abs(_x - _y) > 2: _sq = 3 while (_x * _y)-1 < len(self.series): _x, _y = _sq, _sq _sq += 1 return (_x, _y) def _current_square(self, squares, index): current_square = [1, 1] steps = index + 1 steps_taken = 0 for i in range(squares[0] * squares[1]): steps_taken += 1 if steps_taken != steps and steps_taken % squares[0] != 0: current_square[1] += 1 elif steps_taken != steps and steps_taken % squares[0] == 0: current_square[1] = 1 current_square[0] += 1 else: return tuple(current_square) raise Exception( 'Something went wrong with the current square assignment.')