Skip to content

Commit

Permalink
Process major labels as labels. (Fix #263)
Browse files Browse the repository at this point in the history
  • Loading branch information
paradoxxxzero committed Nov 2, 2015
1 parent 05f7095 commit 57dae84
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 64 deletions.
32 changes: 19 additions & 13 deletions demo/moulinrouge/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,10 +344,11 @@ def test_negative_for(chart):

@app.route('/test/bar')
def test_bar():
bar = Bar(dynamic_print_values=True)
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 = ['a']
bar.x_labels = [2, 4, 6]
bar.x_labels_major = [4]
return bar.render_response()

@app.route('/test/histogram')
Expand Down Expand Up @@ -453,7 +454,7 @@ class LolConfig(Config):

@app.route('/test/dateline')
def test_dateline():
dateline = DateLine(show_dots=False)
dateline = DateLine(x_label_rotation=25, show_minor_x_labels=False)
dateline.x_labels = [
date(2013, 1, 1),
date(2013, 7, 1),
Expand All @@ -462,13 +463,16 @@ def test_dateline():
date(2015, 1, 1),
date(2015, 7, 1)
]
dateline.add('1', [
(date(2013, 1, 2), 300),
(date(2014, 1, 12), 412),
(date(2015, 2, 2), 823),
(date(2013, 2, 22), 672)
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(2014, 12, 7), 198),
(date(2015, 3, 21), 120)
])
dateline.x_label_rotation = 25
return dateline.render_response()

@app.route('/test/timeline')
Expand Down Expand Up @@ -645,18 +649,20 @@ def test_major_dots():

@app.route('/test/x_major_labels/<chart>')
def test_x_major_labels_for(chart):
chart = CHARTS_BY_NAME[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(10))
chart.x_labels = map(str, range(12))
# chart.x_labels_major_count = 4
# chart.x_labels_major = ['1', '5', '11', '1.0', '5.0', '11.0']
# 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', zip(*[range(12), range(12)]))
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]
Expand Down
1 change: 1 addition & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Changelog

* Add `dynamic_print_values` to show print_values on legend hover. (Fix #279)
* Fix unparse_color for python 3.5+ compatibility (thanks felixonmars, sjourdois)
* Process major labels as labels. (Fix #263)


2.0.8
Expand Down
6 changes: 6 additions & 0 deletions pygal/graph/dual.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ def _compute_x_labels(self):
else:
self._x_labels = list(zip(map(self._x_format, x_pos), x_pos))

def _compute_x_labels_major(self):
# In case of dual, x labels must adapters and so majors too
self.x_labels_major = self.x_labels_major and list(
map(self._x_adapt, self.x_labels_major))
super()._compute_x_labels_major()

def _get_x_label(self, i):
"""Convenience function to get the x_label of a value index"""
return
102 changes: 55 additions & 47 deletions pygal/graph/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,10 @@ def _x_axis(self):
lastlabel = self._x_labels[-1][0]

for label, position in self._x_labels:
major = label in self._x_major_labels
if self.horizontal:
major = position in self._x_labels_major
else:
major = label in self._x_labels_major
if not (self.show_minor_x_labels or major):
continue
guides = self.svg.node(axis, class_='guides')
Expand Down Expand Up @@ -188,7 +191,7 @@ def _x_axis(self):
' always_show' if self.show_x_guides else ''
))
for label, position in self._x_2nd_labels:
major = label in self._x_major_labels
major = label in self._x_labels_major
if not (self.show_minor_x_labels or major):
continue
# it is needed, to have the same structure as primary axis
Expand Down Expand Up @@ -224,7 +227,11 @@ def _y_axis(self):
)

for label, position in self._y_labels:
major = position in self._y_major_labels
if self.horizontal:
major = label in self._y_labels_major
else:
major = position in self._y_labels_major

if not (self.show_minor_y_labels or major):
continue
guides = self.svg.node(axis, class_='%sguides' % (
Expand Down Expand Up @@ -263,7 +270,7 @@ def _y_axis(self):
secondary_ax = self.svg.node(
self.nodes['plot'], class_="axis y2")
for label, position in self._y_2nd_labels:
major = position in self._y_major_labels
major = position in self._y_labels_major
if not (self.show_minor_y_labels or major):
continue
# it is needed, to have the same structure as primary axis
Expand Down Expand Up @@ -705,57 +712,34 @@ def _order(self):
"""Getter for the number of series"""
return len(self.all_series)

@cached_property
def _x_major_labels(self):
"""Getter for the x major label"""
if self.x_labels_major:
return self.x_labels_major
def _x_label_format_if_value(self, label):
if not is_str(label):
return self._x_format(label)
return label

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

def _compute_x_labels_major(self):
if self.x_labels_major_every:
return [self._x_labels[i][0] for i in range(
self._x_labels_major = [self._x_labels[i][0] for i in range(
0, len(self._x_labels), self.x_labels_major_every)]
if self.x_labels_major_count:

elif self.x_labels_major_count:
label_count = len(self._x_labels)
major_count = self.x_labels_major_count
if (major_count >= label_count):
return [label[0] for label in self._x_labels]
self._x_labels_major = [label[0] for label in self._x_labels]

return [self._x_labels[
else:
self._x_labels_major = [self._x_labels[
int(i * (label_count - 1) / (major_count - 1))][0]
for i in range(major_count)]

return []

@cached_property
def _y_major_labels(self):
"""Getter for the y major label"""
if self.y_labels_major:
return self.y_labels_major
if self.y_labels_major_every:
return [self._y_labels[i][1] for i in range(
0, len(self._y_labels), self.y_labels_major_every)]
if self.y_labels_major_count:
label_count = len(self._y_labels)
major_count = self.y_labels_major_count
if (major_count >= label_count):
return [label[1] for label in self._y_labels]

return [self._y_labels[
int(i * (label_count - 1) / (major_count - 1))][1]
for i in range(major_count)]

return majorize(
cut(self._y_labels, 1)
)

def _compute_x_labels(self):

def format_if_value(label):
if not is_str(label):
return self._x_format(label)
return label

self._x_labels = self.x_labels and list(
zip(map(format_if_value, self.x_labels), self._x_pos))
else:
self._x_labels_major = self.x_labels_major and list(
map(self._x_label_format_if_value, self.x_labels_major)) or []

def _compute_y_labels(self):
y_pos = compute_scale(
Expand All @@ -780,11 +764,35 @@ def _compute_y_labels(self):
else:
self._y_labels = list(zip(map(self._format, y_pos), y_pos))

def _compute_y_labels_major(self):
if self.y_labels_major_every:
self._y_labels_major = [self._y_labels[i][1] for i in range(
0, len(self._y_labels), self.y_labels_major_every)]

elif self.y_labels_major_count:
label_count = len(self._y_labels)
major_count = self.y_labels_major_count
if (major_count >= label_count):
self._y_labels_major = [label[1] for label in self._y_labels]
else:
self._y_labels_major = [self._y_labels[
int(i * (label_count - 1) / (major_count - 1))][1]
for i in range(major_count)]

elif self.y_labels_major:
self._y_labels_major = list(map(self._adapt, self.y_labels_major))
elif self._y_labels:
self._y_labels_major = majorize(cut(self._y_labels, 1))
else:
self._y_labels_major = []

def _draw(self):
"""Draw all the things"""
self._compute()
self._compute_x_labels()
self._compute_x_labels_major()
self._compute_y_labels()
self._compute_y_labels_major()
self._compute_secondary()
self._post_compute()
self._compute_margin()
Expand Down
2 changes: 2 additions & 0 deletions pygal/graph/horizontal.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ def __init__(self, *args, **kwargs):
def _post_compute(self):
"""After computations transpose labels"""
self._x_labels, self._y_labels = self._y_labels, self._x_labels
self._x_labels_major, self._y_labels_major = (
self._y_labels_major, self._x_labels_major)
self._x_2nd_labels, self._y_2nd_labels = (
self._y_2nd_labels, self._x_2nd_labels)

Expand Down
2 changes: 1 addition & 1 deletion pygal/graph/line.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def line(self, serie, rescale=False):
continue
if (serie.show_only_major_dots and
self.x_labels and i < len(self.x_labels) and
self.x_labels[i] not in self._x_major_labels):
self.x_labels[i] not in self._x_labels_major):
continue

metadata = serie.metadata.get(i)
Expand Down
4 changes: 2 additions & 2 deletions pygal/graph/radar.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def _x_axis(self, draw_axes=True):
truncation = self.truncate_label or 25

for label, theta in self._x_labels:
major = label in self._x_major_labels
major = label in self._x_labels_major
if not (self.show_minor_x_labels or major):
continue
guides = self.svg.node(axis, class_='guides')
Expand Down Expand Up @@ -132,7 +132,7 @@ def _y_axis(self, draw_axes=True):
axis = self.svg.node(self.nodes['plot'], class_="axis y web")

for label, r in reversed(self._y_labels):
major = r in self._y_major_labels
major = r in self._y_labels_major
if not (self.show_minor_y_labels or major):
continue
guides = self.svg.node(axis, class_='%sguides' % (
Expand Down
4 changes: 3 additions & 1 deletion pygal/test/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
Pyramid, HorizontalBar, HorizontalStackedBar,
DateTimeLine, TimeLine, DateLine, TimeDeltaLine)
from pygal.graph.map import BaseMap
from pygal.graph.horizontal import HorizontalGraph
from pygal.graph.dual import Dual
from pygal._compat import u
from pygal.test.utils import texts
from tempfile import NamedTemporaryFile
Expand Down Expand Up @@ -388,7 +390,7 @@ def test_x_label_major(Chart):
Pie, Treemap, Funnel, Dot, Gauge, Histogram, Box,
Pyramid, DateTimeLine, TimeLine, DateLine,
TimeDeltaLine
) or issubclass(Chart, BaseMap) or Chart._dual:
) or issubclass(Chart, (BaseMap, Dual, HorizontalGraph)):
return
chart = Chart()
chart.add('test', range(12))
Expand Down

0 comments on commit 57dae84

Please sign in to comment.