Browse Source

Add stacked line

pull/8/head
Florian Mounier 13 years ago
parent
commit
99490df40a
  1. 8
      demo/moulinrouge/__init__.py
  2. 19
      demo/simple_test.py
  3. 1
      pygal/__init__.py
  4. 4
      pygal/graph/base.py
  5. 10
      pygal/graph/line.py
  6. 2
      pygal/graph/radar.py
  7. 38
      pygal/graph/stackedline.py

8
demo/moulinrouge/__init__.py

@ -83,7 +83,7 @@ def create_app():
random_value((-max, min)[random.randrange(0, 2)], max)) random_value((-max, min)[random.randrange(0, 2)], max))
for i in range(data)] for i in range(data)]
else: else:
values = [random_value((-max, min)[random.randrange(0, 2)], values = [random_value((-max, min)[random.randrange(1, 2)],
max) for i in range(data)] max) for i in range(data)]
g.add(random_label(), values) g.add(random_label(), values)
return g.render_response() return g.render_response()
@ -94,8 +94,10 @@ def create_app():
svgs = [url_for('all_svg', type=type, style=style, fill=fill) svgs = [url_for('all_svg', type=type, style=style, fill=fill)
for style in styles for style in styles
for fill in (False, True) for fill in (False, True)
for type in ('Bar', 'Line', 'XY', 'Pie', 'StackedBar', for type in ('Bar', 'Line', 'XY', 'StackedBar',
'HorizontalBar', 'HorizontalStackedBar', 'Radar')] 'StackedLine', 'HorizontalBar',
'HorizontalStackedBar',
'Pie', 'Radar')]
return render_template('svgs.jinja2', return render_template('svgs.jinja2',
svgs=svgs, svgs=svgs,
width=width, width=width,

19
demo/simple_test.py

@ -19,7 +19,7 @@
# along with pygal. If not, see <http://www.gnu.org/licenses/>. # along with pygal. If not, see <http://www.gnu.org/licenses/>.
from pygal import ( from pygal import (
Line, Bar, XY, Pie, Radar, StackedBar, Config, Line, Bar, XY, Pie, Radar, StackedBar, Config,
HorizontalBar, HorizontalStackedBar) StackedLine, HorizontalBar, HorizontalStackedBar)
from pygal.style import NeonStyle from pygal.style import NeonStyle
from math import cos, sin from math import cos, sin
@ -72,16 +72,25 @@ hstackedbar.add('--->', rng3)
with open('out-horizontalstackedbar.svg', 'w') as f: with open('out-horizontalstackedbar.svg', 'w') as f:
f.write(hstackedbar.render()) f.write(hstackedbar.render())
line = Line(Config(y_scale=.0005)) line = Line(Config(y_scale=.0005, fill=True, style=NeonStyle))
rng = range(-30, 31, 5) rng = range(-30, 31, 5)
line.add('test1', [1000 + cos(x / 10.) for x in rng]) line.add('test1', [cos(x / 10.) for x in rng])
line.add('test2', [1000 + sin(x / 10.) for x in rng]) line.add('test2', [sin(x / 10.) for x in rng])
line.add('test3', [1000 + cos(x / 10.) - sin(x / 10.) for x in rng]) line.add('test3', [cos(x / 10.) - sin(x / 10.) for x in rng])
line.x_labels = map(str, rng) line.x_labels = map(str, rng)
line.title = "Line test" line.title = "Line test"
with open('out-line.svg', 'w') as f: with open('out-line.svg', 'w') as f:
f.write(line.render()) f.write(line.render())
stackedline = StackedLine(Config(y_scale=.0005, fill=True, style=NeonStyle))
stackedline.add('test1', [1, 3, 2, 18, 2, 13, 8])
stackedline.add('test2', [4, 1, 0, 1, 3, 12, 3])
stackedline.add('test3', [9, 3, 2, 10, 8, 2, 3])
stackedline.x_labels = map(str, ['a', 'b', 'c', 'd', 'e', 'f', 'g'])
stackedline.title = "Stackedline test"
with open('out-stackedline.svg', 'w') as f:
f.write(stackedline.render())
xy = XY(Config(x_scale=1)) xy = XY(Config(x_scale=1))
xy.add('test1', [(1981, 1), (2004, 2), (2003, 10), (2012, 8), (1999, -4)]) xy.add('test1', [(1981, 1), (2004, 2), (2003, 10), (2012, 8), (1999, -4)])
xy.add('test2', [(1988, -1), (1986, 12), (2007, 7), (2010, 4), (1999, 2)]) xy.add('test2', [(1988, -1), (1986, 12), (2007, 7), (2010, 4), (1999, 2)])

1
pygal/__init__.py

@ -24,6 +24,7 @@ from pygal.graph.horizontal import HorizontalBar
from pygal.graph.stackedbar import StackedBar from pygal.graph.stackedbar import StackedBar
from pygal.graph.horizontal import HorizontalStackedBar from pygal.graph.horizontal import HorizontalStackedBar
from pygal.graph.line import Line from pygal.graph.line import Line
from pygal.graph.stackedline import StackedLine
from pygal.graph.xy import XY from pygal.graph.xy import XY
from pygal.graph.pie import Pie from pygal.graph.pie import Pie
from pygal.graph.radar import Radar from pygal.graph.radar import Radar

4
pygal/graph/base.py

@ -88,6 +88,10 @@ class BaseGraph(object):
def _values(self): def _values(self):
return [val for serie in self.series for val in serie.values] return [val for serie in self.series for val in serie.values]
@cached_property
def _len(self):
return len(self.series[0].values)
def _draw(self): def _draw(self):
self._compute() self._compute()
self._compute_margin() self._compute_margin()

10
pygal/graph/line.py

@ -38,6 +38,11 @@ class Line(Graph):
self.svg.node(dot, 'circle', cx=x, cy=y, r=2.5) self.svg.node(dot, 'circle', cx=x, cy=y, r=2.5)
self.svg.node(dot, 'text', x=x, y=y self.svg.node(dot, 'text', x=x, y=y
).text = self._get_value(values, i) ).text = self._get_value(values, i)
if self.fill:
zero = self.view.y(min(max(0, self._box.ymin), self._box.ymax))
view_values = ([(view_values[0][0], zero)] +
view_values +
[(view_values[-1][0], zero)])
self.svg.line( self.svg.line(
serie_node, view_values, class_='line', close=self._line_close) serie_node, view_values, class_='line', close=self._line_close)
@ -49,9 +54,8 @@ class Line(Graph):
self._box.ymin = min(self._values) self._box.ymin = min(self._values)
self._box.ymax = max(self._values) self._box.ymax = max(self._values)
x_step = len(self.series[0].values) self._x_pos = [x / float(self._len - 1) for x in range(self._len)
self._x_pos = [x / float(x_step - 1) for x in range(x_step) ] if self._len != 1 else [.5] # Center if only one value
] if x_step != 1 else [.5] # Center if only one value
self._y_pos = self._pos(self._box.ymin, self._box.ymax, self.y_scale self._y_pos = self._pos(self._box.ymin, self._box.ymax, self.y_scale
) if not self.y_labels else map(int, self.y_labels) ) if not self.y_labels else map(int, self.y_labels)

2
pygal/graph/radar.py

@ -19,7 +19,7 @@
from pygal.graph.line import Line from pygal.graph.line import Line
from pygal.view import PolarView from pygal.view import PolarView
from pygal.util import deg from pygal.util import deg
from math import cos, sin, pi from math import cos, pi
class Radar(Line): class Radar(Line):

38
pygal/graph/stackedline.py

@ -0,0 +1,38 @@
# -*- coding: utf-8 -*-
# This file is part of pygal
#
# A python svg graph plotting library
# Copyright © 2012 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/>.
from pygal.graph.line import Line
class StackedLine(Line):
"""Stacked Line graph"""
@property
def _values(self):
sums = map(sum, zip(*[serie.values for serie in self.series]))
return sums + super(StackedLine, self)._values
def _plot(self):
accumulation = map(sum, zip(*[serie.values for serie in self.series]))
for serie in self.series:
self.line(
self._serie(serie.index), [
(self._x_pos[i], v)
for i, v in enumerate(accumulation)])
accumulation = map(sum, zip(accumulation,
[-v for v in serie.values]))
Loading…
Cancel
Save