Dear community,
In my app I’d like to export a pane of plots to png. To expose the save() functionality to the user, I’m using a pn.widgets.FileDownload widget with a callback that saves my pane to a BytesIO object.
Only drawback is that there is no file extension and it always saves to html.
The reason I’m using this FileDownload is because it gives me a directory explorer when saving.
Any suggestions to get the desired functionality?
import param
import panel as pn
pn.extension()
import pandas as pd
import hvplot.pandas
from io import BytesIO
class Explorer(param.Parameterized):
df = pd.DataFrame(range(10))
def __init__(self,**params):
super().__init__(**params)
self.plot = pn.Column(self.df.hvplot(),self.df.hvplot())
self.save_to_png = pn.widgets.FileDownload(
filename="timeseries.png", label="Download .png", button_type="success", callback=self.download_column
)
self.layout = pn.Row(self.plot,self.save_to_png)
def download_column(self):
self.save_to_png.loading=True
height=800
width=int(.75*height)
pane = self.plot
b = BytesIO()
pane.save(b)
b.seek(0)
self.save_to_png.loading=False
return b
e=Explorer()
e.layout
A workaround is to save to a file, read it back and then download. Here is an example using a TemporaryDirectory.
Please note you will have to have a browser (firefox or chrome) in your path and its driver (gecko or chromium) installed and to be available in your PATH.
import panel as pn
import param
pn.extension()
import pathlib
import tempfile
from io import BytesIO
import hvplot.pandas
import pandas as pd
pn.extension(sizing_mode="stretch_width")
ACCENT_COLOR = "#0072B5"
class Explorer(param.Parameterized):
df = pd.DataFrame({"y": range(10)})
def __init__(self,**params):
super().__init__(**params)
self.plot = pn.Column(self.df.hvplot().opts(color=ACCENT_COLOR, line_width=6, responsive=True),self.df.hvplot().opts(color=ACCENT_COLOR, line_width=6, responsive=True))
self.save_to_png = pn.widgets.FileDownload(
filename="timeseries.png", label="Download .png", button_type="primary", callback=self.download_column
)
def download_column(self):
self.save_to_png.loading=True
pane = self.plot
with tempfile.TemporaryDirectory() as tmpdir:
file = pathlib.Path(tmpdir) / "tmp.png"
pane.save(str(file))
with open(file, 'rb') as fh:
b = BytesIO(fh.read())
b.seek(0)
self.save_to_png.loading=False
return b
explorer=Explorer()
pn.template.FastListTemplate(
site="Awesome Panel", title="Application with .png download",
sidebar=[explorer.save_to_png], main=[explorer.plot],
accent_base_color=ACCENT_COLOR, header_background=ACCENT_COLOR
).servable()
I’m not sure if Edge will work. It would be great if we could support Kaleido, an easily embeddable offscreen renderer, but that would take some work to bring in to Bokeh.
Thanks for your reply. Edge doesn’t work at this program. I don’t like paper based report such as pdf and word to share my idea. But my company requests to me about this type. in the near feature , I think this mind-set will change soon to web based report.
But now , I want to have this method to change from panel to pdf. I wait this time.
No, but you need to install Chromium, which could face the same restrictions. That said, Chromium may be shipped in a way that isn’t runnable as an end-user browser application; not sure.
Thank you for your advice. I confirmed my company rule. But our company safe list doesn’t have Chromium. So I tried other way to save our panel image. I think hv.save is similar to what I want. but I met another problem. option can’t render hv.save. I make new topic. link is below.