Folium: How to use folium with iPython / Jupyter notebook

Created on 20 May 2015  路  19Comments  路  Source: python-visualization/folium

As far as I know there are two approaches for using folium inside a notebook:

  • use folium.initialize_notebook()
  • use inline_map / iframe.

What is the preferred way?

Several bugs are associated to the first (a quick search listed #90 , #44 , #132 ). Is there any advantage in using the first approach over the second? I tried to look for an answer in the issue tracker but did not find any.

Is there a reason for keeping both these approaches?

bug enhancement question

All 19 comments

@themiurgo that is a long standing issue that we need to address! The latest version of the Jupyter/IPython Notebook renders the HTML by itself, no need for folium.initialize_notebook().

(I haven't test this though. That is what I gathered from other users and colleagues.)

Maybe we should focus on making this object more "Jupyter friendly" and kill the folium.initialize_notebook() for good.

On the other hand I do use inline_map() extensively, that i because of nbviewer. inline_map() seems to be the "silver bullet" to get folium maps rendered online.

Is there a reason for keeping both these approaches?

The honest answer is no. But we need to check how the HTML object is rendering on nbviewer before telling people to stop using it. I have a bunch of tests here and I will check this once I get to the office.

@ocefpaf Great, thanks!

I use exclusively inline_maps at the moment, that's why I'm asking if there's any advantage in the other approach. Ideally it would be cool to have an "automagic" way to print HTML / visualize maps (print(fmap)?), but we need to know whether that should produce HTML or an iframe, and what are the pros/cons of each approach. Let's keep the discussion going before we go for any decision about this.

is inline_map() documented anywhere? I still can't get folium to render anything :)

is inline_map() documented anywhere? I still can't get folium to render
anything :)

Sorry Andrea, but the docs are so far behind that documenting inline_map()
never happen. Also, inline_map() is a workaround. We are working to in a
better way to show maps in Jupyter/IPython.

@ocefpaf I understand. If it is of any help, I hacked my way around it. Here is a version that works for me andreabedini/folium@50ade07080f802eb73869f0ae51ac72e5edbcfc6.

I use this: https://gist.github.com/themiurgo/f136265bdce26fbff704 and the only problem I've had is that maps disappear on consecutive reconnections to the same notebook.

@themiurgo With my version that works

edit: but to be honest I have some issues with CSS ...

Quite close to @themiurgo , here is my hack for this issue :
https://gist.github.com/BibMartin/0d298c07ebbf7048ca3d

I guess having the map in an iframe avoids interaction between jupyter's javascript and leaflet's.
I have also faced cross-origin problems when the notebooks are served on https ; and the iframes seem to solve that kind of issues also.

At last, I like the possibility to choose the size of the "figure" ; most notebook users are using this functionnality in matplotlib.

Random comment, but yesterday I found https://github.com/sandialabs/toyplot, which "Integrates with Jupyter without any need for plugins, magics, etc." (from their docs). I tried and it really works automagically. Maybe we can get some ideas on how to implement a similar thing in folium.

@themiurgo I had a look at toyplot (which is great btw) and they use SVG for rendering and JS for animation (see render function in https://github.com/sandialabs/toyplot/blob/master/toyplot/html.py).
As the main visual effect we have on folium (rendering tiles) is done by Leaflet, I guess it will be hard to copy the approach.

To sum up we need a method:

  • That renders properly in jupyter notebooks
  • That renders properly in nbviewer
  • That prevents the map's javascript/css to interfer with the notebook's core
  • Eventually that has a nice rendering in github (I guess it's hard as they execute no JS)

And we have three candidates:

  • folium.initialize_notebook()
  • An inline_map of the form:

'<iframe srcdoc="{html}"></iframe>'.format(html=m.HTML.replace('"','&quot;'))

  • Another one of the form:

'<iframe src="{html}"></iframe>'.format(html="data:text/html;base64,"+m.HTML.encode('base64'))

I'll try to test the three and summarize the strength / weakness of each.

Did I miss something ?

As the main visual effect we have on folium (rendering tiles) is done by Leaflet, I guess it will be hard to copy the approach.

Indeed. Their approach is beautiful, but I cannot see how to implement those ideas in folium.

I'll try to test the three and summarize the strength / weakness of each.
Did I miss something?

Nope! That pretty sums what needs to be done. Thanks @BibMartin!

Some thoughts:

  • folium.initialize_notebook() was the original design by @wrobstory. It is the same API used in mpld3, bokeh, and many other libraries that renders complex HTML in the notebook. I think it would be nice to try and fix it to be consistent with these other libraries.
  • inline_map is a hack! I would love to see it go away... But... It solves many problems with nbviewer, external data sources, etc.

Maybe we won't find the "best" solution that to fixes everything 100%. To be honest I think our bug is in the docs. We need to properly document what users should use depending on the map they are producing.

I want to page @rgbkrk to the discussion here.

Kyle, I'm honestly leaning towards recommending a move towards iframe to resolve some of the issues being discussed. Initialize notebook is using the display(HTML stuff, but as discussed there are some nbviewer and external data source issues.

Plotly has built some really nice stuff purely on iframes. Is this the direction we should be moving, or should we keep leaning on the built-in notebook machinery?

As far as I undestand it (now), the main question is:
Shall we share jupyter-notebook's javascript environnement ?

If yes

  • we feel coherent with other projects (like bokeh, mpld3)
  • we have the opportunity to interact with the notebook (use widgets...)
  • we can fix and keep initialize_notebook

But

  • we have to make sure not to break anything in jupyter each time we add some javascript.
  • we have to make sure that nothing breaks in folium each time jupyter changes it's javascript.
  • every dependency that is added into folium will need to be reported into initialize_notebook(or whatever it's name).

If no

  • we have a single template for generating html
  • we have no risk of breaking something between folium and jupyter-notebook
  • we shall go on an iframe that sets a separate javascript interpreter.

But

  • interactions with jupyter widgets or other libraries (bokeh...) may be more difficult
  • folium loads a full html page each time it displays a map

I must confess I am quite afraid about interaction issues (see an illustration on https://github.com/BibMartin/folium/blob/master/examples/javascript%20interference%20example.ipynb) and debugging javascript makes me pain. So my personal answer would be no. But I've tryied to be fair in this _pros and cons_ exercise ; please tell me otherwise.

From a light skim and a glance through docs on this library, I'm noticing that there are problems with:

  • CSS encapsulation
  • JS collisions between the notebook and folium (well, D3 + Leaflet)

The first (CSS) can be handled ok using a shadow DOM (this will only work in Chrome currently unless you include the polyfill on other browsers). You can address both the CSS and JS issues by using an iframe that you create.

You're probably already aware, but working within iframes has its tricky bits. I personally prefer to put the iframe on the document, then get a handle for the iframe.contentWindow.document to do normal document actions.

Does folium ever use the Jupyter/IPython comms interface to pass messages?

There are several issues I'm interested in pushing hard on with current work:

  • Presenting resources (standard HTML/CSS/JS) from kernels to the frontend ("here's my copy of D3")
  • Encapsulating the CSS and JS

/cc @jdfreder

As of PR #190 all you need is to leave the map object as the last thing in the cell and the IPython/Jupyter HTML repr will take care of the rest.

(See: http://nbviewer.ipython.org/github/ocefpaf/folium_notebooks/tree/master/)

Getting Jupyter notebooks to display folium maps now works without any magic. But they are not saved with the notebook, as can be seen in the official examples.

It seems though as if the HTML used to be saved, e.g. in the notebooks you referred to, @ocefpaf? What can I do to bring back that very useful functionality?

But they are not saved with the notebook, as can be seen in the official examples.

They are. That is GitHub scrubbing off the JS for security reasons. Here is the same notebook you mentioned above on nbviewer, which does not scrub the JS.

What can I do to bring back that very useful functionality?

No functionality is gone. And all JS Jypyter stuff on GitHub will suffer from that. There is nothing we can.

My bad, thanks for the clarification @ocefpaf. I did look inside my ipynb file, but overlooked the HTML (the dict key "outputs" was before "source". Python (2)...).

No problem. Glad you are using folium :smile:

Was this page helpful?
0 / 5 - 0 ratings

Related issues

xhx509 picture xhx509  路  15Comments

achourasia picture achourasia  路  19Comments

ispmarin picture ispmarin  路  17Comments

reaganch picture reaganch  路  13Comments

FlorianHoevelmann picture FlorianHoevelmann  路  14Comments