randyzwitch / streamlit-folium

Streamlit Component for rendering Folium maps
https://folium.streamlit.app/
MIT License
468 stars 176 forks source link

Option to pre-render #194

Closed this-josh closed 3 months ago

this-josh commented 3 months ago

I have a streamlit application where the user selects an option and then one of 40 folium figures is shown, a bit like

all_maps = {} # define them here
chosen_map = st.select_slider()
st_folium(all_maps[chosen_map])

Rendering each map is slow, it takes around 4 seconds and is done here https://github.com/randyzwitch/streamlit-folium/blob/b231927bebbd528ef188d8a91bc4e9585a089980/streamlit_folium/__init__.py#L278

I've found it is possible to render a map in my code and then pass it pre-rendered to streamlit_folium, with the above rendering commented out.

I'd like to add an arg pre_rendered which if true skips the rendering on line 278 I can submit a PR if you're interested in this

It would permit something like

@st.cache_resource
def load_maps():
    all_maps = {}
    return {key: value.render() for key, value in all_maps.items()}

all_maps = load_maps()
st_folium(all_maps[chosen_map],pre_rendered=True)

Which is my scenario greatly improves performance

blackary commented 3 months ago

That sounds like a great feature -- if you'd be willing to put in a PR, that would be excellent

randyzwitch commented 3 months ago

Like @blackary, this sounds reasonable...just so I understand, how does this speed up your app? If you have 40 maps, you're rending all 40 in the background first, so when the user chooses it will already be rendered? Or does this prevent re-rendering?

this-josh commented 3 months ago

Hi @randyzwitch, it speeds up the app in both ways

  1. All rendering can be done the first time the app is launched so subsequent usage doesn't require a render - the rendered maps are stored in memory as a dictionary object
  2. st_folium doesn't then re-render

This is effectively caching the rendering.

I'll open a PR shortly.

For my application I'm also comparing this approach with rendering all the maps as HTML and including them as an iframe. I believe this also minimises backend compute as the maps are rendered in the users browser. Although as my maps are 4-8MB each it's still not as performant as I'd like

BastienGauthier commented 3 months ago

I understand that this solution could also help to depict maps that have been pre-rendered and saved in a pickle file for exemple. Is it correct ?

this-josh commented 3 months ago

@BastienGauthier Yep that's one scenario it can help with.