Skip to content

Commit

Permalink
Fix a lot of label related things
Browse files Browse the repository at this point in the history
  • Loading branch information
paradoxxxzero committed Jul 23, 2015
1 parent a1839a7 commit 494d466
Show file tree
Hide file tree
Showing 22 changed files with 106 additions and 68 deletions.
2 changes: 1 addition & 1 deletion demo/moulinrouge/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ def all(style='default', color=None, interpolate=None, base_style=None):
else:
config.x_labels = [random_label() for i in range(data)]
svgs.append({'type': type,
'series': xy_series if type == 'XY' else other_series,
'series': xy_series if chart._dual else other_series,
'config': b64encode(pickle.dumps(config))})

return render_template('svgs.jinja2',
Expand Down
8 changes: 5 additions & 3 deletions demo/moulinrouge/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -376,8 +376,8 @@ def test_secondary_for(chart):
chart.x_label_rotation = 25
chart.y_label_rotation = 50
chart.add('1', [30, 20, -2])
chart.add(10 * '1b', [-4, 50, 6], secondary=True)
chart.add(10 * '2b', [None, 10, 20], secondary=True)
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)
Expand All @@ -395,6 +395,8 @@ def test_secondary_xy():
@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])
Expand All @@ -408,14 +410,14 @@ 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])
stacked.x_labels = ['a', 'b', 'c']
return stacked.render_response()

@app.route('/test/show_dots')
Expand Down
7 changes: 0 additions & 7 deletions docs/api/pygal.adapters.rst
Original file line number Diff line number Diff line change
@@ -1,7 +0,0 @@
pygal.adapters module
=====================

.. automodule:: pygal.adapters
:members:
:undoc-members:
:show-inheritance:
3 changes: 3 additions & 0 deletions pygal/adapters.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,15 @@
# along with pygal. If not, see <http://www.gnu.org/licenses/>.
"""Value adapters to use when a chart doesn't accept all value types"""
from decimal import Decimal
from pygal._compat import is_str


def positive(x):
"""Return zero if value is negative"""
if x is None:
return
if is_str(x):
return x
if x < 0:
return 0
return x
Expand Down
9 changes: 6 additions & 3 deletions pygal/graph/bar.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ def bar(self, serie, rescale=False):
x_center, y_center = self._bar(
serie, bar, x, y, i, self.zero, secondary=rescale)
self._tooltip_data(
bar, val, x_center, y_center, classes="centered")
bar, val, x_center, y_center, "centered",
self._get_x_label(i))
self._static_value(serie_node, val, x_center, y_center)

def _compute(self):
Expand All @@ -98,11 +99,13 @@ def _compute(self):
if self._max:
self._box.ymax = max(self._max, self.zero)

x_pos = [
self._x_pos = [
x / self._len for x in range(self._len + 1)
] if self._len > 1 else [0, 1] # Center if only one value

self._points(x_pos)
self._points(self._x_pos)

self._x_pos = [(i + .5) / self._len for i in range(self._len)]

def _compute_secondary(self):
"""Compute parameters for secondary series rendering"""
Expand Down
2 changes: 2 additions & 0 deletions pygal/graph/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ def prepare_values(self, raw, offset=0):
value = (None, None, None)
elif not is_list_like(value):
value = (value, self.zero, self.zero)
elif len(value) == 2:
value = (1, value[0], value[1])
value = list(map(adapter, value))
elif self._dual:
if value is None:
Expand Down
22 changes: 12 additions & 10 deletions pygal/graph/box.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,16 @@ def _format(self):
def format_maybe_quartile(x):
if is_list_like(x):
if self.box_mode == "extremes":
return 'Min: %s Q1: %s Q2: %s Q3: %s Max: %s' \
% tuple(map(sup, x[1:6]))
return (
'Min: %s\nQ1 : %s\nQ2 : %s\nQ3 : %s\nMax: %s' %
tuple(map(sup, x[1:6])))
elif self.box_mode in ["tukey", "stdev", "pstdev"]:
return 'Min: %s Lower Whisker: %s Q1: %s Q2: %s Q3: %s '\
'Upper Whisker: %s Max: %s' % tuple(map(sup, x))
return (
'Min: %s\nLower Whisker: %s\nQ1: %s\nQ2: %s\nQ3: %s\n'
'Upper Whisker: %s\nMax: %s' % tuple(map(sup, x)))
elif self.box_mode == '1.5IQR':
# 1.5IQR mode
return 'Q1: %s Q2: %s Q3: %s' % tuple(map(sup, x[2:5]))
return 'Q1: %s\nQ2: %s\nQ3: %s' % tuple(map(sup, x[2:5]))
else:
return sup(x)
return format_maybe_quartile
Expand All @@ -71,15 +73,14 @@ def _compute(self):
serie.values, serie.outliers = \
self._box_points(serie.values, self.box_mode)

self._x_pos = [
(i + .5) / self._order for i in range(self._order)]

if self._min:
self._box.ymin = min(self._min, self.zero)
if self._max:
self._box.ymax = max(self._max, self.zero)

def _compute_x_labels(self):
self._x_labels = self.x_labels and list(zip(self.x_labels, [
(i + .5) / self._order for i in range(self._order)]))

def _plot(self):
"""Plot the series data"""
for serie in self.series:
Expand Down Expand Up @@ -108,7 +109,8 @@ def _boxf(self, serie):

x_center, y_center = self._draw_box(
box, serie.values[1:6], serie.outliers, serie.index, metadata)
self._tooltip_data(box, val, x_center, y_center, classes="centered")
self._tooltip_data(box, val, x_center, y_center, "centered",
self._get_x_label(serie.index))
self._static_value(serie_node, val, x_center, y_center)

def _draw_box(self, parent_node, quartiles, outliers, box_index, metadata):
Expand Down
8 changes: 3 additions & 5 deletions pygal/graph/dot.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,9 @@ def dot(self, serie, r_max):
' negative' if value < 0 else '')), metadata)

value = self._format(value)
self._tooltip_data(dots, value, x, y, classes='centered')
self._tooltip_data(
dots, value, x, y, 'centered',
self._get_x_label(i))
self._static_value(serie_node, value, x, y)

def _compute(self):
Expand All @@ -86,10 +88,6 @@ def _compute(self):
(self._x_pos[i], self._y_pos[j])
for i in range(x_len)]

def _compute_x_labels(self):
self._x_labels = self.x_labels and list(
zip(self.x_labels, self._x_pos))

def _compute_y_labels(self):
self._y_labels = list(zip(
self.y_labels or [
Expand Down
4 changes: 4 additions & 0 deletions pygal/graph/dual.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,7 @@ def _compute_x_labels(self):

else:
self._x_labels = list(zip(map(self._x_format, x_pos), x_pos))

def _get_x_label(self, i):
"""Convenience function to get the x_label of a value index"""
return
6 changes: 4 additions & 2 deletions pygal/graph/funnel.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,13 @@ def funnel(self, serie):
points=' '.join(map(fmt, map(self.view, poly))),
class_='funnel reactive tooltip-trigger'), metadata)

# Poly center from label
x, y = self.view((
# Poly center from label
self._center(self._x_pos[serie.index]),
sum([point[1] for point in poly]) / len(poly)))
self._tooltip_data(funnels, value, x, y, classes='centered')
self._tooltip_data(
funnels, value, x, y, 'centered',
self._get_x_label(serie.index))
self._static_value(serie_node, value, x, y)

def _center(self, x):
Expand Down
7 changes: 6 additions & 1 deletion pygal/graph/gauge.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,9 @@ def point(x, y):
metadata)

x, y = self.view((.75, theta))
self._tooltip_data(gauges, value, x, y)
self._tooltip_data(
gauges, value, x, y,
xlabel=self._get_x_label(i))
self._static_value(serie_node, value, x, y)

def _y_axis(self, draw_axes=True):
Expand Down Expand Up @@ -138,6 +140,9 @@ def _compute(self):
self.min_,
self.max_)

def _compute_x_labels(self):
pass

def _compute_y_labels(self):
y_pos = compute_scale(
self.min_, self.max_, self.logarithmic,
Expand Down
15 changes: 12 additions & 3 deletions pygal/graph/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ def _rescale(self, points):
if y is not None else None)
for x, y in points]

def _tooltip_data(self, node, value, x, y, classes=None):
def _tooltip_data(self, node, value, x, y, classes=None, xlabel=None):
"""Insert in desc tags informations for the javascript tooltip"""
self.svg.node(node, 'desc', class_="value").text = value
if classes is None:
Expand All @@ -444,6 +444,9 @@ def _tooltip_data(self, node, value, x, y, classes=None):
class_="x " + classes).text = str(x)
self.svg.node(node, 'desc',
class_="y " + classes).text = str(y)
if xlabel:
self.svg.node(node, 'desc',
class_="x_label").text = str(xlabel)

def _static_value(self, serie_node, value, x, y):
"""Write the print value"""
Expand Down Expand Up @@ -499,6 +502,12 @@ def _post_compute(self):
"""Hook called after compute and before margin computations and plot"""
pass

def _get_x_label(self, i):
"""Convenience function to get the x_label of a value index"""
if not self.x_labels or not self._x_labels or len(self._x_labels) <= i:
return
return self._x_labels[i][0]

@property
def all_series(self):
"""Getter for all series (nomal and secondary)"""
Expand Down Expand Up @@ -716,8 +725,8 @@ def _y_major_labels(self):
)

def _compute_x_labels(self):
self._x_labels = self.x_labels and list(zip(self.x_labels, [
(i + .5) / self._len for i in range(self._len)]))
self._x_labels = self.x_labels and list(
zip(self.x_labels, self._x_pos))

def _compute_y_labels(self):
y_pos = compute_scale(
Expand Down
9 changes: 4 additions & 5 deletions pygal/graph/histogram.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,14 @@
"""

from __future__ import division
from pygal._compat import is_list_like

from pygal.graph.dual import Dual
from pygal.util import (
swap, ident, compute_scale, decorate, cached_property, alter)
from pygal.util import alter, cached_property, decorate, ident, swap


class Histogram(Dual):

"""Histogram chart class"""

_series_margin = 0

@cached_property
Expand Down Expand Up @@ -97,7 +95,8 @@ def bar(self, serie, rescale=False):
x_center, y_center = self._bar(
serie, bar, x0, x1, y, i, self.zero, secondary=rescale)
self._tooltip_data(
bar, val, x_center, y_center, classes="centered")
bar, val, x_center, y_center, "centered",
self._get_x_label(i))
self._static_value(serie_node, val, x_center, y_center)

def _compute(self):
Expand Down
6 changes: 6 additions & 0 deletions pygal/graph/horizontal.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,9 @@ def _set_view(self):
self.width - self.margin_box.x,
self.height - self.margin_box.y,
self._box)

def _get_x_label(self, i):
"""Convenience function to get the x_label of a value index"""
if not self.x_labels or not self._y_labels or len(self._y_labels) <= i:
return
return self._y_labels[i][0]
7 changes: 4 additions & 3 deletions pygal/graph/line.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@ def line(self, serie, rescale=False):
dots, 'circle', cx=x, cy=y, r=serie.dots_size,
class_='dot reactive tooltip-trigger'), metadata)
self._tooltip_data(
dots, val, x, y)
dots, val, x, y,
xlabel=self._get_x_label(i))
self._static_value(
serie_node, val,
x + self.style.value_font_size,
Expand All @@ -141,11 +142,11 @@ def line(self, serie, rescale=False):
def _compute(self):
"""Compute y min and max and y scale and set labels"""
# X Labels
x_pos = [
self._x_pos = [
x / (self._len - 1) for x in range(self._len)
] if self._len != 1 else [.5] # Center if only one value

self._points(x_pos)
self._points(self._x_pos)

if self.include_x_axis:
# Y Label
Expand Down
2 changes: 1 addition & 1 deletion pygal/graph/map.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ def _plot(self):
alter(node, metadata)

value = self._get_value((area_code, value))
self._tooltip_data(area, value, 0, 0, classes='auto')
self._tooltip_data(area, value, 0, 0, 'auto')

self.nodes['plot'].append(map)

Expand Down
4 changes: 2 additions & 2 deletions pygal/graph/pie.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def slice(self, serie, start_angle, total):

alter(self.svg.slice(
serie_node, slice_, big_radius, small_radius,
angle, start_angle, center, val), metadata)
angle, start_angle, center, val, i), metadata)
start_angle += angle
total_perc += perc

Expand All @@ -91,7 +91,7 @@ def slice(self, serie, start_angle, total):
self.svg.slice(serie_node,
self.svg.node(slices, class_="big_slice"),
radius * .9, 0, serie_angle,
original_start_angle, center, val)
original_start_angle, center, val, i)
return serie_angle

def _compute_x_labels(self):
Expand Down
12 changes: 3 additions & 9 deletions pygal/graph/radar.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ class Radar(Line):

def __init__(self, *args, **kwargs):
"""Init custom vars"""
self._x_pos = None
self._rmax = None
super(Radar, self).__init__(*args, **kwargs)

Expand Down Expand Up @@ -168,14 +167,14 @@ def _y_axis(self, draw_axes=True):
def _compute(self):
"""Compute r min max and labels position"""
delta = 2 * pi / self._len if self._len else 0
x_pos = [.5 * pi + i * delta for i in range(self._len + 1)]
self._x_pos = [.5 * pi + i * delta for i in range(self._len + 1)]
for serie in self.all_series:
serie.points = [
(v, x_pos[i])
(v, self._x_pos[i])
for i, v in enumerate(serie.values)]
if self.interpolate:
extended_x_pos = (
[.5 * pi - delta] + x_pos)
[.5 * pi - delta] + self._x_pos)
extended_vals = (serie.values[-1:] +
serie.values)
serie.interpolated = list(
Expand All @@ -190,11 +189,6 @@ def _compute(self):
self._rmax = self._max or 1
self._box.set_polar_box(self._rmin, self._rmax)
self._self_close = True
self._x_pos = x_pos

def _compute_x_labels(self):
self._x_labels = self.x_labels and list(
zip(self.x_labels, self._x_pos))

def _compute_y_labels(self):
y_pos = compute_scale(
Expand Down

0 comments on commit 494d466

Please sign in to comment.