mirror of https://github.com/Kozea/pygal.git
Florian Mounier
11 years ago
3 changed files with 128 additions and 3 deletions
@ -0,0 +1,116 @@
|
||||
# -*- coding: utf-8 -*- |
||||
# This file is part of pygal |
||||
# |
||||
# A python svg graph plotting library |
||||
# Copyright © 2012-2014 Kozea |
||||
# |
||||
# This library is free software: you can redistribute it and/or modify it under |
||||
# the terms of the GNU Lesser General Public License as published by the Free |
||||
# Software Foundation, either version 3 of the License, or (at your option) any |
||||
# later version. |
||||
# |
||||
# This library is distributed in the hope that it will be useful, but WITHOUT |
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
||||
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
||||
# details. |
||||
# |
||||
# You should have received a copy of the GNU Lesser General Public License |
||||
# along with pygal. If not, see <http://www.gnu.org/licenses/>. |
||||
""" |
||||
Treemap chart |
||||
|
||||
""" |
||||
|
||||
from __future__ import division |
||||
from pygal.util import decorate |
||||
from pygal.graph.graph import Graph |
||||
from pygal.adapters import positive, none_to_zero |
||||
|
||||
|
||||
class Treemap(Graph): |
||||
"""Treemap graph""" |
||||
|
||||
_adapters = [positive, none_to_zero] |
||||
|
||||
def _rect(self, serie, x, y, w, h): |
||||
rx, ry = self.view((x, y)) |
||||
rw, rh = self.view((x + w, y + h)) |
||||
rw -= rx |
||||
rh -= ry |
||||
|
||||
serie_node = self._serie(serie._index) |
||||
rects = self.svg.node(serie_node['plot'], class_="rects") |
||||
# metadata = serie.metadata.get(i) |
||||
# value = self._format(serie.values[i]) |
||||
|
||||
# rect = decorate( |
||||
# self.svg, |
||||
# self.svg.node(rects, class_="rect"), |
||||
# metadata) |
||||
|
||||
self.svg.node(rects, 'rect', |
||||
x=rx, |
||||
y=ry, |
||||
width=rw, |
||||
height=rh, |
||||
class_='rect reactive tooltip-trigger') |
||||
|
||||
# self._tooltip_data(rect, value, |
||||
# self.view.x(acc + w / 2), |
||||
# self.view.y(.5), |
||||
# classes='centered') |
||||
# self._static_value(serie_node, value, |
||||
# self.view.x(acc + w / 2), |
||||
# self.view.y(.5)) |
||||
|
||||
def _binary_tree(self, series, total, x, y, w, h): |
||||
if len(series) == 1: |
||||
self._rect(series[0], x, y, w, h) |
||||
return |
||||
|
||||
midpoint = total / 2 |
||||
pivot_index = 1 |
||||
running_sum = 0 |
||||
for serie in series: |
||||
if running_sum >= midpoint: |
||||
pivot_index = serie._index |
||||
break |
||||
|
||||
running_sum += sum(serie.values) |
||||
|
||||
half1 = series[:pivot_index] |
||||
half2 = series[pivot_index:] |
||||
|
||||
half1_sum = sum(map(sum, map(lambda x: x.values, half1))) |
||||
half2_sum = sum(map(sum, map(lambda x: x.values, half2))) |
||||
pivot_pct = half1_sum / total |
||||
if h > w: |
||||
y_pivot = pivot_pct * h |
||||
self._binary_tree( |
||||
half1, half1_sum, x, y, w, y_pivot) |
||||
self._binary_tree( |
||||
half2, half2_sum, x, y + y_pivot, w, h - y_pivot) |
||||
else: |
||||
x_pivot = pivot_pct * w |
||||
self._binary_tree( |
||||
half1, half1_sum, x, y, x_pivot, h) |
||||
self._binary_tree( |
||||
half2, half2_sum, x + x_pivot, y, w - x_pivot, h) |
||||
|
||||
def _plot(self): |
||||
total = sum(map(sum, map(lambda x: x.values, self.series))) |
||||
if total == 0: |
||||
return |
||||
|
||||
gw = self.width - self.margin.x |
||||
gh = self.height - self.margin.y |
||||
|
||||
self.view.box.xmin = self.view.box.ymin = x = y = 0 |
||||
self.view.box.xmax = w = (total * gw / gh) ** .5 |
||||
self.view.box.ymax = h = total / w |
||||
self.view.box.fix() |
||||
|
||||
for index, serie in enumerate(self.series): |
||||
serie._index = index |
||||
|
||||
self._binary_tree(self.series, total, x, y, w, h) |
Loading…
Reference in new issue