def index(request): custom_style = Style(background='transparent', plot_background='transparent', legend_font_size=30) config = Config() config.fill = True pie_chart = pygal.Pie(legend_at_bottom=True, inner_radius=.6, style=custom_style, margin=0, width=400) #pie_chart.title = 'Graduation Rate' pie_chart.add('Graduated', grad_rate) pie_chart.add('Ejected', eject_rate) pie_chart.render_to_file('webapp/static/graduation_donut.svg') pending_applications = Client.objects.filter( client_phase='Applicant').count() sum_residents = Client.objects.filter(client_phase='Resident').count() applicants = Client.objects.filter( client_phase='Applicant').order_by('-id')[:6] sum_applicants = Client.objects.filter( client_phase='Applicant').count() - 6 return render( request, 'index.html', { 'pending_applications': pending_applications, 'applicants': applicants, 'sum_applicants': sum_applicants, 'sum_residents': sum_residents })
def __init__(self, mkchart, title='Default', show_legend=True, x_title=None, y_title=None, show_dots=False, range=None, xrange=None, show_x_guides=False, show_y_guides=False, fill=False, human_readable=True, style=DarkColorizedStyle): self.context = App.get_running_app().root.ids.main_ui style.background = 'transparent' style.plot_background = 'transparent' style.opacity = '.7' config = Config() config.show_legend = show_legend config.human_readable = human_readable config.fill = fill config.title = title config.x_title = x_title config.y_title = y_title config.show_dots = show_dots config.xrange = xrange config.range = range config.show_x_guides = show_x_guides config.show_y_guides = show_y_guides config.style = style self.config = config self.chart = mkchart(config) self.view = None
def test_custom_css_file(): from tempfile import NamedTemporaryFile custom_css = ''' {{ id }}text { fill: green; font-family: monospace; } {{ id }}.legends .legend text { font-size: {{ font_sizes.legend }}; } {{ id }}.axis { stroke: #666; } {{ id }}.axis text { font-size: {{ font_sizes.label }}; font-family: sans; stroke: none; } {{ id }}.axis.y text { text-anchor: end; } {{ id }}#tooltip text { font-size: {{ font_sizes.tooltip }}; } {{ id }}.dot { fill: yellow; } {{ id }}.color-0 { stroke: #ff1100; fill: #ff1100; } {{ id }}.color-1 { stroke: #ffee00; fill: #ffee00; } {{ id }}.color-2 { stroke: #66bb44; fill: #66bb44; } {{ id }}.color-3 { stroke: #88bbdd; fill: #88bbdd; } {{ id }}.color-4 { stroke: #0000ff; fill: #0000ff; } ''' custom_css_file = '/tmp/pygal_custom_style.css' with open(custom_css_file, 'w') as f: f.write(custom_css) config = Config(fill=True, interpolate='cubic') config.css.append(custom_css_file) chart = StackedLine(config) chart.add('A', [1, 3, 5, 16, 13, 3, 7]) chart.add('B', [5, 2, 3, 2, 5, 7, 17]) chart.add('C', [6, 10, 9, 7, 3, 1, 0]) chart.add('D', [2, 3, 5, 9, 12, 9, 5]) chart.add('E', [7, 4, 2, 1, 2, 10, 0]) return chart.render_response()
def node_apply_end(repo, node, duration=None, interactive=None, result=None, **kwargs): if environ.get('TERM_PROGRAM', None) != "iTerm.app" or not interactive: LOG.debug("skipping iTerm stats (wrong terminal)") return if not IMPORTS: LOG.error("failed to import dependencies of itermstats plugin") return css_file = NamedTemporaryFile(delete=False) css_file.write(".text-overlay { display: none; }") css_file.close() config = Config( height=150, style=STYLE, width=350, ) config.css.append(css_file.name) chart = Pie(config) chart.add('correct', result.correct) chart.add('fixed', result.fixed) chart.add('skipped', result.skipped) chart.add('failed', result.failed) png_data = cairosvg.svg2png(bytestring=chart.render()) png_data_b64 = b64encode(png_data) remove(css_file.name) print("\033]1337;File=inline=1:{}\007".format(png_data_b64))
def test_gradient_for(chart): config = Config() config.style = styles['dark'] config.defs.append(''' <linearGradient id="gradient-0" x1="0" x2="0" y1="0" y2="1"> <stop offset="0%" stop-color="#ff5995" /> <stop offset="100%" stop-color="#feed6c" /> </linearGradient> ''') config.defs.append(''' <linearGradient id="gradient-1" x1="0" x2="0" y1="0" y2="1"> <stop offset="0%" stop-color="#b6e354" /> <stop offset="100%" stop-color="#8cedff" /> </linearGradient> ''') config.css.append('''inline: .color-0 { fill: url(#gradient-0) !important; stroke: url(#gradient-0) !important; }''') config.css.append('''inline: .color-1 { fill: url(#gradient-1) !important; stroke: url(#gradient-1) !important; }''') chart = CHARTS_BY_NAME[chart](config) chart.add('1', [1, 3, 12, 3, 4, None, 9]) chart.add('2', [7, -4, 10, None, 8, 3, 1]) chart.x_labels = ('a', 'b', 'c', 'd', 'e', 'f', 'g') chart.legend_at_bottom = True chart.interpolate = 'cubic' return chart.render_response()
def line_config(size): if size == 'small': config = Config() custom_style = get_custom_style(size) config.style = custom_style config.x_label_rotation = 40 config.show_minor_x_labels = False config.truncate_legend = -1 else: config = Config() custom_style = get_custom_style(size) config.style = custom_style config.x_label_rotation = 20 config.show_minor_x_labels = False config.truncate_legend = -1 return config
def test_config_behaviours(): """Test that all different way to set config produce same results""" line1 = Line() line1.show_legend = False line1.fill = True line1.pretty_print = True line1.no_prefix = True line1.x_labels = ['a', 'b', 'c'] line1.add('_', [1, 2, 3]) l1 = line1.render() q = line1.render_pyquery() assert len(q(".axis.x")) == 1 assert len(q(".axis.y")) == 1 assert len(q(".plot .series path")) == 1 assert len(q(".legend")) == 0 assert len(q(".x.axis .guides")) == 3 assert len(q(".y.axis .guides")) == 11 assert len(q(".dots")) == 3 assert q(".axis.x text").map(texts) == ['a', 'b', 'c'] line2 = Line( show_legend=False, fill=True, pretty_print=True, no_prefix=True, x_labels=['a', 'b', 'c']) line2.add('_', [1, 2, 3]) l2 = line2.render() assert l1 == l2 class LineConfig(Config): show_legend = False fill = True pretty_print = True no_prefix = True x_labels = ['a', 'b', 'c'] line3 = Line(LineConfig) line3.add('_', [1, 2, 3]) l3 = line3.render() assert l1 == l3 line4 = Line(LineConfig()) line4.add('_', [1, 2, 3]) l4 = line4.render() assert l1 == l4 line_config = Config() line_config.show_legend = False line_config.fill = True line_config.pretty_print = True line_config.no_prefix = True line_config.x_labels = ['a', 'b', 'c'] line5 = Line(line_config) line5.add('_', [1, 2, 3]) l5 = line5.render() assert l1 == l5
def init_bar_graph(): config = Config() config.x_label_rotation = 45 config.show_legend = True config.title = 'Most-Starred Top-5 Programming Languages\'s Projects on Github' config.y_title = 'Stars' chart = Bar(config) return chart
def test_inline_css(Chart): css = "{{ id }}text { fill: #bedead; }\n" config = Config() config.css.append('inline:' + css) chart = Chart(config) chart.add('/', [10, 1, 5]) svg = chart.render().decode('utf-8') assert '#bedead' in svg
def define_config(): """Defines some configuration options for the pygal plot.""" config = Config() config.show_legend = False config.legend_at_bottom = True config.human_readable = True config.print_values = True config.show_x_labels = True config.show_y_labels = True config.fill = True return config
def test_css(Chart): css = "{{ id }}text { fill: #bedead; }\n" css_file = '/tmp/pygal_custom_style-%s.css' % uuid4() with open(css_file, 'w') as f: f.write(css) config = Config() config.css.append(css_file) chart = Chart(config) chart.add('/', [10, 1, 5]) svg = chart.render().decode('utf-8') assert '#bedead' in svg
def test_css(Chart): css = "{{ id }}text { fill: #bedead; }\n" with NamedTemporaryFile('w') as f: f.write(css) f.flush() config = Config() config.css.append(f.name) chart = Chart(config) chart.add('/', [10, 1, 5]) svg = chart.render().decode('utf-8') assert '#bedead' in svg
def genfoodchart(start, end): '''Generate food chart with Pygal''' now = datetime.datetime.now().strftime("%Y-%m-%d") goodcount = session.query(Food) \ .filter_by(user_id=current_user.id) \ .filter(Food.food_date.between(start, end)).join(Ranks) \ .filter_by(rank=1).add_columns(Ranks.rank).count() okaycount = session.query(Food) \ .filter_by(user_id=current_user.id) \ .filter(Food.food_date.between(start, end)).join(Ranks) \ .filter_by(rank=2).add_columns(Ranks.rank).count() badcount = session.query(Food) \ .filter_by(user_id=current_user.id) \ .filter(Food.food_date.between(start, end)).join(Ranks) \ .filter_by(rank=3).add_columns(Ranks.rank).count() custom_style = Style( background='transparent', value_font_size=24, title_font_size=36, margin=1, plot_background='transparent', foreground='#53E89B', foreground_strong='#53A0E8', foreground_subtle='#630C0D', opacity='.6', opacity_hover='.9', transition='400ms ease-in', colors=('#5cb85c', '#f0ad4e', '#d9534f')) config = Config() config.show_legend = True config.legend_at_bottom=True config.legend_at_bottom_columns=1 config.legend_box_size=10 config.human_readable = True config.fill = True config.style=custom_style config.print_labels=True config.print_values=True config.no_data_text='Need to add some food!' pie_chart = pygal.Pie(config) pie_chart.title = "Current Food Stats" pie_chart.add('Good', goodcount) pie_chart.add('Okay', okaycount) pie_chart.add('Bad', badcount) chart = pie_chart.render(is_unicode=True) return chart
def genweightchart(): '''Generate weight chart with Pygal''' weighthistory = session.query(Weight) \ .filter_by(user_id=current_user.id) \ .order_by(Weight.id.desc()) \ .all() maxweight = session.query(Weight) \ .filter_by(user_id=current_user.id) \ .order_by(Weight.id.desc()) \ .first() if maxweight is None: maxrange = 100 else: maxrange = (int(maxweight.weight) + 50) custom_style = Style( background='transparent', value_font_size=24, title_font_size=36, margin=1, plot_background='transparent', foreground='#53E89B', foreground_strong='#53A0E8', foreground_subtle='#630C0D', opacity='.6', opacity_hover='.9', transition='400ms ease-in', colors=('#5cb85c', '#f0ad4e', '#d9534f')) config = Config() config.show_legend = True config.legend_at_bottom=True config.y_labels = range(0, maxrange, 25) config.human_readable = True config.fill = True config.style=custom_style config.print_labels=True config.no_data_text='Add weight measurements!' wlist = [] for entry in enumerate(weighthistory): wlist.append(entry[1].weight) line_chart = pygal.Line(config) line_chart.title = "Weight History" line_chart.add('Values', wlist) chart = line_chart.render(is_unicode=True) return chart
def make_image(data, filepath, title, labels, major_labels): custom_style = Style(background='#fff', plot_background='transparent', title_font_size=14, guide_stroke_dasharray='1,0', major_guide_stroke_dasharray='1,0', foreground='rgba(0, 0, 0, .87)', foreground_strong='rgba(0, 0, 0, .87)', foreground_subtle='rgba(0, 0, 0, .87)', stroke_opacity='1', stroke_opacity_hover='1', stroke_width=10, stroke_width_hover=10, opacity='1', opacity_hover='1', colors=('#C5D4B5BB', '#3D7930')) print(custom_style.to_dict()) r = get_range(data) config = Config() config.interpolate = 'cubic' config.style = custom_style config.width = 400 config.height = 225 config.explicit_size = True config.margin_left = 0 config.margin_right = 0 config.margin_top = 10 config.margin_bottom = 30 config.show_minor_x_labels = False config.truncate_label = -1 config.show_legend = False config.include_x_axis = True config.range = r config.show_dots = False chart = pygal.Line(config) chart.title = ("Throughput (%s, Mb/s)" % (title)) chart.x_labels = labels chart.x_labels_major = major_labels chart.y_labels = [ x for x in range(0, r[1] + 1, 100 if (r[1] > 550) else 50) ] chart.add(None, data, fill=True) chart.add(None, data) #with open(filepath, 'w') as output: # output.write(chart.render()) chart.render_to_png(filepath)
def drawPercentile(percentile, x_label, path, showPlot): config = Config() config.show_legend = False # config.range = (0,1) dark_lighten_style = LightenStyle('#336676', base_style=LightColorizedStyle) dark_lighten_style.background = '#ffffff' dark_lighten_style.opacity = 1 dark_lighten_style.font_family = "DejaVu Sans" dark_lighten_style.legend_font_family = "DejaVu Sans" dark_lighten_style.major_label_font_family = "DejaVu Sans" dark_lighten_style.title_font_family = "DejaVu Sans" dark_lighten_style.tooltip_font_family = "DejaVu Sans" dark_lighten_style.label_font_family = "DejaVu Sans" dark_lighten_style.label_font_size = 40 dark_lighten_style.major_label_font_size = 40 # print(dark_lighten_style.to_dict()) bar_chart = pygal.Bar(config, width=1600, height=1000, rounded_bars=6, style=dark_lighten_style, margin=0) bar_chart.x_labels = x_label #['Concentration', 'Stability', 'Focus Continuity'] #map(str, range(2002, 2013)) bar_chart.y_labels = (0, 0.2, 0.4, 0.6, 0.8, 1) # bar_chart.add('Percentile0', rd1.percentile[0]) # bar_chart.add('Percentile1', rd1.percentile[1]) # bar_chart.add('Percentile2', rd1.percentile[2]) bar_chart.add('Percentile', [{ 'value': 1 - percentile[0], 'color': selectColor(percentile[0]) }, { 'value': 1 - percentile[1], 'color': selectColor(percentile[1]) }, { 'value': 1 - percentile[2], 'color': selectColor(percentile[2]) }]) if showPlot: display({'image/svg+xml': bar_chart.render()}, raw=True, dpi=200) bar_chart.render_to_png(path + 'Percentile.png', fill=True, dpi=200)
def __init__(self, path='/tmp/graph.png', locale={}, extra_css=[]): self.style = None self.chart = None self.path = path self.locale = locale self.config = Config() self.config.no_data_text = 'No result found' self.config.no_data_font_size = 13 self.config.x_label_rotation = 45 self.config.truncate_legend = 255 self.config.truncate_label = 255 for css in extra_css: self.config.css.append(css) if 'STR_NODATA' in self.locale: self.config.no_data_text = self.locale['STR_NODATA']
def PygalConfigFile(): config = Config() config.human_readable = True config.height = 250 config.width = 700 config.style = NeonStyle config.show_minor_y_labels = True config.x_label_rotation = 25 config.value_font_size = 8 config.title_font_size = 8 config.legend_font_size = 8 config.legend_box_size = 12 config.label_font_size = 6 return (config)
def get_price_chart(self, stat): config = Config() config.show_legend = False config.human_readable = True config.x_label_rotation = 90 config.pretty_print = True config.min_scale = 12 config.height = 480 price_chart = pygal.Line(config) price_chart.title = '售价走势图' price_chart.x_labels = map( lambda x: x.date_created.strftime("%Y-%m-%d"), stat) price_chart.add('价格', [row.price for row in stat]) return price_chart.render_data_uri()
def PygalConfigFileBlue(): configB = Config() configB.human_readable = True configB.height = 250 configB.width = 700 configB.style = NeonStyle configB.show_minor_y_labels = True configB.x_label_rotation = 25 configB.value_font_size = 8 configB.title_font_size = 8 configB.legend_font_size = 8 configB.legend_box_size = 12 configB.label_font_size = 6 configB.colors = ['#000099', '#009999'] return (configB)
def define_config(): """Defines some configuration settings for the pygal plot.""" config = Config() config.show_legend = False config.human_readable = True config.fill = False config.height = 1000 config.width = 2000 config.x_label_rotation = 300 config.show_legend = False config.x_labels_major_every = 200 # 200 config.show_minor_x_labels = False config.show_dots = False config.fill = True config.logarithmic = False return config
def make_buildmd(allmetadata, fullreport, reportFile, metadataFolder): """ Creates several plots from some metadata and a report.md markdown file embedding the plots. """ allmetadata = pd.DataFrame(allmetadata) import pygal from pygal.style import CleanStyle from pygal.style import Style mystyle = CleanStyle(font_family="sans-serif") # Pygal chart configuration from pygal import Config config = Config() config.legend_at_bottom = True config.legend_at_bottom_columns = 3 config.print_values = True config.style = mystyle #config.width=500 #config.height=300 config.font_family = "Arial" # Donut chart for author genders genders = dict(Counter(allmetadata.loc[:, "au-gender"])) chart = pygal.Pie(config, title="Number of novels per author gender", inner_radius=.60, font_family="sans-serif") chart.add("male", genders["M"]) chart.add("female", genders["F"]) chart.add("other", 0) chart.render_to_file(join(metadataFolder, "au-genders.svg")) # Bar chart for time periods timeslots = dict(Counter(allmetadata.loc[:, "time-slot"])) chart = pygal.Bar(config, range=(0, 30), title="Number of novels per 20-year period", font_family="sans-serif", legend_at_bottom_columns=4) chart.add("1840-1859", timeslots["T1"]) chart.add("1860-1879", timeslots["T2"]) chart.add("1880-1899", timeslots["T3"]) chart.add("1900-1919", timeslots["T4"]) chart.render_to_file(join(metadataFolder, "timeslots.svg")) # Save report.md with embedded charts reportmd = "## Corpus composition for ELTeC-fra\n\n<img src=\"/Metadata/au-genders.svg\">\n<img src=\"/Metadata/timeslots.svg\">" with open(reportFile, "w", encoding="utf8") as outfile: outfile.write(reportmd)
def draw_line(valxy): import pygal from pygal import Config from pygal.style import Style config = Config() custom_style = Style(background='white', foreground='#000', foreground_strong='#000', foreground_subtle='#000', opacity='.9', opacity_hover='.6', plot_background='#fff', transition='100ms', label_font_size=12, major_label_font_size=12, value_font_family='Arial', font_family='Arial', major_label_font_family='Sans', colors=('#3333CC', '#3333CC', '#3333CC', '#3333CC'), guide_stroke_dasharray='2,7', major_guide_stroke_dasharray='2,7') config.margin_left = 0 config.margin_bottom = 0 config.width = 350 config.height = 350 config.x_title = "Angle, degrees" config.y_title = "Overlaps, %" config.explicit_size = True config.show_x_guides = False config.show_y_guides = True xy_chart = pygal.XY(config, show_legend=False, dots_size=3, style=custom_style) #interpolate='quadratic', #xy_chart.title = "Overlaps in oscillation range" xy_chart.add('', valxy) #xy_chart.y_labels = [int(phibg), int(phend)] # col=20 # stp=1 # for val in range(int(phibg), int(phend), stp): # xy_chart.add("", [{'value': val, 'color': 'rgb(%s, 0, 0)' % (col)}], # stroke_style={'width': 1, 'linejoin': 'round', 'linecap': 'round', 'linejoin': 'round'}) # col=col+stp return xy_chart.render(is_unicode=True)
def __init__(self): super(DBSize, self).__init__('total-0.png') self.tables_size = {} self.total_size = {} self.lines_count_size = {} self.mean_lines_size = {} self.pygal_config = Config() self.pygal_config.human_readable = True self.pygal_config.legend_box_size = 24 self.pygal_config.show_legend = True self.pygal_config.show_values = True self.pygal_config.style = SolidColorStyle self.pygal_config.style.colors = ['#ff3000', '#ff8900', '#ffe500', \ '#b7ff3f', '#66ff90', '#18ffdd', '#00a4ff', '#0040ff', '#0000ec', '#00007f'] self.pygal_config.style.opacity = '.9' self.pygal_config.style.opacity_hover = '.4' self.pygal_config.style.transition = '100ms ease-in' self.pygal_config.truncate_legend = 9999999
def visualization(self, img, prediction): """Plot list of predictions on barchart Args: img (np.array): image as array prediction (list): array of emotions probabilities Returns: list: barchart as array """ config = Config() config.show_legend = False config.print_labels = True config.show_y_labels = False config.show_y_guides = False config.show_x_guides = False config.max_scale = 12 config.width = img.width config.height = img.height custom_style = Style(background='transparent', plot_background='transparent', foreground='transparent', colors=('#19d5ff', '#19d5ff', '#19d5ff', '#19d5ff', '#19d5ff'), opacity='.8', value_label_font_size=img.width // 30, value__label_font_family='monospace') labels = ['Angry', 'Fear', 'Happy', 'Sad', 'Surprise', 'Neutral'] data = list(zip(prediction, labels)) data_dict = [] for val, label in data: data_dict.append({'value': val, 'label': label}) bar_chart = pygal.HorizontalBar(config=config, style=custom_style) bar_chart.add('', data_dict) imgByteArr = BytesIO() bar_chart.render_to_png(imgByteArr) #pygal, no comments #bar = Image.open('./tmp.png') bar = Image.open(imgByteArr) return bar
def __init__(self, path='/tmp/graph.png', locale=None, extra_css=None): # Mutable list extra_css used as default argument to a method or function extra_css = extra_css or [] self.style = None self.chart = None self.path = path # Mutable dict locale used as default argument to a method or function self.locale = locale or {} self.locale = locale self.config = Config() self.config.no_data_text = 'No result found' self.config.no_data_font_size = 13 self.config.x_label_rotation = 45 self.config.truncate_legend = 255 self.config.truncate_label = 255 for css in extra_css: self.config.css.append(css) if 'STR_NODATA' in self.locale: self.config.no_data_text = self.locale['STR_NODATA']
def languages_draw(prefix, file_name, dir_name, time_title, names, counts): chart = pygal.Bar(interpolate='cubic', width=1000) config = Config() config.show_legend = False config.human_readable = True config.fill = True config.style = DarkColorizedStyle config.label_font_size = 36 config.x_label_rotation = 45 chart.config = config chart.title = file_name + " [" + time_title + "]" chart.x_labels = names chart.add(prefix, counts) save_name = os.path.join(dir_name, file_name + ".svg") chart.render_to_file(save_name)
def test_css(Chart): """Test css file option""" css = "{{ id }}text { fill: #bedead; }\n" with NamedTemporaryFile('w') as f: f.write(css) f.flush() config = Config() config.css.append('file://' + f.name) chart = Chart(config) chart.add('/', [10, 1, 5]) svg = chart.render().decode('utf-8') assert '#bedead' in svg chart = Chart(css=(_ellipsis, 'file://' + f.name)) chart.add('/', [10, 1, 5]) svg = chart.render().decode('utf-8') assert '#bedead' in svg
def charts(): try: dateline = pygal.Line() config = Config() config.box_mode = True dateline = pygal.Line(config) dateline.title = 'Remaining Stories/Bugs' dateline.x_labels = ['21 May 2018','28 May 2018','4 June 2018','11 June 2018','18 June 2018','25 June 2018','2 July 2018','9 July 2018','16 July 2018','23 July 2018','30 July 2018','6 August 2018','13 August 2018','20 August 2018','27 August 2018','3 September 2018','10 September 2018'] dateline.add('Glacier', [None, None, None, None, None, 0, 7, 1, 1, 16, 17, 15, 16, 14, 15, 16]) dateline.add('APS', [None, None, None, None, None, None, None, 0, 60, 128, 128, 117, 120, 121, 116, 118]) dateline.add('AWS Migration', [9, 9, 9, 7, 9, 13, 9, 27, 81, 97, 96, 93, 85, 94, 86, 90, 79]) dateline.add('DBP Builder App', [None, None, None, None, None, None, None, 0, 4, 14, 16, 16, 26, 41, 46, 46, 30]) dateline.add('Workspace', [None, None, None, None, None, None, None, None, 0, 69, 62, 62, 61, 61, 55, 60, 64]) graph_data = dateline.render_data_uri() return render_template("dateline.html",graph_data=graph_data) except Exception as e: return (str(e))
class Chart(object): Y_AXIS_MULTIPLIER = 1.33 # The default style settings for a bart chart or histogram BAR_CONFIG = Config() BAR_CONFIG.legend_box_size = 15 BAR_CONFIG.width = 1000 BAR_CONFIG.legend_at_bottom = True BAR_CONFIG.truncate_legend = -1 BAR_CONFIG.max_scale = 7 BAR_CONFIG.print_values = True BAR_CONFIG.print_values_position = 'top' BAR_CONFIG.style = DefaultStyle(background='#fff', title_font_size=20) # Shared init stuff among all chart types def __init__(self, title): self.chart.title = title self.chart.range = (0, self.max_y_axis) # Output a chart to png def render_png(self, chart_name): self.chart.render_to_png('app/static/charts/{}.png'.format(chart_name))