# Import modules
import ee
import folium
import numpy as np
from matplotlib import colors, colormaps
16 Interactive maps
Interactive maps provide a dynamic user experience, allowing for real-time zooming, panning, and exploration of geospatial data layers. In contrast, Matplotlib’s static figures, while useful for publication-quality visuals, lack the ability to explore data or to easily integrate multiple layers of information. Additionally, interactive maps can be easily integrated withing websites and are ideal for collaborative projects and public dissemination of geospatial research findings.
In this tutorial we will create an interactive map to explore different land covers across the state of Kansas. We will use the folium
Python library, which is a wrapper around the popular Leaflet library implemented Javascript.
In this tutorial we will learn:
- How to add raster layers to an interactive map
- How to add vector layers to an interactive map
Define some helper functions
Let’s define some functions to avoid repeating the following code everytime we want to create a raster image or every time we want to specify a given colormap for our map.
def get_raster_map(ee_object, vis, name):
"""
Function that retrieves raster map from GEE and applies some style.
"""
if isinstance(ee_object, ee.Image):
= folium.TileLayer(ee_object.getMapId(vis)['tile_fetcher'].url_format,
layer =name,
name=True,
overlay=True,
control='Map Data © <a href="https://earthengine.google.com/">Google Earth Engine</a>')
attr
return layer
def get_vector_map(ee_object,vis,name):
"""
Function that retrieves vector map from GEE and applies some style.
"""
if isinstance(ee_object, ee.FeatureCollection):
= folium.GeoJson(ee_object.getInfo(),
layer =name,
name=lambda feature: {
style_function'fillColor': vis['face_color'],
'color': vis['edge_color'],
'weight': vis['line_width']})
return layer
# Authenticate GEE (follow the link and copy-paste the token in the notebook)
#ee.Authenticate()
# Initialize the library.
ee.Initialize()
State land cover
# Read US states
= ee.FeatureCollection("TIGER/2018/States")
US_states
# Select Kansas
= US_states.filter(ee.Filter.inList('NAME',['Kansas'])) region
# Land use for 2021
= ee.ImageCollection('USDA/NASS/CDL')\
land_use filter(ee.Filter.date('2020-01-01', '2021-12-31')).first().clip(region)
.
# Select cropland layer
= land_use.select('cropland') cropland
# Get layer metadata
= cropland.getInfo()
info
# Remove comment to print the entire information (output is long!)
# print(info)
print(info.keys())
dict_keys(['type', 'bands', 'id', 'version', 'properties'])
# Get land cover names, values, and colors from metadata
= info['properties']['cropland_class_names']
class_names = info['properties']['cropland_class_values']
class_values = info['properties']['cropland_class_palette'] class_colors
# Create dictionary to easily access properties by land cover name
= {}
class_props for k,name in enumerate(class_names):
= {'value':class_values[k], 'color':class_colors[k]}
class_props[name]
# Print example
'Corn'] class_props[
{'value': 1, 'color': 'ffd300'}
# Create self masks for each land cover, so that only
# the pixels for this land cover visible
= cropland.eq(class_props['Corn']['value']).selfMask()
corn = cropland.eq(class_props['Sorghum']['value']).selfMask()
sorghum = cropland.eq(class_props['Soybeans']['value']).selfMask()
soybeans = cropland.eq(class_props['Winter Wheat']['value']).selfMask()
wheat = cropland.eq(class_props['Grassland/Pasture']['value']).selfMask() grassland
Since we created a dictionary using the name of the land cover class as the key, in the previous cell you can use Tab-autocompletion.
# Initialize map centered at a specific location and zoom level
= folium.Map(location=[38, -98], zoom_start=7)
m
'palette':[class_props['Corn']['color']]}, 'Corn').add_to(m)
get_raster_map(corn, {'palette':[class_props['Sorghum']['color']]}, 'Sorghum').add_to(m)
get_raster_map(sorghum, {'palette':[class_props['Soybeans']['color']]}, 'Soybeans').add_to(m)
get_raster_map(soybeans, {'palette':[class_props['Winter Wheat']['color']]}, 'Wheat').add_to(m)
get_raster_map(wheat, {'palette':[class_props['Grassland/Pasture']['color']]}, 'Grassland').add_to(m)
get_raster_map(grassland, {
# Add vector layers
={'face_color':'#00FFFF00',
get_vector_map(region, vis'edge_color':'black',
'line_width':2}, name='State boundary').add_to(m)
={'face_color':'#00FFFF00',
get_vector_map(counties, vis'edge_color':'grey',
'line_width':1}, name='County boundary').add_to(m)
# Add a layer control panel to the map.
m.add_child(folium.LayerControl())
# Display the map.
display(m)