File: stackedline.py

package info (click to toggle)
python-pygal 3.0.5-1
  • links: PTS
  • area: main
  • in suites: forky, sid, trixie
  • size: 636 kB
  • sloc: python: 7,359; makefile: 9
file content (80 lines) | stat: -rw-r--r-- 3,161 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# -*- 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/>.
"""
Stacked Line chart: Like a line chart but with all lines stacking
on top of the others. Used along fill=True option.
"""

from pygal.adapters import none_to_zero
from pygal.graph.line import Line


class StackedLine(Line):
    """Stacked Line graph class"""

    _adapters = [none_to_zero]

    def __init__(self, *args, **kwargs):
        """Custom variable initialization"""
        self._previous_line = None
        super(StackedLine, self).__init__(*args, **kwargs)

    def _value_format(self, value, serie, index):
        """
        Display value and cumulation
        """
        sum_ = serie.points[index][1]
        if serie in self.series and (
                self.stack_from_top
                and self.series.index(serie) == self._order - 1
                or not self.stack_from_top and self.series.index(serie) == 0):
            return super(StackedLine, self)._value_format(value)
        return '%s (+%s)' % (self._y_format(sum_), self._y_format(value))

    def _fill(self, values):
        """Add extra values to fill the line"""
        if not self._previous_line:
            self._previous_line = values
            return super(StackedLine, self)._fill(values)
        new_values = values + list(reversed(self._previous_line))
        self._previous_line = values
        return new_values

    def _points(self, x_pos):
        """
        Convert given data values into drawable points (x, y)
        and interpolated points if interpolate option is specified
        """
        for series_group in (self.series, self.secondary_series):
            accumulation = [0] * self._len
            for serie in series_group[::-1 if self.stack_from_top else 1]:
                accumulation = list(map(sum, zip(accumulation, serie.values)))
                serie.points = [(x_pos[i], v)
                                for i, v in enumerate(accumulation)]
                if serie.points and self.interpolate:
                    serie.interpolated = self._interpolate(x_pos, accumulation)
                else:
                    serie.interpolated = []

    def _plot(self):
        """Plot stacked serie lines and stacked secondary lines"""
        for serie in self.series[::-1 if self.stack_from_top else 1]:
            self.line(serie)
        for serie in self.secondary_series[::-1 if self.stack_from_top else 1]:
            self.line(serie, True)