YouthMappers 2021
Interactive Mapping and Geospatial Analysis with Leafmap and Jupyter
This notebook was developed for the 90-min leafmap workshop taking place on November 9, 2021. The workshop is hosted by YouthMappers.
- Author: Qiusheng Wu
- Slides: https://gishub.org/ym
- Streamlit web app: https://streamlit.gishub.org
Launch this notebook to execute code interactively using:
- Google Colab: https://gishub.org/ym-colab
- Pangeo Binder JupyterLab: https://gishub.org/ym-binder
- Pangeo Binder Jupyter Notebook: https://gishub.org/ym-binder-nb
Introduction¶
Workshop description¶
Leafmap is a Python package for interactive mapping and geospatial analysis with minimal coding in a Jupyter environment. It is built upon a number of open-source packages, such as folium and ipyleaflet (for creating interactive maps), WhiteboxTools and whiteboxgui (for analyzing geospatial data), and ipywidgets (for designing interactive graphical user interface). The WhiteboxTools library currently contains 480+ tools for advanced geospatial analysis. Leafmap provides many convenient functions for loading and visualizing geospatial data with only one line of code. Users can also use the interactive user interface to load geospatial data without coding. Anyone with a web browser and Internet connection can use leafmap to perform geospatial analysis and data visualization in the cloud with minimal coding. The topics that will be covered in this workshop include:
- A brief introduction to Jupyter and Colab
- A brief introduction to leafmap and relevant web resources
- Creating interactive maps using multiple plotting backends
- Searching and loading basemaps
- Loading and visualizing vector/raster data
- Using Cloud Optimized GeoTIFF (COG) and SpatialTemporal Asset Catalog (STAC)
- Downloading OpenStreetMap data
- Loading data from a PostGIS database
- Creating custom legends and colorbars
- Creating split-panel maps and linked maps
- Visualizing Planet global monthly/quarterly mosaic
- Designing and publishing interactive web apps
- Performing geospatial analysis (e.g., hydrological analysis) using whiteboxgui
This workshop is intended for scientific programmers, data scientists, geospatial analysts, and concerned citizens of Earth. The attendees are expected to have a basic understanding of Python and the Jupyter ecosystem. Familiarity with Earth science and geospatial datasets is useful but not required. More information about leafmap can be found at https://leafmap.org.
Jupyter keyboard shortcuts¶
- Shift+Enter: run cell, select below
- Ctrl+Enter: : run selected cells
- Alt+Enter: run cell and insert below
- Tab: code completion or indent
- Shift+Tab: tooltip
- Ctrl+/: comment out code
Set up environment¶
Required Python packages:¶
- leafmap - A Python package for interactive mapping and geospatial analysis with minimal coding in a Jupyter environment.
- keplergl - A high-performance web-based application for visual exploration of large-scale geolocation data sets.
- pydeck - High-scale spatial rendering in Python, powered by deck.gl.
- geopandas - An open source project to make working with geospatial data in python easier.
- xarray-leaflet - An xarray extension for tiled map plotting.
Use Google Colab¶
Click the button below to open this notebook in Google Colab and execute code interactively.
# !pip install leafmap
import os
import subprocess
import sys
import warnings
warnings.filterwarnings("ignore")
A function for installing Python packages.
def install(package):
subprocess.check_call([sys.executable, "-m", "pip", "install", package])
Install required Python packages in Google Colab.
pkgs = [
"leafmap",
"geopandas",
"keplergl",
"pydeck",
"xarray_leaflet",
"osmnx",
"pygeos",
"imageio",
"tifffile",
]
if "google.colab" in sys.modules:
for pkg in pkgs:
install(pkg)
Use Pangeo Binder¶
Click the buttons below to open this notebook in JupyterLab (first button) or Jupyter Notebook (second button) and execute code interactively.
- JupyterLab: https://gishub.org/ym-binder
- Jupyter Notebook: https://gishub.org/ym-binder-nb
Use Miniconda/Anaconda¶
If you have Anaconda or Miniconda installed on your computer, you can install leafmap using the following commands. Leafmap has an optional dependency - geopandas, which can be challenging to install on some computers, especially Windows. It is highly recommended that you create a fresh conda environment to install geopandas and leafmap. Follow the commands below to set up a conda env and install geopandas, leafmap, pydeck, keplergl, and xarray_leaflet.
conda create -n geo python=3.8
conda activate geo
conda install geopandas
conda install mamba -c conda-forge
mamba install leafmap keplergl pydeck xarray_leaflet -c conda-forge
mamba install osmnx pygeos imageio tifffile -c conda-forge
jupyter lab
try:
import leafmap
except ImportError:
install("leafmap")
Create an interactive map¶
Leafmap
has five plotting backends: folium, ipyleaflet, here-map, kepler.gl, and pydeck. Note that the backends do not offer equal functionality. Some interactive functionality in ipyleaflet
might not be available in other plotting backends. To use a specific plotting backend, use one of the following:
import leafmap.leafmap as leafmap
import leafmap.foliumap as leafmap
import leafmap.heremap as leafmap
import leafmap.kepler as leafmap
import leafmap.deck as leafmap
Use ipyleaflet¶
import leafmap
m = leafmap.Map()
m
Use folium¶
import leafmap.foliumap as leafmap
m = leafmap.Map()
m
Use kepler.gl¶
import leafmap.kepler as leafmap
m = leafmap.Map()
m
If you encounter an error saying Error displaying widget: model not found
when trying to display the map, you can use m.static_map()
as a workaround until this kepler.gl bug has been resolved.
# m.static_map(width=1280, height=600)
Use pydeck¶
import leafmap.deck as leafmap
m = leafmap.Map()
m
import leafmap
m = leafmap.Map(center=(40, -100), zoom=4) # center=[lat, lon]
m
m = leafmap.Map(center=(51.5, -0.15), zoom=17)
m
Change map size¶
m = leafmap.Map(height="400px", width="800px")
m
Set control visibility¶
When creating a map, set the following controls to either True
or False
as appropriate.
- attribution_control
- draw_control
- fullscreen_control
- layers_control
- measure_control
- scale_control
- toolbar_control
m = leafmap.Map(
draw_control=False,
measure_control=False,
fullscreen_control=False,
attribution_control=False,
)
m
Remove all controls from the map.
m = leafmap.Map()
m.clear_controls()
m
Change basemaps¶
Specify a Google basemap to use, can be one of ["ROADMAP", "TERRAIN", "SATELLITE", "HYBRID"].
import leafmap
m = leafmap.Map(google_map="TERRAIN") # HYBRID, ROADMAP, SATELLITE, TERRAIN
m
Add a basemap using the add_basemap()
function.
m = leafmap.Map()
m.add_basemap("Esri.NatGeoWorldMap")
m
Print out the list of available basemaps.
for basemap in leafmap.basemaps:
print(basemap)
m = leafmap.Map()
m.add_tile_layer(
url="https://mt1.google.com/vt/lyrs=y&x={x}&y={y}&z={z}",
name="Google Satellite",
attribution="Google",
)
m
import leafmap
m = leafmap.Map()
m.add_tile_layer(
url="https://mt1.google.com/vt/lyrs=y&x={x}&y={y}&z={z}",
name="Google Satellite",
attribution="Google",
)
m
Add WMS tile layer¶
More WMS basemaps can be found at the following websites:
- USGS National Map: https://viewer.nationalmap.gov/services
- MRLC NLCD Land Cover data: https://www.mrlc.gov/data-services-page
- FWS NWI Wetlands data: https://www.fws.gov/wetlands/Data/Web-Map-Services.html
m = leafmap.Map()
naip_url = "https://services.nationalmap.gov/arcgis/services/USGSNAIPImagery/ImageServer/WMSServer?"
m.add_wms_layer(
url=naip_url, layers="0", name="NAIP Imagery", format="image/png", shown=True
)
m
Add xyzservices provider¶
Add a layer from xyzservices provider object.
import os
import xyzservices.providers as xyz
basemap = xyz.OpenTopoMap
basemap
m = leafmap.Map()
m.add_basemap(basemap)
m
Add COG/STAC layers¶
A Cloud Optimized GeoTIFF (COG) is a regular GeoTIFF file, aimed at being hosted on a HTTP file server, with an internal organization that enables more efficient workflows on the cloud. It does this by leveraging the ability of clients issuing HTTP GET range requests to ask for just the parts of a file they need.
More information about COG can be found at https://www.cogeo.org/in-depth.html
Some publicly available Cloud Optimized GeoTIFFs:
- https://stacindex.org/
- https://cloud.google.com/storage/docs/public-datasets/landsat
- https://www.digitalglobe.com/ecosystem/open-data
- https://earthexplorer.usgs.gov/
For this demo, we will use data from https://www.maxar.com/open-data/california-colorado-fires for mapping California and Colorado fires. A list of COGs can be found here.
Add COG layer¶
import leafmap
m = leafmap.Map()
url = "https://github.com/opengeos/data/releases/download/raster/Libya-2023-07-01.tif"
url2 = "https://github.com/opengeos/data/releases/download/raster/Libya-2023-09-13.tif"
m.add_cog_layer(url, name="Fire (pre-event)")
m.add_cog_layer(url2, name="Fire (post-event)")
m
Add STAC layer¶
The SpatioTemporal Asset Catalog (STAC) specification provides a common language to describe a range of geospatial information, so it can more easily be indexed and discovered. A 'spatiotemporal asset' is any file that represents information about the earth captured in a certain space and time. The initial focus is primarily remotely-sensed imagery (from satellites, but also planes, drones, balloons, etc), but the core is designed to be extensible to SAR, full motion video, point clouds, hyperspectral, LiDAR and derived data like NDVI, Digital Elevation Models, mosaics, etc. More information about STAC can be found at https://stacspec.org/
Some publicly available SpatioTemporal Asset Catalog (STAC):
For this demo, we will use STAC assets from https://stacindex.org/catalogs/spot-orthoimages-canada-2005#/?t=catalogs
m = leafmap.Map()
url = "https://canada-spot-ortho.s3.amazonaws.com/canada_spot_orthoimages/canada_spot5_orthoimages/S5_2007/S5_11055_6057_20070622/S5_11055_6057_20070622.json"
m.add_stac_layer(url, bands=["B3", "B2", "B1"], name="False color")
m
import os
import leafmap
Download samples raster datasets. More datasets can be downloaded from https://viewer.nationalmap.gov/basic/
out_dir = os.getcwd()
landsat = os.path.join(out_dir, "landsat.tif")
dem = os.path.join(out_dir, "dem.tif")
Download a small Landsat imagery.
landsat_url = (
"https://drive.google.com/file/d/1EV38RjNxdwEozjc9m0FcO3LFgAoAX1Uw/view?usp=sharing"
)
leafmap.download_file(landsat_url, "landsat.tif", unzip=False)
Download a small DEM dataset.
dem_url = (
"https://drive.google.com/file/d/1vRkAWQYsLWCi6vcTMk8vLxoXMFbdMFn8/view?usp=sharing"
)
leafmap.download_file(dem_url, "dem.tif", unzip=False)
m = leafmap.Map()
Add local raster datasets to the map
More colormap can be found at https://matplotlib.org/3.1.0/tutorials/colors/colormaps.html
m.add_raster(dem, colormap="terrain", layer_name="DEM")
m.add_raster(landsat, bands=[5, 4, 3], layer_name="Landsat")
m
import leafmap
List all available built-in legends.
legends = leafmap.builtin_legends
for legend in legends:
print(legend)
Add a WMS layer and built-in legend to the map.
m = leafmap.Map()
url = "https://www.mrlc.gov/geoserver/mrlc_display/NLCD_2019_Land_Cover_L48/wms?"
m.add_wms_layer(
url,
layers="NLCD_2019_Land_Cover_L48",
name="NLCD 2019 CONUS Land Cover",
format="image/png",
transparent=True,
)
m.add_legend(builtin_legend="NLCD")
m
Add U.S. National Wetlands Inventory (NWI). More info at https://www.fws.gov/wetlands.
m = leafmap.Map(google_map="HYBRID")
url1 = "https://www.fws.gov/wetlands/arcgis/services/Wetlands/MapServer/WMSServer?"
m.add_wms_layer(
url1, layers="1", format="image/png", transparent=True, name="NWI Wetlands Vector"
)
url2 = "https://www.fws.gov/wetlands/arcgis/services/Wetlands_Raster/ImageServer/WMSServer?"
m.add_wms_layer(
url2, layers="0", format="image/png", transparent=True, name="NWI Wetlands Raster"
)
m.add_legend(builtin_legend="NWI")
m
Add custom legend¶
There are two ways you can add custom legends:
- Define legend labels and colors
- Define legend dictionary
Define legend keys and colors.
m = leafmap.Map()
labels = ["One", "Two", "Three", "Four", "etc"]
# color can be defined using either hex code or RGB (0-255, 0-255, 0-255)
colors = ["#8DD3C7", "#FFFFB3", "#BEBADA", "#FB8072", "#80B1D3"]
# colors = [(255, 0, 0), (127, 255, 0), (127, 18, 25), (36, 70, 180), (96, 68, 123)]
m.add_legend(title="Legend", labels=labels, colors=colors)
m
Define a legend dictionary.
m = leafmap.Map()
url = "https://www.mrlc.gov/geoserver/mrlc_display/NLCD_2019_Land_Cover_L48/wms?"
m.add_wms_layer(
url,
layers="NLCD_2019_Land_Cover_L48",
name="NLCD 2019 CONUS Land Cover",
format="image/png",
transparent=True,
)
legend_dict = {
"11 Open Water": "466b9f",
"12 Perennial Ice/Snow": "d1def8",
"21 Developed, Open Space": "dec5c5",
"22 Developed, Low Intensity": "d99282",
"23 Developed, Medium Intensity": "eb0000",
"24 Developed High Intensity": "ab0000",
"31 Barren Land (Rock/Sand/Clay)": "b3ac9f",
"41 Deciduous Forest": "68ab5f",
"42 Evergreen Forest": "1c5f2c",
"43 Mixed Forest": "b5c58f",
"51 Dwarf Scrub": "af963c",
"52 Shrub/Scrub": "ccb879",
"71 Grassland/Herbaceous": "dfdfc2",
"72 Sedge/Herbaceous": "d1d182",
"73 Lichens": "a3cc51",
"74 Moss": "82ba9e",
"81 Pasture/Hay": "dcd939",
"82 Cultivated Crops": "ab6c28",
"90 Woody Wetlands": "b8d9eb",
"95 Emergent Herbaceous Wetlands": "6c9fb8",
}
m.add_legend(title="NLCD Land Cover Classification", legend_dict=legend_dict)
m
Add colormap¶
The colormap functionality requires the ipyleaflet plotting backend. Folium is not supported.
import leafmap
import leafmap.colormaps as cm
Common colormaps¶
Color palette for DEM data.
cm.palettes.dem
Show the DEM palette.
cm.plot_colormap(colors=cm.palettes.dem, axis_off=True)
Color palette for NDVI data.
cm.palettes.ndvi
Show the NDVI palette.
cm.plot_colormap(colors=cm.palettes.ndvi)
Custom colormaps¶
Specify the number of classes for a palette.
cm.get_palette("terrain", n_class=8)
Show the terrain palette with 8 classes.
cm.plot_colormap(colors=cm.get_palette("terrain", n_class=8))
Create a palette with custom colors, label, and font size.
cm.plot_colormap(colors=["red", "green", "blue"], label="Temperature", font_size=12)
Create a discrete color palette.
cm.plot_colormap(
colors=["red", "green", "blue"], discrete=True, label="Temperature", font_size=12
)
Specify the width and height for the palette.
cm.plot_colormap(
"terrain",
label="Elevation",
width=8.0,
height=0.4,
orientation="horizontal",
vmin=0,
vmax=1000,
)
Change the orentation of the colormap to be vertical.
cm.plot_colormap(
"terrain",
label="Elevation",
width=0.4,
height=4,
orientation="vertical",
vmin=0,
vmax=1000,
)
Horizontal colormap¶
Add a horizontal colorbar to an interactive map.
m = leafmap.Map()
m.add_basemap("OpenTopoMap")
m.add_colormap(
"terrain",
label="Elevation",
width=8.0,
height=0.4,
orientation="horizontal",
vmin=0,
vmax=4000,
)
m
Vertical colormap¶
Add a vertical colorbar to an interactive map.
m = leafmap.Map()
m.add_basemap("OpenTopoMap")
m.add_colormap(
"terrain",
label="Elevation",
width=0.4,
height=4,
orientation="vertical",
vmin=0,
vmax=4000,
)
m
List of available colormaps¶
cm.plot_colormaps(width=12, height=0.4)
import os
import leafmap
in_csv = "https://raw.githubusercontent.com/opengeos/data/main/world/world_cities.csv"
df = leafmap.csv_to_df(in_csv)
df
Create a point layer from a CSV file containing lat/long information.
m = leafmap.Map()
m.add_xy_data(in_csv, x="longitude", y="latitude", layer_name="World Cities")
m
Set the output directory.
out_dir = os.getcwd()
out_shp = os.path.join(out_dir, "world_cities.shp")
Convert a CSV file containing lat/long information to a shapefile.
leafmap.csv_to_shp(in_csv, out_shp)
Convert a CSV file containing lat/long information to a GeoJSON.
out_geojson = os.path.join(out_dir, "world_cities.geojson")
leafmap.csv_to_geojson(in_csv, out_geojson)
Convert a CSV file containing lat/long information to a GeoPandas GeoDataFrame.
gdf = leafmap.csv_to_gdf(in_csv)
gdf
Add GeoJSON¶
Add a GeoJSON to the map.
m = leafmap.Map(center=[0, 0], zoom=2)
in_geojson = "https://raw.githubusercontent.com/opengeos/leafmap/master/examples/data/cable_geo.geojson"
m.add_geojson(in_geojson, layer_name="Cable lines", info_mode="on_hover")
m
Add a GeoJSON with random filled color to the map.
m = leafmap.Map(center=[0, 0], zoom=2)
url = "https://raw.githubusercontent.com/opengeos/leafmap/master/examples/data/countries.geojson"
m.add_geojson(
url, layer_name="Countries", fill_colors=["red", "yellow", "green", "orange"]
)
m
Use the style_callback
function for assigning a random color to each polygon.
import random
m = leafmap.Map(center=[0, 0], zoom=2)
url = "https://raw.githubusercontent.com/opengeos/leafmap/master/examples/data/countries.geojson"
def random_color(feature):
return {
"color": "black",
"fillColor": random.choice(["red", "yellow", "green", "orange"]),
}
m.add_geojson(url, layer_name="Countries", style_callback=random_color)
m
Use custom style
and hover_style
functions.
m = leafmap.Map(center=[0, 0], zoom=2)
url = "https://raw.githubusercontent.com/opengeos/leafmap/master/examples/data/countries.geojson"
style = {
"stroke": True,
"color": "#0000ff",
"weight": 2,
"opacity": 1,
"fill": True,
"fillColor": "#0000ff",
"fillOpacity": 0.1,
}
hover_style = {"fillOpacity": 0.7}
m.add_geojson(url, layer_name="Countries", style=style, hover_style=hover_style)
m
Add shapefile¶
m = leafmap.Map(center=[0, 0], zoom=2)
in_shp = "https://github.com/opengeos/leafmap/raw/master/examples/data/countries.zip"
m.add_shp(in_shp, layer_name="Countries")
m
Add KML¶
import leafmap
m = leafmap.Map()
in_kml = "https://raw.githubusercontent.com/opengeos/leafmap/master/examples/data/us_states.kml"
m.add_kml(in_kml, layer_name="US States KML")
m
Add GeoDataFrame¶
import geopandas as gpd
m = leafmap.Map()
gdf = gpd.read_file(
"https://github.com/opengeos/leafmap/raw/master/examples/data/cable_geo.geojson"
)
m.add_gdf(gdf, layer_name="Cable lines")
m
Read the GeoPandas sample dataset as a GeoDataFrame.
path_to_data = (
"https://github.com/opengeos/datasets/releases/download/vector/nybb.geojson"
)
gdf = gpd.read_file(path_to_data)
gdf
m = leafmap.Map()
m.add_gdf(gdf, layer_name="New York boroughs", fill_colors=["red", "green", "blue"])
m
Add point layer¶
Add a point layer using the interactive GUI.
m = leafmap.Map()
m
Add a point layer programmatically.
m = leafmap.Map()
url = "https://raw.githubusercontent.com/opengeos/leafmap/master/examples/data/us_cities.geojson"
m.add_point_layer(url, popup=["name", "pop_max"], layer_name="US Cities")
m
Add vector¶
The add_vector
function supports any vector data format supported by GeoPandas.
m = leafmap.Map(center=[0, 0], zoom=2)
url = "https://raw.githubusercontent.com/opengeos/leafmap/master/examples/data/countries.geojson"
m.add_vector(
url, layer_name="Countries", fill_colors=["red", "yellow", "green", "orange"]
)
m
import leafmap
m = leafmap.Map(toolbar_control=False, layers_control=True)
m.add_osm_from_geocode("New York City", layer_name="NYC")
m
m = leafmap.Map(toolbar_control=False, layers_control=True)
m.add_osm_from_geocode("Chicago, Illinois", layer_name="Chicago, IL")
m
OSM from place¶
Add OSM entities within boundaries of geocodable place(s) to the map.
Show OSM feature tags. https://wiki.openstreetmap.org/wiki/Map_features
# leafmap.osm_tags_list()
OSM from address¶
m = leafmap.Map(toolbar_control=False, layers_control=True)
m.add_osm_from_address(
address="New York City", tags={"amenity": "bar"}, dist=1500, layer_name="NYC bars"
)
m
m = leafmap.Map(toolbar_control=False, layers_control=True)
m.add_osm_from_address(
address="New York City",
tags={"landuse": ["retail", "commercial"], "building": True},
dist=1000,
layer_name="NYC buildings",
)
m
OSM from bbox¶
m = leafmap.Map(toolbar_control=False, layers_control=True)
north, south, east, west = 40.7551, 40.7454, -73.9738, -73.9965
m.add_osm_from_bbox(
north, south, east, west, tags={"amenity": "bar"}, layer_name="NYC bars"
)
m
OSM from point¶
Add OSM entities within some distance N, S, E, W of a point to the map.
m = leafmap.Map(
center=[46.7808, -96.0156], zoom=12, toolbar_control=False, layers_control=True
)
m.add_osm_from_point(
center_point=(46.7808, -96.0156),
tags={"natural": "water"},
dist=10000,
layer_name="Lakes",
)
m
m = leafmap.Map(
center=[39.9170, 116.3908], zoom=15, toolbar_control=False, layers_control=True
)
m.add_osm_from_point(
center_point=(39.9170, 116.3908),
tags={"building": True, "natural": "water"},
dist=1000,
layer_name="Beijing",
)
m
OSM from view¶
Add OSM entities within the current map view to the map.
m = leafmap.Map(toolbar_control=False, layers_control=True)
m.set_center(-73.9854, 40.7500, 16)
m
m.add_osm_from_view(tags={"amenity": "bar", "building": True}, layer_name="New York")
Create a GeoPandas GeoDataFrame from place.
gdf = leafmap.osm_gdf_from_place("New York City", tags={"amenity": "bar"})
gdf
Use WhiteboxTools¶
Use the built-in toolbox to perform geospatial analysis. For example, you can perform depression filling using the sample DEM dataset downloaded in the above step.
import os
import leafmap
import urllib.request
Download a sample DEM dataset.
url = "https://github.com/opengeos/whitebox-python/raw/master/whitebox/testdata/DEM.tif"
urllib.request.urlretrieve(url, "dem.tif")
m = leafmap.Map()
m
Display the toolbox using the default mode.
leafmap.whiteboxgui()
Display the toolbox using the collapsible tree mode. Note that the tree mode does not support Google Colab.
leafmap.whiteboxgui(tree=True)
Perform geospatial analysis using the whitebox package.
import os
import whitebox
wbt = whitebox.WhiteboxTools()
wbt.verbose = False
data_dir = os.getcwd()
wbt.set_working_dir(data_dir)
wbt.feature_preserving_smoothing("dem.tif", "smoothed.tif", filter=9)
wbt.breach_depressions("smoothed.tif", "breached.tif")
wbt.d_inf_flow_accumulation("breached.tif", "flow_accum.tif")
import matplotlib.pyplot as plt
import imageio
%matplotlib inline
original = imageio.imread(os.path.join(data_dir, "dem.tif"))
smoothed = imageio.imread(os.path.join(data_dir, "smoothed.tif"))
breached = imageio.imread(os.path.join(data_dir, "breached.tif"))
flow_accum = imageio.imread(os.path.join(data_dir, "flow_accum.tif"))
fig = plt.figure(figsize=(16, 11))
ax1 = fig.add_subplot(2, 2, 1)
ax1.set_title("Original DEM")
plt.imshow(original)
ax2 = fig.add_subplot(2, 2, 2)
ax2.set_title("Smoothed DEM")
plt.imshow(smoothed)
ax3 = fig.add_subplot(2, 2, 3)
ax3.set_title("Breached DEM")
plt.imshow(breached)
ax4 = fig.add_subplot(2, 2, 4)
ax4.set_title("Flow Accumulation")
plt.imshow(flow_accum)
plt.show()
Create basemap gallery¶
import leafmap
for basemap in leafmap.basemaps:
print(basemap)
layers = list(leafmap.basemaps.keys())[17:117]
leafmap.linked_maps(rows=20, cols=5, height="200px", layers=layers, labels=layers)
Create linked map¶
import leafmap
leafmap.basemaps.keys()
layers = ["ROADMAP", "HYBRID"]
leafmap.linked_maps(rows=1, cols=2, height="400px", layers=layers)
layers = ["Esri.WorldTopoMap", "OpenTopoMap"]
leafmap.linked_maps(rows=1, cols=2, height="400px", layers=layers)
Create a 2 * 2 linked map to visualize land cover change. Specify the center
and zoom
parameters to change the default map center and zoom level.
layers = [str(f"NLCD {year} CONUS Land Cover") for year in [2001, 2006, 2011, 2016]]
labels = [str(f"NLCD {year}") for year in [2001, 2006, 2011, 2016]]
leafmap.linked_maps(
rows=2,
cols=2,
height="300px",
layers=layers,
labels=labels,
center=[36.1, -115.2],
zoom=9,
)
Create split-panel map¶
Create a split-panel map by specifying the left_layer
and right_layer
, which can be chosen from the basemap names, or any custom XYZ tile layer.
import leafmap
leafmap.split_map(left_layer="ROADMAP", right_layer="HYBRID")
Hide the zoom control from the map.
leafmap.split_map(
left_layer="Esri.WorldTopoMap", right_layer="OpenTopoMap", zoom_control=False
)
Add labels to the map and change the default map center and zoom level.
leafmap.split_map(
left_layer="NLCD 2001 CONUS Land Cover",
right_layer="NLCD 2019 CONUS Land Cover",
left_label="2001",
right_label="2019",
label_position="bottom",
center=[36.1, -114.9],
zoom=10,
)
Create heat map¶
Specify the file path to the CSV. It can either be a file locally or on the Internet.
import leafmap
m = leafmap.Map(layers_control=True)
in_csv = "https://raw.githubusercontent.com/opengeos/leafmap/master/examples/data/world_cities.csv"
m.add_heatmap(
in_csv,
latitude="latitude",
longitude="longitude",
value="pop_max",
name="Heat map",
radius=20,
)
m
Use the folium plotting backend.
from leafmap import foliumap
m = foliumap.Map()
in_csv = "https://raw.githubusercontent.com/opengeos/leafmap/master/examples/data/world_cities.csv"
m.add_heatmap(
in_csv,
latitude="latitude",
longitude="longitude",
value="pop_max",
name="Heat map",
radius=20,
)
colors = ["blue", "lime", "red"]
m.add_colorbar(colors=colors, vmin=0, vmax=10000)
m.add_title("World Population Heat Map", font_size="20px", align="center")
m
Save map to HTML¶
import leafmap
m = leafmap.Map()
m.add_basemap("Esri.NatGeoWorldMap")
m
Specify the output HTML file name to save the map as a web page.
m.to_html("mymap.html")
If the output HTML file name is not provided, the function will return a string containing contain the source code of the HTML file.
html = m.to_html()
# print(html)
Use kepler plotting backend¶
import leafmap.kepler as leafmap
Create an interactive map¶
Create an interactive map. You can specify various parameters to initialize the map, such as center
, zoom
, height
, and widescreen
.
m = leafmap.Map(center=[40, -100], zoom=2, height=600, widescreen=False)
m
If you encounter an error saying Error displaying widget: model not found
when trying to display the map, you can use m.static_map()
as a workaround until this kepler.gl bug has been resolved.
# m.static_map(width=1280, height=600)
Add CSV¶
Add a CSV to the map. If you have a map config file, you can directly apply config to the map.
m = leafmap.Map(center=[37.7621, -122.4143], zoom=12)
in_csv = "https://raw.githubusercontent.com/opengeos/leafmap/master/examples/data/hex_data.csv"
config = "https://raw.githubusercontent.com/opengeos/leafmap/master/examples/data/hex_config.json"
m.add_csv(in_csv, layer_name="hex_data", config=config)
m
m.static_map(width=1280, height=600)
Save map config¶
Save the map configuration as a JSON file.
m.save_config("cache/config.json")
Save map as html¶
Save the map to an interactive html.
m.to_html(outfile="cache/kepler_hex.html")
Add GeoJONS¶
Add a GeoJSON with US state boundaries to the map.
m = leafmap.Map(center=[50, -110], zoom=2)
polygons = "https://raw.githubusercontent.com/opengeos/leafmap/master/examples/data/us_states.json"
m.add_geojson(polygons, layer_name="Countries")
m
m.static_map(width=1280, height=600)
Add shapefile¶
Add a shapefile to the map.
m = leafmap.Map(center=[20, 0], zoom=1)
in_shp = "https://github.com/opengeos/leafmap/raw/master/examples/data/countries.zip"
m.add_shp(in_shp, "Countries")
m
m.static_map(width=1280, height=600)
Add GeoDataFrame¶
Add a GeoPandas GeoDataFrame to the map.
import geopandas as gpd
gdf = gpd.read_file(
"https://raw.githubusercontent.com/opengeos/leafmap/master/examples/data/world_cities.geojson"
)
gdf
m = leafmap.Map(center=[20, 0], zoom=1)
m.add_gdf(gdf, "World cities")
m
# m.static_map(width=1280, height=600)
Use planet imagery¶
First, you need to sign up a Planet account and get an API key. See https://developers.planet.com/quickstart/apis. Uncomment the following line to pass in your API key.
import os
import leafmap
if os.environ.get("PLANET_API_KEY") is None:
os.environ["PLANET_API_KEY"] = "your-api-key"
quarterly_tiles = leafmap.planet_quarterly_tiles()
for tile in quarterly_tiles:
print(tile)
monthly_tiles = leafmap.planet_monthly_tiles()
for tile in monthly_tiles:
print(tile)
Add a Planet monthly mosaic by specifying year and month.
m = leafmap.Map()
m.add_planet_by_month(year=2020, month=8)
m
Add a Planet quarterly mosaic by specifying year and quarter.
m = leafmap.Map()
m.add_planet_by_quarter(year=2019, quarter=2)
m
Use timeseries inspector¶
import os
import leafmap
if os.environ.get("PLANET_API_KEY") is None:
os.environ["PLANET_API_KEY"] = "your-api-key"
tiles = leafmap.planet_tiles()
leafmap.ts_inspector(tiles, center=[40, -100], zoom=4)
Use time slider¶
Use the time slider to visualize Planet quarterly mosaic.
import os
import leafmap
if os.environ.get("PLANET_API_KEY") is None:
os.environ["PLANET_API_KEY"] = "your-api-key"
Specify the map center and zoom level.
m = leafmap.Map(center=[38.2659, -103.2447], zoom=13)
m
Use the time slider to visualize Planet quarterly mosaic.
m = leafmap.Map()
layers_dict = leafmap.planet_quarterly_tiles()
m.add_time_slider(layers_dict, time_interval=1)
m
Use the time slider to visualize basemaps.
m = leafmap.Map()
m.clear_layers()
layers_dict = leafmap.basemap_xyz_tiles()
m.add_time_slider(layers_dict, time_interval=1)
m