def plot(self, tree, vis): if len(vis.data) == 0: return tree margins = calculate_margins(vis) size = calculate_chart_size(vis, margins) y_scale = calculate_y_scale(vis.data, vis.style.y_axis_tick_number) inner_tree = add_tag(tree, 'svg', attributes={ 'viewBox': f'0 0 {size[0]}, {size[1]}', 'x': str(margins[0]), 'y': str(margins[1]), 'width': str(size[0]), 'height': str(size[1]) }) if isinstance(vis.data, DataSet): for i, data in enumerate(vis.data): self._plot_line(vis, data, y_scale[-1], size[0], size[1], vis.style.data_colours[i%len(data)], inner_tree) elif isinstance(vis.data, Data): self._plot_line(vis, vis.data, y_scale[-1], size[0], size[1], vis.style.data_colour, inner_tree) else: raise Exception if vis.data.labels: for i, label in enumerate(vis.data.labels): if not i % vis.style.x_axis_interval: width_per_node = size[0] / (len(vis.data)-1) x = margins[0] + i * width_per_node label_y = margins[1] + size[1] + vis.style.text_styles["x_axis"].size/2 add_text(tree, (x, label_y), str(label), vis.style.text_styles['x_axis']) return tree
def plot(self, tree, vis): margins = calculate_margins(vis) size = calculate_chart_size(vis, margins) size = (size[0] + 1, size[1] + 1) y_scale = calculate_y_scale(vis.data, vis.style.y_axis_tick_number) inner_tree = add_tag(tree, 'svg', attributes={ 'viewBox': f'0 0 {size[0]}, {size[1]}', 'x': str(margins[0] - 1), 'y': str(margins[1]), 'width': str(size[0]), 'height': str(size[1]) }) for i in range(1, len(y_scale)): y_pos = size[1] - i * size[1] / (len(y_scale) - 1) if vis.style.show_grid_lines: add_tag(inner_tree, 'line', attributes={ 'x1': '0', 'x2': str(size[0]), 'y1': str(y_pos), 'y2': str(y_pos), 'class': 'grid_lines' }) # Axes add_tag(inner_tree, 'line', attributes={ 'x1': str(0), 'x2': str(0), 'y1': str(size[1]), 'y2': str(0), 'class': 'axis' }) add_tag(inner_tree, 'line', attributes={ 'x1': str(0), 'x2': str(size[0]), 'y1': str(size[1]), 'y2': str(size[1]), 'class': 'axis' }) for i, label in enumerate(y_scale): y_pos = margins[0] + size[1] - i * size[1] / (len(y_scale) - 1) add_text(tree, (margins[0] - 5, y_pos), str(label), vis.style.text_styles['y_axis'])
def plot(self, tree, vis): if len(vis.data) == 0: return tree margins = calculate_margins(vis) size = calculate_chart_size(vis, margins) y_scale = calculate_y_scale(vis.data, vis.style.y_axis_tick_number) inner_tree = add_tag(tree, 'svg', attributes={ 'viewBox': f'0 0 {size[0]}, {size[1]}', 'x': str(margins[0]), 'y': str(margins[1]), 'width': str(size[0]), 'height': str(size[1]) }) width_per_bar = size[0] / len(vis.data) bar_width = width_per_bar * vis.style.bar_width for i, item in enumerate(vis.data): height = (item / y_scale[-1]) * size[1] centre_x = i * width_per_bar + width_per_bar/2 add_tag(inner_tree, 'rect', attributes={ 'width': str(bar_width), 'height': str(height), 'x': str(centre_x - bar_width/2), 'y': str(size[1] - height), 'class': 'data_colour' }) if vis.style.show_values == 'all' or (vis.style.show_values == 'limits' and (item == vis.data.max or item == vis.data.min)): label_y = size[1] - height - vis.style.text_styles["value"].size/2 add_text(tree, (margins[0] + centre_x, margins[1] + label_y), str(item), vis.style.text_styles['value']) if vis.data.labels: if not i % vis.style.x_axis_interval: label_y = size[1] + vis.style.text_styles["x_axis"].size/2 add_text(tree, (margins[0] + centre_x, margins[1] + label_y), str(vis.data.labels[i]), vis.style.text_styles['x_axis']) return tree
def _plot_line(self, vis, data, max_value, plot_width, plot_height, colour, tree): width_per_node = plot_width / (len(data)-1) points = [] for i, item in enumerate(data): x = i * width_per_node y = plot_height - (item / max_value) * plot_height points.append((x, y)) if vis.style.show_values == 'all' or (vis.style.show_values == 'limits' and (item == data.max or item == data.min)): label_y = y - vis.style.text_styles["value"].size/2 add_text(tree, (x, label_y), str(item), vis.style.text_styles['value']) add_tag(tree, 'polyline', attributes={ 'points': ' '.join([f'{str(point[0])}, {str(point[1])}' for point in points]), 'fill': 'none', 'stroke': colour, 'class': 'line_chart_data_line' })
def plot(self, tree, vis): x = self.pos[0] + margins[0] y = self.pos[1] + margins[1] add_text(tree, (x, y), self.text, self.style)
def plot(self, tree, vis): if len(vis.data) == 0: return tree # Left, Right plot_x = (vis.style.width * vis.style.margin[0], vis.style.width * vis.style.margin[2]) # Up, Down plot_y = (vis.style.height * vis.style.margin[1], vis.style.height * vis.style.margin[3]) plot_width = vis.style.width - plot_x[0] - plot_x[1] plot_height = vis.style.height - plot_y[0] - plot_y[1] # Plot pie angles = self._calculate_angles(vis.data) centre = (plot_x[0] + plot_width / 2, plot_y[0] + plot_height / 2) radius = min(plot_width, plot_height) / 2 * 0.9 value_radius = radius * vis.style.pie_value_radius # SVG paths can't draw full circle. Backtrack to a circle if we # get too close if len(vis.data) == 1 or max(angles) > 1.99 * math.pi: add_tag(tree, 'circle', attributes={ 'cx': str(centre[0]), 'cy': str(centre[1]), 'r': str(radius), 'fill': vis.style.data_colours[0] }) else: x = centre[0] y = centre[1] - radius angle = 0 for i, item in enumerate(vis.data): (old_x, old_y) = (x, y) angle += angles[i] x = centre[0] + radius * math.sin(angle) y = centre[1] + -(radius * math.cos(angle)) big = 1 if angles[i] > math.pi else 0 add_tag( tree, 'path', attributes={ 'd': f'M{centre[0]},{centre[1]} L{old_x},{old_y} A{radius},{radius} 0 {big},1 {x},{y} Z', 'fill': vis.style.data_colours[(i % len(vis.data)) % len(vis.style.data_colours)] }, text=str((angles[i], angle))) angle = 0 for i, item in enumerate(vis.data): angle += angles[i] / 2 x = centre[0] + value_radius * math.sin(angle) y = centre[1] + -(value_radius * math.cos(angle)) css_class = '_' if angle < math.pi / 2 or angle > math.pi * 6 / 4: css_class += 'upper' else: css_class += 'lower' if angle < math.pi: css_class += '_left' else: css_class += '_right' add_text(tree, (x, y), str(item), vis.style.text_styles['circle_value'], css_class) angle += angles[i] / 2 add_tag(tree, 'circle', attributes={ 'cx': str(centre[0]), 'cy': str(centre[1]), 'r': str(radius * vis.style.pie_inner_radius), 'fill': vis.style.background_colour }) return tree