Python to generate nice looking SVG graph http://pygal.org/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

1155 lines
40 KiB

# -*- coding: utf-8 -*-
# This file is part of pygal
from pygal import (
Bar, Gauge, Pyramid, Funnel, Dot, StackedBar, StackedLine, XY,
CHARTS_BY_NAME, Config, Line, Histogram, Box,
Pie, Treemap, TimeLine, DateLine, Radar, HorizontalBar,
DateTimeLine, SolidGauge)
try:
from pygal.maps import world
except ImportError:
world = None
try:
from pygal.maps import fr
except ImportError:
fr = None
try:
from pygal.maps import ch
except ImportError:
ch = None
from flask import abort
from pygal.style import styles, Style, RotateStyle
from pygal.colors import rotate
from pygal import stats, formatters
from pygal.graph.horizontal import HorizontalGraph
from random import randint, choice
from datetime import datetime, date
def get_test_routes(app):
lnk = lambda v, l=None: {
'value': v,
'xlink': 'javascript:alert("Test %s")' % v,
'label': l}
@app.route('/test/unsorted')
def test_unsorted():
bar = Bar(style=styles['neon'], value_formatter=formatters.human_readable)
bar.add('A', {'red': 10, 'green': 12, 'blue': 14})
bar.add('B', {'green': 11, 'blue': 7})
bar.add('C', {'blue': 7})
bar.add('D', {})
bar.add('E', {'blue': 2, 'red': 13})
bar.x_labels = ('red', 'green', 'blue')
return bar.render_response()
@app.route('/test/bar_links')
def test_bar_links():
bar = StackedLine(style=styles['default'](
font_family='googlefont:Raleway'))
bar.js = ('http://l:2343/2.0.x/pygal-tooltips.js',)
bar.title = 'Wow ! Such Chart !'
bar.x_title = 'Many x labels'
bar.y_title = 'Much y labels'
bar.dynamic_print_values = True
bar.add('Red serie', [
{'value': 10,
'label': 'Ten',
'xlink': 'http://google.com?q=10'},
{'value': 20,
'label': 'Twenty is a good number yada yda yda yada '
'yadaaaaaaaaaaaaaaaaaaaaaa',
'xlink': 'http://google.com?q=20'},
30,
{'value': 40,
'label': 'Forty',
'xlink': 'http://google.com?q=40'}
])
bar.add('Blue serie', [40, {
'value': 30,
'label': 'Thirty',
'xlink': 'http://google.com?q=30'
}, 20, 10])
bar.x_labels = ['Yesterday', 'Today or any other day',
'Tomorrow', 'Someday']
bar.logarithmic = True
# bar.zero = 1
return bar.render_response()
@app.route('/test/xy_links')
def test_xy_links():
xy = XY(style=styles['neon'], interpolate='cubic')
xy.add('1234', [
{'value': (10, 5),
'label': 'Ten',
'xlink': 'http://google.com?q=10'},
{'value': (20, 20),
'tooltip': 'Twenty',
'xlink': 'http://google.com?q=20'},
(30, 15),
{'value': (40, -5),
'label': 'Forty',
'xlink': 'http://google.com?q=40'}
])
xy.add('4321', [(40, 10), {
'value': (30, 3),
'label': 'Thirty',
'xlink': 'http://google.com?q=30'
}, (20, 10), (10, 21)])
xy.x_labels = list(range(1, 50))
xy.y_labels = list(range(1, 50))
return xy.render_response()
@app.route('/test/long_title')
def test_long_title():
bar = Bar()
bar.add('Looooooooooooooooooooooooooooooooooong', [2, None, 12])
bar.title = (
'1 12 123 1234 12345 123456 1234567 12345678 123456789 1234567890 '
'12345678901 123456789012 1234567890123 12345678901234 '
'123456789012345 1234567890123456 12345678901234567 '
'123456789012345678 1234567890123456789 12345678901234567890 '
'123456789012345 1234567890123456 12345678901234567 '
'12345678901 123456789012 1234567890123 12345678901234 '
'1 12 123 1234 12345 123456 1234567 12345678 123456789 1234567890')
return bar.render_response()
@app.route('/test/multiline_title')
def test_multiline_title():
bar = Bar()
bar.add('Looooooooooooooooooooooooooooooooooong', [2, None, 12])
bar.title = (
'First line \n Second line \n Third line'
)
return bar.render_response()
@app.route('/test/long_labels')
def test_long_labels():
bar = Bar()
bar.add('Long', [2, None, 12])
bar.title = (
'1 12 123 1234 12345 123456 1234567 12345678 123456789 1234567890')
bar.x_labels = 'a' * 100, 'b ' * 50, 'cc ! ' * 20
bar.x_label_rotation = 45
return bar.render_response()
@app.route('/test/none')
def test_bar_none():
bar = Bar()
bar.add('Lol', [2, None, 12])
bar.x_labels = range(1, 4)
return bar.render_response()
@app.route('/test/print_values/<chart>')
def test_print_values_for(chart):
graph = CHARTS_BY_NAME[chart](
print_values=True, print_labels=True, print_zeroes=True,
style=styles['default'](
value_font_family='googlefont:Raleway',
value_colors=(None, None, 'blue', 'red', 'green')
))
graph.js = ('http://l:2343/2.0.x/pygal-tooltips.js',)
for i in range(12):
graph.add('', [{
'value': i + j,
'label': 'abcdefghijklmnopqrstuvwxyz'[i + j]
} for j in range(5)])
return graph.render_response()
@app.route('/test/treemap')
def test_treemap():
treemap = Treemap(style=RotateStyle('#ff5995', opacity=.6,
value_font_size=32,
value_colors=['#ffffff']))
treemap.title = 'Binary TreeMap'
treemap.print_values = True
treemap.print_labels = True
for i in range(1, 5):
treemap.add('', [{'label': 'Area %d' % i, 'value': i}])
treemap.add('', [2])
# treemap.add('A', [2, 1, 12, 4, 2, 1, 1, 3, 12, 3, 4, None, 9])
# treemap.add('B', [4, 2, 5, 10, 3, 4, 2, 7, 4, -10, None, 8, 3, 1])
# treemap.add('C', [3, 8, 3, 3, 5, 3, 3, 5, 4, 12])
# treemap.add('D', [23, 18])
# treemap.add('E', [1, 2, 1, 2, 3, 3, 1, 2, 3,
# 4, 3, 1, 2, 1, 1, 1, 1, 1])
# treemap.add('F', [31])
# treemap.add('G', [5, 9.3, 8.1, 12, 4, 3, 2])
# treemap.add('H', [12, 3, 3])
return treemap.render_response()
@app.route('/test/gauge')
def test_gauge():
gauge = Gauge()
gauge.range = [-10, 10]
gauge.add('Need l', [2.3, 5.12])
gauge.add('Need m', [-4])
gauge.add('Need z', [-10, 10.5])
gauge.add('No', [99, -99])
gauge.y_labels = [
{'label': 'X',
'value': 6},
{'label': '><',
'value': -6}
]
return gauge.render_response()
@app.route('/test/solidgauge/')
def test_solidgauge():
gauge = SolidGauge(half_pie=True,
inner_radius=0.70,
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, '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}])
return gauge.render_response()
@app.route('/test/gauge/log')
def test_gauge_log():
gauge = Gauge(logarithmic=True)
gauge.add('Need l', [200.3, 500.12])
gauge.add('Need z', [10, 1000.5])
return gauge.render_response()
@app.route('/test/pyramid')
def test_pyramid():
pyramid = Pyramid()
pyramid.x_labels = ['0-25', '25-45', '45-65', '65+']
pyramid.add('Man single', [2, 4, 2, 1])
pyramid.add('Woman single', [10, 6, 1, 1])
pyramid.add('Man maried', [10, 3, 4, 2])
pyramid.add('Woman maried', [3, 3, 5, 3])
return pyramid.render_response()
@app.route('/test/funnel')
def test_funnel():
funnel = Funnel()
funnel.add('1', [1, 2, 3])
funnel.add('3', [3, 4, 5])
funnel.add('6', [6, 5, 4])
funnel.add('12', [12, 2, 9])
return funnel.render_response()
@app.route('/test/dot')
def test_dot():
dot = Dot(logarithmic=True)
dot.x_labels = map(str, range(4))
dot.add('a', [1, lnk(3, 'Foo'), 5, 3])
dot.add('b', [2, -2, 0, 2, .1])
dot.add('c', [5, 1, 50, lnk(3, 'Bar')])
dot.add('d', [-5, 5, lnk(0, 'Babar'), 3])
return dot.render_response()
@app.route('/test/<chart>')
def test_for(chart):
graph = CHARTS_BY_NAME[chart]()
graph.add('1', [1, 3, 12, 3, 4, None, 9])
graph.add('2', [7, -4, 10, None, 8, 3, 1])
graph.add('3', [7, -14, -10, None, 8, 3, 1])
graph.add('4', [7, 4, -10, None, 8, 3, 1])
graph.x_labels = ('a', 'b', 'c', 'd')
graph.x_label_rotation = 90
return graph.render_response()
@app.route('/test/<chart>')
def test_call_api_for(chart):
graph = CHARTS_BY_NAME[chart]()
graph(1, 3, 12, 3, 4, None, 9, title='1')
graph(7, -4, 10, None, 8, 3, 1, title='2')
graph(7, -14, -10, None, 8, 3, 1, title='3')
graph(7, 4, -10, None, 8, 3, 1, title='4')
graph.x_labels = ('a', 'b', 'c', 'd')
graph.x_label_rotation = 90
return graph.render_response()
@app.route('/test/one/<chart>')
def test_one_for(chart):
graph = CHARTS_BY_NAME[chart]()
graph.add('1', [10])
graph.x_labels = 'a',
return graph.render_response()
@app.route('/test/xytitles/<chart>')
def test_xy_titles_for(chart):
graph = CHARTS_BY_NAME[chart]()
graph.title = 'My global title'
graph.x_title = 'My X title'
graph.y_title = 'My Y title'
graph.add('My number 1 serie', [1, 3, 12])
graph.add('My number 2 serie', [7, -4, 10])
graph.add('A', [17, -14, 11], secondary=True)
graph.x_label_rotation = 25
graph.legend_at_bottom = not True
graph.x_labels = (
'First point', 'Second point', 'Third point')
return graph.render_response()
@app.route('/test/no_data/<chart>')
def test_no_data_for(chart):
graph = CHARTS_BY_NAME[chart]()
graph.add('Empty 1', [])
graph.add('Empty 2', [])
graph.x_labels = 'empty'
graph.title = '123456789 ' * 30
return graph.render_response()
@app.route('/test/xy_single')
def test_xy_single():
graph = XY(interpolate='cubic')
graph.add('Single', [(1, 1)])
return graph.render_response()
@app.route('/test/no_data/at_all/<chart>')
def test_no_data_at_all_for(chart):
graph = CHARTS_BY_NAME[chart]()
return graph.render_response()
@app.route('/test/interpolate/<chart>')
def test_interpolate_for(chart):
graph = CHARTS_BY_NAME[chart](interpolate='lagrange',
interpolation_parameters={
'type': 'kochanek_bartels',
'c': 1,
'b': -1,
't': -1})
graph.add('1', [1, 3, 12, 3, 4])
graph.add('2', [7, -4, 10, None, 8, 3, 1])
return graph.render_response()
@app.route('/test/logarithmic/<chart>')
def test_logarithmic_for(chart):
graph = CHARTS_BY_NAME[chart](logarithmic=True)
if isinstance(graph, CHARTS_BY_NAME['XY']):
graph.add('xy', [
(.1, .234), (10, 243), (.001, 2), (1000000, 1231)])
else:
graph.add('1', [.1, 10, .01, 10000])
graph.add('2', [.234, 243, 2, 2379, 1231])
graph.x_labels = ('a', 'b', 'c', 'd', 'e')
graph.x_label_rotation = 90
return graph.render_response()
@app.route('/test/zero_at_34/<chart>')
@app.route('/test/zero_at_<int:zero>/<chart>')
def test_zero_at_34_for(chart, zero=34):
graph = CHARTS_BY_NAME[chart](fill=True, zero=zero)
graph.add('1', [100, 34, 12, 43, -48])
graph.add('2', [73, -14, 10, None, -58, 32, 91])
return graph.render_response()
@app.route('/test/range/<chart>')
def test_range_for(chart):
graph = CHARTS_BY_NAME[chart]()
graph.range = [0, 100]
graph.add('1', [1, 2, 10])
return graph.render_response()
@app.route('/test/fill_with_none/')
def test_fill_with_none():
graph = XY(fill=True)
graph.add('1', [(1, 2), (3, 3), (3.5, 5), (5, 1)])
graph.add('2', [(1, 9), (None, 5), (5, 23)])
return graph.render_response()
@app.route('/test/negative/<chart>')
def test_negative_for(chart):
graph = CHARTS_BY_NAME[chart]()
graph.add('1', [10, 0, -10])
return graph.render_response()
@app.route('/test/bar')
def test_bar():
bar = Bar(dynamic_print_values=True, show_minor_x_labels=False)
bar.add('1', [1, 2, 3])
bar.add('2', [4, 5, 6])
bar.x_labels = [2, 4, 6]
bar.x_labels_major = [4]
return bar.render_response()
@app.route('/test/formatters/<chart>')
def test_formatters_for(chart):
chart = CHARTS_BY_NAME[chart](
print_values=True, formatter=lambda x, chart, serie: '%s%s$' % (
x, serie.title))
chart.add('_a', [1, 2, {'value': 3, 'formatter': lambda x: '%s¥' % x}])
chart.add('_b', [4, 5, 6], formatter=lambda x: '%s€' % x)
chart.x_labels = [2, 4, 6]
chart.x_labels_major = [4]
return chart.render_response()
@app.route('/test/bar/position')
def test_bar_print_values_position():
bar = StackedBar(
print_values=True, print_values_position='top', zero=2,
style=styles['default'](
value_font_family='googlefont:Raleway',
value_font_size=46))
bar.add('1', [1, -2, 3])
bar.add('2', [4, -5, 6])
bar.x_labels = [2, 4, 6]
bar.x_labels_major = [4]
return bar.render_response()
@app.route('/test/histogram')
def test_histogram():
hist = Histogram(
print_values=True,
print_values_position='top',
style=styles['neon'])
hist.add('1', [
(2, 0, 1),
(4, 1, 3),
(3, 3.5, 5),
(1.5, 5, 10)
])
hist.add('2', [(2, 2, 8)])
hist.x_labels = [0, 3, 6, 9, 12]
return hist.render_response()
@app.route('/test/ylabels')
def test_ylabels():
chart = Bar()
chart.x_labels = 'Red', 'Blue', 'Green'
chart.y_labels = [
{'value': .0001,
'label': 'LOL'},
{'value': .0003,
'label': 'ROFL'},
{'value': .0004,
'label': 'MAO'},
{'value': .00045,
'label': 'LMFAO'},
{'value': .0005,
'label': 'GMCB'}]
chart.add('line', [.0002, .0005, .00035])
return chart.render_response()
@app.route('/test/secondary/<chart>')
def test_secondary_for(chart):
chart = CHARTS_BY_NAME[chart](fill=True)
chart.title = 'LOL ' * 23
chart.x_labels = 'abc'
chart.x_label_rotation = 25
chart.y_label_rotation = 50
chart.add('1', [30, 20, -2])
chart.add('1b', [-4, 50, 6], secondary=True)
chart.add('2b', [None, 10, 20], secondary=True)
chart.add('2', [8, 21, -0])
chart.add('3', [None, 20, 10])
chart.add('3b', [-1, 2, -3], secondary=True)
return chart.render_response()
@app.route('/test/secondary_xy')
def test_secondary_xy():
chart = XY()
chart.add(10 * '1', [(30, 5), (20, 12), (25, 4)])
chart.add(10 * '1b', [(4, 12), (5, 8), (6, 4)], secondary=True)
chart.add(10 * '2b', [(3, 24), (0, 17), (12, 9)], secondary=True)
chart.add(10 * '2', [(8, 23), (21, 1), (5, 0)])
chart.value_formatter = lambda x: str(int(x)) + '+'
return chart.render_response()
@app.route('/test/box')
def test_box():
chart = Box()
# chart.js = ('http://l:2343/2.0.x/pygal-tooltips.js',)
chart.box_mode = '1.5IQR'
chart.add('One', [15, 8, 2, -12, 9, 23])
chart.add('Two', [5, 8, 2, -9, 23, 12])
chart.add('Three', [8, -2, 12, -5, 9, 3])
chart.add('Four', [5, 8, 2, -9, -3, 12])
chart.add('Five', [8, 12, 12, -9, 5, 13])
chart.x_labels = map(str, range(5))
return chart.render_response()
@app.route('/test/stacked')
def test_stacked():
stacked = StackedLine(stack_from_top=True, logarithmic=True)
stacked.add('1', [1, 2])
stacked.add('2', [10, 12])
stacked.x_labels = ['a', 'b', 'c', 'd']
return stacked.render_response()
@app.route('/test/stacked/reverse')
def test_stacked_reverse():
stacked = StackedBar(stack_from_top=True)
stacked.add('1', [1, 2, 3])
stacked.add('2', [4, 5, 6])
return stacked.render_response()
@app.route('/test/show_dots')
def test_show_dots():
line = Line(show_dots=False)
line.add('1', [1, 2, 3])
line.add('2', [4, 5, 6])
return line.render_response()
@app.route('/test/config')
def test_config():
class LolConfig(Config):
js = ['http://l:2343/2.0.x/pygal-tooltips.js']
stacked = StackedBar(LolConfig())
stacked.add('', [1, 2, 3])
stacked.add('My beautiful serie of 2019', [4, 5, 6])
return stacked.render_response()
@app.route('/test/dateline')
def test_dateline():
dateline = DateLine(y_label_rotation=112)
dateline.x_labels = [
date(2013, 1, 1),
date(2013, 7, 1),
date(2014, 1, 1),
date(2014, 7, 1),
date(2015, 1, 1),
date(2015, 7, 1)
]
dateline.x_labels_major = [
date(2013, 1, 1),
date(2015, 7, 1)
]
dateline.add("Serie", [
(date(2013, 1, 2), 213),
(date(2013, 8, 2), 281),
(date(2013, 5, 31), 281),
(date(2014, 12, 7), 198),
(date(2014, 9, 6), 198),
(date(2015, 3, 21), 120)
])
return dateline.render_response()
@app.route('/test/timeline')
def test_timexy():
from datetime import time
timeline = TimeLine()
timeline.add('1', [
(time(1, 12, 29), 2),
(time(21, 2, 29), 10),
(time(12, 30, 59), 7)
])
timeline.add(
'2', [(time(12, 12, 12), 4), (time(), 8), (time(23, 59, 59), 6)])
timeline.x_label_rotation = 25
return timeline.render_response()
@app.route('/test/worldmap')
def test_worldmap():
wmap = world.World(print_values=True, style=choice(list(styles.values())))
# wmap.js = ('http://l:2343/2.0.x/pygal-tooltips.js',)
# wmap.add('1st', [('fr', 100), {
# 'value': ('us', 10),
# 'node': {'style': 'fill: red'}
# }
# ])
# wmap.add('2nd', [('jp', 1), ('ru', 7), ('uk', 0)])
# wmap.add('3rd', ['ch', 'cz', 'ca', 'cn'])
# wmap.add('4th', {'jp': 12, 'bo': 1, 'bu': 23, 'fr': 34})
# wmap.add('5th', [{
# 'value': ('tw', 10),
# 'label': 'First label',
# 'xlink': 'http://google.com?q=tw',
# }, {
# 'value': ('bw', 20),
# 'label': 'Second one',
# 'xlink': 'http://google.com?q=bw',
# 'node': {'style': 'fill: blue'}
# }, {
# 'value': ('mw', 40),
# 'label': 'Last'
# }])
wmap.add('_', {'us': 1})
wmap.add('-', {'us': 2})
wmap.add('.', {'us': 3})
wmap.title = 'World Map !!'
wmap.value_formatter = lambda x: '%d%%' % x
return wmap.render_response()
@app.route('/test/supranational')
def test_supranational():
wmap = world.SupranationalWorld(style=choice(list(styles.values())))
v = [
('europe', 0),
('oceania', 2),
('antartica', 4),
('south_america', 5),
('africa', 6),
('north_america', 7),
('asia', 8)
]
wmap.add('Serie with metadata', [
v[0],
{'value': v[1]},
{'value': v[2], 'label': 'Three'},
{'value': v[3], 'xlink': 'http://4.example.com/'},
{'value': v[4], 'xlink': 'http://5.example.com/', 'label': 'Five'},
{'value': v[5], 'xlink': {
'href': 'http://6.example.com/'}, 'label': 'Six'},
{'value': v[6], 'xlink': {
'href': 'http://7.example.com/',
'target': '_blank'}, 'label': 'Seven'}
])
# wmap.add('Asia', [('asia', 1)])
# wmap.add('Europe', [('europe', 1)])
# wmap.add('Africa', [('africa', 1)])
# wmap.add('North america', [('north_america', 1)])
# wmap.add('South america', [('south_america', 1)])
# wmap.add('Oceania', [('oceania', 1)])
# wmap.add('Antartica', [('antartica', 1)])
wmap.title = 'Supra World Map !!'
return wmap.render_response()
@app.route('/test/frenchmapdepartments')
def test_frenchmapdepartments():
if fr is None:
abort(404)
fmap = fr.Departments(style=choice(list(styles.values())))
fmap.add('', [(i, i) for i in range(1, 100)])
fmap.add('', [(970 + i, i) for i in range(1, 7)])
fmap.add('', [('2A', 1), ('2B', 2)])
fmap.title = 'French map'
return fmap.render_response()
@app.route('/test/swissmap')
def test_swissmap():
smap = ch.Cantons(style=choice(list(styles.values())))
for i in range(10):
smap.add('s%d' % i, [
(choice(list(ch.CANTONS.keys())), randint(0, 100))
for _ in range(randint(1, 5))])
smap.add('links', [{
'value': ('kt-vs', 10),
'label': '\o/',
'xlink': 'http://google.com?q=69'
}, {
'value': ('bt', 20),
'label': 'Y',
}])
smap.add('6th', [3, 5, 34, 12])
smap.title = 'Swiss map'
return smap.render_response()
@app.route('/test/frenchmapregions')
def test_frenchmapregions():
if fr is None:
abort(404)
fmap = fr.Regions(style=choice(list(styles.values())))
for i in range(10):
fmap.add('s%d' % i, [
(choice(list(fr.REGIONS.keys())), randint(0, 100))
for _ in range(randint(1, 5))])
fmap.add('links', [{
'value': ('02', 10),
'label': '\o/',
'xlink': 'http://google.com?q=69'
}, {
'value': ('72', 20),
'label': 'Y',
}])
fmap.add('6th', [91, 2, 41])
fmap.title = 'French map'
return fmap.render_response()
@app.route('/test/labels')
def test_labels():
line = Line()
line.add('test1', range(100))
line.x_labels = map(str, range(11))
return line.render_response()
@app.route('/test/64colors')
def test_64_colors():
n = 64
colors = [rotate('#ff0000', i * 360 / n) for i in range(n)]
pie = Pie(style=Style(colors=colors))
for i in range(n):
pie(1, title=str(i) if i % 5 == 1 else None)
return pie.render_response()
@app.route('/test/major_dots')
def test_major_dots():
line = Line(x_labels_major_count=2, show_only_major_dots=True)
line.add('test', range(12))
line.x_labels = [
'lol', 'lol1', 'lol2', 'lol3', 'lol4', 'lol5',
'lol6', 'lol7', 'lol8', 'lol9', 'lol10', 'lol11']
# line.x_labels_major = ['lol3']
return line.render_response()
@app.route('/test/x_major_labels/<chart>')
def test_x_major_labels_for(chart):
chart = CHARTS_BY_NAME[chart](show_minor_y_labels=False)
for i in range(12):
chart.add('test', range(12))
chart.x_labels = map(str, range(12))
# chart.x_labels_major_count = 4
# chart.x_labels_major = ['1', '5', '11', 6]
# chart.y_labels_major = [60, 120]
return chart.render_response()
@app.route('/test/y_major_labels/<chart>')
def test_y_major_labels_for(chart):
chart = CHARTS_BY_NAME[chart]()
chart.add('test', range(12))
# chart.add('test', zip(*[range(12), range(12)]))
chart.y_labels = range(12)
# chart.y_labels_major_count = 4
chart.y_labels_major = [1.0, 5.0, 11.0]
return chart.render_response()
@app.route('/test/stroke_config')
def test_stroke_config():
line = Line(stroke_style={'width': .5})
line.add('test_no_line', range(12), stroke=False)
line.add('test', reversed(range(12)), stroke_style={'width': 3})
line.add('test_no_dots', [5] * 12, show_dots=False,
stroke_style={'width': 2, 'dasharray': '12, 31'})
line.add('test_big_dots', [
randint(1, 12) for _ in range(12)], dots_size=5)
line.add('test_fill', [
randint(1, 3) for _ in range(12)], fill=True,
stroke_style={'width': 5, 'dasharray': '4, 12, 7, 20'})
line.x_labels = [
'lol', 'lol1', 'lol2', 'lol3', 'lol4', 'lol5',
'lol6', 'lol7', 'lol8', 'lol9', 'lol10', 'lol11']
return line.render_response()
@app.route('/test/radar')
def test_radar():
radar = Radar()
for i in range(10):
radar.add(str(i), [i * j for j in range(8)])
radar.x_labels = [
'lol',
'rofl',
'mao',
'lolroflmao',
'12345678901234567890'
]
radar.x_label_rotation = 35
radar.y_label_rotation = 35
radar.y_labels = [{
'label': '500',
'value': 10
}, {
'label': '1000',
'value': 20
}, {
'label': '5000',
'value': 30
}, {
'label': '10000',
'value': 40
}]
return radar.render_response()
@app.route('/test/pie_serie_radius')
def test_pie_serie_radius():
pie = Pie()
pie.js = ('http://a.zi:2343/2.0.x/pygal-tooltips.js',)
for i in range(10):
pie.add(str(i), i, inner_radius=(10 - i) / 10)
return pie.render_response()
@app.route('/test/half_pie')
def test_half_pie():
pie = Pie(half_pie=True)
for i in range(20):
pie.add(str(i), i, inner_radius=.1)
pie.legend_at_bottom = True
pie.legend_at_bottom_columns = 4
return pie.render_response()
@app.route('/test/interpolate/secondary')
def test_interpolate_secondary():
chart = Line(title=u'Some different points', interpolate='cubic')
chart.add('line', [1000, 2000, 7000])
chart.add('other line', [100, 500, 500], secondary=True)
chart.range = 0, 10000
chart.secondary_range = 0, 1000
return chart.render_response()
@app.route('/test/legend_at_bottom/<chart>')
def test_legend_at_bottom_for(chart):
graph = CHARTS_BY_NAME[chart]()
graph.add('1', [1, 3, 12, 3, 4, None, 9])
graph.add('2', [7, -4, 10, None, 8, 3, 1])
graph.add('3', [7, -14, -10, None, 8, 3, 1])
graph.add('4', [7, 4, -10, None, 8, 3, 1])
graph.x_labels = ('a', 'b', 'c', 'd', 'e', 'f', 'g')
graph.legend_at_bottom = True
return graph.render_response()
@app.route('/test/custom_metadata/<chart>')
def test_custom_metadata_for(chart):
c = CHARTS_BY_NAME[chart]()
c.add('1', [
{'style': 'fill: red', 'value': 1, 'node': {'r': 12}},
{'color': 'blue', 'value': 2, 'node': {'width': 12}},
{'style': 'fill: red; stroke: yellow', 'value': 3}])
c.add('2', [
{'value': 4, 'xlink': {
'href': 'javascript:alert("-")', 'target': 'top',
'class': 'lol'
}
},
{'color': 'green', 'value': 5},
6])
return c.render_response()
@app.route('/test/sparkline/<chart>')
def test_sparkline_for(chart):
graph = CHARTS_BY_NAME[chart](**dict(
width=200,
height=50,
show_dots=False,
show_legend=False,
show_y_labels=False,
show_x_labels=False,
spacing=0,
margin=5,
explicit_size=True
))
graph.add('1', [1, 3, 12, 3, 4, None, 9])
graph.add('2', [7, -4, 10, None, 8, 3, 1])
graph.add('3', [7, -14, -10, None, 8, 3, 1])
graph.add('4', [7, 4, -10, None, 8, 3, 1])
graph.x_labels = ('a', 'b', 'c', 'd', 'e', 'f', 'g')
graph.legend_at_bottom = True
return graph.render_response()
@app.route('/test/sparkline/label/<chart>')
def test_sparkline_label_for(chart):
graph = CHARTS_BY_NAME[chart](**dict(
width=200,
height=50,
show_dots=False,
show_legend=False,
# show_y_labels=False,
# show_x_labels=False,
spacing=0,
margin=5,
min_scale=2,
max_scale=2,
explicit_size=True
))
graph.add('1', [1, 3, 12, 3, 4, None, 9])
graph.add('2', [7, -4, 10, None, 8, 3, 1])
graph.add('3', [7, -14, -10, None, 8, 3, 1])
graph.add('4', [7, 4, -10, None, 8, 3, 1])
graph.x_labels = ('a', 'b', 'c', 'd', 'e', 'f', 'g')
graph.legend_at_bottom = True
return graph.render_response()
@app.route('/test/normal/<chart>')
def test_normal_for(chart):
graph = CHARTS_BY_NAME[chart]()
graph.add('1', [1, 3, 12, 3, 4, None, 9])
graph.add('2', [7, -4, 10, None, 8, 3, 1])
graph.add('3', [7, -14, -10, None, 8, 3, 1])
graph.add('4', [7, 4, -10, None, 8, 3, 1])
graph.x_labels = ('a', 'b', 'c', 'd', 'e', 'f', 'g')
graph.legend_at_bottom = True
return graph.render_response()
@app.route('/test/horizontal_force/<chart>')
def test_horizontal_force_for(chart):
class H(CHARTS_BY_NAME[chart], HorizontalGraph):
pass
graph = H()
graph.add('1', [1, 3, 12, 3, 4, None, 9])
graph.add('2', [7, -4, 10, None, 8, 3, 1])
graph.add('3', [7, -14, -10, None, 8, 3, 1])
graph.add('4', [7, 4, -10, None, 8, 3, 1])
graph.x_labels = ('a', 'b', 'c', 'd', 'e', 'f', 'g')
graph.legend_at_bottom = True
return graph.render_response()
@app.route('/test/inverse_y_axis/<chart>')
def test_inverse_y_axis_for(chart):
graph = CHARTS_BY_NAME[chart](**dict(inverse_y_axis=True))
graph.add('inverse', [1, 2, 3, 12, 24, 36])
return graph.render_response()
@app.route('/test/only_zeroes')
def test_only_zeroes():
line = Line()
line.add('zeroes', [])
line.add('zeroes 2', [0])
return line.render_response()
@app.route('/test/rotations/<chart>')
def test_rotations_for(chart):
graph = CHARTS_BY_NAME[chart]()
# graph.x_label_rotation = 290
# graph.y_label_rotation = 0
graph.add('lalalla al alallaa a 1',
[1, 3, 12, 3, 4, None, 9])
graph.add('lalalla al alallaa a 2',
[7, -4, 10, None, 8, 3, 1], secondary=True)
graph.add('lalalla al alallaa a 3',
[7, -14, -10, None, 8, 3, 1])
graph.add('lalalla al alallaa a 4',
[7, 4, -10, None, 8, 3, 1], secondary=True)
graph.x_labels = ('a', 'b', 'c', 'd', 'e', 'f', 'g')
# graph.legend_at_bottom = True
return graph.render_response()
@app.route('/test/datetimeline')
def test_datetimeline():
line = DateTimeLine()
from datetime import timezone, timedelta
tz7 = timezone(timedelta(hours=7), 'GMT +7')
tzn4 = timezone(timedelta(hours=-4), 'GMT -4')
line.add('dt', [
(datetime(2013, 1, 12, 8, tzinfo=tz7), 300),
(datetime(2013, 1, 12, 8), 412),
(datetime(2013, 1, 12, 8, tzinfo=tzn4), 823)
])
line.x_label_rotation = 45
return line.render_response()
@app.route('/test/datetimeline_with_pytz')
def test_datetimeline_with_pytz():
import pytz
tz = pytz.timezone('US/Eastern')
line = DateTimeLine()
line.add('dt', [
(tz.localize(datetime(2013, 1, 12, 8)), 300),
(tz.localize(datetime(2013, 1, 12, 10)), 600),
(tz.localize(datetime(2013, 1, 12, 14)), 30),
(tz.localize(datetime(2013, 1, 12, 16)), 200)
])
from datetime import timezone
line.x_value_formatter = lambda x: (
x.replace(tzinfo=timezone.utc).astimezone(tz)).isoformat()
# line.x_value_formatter = lambda x: tz.normalize(
# x.replace(tzinfo=pytz.utc)).isoformat()
line.x_label_rotation = 45
return line.render_response()
@app.route('/test/order_min')
def test_order_min():
line = Line(order_min=-32)
line.add('_', [1, 32, 12, .4, .009])
return line.render_response()
@app.route('/test/custom_css_file')
def test_custom_css_file():
from tempfile import NamedTemporaryFile
custom_css = '''
{{ id }}text {
fill: green;
font-family: monospace;
}
{{ id }}.legends .legend text {
font-size: {{ font_sizes.legend }};
}
{{ id }}.axis {
stroke: #666;
}
{{ id }}.axis text {
font-size: {{ font_sizes.label }};
font-family: sans;
stroke: none;
}
{{ id }}.axis.y text {
text-anchor: end;
}
{{ id }}#tooltip text {
font-size: {{ font_sizes.tooltip }};
}
{{ id }}.dot {
fill: yellow;
}
{{ id }}.color-0 {
stroke: #ff1100;
fill: #ff1100;
}
{{ id }}.color-1 {
stroke: #ffee00;
fill: #ffee00;
}
{{ id }}.color-2 {
stroke: #66bb44;
fill: #66bb44;
}
{{ id }}.color-3 {
stroke: #88bbdd;
fill: #88bbdd;
}
{{ id }}.color-4 {
stroke: #0000ff;
fill: #0000ff;
}
'''
custom_css_file = '/tmp/pygal_custom_style.css'
with open(custom_css_file, 'w') as f:
f.write(custom_css)
config = Config(fill=True, interpolate='cubic')
config.css.append(custom_css_file)
chart = StackedLine(config)
chart.add('A', [1, 3, 5, 16, 13, 3, 7])
chart.add('B', [5, 2, 3, 2, 5, 7, 17])
chart.add('C', [6, 10, 9, 7, 3, 1, 0])
chart.add('D', [2, 3, 5, 9, 12, 9, 5])
chart.add('E', [7, 4, 2, 1, 2, 10, 0])
return chart.render_response()
@app.route('/test/legendlink/<chart>')
def test_legend_link_for(chart):
chart = CHARTS_BY_NAME[chart]()
# link on chart and label
chart.add(
[{
'value': 2,
'label': 'This is red',
'tooltip': 'LOOLLOLOLO',
'xlink': {'href': 'http://en.wikipedia.org/wiki/Red'}}],
title={
'title': 'Red',
'tooltip': 'Cramoisi',
'xlink': {'href': 'http://en.wikipedia.org/wiki/Red'}
})
chart.add({'title': 'Yellow', 'xlink': {
'href': 'http://en.wikipedia.org/wiki/Yellow',
'target': '_blank'}}, 7)
return chart.render_response()
@app.route('/test/gradient/<chart>')
def test_gradient_for(chart):
config = Config()
config.style = styles['dark']
config.defs.append('''
<linearGradient id="gradient-0" x1="0" x2="0" y1="0" y2="1">
<stop offset="0%" stop-color="#ff5995" />
<stop offset="100%" stop-color="#feed6c" />
</linearGradient>
''')
config.defs.append('''
<linearGradient id="gradient-1" x1="0" x2="0" y1="0" y2="1">
<stop offset="0%" stop-color="#b6e354" />
<stop offset="100%" stop-color="#8cedff" />
</linearGradient>
''')
config.css.append('''inline:
.color-0 {
fill: url(#gradient-0) !important;
stroke: url(#gradient-0) !important;
}''')
config.css.append('''inline:
.color-1 {
fill: url(#gradient-1) !important;
stroke: url(#gradient-1) !important;
}''')
chart = CHARTS_BY_NAME[chart](config)
chart.add('1', [1, 3, 12, 3, 4, None, 9])
chart.add('2', [7, -4, 10, None, 8, 3, 1])
chart.x_labels = ('a', 'b', 'c', 'd', 'e', 'f', 'g')
chart.legend_at_bottom = True
chart.interpolate = 'cubic'
return chart.render_response()
@app.route('/test/erfinv/approx')
def test_erfinv():
from scipy import stats as sstats
chart = Line(show_dots=False)
chart.add('scipy', [
sstats.norm.ppf(x/1000) for x in range(1, 999)])
chart.add('approx', [stats.ppf(x/1000) for x in range(1, 999)])
# chart.add('approx', [
# special.erfinv(x/1000) - erfinv(x/1000)
# for x in range(-999, 1000)])
return chart.render_response()
@app.route('/test/ci/<chart>')
def test_ci_for(chart):
chart = CHARTS_BY_NAME[chart](
style=styles['default'](
value_font_family='googlefont:Raleway',
value_colors=(None, None, 'blue', 'red', 'green'),
ci_colors=(None, 'magenta')
))
chart.add('Series 1', [
{'value': 127.3, 'ci': {
'type': 'continuous', 'sample_size': 3534, 'stddev': 19,
'confidence': .99}},
{'value': 127.3, 'ci': {
'type': 'continuous', 'sample_size': 3534, 'stddev': 19}},
{'value': 127.3, 'ci': {
'type': 'continuous', 'sample_size': 3534, 'stddev': 19,
'confidence': .90}},
{'value': 127.3, 'ci': {
'type': 'continuous', 'sample_size': 3534, 'stddev': 19,
'confidence': .75}},
])
chart.add('Series 2', [
{'value': 34.5, 'ci': {
'type': 'dichotomous', 'sample_size': 3532}},
])
chart.add('Series 3', [
{'value': 100, 'ci': {'low': 50, 'high': 150}},
{'value': 100, 'ci': {'low': 75, 'high': 175}},
{'value': 50, 'ci': {'low': 50, 'high': 100}},
{'value': 125, 'ci': {'low': 120, 'high': 130}},
])
chart.range = (30, 200)
return chart.render_response()
@app.route('/test/interruptions')
def test_interruptions():
chart = Line(allow_interruptions=True)
chart.add(
'interrupt', [22, 34, 43, 12, None, 12, 55, None, 56],
allow_interruptions=False)
chart.add('not interrupt', [
-a if a else None
for a in (22, 34, 43, 12, None, 12, 55, None, 56)])
return chart.render_response()
return list(sorted(filter(
lambda x: x.startswith('test') and not x.endswith('_for'), locals()))
) + list(sorted(filter(
lambda x: x.startswith('test') and x.endswith('_for'), locals())))