[GIS] Explanation of HAND (height above nearest drainage) model procedure

arcgis-10.2arcpyfloodhandhydrology

i tried to follow this procedure Spatial Analysis – Calculate a cells elevation (height) above the nearest stream cell but i have some problem to understand everything. I mean the 2th answer in the link.
I don't understand the 3th and 4th points. I have flowdirection, stream network and dem. I would to understand what about flow elevation difference and what i need to do to get the hand model.

Best Answer

I will assume you have your DEM, have been able to calculate the flow direction raster (the ArcGis help has a good explanation). You also need to have defined a raster of the drainage which has values of 0 for each cell along a drainage (height above drainage is 0 by definition) and has nulls for all other cells.

You need to know which cell is downslope and the elevation drop for each cell in your DEM, except for the cells that are along the drainage. To do this you use focal statistics with a mask for each possible flow direction.

The directions when you calculate a flow direction raster are defined by powers of 2 so the designation for the directions from cell X are:

32..64..128

16...X....1

8....4....2

So we calculate the elevation of the cell in each direction by using a masks that defines a 3x3 square neighborhood and says only use one cell in that neighborhood for the focal statistics. You need 8 mask files for this. For the cell to the east with value 1 the mask file looks like:

3 3

0 0 0

0 0 1

0 0 0

For the cell to the sw with value 8 it is:

3 3

0 0 0

0 0 0

1 0 0

I call these files DirCode1.txt, DirCode2.txt, Dircode4.txt...DirCode128.txt. Put them all in the same directory.

The function

FocalStatistics(inElevRaster, NbrIrregular(focalMaskFile), "MINIMUM")

returns the minimum elevation in the cells around each location where the mask has the value 1. Since there is only one such cell in the mask it doesn't really matter if you use minimum, maximum or whatever and you just subtract that value from the DEM value for the original cell to get the difference. But you only do that for the cell in the direction of flow. Do this by iterating through each flow direction mask file and use the Con function to return a value if the mask file direction is the same as the flow direction for each cell:

lstDirection = [1,2,4,8,16,32,64,128]

# This block only needs to be calculated once for the area

for idx in lstDirection:
    focalMaskFile = "C:/Data/GIS_Data/DEM/FocalStatNeighbor/" + "DirCode" + str(idx) + ".txt"
    outElDifRaster = Con(inFDirRaster == idx, inElevRaster - FocalStatistics(inElevRaster, NbrIrregular(focalMaskFile), "MINIMUM"))
else:
    # Calculate values for indeterminate flow direction cells
    outElDifRaster = Con(inFDirRaster,inElevRaster - FocalStatistics(inElevRaster, NbrRectangle(3,3), "MINIMUM"))
outElDifRaster.save("floweldif")

For some reason I forget, you can get cells where the flow direction value is not in the 8 we are using. Define the elevation difference for those bu using the minimum value in the 3x3 region around the cell.

Calculating the HAND is similar. Start by copying your drainage raster to the output raster. For each focal mask file, check each null cell in the output raster to see if that mask matches the flow direction, then add the value from the cell in that direction. At first that will only give a value for cells next to the drainage. When that's done, you have HAND values for more cells. Repeat the process to calculate values for null cells upslope from those cells. Loop, working your way upslope, until you have no more null cells.