Browse Source

Handle rounding

pull/8/head
Florian Mounier 13 years ago
parent
commit
72d5a82721
  1. 24
      pygal/bar.py
  2. 24
      pygal/line.py
  3. 11
      pygal/test/test_bar.py
  4. 6
      pygal/test/test_line.py
  5. 22
      pygal/test/test_util.py
  6. 18
      pygal/util.py
  7. 4
      pygal/view.py

24
pygal/bar.py

@ -1,38 +1,38 @@
from pygal import Serie, Margin, Label from pygal import Serie, Margin, Label
from pygal.svg import Svg from pygal.svg import Svg
from pygal.util import round_to_int, round_to_float
from pygal.base import BaseGraph from pygal.base import BaseGraph
class Bar(BaseGraph): class Bar(BaseGraph):
"""Bar graph""" """Bar graph"""
def __init__(self, width, height, precision=5, def __init__(self, width, height, scale=1, style=None):
format='g', style=None):
self.width = width self.width = width
self.height = height self.height = height
self.svg = Svg(width, height, style=style) self.svg = Svg(width, height, style=style)
self.label_font_size = 12 self.label_font_size = 12
self.format = format
self.precision = precision
self.series = [] self.series = []
self.scale = scale
self.x_labels = self.y_labels = self.title = None self.x_labels = self.y_labels = self.title = None
rnd = round_to_float if self.scale < 1 else round_to_int
self.round = lambda x: rnd(x, self.scale)
def add(self, title, values): def add(self, title, values):
self.series.append( self.series.append(Serie(title, values))
Serie(title, values))
def _label(self, label): def _label(self, number):
return Label(('{:.%d%s}' % ( return Label(*self.round(number))
self.precision, self.format)).format(label), label)
def _y_labels(self, ymin, ymax): def _y_labels(self, ymin, ymax):
step = (ymax - ymin) / 20. step = (ymax - ymin) / 20.
if not step: if not step:
return [self._label(ymin)] return [self._label(ymin)]
label = ymin label = ymin
labels = [] labels = set()
while label <= ymax: while label < (ymax + step):
labels.append(self._label(label)) labels.add(self._label(label))
label += step label += step
return labels return labels

24
pygal/line.py

@ -1,38 +1,38 @@
from pygal import Serie, Margin, Label from pygal import Serie, Margin, Label
from pygal.svg import Svg from pygal.svg import Svg
from pygal.util import round_to_int, round_to_float
from pygal.base import BaseGraph from pygal.base import BaseGraph
class Line(BaseGraph): class Line(BaseGraph):
"""Line graph""" """Line graph"""
def __init__(self, width, height, precision=5, def __init__(self, width, height, scale=1, style=None):
format='g', style=None):
self.width = width self.width = width
self.height = height self.height = height
self.svg = Svg(width, height, style=style) self.svg = Svg(width, height, style=style)
self.label_font_size = 12 self.label_font_size = 12
self.format = format
self.precision = precision
self.series = [] self.series = []
self.scale = scale
self.x_labels = self.y_labels = self.title = None self.x_labels = self.y_labels = self.title = None
rnd = round_to_float if self.scale < 1 else round_to_int
self.round = lambda x: rnd(x, self.scale)
def add(self, title, values): def add(self, title, values):
self.series.append( self.series.append(Serie(title, values))
Serie(title, values))
def _label(self, label): def _label(self, number):
return Label(('{:.%d%s}' % ( return Label(*self.round(number))
self.precision, self.format)).format(label), label)
def _y_labels(self, ymin, ymax): def _y_labels(self, ymin, ymax):
step = (ymax - ymin) / 20. step = (ymax - ymin) / 20.
if not step: if not step:
return [self._label(ymin)] return [self._label(ymin)]
label = ymin label = ymin
labels = [] labels = set()
while label <= ymax: while label < (ymax + step):
labels.append(self._label(label)) labels.add(self._label(label))
label += step label += step
return labels return labels

11
pygal/test/test_bar.py

@ -3,9 +3,18 @@ from math import cos, sin
def test_simple_bar(): def test_simple_bar():
bar = Bar(800, 600, precision=2, format='f') bar = Bar(800, 600)
rng = [12, 3, 30, 4, 40, 10, 9, 2] rng = [12, 3, 30, 4, 40, 10, 9, 2]
bar.add('test1', rng) bar.add('test1', rng)
bar.x_labels = map(str, rng) bar.x_labels = map(str, rng)
bar.title = "Bar test" bar.title = "Bar test"
bar.render()
def test_null_bar():
bar = Bar(800, 600, scale=.25)
rng = [1, 1]
bar.add('test1', rng)
bar.x_labels = map(str, rng)
bar.title = "Bar test"
bar._in_browser() bar._in_browser()

6
pygal/test/test_line.py

@ -3,14 +3,14 @@ from math import cos, sin
def test_simple_line(): def test_simple_line():
line = Line(800, 600, precision=2, format='f') line = Line(800, 600)
rng = range(-30, 30, 5) rng = range(-30, 31, 5)
line.add('test1', [cos(x / 10.) for x in rng]) line.add('test1', [cos(x / 10.) for x in rng])
line.add('test2', [sin(x / 10.) for x in rng]) line.add('test2', [sin(x / 10.) for x in rng])
line.add('test3', [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 = "cos sin and cos - sin" line.title = "cos sin and cos - sin"
line.render() line._in_browser()
def test_one_dot(): def test_one_dot():

22
pygal/test/test_util.py

@ -0,0 +1,22 @@
from pygal.util import round_to_int, round_to_float
def test_round_to_int():
assert round_to_int(154231, 1000) == ('154000', 154000)
assert round_to_int(154231, 10) == ('154230', 154230)
assert round_to_int(154231, 100000) == ('200000', 200000)
assert round_to_int(154231, 50000) == ('150000', 150000)
assert round_to_int(154231, 500) == ('154000', 154000)
assert round_to_int(154231, 200) == ('154200', 154200)
assert round_to_int(154361, 200) == ('154400', 154400)
def test_round_to_float():
assert round_to_float(12.01934, .01) == ('12.02', 12.02)
assert round_to_float(12.01134, .01) == ('12.01', 12.01)
assert round_to_float(12.1934, .1) == ('12.2', 12.2)
assert round_to_float(12.1134, .1) == ('12.1', 12.1)
assert round_to_float(12.1134, .001) == ('12.113', 12.113)
assert round_to_float(12.1134, .00001) == ('12.11340', 12.1134)
assert round_to_float(12.1934, .5) == ('12.0', 12.0)
assert round_to_float(12.2934, .5) == ('12.5', 12.5)

18
pygal/util.py

@ -0,0 +1,18 @@
from decimal import Decimal
from math import floor
def round_to_int(number, precision):
rounded = (int(number) + precision / 2) / precision * precision
return str(int(rounded)), rounded
# def round_to_float(number, precision):
# decimal = Decimal(str(number))
# rounded = decimal.quantize(Decimal(str(precision)))
# return str(rounded), float(rounded)
def round_to_float(number, precision):
rounded = Decimal(
floor((number + precision / 2) / precision)) * Decimal(str(precision))
return str(rounded), float(rounded)

4
pygal/view.py

@ -14,8 +14,8 @@ class View(object):
self.height = height self.height = height
xrng = (xmax - xmin) or 1 xrng = (xmax - xmin) or 1
yrng = (ymax - ymin) or 1 yrng = (ymax - ymin) or 1
if yrng == 1: # if yrng == 1:
ymin -= .5 # ymin -= .5x
self.box = Box(xmin, ymin, xrng, yrng) self.box = Box(xmin, ymin, xrng, yrng)
def x(self, x): def x(self, x):

Loading…
Cancel
Save