Skip to content

Commit 842c4f7

Browse files
Add a colormap control to be used with Choropleth layer (#1010)
* Add a colormap control to be used with Choropleth layer to display a colormap (the ColormapControl class has Widget Control as a parent and used an Input widget.) * Remove the right padding on the colormap and set the background to transparent in the examples' notebook. * Change colormap_choice into colormap in class ColormapControl and update the docstring of the class. * Replace Any traitlet type by Instance for colormap in ColormapControl and modify the docstring for the default value. * Change Instance of colormap from LinearColormap to Colormap. Change trailet type of colormap in Choropleth from Any to Colormap and add importation of Colormap from branca. Remove LinearColormap mistaken importation from Folium. * Remove _default_colormap() and add a default value in the trailet definition. Remove unused importation in the example notebook and homogeneize the default colormap to linear.OrRd_06.
1 parent 7a2b15d commit 842c4f7

File tree

3 files changed

+154
-13
lines changed

3 files changed

+154
-13
lines changed

examples/ColormapControl.ipynb

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": null,
6+
"metadata": {},
7+
"outputs": [],
8+
"source": [
9+
"# Set up for JupyterLite\n",
10+
"try:\n",
11+
" import piplite\n",
12+
" await piplite.install(['ipyleaflet', 'branca'])\n",
13+
"except ImportError:\n",
14+
" pass"
15+
]
16+
},
17+
{
18+
"cell_type": "code",
19+
"execution_count": null,
20+
"metadata": {},
21+
"outputs": [],
22+
"source": [
23+
"import ipyleaflet\n",
24+
"import json\n",
25+
"import pandas as pd\n",
26+
"from branca.colormap import linear\n",
27+
"\n",
28+
"geo_json_data = json.load(open(\"us-states.json\"))\n",
29+
"m = ipyleaflet.Map(center=(43, -100), zoom=4)\n",
30+
"unemployment = pd.read_csv(\"US_Unemployment_Oct2012.csv\")"
31+
]
32+
},
33+
{
34+
"cell_type": "code",
35+
"execution_count": null,
36+
"metadata": {},
37+
"outputs": [],
38+
"source": [
39+
"unemployment = dict(\n",
40+
" zip(unemployment[\"State\"].tolist(), unemployment[\"Unemployment\"].tolist())\n",
41+
")"
42+
]
43+
},
44+
{
45+
"cell_type": "code",
46+
"execution_count": null,
47+
"metadata": {},
48+
"outputs": [],
49+
"source": [
50+
"colormap = linear.YlOrRd_04\n",
51+
"layer = ipyleaflet.Choropleth(\n",
52+
" geo_data=geo_json_data,\n",
53+
" choro_data=unemployment,\n",
54+
" colormap=colormap,\n",
55+
" style={\"fillOpacity\": 0.8, \"dashArray\": \"5, 5\"},\n",
56+
")"
57+
]
58+
},
59+
{
60+
"cell_type": "code",
61+
"execution_count": null,
62+
"metadata": {},
63+
"outputs": [],
64+
"source": [
65+
"colormap_control = ipyleaflet.ColormapControl(\n",
66+
" caption='Unemployment rate',\n",
67+
" colormap=colormap,\n",
68+
" value_min=layer.value_min,\n",
69+
" value_max=layer.value_max,\n",
70+
" position='topright',\n",
71+
" transparent_bg=True\n",
72+
")"
73+
]
74+
},
75+
{
76+
"cell_type": "code",
77+
"execution_count": null,
78+
"metadata": {},
79+
"outputs": [],
80+
"source": [
81+
"m.add(layer)\n",
82+
"m.add(colormap_control)\n",
83+
"m"
84+
]
85+
},
86+
{
87+
"cell_type": "code",
88+
"execution_count": null,
89+
"metadata": {},
90+
"outputs": [],
91+
"source": []
92+
}
93+
],
94+
"metadata": {
95+
"kernelspec": {
96+
"display_name": "Python 3 (ipykernel)",
97+
"language": "python",
98+
"name": "python3"
99+
},
100+
"language_info": {
101+
"codemirror_mode": {
102+
"name": "ipython",
103+
"version": 3
104+
},
105+
"file_extension": ".py",
106+
"mimetype": "text/x-python",
107+
"name": "python",
108+
"nbconvert_exporter": "python",
109+
"pygments_lexer": "ipython3",
110+
"version": "3.9.13"
111+
}
112+
},
113+
"nbformat": 4,
114+
"nbformat_minor": 4
115+
}

ipyleaflet/leaflet.py

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@
88
import xyzservices
99
from datetime import date, timedelta
1010
from math import isnan
11+
from branca.colormap import linear, ColorMap
12+
from IPython.display import display
1113
import warnings
1214

1315
from ipywidgets import (
1416
Widget, DOMWidget, Box, Color, CallbackDispatcher, widget_serialization,
15-
interactive, Style
17+
interactive, Style, Output
1618
)
1719

1820
from ipywidgets.widgets.trait_types import InstanceDict
@@ -22,7 +24,6 @@
2224
CFloat, Float, Unicode, Int, Tuple, List, Instance, Bool, Dict, Enum,
2325
link, observe, default, validate, TraitError, Union, Any
2426
)
25-
2627
from ._version import EXTENSION_VERSION
2728

2829
from .projections import projections
@@ -1399,7 +1400,7 @@ class Choropleth(GeoJSON):
13991400
Minimum data value for the color mapping.
14001401
value_max: float, default None
14011402
Maximum data value for the color mapping.
1402-
colormap: branca.colormap.ColorMap instance, default None
1403+
colormap: branca.colormap.ColorMap instance, default linear.OrRd_06
14031404
The colormap used for the effect.
14041405
key_on: string, default "id"
14051406
The feature key to use for the colormap effect.
@@ -1415,7 +1416,7 @@ class Choropleth(GeoJSON):
14151416
choro_data = Dict()
14161417
value_min = CFloat(None, allow_none=True)
14171418
value_max = CFloat(None, allow_none=True)
1418-
colormap = Any()
1419+
colormap = Instance(ColorMap, default_value=linear.OrRd_06)
14191420
key_on = Unicode('id')
14201421
nan_color = Unicode('black')
14211422
nan_opacity = CFloat(0.4)
@@ -1425,14 +1426,6 @@ class Choropleth(GeoJSON):
14251426
def _update_data(self, change):
14261427
self.data = self._get_data()
14271428

1428-
@default('colormap')
1429-
def _default_colormap(self):
1430-
try:
1431-
from branca.colormap import linear
1432-
except ImportError:
1433-
raise RuntimeError("The Choropleth needs branca to be installed, please run `pip install branca`")
1434-
return linear.OrRd_06
1435-
14361429
@default('style_callback')
14371430
def _default_style_callback(self):
14381431
def compute_style(feature, colormap, choro_data):
@@ -2031,6 +2024,38 @@ def remove_legend_element(self, key):
20312024
self.send_state()
20322025

20332026

2027+
class ColormapControl(WidgetControl):
2028+
"""ColormapControl class, with WidgetControl as parent class.
2029+
2030+
A control which contains a colormap.
2031+
2032+
Attributes
2033+
----------
2034+
caption : str, default 'caption'
2035+
The caption of the colormap.
2036+
colormap: branca.colormap.ColorMap instance, default linear.OrRd_06
2037+
The colormap used for the effect.
2038+
value_min : float, default 0.0
2039+
The minimal value taken by the data to be represented by the colormap.
2040+
value_max : float, default 1.0
2041+
The maximal value taken by the data to be represented by the colormap.
2042+
"""
2043+
caption = Unicode('caption')
2044+
colormap = Instance(ColorMap, default_value=linear.OrRd_06)
2045+
value_min = CFloat(0.0)
2046+
value_max = CFloat(1.0)
2047+
2048+
@default('widget')
2049+
def _default_widget(self):
2050+
widget = Output(layout={'height': '40px', 'width': '520px', 'margin': '0px -19px 0px 0px'})
2051+
with widget:
2052+
colormap = self.colormap.scale(self.value_min, self.value_max)
2053+
colormap.caption = self.caption
2054+
display(colormap)
2055+
2056+
return widget
2057+
2058+
20342059
class SearchControl(Control):
20352060
""" SearchControl class, with Control as parent class.
20362061

setup.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@
5656
install_requires=[
5757
'ipywidgets>=7.6.0,<8',
5858
'traittypes>=0.2.1,<3',
59-
'xyzservices>=2021.8.1'
59+
'xyzservices>=2021.8.1',
60+
'branca>=0.5.0'
6061
],
6162
packages=find_packages(),
6263
zip_safe=False,

0 commit comments

Comments
 (0)