Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HeatMapWithTime: one time slider across multiple data layers #1062

Closed
kjarus1 opened this issue Feb 8, 2019 · 11 comments
Closed

HeatMapWithTime: one time slider across multiple data layers #1062

kjarus1 opened this issue Feb 8, 2019 · 11 comments
Labels
enhancement Feature request or idea about how to make folium better

Comments

@kjarus1
Copy link

kjarus1 commented Feb 8, 2019

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

heatmap = folium.Map(location=[0, 0], zoom_start=1.5)
HeatMapWithTime(data_1,index=index,overlay=False).add_to(heatmap)
HeatMapWithTime(data_2,index=index,overlay=False).add_to(heatmap)

Problem description

Since I am using the same index variable with default time slider parameters for both data layers, I expect the map to only produce one time slider. However, that is not the case as it adds extra time slider for each layer. This becomes an issue when you have let's say 10 different data layers and 10 identical time sliders on the side of your map.

image

Expected Output

If index variable and time slider parameters are set to be the same across different data layers, the map should only produce one time slider.

Output of folium.__version__

0.7.0

Update

I just found multiple layer example with one time slider using TimestampedWmsTileLayers on nbviewer. How can this be re-created using HeatMapWithTime??

@Conengmo
Copy link
Member

Conengmo commented Feb 9, 2019

Hi @kjarus1, I already commented on a related comment of yours. Can you combine your data into a single geojson dictionary? Then create a single HeatMapWithTime object.

The current implementation of HeatMapWithTime doesn't do what you want. If you want to look into this, I'd be happy to review any PR's. But I don't know if and how it can be done.

@Conengmo Conengmo added the enhancement Feature request or idea about how to make folium better label Feb 9, 2019
@kjarus1
Copy link
Author

kjarus1 commented Feb 9, 2019

Hi @Conengmo, thank you very much for getting back to me and offering the solution. One question though: how can I convert my heatmap data into geojson dictionary and then achieve what I want? A simple example would be very useful here and I think it would not only benefit me, especially, those who are not familiar with GeoJSON.

Let's say I already converted my pandas dataframe into two list of lists with three columns (lat,lon,weight) representing different datasets:

data_1
[[[46.7, -120.6, 0.005785500734206994],
  [56.6, 60.8, 0.0036496258440861704],
  [12.9, 80.0, 0.09627556816035182],
  ...]]

data_2
[[[34.2, -118.6, 0.00014104834180043172],
  [27.9, -81.0, 0.0001183798582967909],
  [41.0, 2.0, 2.0149763114347388e-05],
  ...]]

How can I now plot data_1 layer and data_2 layer using single HeatMapWithTime object with the same index?

Thanks,

Klaudijus

@kjarus1
Copy link
Author

kjarus1 commented Feb 9, 2019

Update

So far I have tried this but without much success. It seems that HeatMapWithTime requires to pass the list and, therefore, is not suitable with GeoJson or TimestampedGeoJson object:

geojson = GeoJson({
...     'type': 'FeatureCollection',
...     'features': [
...       {
...         'type': 'Feature',
...         'geometry': {
...           'type': 'MultiPoint',
...           'coordinates': data_1
...           },
...         }
...       ]
...     })

folium.plugins.HeatMapWithTime(geojson,name='data_1',overlay=False,index=index).add_to(heatmap)
heatmap

TypeError: object of type 'GeoJson' has no len()

@Conengmo
Copy link
Member

Conengmo commented Feb 9, 2019

I'm sorry, I shouldn't be talking about geojson since we're not dealing with those here. My bad.

So if I understand correctly you want multiple different heatmaps, each with their own entry in the layer controls, but with a single time control?

@kjarus1
Copy link
Author

kjarus1 commented Feb 9, 2019

Yes exactly sir! Is there is any way to achieve that? Your help would be much appreciated by not only me, but also my workplace.

@Conengmo
Copy link
Member

Conengmo commented Feb 9, 2019

You can do this but not how the code is now. So you need to hack things a bit. If you look in the HeatMapTime template you can see a TDHeatmap being created. You need to create additional ones for you other layers.

I just tested a solution where I created a class that only adds additional TDHeatmap objects:

class HeatMapWithTimeAdditional(Layer):
    _template = Template("""
        {% macro script(this, kwargs) %}
            var {{this.get_name()}} = new TDHeatmap({{ this.data }},
                {heatmapOptions: {
                    radius: {{this.radius}},
                    minOpacity: {{this.min_opacity}},
                    maxOpacity: {{this.max_opacity}},
                    scaleRadius: {{this.scale_radius}},
                    useLocalExtrema: {{this.use_local_extrema}},
                    defaultWeight: 1,
                    {% if this.gradient %}gradient: {{ this.gradient }}{% endif %}
                }
            }).addTo({{ this._parent.get_name() }});
        {% endmacro %}
    """)

    def __init__(self, data, name=None, radius=15,
                 min_opacity=0, max_opacity=0.6,
                 scale_radius=False, gradient=None, use_local_extrema=False,
                 overlay=True, control=True, show=True):
        super(HeatMapWithTimeAdditional, self).__init__(
            name=name, overlay=overlay, control=control, show=show
        )
        self._name = 'HeatMap'
        self.data = data

        # Heatmap settings.
        self.radius = radius
        self.min_opacity = min_opacity
        self.max_opacity = max_opacity
        self.scale_radius = 'true' if scale_radius else 'false'
        self.use_local_extrema = 'true' if use_local_extrema else 'false'
        self.gradient = gradient

You can add these after a HeatMapWithTime object has been added to your map:

folium.plugins.HeatMapWithTime(data).add_to(m)
folium.plugins.HeatMapWithTimeAdditional(other_data).add_to(m)

I had some issue with the layer controls, but if you untoggle both and then retoggle them they should appear.

If we wanted to add this functionality to folium it would need some work to get it robust.

@kjarus1
Copy link
Author

kjarus1 commented Feb 9, 2019

Hey @Conengmo thank you very very much for such prompt response and all your help.

This is probably a dump question but what do you define in your code as "Layer"? This is the message that I am getting: name 'Layer' is not defined. I tried the following but it fails:

from folium import Layer

Could it be because I am using a Jupyter Notebook?

Found it!

from jinja2 import Template from folium.map import Layer

@Conengmo
Copy link
Member

Conengmo commented Feb 9, 2019

Let me know if it works out! I'll close the issue, since I think we don't have anybody to work on implementing this. If somebody comes along who wants to do that, we can of course reopen the issue. PR's are always welcome!

@Conengmo Conengmo closed this as completed Feb 9, 2019
@kjarus1
Copy link
Author

kjarus1 commented Feb 18, 2019

Hi, apologies for the late reply but I just wanted to make sure that everything is tested and the code works properly before I write an update.

For my heatmap purposes the code published by @Conengmo works like a charm using this type of set-up:

folium.plugins.HeatMapWithTime(data,overlay=False,name='data',index=index,min_opacity=0.05,radius=20,min_speed=0.1,speed_step=0.1,max_speed=1,max_opacity=1).add_to(heatmap)
HeatMapWithTimeAdditional(data_1,overlay=False,name='data1',min_opacity=0.05,radius=20,max_opacity=1).add_to(heatmap)
HeatMapWithTimeAdditional(data_2,overlay=False,name='data2',min_opacity=0.05,radius=20,max_opacity=1).add_to(heatmap)

I hope this will help other people seeking for similar outcome. Thank you again @Conengmo

@ChandiniGanesan
Copy link

I was facing a similar issue and tried to use the code. However when using the HeaMapWithTimeAdditional my Map tile dissapears. Could some one suggest solution?

@neha845
Copy link

neha845 commented Jul 19, 2021

I was facing a similar issue and tried to use the code. However when using the HeaMapWithTimeAdditional my Map tile dissapears. Could some one suggest solution?

May be map is zooming more than max_zoom limit of the tile.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Feature request or idea about how to make folium better
Projects
None yet
Development

No branches or pull requests

4 participants