π Simple and fast watershed delineation in python
View the Project on GitHub mdbartos/pysheds
The grid.catchment method operates on a flow direction grid. This flow direction grid can be computed from a DEM, as shown in flow directions.
from pysheds.grid import Grid
# Instantiate grid from raster
grid = Grid.from_raster('./data/dem.tif')
dem = grid.read_raster('./data/dem.tif')
# Resolve flats and compute flow directions
inflated_dem = grid.resolve_flats(dem)
fdir = grid.flowdir(inflated_dem)
To delineate a catchment, first specify a pour point (the outlet of the catchment). If the x and y components of the pour point are spatial coordinates in the gridβs spatial reference system, specify xytype='coordinate'.
# Specify pour point
x, y = -97.294167, 32.73750
# Delineate the catchment
catch = grid.catchment(x=x, y=y, fdir=fdir, xytype='coordinate')
# Plot the result
grid.clip_to(catch)
catch_view = grid.view(catch)
# Plot the catchment
fig, ax = plt.subplots(figsize=(8,6))
fig.patch.set_alpha(0)
plt.grid('on', zorder=0)
im = ax.imshow(np.where(catch_view, catch_view, np.nan), extent=grid.extent,
zorder=1, cmap='Greys_r')
plt.xlabel('Longitude')
plt.ylabel('Latitude')
plt.title('Delineated Catchment', size=14)

If the x and y components of the pour point correspond to the row and column indices of the flow direction array, specify xytype='index':
# Reset the view
grid.viewfinder = fdir.viewfinder
# Find the row and column index corresponding to the pour point
col, row = grid.nearest_cell(x, y)
# Delineate the catchment
catch = grid.catchment(x=col, y=row, fdir=fdir, xytype='index')
# Plot the result
grid.clip_to(catch)
catch_view = grid.view(catch)
# Plot the catchment
fig, ax = plt.subplots(figsize=(8,6))
fig.patch.set_alpha(0)
plt.grid('on', zorder=0)
im = ax.imshow(np.where(catch_view, catch_view, np.nan), extent=grid.extent,
zorder=1, cmap='Greys_r')
plt.xlabel('Longitude')
plt.ylabel('Latitude')
plt.title('Delineated Catchment', size=14)

Sometimes the pour point isnβt known exactly. In this case, it can be helpful to first compute the accumulation and then snap a trial pour point to the nearest high accumulation cell.
# Reset view
grid.viewfinder = fdir.viewfinder
# Compute accumulation
acc = grid.accumulation(fdir)
# Snap pour point to high accumulation cell
x_snap, y_snap = grid.snap_to_mask(acc > 1000, (x, y))
# Delineate the catchment
catch = grid.catchment(x=x_snap, y=y_snap, fdir=fdir, xytype='coordinate')
# Plot the result
grid.clip_to(catch)
catch_view = grid.view(catch)
# Plot the catchment
fig, ax = plt.subplots(figsize=(8,6))
fig.patch.set_alpha(0)
plt.grid('on', zorder=0)
im = ax.imshow(np.where(catch_view, catch_view, np.nan), extent=grid.extent,
zorder=1, cmap='Greys_r')
plt.xlabel('Longitude')
plt.ylabel('Latitude')
plt.title('Delineated Catchment', size=14)
