Skip to content

Elevation

Australia elevation logo

Image caption

Please check out this summary of the basic concepts for Digital Elevation Models (DEM) from Neon. First however is the distinction between DTMs and DSMs. Their figure highlights the main points.

Australia elevation logo

Image caption

Additionally, there are a great many DEM datasets available globally, particularly for the US and Europe. These options are nicely highlighted at this repository.

Goals

What we ideally need is a single tiff tile that provides decent elevation estimates for a given latitude and longitude across all of Australia.

Australia elevation logo

Image caption

We can then simply point to this (large) tiff, and apply an elevation model in Python.

from osgeo import gdal

class ElevationModel:
    def __init__(self, filename, geojson_file):
        self.ds = gdal.Open(filename)

    def get_elevation(self, lon, lat):
        gt = self.ds.GetGeoTransform()
        x = int((lon - gt[0]) / gt[1])
        y = int((lat - gt[3]) / gt[5])

        return self.ds.ReadAsArray(x, y, 1, 1)[0][0]

Which we can then call via:

model = ElevationModel('elevation.tif')

# Let's try Sydney (151.209900, -33.865143)
lon,lat = wombat.datasets.caplatlon['Sydney']

# Calculate elevation
elevation = model.get_elevation(lon, lat)

print(f"Elevation at {lon}, {lat} is {elevation}")
> 6.23

This can then be used and extended to calculate viewsheds, walkability metrics and provide to our property pricing models to name a few.

Sources

ELVIS

One primary source for Australia is the ELVIS data.

Australia elevation logo

ELVIS

This data consists of the following:

  • Combined state and national datasets
  • Generally lidar-derived data
  • Resolutions include: 1m, 2m, 5m, 1 second
  • Complete coverage for NSW, Victoria and Tasminia with partial coverage in other state/territories
  • Bathymetry also provided for surrounding waters

One can access the LiDAR 5 Metre Grid models from GeoScience Australia, though the piecemeal nature of it makes creating a generalised elevation map for each city is challenging. It entails downloading every bounding box region of interest for each city then more backend handling to get what is needed for wombat.

The only government dataset that seems to provides a manageable dataset (fully integrated tile) and achieves out goal is the following:

Which has since been updated (2010) to address several issues in the original dataset.

The 1 second Shuttle Radar Topographic Mission (SRTM) derived smoothed Digital Elevation Model (DEM-S) Version 1.0 is a 1 arc second (~30m) gridded smoothed version of the DEM (ANZCW0703013355). The DEM-S represents ground surface topography, excluding vegetation features, and has been smoothed to reduce noise and improve the representation of surface shape. The dataset was derived from the 1 second Digital Elevation Model Version 1.0 (DSM; ANZCW0703013336) by an adaptive smoothing process that applies more smoothing in flatter areas than hilly areas, and more smoothing in noisier areas than in less noisy areas. This DEM-S supports calculation of local terrain shape attributes such as slope, aspect and curvatures that could not be reliably derived from the unsmoothed DEM because of noise. A full description of the methods is in progress (Gallant et al., in prep) and in the User Guide (Geoscience Australia & CSIRO, 2010). ~Gallant, J. ; Tickle, P.K. ; Wilson, N. ; Dowling, T. ; Read, A. (2010)

Upon downloading this 40GB file, we can check the extent to verify it's coverage:

import matplotlib.pyplot as plt
import geopandas as gpd
import rasterio
from shapely.geometry import shape, box

import wombat

w = wombat.Wombat()

# Path to elevation tif file
tif_file = w.Datasets.elevation_tif_filename

# State and territory boundaries
w.Boundary.load_states_territories()
gdf = w.Boundary.gdf_states_territories

fig,ax = plt.subplots(constrained_layout=True)
gdf.plot(color='white', edgecolor='black',ax=ax)

# Load the TIFF file
src = rasterio.open(tif_file)

# Retrieve the TIFF file's polygon coordinates
left,bottom,right,top = src.bounds

# Create a new GeoDataFrame for the TIFF
tiff_gdf = gpd.GeoDataFrame({'geometry': [box(left,bottom,right,top)]}, 
                            crs=src.crs.to_string())
tiff_gdf = tiff_gdf.to_crs(gdf.crs)

# Plot tiff coverage area over the top of the country boundary
tiff_gdf.plot(ax=ax, facecolor='none', edgecolor='red',linewidth=2)

# Title for the plot
plt.title("Elevation Data Coverage")

# Show the plot
plt.show()

There are however other options which have be explored.

TessaDM

TessaDM provides an API to access elevation data globally.

TessaDM

TessaDEM

The downside is that it is per request and there is no free cap available. From their page "Elevation data were merged and adjusted from multiple sources according to tree height, urbanization and water presence using AW3D30, MERIT DEM, Forest Height, World Settlement Footprint and Global Surface Water". You can download the raw binary files (405GB) though this may take some time. Their team promptly responded to a request for a compressed version (40GB). This was subsequently downloaded over a few days and then the Australian region was extracted.

FABDEM

Lastly, there are some more advanced models coming online such as FABDEM by the University of Bristol. FABDEM (Forest And Buildings removed Copernicus DEM) is a global elevation map that removes building and tree height biases from the Copernicus GLO 30 Digital Elevation Model (DEM). The data is available at 1 arc second grid spacing (approximately 30m at the equator) for the globe.

You can download the entire dataset for the Earth here. For our purposes we only need the tiles for our interested areas. Fortunately in the v1.2 release, the tileset has been provided so those specific tiles for the capitals can be acquired. The tileset for Australis looks as follows:

Australia elevation logo

FABDEM Elevation Tiles (Australia)

The individual tiles that overlap with the major capital cities are as follows:

tile_name file_name zipfile_name
S013E130 S013E130_FABDEM_V1-2.tif S20E130-S-10E140_FABDEM_V1-2.zip
S028E152 S028E152_FABDEM_V1-2.tif S30E150-S-20E160_FABDEM_V1-2.zip
S028E153 S028E153_FABDEM_V1-2.tif S30E150-S-20E160_FABDEM_V1-2.zip
S032E115 S032E115_FABDEM_V1-2.tif S40E110-S-30E120_FABDEM_V1-2.zip
S033E115 S033E115_FABDEM_V1-2.tif S40E110-S-30E120_FABDEM_V1-2.zip
S034E150 S034E150_FABDEM_V1-2.tif S40E150-S-30E160_FABDEM_V1-2.zip
S034E151 S034E151_FABDEM_V1-2.tif S40E150-S-30E160_FABDEM_V1-2.zip
S035E138 S035E138_FABDEM_V1-2.tif S40E130-S-30E140_FABDEM_V1-2.zip
S036E149 S036E149_FABDEM_V1-2.tif S40E140-S-30E150_FABDEM_V1-2.zip
S038E144 S038E144_FABDEM_V1-2.tif S40E140-S-30E150_FABDEM_V1-2.zip
S038E145 S038E145_FABDEM_V1-2.tif S40E140-S-30E150_FABDEM_V1-2.zip
S043E147 S043E147_FABDEM_V1-2.tif S50E140-S-40E150_FABDEM_V1-2.zip

We can then simply loop through these files and download them locally.

import wget
import pandas as pd

# set downloads
output_folder = "/path/to/downloads/"

# download capital city tile info
df = pd.read_csv("FABDEM.csv")

# set base download path
url_base = "https://data.bris.ac.uk/datasets/s5hqmjcdj8yo2ibzi9b4ew3sn"

# loop through each zipfile
for fname in list(set(df['zipfile_name'])):
    url_full = url_base+"/"+fname.replace("-S-","-S")
    wget.download(url_full,output_folder)