diff --git a/pygal/config.py b/pygal/config.py index 083393cb..5150a547 100644 --- a/pygal/config.py +++ b/pygal/config.py @@ -114,6 +114,8 @@ class Config(object): truncate_label = None #: Pretty print the svg pretty_print = False + #: If True don't try to adapt / filter wrong values + strict = False def __init__(self, **kwargs): """Can be instanciated with config kwargs""" diff --git a/pygal/graph/base.py b/pygal/graph/base.py index e5ab7559..d93edde7 100644 --- a/pygal/graph/base.py +++ b/pygal/graph/base.py @@ -48,6 +48,13 @@ def __init__(self, config, series): self._box = Box() self.view = None + if self.series and self._has_data(): + self._draw() + else: + self.svg.draw_no_data() + + self.svg.pre_render() + def __getattr__(self, attr): """Search in config, then in self""" if attr in dir(self.config): @@ -129,11 +136,6 @@ def _max(self): """Getter for the maximum series value""" return (self.range and self.range[1]) or max(self._values) - @cached_property - def _cumul_max(self): - """Getter for the maximum sum of series value""" - return max(map(sum, cut(self.series, 'safe_values'))) - @cached_property def _order(self): """Getter for the maximum series value""" @@ -148,27 +150,13 @@ def _draw(self): def _has_data(self): """Check if there is any data""" - if self._order == 0: - return False - if sum(map(len, map(lambda s: s.values, self.series))) == 0: - return False - return True - - def _render(self): - """Make the graph internally""" - if self.series and self._has_data(): - self._draw() - self.svg.pre_render(False) - else: - self.svg.pre_render(True) + return sum(map(len, map(lambda s: s.values, self.series))) != 0 def render(self, is_unicode): """Render the graph, and return the svg string""" - self._render() return self.svg.render( is_unicode=is_unicode, pretty_print=self.pretty_print) def render_tree(self): """Render the graph, and return lxml tree""" - self._render() return self.svg.root diff --git a/pygal/graph/line.py b/pygal/graph/line.py index 14f4ff15..ca494d6f 100644 --- a/pygal/graph/line.py +++ b/pygal/graph/line.py @@ -41,7 +41,8 @@ def _values(self): return [ val[1] for serie in self.series - for val in serie.points + for val in (serie.interpolated + if self.interpolate else serie.points) if val[1] is not None and (not self.logarithmic or val[1] > 0)] def _fill(self, values): @@ -81,6 +82,8 @@ def line(self, serie_node, serie): y + self.value_font_size) if self.stroke: + if self.interpolate: + view_values = map(self.view, serie.interpolated) if self.fill: view_values = self._fill(view_values) self.svg.line( @@ -93,12 +96,11 @@ def _compute(self): ] if self._len != 1 else [.5] # Center if only one value for serie in self.series: + serie.points = [ + (x_pos[i], v) + for i, v in enumerate(serie.values)] if self.interpolate: - serie.points = self._interpolate(serie.values, x_pos) - else: - serie.points = [ - (x_pos[i], v) - for i, v in enumerate(serie.values)] + serie.interpolated = self._interpolate(serie.values, x_pos) if self.include_x_axis: self._box.ymin = min(self._min, 0) diff --git a/pygal/graph/radar.py b/pygal/graph/radar.py index a80055dd..fdf3fb33 100644 --- a/pygal/graph/radar.py +++ b/pygal/graph/radar.py @@ -49,7 +49,7 @@ def _get_value(self, values, i): def _values(self): if self.interpolate: return [val[0] for serie in self.series - for val in serie.points] + for val in serie.interpolated] else: return super(Line, self)._values @@ -109,6 +109,9 @@ def _compute(self): delta = 2 * pi / self._len x_pos = [.5 * pi + i * delta for i in range(self._len + 1)] for serie in self.series: + serie.points = [ + (v, x_pos[i]) + for i, v in enumerate(serie.values)] if self.interpolate: extend = 2 extended_x_pos = ( @@ -119,12 +122,8 @@ def _compute(self): extended_vals = (serie.values[-extend:] + serie.values + serie.values[:extend]) - serie.point = self._interpolate( + serie.interpolated = self._interpolate( extended_vals, extended_x_pos, polar=True) - else: - serie.points = [ - (v, x_pos[i]) - for i, v in enumerate(serie.values)] self._box.margin *= 2 self._box.xmin = self._box.ymin = - self._max diff --git a/pygal/graph/stackedline.py b/pygal/graph/stackedline.py index 3f6a5132..5cd52fef 100644 --- a/pygal/graph/stackedline.py +++ b/pygal/graph/stackedline.py @@ -49,11 +49,10 @@ def _compute(self): accumulation = [0] * self._len for serie in self.series: accumulation = map(sum, zip(accumulation, serie.values)) + serie.points = [ + (x_pos[i], v) + for i, v in enumerate(accumulation)] if self.interpolate: - serie.points = self._interpolate(accumulation, x_pos) - else: - serie.points = [ - (x_pos[i], v) - for i, v in enumerate(accumulation)] + serie.interpolated = self._interpolate(accumulation, x_pos) return super(StackedLine, self)._compute() diff --git a/pygal/graph/xy.py b/pygal/graph/xy.py index 09f330b1..1c1a1e1d 100644 --- a/pygal/graph/xy.py +++ b/pygal/graph/xy.py @@ -46,20 +46,19 @@ def _compute(self): rng = (xmax - xmin) for serie in self.series: + serie.points = serie.values if self.interpolate: vals = zip(*sorted(serie.points, key=lambda x: x[0])) - serie.points = self._interpolate( + serie.interpolated = self._interpolate( vals[1], vals[0], xy=True, xy_xmin=xmin, xy_rng=rng) - else: - serie.points = serie.values if self.interpolate: xvals = [val[0] for serie in self.series - for val in serie.points] + for val in serie.interpolated] yvals = [val[1] for serie in self.series - for val in serie.points] + for val in serie.interpolated] self._box.xmin, self._box.xmax = min(xvals), max(xvals) self._box.ymin, self._box.ymax = min(yvals), max(yvals) diff --git a/pygal/svg.py b/pygal/svg.py index a5748abb..438d122a 100644 --- a/pygal/svg.py +++ b/pygal/svg.py @@ -172,7 +172,7 @@ def slice( self.graph._tooltip_data(node, val, x, y, classes="centered") self.graph._static_value(serie_node, val, x, y) - def pre_render(self, no_data=False): + def pre_render(self): """Last things to do before rendering""" self.add_styles() self.add_scripts() @@ -181,12 +181,13 @@ def pre_render(self, no_data=False): if self.graph.explicit_size: self.root.set('width', str(self.graph.width)) self.root.set('height', str(self.graph.height)) - if no_data: - no_data = self.node(self.root, 'text', - x=self.graph.width / 2, - y=self.graph.height / 2, - class_='no_data') - no_data.text = self.graph.no_data_text + + def draw_no_data(self): + no_data = self.node(self.root, 'text', + x=self.graph.width / 2, + y=self.graph.height / 2, + class_='no_data') + no_data.text = self.graph.no_data_text def render(self, is_unicode=False, pretty_print=False): """Last thing to do before rendering"""