Browse Source

Fixed failing test case in Pie.add_data. Tests now pass on Python 3

pull/8/head
Jason R. Coombs 13 years ago
parent
commit
46a8dc70ad
  1. 80
      svg/charts/pie.py

80
svg/charts/pie.py

@ -1,5 +1,5 @@
import math
from operator import add
import itertools
from lxml import etree
from svg.charts.graph import Graph
@ -14,15 +14,15 @@ RADIANS = math.pi/180
class Pie(Graph):
"""
A presentation-quality SVG pie graph
Synopsis
========
from svg.charts.pie import Pie
fields = ['Jan', 'Feb', 'Mar']
data_sales_02 = [12, 45, 21]
graph = Pie(dict(
height = 500,
width = 300,
@ -30,7 +30,7 @@ class Pie(Graph):
graph.add_data({'data': data_sales_02, 'title': 'Sales 2002'})
print "Content-type" image/svg+xml\r\n\r\n'
print graph.burn()
Description
===========
This object aims to allow you to easily create high quality
@ -44,14 +44,14 @@ class Pie(Graph):
"if true, displays a drop shadow for the chart"
show_shadow = True
"Sets the offset of the shadow from the pie chart"
shadow_offset = 10
shadow_offset = 10
show_data_labels = False
"If true, display the actual field values in the data labels"
"If true, display the actual field values in the data labels"
show_actual_values = False
"If true, display the percentage value of each pie wedge in the data labels"
show_percent = True
"If true, display the labels in the key"
show_key_data_labels = True
"If true, display the actual value of the field in the key"
@ -59,13 +59,13 @@ class Pie(Graph):
"If true, display the percentage value of the wedges in the key"
show_key_percent = False
"If true, explode the pie (put space between the wedges)"
"If true, explode the pie (put space between the wedges)"
expanded = False
"If true, expand the largest pie wedge"
expand_greatest = False
"The amount of space between expanded wedges"
expand_gap = 10
show_x_labels = False
show_y_labels = False
@ -77,22 +77,38 @@ class Pie(Graph):
def add_data(self, data_descriptor):
"""
Add a data set to the graph
>>> graph.add_data({data:[1,2,3,4]}) # doctest: +SKIP
Note that a 'title' key is ignored.
Multiple calls to add_data will sum the elements, and the pie will
display the aggregated data. e.g.
>>> graph.add_data({data:[1,2,3,4]}) # doctest: +SKIP
>>> graph.add_data({data:[2,3,5,7]}) # doctest: +SKIP
is the same as:
graph.add_data({data:[3,5,8,11]}) # doctest: +SKIP
>>> graph.add_data({data:[3,5,8,11]}) # doctest: +SKIP
If data is added of with differing lengths, the corresponding
values will be assumed to be zero.
>>> graph.add_data({data:[1,2,3,4]}) # doctest: +SKIP
>>> graph.add_data({data:[5,7]}) # doctest: +SKIP
is the same as:
>>> graph.add_data({data:[5,7]}) # doctest: +SKIP
>>> graph.add_data({data:[1,2,3,4]}) # doctest: +SKIP
and
>>> graph.add_data({data:[6,9,3,4]}) # doctest: +SKIP
"""
self.data = map(robust_add, self.data, data_descriptor['data'])
pairs = itertools.izip_longest(self.data, data_descriptor['data'])
self.data = list(itertools.starmap(robust_add, pairs))
def add_defs(self, defs):
"Add svg definitions"
@ -123,7 +139,7 @@ class Pie(Graph):
return ['']
def keys(self):
total = reduce(add, self.data)
total = sum(self.data)
percent_scale = 100.0 / total
def key(field, value):
result = [field]
@ -133,13 +149,13 @@ class Pie(Graph):
result.append(percent)
return ' '.join(result)
return map(key, self.fields, self.data)
def draw_data(self):
self.graph = etree.SubElement(self.root, 'g')
background = etree.SubElement(self.graph, 'g')
# midground is somewhere between the background and the foreground
midground = etree.SubElement(self.graph, 'g')
is_expanded = (self.expanded or self.expand_greatest)
diameter = min(self.graph_width, self.graph_height)
# the following assumes int(True)==1 and int(False)==0
@ -157,7 +173,7 @@ class Pie(Graph):
wedge_text_pad = 5
wedge_text_pad = 20 * int(self.show_percent) * int(self.show_data_labels)
total = reduce(add, self.data)
total = sum(self.data)
max_value = max(self.data)
percent_scale = 100.0 / total
@ -166,7 +182,7 @@ class Pie(Graph):
rad_mult = 3.6 * RADIANS
for index, (field, value) in enumerate(zip(self.fields, self.data)):
percent = percent_scale * value
radians = prev_percent * rad_mult
x_start = radius+(math.sin(radians) * radius)
y_start = radius-(math.cos(radians) * radius)
@ -182,7 +198,7 @@ class Pie(Graph):
"%(percent_greater_fifty)s,1,",
"%(x_end)s %(y_end)s Z"))
path = path % vars()
wedge = etree.SubElement(
self.foreground,
'path',
@ -191,13 +207,13 @@ class Pie(Graph):
'class': 'fill%s' % (index+1),
}
)
translate = None
tx = 0
ty = 0
half_percent = prev_percent + percent / 2
radians = half_percent * rad_mult
if self.show_shadow:
shadow = etree.SubElement(
background,
@ -215,20 +231,20 @@ class Pie(Graph):
# consider getting the style from the stylesheet
style="fill:#fff; stroke:none;",
)
if self.expanded or (self.expand_greatest and value == max_value):
tx = (math.sin(radians) * self.expand_gap)
ty = -(math.cos(radians) * self.expand_gap)
translate = "translate(%(tx)s %(ty)s)" % vars()
wedge.set('transform', translate)
clear.set('transform', translate)
if self.show_shadow:
shadow_tx = self.shadow_offset + tx
shadow_ty = self.shadow_offset + ty
translate = 'translate(%(shadow_tx)s %(shadow_ty)s)' % vars()
shadow.set('transform', translate)
if self.show_data_labels and value != 0:
label = []
if self.show_key_data_labels:
@ -243,7 +259,7 @@ class Pie(Graph):
mcr = math.cos(radians)
tx = radius + (msr * radius)
ty = radius -(mcr * radius)
if self.expanded or (self.expand_greatest and value == max_value):
tx += (msr * self.expand_gap)
ty -= (mcr * self.expand_gap)
@ -270,7 +286,7 @@ class Pie(Graph):
}
)
label_node.text = label
prev_percent += percent
def round(self, val, to):

Loading…
Cancel
Save