ipyleaflet icon indicating copy to clipboard operation
ipyleaflet copied to clipboard

Map.fit_bounds() has no effect on Xeus-Python kernel in JupyterLab 3

Open deeplook opened this issue 4 years ago • 6 comments

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
Screenshot 2021-03-23 at 08 51 47 Screenshot 2021-03-23 at 08 50 32

deeplook avatar Mar 23 '21 08:03 deeplook

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.

martinRenou avatar Mar 23 '21 08:03 martinRenou

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.

martinRenou avatar Mar 23 '21 08:03 martinRenou

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).

martinRenou avatar Mar 23 '21 08:03 martinRenou

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

deeplook avatar Mar 23 '21 09:03 deeplook

Oh, I thought fit_bounds was using comm messages, but it actually doesn't do that. Then what I said is not valid.

martinRenou avatar Mar 23 '21 09:03 martinRenou

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.

davidbrochart avatar Mar 23 '21 09:03 davidbrochart