10.5 Lab — End-to-End Raster Analysis
Combine reclassification, focal stats, zonal stats, and cost surfaces into a single realistic workflow.
Key takeaways
- Real raster analyses chain the operations you've learned into multi-step pipelines.
- Each step is testable; save intermediates and visualise them to catch bugs early.
- The same pattern applies to conservation planning, utility corridors, agriculture, and disaster response.
Introduction
This lab replicates a realistic conservation-planning workflow. You'll identify the most cost-effective corridor for wildlife connecting two protected areas, using a chain of raster operations.
Scenario: Two national parks are separated by a human-modified landscape. Your task is to propose a 1 km-wide corridor that balances ecological value, avoids infrastructure, and minimises human conflict.
Prerequisites
- QGIS and Python with rasterio, numpy, scikit-image installed.
- Sample data: DEM, land cover raster, roads vector, existing protected areas vector. Use the bundled sample, any national park dataset, or synthesise with
gdal_rasterizeon OSM extracts. - About 1 hour.
Step 1 — Prepare aligned rasters
1# Reproject and align everything to a common grid
2gdalwarp -t_srs EPSG:3857 -tr 30 30 dem.tif dem_aligned.tif
3gdalwarp -t_srs EPSG:3857 -tr 30 30 -r near landcover.tif lc_aligned.tif
4gdal_rasterize -tr 30 30 -te <xmin ymin xmax ymax> -burn 1 roads.gpkg roads.tifAlignment check:
1import rasterio
2for fn in ['dem_aligned.tif', 'lc_aligned.tif', 'roads.tif']:
3 with rasterio.open(fn) as r:
4 print(fn, r.shape, r.transform, r.crs)All three should print identical shapes and transforms.
Step 2 — Reclassify land cover to habitat suitability
Assume land cover codes: 1 urban, 2 cropland, 3 grassland, 4 forest, 5 wetland, 6 water.
1import numpy as np
2with rasterio.open('lc_aligned.tif') as src:
3 lc = src.read(1)
4 profile = src.profile
5[object Object]
6Step 3 — Compute slope from DEM
1from scipy.ndimage import sobel
2[object Object]
3[object Object]
4Step 4 — Build a cost surface
Higher cost = harder for wildlife. Combine habitat (inverted), slope, and proximity to roads.
1from scipy.ndimage import distance_transform_edt
2[object Object]
3[object Object]
4[object Object]
5[object Object]
6[object Object]
7Step 5 — Compute least-cost path between park centroids
1from skimage.graph import route_through_array
2[object Object]
3[object Object]
4Rasterise the route:
1path_raster = np.zeros_like(cost, dtype='uint8')
2for r, c in route:
3 path_raster[r, c] = 1Step 6 — Buffer the path into a 1 km corridor
Load path.tif in QGIS and buffer the resulting line by 500 m to form a 1 km-wide corridor. Or in Python:
1from scipy.ndimage import distance_transform_edt
2[object Object]
3Step 7 — Zonal stats — what's inside the corridor?
from rasterstats import zonal_statsA high mean and forest majority indicate a good corridor.
Step 8 — Map it
Load DEM, land cover, the corridor, and the two parks into QGIS. Produce a print layout (reuse Lab 5.5 template). Add legend, scale bar, data sources.
Step 9 — Reflection
Answer in your notes:
- Which criterion dominated the cost surface? How sensitive is the corridor to the weights?
- What would happen if you doubled the slope weight? Halved it?
- Where does the path take unexpected detours, and why?
Troubleshooting
- Path hugs one row/column — enable
fully_connected=True; normalise cost components before combining. - Path goes through water — ensure water has very high cost or nodata; don't use exactly
inf(some algorithms don't handle it). - Raster alignment errors — verify shape and transform match across all inputs; reproject if not.
- Corridor is too narrow / wide — adjust the buffer distance.
Self-check exercises
1. Why normalise each cost component before summing?
Without normalisation, a component with a larger absolute range (slope 0–45° vs habitat 0–1) dominates the total. Scaling each to 0–1 (or comparable units) and applying explicit weights makes the trade-offs clear and controllable. Weights should sum to a meaningful total (like 10 or 1) for interpretability.
2. Your corridor crosses a major highway. How would you force it to find an alternative?
Assign the highway cells a very high cost (say 100× the baseline). The least-cost algorithm will detour around them unless no alternative exists. For absolute barriers, set nodata on those cells — but then ensure there's a feasible path, or the algorithm fails. Verifying the cost surface visually before running the path is key.
3. You want a sensitivity analysis across different weighting schemes. What workflow?
Parameterise the weights (w_habitat, w_slope, w_roads) and run the pipeline in a loop, saving each resulting corridor with a descriptive name. Compare outcomes visually (overlay in QGIS) and quantitatively (total cost, length, mean habitat). Monte Carlo sampling of weights with summary statistics is the rigorous approach; a grid search is usually enough for three or four weights.
Summary
- Chained raster operations model real decision problems: reclass → slope → cost → path → corridor → stats.
- Alignment up front prevents dozens of bugs downstream.
- Sensitivity analysis on weights is the difference between a defensible recommendation and hand-waving.
Further reading
- Beier, P. & Majka, D. — Conservation Corridor Design.
- Adriaensen et al. — The application of least-cost modeling as a functional landscape model.
- Earth Engine documentation on cost-distance.
- SCALGO Live — practical hydrological analysis at scale.
Module 10: Raster Analysis
Answer these quick multiple-choice questions to check your understanding before moving on.