From 7c30891274b541ad7c34e15275a8d1ece20cfb29 Mon Sep 17 00:00:00 2001 From: Florian Mounier Date: Wed, 3 Oct 2012 16:41:46 +0200 Subject: [PATCH] Fix log --- demo/moulinrouge/tests.py | 2 ++ pygal/graph/bar.py | 2 +- pygal/graph/graph.py | 4 ++-- pygal/graph/horizontal.py | 4 ++-- pygal/graph/stackedbar.py | 14 ++++++++----- pygal/view.py | 44 +++++++++++++++++++++++++++++---------- 6 files changed, 49 insertions(+), 21 deletions(-) diff --git a/demo/moulinrouge/tests.py b/demo/moulinrouge/tests.py index 4d4429ea..b56fbc0a 100644 --- a/demo/moulinrouge/tests.py +++ b/demo/moulinrouge/tests.py @@ -132,6 +132,8 @@ def test_logarithmic_for(chart): else: graph.add('1', [.1, 10, .001, 1000000]) graph.add('2', [.234, 243, 2, 2981379, 1231]) + graph.x_labels = ('a', 'b', 'c', 'd', 'e') + graph.x_label_rotation = 45 return graph.render_response() @app.route('/test/zero_at_34/') diff --git a/pygal/graph/bar.py b/pygal/graph/bar.py index 14165c04..60e85fdd 100644 --- a/pygal/graph/bar.py +++ b/pygal/graph/bar.py @@ -62,7 +62,7 @@ def bar(self, serie_node, serie, index): """Draw a bar graph for a serie""" bars = self.svg.node(serie_node['plot'], class_="bars") for i, (x, y) in enumerate(serie.points): - if None in (x, y): + if None in (x, y) or (self.logarithmic and y <= 0): continue metadata = serie.metadata.get(i) diff --git a/pygal/graph/graph.py b/pygal/graph/graph.py index 74025945..66101b31 100644 --- a/pygal/graph/graph.py +++ b/pygal/graph/graph.py @@ -24,7 +24,7 @@ from __future__ import division from pygal.interpolate import interpolation from pygal.graph.base import BaseGraph -from pygal.view import View, XLogView, YLogView, XYLogView, HorizontalView +from pygal.view import View, LogView, XYLogView from pygal.util import is_major, truncate, reverse_text_len from math import isnan, pi, sqrt, ceil @@ -51,7 +51,7 @@ def _set_view(self): if self.__class__.__name__ == 'XY': view_class = XYLogView else: - view_class = YLogView + view_class = LogView else: view_class = View diff --git a/pygal/graph/horizontal.py b/pygal/graph/horizontal.py index e541faa9..08bd2c34 100644 --- a/pygal/graph/horizontal.py +++ b/pygal/graph/horizontal.py @@ -21,7 +21,7 @@ """ from pygal.graph.graph import Graph -from pygal.view import HorizontalView, XLogView +from pygal.view import HorizontalView, HorizontalLogView class HorizontalGraph(Graph): @@ -42,7 +42,7 @@ def _axes(self): def _set_view(self): """Assign a view to current graph""" if self.logarithmic: - view_class = XLogView + view_class = HorizontalLogView else: view_class = HorizontalView diff --git a/pygal/graph/stackedbar.py b/pygal/graph/stackedbar.py index 66bf9161..044304c5 100644 --- a/pygal/graph/stackedbar.py +++ b/pygal/graph/stackedbar.py @@ -44,6 +44,10 @@ def _compute(self): if val is not None and val < self.zero]) for vals in transposed] + if self.logarithmic: + positive_vals = filter(lambda x: x > 0, positive_vals) + negative_vals = filter(lambda x: x > 0, negative_vals) + positive_vals = positive_vals or [self.zero] negative_vals = negative_vals or [self.zero] @@ -68,13 +72,13 @@ def _compute(self): self.negative_cumulation = [0] * self._len self.positive_cumulation = [0] * self._len - def _bar(self, parent, x, val, index, i, zero): - cumulation = (self.negative_cumulation if val < self.zero else + def _bar(self, parent, x, y, index, i, zero): + cumulation = (self.negative_cumulation if y < self.zero else self.positive_cumulation) zero = cumulation[i] - cumulation[i] = zero + val + cumulation[i] = zero + y if zero == 0: zero = self.zero - val -= self.zero + y -= self.zero return super(StackedBar, self)._bar( - parent, x, zero + val, index, i, zero, False) + parent, x, zero + y, index, i, zero, False) diff --git a/pygal/view.py b/pygal/view.py index 35b84431..a7a4b5bc 100644 --- a/pygal/view.py +++ b/pygal/view.py @@ -150,7 +150,7 @@ def __call__(self, rhotheta): (rho * cos(theta), rho * sin(theta))) -class YLogView(View): +class LogView(View): """Logarithmic projection """ # Do not want to call the parent here # pylint: disable-msg=W0231 @@ -158,8 +158,6 @@ def __init__(self, width, height, box): self.width = width self.height = height self.box = box - self.ymin = self.box.ymin - self.ymax = self.box.ymax self.log10_ymax = log10(self.box.ymax) self.log10_ymin = log10(self.box.ymin) self.box.fix(False) @@ -182,8 +180,6 @@ def __init__(self, width, height, box): self.width = width self.height = height self.box = box - self.xmin = self.box.xmin - self.xmax = self.box.xmax self.log10_xmax = log10(self.box.xmax) self.log10_xmin = log10(self.box.xmin) self.box.fix(False) @@ -193,22 +189,48 @@ def x(self, x): """Project x""" if x is None or x <= 0 or self.log10_xmax - self.log10_xmin == 0: return None - return (self.width - self.width * + return (self.width * (log10(x) - self.log10_xmin) / (self.log10_xmax - self.log10_xmin)) -class XYLogView(XLogView, YLogView): +class XYLogView(XLogView, LogView): def __init__(self, width, height, box): self.width = width self.height = height self.box = box - self.xmin = self.box.xmin - self.xmax = self.box.xmax - self.ymin = self.box.ymin - self.ymax = self.box.ymax self.log10_ymax = log10(self.box.ymax) self.log10_ymin = log10(self.box.ymin) self.log10_xmax = log10(self.box.xmax) self.log10_xmin = log10(self.box.xmin) self.box.fix(False) + + +class HorizontalLogView(XLogView): + """Logarithmic projection """ + # Do not want to call the parent here + # pylint: disable-msg=W0231 + def __init__(self, width, height, box): + self._force_vertical = None + self.width = width + self.height = height + self.box = box + self.log10_xmax = log10(self.box.ymax) + self.log10_xmin = log10(self.box.ymin) + self.box.fix(False) + self.box.swap() + + def x(self, x): + """Project x""" + if x is None: + return None + if self._force_vertical: + return super(HorizontalLogView, self).x(x) + return super(XLogView, self).y(x) + + def y(self, y): + if y is None: + return None + if self._force_vertical: + return super(XLogView, self).y(y) + return super(HorizontalLogView, self).x(y)