forked from makepath/xarray-spatial
-
Notifications
You must be signed in to change notification settings - Fork 0
/
slope.py
71 lines (60 loc) · 2.18 KB
/
slope.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import numpy as np
from xarray import DataArray
from xrspatial.utils import ngjit
@ngjit
def _horn_slope(data, cellsize_x, cellsize_y):
out = np.zeros_like(data)
rows, cols = data.shape
for y in range(1, rows-1):
for x in range(1, cols-1):
a = data[y+1, x-1]
b = data[y+1, x]
c = data[y+1, x+1]
d = data[y, x-1]
f = data[y, x+1]
g = data[y-1, x-1]
h = data[y-1, x]
i = data[y-1, x+1]
dz_dx = ((c + 2 * f + i) - (a + 2 * d + g)) / (8 * cellsize_x)
dz_dy = ((g + 2 * h + i) - (a + 2 * b + c)) / (8 * cellsize_y)
p = (dz_dx * dz_dx + dz_dy * dz_dy) ** .5
out[y, x] = np.arctan(p) * 57.29578
return out
def slope(agg, name='slope'):
"""Returns slope of input aggregate in degrees.
Parameters
----------
agg : DataArray
Returns
-------
data: DataArray
Notes:
------
Algorithm References:
- http://desktop.arcgis.com/en/arcmap/10.3/tools/spatial-analyst-toolbox/how-slope-works.htm
- Burrough, P. A., and McDonell, R. A., 1998.
Principles of Geographical Information Systems
(Oxford University Press, New York), pp 406
"""
if not isinstance(agg, DataArray):
raise TypeError("agg must be instance of DataArray")
if not agg.attrs.get('res'):
raise ValueError('input xarray must have `res` attr.')
# get cellsize out from 'res' attribute
cellsize = agg.attrs.get('res')
if isinstance(cellsize, tuple) and len(cellsize) == 2 \
and isinstance(cellsize[0], (int, float)) \
and isinstance(cellsize[1], (int, float)):
cellsize_x, cellsize_y = cellsize
elif isinstance(cellsize, (int, float)):
cellsize_x = cellsize
cellsize_y = cellsize
else:
raise ValueError('`res` attr of input xarray must be a numeric'
' or a tuple of numeric values.')
slope_agg = _horn_slope(agg.data, cellsize_x, cellsize_y)
return DataArray(slope_agg,
name=name,
coords=agg.coords,
dims=agg.dims,
attrs=agg.attrs)