From 2bb0e9e9916ef22018d200c8aeac773e76c306cf Mon Sep 17 00:00:00 2001 From: Florian Mounier Date: Tue, 7 Feb 2012 19:01:23 +0100 Subject: [PATCH] Fix negative bars --- demo/moulinrouge/__init__.py | 6 +++--- pygal/bar.py | 2 +- pygal/base.py | 9 ++++++--- pygal/config.py | 1 + pygal/svg.py | 6 +++++- pygal/test/test_bar.py | 3 ++- pygal/test/test_line.py | 2 +- 7 files changed, 19 insertions(+), 10 deletions(-) diff --git a/demo/moulinrouge/__init__.py b/demo/moulinrouge/__init__.py index 8cd9a4e..d2c6ae5 100644 --- a/demo/moulinrouge/__init__.py +++ b/demo/moulinrouge/__init__.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- from flask import Flask, Response, render_template, url_for from log_colorizer import make_colored_stream_handler -from logging import getLogger, INFO, WARN, DEBUG +from logging import getLogger, INFO, DEBUG from moulinrouge.data import labels, series # from pygal.bar import VerticalBar, HorizontalBar from pygal.line import Line @@ -9,7 +9,6 @@ from pygal.bar import Bar from pygal.config import Config from pygal.style import styles # from pygal.pie import Pie -import math import string import random @@ -73,7 +72,8 @@ def create_app(): return for i in range(random.randrange(1, 10)): - values = [random_value(min, max) for i in range(data)] + values = [random_value((-max, min)[random.randrange(0, 2)], + max) for i in range(data)] g.add(random_label(), values) return Response(g.render(), mimetype='image/svg+xml') diff --git a/pygal/bar.py b/pygal/bar.py index 24d8ab9..333962b 100644 --- a/pygal/bar.py +++ b/pygal/bar.py @@ -6,7 +6,7 @@ class Bar(BaseGraph): def _draw(self): vals = [val for serie in self.series for val in serie.values] - ymin, ymax = min(min(vals), 0), max(vals) + ymin, ymax = min(min(vals), 0), max(max(vals), 0) x_step = len(self.series[0].values) x_pos = [x / float(x_step) for x in range(x_step + 1) ] if x_step > 1 else [0, 1] # Center if only one value diff --git a/pygal/base.py b/pygal/base.py index a29417e..a4337ae 100644 --- a/pygal/base.py +++ b/pygal/base.py @@ -20,13 +20,16 @@ class BaseGraph(object): return object.__getattribute__(self, attr) def _y_pos(self, ymin, ymax): - order = round(math.log10(ymax)) - 1 + order = round(math.log10(max(abs(ymin), abs(ymax)))) - 1 if (ymax - ymin) / float(10 ** order) < 4: order -= 1 step = 10 ** order positions = set() - position = round_to_scale(ymin, step) - while position < ymax: + if self.x_start_at_zero: + position = 0 + else: + position = round_to_scale(ymin, step) + while position < (ymax + step): rounded = round_to_scale(position, self.scale) if ymin <= rounded <= ymax: positions.add(rounded) diff --git a/pygal/config.py b/pygal/config.py index d98db15..30c5485 100644 --- a/pygal/config.py +++ b/pygal/config.py @@ -12,6 +12,7 @@ class Config(object): x_labels = None y_labels = None title = None + x_start_at_zero = False def __init__(self, **kwargs): self.__dict__.update(kwargs) diff --git a/pygal/svg.py b/pygal/svg.py index 5df5491..af280da 100644 --- a/pygal/svg.py +++ b/pygal/svg.py @@ -164,11 +164,15 @@ class Svg(object): bar_padding = .1 * bar_width bar_inner_width = bar_width - 2 * bar_padding offset = serie.index * bar_width + bar_padding + height = self.view.y(0) - y + if height < 0: + y = y + height + height = -height self.node(serie_node, 'rect', x=x + padding + offset, y=y, width=bar_inner_width, - height=self.view.y(0) - y, + height=height, class_='rect') def render(self): diff --git a/pygal/test/test_bar.py b/pygal/test/test_bar.py index efc988a..8f29218 100644 --- a/pygal/test/test_bar.py +++ b/pygal/test/test_bar.py @@ -4,8 +4,9 @@ from math import cos, sin def test_simple_bar(): bar = Bar() - rng = [12, 3, 30, -5, 40, 10, 9, 2] + rng = [-3, -32, -39] bar.add('test1', rng) + bar.add('test2', map(abs, rng)) bar.x_labels = map(str, rng) bar.title = "Bar test" bar._in_browser() diff --git a/pygal/test/test_line.py b/pygal/test/test_line.py index 7a39b79..2ad78bf 100644 --- a/pygal/test/test_line.py +++ b/pygal/test/test_line.py @@ -4,7 +4,7 @@ from math import cos, sin def test_simple_line(): - line = Line(Config(scale=.5)) + line = Line(Config(scale=.0005)) rng = range(-30, 31, 5) line.add('test1', [cos(x / 10.) for x in rng]) line.add('test2', [sin(x / 10.) for x in rng])