def to_svg_group(self, width=None, height=None): """ Render this chart to an SVG group element. This can then be placed inside an :code:`<svg>` tag to make a complete SVG graphic. See :meth:`.Chart.to_svg` for arguments. """ width = width or theme.default_width height = height or theme.default_height if not self._layers: raise ValueError( 'You must add at least one series to the chart before rendering.' ) if isinstance(theme.margin, float): default_margin = width * theme.margin margin = Box(top=default_margin, right=default_margin, bottom=default_margin, left=default_margin) elif isinstance(margin, int): margin = Box(margin, margin, margin, margin) elif not isinstance(margin, Box): margin = Box(*margin) # Root / background root_group = ET.Element('g') root_group.append( ET.Element('rect', x=six.text_type(0), y=six.text_type(0), width=six.text_type(width), height=six.text_type(height), fill=theme.background_color)) # Margins margin_group = ET.Element('g') margin_group.set('transform', svg.translate(margin.left, margin.top)) margin_width = width - (margin.left + margin.right) margin_height = height - (margin.top + margin.bottom) root_group.append(margin_group) # Header header_group = ET.Element('g') header_margin = 0 if self._title: label = ET.Element('text', x=six.text_type(0), y=six.text_type(0), fill=theme.title_color) label.set('font-family', theme.title_font_family) label.set('font-size', six.text_type(theme.title_font_size)) label.text = six.text_type(self._title) header_group.append(label) header_margin += theme.title_font_char_height + theme.title_gap # Legend if len(self._layers) > 1 or isinstance(self._layers[0][0], CategorySeries): legend_group = ET.Element('g') legend_group.set('transform', svg.translate(0, header_margin)) indent = 0 rows = 1 palette = self._palette() for series, shape in self._layers: for item_group, item_width in shape.legend_to_svg( series, palette): if indent + item_width > width: indent = 0 rows += 1 y = (rows - 1) * (theme.legend_font_char_height + theme.legend_gap) item_group.set('transform', svg.translate(indent, y)) indent += item_width legend_group.append(item_group) legend_height = rows * (theme.legend_font_char_height + theme.legend_gap) header_margin += legend_height header_group.append(legend_group) margin_group.append(header_group) # Body body_group = ET.Element('g') body_group.set('transform', svg.translate(0, header_margin)) body_width = margin_width body_height = margin_height - header_margin margin_group.append(body_group) # Axes x_scale, x_axis = self._validate_dimension(X) y_scale, y_axis = self._validate_dimension(Y) bottom_margin = x_axis.estimate_label_margin(x_scale, 'bottom') left_margin = y_axis.estimate_label_margin(y_scale, 'left') canvas_width = body_width - left_margin canvas_height = body_height - bottom_margin axes_group = ET.Element('g') axes_group.set('transform', svg.translate(left_margin, 0)) axes_group.append( x_axis.to_svg(canvas_width, canvas_height, x_scale, 'bottom')) axes_group.append( y_axis.to_svg(canvas_width, canvas_height, y_scale, 'left')) header_group.set('transform', svg.translate(left_margin, 0)) body_group.append(axes_group) # Series series_group = ET.Element('g') palette = self._palette() for series, shape in self._layers: series_group.append( shape.to_svg(canvas_width, canvas_height, x_scale, y_scale, series, palette)) axes_group.append(series_group) return root_group
def to_svg(self, path=None, width=None, height=None): """ Render the grid to an SVG. The :code:`width` and :code:`height` arguments refer to the size of the entire grid. The size of individual charts will be inferred automatically. See :meth:`.Chart.to_svg` for arguments. """ if not width or not height: count = len(self._charts) columns = math.ceil(math.sqrt(count)) rows = math.ceil(count / columns) width = columns * theme.default_chart_width height = rows * theme.default_chart_height root = ET.Element('svg', width=six.text_type(width), height=six.text_type(height), version='1.1', xmlns='http://www.w3.org/2000/svg' ) # Root / background root_group = ET.Element('g') root_group.append(ET.Element('rect', x=six.text_type(0), y=six.text_type(0), width=six.text_type(width), height=six.text_type(height), fill=theme.background_color )) root.append(root_group) # Charts grid_group = ET.Element('g') chart_count = len(self._charts) grid_width = math.ceil(math.sqrt(chart_count)) grid_height = math.ceil(chart_count / grid_width) chart_width = width / grid_width chart_height = height / grid_height for i, chart in enumerate(self._charts): x = (i % grid_width) * chart_width y = math.floor(i / grid_width) * chart_height group = ET.Element('g') group.set('transform', svg.translate(x, y)) chart = chart.to_svg_group(chart_width, chart_height) group.append(chart) grid_group.append(group) root_group.append(grid_group) svg_text = svg.stringify(root) close = True if path: try: if hasattr(path, 'write'): f = path close = False else: dirpath = os.path.dirname(path) if dirpath and not os.path.exists(dirpath): os.makedirs(dirpath) f = open(path, 'w') f.write(svg.HEADER) f.write(svg_text) finally: if close and f is not None: f.close() else: return IPythonSVG(svg_text)
def to_svg_group(self, width=None, height=None): """ Render this chart to an SVG group element. This can then be placed inside an :code:`<svg>` tag to make a complete SVG graphic. See :meth:`.Chart.to_svg` for arguments. """ width = width or theme.default_width height = height or theme.default_height if not self._layers: raise ValueError('You must add at least one series to the chart before rendering.') if isinstance(theme.margin, float): default_margin = width * theme.margin margin = Box( top=default_margin, right=default_margin, bottom=default_margin, left=default_margin ) elif isinstance(margin, int): margin = Box(margin, margin, margin, margin) elif not isinstance(margin, Box): margin = Box(*margin) # Root / background root_group = ET.Element('g') root_group.append(ET.Element('rect', x=six.text_type(0), y=six.text_type(0), width=six.text_type(width), height=six.text_type(height), fill=theme.background_color )) # Margins margin_group = ET.Element('g') margin_group.set('transform', svg.translate(margin.left, margin.top)) margin_width = width - (margin.left + margin.right) margin_height = height - (margin.top + margin.bottom) root_group.append(margin_group) # Header header_group = ET.Element('g') header_margin = 0 if self._title: label = ET.Element('text', x=six.text_type(0), y=six.text_type(0), fill=theme.title_color ) label.set('font-family', theme.title_font_family) label.set('font-size', six.text_type(theme.title_font_size)) label.text = six.text_type(self._title) header_group.append(label) header_margin += theme.title_font_char_height + theme.title_gap if not self._legend: if len(self._layers) > 1: self._legend = Legend() if self._legend: legend_group, legend_height = self._legend.to_svg(margin_width, self._layers) legend_group.set('transform', svg.translate(0, header_margin)) header_margin += legend_height header_group.append(legend_group) margin_group.append(header_group) # Body body_group = ET.Element('g') body_group.set('transform', svg.translate(0, header_margin)) body_width = margin_width body_height = margin_height - header_margin margin_group.append(body_group) # Axes x_scale, x_axis = self._validate_dimension(X) y_scale, y_axis = self._validate_dimension(Y) bottom_margin = x_axis.estimate_label_margin(x_scale, 'bottom') left_margin = y_axis.estimate_label_margin(y_scale, 'left') canvas_width = body_width - left_margin canvas_height = body_height - bottom_margin axes_group = ET.Element('g') axes_group.set('transform', svg.translate(left_margin, 0)) axes_group.append(x_axis.to_svg(canvas_width, canvas_height, x_scale, 'bottom')) axes_group.append(y_axis.to_svg(canvas_width, canvas_height, y_scale, 'left')) header_group.set('transform', svg.translate(left_margin, 0)) body_group.append(axes_group) # Series series_group = ET.Element('g') for series in self._layers: series_group.append(series.to_svg(canvas_width, canvas_height, x_scale, y_scale)) axes_group.append(series_group) return root_group
def to_svg(self, path=None, width=None, height=None): """ Render the grid to an SVG. The :code:`width` and :code:`height` arguments refer to the size of the entire grid. The size of individual charts will be inferred automatically. See :meth:`.Chart.to_svg` for arguments. """ if not width or not height: count = len(self._charts) columns = math.ceil(math.sqrt(count)) rows = math.ceil(count / columns) width = columns * theme.default_chart_width height = rows * theme.default_chart_height root = ET.Element('svg', width=six.text_type(width), height=six.text_type(height), version='1.1', xmlns='http://www.w3.org/2000/svg') # Root / background root_group = ET.Element('g') root_group.append( ET.Element('rect', x=six.text_type(0), y=six.text_type(0), width=six.text_type(width), height=six.text_type(height), fill=theme.background_color)) root.append(root_group) # Charts grid_group = ET.Element('g') chart_count = len(self._charts) grid_width = math.ceil(math.sqrt(chart_count)) grid_height = math.ceil(chart_count / grid_width) chart_width = width / grid_width chart_height = height / grid_height for i, chart in enumerate(self._charts): x = (i % grid_width) * chart_width y = math.floor(i / grid_width) * chart_height group = ET.Element('g') group.set('transform', svg.translate(x, y)) chart = chart.to_svg_group(chart_width, chart_height) group.append(chart) grid_group.append(group) root_group.append(grid_group) svg_text = svg.stringify(root) close = True if path: try: if hasattr(path, 'write'): f = path close = False else: dirpath = os.path.dirname(path) if dirpath and not os.path.exists(dirpath): os.makedirs(dirpath) f = open(path, 'w') f.write(svg.HEADER) f.write(svg_text) finally: if close and f is not None: f.close() else: return IPythonSVG(svg_text)
def to_svg(self, width, series_list): """ Render a legend series list and return it for embedding in an SVG. """ legend_group = ET.Element('g') bubble_width = theme.legend_bubble_size + theme.legend_bubble_offset rows = 1 indent = 0 for i, series in enumerate(series_list): text = six.text_type(series._name or 'Series %i' % i) text_width = (len(text) + 4) * theme.legend_font_char_width if indent + text_width + bubble_width > width: indent = 0 rows += 1 y = (rows - 1) * (theme.legend_font_char_height + theme.legend_gap) # Group item_group = ET.Element('g') item_group.set('transform', svg.translate(indent, y)) fill_color = getattr(series._shape, '_fill_color', None) stroke_color = getattr(series._shape, '_stroke_color', None) if callable(fill_color): # TODO fill_color = 'black' # Bubble bubble = ET.Element('rect', x=six.text_type(0), y=six.text_type(-theme.legend_font_char_height + theme.legend_bubble_offset), width=six.text_type(theme.legend_bubble_size), height=six.text_type(theme.legend_bubble_size) ) if fill_color: bubble.set('fill', fill_color) elif stroke_color: bubble.set('fill', stroke_color) item_group.append(bubble) # Label label = ET.Element('text', x=six.text_type(bubble_width), y=six.text_type(0), fill=theme.legend_color ) label.set('font-family', theme.legend_font_family) label.set('font-size', six.text_type(theme.legend_font_size)) label.text = text item_group.append(label) legend_group.append(item_group) indent += text_width + bubble_width height = rows * (theme.legend_font_char_height + theme.legend_gap) return (legend_group, height)
def to_svg(self, width, series_list): """ Render a legend series list and return it for embedding in an SVG. """ legend_group = ET.Element('g') bubble_width = theme.legend_bubble_size + theme.legend_bubble_offset rows = 1 indent = 0 for i, series in enumerate(series_list): text = six.text_type(series._name or 'Series %i' % i) text_width = (len(text) + 4) * theme.legend_font_char_width if indent + text_width + bubble_width > width: indent = 0 rows += 1 y = (rows - 1) * (theme.legend_font_char_height + theme.legend_gap) # Group item_group = ET.Element('g') item_group.set('transform', svg.translate(indent, y)) fill_color = getattr(series._shape, '_fill_color', None) stroke_color = getattr(series._shape, '_stroke_color', None) if callable(fill_color): # TODO fill_color = 'black' # Bubble bubble = ET.Element( 'rect', x=six.text_type(0), y=six.text_type(-theme.legend_font_char_height + theme.legend_bubble_offset), width=six.text_type(theme.legend_bubble_size), height=six.text_type(theme.legend_bubble_size)) if fill_color: bubble.set('fill', fill_color) elif stroke_color: bubble.set('fill', stroke_color) item_group.append(bubble) # Label label = ET.Element('text', x=six.text_type(bubble_width), y=six.text_type(0), fill=theme.legend_color) label.set('font-family', theme.legend_font_family) label.set('font-size', six.text_type(theme.legend_font_size)) label.text = text item_group.append(label) legend_group.append(item_group) indent += text_width + bubble_width height = rows * (theme.legend_font_char_height + theme.legend_gap) return (legend_group, height)