Browse Source

Update documentation

pull/307/head
Florian Mounier 9 years ago
parent
commit
9d70ff3bf9
  1. 14
      demo/moulinrouge/tests.py
  2. 7
      docs/api/pygal.formatters.rst
  3. 1
      docs/api/pygal.graph.rst
  4. 7
      docs/api/pygal.graph.solidgauge.rst
  5. 1
      docs/api/pygal.rst
  6. 1
      docs/api/pygal.test.rst
  7. 7
      docs/api/pygal.test.test_formatters.rst
  8. 1
      docs/documentation/types/index.rst
  9. 52
      docs/documentation/types/solidgauge.rst
  10. 10
      pygal/css/style.css
  11. 10
      pygal/graph/solidgauge.py
  12. 151
      pygal/svg.py
  13. 4
      pygal/table.py
  14. 12
      pygal/test/test_config.py
  15. 2
      pygal/test/test_graph.py

14
demo/moulinrouge/tests.py

@ -206,24 +206,24 @@ def get_test_routes(app):
def test_solidgauge():
gauge = SolidGauge(half_pie=True,
inner_radius=0.70,
print_values=True,
print_values=not True,
human_readable=True)
gauge.title = 'Hello World!'
percent_formatter = lambda x: '{:.10g}%'.format(x)
dollar_formatter = lambda x: '{:.10g}$'.format(x)
gauge.value_formatter = percent_formatter
gauge.add('Series 1', [{'value': 225000, 'maxvalue': 1275000}],
gauge.add('Series 1', [{'value': 225000, 'max_value': 1275000}],
formatter=dollar_formatter)
gauge.add('Series 2', [{'value': 110, 'maxvalue': 100}])
gauge.add('Series 2', [{'value': 110, 'max_value': 100}])
gauge.add('Series 3', [{'value': 3}])
gauge.add(
'Series 4', [
{'value': 51, 'maxvalue': 100},
{'value': 12, 'maxvalue': 100}])
gauge.add('Series 5', [{'value': 79, 'maxvalue': 100}])
{'value': 51, 'max_value': 100},
{'value': 12, 'max_value': 100}])
gauge.add('Series 5', [{'value': 79, 'max_value': 100}])
gauge.add('Series 6', 99)
gauge.add('Series 7', [{'value': 100, 'maxvalue': 100}])
gauge.add('Series 7', [{'value': 100, 'max_value': 100}])
return gauge.render_response()
@app.route('/test/gauge/log')

7
docs/api/pygal.formatters.rst

@ -0,0 +1,7 @@
pygal.formatters module
=======================
.. automodule:: pygal.formatters
:members:
:undoc-members:
:show-inheritance:

1
docs/api/pygal.graph.rst

@ -31,6 +31,7 @@ Submodules
pygal.graph.public
pygal.graph.pyramid
pygal.graph.radar
pygal.graph.solidgauge
pygal.graph.stackedbar
pygal.graph.stackedline
pygal.graph.time

7
docs/api/pygal.graph.solidgauge.rst

@ -0,0 +1,7 @@
pygal.graph.solidgauge module
=============================
.. automodule:: pygal.graph.solidgauge
:members:
:undoc-members:
:show-inheritance:

1
docs/api/pygal.rst

@ -24,6 +24,7 @@ Submodules
pygal.colors
pygal.config
pygal.etree
pygal.formatters
pygal.interpolate
pygal.serie
pygal.state

1
docs/api/pygal.test.rst

@ -17,6 +17,7 @@ Submodules
pygal.test.test_colors
pygal.test.test_config
pygal.test.test_date
pygal.test.test_formatters
pygal.test.test_graph
pygal.test.test_histogram
pygal.test.test_interpolate

7
docs/api/pygal.test.test_formatters.rst

@ -0,0 +1,7 @@
pygal.test.test_formatters module
=================================
.. automodule:: pygal.test.test_formatters
:members:
:undoc-members:
:show-inheritance:

1
docs/documentation/types/index.rst

@ -15,6 +15,7 @@ pygal provides various kinds of charts:
box
dot
funnel
solidgauge
gauge
pyramid
treemap

52
docs/documentation/types/solidgauge.rst

@ -0,0 +1,52 @@
SolidGauge
----------
SolidGauge charts
Normal
~~~~~~
.. pygal-code::
gauge = pygal.SolidGauge(inner_radius=0.70)
percent_formatter = lambda x: '{:.10g}%'.format(x)
dollar_formatter = lambda x: '{:.10g}$'.format(x)
gauge.value_formatter = percent_formatter
gauge.add('Series 1', [{'value': 225000, 'max_value': 1275000}],
formatter=dollar_formatter)
gauge.add('Series 2', [{'value': 110, 'max_value': 100}])
gauge.add('Series 3', [{'value': 3}])
gauge.add(
'Series 4', [
{'value': 51, 'max_value': 100},
{'value': 12, 'max_value': 100}])
gauge.add('Series 5', [{'value': 79, 'max_value': 100}])
gauge.add('Series 6', 99)
gauge.add('Series 7', [{'value': 100, 'max_value': 100}])
Half
~~~~
.. pygal-code::
gauge = pygal.SolidGauge(
half_pie=True, inner_radius=0.70,
style=pygal.style.styles['default'](value_font_size=10))
percent_formatter = lambda x: '{:.10g}%'.format(x)
dollar_formatter = lambda x: '{:.10g}$'.format(x)
gauge.value_formatter = percent_formatter
gauge.add('Series 1', [{'value': 225000, 'max_value': 1275000}],
formatter=dollar_formatter)
gauge.add('Series 2', [{'value': 110, 'max_value': 100}])
gauge.add('Series 3', [{'value': 3}])
gauge.add(
'Series 4', [
{'value': 51, 'max_value': 100},
{'value': 12, 'max_value': 100}])
gauge.add('Series 5', [{'value': 79, 'max_value': 100}])
gauge.add('Series 6', 99)
gauge.add('Series 7', [{'value': 100, 'max_value': 100}])

10
pygal/css/style.css

@ -90,6 +90,7 @@
fill: {{ style.foreground_strong }};
}
{{ id }}.reactive {
fill-opacity: {{ style.opacity }};
}
@ -147,6 +148,15 @@
font-size: 1.5em;
}
{{ id }}.bound {
font-size: .5em;
}
{{ id }}.max-value {
font-size: .75em;
fill: {{ style.foreground_subtle }};
}
{{ id }}.map-element {
fill: {{ style.plot_background }};
stroke: {{ style.foreground_subtle }} !important;

10
pygal/graph/solidgauge.py

@ -48,19 +48,19 @@ class SolidGauge(Graph):
(current_square[0]*sq_dimensions[1]) - (sq_dimensions[1] / 2.))
end_angle = 2 * pi
maxvalue = serie.metadata.get(0, {}).get('maxvalue', 100)
max_value = serie.metadata.get(0, {}).get('max_value', 100)
radius = min([sq_dimensions[0]/2, sq_dimensions[1]/2]) * .9
small_radius = radius * serie.inner_radius
self.svg.gauge_background(
serie_node, start_angle, center, radius, small_radius, end_angle,
self.half_pie)
self.half_pie, self._serie_format(serie, max_value))
sum_ = 0
for i, value in enumerate(serie.values):
if value is None:
continue
ratio = min(value, maxvalue) / maxvalue
ratio = min(value, max_value) / max_value
if self.half_pie:
angle = 2 * pi * ratio / 2
else:
@ -79,7 +79,7 @@ class SolidGauge(Graph):
serie_node, gauge_, radius, small_radius,
angle, start_angle, center, val, i, metadata,
self.half_pie, end_angle,
self._serie_format(serie, maxvalue)),
self._serie_format(serie, max_value)),
metadata)
start_angle += angle
sum_ += value
@ -87,7 +87,7 @@ class SolidGauge(Graph):
x, y = center
self.svg.node(
serie_node['text_overlay'], 'text',
class_='value solidgauge-sum',
class_='value gauge-sum',
x=x,
y=y + self.style.value_font_size / 3,
attrib={'text-anchor': 'middle'}

151
pygal/svg.py

@ -32,6 +32,8 @@ from pygal.util import (
coord_project, coord_diff, coord_format, coord_dual, coord_abs_project)
from pygal import __version__
nearly_2pi = 2 * pi - .00001
class Svg(object):
@ -258,17 +260,13 @@ class Svg(object):
angle, start_angle, center, val, i, metadata):
"""Draw a pie slice"""
if angle == 2 * pi:
rv = self.node(
node, 'circle',
cx=center[0],
cy=center[1],
r=radius,
class_='slice reactive tooltip-trigger')
elif angle > 0:
to = [coord_abs_project(center,radius, start_angle),
coord_abs_project(center,radius, start_angle + angle),
coord_abs_project(center,small_radius, start_angle + angle),
coord_abs_project(center,small_radius, start_angle)]
angle = nearly_2pi
if angle > 0:
to = [coord_abs_project(center, radius, start_angle),
coord_abs_project(center, radius, start_angle + angle),
coord_abs_project(center, small_radius, start_angle + angle),
coord_abs_project(center, small_radius, start_angle)]
rv = self.node(
node, 'path',
d='M%s A%s 0 %d 1 %s L%s A%s 0 %d 0 %s z' % (
@ -291,7 +289,11 @@ class Svg(object):
def gauge_background(
self, serie_node, start_angle, center, radius, small_radius,
end_angle, half_pie):
end_angle, half_pie, max_value):
if end_angle == 2 * pi:
end_angle = nearly_2pi
to_shade = [
coord_abs_project(center, radius, start_angle),
coord_abs_project(center, radius, end_angle),
@ -309,83 +311,68 @@ class Svg(object):
to_shade[3]),
class_='gauge-background reactive')
if half_pie:
begin_end = [
coord_diff(
center,
coord_project(
radius-(radius-small_radius)/2, start_angle)),
coord_diff(
center,
coord_project(
radius-(radius-small_radius)/2, end_angle))]
pos = 0
for i in begin_end:
self.node(
serie_node['plot'], 'text',
class_='y-{} bound reactive'.format(pos),
x=i[0],
y=i[1]+10,
attrib={'text-anchor': 'middle'}
).text = '{}'.format(0 if pos == 0 else max_value)
pos += 1
else:
middle_radius = .5 * (radius + small_radius)
# Correct text vertical alignment
middle_radius -= .1 * (radius - small_radius)
to_labels = [
coord_abs_project(
center, middle_radius, 0),
coord_abs_project(
center, middle_radius, nearly_2pi)
]
self.node(
self.defs, 'path', id='valuePath-%s%s' % center,
d='M%s A%s 0 1 1 %s' % (
to_labels[0],
coord_dual(middle_radius),
to_labels[1]
))
text_ = self.node(
serie_node['text_overlay'], 'text')
self.node(
text_, 'textPath', class_='max-value reactive',
attrib={
'href': '#valuePath-%s%s' % center,
'startOffset': '99%',
'text-anchor': 'end'
}
).text = max_value
def solid_gauge(
self, serie_node, node, radius, small_radius,
angle, start_angle, center, val, i, metadata, half_pie, end_angle,
maxvalue):
max_value):
"""Draw a solid gauge slice and background slice"""
if angle == 2 * pi:
to = [coord_abs_project(center, radius, start_angle),
coord_abs_project(
center, radius, start_angle + angle - 0.0001),
coord_abs_project(
center, small_radius, start_angle + angle - 0.0001),
coord_abs_project(center, small_radius, start_angle)]
self.node(
node, 'path',
d='M%s A%s 0 %d 1 %s L%s A%s 0 %d 0 %s z' % (
to[0],
coord_dual(radius),
int(angle > pi),
to[1],
to[2],
coord_dual(small_radius),
int(angle > pi),
to[3]),
class_='slice reactive tooltip-trigger')
elif angle > 0:
angle = nearly_2pi
if angle > 0:
to = [coord_abs_project(center, radius, start_angle),
coord_abs_project(center, radius, start_angle + angle),
coord_abs_project(center, small_radius, start_angle + angle),
coord_abs_project(center, small_radius, start_angle)]
if half_pie:
begin_end = [
coord_diff(
center,
coord_project(
radius-(radius-small_radius)/2, start_angle)),
coord_diff(
center,
coord_project(
radius-(radius-small_radius)/2, end_angle))]
pos = 0
for i in begin_end:
self.node(
node, 'text',
class_='y-{} reactive'.format(pos),
x=i[0],
y=i[1]+10,
attrib={'text-anchor': 'middle',
'font-size': 10}
).text = '{}'.format(0 if pos == 0 else maxvalue)
pos += 1
else:
to_labels = [
coord_abs_project(
center, radius-(radius-small_radius)/2, 0),
coord_abs_project(
center, radius-(radius-small_radius)/2, 2*359.5/360*pi)
]
self.node(
self.defs, 'path', id='valuePath-%s%s' % center,
d='M%s A%s 0 1 1 %s' % (
to_labels[0],
coord_dual(radius-(radius-small_radius)/2),
to_labels[1]
), stroke='#000000', width='3px')
text_ = self.node(node, 'text', x=10, y=100, stroke='black')
self.node(
text_, 'textPath', class_='maxvalue reactive',
attrib={
'href': '#valuePath-%s%s' % center,
'startOffset': '%s' % (
97-1.2*len(str(maxvalue))) + '%',
'text-anchor': 'start',
'font-size': (radius-small_radius)/2,
'fill': '#999999'}
).text = maxvalue
self.node(
node, 'path',
d='M%s A%s 0 %d 1 %s L%s A%s 0 %d 0 %s z' % (
@ -410,9 +397,9 @@ class Svg(object):
def confidence_interval(self, node, x, low, high, width=7):
if self.graph.horizontal:
coord_format = lambda xy: '%f %f' % (xy[1], xy[0])
fmt = lambda xy: '%f %f' % (xy[1], xy[0])
else:
coord_format = lambda xy: '%f %f' % xy
fmt = coord_format
shr = lambda xy: (xy[0] + width, xy[1])
shl = lambda xy: (xy[0] - width, xy[1])
@ -424,7 +411,7 @@ class Svg(object):
self.node(
ci, 'path', d="M%s L%s M%s L%s M%s L%s L%s M%s L%s" % tuple(
map(coord_format, (
map(fmt, (
top, shr(top), top, shl(top), top,
bottom, shr(bottom), bottom, shl(bottom)
))

4
pygal/table.py

@ -94,7 +94,7 @@ class Table(object):
row.append(self.chart._format(serie, j))
if total:
acc[-1] += sum_
row.append(self.chart._value_format(serie, sum_))
row.append(self.chart._serie_format(serie, sum_))
table.append(row)
width = ln + 1
@ -102,7 +102,7 @@ class Table(object):
width += 1
table.append(['Total'])
for val in acc:
table[-1].append(self.chart._value_format(serie, val))
table[-1].append(self.chart._serie_format(serie, val))
# Align values
len_ = max([len(r) for r in table] or [0])

12
pygal/test/test_config.py

@ -24,7 +24,9 @@ from pygal import (
Histogram, Gauge, Box, XY,
Pyramid, HorizontalBar, HorizontalStackedBar,
HorizontalStackedLine, HorizontalLine,
DateTimeLine, TimeLine, DateLine, TimeDeltaLine)
DateTimeLine, TimeLine, DateLine, TimeDeltaLine,
SolidGauge
)
from pygal.graph.map import BaseMap
from pygal.graph.horizontal import HorizontalGraph
from pygal.graph.dual import Dual
@ -299,7 +301,7 @@ def test_include_x_axis(Chart):
"""Test x axis inclusion option"""
chart = Chart()
if Chart in (
Pie, Treemap, Radar, Funnel, Dot, Gauge, Histogram, Box
Pie, Treemap, Radar, Funnel, Dot, Gauge, Histogram, Box, SolidGauge
) or issubclass(Chart, BaseMap):
return
if not chart._dual:
@ -391,7 +393,7 @@ def test_x_y_title(Chart):
def test_x_label_major(Chart):
"""Test x label major option"""
if Chart in (
Pie, Treemap, Funnel, Dot, Gauge, Histogram, Box,
Pie, Treemap, Funnel, Dot, Gauge, Histogram, Box, SolidGauge,
Pyramid, DateTimeLine, TimeLine, DateLine,
TimeDeltaLine
) or issubclass(Chart, (BaseMap, Dual, HorizontalGraph)):
@ -436,7 +438,7 @@ def test_x_label_major(Chart):
def test_y_label_major(Chart):
"""Test y label major option"""
if Chart in (
Pie, Treemap, Funnel, Dot, Gauge, Histogram, Box,
Pie, Treemap, Funnel, Dot, Gauge, Histogram, Box, SolidGauge,
HorizontalBar, HorizontalStackedBar,
HorizontalStackedLine, HorizontalLine,
Pyramid, DateTimeLine, TimeLine, DateLine,
@ -522,4 +524,4 @@ def test_formatters(Chart):
q = chart.render_pyquery()
assert set([v.text for v in q(".value")]) == set((
u('4€'), u('5€'), u('6€'), '1_a$', '2_a$', u('')) + (
('6_a$', u('15€')) if Chart == Pie else ()))
('6_a$', u('15€')) if Chart in (Pie, SolidGauge) else ()))

2
pygal/test/test_graph.py

@ -107,7 +107,7 @@ def test_metadata(Chart):
for md in ('http://7.example.com/', 'http://4.example.com/'):
assert md in [e.attrib.get('xlink:href') for e in q('a')]
if Chart in (pygal.Pie, pygal.Treemap):
if Chart in (pygal.Pie, pygal.Treemap, pygal.SolidGauge):
# Slices with value 0 are not rendered
assert len(v) - 1 == len(q('.tooltip-trigger').siblings('.value'))
elif not issubclass(Chart, BaseMap):

Loading…
Cancel
Save