Map of Biodiversity Importance, NatureServe
Demonstration of generating and serving static raster tiles with GDAL using Map of Biodiversity Importance (MOBI) data from NatureServe, (2022) https://www.natureserve.org/map-biodiversity-importance, original data files from https://geohub-natureserve.opendata.arcgis.com/search?q=mobiData
Demonstration of generating and serving static raster tiles with GDAL using Map of Biodiversity Importance (MOBI) data from NatureServe, (2022)
- Overview: https://www.natureserve.org/map-biodiversity-importance
- Data: https://geohub-natureserve.opendata.arcgis.com/search?q=mobi
Example Interactive Maps
Zoomable maps rendered with static tiles (via map.py):
https://data.source.coop/cboettig/mobi/tiles/grey/species-richness-all/{z}/{x}/{y}.png
https://data.source.coop/cboettig/mobi/tiles/red/species-richness-all/{z}/{x}/{y}.png
https://data.source.coop/cboettig/mobi/tiles/green/range-size-rarity-all/{z}/{x}/{y}.png
Creating a Static Tile Server
We recommend using the latest release of GDAL, built with support for python for these examples. It can easily be installed with pip, e.g.:
pip install -U --find-links https://girder.github.io/large_image_wheels GDAL
Standard raster formats including cloud-optimized geotiffs provide an excellent format for analysis-ready geospatial data, where precise quantitative values along a geospatial grid can be encoded digitally.
To provide efficient visualization on interactive, zoomable maps however, it is more common to use a more lightweight approach that divides a potentially very large single tiff file into smaller PNG tiles, optimized for visual display in a web browser rather than for computational analysis on pixel values. By pre-computing a complete layer of tiles at each zoom level, client-side javascript maps such as leaflet can quickly and smoothly request new tiles as the user zooms and pans around the map.
A static tileserver simply pre-computes these tiles and serves them through a high bandwidth storage platform like Source.coop.
To create png tiles, we must first represent our geotiff raster in Byte type, which can mostly easily do in gdal using gdaltranslate
to create a GDAL virtual dataset (VRT):
gdal_translate -of VRT -ot Byte -scale /vsicurl/https://data.source.coop/cboettig/mobi/species-richness-all/SpeciesRichness_All.tif temp.vrt
From this VRT, we can now create a whole suite of tiles. Here we indicate the --xyz
format (used by leaflet etc), we --exclude
any tiles that contain only missing data, and we compute tiles for 10 different zoom levels. Note that each higher zoom level is exponentially larger, which means more files and more space required. This can be computationally intensive but is easily parallelized to multiple processes using the --processes
option. Lastly, we specify a target directory path that will be created to store all the PNGs. these are organized by subfolders {z}/{y}/{x}.png
indicating the zoom and x/y tile positions.
gdal2tiles.py --xyz --zoom=1-10 --exclude --processes=24 temp.vrt tiles/grey/species-richness-all
Color scales
In this example, or geotif consists of a single band of data representing the species richness observed in a pixel (i.e. as an integer between 0 and 32 in this case). The gdal2tiles.py
will by default map those numeric values to a greyscale color ramp. Unlike typical raster images where we can provide mappings from data values to color aesthetics when rendering our maps, remember that map tiles are entirely pre-rendered, so we get only the colors those original png files come with. If we want to add a color ramp, we need to declare that in the VRT before we generate all the png tiles. We can do this with gdaldem
:
gdaldem color-relief -of GTiff temp.vrt color.txt colored-temp.vrt -alpha
Where color.txt
is a text file indicating the band byte value followed by the red, blue, green, and alpha (transparency) values (on a scale of 0 to 255) in the colorscale. Note that we can often generate color.txt
programmatically, e.g. see colormap.R
.
Then we can recreated the tiles
gdal2tiles.py --xyz --zoom=1-10 --exclude --processes=24 colored-temp.vrt tiles/red/species-richness-all
Likewise we can process the other variables. Note that we need to calibrate the colormap appropriately.
gdal_translate -of VRT -ot Byte -scale range-size-rarity-all/RSR_All.tif temp.vrt
gdaldem color-relief -of GTiff temp.vrt color.txt colored-temp.vrt -alpha
gdal2tiles.py --xyz --zoom=1-10 --exclude --processes=24 colored-temp.vrt tiles/green/range-size-rarity-all
Leaflet rendering
Once we have rendered our tiles, we simply need to point our mapping tool to the corresponding URL template. For instance:
import leafmap.foliumap as leafmap
m = leafmap.Map(center=[35, -100], zoom=5)
m.add_basemap("CartoDB.DarkMatter")
m.add_tile_layer(
url="https://minio.carlboettiger.info/shared-data/mobi-tiles/grey/{z}/{x}/{y}.png",
name="Imperiled Species Richness (Greyscale)",
attribution="NatureServe",
opacity=0.99
)
m.to_html("mobi-grey.html")
m
Generates the greyscale interactive map
Changing to the red tiles (and a lighter basemap) we can see the colored version
License
The Map of Biodiversity Data Importance is a data product of NatureServe, cc-by-nc-nd