Skip to content

Commit 59f964d

Browse files
Add support for as_leaflet_layer in Map.add (#1033)
* Add support for as_leaflet_layer in Map.add * Improve docstring * Add documentation page * Simplify example * Update docs/source/layers/layer_like.rst Co-authored-by: David Brochart <[email protected]> * Update docs/source/layers/layer_like.rst Co-authored-by: David Brochart <[email protected]> * Update docs/source/layers/layer_like.rst Co-authored-by: David Brochart <[email protected]> * Minor rewording Co-authored-by: David Brochart <[email protected]>
1 parent 491da47 commit 59f964d

File tree

3 files changed

+74
-2
lines changed

3 files changed

+74
-2
lines changed

docs/source/layers/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,4 @@ Layers
2929
choropleth
3030
vector_tile.rst
3131
wkt_layer
32-
32+
layer_like

docs/source/layers/layer_like.rst

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
Layer-Like Objects
2+
==================
3+
4+
The :func:`ipyleaflet.Map.add` method supports
5+
"layer-like" objects; meaning any object with an ``as_leaflet_layer`` method.
6+
This interface can be especially useful for downstream developers who want
7+
their users to more easily be able to add their objects to an
8+
:class:`ipyleaflet.Map`.
9+
10+
Example
11+
-------
12+
13+
Downstream objects should implement an ``as_leaflet_layer`` method that returns
14+
an ``ipyleaflet`` type capable of being added to the ``Map``.
15+
16+
Here is a simple example of creating a custom data class to hold heatmap data
17+
(coordinates with some numerical value).
18+
19+
20+
.. jupyter-execute::
21+
22+
import numpy as np
23+
24+
25+
class MyHeatMap:
26+
def __init__(self, points, values, radius=20):
27+
self.points = points
28+
self.values = values
29+
self.radius = radius
30+
31+
@property
32+
def data(self):
33+
return np.column_stack((self.points, self.values))
34+
35+
def as_leaflet_layer(self):
36+
from ipyleaflet import Heatmap
37+
return Heatmap(
38+
locations=self.data.tolist(),
39+
radius=self.radius,
40+
)
41+
42+
We can now use that custom data class and because it has an
43+
``as_leaflet_layer`` interface, we can pass the object directly to
44+
:func:`ipyleaflet.Map.add`.
45+
46+
47+
.. jupyter-execute::
48+
49+
from ipyleaflet import Map
50+
51+
n = 1000
52+
data = MyHeatMap(
53+
np.random.uniform(-80, 80, (n, 2)),
54+
np.random.uniform(0, 1000, n),
55+
)
56+
57+
m = Map(center=(0, 0), zoom=2)
58+
m.add(data)
59+
m
60+
61+
62+
External Examples
63+
-----------------
64+
65+
The following external libraries are working to implement this new interface
66+
67+
- `localtileserver <https://github.com/banesullivan/localtileserver>`_: a dynamic tile server built for visualizing large geospatial images/rasters with ipyleaflet.
68+
- `xarray-leaflet <https://github.com/xarray-contrib/xarray_leaflet>`_: an xarray extension for tiled map plotting, based on ipyleaflet.

ipyleaflet/leaflet.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1165,11 +1165,15 @@ def add(self, layer):
11651165
Parameters
11661166
----------
11671167
layer: layer instance
1168-
The new layer to include in the group.
1168+
The new layer to include in the group. This can also be an object
1169+
with an ``as_leaflet_layer`` method which generates a compatible
1170+
layer type.
11691171
"""
11701172

11711173
if isinstance(layer, dict):
11721174
layer = basemap_to_tiles(layer)
1175+
elif hasattr(layer, 'as_leaflet_layer'):
1176+
layer = layer.as_leaflet_layer()
11731177
if layer.model_id in self._layer_ids:
11741178
raise LayerException('layer already in layergroup: %r' % layer)
11751179
self.layers = tuple([layer for layer in self.layers] + [layer])

0 commit comments

Comments
 (0)