From 606d246833419a0317ae19a4a045e7709b117247 Mon Sep 17 00:00:00 2001 From: Florian Mounier Date: Thu, 13 Feb 2014 12:06:01 +0100 Subject: [PATCH] Add major y options, this should fix #72 and fix #88 and fix #93 --- CHANGELOG | 11 +++++++++++ pygal/config.py | 18 +++++++++++++++--- pygal/graph/graph.py | 34 ++++++++++++++++++++++++++-------- pygal/graph/radar.py | 29 +++++++++++++++++++++++------ pygal/test/test_util.py | 4 ++++ 5 files changed, 79 insertions(+), 17 deletions(-) create mode 100644 CHANGELOG diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..6df8408 --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,11 @@ +TO BE RELEASED: V 1.4.0 + Finally a changelog ! + Hopefully fix weird major scale algorithm + Add options to customize major labels (y_labels_major, y_labels_major_every, y_labels_major_count) + Css can now be inline with the "inline:" prefix + Visited links bug fixed + +V 1.3.x + Whisker Box Plot + Python 3 fix + DateY X axis formatting (x_label_format) diff --git a/pygal/config.py b/pygal/config.py index 7267b3f..d17f337 100644 --- a/pygal/config.py +++ b/pygal/config.py @@ -204,9 +204,21 @@ class Config(object): "You can specify explicit y labels", "Must be a list of numbers", float) - y_labels_use_major = Key( - True, bool, "Label", - "Whether to promote some labels majors.") + y_labels_major = Key( + None, list, "Label", + "Y labels that will be marked major. Default: auto", + subtype=str) + + y_labels_major_every = Key( + None, int, "Label", + "Mark every n-th y label as major.") + + y_labels_major_count = Key( + None, int, "Label", + "Mark n evenly distributed y labels as major.") + + show_minor_y_labels = Key( + True, bool, "Label", "Set to false to hide y-labels not marked major") show_y_labels = Key( True, bool, "Label", "Set to false to hide y-labels") diff --git a/pygal/graph/graph.py b/pygal/graph/graph.py index 7b38a0d..c3e1bb5 100644 --- a/pygal/graph/graph.py +++ b/pygal/graph/graph.py @@ -158,6 +158,7 @@ class Graph(BaseGraph): for i in range(major_count)] else: x_labels_major = [] + for label, position in self._x_labels: major = label in x_labels_major if not (self.show_minor_x_labels or major): @@ -228,11 +229,29 @@ class Graph(BaseGraph): d='M%f %f h%f' % (0, self.view.height, self.view.width), class_='line' ) - majors = majorize( - cut(self._y_labels, 1) - ) if self.y_labels_use_major else [] + + if self.y_labels_major: + y_labels_major = self.y_labels_major + elif self.y_labels_major_every: + 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): + y_labels_major = [label[1] for label in self._y_labels] + else: + y_labels_major = [self._y_labels[ + int(i * (label_count - 1) / (major_count - 1))][1] + for i in range(major_count)] + else: + y_labels_major = majorize( + cut(self._y_labels, 1) + ) for label, position in self._y_labels: - major = position in majors + major = position in y_labels_major + if not (self.show_minor_y_labels or major): + continue guides = self.svg.node(axis, class_='%sguides' % ( 'logarithmic ' if self.logarithmic else '' )) @@ -265,11 +284,10 @@ class Graph(BaseGraph): if self._y_2nd_labels: secondary_ax = self.svg.node( self.nodes['plot'], class_="axis y2") - majors = majorize( - cut(self._y_2nd_labels, 1) - ) if self.y_labels_use_major else [] for label, position in self._y_2nd_labels: - major = position in majors + major = position in y_labels_major + if not (self.show_minor_x_labels or major): + continue # it is needed, to have the same structure as primary axis guides = self.svg.node(secondary_ax, class_='guides') x = self.view.width + 5 diff --git a/pygal/graph/radar.py b/pygal/graph/radar.py index ad9e1fd..2c7a650 100644 --- a/pygal/graph/radar.py +++ b/pygal/graph/radar.py @@ -75,7 +75,7 @@ class Radar(Line): if self.x_labels_major: x_labels_major = self.x_labels_major elif self.x_labels_major_every: - x_labels_major = [self._x_labels[i][0] for i in xrange( + x_labels_major = [self._x_labels[i][0] for i in range( 0, len(self._x_labels), self.x_labels_major_every)] elif self.x_labels_major_count: label_count = len(self._x_labels) @@ -85,7 +85,7 @@ class Radar(Line): else: x_labels_major = [self._x_labels[ int(i * label_count / major_count)][0] - for i in xrange(major_count)] + for i in range(major_count)] else: x_labels_major = [] @@ -118,12 +118,29 @@ class Radar(Line): return axis = self.svg.node(self.nodes['plot'], class_="axis y web") - majors = majorize( - cut(self._y_labels, 1) - ) if self.y_labels_use_major else [] + if self.y_labels_major: + y_labels_major = self.y_labels_major + elif self.y_labels_major_every: + 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): + y_labels_major = [label[1] for label in self._y_labels] + else: + y_labels_major = [self._y_labels[ + int(i * (label_count - 1) / (major_count - 1))][1] + for i in range(major_count)] + else: + y_labels_major = majorize( + cut(self._y_labels, 1) + ) for label, r in reversed(self._y_labels): - major = r in majors + major = r in y_labels_major + if not (self.show_minor_y_labels or major): + continue guides = self.svg.node(axis, class_='guides') self.svg.line( guides, [self.view((r, theta)) for theta in self.x_pos], diff --git a/pygal/test/test_util.py b/pygal/test/test_util.py index 1044e76..5deaf13 100644 --- a/pygal/test/test_util.py +++ b/pygal/test/test_util.py @@ -167,3 +167,7 @@ def test_major(): assert majorize((-6, -5, -4, -3, -2, -1, 0, 1, 2, 3)) == [-5, 0] assert majorize((-6, -5, -4, -3)) == [-5] assert majorize((1, 10, 100, 1000, 10000, 100000)) == [] + assert majorize(range(30, 70, 5)) == [30, 40, 50, 60] + assert majorize(range(20, 55, 2)) == [20, 30, 40, 50] + assert majorize(range(21, 83, 3)) == [30, 45, 60, 75] + assert majorize(range(20, 83, 3)) == [20, 35, 50, 65, 80]