folium: Maps with complex polygon layers not rendering in Jupyter Lab/Notebook

Please add a code sample or a nbviewer link, copy-pastable if possible

# Your code here

Problem description

I have been trying to run your sample notebook in examples/Geopandas.ipnyb in both Jupyter Lab and Jupyter Notebook. When I execute the cells, they all execute with no error but no map is rendered. I have had a similar problem in my own notebooks that seems to occur when the polygons are complex and have a lot of data points. I can get it to render simple polygons and so it doesn’t seem to be a library problem. Can you confirm this example still works with the latest release?

Versions below: notebook: 5.2.2 Jupyter Lab: 0.30 (note I upgraded to 0.31 but was having issues getting Lab to load) python: 3.6 Folium: 0.5.0

Expected Output

Rendered map in the examples/Geopandas.ipnyb

Output of folium.__version__

0.5.0

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 41 (13 by maintainers)

Most upvoted comments

There are two separated issues here:

  • loading maps on JupyterLab,
  • maps with many elements are not loading on Chrome/Chromium on Jupyter.

The former is not in our roadmap! People can try ipyleaflet or, if that works, saving the folium HTML and seeing if JupyterLab can load it. The reason is b/c folium devs have no bandwidth to write a JupyterLab extension (and that was quite te moving target in the past which drove me away from it).

For the latter there is a workaround:

def embed_map(m):
    from IPython.display import IFrame

    m.save('index.html')
    return IFrame('index.html', width='100%', height='750px')

I don’t know the details of why everything works in all the browsers I tested but Chrome so I’m closing this as “won’t fix.” (PRs are still welcome though 😉)

In the meantime, others encountering this issue can workaround the problem by using the following monkey patch, which works for folium==0.10.0 and branca==0.3.1. This code would have to be executed before using folium (e.g., in an early cell of a Jupyter notebook).

import base64

import folium

def _repr_html_(self, **kwargs):
    html = base64.b64encode(self.render(**kwargs).encode('utf8')).decode('utf8')
    onload = (
        'this.contentDocument.open();'
        'this.contentDocument.write(atob(this.getAttribute(\'data-html\')));'
        'this.contentDocument.close();'
    )
    if self.height is None:
        iframe = (
            '<div style="width:{width};">'
            '<div style="position:relative;width:100%;height:0;padding-bottom:{ratio};">'
            '<iframe src="about:blank" style="position:absolute;width:100%;height:100%;left:0;top:0;'
            'border:none !important;" '
            'data-html={html} onload="{onload}" '
            'allowfullscreen webkitallowfullscreen mozallowfullscreen>'
            '</iframe>'
            '</div></div>').format
        iframe = iframe(html=html, onload=onload, width=self.width, ratio=self.ratio)
    else:
        iframe = ('<iframe src="about:blank" width="{width}" height="{height}"'
                  'style="border:none !important;" '
                  'data-html={html} onload="{onload}" '
                  '"allowfullscreen" "webkitallowfullscreen" "mozallowfullscreen">'
                  '</iframe>').format
        iframe = iframe(html=html, onload=onload, width=self.width, height=self.height)
    return iframe

folium.branca.element.Figure._repr_html_ = _repr_html_

I’m having this exact problem when displaying a lot of data, using a layer. Works in every browser but Chrome.

Something to note, this doesn’t seem to be strictly a Jupyter Notebook situation, as the hex iFrame doesn’t load in Chrome in just a regular webpage, independent form Jupyter Notebook.

i experienced this problem today - the following maps for london boroughs will not display in chrome but will display in firefox or safari: http://nbviewer.jupyter.org/github/s-cork/OCR_LDS/blob/master/LondonMaps.ipynb

I found that if I reduced the number of London boroughs to 23 boroughs rather than 33 it would display fine in chrome.

@jmaralcZ the work around has been applied in branca, so you can install from the master branch to use it.

pip install git+https://github.com/python-visualization/branca

In the meantime, others encountering this issue can workaround the problem by using the following monkey patch, which works for folium==0.10.0 and branca==0.3.1. This code would have to be executed before using folium (e.g., in an early cell of a Jupyter notebook).

import base64

import folium

def _repr_html_(self, **kwargs):
    html = base64.b64encode(self.render(**kwargs).encode('utf8')).decode('utf8')
    onload = (
        'this.contentDocument.open();'
        'this.contentDocument.write(atob(this.getAttribute(\'data-html\')));'
        'this.contentDocument.close();'
    )
    if self.height is None:
        iframe = (
            '<div style="width:{width};">'
            '<div style="position:relative;width:100%;height:0;padding-bottom:{ratio};">'
            '<iframe src="about:blank" style="position:absolute;width:100%;height:100%;left:0;top:0;'
            'border:none !important;" '
            'data-html={html} onload="{onload}" '
            'allowfullscreen webkitallowfullscreen mozallowfullscreen>'
            '</iframe>'
            '</div></div>').format
        iframe = iframe(html=html, onload=onload, width=self.width, ratio=self.ratio)
    else:
        iframe = ('<iframe src="about:blank" width="{width}" height="{height}"'
                  'style="border:none !important;" '
                  'data-html={html} onload="{onload}" '
                  '"allowfullscreen" "webkitallowfullscreen" "mozallowfullscreen">'
                  '</iframe>').format
        iframe = iframe(html=html, onload=onload, width=self.width, height=self.height)
    return iframe

folium.branca.element.Figure._repr_html_ = _repr_html_

@dstein64 Thanks a lot for the work around. I would like to understand the fix but I do not get it completely. How is the fix reducing the length of html? is by using atob? Thanks again.

@dstein64 Thanks a lot! Was Finally able to put out my code in kaggle - Australian bushfire - map analysis.

Cool ,does it resolve the issue?

I confirmed that it resolves the issue, by using the following line in the notebook to install folium from the branch of the PR (this line has to precede import folium and the notebook has to be restarted).

!pip install git+https://github.com/sknzl/folium@update-css-url-to-https

Could you try it out?

I tried using the patched branca combined with the patched folium, and everything worked as expected.

!pip install git+https://github.com/python-visualization/branca
!pip install git+https://github.com/sknzl/folium@update-css-url-to-https

@nagarajbhat, thanks for the link.

I’ve replicated the issue you’ve encountered. I had to move the following line earlier in the notebook (prior to importing folium) in order to use the updated version of branca:

!pip install git+https://github.com/python-visualization/branca

After making this change, restarting the session, then running the notebook, I see that the branca version printed is 0.3.1+26.gf0dfe2e.

I saw the problematic play button and slider in Chrome, and not Firefox.

After I revert the updated branca version by removing the pip install statement, restarting the session, then running the notebook, I see that the branca version printed is 0.3.1.

With this reverted version, the map won’t display, but if I reduce the amount of data by changing 500 to 10:

data = [(initial_data + move_data * i).tolist() for i in range(10)]

… the map displays.

However, I am encountering the same issue with the play button and slider, even when using the older version of branca without updating nor patching.

Can you confirm whether you are also encountering the issue in Kaggle with a reduced data size and the existing version of branca (without updating nor patching)? If so, that suggests that the issue is separate (i.e., not related to the update recently merged into branca).

@dstein64 Thanks for the git install code. Just a clarification . It works fine locally (both in chrome and firefox) .And both by installing from github and monkey patch.

But I am not able to get it to work in Kaggle (chrome). You can use the same example, but increase the data points from 100 to around 500.

You can copy the kernel and try it out here in kaggle - https://www.kaggle.com/nagarajbhat/test-folium-heatmapwithtime

@nagarajbhat, I don’t know the schedule, but the update has been merged into branca in branca PR #66.

Given that folium specifies branca>=0.3.0 as a dependency, once an updated branca is released, this fix should be available in folium (after e.g., upgrading folium’s branca dependency).

Thanks for confirming @jwhendy. Next thing I’ll do is review that PR.

Confirming that the monkey patch above resolves the issue I ran into in #1244 (a duplicate, as I didn’t see this issue). Previously my limit was 3167 points and I just ran a test with 5k and 15k points with no problems. Thanks, @dstein64 !

Thanks for your work on this @dstein64! I’ll review your PR.

That’s actually done in branca, which the base library folium extends on. We can make changes or customise if needed. You can see the code here: https://github.com/python-visualization/branca/blob/master/branca/element.py#L324

Interesting find @dstein64, thanks for sharing!

We have another ticket on minifying html/js: https://github.com/python-visualization/folium/issues/975#issuecomment-451550054

Given this issue we could consider applying a minifyer in Jupyter context.

But it would be better IMO, more robust, to circumvent this limit entirely. Possibly in addition to minifying. In the Stackoverflow post you link to they mention some alternatives, such as saving data to disk or using some blob URL thing (I haven’t thorougly read it).

Help is welcome to work on this.

Chrome has a 2MB data URI limit.

I believe this issue may be from surpassing 2MB in a data URI in an iframe.

For example, in the link that @s-cork posted above, the Jupyter notebook embeds the first map in an <iframe> element. The data URI, data:text/html;charset=utf-8;base64,PCFET0NUW..., is 2.7MB.

A possibility for reducing the likelihood of this issue is to have folium generate minified html/javascript. That would result in a shorter length of the corresponding data URI.

This explains why the maps don’t work in Jupyter (where they’re encoded in data URIs), but work fine when loaded as html files directly into Chrome (outside the context of Jupyter).

https://github.com/python-visualization/folium/issues/812#issuecomment-437483792 ^ This workaround doesn’t work if using colab. The IFrame just shows “localhost refused to connect.” I assume it’s some issue with cross origin content?