5. Visualizing Geospatial Data#
5.1. Introduction#
5.2. Technical requirements#
conda create -n gee python
conda activate gee
conda install -c conda-forge mamba
mamba install -c conda-forge pygis
jupyter lab
# %pip install pygis
import ee
import geemap
geemap.ee_initialize()
5.3. Using the plotting tool#
Map = geemap.Map(center=[40, -100], zoom=4)
landsat7 = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(
['B1', 'B2', 'B3', 'B4', 'B5', 'B7']
)
landsat_vis = {'bands': ['B4', 'B3', 'B2'], 'gamma': 1.4}
Map.addLayer(landsat7, landsat_vis, "Landsat")
hyperion = ee.ImageCollection('EO1/HYPERION').filter(
ee.Filter.date('2016-01-01', '2017-03-01')
)
hyperion_vis = {
'min': 1000.0,
'max': 14000.0,
'gamma': 2.5,
}
Map.addLayer(hyperion, hyperion_vis, 'Hyperion')
Map
Map.set_plot_options(add_marker_cluster=True, overlay=True)
5.4. Changing layer opacity#
Map = geemap.Map(center=(40, -100), zoom=4)
dem = ee.Image('USGS/SRTMGL1_003')
states = ee.FeatureCollection("TIGER/2018/States")
vis_params = {
'min': 0,
'max': 4000,
'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],
}
Map.addLayer(dem, vis_params, 'SRTM DEM', True, 1)
Map.addLayer(states, {}, "US States", True)
Map
5.5. Visualizing raster data#
5.5.1. Single-band images#
Map = geemap.Map(center=[12, 69], zoom=3)
dem = ee.Image('USGS/SRTMGL1_003')
vis_params = {
'min': 0,
'max': 4000,
'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],
}
Map.addLayer(dem, vis_params, 'SRTM DEM')
Map
vis_params = {
'bands': ['elevation'],
'palette': ['333399', ' 00b2b2', ' 99eb85', ' ccbe7d', ' 997c76', ' ffffff'],
'min': 0.0,
'max': 6000.0,
'opacity': 1.0,
'gamma': 1.0,
}
5.5.2. Multi-band images#
Map = geemap.Map()
landsat7 = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003')
vis_params = {
'min': 20,
'max': 200,
'gamma': 2,
'bands': ['B4', 'B3', 'B2'],
}
Map.addLayer(landsat7, vis_params, 'Landsat 7')
Map
5.6. Visualizing vector data#
Map = geemap.Map()
states = ee.FeatureCollection("TIGER/2018/States")
Map.addLayer(states, {}, "US States")
Map
vis_params = {
'color': 'ff0000ff',
'width': 2,
'lineType': 'solid',
'fillColor': '00000000',
}
Map = geemap.Map(center=[40, -100], zoom=4)
states = ee.FeatureCollection("TIGER/2018/States")
Map.addLayer(states.style(**vis_params), {}, "US States")
Map
5.7. Creating legends#
5.7.1. Built-in legends#
from geemap.legends import builtin_legends
for legend in builtin_legends:
print(legend)
Map.add_legend(builtin_legend='NLCD')
Map = geemap.Map(center=[40, -100], zoom=4)
Map.add_basemap('HYBRID')
nlcd = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2019')
landcover = nlcd.select('landcover')
Map.addLayer(landcover, {}, 'NLCD Land Cover 2019')
Map.add_legend(
title="NLCD Land Cover Classification", builtin_legend='NLCD', height='465px'
)
Map
5.7.2. Custom legends#
Map = geemap.Map(add_google_map=False)
labels = ['One', 'Two', 'Three', 'Four', 'etc']
# colors can be defined using either hex code or RGB (0-255, 0-255, 0-255)
colors = ['#8DD3C7', '#FFFFB3', '#BEBADA', '#FB8072', '#80B1D3']
# legend_colors = [(255, 0, 0), (127, 255, 0), (127, 18, 25), (36, 70, 180), (96, 68 123)]
Map.add_legend(
labels=labels, colors=colors, position='bottomright'
)
Map
Map = geemap.Map(center=[40, -100], zoom=4)
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',
}
nlcd = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2019')
landcover = nlcd.select('landcover')
Map.addLayer(landcover, {}, 'NLCD Land Cover 2019')
Map.add_legend(title="NLCD Land Cover Classification", legend_dict=legend_dict)
Map
5.7.3. Earth Engine class table#
Map = geemap.Map()
dataset = ee.ImageCollection("ESA/WorldCover/v100").first()
Map.addLayer(dataset, {'bands': ['Map']}, "Landcover")
ee_class_table = """
Value Color Description
10 006400 Trees
20 ffbb22 Shrubland
30 ffff4c Grassland
40 f096ff Cropland
50 fa0000 Built-up
60 b4b4b4 Barren / sparse vegetation
70 f0f0f0 Snow and ice
80 0064c8 Open water
90 0096a0 Herbaceous wetland
95 00cf75 Mangroves
100 fae6a0 Moss and lichen
"""
legend_dict = geemap.legend_from_ee(ee_class_table)
Map.add_legend(title="ESA Land Cover", legend_dict=legend_dict)
Map
5.8. Creating color bars#
Map = geemap.Map()
dem = ee.Image('USGS/SRTMGL1_003')
vis_params = {
'min': 0,
'max': 4000,
'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],
}
Map.addLayer(dem, vis_params, 'SRTM DEM')
Map
Map.add_colorbar(vis_params, label="Elevation (m)", layer_name="SRTM DEM")
Map
Map.add_colorbar(
vis_params, label="Elevation (m)", layer_name="SRTM DEM", orientation="vertical"
)
Map.add_colorbar(
vis_params,
label="Elevation (m)",
layer_name="SRTM DEM",
orientation="vertical",
transparent_bg=True,
)
5.9. Displaying labels#
Map = geemap.Map(center=[40, -100], zoom=4, add_google_map=False)
states = ee.FeatureCollection("TIGER/2018/States")
style = {'color': 'black', 'fillColor': "00000000"}
Map.addLayer(states.style(**style), {}, "US States")
Map
Map.add_labels(
data=states,
column="STUSPS",
font_size="12pt",
font_color="blue",
font_family="arial",
font_weight="bold",
draggable=True,
)
Map.remove_labels()
centroids = geemap.vector_centroids(states)
df = geemap.ee_to_df(centroids)
df
Map.add_labels(
data=df,
column="STUSPS",
font_size="12pt",
font_color="blue",
font_family="arial",
font_weight="bold",
x='longitude',
y='latitude',
)
Map
5.10. Image overlay#
Map = geemap.Map(center=(25, -115), zoom=5)
url = 'https://i.imgur.com/06Q1fSz.png'
image = geemap.ImageOverlay(url=url, bounds=((13, -130), (32, -100)))
Map.add_layer(image)
Map
image.url = 'https://i.imgur.com/U0axit9.png'
Map
url = 'https://i.imgur.com/06Q1fSz.png'
filename = 'hurricane.png'
geemap.download_file(url, filename)
Map = geemap.Map(center=(25, -115), zoom=5)
image = geemap.ImageOverlay(url=filename, bounds=((13, -130), (32, -100)))
Map.add_layer(image)
Map
5.11. Video overlay#
Map = geemap.Map(center=(25, -115), zoom=5)
url = 'https://labs.mapbox.com/bites/00188/patricia_nasa.webm'
bounds = ((13, -130), (32, -100))
Map.video_overlay(url, bounds)
Map
5.12. Split-panel maps#
Map = geemap.Map()
Map.split_map(left_layer='HYBRID', right_layer='TERRAIN')
Map
list(geemap.basemaps.keys())
Map = geemap.Map(center=(40, -100), zoom=4, height=600)
nlcd_2001 = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2001').select('landcover')
nlcd_2019 = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2019').select('landcover')
left_layer = geemap.ee_tile_layer(nlcd_2001, {}, 'NLCD 2001')
right_layer = geemap.ee_tile_layer(nlcd_2019, {}, 'NLCD 2019')
Map.split_map(left_layer, right_layer, add_close_button=True)
Map
5.13. Linked maps#
image = (
ee.ImageCollection('COPERNICUS/S2')
.filterDate('2018-09-01', '2018-09-30')
.map(lambda img: img.divide(10000))
.median()
)
vis_params = [
{'bands': ['B4', 'B3', 'B2'], 'min': 0, 'max': 0.3, 'gamma': 1.3},
{'bands': ['B8', 'B11', 'B4'], 'min': 0, 'max': 0.3, 'gamma': 1.3},
{'bands': ['B8', 'B4', 'B3'], 'min': 0, 'max': 0.3, 'gamma': 1.3},
{'bands': ['B12', 'B12', 'B4'], 'min': 0, 'max': 0.3, 'gamma': 1.3},
]
labels = [
'Natural Color (B4/B3/B2)',
'Land/Water (B8/B11/B4)',
'Color Infrared (B8/B4/B3)',
'Vegetation (B12/B11/B4)',
]
geemap.linked_maps(
rows=2,
cols=2,
height="300px",
center=[38.4151, 21.2712],
zoom=12,
ee_objects=[image],
vis_params=vis_params,
labels=labels,
label_position="topright",
)
5.14. Timeseries inspector#
5.14.1. Visualizing image collections#
Map = geemap.Map(center=[40, -100], zoom=4)
collection = ee.ImageCollection('USGS/NLCD_RELEASES/2019_REL/NLCD').select('landcover')
vis_params = {'bands': ['landcover']}
years = collection.aggregate_array('system:index').getInfo()
years
Map.ts_inspector(
left_ts=collection,
right_ts=collection,
left_names=years,
right_names=years,
left_vis=vis_params,
right_vis=vis_params,
width='80px',
)
Map
5.14.2. Visualizing planet.com imagery#
import os
os.environ["PLANET_API_KEY"] = "your-api-key"
monthly_tiles = geemap.planet_monthly_tiles()
geemap.ts_inspector(monthly_tiles)
quarterly_tiles = geemap.planet_quarterly_tiles()
geemap.ts_inspector(quarterly_tiles)
tiles = geemap.planet_tiles()
geemap.ts_inspector(tiles)
Map = geemap.Map()
Map
5.15. Time slider#
5.15.1. Visualizing vegetation data#
Map = geemap.Map()
collection = (
ee.ImageCollection('MODIS/MCD43A4_006_NDVI')
.filter(ee.Filter.date('2018-06-01', '2018-07-01'))
.select("NDVI")
)
vis_params = {
'min': 0.0,
'max': 1.0,
'palette': 'ndvi',
}
Map.add_time_slider(collection, vis_params, time_interval=2)
Map
5.15.2. Visualizing weather data#
Map = geemap.Map()
collection = (
ee.ImageCollection('NOAA/GFS0P25')
.filterDate('2018-12-22', '2018-12-23')
.limit(24)
.select('temperature_2m_above_ground')
)
vis_params = {
'min': -40.0,
'max': 35.0,
'palette': ['blue', 'purple', 'cyan', 'green', 'yellow', 'red'],
}
labels = [str(n).zfill(2) + ":00" for n in range(0, 24)]
Map.add_time_slider(collection, vis_params, labels=labels, time_interval=1, opacity=0.8)
Map
5.15.3. Visualizing Sentinel-2 imagery#
Map = geemap.Map(center=[37.75, -122.45], zoom=12)
collection = (
ee.ImageCollection('COPERNICUS/S2_SR')
.filterBounds(ee.Geometry.Point([-122.45, 37.75]))
.filterMetadata('CLOUDY_PIXEL_PERCENTAGE', 'less_than', 10)
)
vis_params = {"min": 0, "max": 4000, "bands": ["B8", "B4", "B3"]}
Map.add_time_slider(collection, vis_params)
Map
5.16. Shaded relief maps#
import geemap.colormaps as cm
Map = geemap.Map()
dem = ee.Image("USGS/SRTMGL1_003")
hillshade = ee.Terrain.hillshade(dem)
vis = {'min': 0, 'max': 6000, 'palette': cm.palettes.terrain}
blend = geemap.blend(top_layer=dem, top_vis=vis)
Map.addLayer(hillshade, {}, 'Hillshade')
Map.addLayer(blend, {}, 'Shaded relief')
Map.add_colorbar(vis, label='Elevation (m)')
Map.setCenter(91.4206, 27.3225, zoom=9)
Map
left_layer = geemap.ee_tile_layer(blend, {}, "Shaded relief")
right_layer = geemap.ee_tile_layer(hillshade, {}, "Hillshade")
Map.split_map(left_layer, right_layer)
Map = geemap.Map()
nlcd = ee.Image("USGS/NLCD_RELEASES/2019_REL/NLCD/2019").select('landcover')
nlcd_vis = {'bands': ['landcover']}
blend = geemap.blend(nlcd, dem, top_vis=nlcd_vis, expression='a*b')
Map.addLayer(blend, {}, 'Blend NLCD')
Map.add_legend(builtin_legend='NLCD', title='NLCD Land Cover')
Map.setCenter(-118.1310, 35.6816, 10)
Map
5.17. Elevation contours#
import geemap.colormaps as cm
Map = geemap.Map()
image = ee.Image("USGS/SRTMGL1_003")
hillshade = ee.Terrain.hillshade(image)
Map.addLayer(hillshade, {}, "Hillshade")
Map
vis_params = {'min': 0, "max": 5000, "palette": cm.palettes.dem}
Map.addLayer(image, vis_params, "dem", True, 0.5)
Map.add_colorbar(vis_params, label='Elevation (m)')
contours = geemap.create_contours(image, 0, 5000, 100, region=None)
Map.addLayer(contours, {'palette': 'black'}, 'contours')
Map.setCenter(-119.3678, 37.1671, 12)
5.18. Visualizing NetCDF data#
url = 'https://github.com/gee-community/geemap/raw/master/examples/data/wind_global.nc'
filename = 'wind_global.nc'
geemap.download_file(url, output=filename)
data = geemap.read_netcdf(filename)
data
Map = geemap.Map(layers_control=True)
Map.add_netcdf(
filename,
variables=['v_wind'],
palette='coolwarm',
shift_lon=True,
layer_name='v_wind',
)
geojson = 'https://github.com/gee-community/geemap/raw/master/examples/data/countries.geojson'
Map.add_geojson(geojson, layer_name='Countries')
Map
Map = geemap.Map(layers_control=True)
Map.add_basemap('CartoDB.DarkMatter')
Map.add_velocity(filename, zonal_speed='u_wind', meridional_speed='v_wind')
Map
5.19. Visualizing LiDAR data#
%pip install "geemap[lidar]"
import os
url = (
'https://drive.google.com/file/d/1H_X1190vL63BoFYa_cVBDxtIa8rG-Usb/view?usp=sharing'
)
filename = 'madison.las'
if not os.path.exists(filename):
geemap.download_file(url, 'madison.zip', unzip=True)
las = geemap.read_lidar(filename)
las.header
las.header.point_count
list(las.point_format.dimension_names)
las.X
las.intensity
geemap.view_lidar(filename, cmap='terrain', backend='pyvista', background='gray')
geemap.view_lidar(filename, backend='ipygany', background='white')
5.20. Visualizing raster data in 3D#
url = 'https://github.com/giswqs/data/raw/main/raster/srtm90.tif'
image = 'srtm90.tif'
if not os.path.exists(image):
geemap.download_file(url, image)
geemap.plot_raster(image, cmap='terrain', figsize=(15, 10))
geemap.plot_raster_3d('srtm90.tif', factor=2, cmap='terrain', background='gray')
5.21. Creating choropleth maps#
data = geemap.examples.datasets.countries_geojson
Map = geemap.Map()
Map.add_data(
data, column='POP_EST', scheme='Quantiles', cmap='Blues', legend_title='Population'
)
Map
Map = geemap.Map()
Map.add_data(
data,
column='POP_EST',
scheme='EqualInterval',
cmap='Blues',
legend_title='Population',
)
Map
Map = geemap.Map()
Map.add_data(
data,
column='POP_EST',
scheme='FisherJenks',
cmap='Blues',
legend_title='Population',
)
Map
Map = geemap.Map()
Map.add_data(
data,
column='POP_EST',
scheme='JenksCaspall',
cmap='Blues',
legend_title='Population',
)
Map