Fluvial flood inundation mapping quick start

Open In Colab

On Google Colab, run the following command to install pygeoflood:

%pip install git+https://github.com/passah2o/pygeoflood

Import libraries

[1]:
from pathlib import Path
from pygeoflood import PyGeoFlood

Instantiate pygeoflood model class

[2]:
pgf = PyGeoFlood(dem_path="data/OC1mTest.tif")

Set paths to input datasets

[3]:
pgf.flowline_path = "data/Flowline.shp"
pgf.catchment_path = "data/Catchment.shp"

# # we are not using these datasets for this example
# pgf.streamflow_forecast_path = "data/prod_nwm.t00z.analysis_assim.channel_rt.tm00.conus.nc"
# pgf.custom_flowline_path = Path(data_dir, "NHDPlus_H_1209_HU4_GDB.gdb")

Download example input datasets if necessary

[4]:
# make data directory if it doesn't exist
if not Path("data").is_dir():
    Path("data").mkdir()
# download input datasets if they doesn't exist
# DEM from USGS 3DEP
if not pgf.dem_path.is_file():
    !curl https://utexas.box.com/shared/static/id0in7w8yn38o59sexa50aqunsr7mzk0.tif -Lso data/OC1mTest.tif
# flowlines and catchments from NFIE (NHD MR) dataset
# https://www.arcgis.com/home/webmap/viewer.html?webmap=9766a82973b34f18b43dafa20c5ef535
if not pgf.flowline_path.is_file():
    !curl -sL https://utexas.box.com/shared/static/s1vlnymonbidnhul52oja7s83ky1212j.tgz | tar -xz -C data
if not pgf.catchment_path.is_file():
    !curl -sL https://utexas.box.com/shared/static/jzawwvmb2tjl4yqtnitgvfjcc4ho4tg5.tgz | tar -xz -C data

Run full fluvial flood inundation mapping workflow

[5]:
# set constant flowrate since we don't have a streamflow forecast
# see docs for `PyGeoFlood.config` and `PyGeoFlood.calculate_flood_stage`

pgf.config = {"calculate_flood_stage": {"custom_Q": 500}}

pgf.run_fim_workflow()
Running apply_nonlinear_filter with parameters:
    custom_dem = None
    custom_path = None
    method = PeronaMalik2
    smoothing_quantile = 0.9
    time_increment = 0.1
    n_iter = 50
    sigma_squared = 0.05
Computing slope of raw DTM
DEM slope array shape: (3378, 4750)
Computing lambda = q-q-based nonlinear filtering threshold
DEM smoothing Quantile: 0.9
Edge Threshold Value: 0.34356024861335754
Filtered DEM written to data/OC1mTest_filtered.tif
apply_nonlinear_filter completed in 10.7802 seconds

Running calculate_slope with parameters:
    custom_filtered_dem = None
    custom_path = None
 slope statistics
 min angle: 0.0
 max angle: 54.863846043721324
 mean slope: 0.13960592
 stdev slope: 0.15432632
Slope raster written to data/OC1mTest_slope.tif
calculate_slope completed in 1.2883 seconds

Running calculate_curvature with parameters:
    custom_filtered_dem = None
    custom_path = None
    method = geometric
 using geometric curvature
 curvature statistics
 non-nan curvature cell number: 16045500
 non-nan finite curvature cell number:  mean:  -0.00031314598
 standard deviation:  0.112147875
Curvature raster written to data/OC1mTest_curvature.tif
calculate_curvature completed in 1.3863 seconds

Running fill_depressions with parameters:
    custom_filtered_dem = None
    custom_path = None
./whitebox_tools --run="FillDepressions" --dem='/Users/markwang/repos/pygeoflood/examples/data/OC1mTest_filtered.tif' --output='/Users/markwang/repos/pygeoflood/examples/data/OC1mTest_filled.tif' --fix_flats -v --compress_rasters=True

******************************
* Welcome to FillDepressions *
* Powered by WhiteboxTools   *
* www.whiteboxgeo.com        *
******************************
Reading data...
Fixing flow on flats...
Flats increment value: 0.000002
Saving data...
Output file written
Elapsed Time (excluding I/O): 0.190s
Filled DEM written to data/OC1mTest_filled.tif
fill_depressions completed in 8.0148 seconds

Running calculate_mfd_flow_accumulation with parameters:
    custom_filled_dem = None
    custom_path = None
./whitebox_tools --run="QuinnFlowAccumulation" --dem='/Users/markwang/repos/pygeoflood/examples/data/OC1mTest_filled.tif' --output='/Users/markwang/repos/pygeoflood/examples/data/OC1mTest_mfd_fac.tif' --out_type=cells --exponent=1.0 -v --compress_rasters=True

************************************
* Welcome to QuinnFlowAccumulation *
* Powered by WhiteboxTools         *
* www.whiteboxgeo.com              *
************************************
Saving data...
Output file written

Elapsed Time (Including I/O): 4.702s
MFD flow accumulation raster written to data/OC1mTest_mfd_fac.tif
calculate_mfd_flow_accumulation completed in 4.7655 seconds

Running calculate_d8_flow_direction with parameters:
    custom_filled_dem = None
    custom_filtered_dem = None
    custom_path = None
./whitebox_tools --run="D8Pointer" --dem='/Users/markwang/repos/pygeoflood/examples/data/OC1mTest_filled.tif' --output='/Users/markwang/repos/pygeoflood/examples/data/OC1mTest_d8_fdr.tif' -v --compress_rasters=True

****************************
* Welcome to D8Pointer     *
* Powered by WhiteboxTools *
* www.whiteboxgeo.com      *
****************************
Reading data...
Saving data...
Output file written
Elapsed Time (excluding I/O): 0.251s
D8 flow direction raster written to data/OC1mTest_d8_fdr.tif
calculate_d8_flow_direction completed in 1.9938 seconds

Running find_outlets with parameters:
    custom_d8_fdr = None
    custom_path = None
Outlets raster written to data/OC1mTest_outlets.tif
find_outlets completed in 0.2224 seconds

Running delineate_basins with parameters:
    custom_d8_fdr = None
    custom_path = None
./whitebox_tools --run="Basins" --d8_pntr='/Users/markwang/repos/pygeoflood/examples/data/OC1mTest_d8_fdr.tif' --output='/Users/markwang/repos/pygeoflood/examples/data/OC1mTest_basins.tif' -v --compress_rasters=True

****************************
* Welcome to Basins        *
* Powered by WhiteboxTools *
* www.whiteboxgeo.com      *
****************************
Reading data...
Saving data...
Output file written
Elapsed Time (excluding I/O): 0.465s
Basins raster written to data/OC1mTest_basins.tif
delineate_basins completed in 1.0381 seconds

Running define_skeleton with parameters:
    custom_curvature = None
    custom_mfd_fac = None
    custom_path = None
    fac_threshold = 3000
    write_flow_skeleton = False
    write_curvature_skeleton = False
Curvature mean:  -0.00031413726
Curvature standard deviation:  0.11232527
Curvature Projection: EPSG:6343
Mean upstream flow:  2617.3564
Combined skeleton written to data/OC1mTest_combined_skeleton.tif
define_skeleton completed in 0.7782 seconds

Running find_endpoints with parameters:
    custom_flowline = None
    custom_path = None
Endpoints csv written to data/OC1mTest_endpoints.csv
find_endpoints completed in 0.0330 seconds

Running calculate_binary_hand with parameters:
    custom_dem = None
    custom_flowline = None
    custom_path = None
Binary HAND raster written to data/OC1mTest_binary_hand.tif
calculate_binary_hand completed in 4.9416 seconds

Running extract_channel_network with parameters:
    custom_flowline = None
    custom_curvature = None
    custom_mfd_fac = None
    custom_endpoints = None
    custom_binary_hand = None
    custom_path = None
    retrace_flowline = True
    vector_extension = shp
    write_cost_function = False
    use_custom_flowline = False
    no_flowline = False
    custom_weight_curvature = None
    custom_weight_mfd_fac = None
    custom_weight_binary_hand = None
    custom_weight_custom_flowline = None
Retracing flowline...
Cost function weights:
curvature          0.2520 (mean flow accumulation)
mfd_fac            1.0000
binary_hand        0.7500
custom_flowline    0.0000
0.25195235 1 0.75 0
Cost min: 0.5028838188775905
Cost max: inf
cost shape: (3378, 4750)
Creating path 1/1: RAM usage: 12.00/16.00 GB (75.0%)
Number of endpoints: 1
Channel network raster written to data/OC1mTest_channel_network_raster.tif
Channel network vector written to data/OC1mTest_channel_network.shp
extract_channel_network completed in 2.0418 seconds

Running calculate_hand with parameters:
    custom_filled_dem = None
    custom_channel_network_raster = None
    custom_path = None
./whitebox_tools --run="ElevationAboveStream" --dem='/Users/markwang/repos/pygeoflood/examples/data/OC1mTest_filled.tif' --streams='/Users/markwang/repos/pygeoflood/examples/data/OC1mTest_channel_network_raster.tif' --output='/Users/markwang/repos/pygeoflood/examples/data/OC1mTest_HAND.tif' -v --compress_rasters=True

***********************************
* Welcome to ElevationAboveStream *
* Powered by WhiteboxTools        *
* www.whiteboxgeo.com             *
***********************************
Reading DEM data...
Reading streams data...
Saving data...
Output file written
Elapsed Time (excluding I/O): 0.644s
**********************************************************************************
WARNING: Interior pit cells were found within the input DEM. It is likely that the
DEM needs to be processed to remove topographic depressions and flats prior to
running this tool.
**********************************************************************************
HAND raster written to data/OC1mTest_HAND.tif
calculate_hand completed in 5.1220 seconds

Running segment_channel_network with parameters:
    custom_channel_network_vector = None
    custom_path = None
    vector_extension = shp
    segment_length = 1000
Segmented channel network written to data/OC1mTest_segmented_channel_network.shp
segment_channel_network completed in 0.7907 seconds

Running delineate_segment_catchments with parameters:
    custom_segmented_channel_network = None
    custom_d8_fdr = None
    custom_path = None
./whitebox_tools --run="Watershed" --d8_pntr='/Users/markwang/repos/pygeoflood/examples/data/OC1mTest_d8_fdr.tif' --pour_pts='/Users/markwang/repos/pygeoflood/examples/data/OC1mTest_segmented_channel_network_raster.tif' --output='/Users/markwang/repos/pygeoflood/examples/data/OC1mTest_segment_catchments.tif' -v --compress_rasters=True

****************************
* Welcome to Watershed     *
* Powered by WhiteboxTools *
* www.whiteboxgeo.com      *
****************************
Reading data...
Saving data...
Output file written
Elapsed Time (excluding I/O): 0.841s
Segment catchments written to data/OC1mTest_segment_catchments.tif
delineate_segment_catchments completed in 1.5538 seconds

Running calculate_src with parameters:
    custom_dem = None
    custom_segmented_channel_network = None
    custom_segment_catchments_raster = None
    custom_catchments = None
    custom_hand = None
    custom_path = None
    min_slope = 1e-06
    max_stage = 20
    incr_stage = 0.1
    custom_roughness_path = None
River attributes written to data/OC1mTest_river_attributes.csv
Synthetic rating curves written to data/OC1mTest_src.csv
calculate_src completed in 3.4749 seconds

Running calculate_flood_stage with parameters:
    custom_src = None
    custom_streamflow_forecast_path = None
    custom_path = None
    custom_Q = 500
Applying custom streamflow to each segment: 500 cms
Flood stages written to data/OC1mTest_flood_stage.csv
calculate_flood_stage completed in 0.0042 seconds

Running inundate with parameters:
    custom_hand = None
    custom_flood_stage = None
    custom_segment_catchments_raster = None
    custom_path = None
Flood inundation raster written to data/OC1mTest_fim.tif
inundate completed in 0.9615 seconds

run_fim_workflow completed in 49.1919 seconds

Plot flood inundation map

[ ]:
import matplotlib.pyplot as plt
import numpy as np
import rasterio as rio

with rio.open(pgf.fim_path) as ds:
    fim = ds.read(1)
    fim[fim == ds.nodata] = np.nan

plt.imshow(fim, cmap="Blues")
plt.colorbar()
plt.show()
../_images/examples_fim_workflow_combined_13_0.png

All output files are saved in the data directory and can be downloaded for viewing with a GIS software such as QGIS

[7]:
# save output data file paths we can load our PyGeoFlood instance later with
# pgf = PyGeoFlood.from_paths("data/paths.txt")
pgf.to_paths("data/paths.txt")
Paths written to data/paths.txt