Browse Source

Support for Swiss cantons. Keys are of the form kt-xx where

xx ist the short for the respective canton
pull/207/head
Serge Droz 10 years ago
parent
commit
b72b6f1112
  1. 1
      pygal/graph/__init__.py
  2. 96
      pygal/graph/ch.cantons.svg
  3. 173
      pygal/graph/swissmap.py
  4. 7
      pygal/util.py

1
pygal/graph/__init__.py

@ -41,6 +41,7 @@ CHARTS_NAMES = [
'Histogram', 'Histogram',
'Box', 'Box',
'FrenchMap', 'FrenchMap',
'SwissMap',
'Treemap', 'Treemap',
'DateY', 'DateY',
'DateTimeLine', 'DateTimeLine',

96
pygal/graph/ch.cantons.svg

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 152 KiB

173
pygal/graph/swissmap.py

@ -0,0 +1,173 @@
# -*- 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/>.
"""
Worldmap chart
"""
from __future__ import division
from collections import defaultdict
from pygal.ghost import ChartCollection
from pygal.util import cut, cached_property, decorate
from pygal.graph.graph import Graph
from pygal._compat import u
from pygal.etree import etree
from numbers import Number
import os
CANTONS = {
'kt-zh': u("Zürich"),
'kt-be': u("Bern"),
'kt-lu': u("Luzern"),
'kt-ur': u("Uri"),
'kt-sz': u("Schwyz"),
'kt-ow': u("Obwalden"),
'kt-nw': u("Nidwalden"),
'kt-gl': u("Glarus"),
'kt-zg': u("Zug"),
'kt-fr': u("Freiburg"),
'kt-so': u("Solothurn"),
'kt-bl': u("Basel-Stadt "),
'kt-bs': u("Basle-Land"),
'kt-sh': u("Schaffhausen"),
'kt-ar': u("Appenzell Ausseroden"),
'kt-ai': u("Appenzell Innerroden"),
'kt-sg': u("St. Gallen"),
'kt-gr': u("Graubünden"),
'kt-ag': u("Aargau"),
'kt-tg': u("Thurgau"),
'kt-ti': u("Tessin"),
'kt-vd': u("Waadt"),
'kt-vs': u("Wallis"),
'ke-ne': u("Neuenburg"),
'ke-ge': u("Genf"),
}
with open(os.path.join(
os.path.dirname(__file__),
'ch.cantons.svg')) as file:
CNT_MAP = file.read()
class SwissMapCantons(Graph):
"""Swiss Cantons map"""
_dual = True
x_labels = list(CANTONS.keys())
area_names = CANTONS
area_prefix = 'z'
kind = 'canton'
svg_map = CNT_MAP
@cached_property
def _values(self):
"""Getter for series values (flattened)"""
return [val[1]
for serie in self.series
for val in serie.values
if val[1] is not None]
def _plot(self):
map = etree.fromstring(self.svg_map)
map.set('width', str(self.view.width))
map.set('height', str(self.view.height))
for i, serie in enumerate(self.series):
safe_vals = list(filter(
lambda x: x is not None, cut(serie.values, 1)))
if not safe_vals:
continue
min_ = min(safe_vals)
max_ = max(safe_vals)
for j, (area_code, value) in enumerate(serie.values):
if isinstance(area_code, Number):
area_code = '%2d' % area_code
if value is None:
continue
if max_ == min_:
ratio = 1
else:
ratio = .3 + .7 * (value - min_) / (max_ - min_)
try:
areae = map.findall(
".//*[@class='%s%s %s map-element']" % (
self.area_prefix, area_code,
self.kind))
except SyntaxError:
# Python 2.6 (you'd better install lxml)
areae = []
for g in map:
for e in g:
if '%s%s' % (
self.area_prefix, area_code
) in e.attrib.get('class', ''):
areae.append(e)
if not areae:
continue
for area in areae:
cls = area.get('class', '').split(' ')
cls.append('color-%d' % i)
area.set('class', ' '.join(cls))
area.set('style', 'fill-opacity: %f' % (ratio))
metadata = serie.metadata.get(j)
if metadata:
node = decorate(self.svg, area, metadata)
if node != area:
area.remove(node)
for g in map:
if area not in g:
continue
index = list(g).index(area)
g.remove(area)
node.append(area)
g.insert(index, node)
last_node = len(area) > 0 and area[-1]
if last_node is not None and last_node.tag == 'title':
title_node = last_node
text = title_node.text + '\n'
else:
title_node = self.svg.node(area, 'title')
text = ''
title_node.text = text + '[%s] %s: %s' % (
serie.title,
self.area_names[area_code], self._format(value))
self.nodes['plot'].append(map)
class SwissMapCantons(SwissMapCantons):
"""French regions map"""
x_labels = list(CANTONS.keys())
area_names = CANTONS
area_prefix = 'z'
svg_map = CNT_MAP
kind = 'canton'
class SwissMap(ChartCollection):
Cantons = SwissMapCantons

7
pygal/util.py

@ -339,9 +339,10 @@ def prepare_values(raw, config, cls, offset=0):
from pygal.graph.histogram import Histogram from pygal.graph.histogram import Histogram
from pygal.graph.worldmap import Worldmap from pygal.graph.worldmap import Worldmap
from pygal.graph.frenchmap import FrenchMapDepartments from pygal.graph.frenchmap import FrenchMapDepartments
from pygal.graph.swissmap import SwissMapCantons
if config.x_labels is None and hasattr(cls, 'x_labels'): if config.x_labels is None and hasattr(cls, 'x_labels'):
config.x_labels = list(map(to_unicode, cls.x_labels)) config.x_labels = list(map(to_unicode, cls.x_labels))
if config.zero == 0 and issubclass(cls, (Worldmap, FrenchMapDepartments)): if config.zero == 0 and issubclass(cls, (Worldmap, FrenchMapDepartments,SwissMapCantons)):
config.zero = 1 config.zero = 1
for key in ('x_labels', 'y_labels'): for key in ('x_labels', 'y_labels'):
@ -376,7 +377,7 @@ def prepare_values(raw, config, cls, offset=0):
metadata = {} metadata = {}
values = [] values = []
if isinstance(raw_values, dict): if isinstance(raw_values, dict):
if issubclass(cls, (Worldmap, FrenchMapDepartments)): if issubclass(cls, (Worldmap, FrenchMapDepartments,SwissMapCantons)):
raw_values = list(raw_values.items()) raw_values = list(raw_values.items())
else: else:
value_list = [None] * width value_list = [None] * width
@ -411,7 +412,7 @@ def prepare_values(raw, config, cls, offset=0):
if x_adapter: if x_adapter:
value = (x_adapter(value[0]), adapter(value[1])) value = (x_adapter(value[0]), adapter(value[1]))
if issubclass( if issubclass(
cls, (Worldmap, FrenchMapDepartments)): cls, (Worldmap, FrenchMapDepartments,SwissMapCantons)):
value = (adapter(value[0]), value[1]) value = (adapter(value[0]), value[1])
else: else:
value = list(map(adapter, value)) value = list(map(adapter, value))

Loading…
Cancel
Save