Dear Folium Developers,
I love your work. It makes my life so much easier. I was wondering though if theres a possibility to us polylines with a color parameter, based on another value (like altitude or similar). Is there anything to do that? I found this leaflet example to make clear what I mean: http://hgoebl.github.io/Leaflet.MultiOptionsPolyline/demo/ based on https://github.com/hgoebl/Leaflet.MultiOptionsPolyline
Thanks a lot, keep the good work coming!
I'm not a folium Developper, but i've done something similar to what you're looking for in a project. Basically, if you know the points, you can create such a line yourself with something like this using 0.3's ColorLine class, assuming your coordinates are in an ordered list like mine were:
for k in range(len(coordinates)-1):
line = ColorLine(
[coordinates[k], coordinates[k+1],
colors=[altitudes[k]],
colormap=altitudeColorMap
)
line.add_to(map)
The color map is just whatever folium.colormap you decide to use. Hope this helps until the devs decide to do a better implementation.
Hi yeah Ive done a very similar implementation. Thats definitely the way to go right now. And matplotlib provides nice colorfunction which work great in combination.
Here is my implementation:
def get_color(altitude):
norm = mpl.colors.Normalize(vmin=0, vmax=3000)
cmap = cm.nipy_spectral
m = cm.ScalarMappable(norm=norm, cmap=cmap)
return m.to_rgba(altitude)
i = 0
last_pos = all_x_y[i]
for pos in all_x_y[1:MAX_RECORDS]:
i += 1
this_plane = [last_pos] + [pos]
last_pos = pos
this_color = get_color(all_alt[i-1])
this_color = colors.rgb2hex(this_color)
folium.PolyLine(this_plane, color=this_color, weight=2.5, opacity=1).add_to(map)
@Etiennepi and @olibchr it would be nice if you could send notebooks examples to our gallery: https://github.com/python-visualization/folium/tree/master/examples :smile:
Sure! I use my own data tho. Would you add the data to the repo or prefer to have an implementation for your data?
Another thing I was wondering: When using a lot of points (like more than 10k) the rendering takes a lot of time. Any suggestions to improve that? I just have a lot of data and would like to bring it all on one map. Is it faster to safe it to an HTML and than serve that?
Sure! I use my own data tho. Would you add the data to the repo or prefer to have an implementation for your data?
Ideally we should auto-generate some fake data so it is self-contained. But do whatever is easier for you.
Doesnt matter to me. In this case its nice to have some "real" data as it gives the visualization context. But Ill publish it anyways. So, your choice.. For the purpose of an example, maybe your right!
Doesnt matter to me. In this case its nice to have some "real" data as it gives the visualization context.
As long as it is free data that we can publish (an open license would be good) go head. I love cool examples with context :smile:
Yeah its data from openstreetmap and openskynet, so no probs :-). Itll take me some more time to finish tho. Ill let you know
The implementation I made is dependent on copying the Colorline class from the unreleased version into a notebook (at least until 0.3 is released), so I think @olibchr 's solution would be better for the time being as an example.
Also, @olibchr, I found out that the html generated by folium's map.save function contains a lot of lines that contain white spaces. I recently had to generate a map that contained 74k points and it took about 67MB. I then wrote a script to minify the map and it went down to about 47MB, so if you want to serve the maps, that's definitely something you should look into doing yourself.
Awesome. Thanks you both.
PS: @Etiennepi I am working on a new release ASAP. But be aware that the Colormap class will probably be moved to branca and not folium.
Cool! I finished my project and made a few more implementations which might be interesting to you or others. I implemented:
I am more than happy to share my code. Feel free to alter it ( you probably have to, as its very focussed on my use.
A working example can be found here: lsde.becher.one
For questions, please ask!
`
class CustomLegend(Layer):
def __init__(self, content):
super(CustomLegend,self).__init__()
self._name = 'Legend'
self.position = 'topright'
self.content = content
self._template = Template(u"""
{% macro script(this, kwargs) %}
var info = L.control({position: '{{ this.position }}'});
info.onAdd = function () {
this._div = L.DomUtil.create('div', 'info'); // create a div with a class "info"
this.update();
return this._div;
};
info.update = function (flight_id, flight_nr, boxtxt) {
this._div.innerHTML = (flight_id ? '<div style="padding: 6px 8px;font: 14px/16px Arial, Helvetica, sans-serif;box-shadow: 0 0 15px;background: white;border-radius: 5px"><h4 style="color: #777">Trajectories for ICAO {{ this.content }}</h4> Double click circle to close box </br>' + boxtxt + '<img src="' + flight_id + '" style="width: 330px"/>' : '<div style="padding: 6px 8px;font: 14px/16px Arial, Helvetica, sans-serif;box-shadow: 0 0 15px;background: white;border-radius: 5px"><h4 style="color: #777">Trajectories for ICAO {{ this.content }}</h4>' + 'Click on black circles to get more information</div><br><div><img src="plots/bar_tr.gif" style="float: right;width: 80px"/></div>')
};
info.addTo({{this._parent.get_name()}});
{% endmacro %}
""")
`
Custom circle: can be used e.g. CustomCircleMarker(pos, radius=10, color="red", fill_color="black", flight_id=this_flight, flight_nr=flight_cnt, boxtxt="some text").add_to(flight_map)
`
class CustomCircleMarker(Marker):
"""
Self made template
"""
def init(self, location, radius=500, color='black',
fill_color='black', fill_opacity=0.6, popup=None, riseOnHover = 'true', clickUrl = "", flight_id = "", flight_nr = 0, boxtxt=""):
super(CustomCircleMarker, self).init(location, popup=popup)
self._name = 'CircleMarker'
self.radius = radius
self.color = color
self.fill_color = fill_color
self.fill_opacity = fill_opacity
self.riseOnHover = riseOnHover
self.clickUrl = clickUrl
self.icao = 'l' + clickUrl
self.flight_id = "plots/" + flight_id + ".png"
self.flightname = "plot" + flight_id.replace('-', '')
self.flight_nr = flight_nr
self.boxtxt = boxtxt
self._template = Template(u"""
{% macro script(this, kwargs) %}
var {{this.get_name()}} = L.circleMarker(
[{{this.location[0]}},{{this.location[1]}}],
{
color: '{{ this.color }}',
fillColor: '{{ this.fill_color }}',
fillOpacity: '{{ this.fill_opacity }}',
riseOnHover: {{this.riseOnHover }}
}
)
.on('click', function() {
info.update('{{ this.flight_id }}', '{{ this.flight_nr }}', '{{ this.boxtxt }}')
})
.on('dblclick', function() {
console.log('2');
info.update()
})
.on('mouseover', function(e){
this.setStyle({
fillColor: '#000000',
fillOpacity: 1.0
})
})
.on('mouseout', function(e){
this.setStyle({
fillColor: '#000000',
fillOpacity: '{{ this.fill_opacity }}'
})
})
.setRadius({{ this.radius }})
.addTo({{this._parent.get_name()}});
{% endmacro %}
""")
`
@olibchr do you want to open a PR with https://github.com/python-visualization/folium/issues/523#issuecomment-256879471 ?
Ill do it. Was busy in the last weeks, sorry.
I made some generalization of the code and put it into features.py. How can i push it to the repo so you can merge it @ocefpaf ?
A final working example is running here: http://lsde.becher.one/
I made some generalization of the code and put it into features.py. How can i push it to the repo so you can merge it @ocefpaf ?
Are you familiar with git and github to send it as a PR? If not do you feel comfortable attaching your version of features.py here so someone else can do that for you?
open pr in #574
As @Etiennepi showed this is easily done with Colorline, here is the same example from the plugin site:
http://nbviewer.jupyter.org/gist/ocefpaf/dd5aa84e9160ef05df6511391011d467
Note that PR #574 is unrelated to this issue and the code there may still be of interest.