folium icon indicating copy to clipboard operation
folium copied to clipboard

LayerGroup support

Open DenisFLASH opened this issue 6 years ago • 10 comments

Short question

Will Folium ever allow a generation of LayerGroup, or a decision had been made to keep only FeatureGroup?

Details

According to LeafletJS documentation, FeatureGroup extends LayerGroup. They have different JS constructors: L.featureGroup(<Layer[]> layers) with only a list of layers, L.layerGroup(<Layer[]> layers?, <Object> options?) with some options in addition to layers.

When creating a FeatureGroup in Folium, there is a parameter name in its Python constructor (as well as some visualization-related params): __init__(self, name=None, overlay=True, control=True, show=True) However, this name is only used to display a name of this featuregroup in a LayerControl:

var feature_group_bdeeee... = L.featureGroup(name="events").addTo(map_...);
var layer_control_... = {
    base_layers : { "openstreetmap" : ...},
    overlays : { "events" : feature_group_bdeeee... }
}

What I need to have in a generated code for my use-case is a constructor with those options parameter, proposed by LayerGroup:

var layer_group_2... = L.layerGroup(null, {'step': '2'})

This would allow to access those attributes (step in my example) of my featuregroup (layergroup) using some custom JS code to put listeners on some objects.

Example of use case: when hovering step=5 name in a custom div element, 5th circle from events group and 5th marker of another (say, places) group change their CSS classes to highlight the connection between 5th "event" and "place", a bit like zip in Python.

To make it possible, i need L.layerGroup(null, {'step': '1'}) generated code instead of just empty L.featureGroup(). I could write corresponding code and make a PR, if ever this functionality is welcomed by the community :-)

folium version 0.7.0.

Sorry if anything is unclear, this is the 1st issue i open. Don't hesitate to ask for more details. Thanks!

DenisFLASH avatar Dec 06 '18 14:12 DenisFLASH

Hi @denisflash, I don’t think there was ever a conscious decision not to add layergroup. So we can definitely consider adding it. I don’t really understand your example though. Could you explain a bit more why you need layergroup, and featuregroup doesn’t work for you?

Conengmo avatar Jan 14 '19 17:01 Conengmo

I’m thinking now that adding this might help with some of the issues we’ve been having with the grouping of geojson layers. So if someone wants to pick this up that would be great. Should be straightforward to duplicate the current featuregroup implementation and alter it.

Conengmo avatar Jan 22 '19 08:01 Conengmo

Thanks a lot, @Conengmo ! Sorry for the late answer.

As I said, what I need is that Folium generate a JS object that can accept some custom parameters. I will later have some JS script that will use those parameters to do some CSS magic for my use case. LayerGroup has custom parameters, while FeatureGroup does not.

This is the shortest and the most generic explanation I could give. Tell me if you want more details, I could potentially explain a bit more on what I mean by step: 1, step: 2 in the example I gave above.

Great! I will try to pick this issue up. It could take some time however (the "onboarding" part: setting up the environment, launching tests, etc. etc., before even diving into the code itself), as this will be my first contribution to Folium. Thanks for putting badges on this issue! :-)

DenisFLASH avatar Jan 24 '19 17:01 DenisFLASH

While trying to do the dev, I note the following:

  1. Implementing LayerGroup class by copying and modifying FeatureGroup and its template is quite easy; I already have a simple LayerGroup implementation and could push it. However, it will not solve my problem (see below).

  2. More tricky (and almost blocking for my use case) is the fact that branca.element.Element can only have one parent in its ._parent attribute. When doing something like Marker(...).add_to(feature_group_1).add_to(layer_group_1) , only the last add_to is taken into account (it overwrites element's parent). When creating this issue, i thought having LayerGroup with options/attributes dictionary can solve my problem, but it appears to be insufficient, since i need elements to have multiple parents. Which looks like a potentially huuuge modification affecting not only a lot of classes in Folium repository, but even Branca repository. To have a "green light", this type of modifications would certainly require a lot of discussions inside the community.

Another solution for my problem (without touching number of parents) would be to pass custom attributes to elements themselves (Circle and other folium.vector_layers.* elements). But then, the problem is that on the LeafletJS side, there is no support for elements' attributes (while L.LayerGroup does accept options object, L.Layer class does not). So looks like the only way to pass some custom attributes to vector layer's elements is through adding a popup. Theoretically we could then parse those popups with a piece of custom JS on our "user" side. It could theoretically solve our problem without changing anything inside Folium. We will have to write that custom JS and accept our popups to be quite clumsy.

@Conengmo , tell me if you think that pushing LayerGroup will at least be useful for your case:

"adding this might help with some of the issues we’ve been having with the grouping of geojson layers"

If it is, i will create a PR. Thanks!

DenisFLASH avatar Mar 07 '19 14:03 DenisFLASH

I don't really understand what you are trying to achieve to be honest.

Letting an Element have multiple parents is an interesting proposal. It would allow for a popup to be applied to multiple features for example, quite useful. I don't think a lot of discussion is needed for this. But we do need to be sure what the side effects are.

If you still want to push a PR simply implementing LayerGroup that's welcome! Please include:

  • the actual change
  • a test to verify the template rendering correctly
  • ideally an example notebook showing the difference between FeatureGroup and LayerGroup.

Conengmo avatar Mar 09 '19 12:03 Conengmo

Thanks for a fast response, Frank. Ok, I think I should give more details to be clear about the main reason I created this issue.

Some time ago my colleague had written a custom Python wrapper for Leaflet. In my opinion, using Folium would give us more possibilities, moreover it is stable, open source and maintained by the community. Having custom code will be quite difficult to maintain/evolve. So I started investigating why he decided to write this custom framework, instead of just using Folium. As the guy has already left the team, I don't have a 100% clear answer. But it looks like there were 2 reasons:

  • Technical. Code generated by Folium was more verbose than generated with his custom tool, see my comment showing that difference (an example I give at the end of that comment looks almost as what his tool generates).

  • Functional. And this is the main reason I created this issue. He created something called "trace", which does the following. Imagine a sequence of Circle elements, with timestamp associated to each of them. There is also a

    on the generated HTML which gives an ordered list of those timestamps. Mouse hover event on any circle draws a rectangle around it, and highlights in that "trace div" the element corresponding to hovered circle. And vice versa: hovering on any of "trace div" draws a rectangle around the circle linked to this . This is simply a CSS mechanism, which is enabled by the ability to pass custom parameters to a LayerGroup that will link a circle and a in trace div. So for our example we would have 1 FeatureGroup (let's say, "circles"), and N LayerGroups (where N is the number of circles) that looks something like that:
    var lay_1 = L.layerGroup(null, {'step': '1', 'label': '2018-01-02 12:34:56'}
    

    (Today, we cannot generate a line like that using Folium's FeatureGroup, as it does not accept parameters).

    Then we add each circle to its corresponding LayerGroup, and the layergroup's step attribute allows us to do our custom CSS stuff. But as each circle is also a part of a "circles" FeatureGroup, it would mean we need each circle to have two parents: "circles" FeatureGroup and its lay_x LayerGroup where "x" is replaced by the position of a circle in the sequence (stepattribute).

    Hope this makes more sense.

DenisFLASH avatar Mar 09 '19 13:03 DenisFLASH

Thanks for explaining, I do get it better now. If you open a PR we can look at what’s possible without overcomplicating the class. You can always add additional functionality by adding some custom Javascript.

Conengmo avatar Mar 11 '19 07:03 Conengmo

Any updates on this? I also believe this would be a great piece of functionality - as of today only one choropleth can be used, having multiple layers would benefit many folks

gloriamacia avatar Jan 08 '22 12:01 gloriamacia

If we adopt LayerGroup, I think we should be able to explain to our users what the difference with FeatureGroup is. As I see it now, in folium it doesn't really make a difference in practice. We don't use any of the distinguishing features of FeatureGroup: https://leafletjs.com/reference.html#featuregroup. Grouping GeoJsons already works fine with FeatureGroup. The issue with Choropleth grouping is not the FeatureGroup, but the fact that colorscales are placed absolutely, outside of Leaflet.

I see three options at the moment:

  • Don't adopt LayerGroup, keep the focus on FeatureGroup as we have always done.
  • Adopt LayerGroup silently for the benefit of advanced users.
  • Someone reply in this issue why I'm wrong and what the folium use case for LayerGroup is :)

Conengmo avatar Nov 30 '22 10:11 Conengmo

Hi everyone, As for myself, unfortunately i'm not working on that project anymore, the one where i had the use case i described back in 2019. So i will not be able to continue neither the implementation work, nor discussing the technical decisions. The reason: the use case is not there anymore.

So, @gloriamacia , if you're currently working on a related topic and will benefit from this new feature, i guess it would be more convenient if you take it over and describe to the team, what your needs are.

I'll continue following the topic though. Thanks guys!

p.s. sorry for closing and reopening, just a misclick.

DenisFLASH avatar Dec 13 '22 14:12 DenisFLASH