import matplotlib.pyplot as plt import matplotlib, io import plotly.express as px import plotly from datetime import datetime def generate_table(headers, data, title="", bg="skyblue", border="steelblue"): timestamp = datetime.now().strftime("%d/%m/%Y %H:%M:%S") font = {"family": "monospace", "weight": "normal", "size": 12} matplotlib.rc("font", **font) title_text = title footer_text = timestamp fig_background_color = bg fig_border = border column_headers = headers if data: cell_text = [] for row in data: cell_text.append([x for x in row]) else: cell_text = [["No Data"] + ["" for x in range(len(headers) - 1)]] # Create the figure. Setting a small pad on tight_layout # seems to better regulate white space. Sometimes experimenting # with an explicit figsize here can produce better outcome. dpi = 160 # image_height = (( 0.5 + ( 0.4125 * ( len(data) + 1) ) ) * dpi) image_height = 100 + (67 * (len(data) + 1)) image_width = 6 * dpi plt.figure( linewidth=2, edgecolor=fig_border, facecolor=fig_background_color, tight_layout={"pad": 1}, dpi=dpi, figsize=(image_width / dpi, image_height / dpi), ) # Add a table at the bottom of the axes the_table = plt.table( cellText=cell_text, colLabels=column_headers, loc="upper center" ) # Scaling is the only influence we have over top and bottom cell padding. # Make the rows taller (i.e., make cell y scale larger). the_table.scale(1, 2) # Hide axes ax = plt.gca() ax.get_xaxis().set_visible(False) ax.get_yaxis().set_visible(False) # Hide axes border plt.box(on=None) # Add title plt.suptitle(title_text, x=0.5, y=((image_height - 15) / image_height)) # Add footer plt.figtext( ((image_width - 15) / image_width), 1 - ((image_height - 15) / image_height), footer_text, horizontalalignment="right", size=12, weight="light", ) # Force the figure to update, so backends center objects correctly within the figure. # Without plt.draw() here, the title will center on the axes and not the figure. plt.draw() # Create image. plt.savefig ignores figure edge and face colors, so map them. image_buffer = io.BytesIO() plt.savefig(image_buffer, format="png") image_buffer.seek(0) return image_buffer def generate_chart(ticker, history): fig = px.line( history, x=history.index, y="Open", title="{} Stock Prices".format(ticker), labels={"Open": "Price Per Share"}, ) img_bytes = plotly.io.to_image(fig, format="png") return io.BytesIO(img_bytes)