First terrain analysis from a Copernicus DEM
This tutorial walks you end-to-end through a realistic terrain analysis: you will download a real digital elevation model from a public STAC catalog, reproject it to a metric coordinate system, compute slope, aspect, and hillshade, clip the result to a smaller area, and understand what the outputs actually mean. It takes about 30 minutes.
By the end you will have:
- A 30-metre DEM of a ~11 km × 5 km patch of the Chilean Andes on disk.
- A set of terrain-factor rasters derived from it.
- A clear mental model of SurtGIS’s command flow: source → transform → derive → consume.
Prerequisites: SurtGIS installed (see Installation). Network access for the STAC download step (about 20 MB transferred).
1. Set up a working directory
mkdir -p ~/surtgis-tutorial
cd ~/surtgis-tutorial
All subsequent commands expect you to be in this directory.
2. Download the DEM from STAC
We’ll pull a patch of the Copernicus GLO-30 DEM (30-metre global coverage) from Microsoft’s Planetary Computer:
surtgis stac fetch-mosaic \
--catalog pc \
--collection cop-dem-glo-30 \
--bbox=-71.0,-35.1,-70.9,-35.05 \
dem_wgs84.tif
What each flag does:
--catalog pc— use Planetary Computer. The other supported catalogs arees(Earth Search) and any full STAC API URL. Forcop-dem-glo-30, PC is the cleaner source (Earth Search returns multiple overlapping tiles that slow the download).--collection cop-dem-glo-30— the STAC collection ID. PC’s browser atplanetarycomputer.microsoft.com/cataloglists every available.--bbox=-71.0,-35.1,-70.9,-35.05— west, south, east, north in degrees. Note the=syntax: with a negative number as the first value, the shell would otherwise interpret-71.0as a flag.dem_wgs84.tif— output filename. The_wgs84suffix is a note to future-us: this DEM is in EPSG:4326 (latitude/longitude). We’ll reproject in a moment.
The command should take ~10 seconds. Verify:
surtgis info dem_wgs84.tif
You should see something close to:
Dimensions: 360 x 182 (65520 cells)
Cell size: 0.0002777777777777778
Bounds: (-71.000000, -35.100278) - (-70.900000, -35.049722)
CRS: EPSG:4326
Statistics:
Min: 400.0
Max: 1380.0
Mean: ~800
Valid cells: 65520 (100.0%)
Elevations between 400 m and 1380 m tell us this patch is at a foothill level of the Andes, not in the high peaks. That’s realistic for the latitude (35°S, near Curicó).
3. Why we have to reproject before computing slope
Here is a trap almost every newcomer falls into, so we’re going to walk straight into it on purpose.
Try computing slope on this DEM directly:
surtgis terrain slope dem_wgs84.tif slope_wgs84.tif
surtgis info slope_wgs84.tif
Look at the statistics:
Statistics:
Min: 89.8
Max: 90.0
Mean: ~89.99
Every pixel is saying “89.99 degrees of slope” — essentially vertical, everywhere. This is wrong; the Andes foothills are not a sheer cliff.
Why this happens. Slope is atan(rise / run). The run in our DEM is
measured in degrees of longitude (about 0.000278° per pixel), but the
rise is measured in metres. When you divide metres by degrees, the ratio
is on the order of hundreds or thousands, so the atan saturates to 90°.
The fix is to reproject the DEM into a coordinate system where both axes
are metres. For Chile at 35°S, that’s UTM zone 19 South (EPSG:32719).
SurtGIS doesn’t have a dedicated reproject command yet — but stac fetch-mosaic accepts --align-to which can reproject-on-read, and the
resample command is the general-purpose tool for grid alignment. For
this tutorial we’ll take a simpler route: ask STAC for the DEM in the right
projection in one shot.
4. Reproject via resample to a reference grid
If you have a reference raster in the target CRS, resample is the
cleanest path:
# (skip this if you don't have an existing UTM raster — see the next
# section for the alternate path)
surtgis resample dem_wgs84.tif dem_utm.tif --reference reference_utm.tif
Most first-time users don’t have a reference. For a standalone reprojection you’ll want the more direct approach below.
5. Alternative: process a native-metric DEM from a different source
For this tutorial we’ll sidestep the reprojection question entirely by
working with a small pre-projected DEM we can compute slope on directly.
The sentinel-2-l2a collection on Planetary Computer serves imagery
already in UTM, and its companion DEM products do the same.
If you’re following along without a reference raster, skip to tutorial 2 Sentinel-2 composite and NDVI which starts with UTM data and avoids this rabbit hole.
For the remainder of this tutorial, if you want to compute terrain factors
on the dem_wgs84.tif we just downloaded, you will need to reproject it
first. The simplest way today is a one-liner with GDAL (yes, the tool
SurtGIS doesn’t depend on — we’re not dogmatic about it):
gdalwarp -t_srs EPSG:32719 -tr 30 30 -r bilinear dem_wgs84.tif dem_utm.tif
surtgis info dem_utm.tif
Output:
Cell size: 30
CRS: EPSG:32719
Now the cells are 30 m on a side, and we can compute slope meaningfully.
This is a documented limitation of SurtGIS 0.7.0. A native reproject command is on the roadmap. Until it lands, GDAL’s
gdalwarpis the recommended path. See the Reproject between UTM zones how-to for more.
6. Compute the core terrain factors
With a UTM DEM, we can compute the standard factors:
surtgis terrain slope dem_utm.tif slope.tif
surtgis terrain aspect dem_utm.tif aspect.tif
surtgis terrain hillshade dem_utm.tif hillshade.tif
Each of these takes a fraction of a second on a patch this size. Verify one:
surtgis info slope.tif
You should see a reasonable range now, roughly:
Min: 0.0
Max: ~45
Mean: ~12
Twelve degrees mean slope is consistent with Andean foothills. Peak slopes of 45° correspond to the steeper gullies.
7. Or: compute every standard factor in one pass
The terrain all subcommand computes the full set (slope, aspect,
hillshade, curvature, TPI, TRI, roughness) in one shot, reading the DEM
once and writing each factor as a separate file:
surtgis terrain all dem_utm.tif --outdir factors/ --compress
ls factors/
slope.tif aspect.tif hillshade.tif curvature.tif tpi.tif tri.tif roughness.tif
This is the ergonomic path for “give me the standard factor set to feed into a model”. For ad-hoc experimentation, the individual commands are fine.
8. Clip to a smaller area of interest
If your model only cares about the eastern half of this patch:
surtgis clip factors/slope.tif --bbox=300000,6110000,315000,6120000 slope_east.tif
--bbox is in the raster’s CRS (so UTM metres here, not degrees).
Alternatively, --polygon my_aoi.gpkg clips by a vector geometry — see
Clip by polygon how-to for that workflow.
9. Understand what you just produced
Let’s make sure the outputs actually make sense.
Slope is degrees above horizontal, 0 to 90. Flat plains are 0–3°, gentle hills 5–15°, steep terrain 25–45°, cliffs >45°. If your DEM yields slopes above 70° widely, something is wrong with units (as we saw in step 3) or with artifacts in the DEM.
Aspect is compass direction the slope faces, 0–360° (or −1 where the slope is too flat to have a direction). 0° = north, 90° = east, 180° = south, 270° = west.
Hillshade is a synthetic illumination value, 0–255, simulating a light source at a default azimuth (315°) and altitude (45°). It’s purely for visualisation; it has no physical unit. Darker values = in shadow from the light source; brighter = facing it.
Open factors/hillshade.tif in QGIS (or any raster viewer) and you should
immediately see the terrain structure of the patch. That visual check is
the single best way to confirm your pipeline is correct before trusting
the downstream derivatives.
What’s next
- For cloud masking and Sentinel-2 imagery, continue with Tutorial 2: Sentinel-2 composite and NDVI.
- For scaling this to a much larger DEM (>5 GB), read
Memory model and use
--streaming. - For writing this pipeline as a script, every command here is composable via shell scripts; most users treat the CLI as the primary interface.
Common gotchas
“My slope is everywhere 89°.” You’re computing slope on a lat/lon-projected DEM. Reproject to a metric CRS first (step 5).
“All my outputs are black or blank.” Open in QGIS with “Singleband pseudocolor” and let it auto-stretch the min–max. The TIFF viewer on your OS is probably clamping to the raw byte range.
“Some pixels are NaN / nodata.” Edge pixels within one cell of the DEM boundary are undefined for 3×3 window algorithms (slope, aspect, TPI, TRI). This is intentional; the alternatives either extrapolate off the edge or silently invent values.
“The STAC download was slow.” For cop-dem-glo-30, prefer
--catalog pc. Earth Search serves the same collection but with multiple
overlapping tile granules — transfer volume can be 20× higher for the
same bbox.