To expand on that: you can send the data that goes into making the plots, but you can also send the plots themselves as Media objects.
It’s often a good idea to use the client-side Plotly library (not least because it gives you Python event handlers so your plot can interact with the rest of your app). But you can use other plotting libraries too, on the server-side…
Matplotlib, Seaborn, Pandas
If you’re using Matplotlib, Seaborn or Pandas, you can create Media objects containing images by calling anvil.mpl_util.plot_image()
(you don’t need to call plt.show()
)
You can return this to the client-side, then use it as the source of an Image component, download it from a Link, or save it to a Data Table.
img = anvil.server.call('make_plot')
self.image_1.source = img
self.download_lnk.url = img
Bokeh, Altair, Pygal
Bokeh, Altair and Pygal all write HTML or SVG plots to a file. You can create a Media object from that file, return it to the client, then embed it in an IFrame component. This gives you a dynamic plot embedded in your app!
Clone link for IFrame component:
https://anvil.works/build#clone:CFRUWSM6PQ6JUUXH=SX4SACDSXBB4UOIVEVPWXH55
Here’s a Bokeh example. Creating a plot in a Server Module:
import anvil.server
import anvil.media
import numpy as np
from bokeh.plotting import figure, output_file, show
@anvil.server.callable
def make_plot():
# Point Bokeh at a file
output_file("/tmp/bokeh.html")
# Make a nice wiggle
x = np.arange(0.0, 5.0, 0.02)
y = np.exp(-x) * np.cos(2*np.pi*x)
# Plot it in the usual Bokeh way
p = figure(width=600, height=300)
p.line(x, y)
# Save the plot
show(p)
# Return this plot as HTML in a Media object
return anvil.media.from_file('/tmp/bokeh.html', 'text/html')
Include the IFrame component as a Dependency, drag-and-drop it onto a Form, then do this:
def __init__(self, **properties):
# Set Form properties and Data Bindings.
self.init_components(**properties)
# Any code you write here will run when the form opens.
media_obj = anvil.server.call('make_plot')
self.i_frame_1.url = media_obj.get_url(True)