have change into more frequent and devastating across the globe, with the results of climate change in recent a long time. On this context, flood modeling has a very important role in risk assessment and disaster-response operations, while also remaining a key focus of advanced research and academic studies.
In this text, we’ll construct a basic flood inundation model using Python and a Digital Elevation Model (DEM). We’ll use a flood fill technique to incrementally simulate how rising water levels affect a landscape and animate the inundation process. It’s a visible and hands-on strategy to explore geospatial data and flood risks, even with out a background in hydraulic modeling.
What you’ll Learn
1. What’s a Digital Elevation Model (DEM)
A Digital Elevation Model (DEM) is a numerical representation of the Earth’s surface, where each cell (or pixel) in a daily grid (referred to as raster data) accommodates an elevation value. Unlike digital images that store color information, DEMs store height data, typically excluding surface features like vegetation, buildings, and other man-made structures.
DEMs are commonly utilized in fields equivalent to mapping, hydrology, environmental monitoring, and earth sciences. They function a foundational dataset for any application that requires an in depth understanding of terrain and elevation.
Many sources offer free and reliable DEM data, including the USGS National Map, NASA Earthdata, and the Shuttle Radar Topography Mission (SRTM).
In this text, we’ll be using a DEM provided by the USGS National Geospatial Program, which is freely available and released into the general public domain.
Note: The info provided by USGS has a spatial resolution of 1 arc second (roughly 30 meters on the equator).
The realm of interest (AOI) on this study is positioned within the Northeast region of Brazil. The DEM file covers a 1° × 1° tile, extending from 6°S, 39°W to five°S, 38°W, and utilizes the WGS84 coordinate system (EPSG: 4326), as illustrated below.
2. How you can load and visualize elevation data with Python
Now we’ll use Python to set a viable environment to visualise and analyze some initial details about DEM data. First, let’s import the essential libraries.
# import libraries
import rasterio
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.animation import FuncAnimation
rasterio
: Reads and writes geospatial raster data like DEMs.
matplotlib.pyplot
: Creates static and interactive visualizations.
numpy
: Handles numerical operations and array-based data.
FuncAnimation
: Generates animations by updating plots frame by frame.
Next, let’s use the rasterio
library to open and visualize a DEM file of the AOI.
# Helper function to load DEM Files
def load_dem(path):
with rasterio.open(path) as src:
dem = src.read(1)
transform = src.transform
nodata = src.nodata
if nodata will not be None:
# Mask no-data values
dem = np.ma.masked_equal(dem, nodata)
return dem, transform
The function above reads the elevation data and checks whether the file includes “no-data values”. No-data values are used to represent areas without valid elevation data (e.g., outside coverage or corrupted pixels). If a no-data value is present, the function replaces those pixels with np.nan
, making it easier to handle or ignore them in later evaluation and visualizations.
Visualizing DEM data
dem = load_dem("s06_w039_1arc_v3.tif")
plt.imshow(dem, cmap='terrain')
plt.title("Digital Elevation Model")
plt.colorbar(label="Elevation (m)")
plt.show()

- Using geographic coordinates within the visualization
As we will see, the axes are in pixel coordinates (columns and features). To raised understand flood inundation, it’s vital to know the geographic coordinates (latitude and longitude) related to each pixel of the image.
To attain that, we’ll use the coordinate reference system data of the DEM file. As said earlier, the DEM we’re using utilizes the WGS84 coordinate system (EPSG: 4326).
We are able to adapt the helper function to load DEM files as follows:
def load_dem(path):
with rasterio.open(path) as src:
dem = src.read(1)
transform = src.transform
nodata = src.nodata
if nodata will not be None:
# Mask nodata values
dem = np.ma.masked_equal(dem, nodata)
return dem, transform
The function retrieves the data from the DEM, which is an affine object that maps pixel positions (row, column) to geographic coordinates (latitude and longitude).
To represent the geographic coordinates on the axes of the plot, it’ll be essential to explore the extent
parameter from the imshow()
function.
dem, transform = load_dem("s06_w039_1arc_v3.tif")
# Compute extent from transform
extent = [
transform[2], # xmin (longitude)
transform[2] + transform[0] * dem.shape[1], # xmax
transform[5] + transform[4] * dem.shape[0], # ymin (latitude)
transform[5] # ymax
]
# Plot with using geographic coordinates
fig, ax = plt.subplots()
img = ax.imshow(dem, cmap='terrain', extent=extent, origin='upper')
ax.set_xlabel('Longitude')
ax.set_ylabel('Latitude')
plt.colorbar(img, label='Elevation (m)')
plt.title('DEM Visualization')
plt.show()
The extent
parameter might be used to define the spatial bounds of the DEM plot using values derived from the raster’s transform
affine object. It sets the minimum and maximum longitude (xmin
, xmax
) and latitude (ymin
, ymax
) in order that the plot shows coordinates on the axes as a substitute of pixel indices.
Finally, we now have the next results:

3. How you can simulate flood scenarios with elevation thresholds
Now, we’ll reveal a straightforward yet useful method for visualizing flood scenarios and simulating inundation. It consists of defining a height threshold and generating a binary mask that identifies all areas with elevation below this level.
In this instance, we simulate Flooding across all areas with elevations below 40 meters.
flood_threshold = 40 # meters
flood_mask = (dem <= flood_threshold).astype(int)
plt.imshow(flood_mask, extent=extent, cmap='Blues')
plt.title(f"Flooded Area (Threshold: {flood_threshold}m)")
plt.xlabel("Longitude")
plt.ylabel("Latitude")
plt.show()

With just just a few lines of code, we will visualize the impact of various flood scenarios on the world of interest (AOI). Nevertheless, because this visualization is static, it doesn’t show how the flood progresses over time. To cope with that, we’ll use matplotlib’s FuncAnimation
to create a dynamic visualization.
4. How you can animate flood progression with Python
We’ll now simulate a progressive flood scenario by increasing the water level incrementally and generating a brand new mask at each step. We’ll overlay this mask on the terrain image and animate it.
# flood_levels defines how high the flood rises per frame
flood_levels = np.arange(15, 100, 5)
# Arrange figure and axes
fig, ax = plt.subplots()
img = ax.imshow(dem, cmap='terrain', extent=extent, origin='upper')
flood_overlay = ax.imshow(np.zeros_like(dem), cmap='Blues', alpha=0.4, extent=extent, origin='upper')
title = ax.set_title("")
ax.set_xlabel("Longitude")
ax.set_ylabel("Latitude")
# Animation function
def update(frame):
level = flood_levels[frame]
mask = np.where(dem <= level, 1, np.nan)
flood_overlay.set_data(mask)
title.set_text(f"Flood Level: {level} m")
return flood_overlay, title
# Create animation
ani = FuncAnimation(fig, update, frames=len(flood_levels), interval=300, blit=True)
plt.tight_layout()
plt.show()
# save the output as a gif
ani.save("flood_simulation.gif", author='pillow', fps=5)

When you’re excited by creating animations with Python, this step-by-step tutorial is a fantastic place to start out.
Conclusion and next steps
In this text, we created a basic workflow to perform a flood simulation in Python using elevation data from a DEM file. After all, this model doesn’t implement essentially the most advanced techniques on the topic, still for visualization and communication, this elevation threshold method offers a strong and accessible entry point.
More advanced simulation techniques include:
- Connectivity-based flood propagation
- Flow direction and accumulation
- Time-based flow modeling
Nevertheless, this hands-on approach might be of great profit for educators, students, and analysts exploring Geospatial Data in disaster response studies and environmental modeling.
The entire code is obtainable here.
I strongly encourage readers to experiment with the code using their very own elevation data, adapt it to their specific context, and explore ways to boost or expand the approach.
References
[1] U.S. Geological Survey. . U.S. Department of the Interior. Retrieved May 17, 2025, from https://www.usgs.gov/programs/national-geospatial-program/national-map
[2] U.S. Geological Survey. U.S. Department of the Interior. Retrieved May 17, 2025, from https://www.usgs.gov/faqs/what-a-digital-elevation-model-dem
[3] Gillies, S. . Rasterio. Retrieved May 27, 2025, from https://rasterio.readthedocs.io/en/stable/topics/georeferencing.html
[4] Gillies, Sean. . Accessed May 27, 2025. https://rasterio.readthedocs.io/en/latest/topics/transforms.html.