Skip to content

Commit

Permalink
Pylint and interpolation refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
paradoxxxzero committed Apr 4, 2012
1 parent e61551e commit a1ec68e
Show file tree
Hide file tree
Showing 17 changed files with 286 additions and 196 deletions.
4 changes: 2 additions & 2 deletions .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
const-rgx=(([A-Za-z_][A-Za-z0-9_]*)|(__.*__))$

# Regular expression which should only match correct class names
class-rgx=[a-zA-Z_][a-zA-Z0-9]+$
class-rgx=[a-zA-Z_][a-zA-Z0-9_]+$

# Regular expression which should only match correct function names
function-rgx=[a-z_][a-z0-9_]{2,30}$
Expand Down Expand Up @@ -200,7 +200,7 @@ max-args=20
ignored-argument-names=_.*

# Maximum number of locals for function / method body
max-locals=15
max-locals=30

# Maximum number of return / yield for function / method body
max-returns=6
Expand Down
4 changes: 3 additions & 1 deletion demo/moulinrouge/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@ def svg(type, series, config):

@app.route("/all")
@app.route("/all/style=<style>")
def all(style=DefaultStyle):
@app.route("/all/interpolate=<interpolate>")
def all(style='default', interpolate=None):
width, height = 600, 400
data = random.randrange(1, 10)
order = random.randrange(1, 10)
Expand All @@ -119,6 +120,7 @@ def all(style=DefaultStyle):
config.height = height
config.fill = bool(random.randrange(0, 2))
config.human_readable = True
config.interpolate = interpolate
config.style = styles[style]
config.x_labels = [random_label() for i in range(data)]
svgs = []
Expand Down
1 change: 0 additions & 1 deletion pygal/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ class FontSizes(object):

class Config(object):
"""Class holding config values"""
_horizontal = False

#: Graph width
width = 800
Expand Down
4 changes: 4 additions & 0 deletions pygal/graph/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,7 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with pygal. If not, see <http://www.gnu.org/licenses/>.
"""
Graph modules
"""
26 changes: 18 additions & 8 deletions pygal/graph/bar.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,31 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with pygal. If not, see <http://www.gnu.org/licenses/>.
"""
Bar chart
"""

from __future__ import division
from pygal.graph.graph import Graph
from pygal.util import swap, ident
from pygal.util import swap, ident, compute_scale


class Bar(Graph):
"""Bar graph"""

def __init__(self, *args, **kwargs):
self._x_ranges = None
super(Bar, self).__init__(*args, **kwargs)

def bar(self, serie_node, serie, values, stack_vals=None):
"""Draw a bar graph for a serie"""
# value here is a list of tuple range of tuple coord

def view(rng):
"""Project range"""
t, T = rng
fun = swap if self._horizontal else ident
fun = swap if self.horizontal else ident
return self.view(fun(t)), self.view(fun(T))

bars = self.svg.node(serie_node['plot'], class_="bars")
Expand All @@ -52,12 +61,12 @@ def view(rng):
#
# x and y are left range coords and X, Y right ones
val = self._format(values[i][1][1])
if self._horizontal:
if self.horizontal:
x, y, X, Y = Y, X, y, x
width = X - x
padding = .1 * width
inner_width = width - 2 * padding
if self._horizontal:
if self.horizontal:
height = self.view.x(0) - y
else:
height = self.view.y(0) - y
Expand Down Expand Up @@ -93,11 +102,11 @@ def view(rng):
str, (x + bar_inner_width / 2, y + height / 2))
self.svg.node(bar, 'desc',
class_="x centered"
).text = tooltip_positions[int(self._horizontal)]
).text = tooltip_positions[int(self.horizontal)]
self.svg.node(bar, 'desc',
class_="y centered"
).text = tooltip_positions[int(not self._horizontal)]
if self._horizontal:
).text = tooltip_positions[int(not self.horizontal)]
if self.horizontal:
x += .3 * self.value_font_size
y += height / 2
else:
Expand All @@ -117,7 +126,8 @@ def _compute(self):
x_step = len(self.series[0].values)
x_pos = [x / x_step for x in range(x_step + 1)
] if x_step > 1 else [0, 1] # Center if only one value
y_pos = self._compute_scale(self._box.ymin, self._box.ymax,
y_pos = compute_scale(
self._box.ymin, self._box.ymax, self.logarithmic
) if not self.y_labels else map(float, self.y_labels)

self._x_ranges = zip(x_pos, x_pos[1:])
Expand Down
88 changes: 18 additions & 70 deletions pygal/graph/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,38 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with pygal. If not, see <http://www.gnu.org/licenses/>.
"""
Base for pygal charts
"""

from __future__ import division
import io
from pygal.serie import Serie
from pygal.view import Margin, Box
from pygal.util import round_to_scale, cut, rad, humanize
from pygal.util import get_text_box, get_texts_box, cut, rad, humanize
from pygal.svg import Svg
from pygal.config import Config
from pygal.util import cached_property
from math import log10, sin, cos, floor, ceil
from math import sin, cos


class BaseGraph(object):
"""Graphs commons"""

def __init__(self, config=None, **kwargs):
"""Init the graph"""
self.horizontal = hasattr(self, 'horizontal') and self.horizontal
self.config = config or Config()
self.config(**kwargs)
self.svg = Svg(self)
self.series = []
self._x_labels = self._y_labels = None
self._x_labels = None
self._y_labels = None
self._box = None
self.nodes = {}
self.margin = None
self.view = None

def add(self, title, values):
"""Add a serie to this graph"""
Expand All @@ -58,69 +69,6 @@ def _format(self):
"""Return the value formatter for this graph"""
return humanize if self.human_readable else str

def _compute_logarithmic_scale(self, min_, max_):
"""Compute an optimal scale for logarithmic"""
min_order = int(floor(log10(min_)))
max_order = int(ceil(log10(max_)))
positions = []
amplitude = max_order - min_order
if amplitude <= 1:
return []
detail = 10.
while amplitude * detail < 20:
detail *= 2
while amplitude * detail > 50:
detail /= 2
for order in range(min_order, max_order + 1):
for i in range(int(detail)):
tick = (10 * i / detail or 1) * 10 ** order
tick = round_to_scale(tick, tick)
if min_ <= tick <= max_ and tick not in positions:
positions.append(tick)
return positions

def _compute_scale(self, min_, max_, min_scale=4, max_scale=20):
"""Compute an optimal scale between min and max"""
if min_ == 0 and max_ == 0:
return [0]
if max_ - min_ == 0:
return [min_]
if self.logarithmic:
log_scale = self._compute_logarithmic_scale(min_, max_)
if log_scale:
return log_scale
# else we fallback to normal scalling
order = round(log10(max(abs(min_), abs(max_)))) - 1
while (max_ - min_) / (10 ** order) < min_scale:
order -= 1
step = float(10 ** order)
while (max_ - min_) / step > max_scale:
step *= 2.
positions = []
position = round_to_scale(min_, step)
while position < (max_ + step):
rounded = round_to_scale(position, step)
if min_ <= rounded <= max_:
if rounded not in positions:
positions.append(rounded)
position += step
if len(positions) < 2:
return [min_, max_]
return positions

def _text_len(self, lenght, fs):
"""Approximation of text length"""
return lenght * 0.6 * fs

def _get_text_box(self, text, fs):
"""Approximation of text bounds"""
return (fs, self._text_len(len(text), fs))

def _get_texts_box(self, texts, fs):
"""Approximation of multiple texts bounds"""
max_len = max(map(len, texts))
return (fs, self._text_len(max_len, fs))

def _compute(self):
"""Initial computations to draw the graph"""

Expand All @@ -130,16 +78,16 @@ def _plot(self):
def _compute_margin(self):
"""Compute graph margins from set texts"""
if self.show_legend:
h, w = self._get_texts_box(
h, w = get_texts_box(
cut(self.series, 'title'), self.legend_font_size)
self.margin.right += 10 + w + self.legend_box_size

if self.title:
h, w = self._get_text_box(self.title, self.title_font_size)
h, w = get_text_box(self.title, self.title_font_size)
self.margin.top += 10 + h

if self._x_labels:
h, w = self._get_texts_box(
h, w = get_texts_box(
cut(self._x_labels), self.label_font_size)
self.margin.bottom += 10 + max(
w * sin(rad(self.x_label_rotation)), h)
Expand All @@ -148,7 +96,7 @@ def _compute_margin(self):
w * cos(rad(self.x_label_rotation)),
self.margin.right)
if self._y_labels:
h, w = self._get_texts_box(
h, w = get_texts_box(
cut(self._y_labels), self.label_font_size)
self.margin.left += 10 + max(
w * cos(rad(self.y_label_rotation)), h)
Expand Down
Loading

0 comments on commit a1ec68e

Please sign in to comment.