ipyleaflet
ipyleaflet copied to clipboard
Map.fit_bounds() has no effect on Xeus-Python kernel in JupyterLab 3
It seems like map.fit_bounds() does not have any effect when run on the Xeus-Python (Python 3.8 (XPython)), but works as expected on the "normal" Python 3 kernel. The same effect can be seen when running in the "normal" mode (not the "simple" one in which the screenshots below were made) and when running as a "classic" notebook (after pressing "Help -> Launch Classic Notebook").
This took me a while to find out and I'm opening it here first, but I've opened one on Xeus kernel as a cross-reference: https://github.com/jupyter-xeus/xeus-python/issues/432. I'm using JupyterLab 3.0.10.
import ipyleaflet
print(ipyleaflet.__version__)
m = ipyleaflet.Map(center=[0, 0], zoom=1)
((s, w), (n, e)) = ((42, -6), (52, 9))
m += ipyleaflet.Polygon(locations=[(s, w), (n, w), (n, e), (s, e)])
# No effect under Xeus-Python (Python 3.8 (XPython)) kernel,
# but as expected under Python 3 kernel:
m.fit_bounds(((s, w), (n, e)))
m
I suspect it will work in both kernels if you put fit_bounds in a separate cell and call it only when you see the map on the page.
I think the problem is due to a race condition. Here fit_bounds is called before the map is even rendered on the page, so the comm message is received on the front-end, but the front-end doesn't know what to do with this message and discard it.
The fact that you see the problem with xeus-python and not with ipykernel, is because xeus-python is faster at creating the comm message and sending it (ipykernel does an extra ammount of work "cleaning" the JSON that xeus-python doesn't do). The slow parts of ipykernel gives the map the time to render, and the fit_bound message happens to be received when the map is actually rendered.
As a test, I would also suggest trying with Voila. If I am correct, fit_bounds will never work in Voila, whether it's xeus-python or ipykernel (because the map widget is rendered way later after fit_bounds has been called).
It seems like it makes no difference, how many cells I use for this in Xeus-Python. This one also doesn't work:
import ipyleaflet
m = ipyleaflet.Map(center=[0, 0], zoom=1)
m
((s, w), (n, e)) = ((42, -6), (52, 9))
m += ipyleaflet.Polygon(locations=[(s, w), (n, w), (n, e), (s, e)])
m
# No effect under Xeus-Python (Python 3.8 (XPython)) kernel,
# but as expected under Python 3 kernel:
m.fit_bounds(((s, w), (n, e)))
m
Oh, I thought fit_bounds was using comm messages, but it actually doesn't do that. Then what I said is not valid.
I think it is because xeus-python doesn't have event loop integration as ipykernel has.
We could also implement fit_bounds() using https://github.com/mapbox/mercantile, which would work with all python kernels, but that would only work for Mercator projections. Maybe this is fine.