Skip to content

Commit 0e4902e

Browse files
committed
Add docs, benchmarks, and user guide notebook for flood module
- docs/source/reference/flood.rst: API reference (autosummary) - benchmarks/benchmarks/flood.py: ASV benchmarks for all four functions - examples/user_guide/12_Flood_Analysis.ipynb: walkthrough notebook covering HAND-based inundation, flood depth, CN runoff, and travel time - README.md: add Flood section to the feature matrix - docs/source/reference/index.rst: register flood in toctree
1 parent 8d6a707 commit 0e4902e

File tree

5 files changed

+588
-0
lines changed

5 files changed

+588
-0
lines changed

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,17 @@ In the GIS world, rasters are used for representing continuous phenomena (e.g. e
255255

256256
-----------
257257

258+
### **Flood**
259+
260+
| Name | Description | NumPy xr.DataArray | Dask xr.DataArray | CuPy GPU xr.DataArray | Dask GPU xr.DataArray |
261+
|:----------:|:------------|:----------------------:|:--------------------:|:-------------------:|:------:|
262+
| [Flood Depth](xrspatial/flood.py) | Computes water depth above terrain from a HAND raster and water level | ✅️ | ✅️ | ✅️ | ✅️ |
263+
| [Inundation](xrspatial/flood.py) | Produces a binary flood/no-flood mask from a HAND raster and water level | ✅️ | ✅️ | ✅️ | ✅️ |
264+
| [Curve Number Runoff](xrspatial/flood.py) | Estimates runoff depth from rainfall using the SCS/NRCS curve number method | ✅️ | ✅️ | ✅️ | ✅️ |
265+
| [Travel Time](xrspatial/flood.py) | Estimates overland flow travel time via simplified Manning's equation | ✅️ | ✅️ | ✅️ | ✅️ |
266+
267+
-----------
268+
258269
### **Zonal**
259270

260271
| Name | Description | NumPy xr.DataArray | Dask xr.DataArray | CuPy GPU xr.DataArray | Dask GPU xr.DataArray |

benchmarks/benchmarks/flood.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
from xrspatial import (
2+
flow_direction, flow_accumulation, hand, slope, flow_length,
3+
)
4+
from xrspatial.flood import (
5+
flood_depth, inundation, curve_number_runoff, travel_time,
6+
)
7+
8+
from .common import get_xr_dataarray
9+
10+
11+
class FloodDepth:
12+
params = ([100, 300, 1000], ["numpy", "dask"])
13+
param_names = ("nx", "type")
14+
15+
def setup(self, nx, type):
16+
ny = nx // 2
17+
elev = get_xr_dataarray((ny, nx), "numpy")
18+
flow_dir = flow_direction(elev)
19+
flow_accum = flow_accumulation(flow_dir)
20+
self.hand_agg = hand(flow_dir, flow_accum, elev)
21+
22+
if type == "dask":
23+
import dask.array as da
24+
chunks = (max(1, ny // 2), max(1, nx // 2))
25+
self.hand_agg.data = da.from_array(
26+
self.hand_agg.data, chunks=chunks,
27+
)
28+
29+
def time_flood_depth(self, nx, type):
30+
result = flood_depth(self.hand_agg, water_level=5.0)
31+
if hasattr(result.data, 'compute'):
32+
result.data.compute()
33+
34+
35+
class Inundation:
36+
params = ([100, 300, 1000], ["numpy", "dask"])
37+
param_names = ("nx", "type")
38+
39+
def setup(self, nx, type):
40+
ny = nx // 2
41+
elev = get_xr_dataarray((ny, nx), "numpy")
42+
flow_dir = flow_direction(elev)
43+
flow_accum = flow_accumulation(flow_dir)
44+
self.hand_agg = hand(flow_dir, flow_accum, elev)
45+
46+
if type == "dask":
47+
import dask.array as da
48+
chunks = (max(1, ny // 2), max(1, nx // 2))
49+
self.hand_agg.data = da.from_array(
50+
self.hand_agg.data, chunks=chunks,
51+
)
52+
53+
def time_inundation(self, nx, type):
54+
result = inundation(self.hand_agg, water_level=5.0)
55+
if hasattr(result.data, 'compute'):
56+
result.data.compute()
57+
58+
59+
class CurveNumberRunoff:
60+
params = ([100, 300, 1000], ["numpy", "dask"])
61+
param_names = ("nx", "type")
62+
63+
def setup(self, nx, type):
64+
ny = nx // 2
65+
self.rainfall = get_xr_dataarray((ny, nx), type)
66+
# Make all values positive for rainfall
67+
import numpy as np
68+
if type == "numpy":
69+
self.rainfall.data = np.abs(self.rainfall.data) + 1.0
70+
else:
71+
import dask.array as da
72+
self.rainfall.data = da.abs(self.rainfall.data) + 1.0
73+
74+
def time_curve_number_runoff(self, nx, type):
75+
result = curve_number_runoff(self.rainfall, curve_number=80.0)
76+
if hasattr(result.data, 'compute'):
77+
result.data.compute()
78+
79+
80+
class TravelTime:
81+
params = ([100, 300, 1000], ["numpy", "dask"])
82+
param_names = ("nx", "type")
83+
84+
def setup(self, nx, type):
85+
ny = nx // 2
86+
elev = get_xr_dataarray((ny, nx), "numpy")
87+
flow_dir = flow_direction(elev)
88+
self.slope_agg = slope(elev)
89+
self.flow_length_agg = flow_length(flow_dir)
90+
91+
if type == "dask":
92+
import dask.array as da
93+
chunks = (max(1, ny // 2), max(1, nx // 2))
94+
self.slope_agg.data = da.from_array(
95+
self.slope_agg.data, chunks=chunks,
96+
)
97+
self.flow_length_agg.data = da.from_array(
98+
self.flow_length_agg.data, chunks=chunks,
99+
)
100+
101+
def time_travel_time(self, nx, type):
102+
result = travel_time(
103+
self.flow_length_agg, self.slope_agg, mannings_n=0.03,
104+
)
105+
if hasattr(result.data, 'compute'):
106+
result.data.compute()

docs/source/reference/flood.rst

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
.. _reference.flood:
2+
3+
*****
4+
Flood
5+
*****
6+
7+
Flood Depth
8+
===========
9+
.. autosummary::
10+
:toctree: _autosummary
11+
12+
xrspatial.flood.flood_depth
13+
14+
Inundation
15+
==========
16+
.. autosummary::
17+
:toctree: _autosummary
18+
19+
xrspatial.flood.inundation
20+
21+
Curve Number Runoff
22+
===================
23+
.. autosummary::
24+
:toctree: _autosummary
25+
26+
xrspatial.flood.curve_number_runoff
27+
28+
Travel Time
29+
===========
30+
.. autosummary::
31+
:toctree: _autosummary
32+
33+
xrspatial.flood.travel_time

docs/source/reference/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Reference
88
:maxdepth: 2
99

1010
classification
11+
flood
1112
focal
1213
multispectral
1314
pathfinding

0 commit comments

Comments
 (0)