jupyter-widgets / ipyleaflet

A Jupyter - Leaflet.js bridge
https://ipyleaflet.readthedocs.io
MIT License
1.49k stars 363 forks source link

Asyncio error in fit_bounds() when using leafmap and streamlit #1058

Closed satmonkey closed 1 year ago

satmonkey commented 1 year ago

Hi, I am getting an error in add_gdf() (which is using fit_bounds()) function:

$ streamlit run app.py ... 2022-09-25 19:28:20.930 Uncaught app exception Traceback (most recent call last): File "/home/pi/vRMS/lib/python3.8/site-packages/streamlit/runtime/scriptrunner/script_runner.py", line 562, in _run_script exec(code, module.dict) File "/home/pi/source/leafmap-apps/apps/gdf_test.py", line 7, in m.add_gdf(gdf, layer_name="New York boroughs", fill_colors=["red", "green", "blue"]) File "/home/pi/vRMS/lib/python3.8/site-packages/leafmap/leafmap.py", line 2216, in add_gdf self.fit_bounds([[south, east], [north, west]]) File "/home/pi/vRMS/lib/python3.8/site-packages/ipyleaflet/leaflet.py", line 2608, in fit_bounds asyncio.ensure_future(self._fit_bounds(bounds)) File "/usr/lib/python3.8/asyncio/tasks.py", line 660, in ensure_future loop = events.get_event_loop() File "/usr/lib/python3.8/asyncio/events.py", line 639, in get_event_loop raise RuntimeError('There is no current event loop in thread %r.' RuntimeError: There is no current event loop in thread 'ScriptRunner.scriptThread'.

The code (from leafmap notebooks):

import leafmap.leafmap as leafmap import geopandas as gpd path_to_data = gpd.datasets.get_path("nybb") gdf = gpd.read_file(path_to_data) geojson = leafmap.gdf_to_geojson(gdf, epsg="4326") m = leafmap.Map() m.add_gdf(gdf, layer_name="New York boroughs", fill_colors=["red", "green", "blue"]) m.to_streamlit()

python 3.8.0 leafmap 0.10.5 ipyleaflet 0.17.1 pandas 1.5.0 geopandas 0.11.1

Milan

davidbrochart commented 1 year ago

fit_bounds() expects to be running in an event loop, as it is the case if you're running in ipykernel. You could create your map in an event loop, something like:

import asyncio
from ipyleaflet import Map

async def main():
    m = Map(...)
    m.fit_bounds(bounds)

asyncio.run(main())
satmonkey commented 1 year ago

I am simply running this from the bash in virtualenv. Adding geodataframe using folium backend works fine.

davidbrochart commented 1 year ago

I understand that the issue is not about adding a geodataframe, but using fit_bounds().

satmonkey commented 1 year ago

from the user view, calling add_gdf() ends with an error. I was able to track this down to this line (as seen from the error message): loop = events.get_event_loop() Calling add_gdf() with "zoom_to_layer=False" avoids the error, but vector elements rendering on the map is broken during zooming.

davidbrochart commented 1 year ago

This is a Leafmap issue.

satmonkey commented 1 year ago

In Jupyter notebook, this code runs well. After some serching, this seems to be Streamlit issue: streamlit/streamlit#744

asadimtiazmalik commented 1 year ago

Could you solve the issue since I am facing the same issue: image

davidbrochart commented 1 year ago

As reported above, it seems to be a Streamlit issue.