7/7/2005 How to delineate a drainage basin in Arc (and get that

advertisement
2/16/2016
How to delineate a drainage basin in Arc
(and get that basin’s mean elevation and mean hillslope gradient)
I want to find mean elevations and mean hillslope gradients for some watersheds, but I
don’t want to spend days poring over topo maps. I want to spend days learning how to
make Arc do it for me. Here’s what I’ve learned so far.
First, get some elevation data. Let’s say you start by downloading some free 10m SDTS
data, and these data come in 7.5’ quadrangles, and your watershed of interest spans 4 of
these quads. The first step is to merge these 4 quads together into a single grid.
First, open the ArcToolbox from the desktop, and use the SDTS Wizard to convert the
STDS files into grids. Name the grids grid1, grid2, grid3 and grid4.
(How to use the SDTS Wizard: Click on “Import SDTS Wizard” in the ArcToolbox and
let it walk you through it. Click on the folder icon next to the “Input SDTS transfer
prefix” line. Double click the folder which contains the SDTS data, e.g.
c:\users\ken\1694660.DEM.SDTS. A prefix (e.g. 9949) should show up in the prefix
window to the right. Click on that and press OK. Click next until you get to “Name your
output datasets”. Save the output grid wherever you like under whatever name. Done.)
After converting all of your SDTS files into grids, merge the grids together into a single
grid, and call it something, e.g. “elev”. Here’s how:
Open Grid (Program Files  Arc Workstation  Grid), and change the workspace to
wherever your files are saved.
&wo c:\users\ken
&wo means change path.
Now merge all the grids into a single grid.
elev = merge(grid1, grid2, grid3, grid4)
When using the “merge” command, it’s necessary to include the pathnames for
each file if each grid is in a different folder. For example:
elev = merge(c:\ken\folder1\grid1, c:\ken\folder2\grid2, etc.)
That’s great. You can even take a look at your file now.
mape elev
This defines the map extent (mape) to be the size of the grid “elev”.
image elev
This displays the grid “elev” in the image window.
2/16/2016
At this point the grid looks pretty groovy, but it’s probably not as groovy as you think.
The grid likely needs to be cleaned up a bit. If there are “sinks” in the elevation grid, Arc
will choke when it tries to delineate basins. A sink is a cell that somehow flows into
itself; I think it’s a local closed basin. Luckily, there’s a way to get rid of sinks. Once
you successfully do that, you can get on with the real business of delineating basins.
How to fill sinks:
According to the Arc help, to fill sinks all you need is the “fill” command and an input
elevation grid. The “fill” command is used like this:
fill elev elev_nosink
Here “elev” is the input elevation grid, and “elev_nosink” is the output grid after the
sinks have been filled. You can add a couple more optional parameters to the fill
command, such as
fill elev elev_nosink sink 100 flowdir
Here “sink” means “fill up the sinks, don’t cut off the peaks”, “100” means fill up all
sinks less than 100 meters deep (or whatever units “elev” is in), and “flowdir” means
“create another grid called “flowdir” after filling the sinks, and the “flowdir” grid will be
exactly the same type of grid created by the “flowdirection” command”.
This command takes some time (maybe ~10 minutes, depending on the file size) in Arc.
The fill command runs iteratively, because it can create new sinks by filling in the
original sinks. So it just keeps going until all the sinks are filled. It’ll tell you it’s done
by writing “Number of sink(s): -1”.
After the sinks are filled, the next step is to create a “flowdirection” grid. (Note: you can
also do this automatically with the “fill” command in the previous step, if you prefer.)
flowdir = flowdirection(elev_nosink)
This creates a grid that indicates, for each cell, which neighboring cell it flows
into. It is necessary to create this flowdirection grid after filling the sinks, and
before running the “watershed” command.
Now you can actually try to delineate a watershed. First, make sure the grid is visible in
the image window. Picking a starting point for the “watershed” command is easiest if the
image is a shaded relief image, so create a shaded relief map and plot it.
elev_shd = hillshade(elev)
mape elev_shd
image elev_shd
2/16/2016
Now that elev_shd is visible in the image window, go ahead and use the “watershed”
command.
wshed = watershed(flowdir, selectpoint(elev_nosink, *))
The watershed command is the crucial part of the whole process. If everything
works right, it automatically delineates the basin you’re interested in. It requires
two inputs: a flowdirection grid and a single point to start from. The above syntax
(the “selectpoint(elev_nosink, *)” part) allows you to pick a point with the mouse.
After clicking once with the mouse on the outlet of the basin you’re interested in,
press “9”. After Arc tells you it delineated a basin, check to see if it worked by
imaging the new grid you just created.
mape wshed
image wshed
A white watershed should show up in the image window on a black background.
If it doesn’t, the command didn’t work and you have to try again. If you keep
trying and it never works, try picking an outlet point with “snappour”.
How to use “snappour”:
Sometimes it’s really difficult to get the watershed command to work because it’s hard to
click on the outlet of the basin. You can get around this problem by creating a point at
the outlet of the basin. The trick is using the command “snappour”.
Snappour takes a few inputs: a point to start searching from, a flowaccumulation grid,
and a maximum distance to search. The first thing to do is to create a flowaccumulation
grid. This takes some time. For example, it took about 10 minutes to process my
Redwood Creek file, which was 24 quads worth of 10m SDTS data. The
flowaccumulation command requires only one input, a flowdirection grid.
flowacc = flowaccumulation(flowdir)
Now create the outlet point.
outletpt = snappour(*, flowacc, 100)
This command will create a point called outletpt. The starting point is defined by the
mouse (that’s what the * means), the flowaccumulation grid is flowacc, and the
maximum distance to search is 100 pixels (I think it’s pixels) away from the point
selected by the mouse.
After you’ve created outletpt, you can use that as an input into the watershed command.
wshed = watershed(flowdir, outletpt)
2/16/2016
Hopefully that’ll work better.
Once you’ve successfully delineated the watershed, you need to turn off all the points
outside the watershed, and create a new grid that only contains elevations inside the
watershed.
setmask wshed
Setmask turns off everything outside the delineated watershed.
After you apply the mask, you can create a new grid that only contains data (e.g.
elevation) inside the watershed. Everything outside the watershed is considered
“nodata”, or something like that. Here’s an example.
mape wshed
image wshed
setmask wshed
temp_grid = elev
image temp_grid
(This is just to check that “temp_grid” really is there.)
basinname = temp_grid
The above commands leave you with the desired end result: a drainage basin grid entitled
“basinname”, cut out all by itself. Now we can look at it, and get a few important basin
characteristics out of it.
mape basinname
image basinname
describe basinname
“describe” gives a short list of the characteristics of the input grid. For example,
it gives the mean elevation of the basin.
If you want to find the mean hillslope gradients inside the watershed, you can easily
create a new grid of slopes, and then “describe” the slope grid.
basinslope = slope(basinname)
The “slope” command identifies the rate of maximum change in z from each cell.
By default, it calculates slope in degrees. If you prefer to have the slopes in
percentages, type “slope(basinname, percentrise)” instead.
describe basinslope
Other stuff:
I don’t know how to zoom, but there’s a way to sort of zoom. It involves drawing a box
and creating a new grid. Let’s say you start with an elevation grid called elev, but elev is
2/16/2016
very big, and you’re interested only in a small portion of elev. Here’s how you can sort
of zoom:
mape elev
image elev
setwindow *
This allows you to create a box on the image with the mouse. Create a box
around the small portion of elev that you’re interested in.
elev_small = elev
Now you’ve just created a new grid “elev_small” that is the size of the window
you just defined with setwindow, and the data in elev_small is the same data that
is in elev. Check it out.
mape elev_small
image elev_small
There’s another way to do this, too, which is even easier. It’s not a zoom function either,
but it is a way to create a new, smaller grid, with the function “gridclip”. You also use
the mouse to create a new box around the area you’re interested in.
mape elev
image elev
gridclip elev elev_small
Click the mouse in two different places to delineate a new rectangular grid around the
area of interest, and presto, you’ve got a new grid called “elev_small”.
________________________________________________________________________
How to create a histogram of elevations:
histogram basinname
That creates a plot of elevations for the file “basinname”. Looks very nice. But where
are the data in the histogram stored? I want that file. RAR! It doesn’t give you the data
– it only gives you the plot of the data. How frustrating.
________________________________________________________________________
How to output an Arc file into MATLAB:
This procedure requires a few different steps, a few homemade commands and some help
from Taylor. First, convert the grid into an Arc ASCII file. Then, convert that Arc ASCII
file into a Surfer ASCII file. Then convert that Surfer ASCII file into a MATLABreadable matrix.
To convert an Arc grid into an Arc ASCII file, open ArcToolbox and click on Export
From Raster  Grid to ASCII. Find the correct input grid (e.g. c:\users\ken\caspar\car)
2/16/2016
and give it a new filename to output the new ASCII file to (e.g. …\ken\caspar\car.asc).
Note: ArcToolbox can do this in batches.
You can also do this with the “gridascii” command in Arc’s grid window. As an
example, I did:
newfilename.asc = gridascii(oldfilename)
And that produced a file called newfilename.asc, which is an ASCII grid.
To convert that Arc grid into an Arc ASCII file, use the homemade command “arc2surf”,
which I think Dino created. This has to be done in a Unix shell from one of the machines
that has arc2surf in its active directory. It works like this:
arc2surf inputfile.asc > outputfile.grd
For example, I wrote
arc2surf car.asc > car.grd
The .grd file is a Surfer ASCII grid.
Then, to convert the Surfer .grd file into a MATLAB-readable file, use Taylor’s
homemade ReadSuferGrid.m file. Open MATLAB, and type
[M dimensions] = readsurfergrid(‘car.grd’);
This yields a grid called “car” which is the rectangular matrix of all the elevations in
car.grd. Unfortunately, it also contains all the non-data cells, which Surfer gives a value
of 1.7014*10^38. Blech. You can turn all of those into NaN pretty simply:
[nrow2 ncol2] = size(M2);
for i=1:nrow2
for j=1:ncol2
if M2(i,j) < 10000
M2new(i,j) = M2(i,j);
else
M2new(i,j) = NaN;
end
end
end
% or whatever cutoff elevation you choose
Now you’ve got a matrix called Mnew, where all the non-data cells are NaN’s. The
histogram function, “hist”, accepts vectors easily but does something weird with
matrices. So the first thing to do is to put Mnew into a single vector form so hist can read
it. Call the new vector “b”, for no reason other than expediency.
b2 = [ ];
2/16/2016
for i=1:nrow2
b2 = [b2 M2new(i , :)];
end
The vector b contains all of matrix Mnew in a single column. Now you can run the “hist”
function. First thing you want to do is figure out how many bins you want. I’ve created
10 meter sized bins, with the centers halfway between the 10m intervals (i.e. centers at
125m, 135m, 145m, etc.). To do this in 10m intervals all the way along the possible data,
you need to know the range of elevations.
low=min(b);
high=max(b);
Then, create a vector “x” that lists the centers of all the 10m intervals. If the elevations
go from 100m to 700m, then x = [ 105 115 125 … 695 ]. A quicker way to do it is
x = [105:10:695]. The trick is knowing how to tell MATLAB the starting and ending
points.
You know what? I put this all in an m-file named “histelev.m”. It does everything (after
you have a Surfer .grd file.) C:\users\ken\surfer\histelev.m.
Download