SlideShare a Scribd company logo
1 of 13
Download to read offline
This and more at my website: https://sites.google.com/site/sorsbysj/
LinkedIn: https://www.linkedin.com/in/skylersorsby
Calculating Sinuosity for a stream raster with moving-window analysis in GRASS
By Skyler Sorsby
Among the many useful
hydrological tools present in
GRASS GIS, The ‘sinuos’ option
of the v.to.db module provides the
means to extract channel
sinuosity for a segmented vector
line. Sinuosity, a measure of
channel curviness is expressed
by the formula:
𝑆𝑖𝑛𝑢𝑜𝑠𝑖𝑡𝑦 =
𝑃𝑙𝑎𝑛𝑓𝑜𝑟𝑚 𝑑𝑖𝑠𝑡𝑎𝑛𝑐𝑒
𝑆𝑡𝑟𝑎𝑖𝑔ℎ𝑡 𝑙𝑖𝑛𝑒 𝑑𝑖𝑠𝑡𝑎𝑛𝑐𝑒
where distances are measured
between two points at different
locations along a stream
channel’s path. Planform distance
describes the space along the
river between the two points,
while straight line distance is
simply the smallest gap between
those points “as the crow flies”
(Fig. 1). This channel ‘curviness’ parameter is useful for parameterizing stream maturity.
Greater curves, or ‘meanders’, indicate more-erodible substrate, lower stream energy,
and lower-relief topography proximal to the planform, all
else being equal. Additionally, stream channels may
become more sinuous as they cross zones of tectonic tilting.
Due to the law of conservation of energy, systems tend to
resist change. As a floodplain tilts, river channels become
more curve-y, such that more of the channel’s reach is
perpendicular to the maximum downstream gradient. This
has the effect of minimizing the change in stream power
(and thus energy level) of the fluvial network. As such,
sinuosity bears important tectonic implications.
Channel sinuosity values are generally rough estimates,
performed by hand. Each calculation requires a reasonably
long segment of channel. For example, choosing to
calculate over the entire planform extent will give an accurate value for the stream’s
sinuosity, yet one that is quite generalized. Conversely, performing the calculation over a
short distance may prove unusable if the river fails to curve much in between. A standard
Figure 1. Sinuosity is a distance ratio, a river’s
‘curviness’ parameter.
Figure 2. River distance ~
straight line distance…
for the whole stream! The
window is too narrow.
This and more at my website: https://sites.google.com/site/sorsbysj/
LinkedIn: https://www.linkedin.com/in/skylersorsby
compromise is to measure over a distance equal to one (or one-half) wavelength of the
river’s general periodic curve.
One problem with making a single calculation over a segment of a river, however, is that
it treats change in a discrete manner. Planform geometry, however, varies gradationally
along a river’s course. Accordingly, sinuosity measurements, although dependent on
adjacent upstream and downstream portions of a river, must be calculated in a way that
shows gradational change. My proposed solution to this problem is to utilize a sufficiently
long moving-window for each downstream step. With this approach, higher-resolution,
continuous sinuosity is calculated over a representative, wavelength-scale reach
surrounding each pixel in a stream raster.
Here, I offer for review a new method for digitally calculating channel sinuosity, using the
r.mapcalc, r.stream.distance, and r.neighbors GRASS modules. Additionally, I provide
the Python code to perform this calculation in an automated GRASS script.
Sinuosity Workflow:
*NOTE: this workflow requires the freely-accessible r.stream.distance GRASS Addon*
(Obtain r.stream distance from SettingsAddons extensions g.extention)
1) Derive your stream channel segments vector with r.watershed. Trim it to main
channels with the vector editor, such that the necessary moving window size will NOT
overlap multiple channels (in many places). Once you’re satisfied, convert your trimmed
vector stream map to a raster map (make sure g.region is current!) with VectorMap
type conversionsVector to raster. Choose ‘lines’ as the type, the ‘val’ parameter (NOT
‘attr’!), and make sure that the ‘val’ value is set to 1.
1a) Alternatively, if you’re satisfied with your stream segments map directly from
r.watershed’s output, convert it to binary (channel pixels=1, all else=0) by hand: Use
r.mapcalculator to divide your segments raster map by itself.
Figure 3. The stream segments raster is fed through r.mapcalculator.
This and more at my website: https://sites.google.com/site/sorsbysj/
LinkedIn: https://www.linkedin.com/in/skylersorsby
2) Generate a ‘Stream distance’ map using r.stream.distance. To do this, you will need
a rasterized map of channel outlets. Use the heads-up digitizer to place points squarely
on top of each channel outlet (last, lowest) pixel of the new binary stream map. Save
your edits, quit the digitizer. Next, use VectorMap type conversionsv.to.rast again,
this time to rasterize your points.
Next, input your Flow Direction raster (output of r.watershed) and your rasterized
channel outlets map in the ‘Required’ tab. In the ‘Optional’ tab, input your DEM (used in
r.watershed) as the elevation map. Name the output distance map. Check the –o flag
(Calculate parameters for outlets). Hit ‘Run’.
Figure 4. My outlets map (still need to
convert from vector to raster)
Figure 5. r.stream.distance interface. Freely-
downloadable, use SettingsAddons
extensions g.extention.
3) Now that you have a raster of channel distance, you need to somehow generate
maps of Easting and Northing to eventually calculate straight-line distance. Here’s’ how:
a) In r.mapcalculator, name your new map (EW_coord, or something like that), and
select the x() function. Just leave those three characters by themselves in the
calculations window. Just leave ‘em. Hit ‘Run’. This will auto-generate a map of East-
West UTM coordinates (You SHOULD be in UTM coordinates from the get-go).
b) Type y() into the command window, name your Northings map something
memorable, and hit ‘Run’ to auto-generate a map of North-South UTM coordinates.
This and more at my website: https://sites.google.com/site/sorsbysj/
LinkedIn: https://www.linkedin.com/in/skylersorsby
Figure 6. The syntax for creating Easting and Northing maps is quite simple!
4) Now, impart the Easting, Northing, and River Distance map data to your binary
stream channels. This is done in r.mapcalculator by:
streams_binary * Eastingmap
streams_binary * Northingmap
streams_binary * RiverDistancemap
You’ll have to run r.mapcalculator three times—one for each calculation (such that a
new map is created each time).
5) Now, you should have three stream rasters with Easting, Northing, and stream-
parallel distance as their respective pixel values. Now you need to use a moving-
window to take these absolute distances and calculate discrete stepwise distances for a
specified area around each stream pixel in each of the three rasters. To do this, use
r.neighbors. It will get slightly complicated.
r.neighbors is simple to use for calculating averages of proximal values in a raster. What
it’s not intuitively good at is looking a set distance away from the pixel in question for
values, like we would need in order to standardize our distance calculation procedure.
To create an “annular” search radius, instead of including every pixel nearby, you need
to create a weights file.
A weights file is, simply a text file with a series of numbers, each separated by a space.
For a 3x3 search window of normal weights, type 1 1 1 1 1 1 1 1 1 . GRASS sees:
1 1 1
1 1 1
1 1 1
The pixel receiving the output of the calculation is always the central one. Subsequently,
your moving-average window MUST always have an odd width! For a 5x5 hollow
This and more at my website: https://sites.google.com/site/sorsbysj/
LinkedIn: https://www.linkedin.com/in/skylersorsby
(“annular”) search window, type 1 1 1 1 1 1 0 0 0 1 1 0 0 0 1 1 0 0 0 1 1 1 1 1 1 .
GRASS sees:
1 1 1 1 1
1 0 0 0 1
1 0 0 0 1
1 0 0 0 1
1 1 1 1 1
This will probably not be large enough for a sinuosity calculation; you will have to
determine how many pixels the wavelength is, and size your weights file accordingly.
Save it somewhere convenient, and use it as an input to r.neighbors.
The importance of an annular weights file, and the trick to this
methodology:
If you let r.neighbors run ‘as is’, with only a numeric value for the window size (i.e., no
weights file), you will include every point within your window in the calculation. Since
you only want to deal with two points on the stream, you need to hand-make the search
window into an annulus. Thus, with a large enough window, only two points on the
stream will be consulted for each calculation. With the weighting and size parameters
held the same, the corresponding pixels in each raster map will corresponding points on
each stream.
Another technicality of r.neighbors, the binary weighting scheme I’ve devised will only
work for neighborhood statistics that are “unaffected” by weighting: local minimum, local
maximum, diversity, interspersion. So, to get my relative Easting and Northing values
for my straight-line calculation, I need to use my annular-weighted r.neighbors moving
window to find the maximum Easting stream pixel (1 of 2 pixels total) and the minimum
Easting stream pixel (2 of 2 pixels total), the maximum Northing stream pixel (1 of 2
pixels total) and minimum Northing pixel (2 of 2 pixels total), and finally the maximum
river distance (1 of 2 pixels total) and the minimum river distance total (2 of 2 pixels
total). This will require you to run the r.neighbors module six times, unfortunately. On
the bright side, compiling these instructions into a Python script (code included at the
end of the document) will allow you to perform these steps very rapidly.
This and more at my website: https://sites.google.com/site/sorsbysj/
LinkedIn: https://www.linkedin.com/in/skylersorsby
Figure 7. Visualization of single pixel
width “annular” search window. The
desired statistic is assigned to the pixel in
the center of the window. Statistics are
run for each pixel in the raster map.
Figure 8. The six rasters you must
produce with r.neighbors. Note that only
the two single pixels that intersect the
stream on the outermost edge of the
window will be factored into the statistics.
Figure 9. NS=Northing, EW=Easting. This
is the derivation of the straight-line
distance from the Pythagorean Theorem
Figure 10. River distances are found for
the same two pixels, due to the use of the
same weight file and window size!
This and more at my website: https://sites.google.com/site/sorsbysj/
LinkedIn: https://www.linkedin.com/in/skylersorsby
6) Now, you should have six output maps, containing max and min Northing, max and
min Easting, and max and min river distances for corresponding pixels in each stream
raster. The problem now, is, the stream lines are suddenly quite thick! Remember that
r.neighbors acts upon each cell within the raster—if any of the zero-value cells sees a
stream cell intersecting its “annular” search window, it will nab that stream cell’s value.
Don’t worry—this doesn’t affect the stream cells. We haven’t run multiple iterations.
The fix is simple: multiply each output map by your binary stream map (1’s and 0’s) to
extract Northings, Eastings, and stream distances for only stream pixels.
7) Now, use some fancy map algebra and the Pythagorean Theorem to derive a
straight-line distance for each pixel in the study area:
sqrt( (EastingMax – EastingMin)^2 + (NorthingMax – NorthingMin)^2 )
NOTE: this is too complex for Python scripting, and requires “Expert mode”. I reduce its
complexity instead by removing the squaring notation:
sqrt( (EastingMax – EastingMin)* (EastingMax – EastingMin) + (NorthingMax – NorthingMin)* (NorthingMax – NorthingMin) )
8) Use less-fancy map algebra to derive stream distance for each pixel in the study
area:
StreamDistanceMax – StreamDistanceMin
9) Finally, use Map Algebra to divide StreamDistance by StraighLineDistance:
StreamDistance / StraightLineDistance
And, voila! You have sinuosity calculated over a desired moving window for each pixel
in your stream system, no manual calculations required. Although no more
representative than calculating sinuosity for set blocks of vector stream segments with
v.to.db, this approach may produce results that are more easily-manipulated and useful
to work with!
This and more at my website: https://sites.google.com/site/sorsbysj/
LinkedIn: https://www.linkedin.com/in/skylersorsby
My Python code for automating the above steps
(usable as a GRASS GIS script):
#!/usr/bin/env python
#
# g.parser demo script for python programing
#%module
#% description: g.parser test script (python)
#%end
#%option
#% key: raster1
#% type: string
#% gisprompt: old,cell,raster
#% description: Flow Direction Map:
#% required : yes
#%end
#%option
#% key: raster2
#% type: string
#% gisprompt: old,cell,raster
#% description: DEM
#% required : yes
#%end
#%option
#% key: raster3
#% type: string
#% gisprompt: old,cell,raster
#% description: Outlet nodes (rasterized points):
#% required : yes
#%end
#%option
#% key: raster4
#% type: string
#% gisprompt: old,cell,raster
#% description: Stream segment raster (r.watershed output):
#% required : yes
#%end
#%option
#% key: windowsize
#% type: integer
#% description: Width of moving window
#% required : yes
#%end
This and more at my website: https://sites.google.com/site/sorsbysj/
LinkedIn: https://www.linkedin.com/in/skylersorsby
#%option
#% key: weights
#% type: string
#% gisprompt: old,file,input
#% description: Input weight file (annular):
#% required : yes
#%end
##############################################################################
##
#
# MODULE: Sinuosity Calculator
#
# AUTHOR: Skyler Sorsby
#
# PURPOSE: GRASS’ wxGUI model builder was ultimately too unreliable and buggy for me
# to be satisfied with automating the sinuosity calculator that way.
#
# DATE: Sat Feb 15 17:39:36 2014
#
##############################################################################
##
import sys
import os
import atexit
import grass.script as grass
def cleanup():
pass
def main():
FloDir=options['raster1']
DEM=options['raster2']
OutletNodes=options['raster3']
WindowSize=options['windowsize']
streamsegs=options['raster4']
grass.run_command("r.mapcalculator",
amap = streamsegs,
overwrite = True,
formula = "A/A",
outfile = "streams_binary",
help = "-")
grass.run_command("r.mapcalculator",
overwrite = True,
This and more at my website: https://sites.google.com/site/sorsbysj/
LinkedIn: https://www.linkedin.com/in/skylersorsby
formula = "x()",
outfile = "EW_dist",
help = "-")
grass.run_command("r.mapcalculator",
overwrite = True,
formula = "y()",
outfile = "NS_dist",
help = "-")
grass.run_command("r.stream.distance",
stream = OutletNodes,
dir = FloDir,
dem = DEM,
flags = 'o',
overwrite = True,
method = "downstream",
distance = "Dist_map")
grass.run_command("r.mapcalculator",
overwrite = True,
amap = "streams_binary",
bmap = "EW_dist",
formula = "A*B",
outfile = "EW_streams",
help = "-")
grass.run_command("r.mapcalculator",
overwrite = True,
amap = "streams_binary",
bmap = "NS_dist",
formula = "A*B",
outfile = "NS_streams",
help = "-")
grass.run_command("r.mapcalculator",
overwrite = True,
amap = "streams_binary",
bmap = "Dist_map",
formula = "A*B",
outfile = "Dist_streams",
help = "-")
grass.run_command("r.neighbors",
overwrite = True,
input = "EW_streams",
output = "EW_streams_max",
method = "maximum",
size = WindowSize,
weight = options['weights'])
grass.run_command("r.neighbors",
overwrite = True,
This and more at my website: https://sites.google.com/site/sorsbysj/
LinkedIn: https://www.linkedin.com/in/skylersorsby
input = "EW_streams",
output = "EW_streams_min",
method = "minimum",
size = WindowSize,
weight = options['weights'])
grass.run_command("r.neighbors",
overwrite = True,
input = "NS_streams",
output = "NS_streams_max",
method = "maximum",
size = WindowSize,
weight = options['weights'])
grass.run_command("r.neighbors",
overwrite = True,
input = "NS_streams",
output = "NS_streams_min",
method = "minimum",
size = WindowSize,
weight = options['weights'])
grass.run_command("r.neighbors",
overwrite = True,
input = "Dist_streams",
output = "Dist_streams_diff",
method = "range",
size = WindowSize,
weight = options['weights'])
grass.run_command("r.mapcalculator",
overwrite = True,
amap = "streams_binary",
bmap = "EW_streams_max",
formula = "A*B",
outfile = "EW_streams_max_thinned",
help = "-")
grass.run_command("r.mapcalculator",
overwrite = True,
amap = "streams_binary",
bmap = "EW_streams_min",
formula = "A*B",
outfile = "EW_streams_min_thinned",
help = "-")
grass.run_command("r.mapcalculator",
overwrite = True,
amap = "streams_binary",
bmap = "NS_streams_max",
formula = "A*B",
outfile = "NS_streams_max_thinned",
This and more at my website: https://sites.google.com/site/sorsbysj/
LinkedIn: https://www.linkedin.com/in/skylersorsby
help = "-")
grass.run_command("r.mapcalculator",
overwrite = True,
amap = "streams_binary",
bmap = "NS_streams_min",
formula = "A*B",
outfile = "NS_streams_min_thinned",
help = "-")
grass.run_command("r.mapcalculator",
overwrite = True,
amap = "streams_binary",
bmap = "Dist_streams_diff",
formula = "A*B",
outfile = "Dist_streams_diff_thinned",
help = "-")
grass.run_command("r.mapcalculator",
overwrite = True,
amap = "EW_streams_max_thinned",
bmap = "EW_streams_min_thinned",
cmap = "NS_streams_max_thinned",
dmap = "NS_streams_min_thinned",
formula = "sqrt((A-B)*(A-B)+(C-D)*(C-D))",
outfile = "A_straightline_dist",
help = "-")
grass.run_command("r.mapcalculator",
overwrite = True,
amap = "Dist_streams_diff_thinned",
bmap = "A_straightline_dist",
formula = "A/B",
outfile = "A_stream_sinuosity",
help = "-")
return 0
if __name__ == "__main__":
options, flags = grass.parser()
atexit.register(cleanup)
sys.exit(main())
This and more at my website: https://sites.google.com/site/sorsbysj/
LinkedIn: https://www.linkedin.com/in/skylersorsby

More Related Content

What's hot

Passive and active sensors
Passive and active sensorsPassive and active sensors
Passive and active sensorsVivek Srivastava
 
Spatial analysis & interpolation in ARC GIS
Spatial analysis & interpolation in ARC GISSpatial analysis & interpolation in ARC GIS
Spatial analysis & interpolation in ARC GISKU Leuven
 
Remote Sensing: Resolution Merge
Remote Sensing: Resolution MergeRemote Sensing: Resolution Merge
Remote Sensing: Resolution MergeKamlesh Kumar
 
Spatial interpolation techniques
Spatial interpolation techniquesSpatial interpolation techniques
Spatial interpolation techniquesManisha Shrivastava
 
Supervised and unsupervised classification techniques for satellite imagery i...
Supervised and unsupervised classification techniques for satellite imagery i...Supervised and unsupervised classification techniques for satellite imagery i...
Supervised and unsupervised classification techniques for satellite imagery i...gaup_geo
 
Digital image processing 1
Digital  image processing 1Digital  image processing 1
Digital image processing 1Dhaval Jalalpara
 
Applications of gis
Applications of gisApplications of gis
Applications of gisPramoda Raj
 
Topografia ii ing claudia reyes (2)
Topografia ii ing claudia reyes (2)Topografia ii ing claudia reyes (2)
Topografia ii ing claudia reyes (2)BorisUrrutia
 
Surface Analysis in GIS
Surface Analysis in GISSurface Analysis in GIS
Surface Analysis in GISRituSaha3
 
Green space suitability evaluation for urban resilience converted
Green space suitability evaluation for urban resilience convertedGreen space suitability evaluation for urban resilience converted
Green space suitability evaluation for urban resilience convertedShiva Pokhrel
 
Derive hypsometric curves in GRASS GIS
Derive hypsometric curves in GRASS GISDerive hypsometric curves in GRASS GIS
Derive hypsometric curves in GRASS GISSkyler Sorsby
 
Map Projection
Map ProjectionMap Projection
Map Projectionmekinglove
 
TU1.L09.1 - APPLICATION OF POLARIMETRIC SAR TO EARTH REMOTE SENSING
TU1.L09.1	 - APPLICATION OF POLARIMETRIC SAR TO EARTH REMOTE SENSINGTU1.L09.1	 - APPLICATION OF POLARIMETRIC SAR TO EARTH REMOTE SENSING
TU1.L09.1 - APPLICATION OF POLARIMETRIC SAR TO EARTH REMOTE SENSINGgrssieee
 

What's hot (20)

Passive and active sensors
Passive and active sensorsPassive and active sensors
Passive and active sensors
 
Spatial analysis & interpolation in ARC GIS
Spatial analysis & interpolation in ARC GISSpatial analysis & interpolation in ARC GIS
Spatial analysis & interpolation in ARC GIS
 
TIN IN GIS
TIN IN GISTIN IN GIS
TIN IN GIS
 
Remote Sensing: Resolution Merge
Remote Sensing: Resolution MergeRemote Sensing: Resolution Merge
Remote Sensing: Resolution Merge
 
Spatial interpolation techniques
Spatial interpolation techniquesSpatial interpolation techniques
Spatial interpolation techniques
 
GIS - Topology
GIS - Topology GIS - Topology
GIS - Topology
 
Gis applications
Gis applicationsGis applications
Gis applications
 
Raster processing
Raster processingRaster processing
Raster processing
 
Remote Sensin
Remote SensinRemote Sensin
Remote Sensin
 
Supervised and unsupervised classification techniques for satellite imagery i...
Supervised and unsupervised classification techniques for satellite imagery i...Supervised and unsupervised classification techniques for satellite imagery i...
Supervised and unsupervised classification techniques for satellite imagery i...
 
Digital image processing 1
Digital  image processing 1Digital  image processing 1
Digital image processing 1
 
Applications of gis
Applications of gisApplications of gis
Applications of gis
 
Topografia ii ing claudia reyes (2)
Topografia ii ing claudia reyes (2)Topografia ii ing claudia reyes (2)
Topografia ii ing claudia reyes (2)
 
Surface Analysis in GIS
Surface Analysis in GISSurface Analysis in GIS
Surface Analysis in GIS
 
Stereoscopic Parallax
Stereoscopic ParallaxStereoscopic Parallax
Stereoscopic Parallax
 
Green space suitability evaluation for urban resilience converted
Green space suitability evaluation for urban resilience convertedGreen space suitability evaluation for urban resilience converted
Green space suitability evaluation for urban resilience converted
 
Digital image processing
Digital image processingDigital image processing
Digital image processing
 
Derive hypsometric curves in GRASS GIS
Derive hypsometric curves in GRASS GISDerive hypsometric curves in GRASS GIS
Derive hypsometric curves in GRASS GIS
 
Map Projection
Map ProjectionMap Projection
Map Projection
 
TU1.L09.1 - APPLICATION OF POLARIMETRIC SAR TO EARTH REMOTE SENSING
TU1.L09.1	 - APPLICATION OF POLARIMETRIC SAR TO EARTH REMOTE SENSINGTU1.L09.1	 - APPLICATION OF POLARIMETRIC SAR TO EARTH REMOTE SENSING
TU1.L09.1 - APPLICATION OF POLARIMETRIC SAR TO EARTH REMOTE SENSING
 

Similar to Calculation of sinuosity in GRASS GIS

Create swath profiles in GRASS GIS
Create swath profiles in GRASS GISCreate swath profiles in GRASS GIS
Create swath profiles in GRASS GISSkyler Sorsby
 
Exercise advanced gis_and_hydrology
Exercise advanced gis_and_hydrologyExercise advanced gis_and_hydrology
Exercise advanced gis_and_hydrologyBUGINGO Annanie
 
Controlled assessment - Data Presentation
Controlled assessment - Data PresentationControlled assessment - Data Presentation
Controlled assessment - Data PresentationRCB78
 
YARCA (Yet Another Raycasting Application) Project
YARCA (Yet Another Raycasting Application) ProjectYARCA (Yet Another Raycasting Application) Project
YARCA (Yet Another Raycasting Application) Projectgraphitech
 
JGrass: the Horton machine (FOSS4G2008)
JGrass: the Horton machine (FOSS4G2008)JGrass: the Horton machine (FOSS4G2008)
JGrass: the Horton machine (FOSS4G2008)Andrea Antonello
 
Design and Implementation of Mobile Map Application for Finding Shortest Dire...
Design and Implementation of Mobile Map Application for Finding Shortest Dire...Design and Implementation of Mobile Map Application for Finding Shortest Dire...
Design and Implementation of Mobile Map Application for Finding Shortest Dire...Eswar Publications
 
How to choose a map projection guide.pdf
How to choose a map projection guide.pdfHow to choose a map projection guide.pdf
How to choose a map projection guide.pdfAndrew Scholl
 
Geomorphology Maps
Geomorphology MapsGeomorphology Maps
Geomorphology Mapshaythemdinar
 
EFFECTIVE INTEREST REGION ESTIMATION MODEL TO REPRESENT CORNERS FOR IMAGE
EFFECTIVE INTEREST REGION ESTIMATION MODEL TO REPRESENT CORNERS FOR IMAGE EFFECTIVE INTEREST REGION ESTIMATION MODEL TO REPRESENT CORNERS FOR IMAGE
EFFECTIVE INTEREST REGION ESTIMATION MODEL TO REPRESENT CORNERS FOR IMAGE sipij
 
Continuing Our Look At Primary And Secondary Data
Continuing Our Look At Primary And Secondary DataContinuing Our Look At Primary And Secondary Data
Continuing Our Look At Primary And Secondary Dataguest2137aa
 
Continuing Our Look At Primary And Secondary Data
Continuing Our Look At Primary And Secondary DataContinuing Our Look At Primary And Secondary Data
Continuing Our Look At Primary And Secondary Dataguest9fa52
 
The GRASS GIS software (with QGIS) - GIS Seminar
The GRASS GIS software (with QGIS) - GIS SeminarThe GRASS GIS software (with QGIS) - GIS Seminar
The GRASS GIS software (with QGIS) - GIS SeminarMarkus Neteler
 
Machine learning for high-speed corner detection
Machine learning for high-speed corner detectionMachine learning for high-speed corner detection
Machine learning for high-speed corner detectionbutest
 

Similar to Calculation of sinuosity in GRASS GIS (20)

Create swath profiles in GRASS GIS
Create swath profiles in GRASS GISCreate swath profiles in GRASS GIS
Create swath profiles in GRASS GIS
 
Exercise advanced gis_and_hydrology
Exercise advanced gis_and_hydrologyExercise advanced gis_and_hydrology
Exercise advanced gis_and_hydrology
 
FinalPresentation
FinalPresentationFinalPresentation
FinalPresentation
 
Controlled assessment - Data Presentation
Controlled assessment - Data PresentationControlled assessment - Data Presentation
Controlled assessment - Data Presentation
 
YARCA (Yet Another Raycasting Application) Project
YARCA (Yet Another Raycasting Application) ProjectYARCA (Yet Another Raycasting Application) Project
YARCA (Yet Another Raycasting Application) Project
 
Flood plain mapping
Flood plain mappingFlood plain mapping
Flood plain mapping
 
Iris
IrisIris
Iris
 
Description Of A Graph
Description Of A GraphDescription Of A Graph
Description Of A Graph
 
06 Vector Visualization
06 Vector Visualization06 Vector Visualization
06 Vector Visualization
 
JGrass: the Horton machine (FOSS4G2008)
JGrass: the Horton machine (FOSS4G2008)JGrass: the Horton machine (FOSS4G2008)
JGrass: the Horton machine (FOSS4G2008)
 
Design and Implementation of Mobile Map Application for Finding Shortest Dire...
Design and Implementation of Mobile Map Application for Finding Shortest Dire...Design and Implementation of Mobile Map Application for Finding Shortest Dire...
Design and Implementation of Mobile Map Application for Finding Shortest Dire...
 
How to choose a map projection guide.pdf
How to choose a map projection guide.pdfHow to choose a map projection guide.pdf
How to choose a map projection guide.pdf
 
Geomorphology Maps
Geomorphology MapsGeomorphology Maps
Geomorphology Maps
 
EFFECTIVE INTEREST REGION ESTIMATION MODEL TO REPRESENT CORNERS FOR IMAGE
EFFECTIVE INTEREST REGION ESTIMATION MODEL TO REPRESENT CORNERS FOR IMAGE EFFECTIVE INTEREST REGION ESTIMATION MODEL TO REPRESENT CORNERS FOR IMAGE
EFFECTIVE INTEREST REGION ESTIMATION MODEL TO REPRESENT CORNERS FOR IMAGE
 
WATERSHED ANALYSIS .pptx
WATERSHED ANALYSIS .pptxWATERSHED ANALYSIS .pptx
WATERSHED ANALYSIS .pptx
 
Continuing Our Look At Primary And Secondary Data
Continuing Our Look At Primary And Secondary DataContinuing Our Look At Primary And Secondary Data
Continuing Our Look At Primary And Secondary Data
 
Continuing Our Look At Primary And Secondary Data
Continuing Our Look At Primary And Secondary DataContinuing Our Look At Primary And Secondary Data
Continuing Our Look At Primary And Secondary Data
 
The GRASS GIS software (with QGIS) - GIS Seminar
The GRASS GIS software (with QGIS) - GIS SeminarThe GRASS GIS software (with QGIS) - GIS Seminar
The GRASS GIS software (with QGIS) - GIS Seminar
 
NavMesh
NavMeshNavMesh
NavMesh
 
Machine learning for high-speed corner detection
Machine learning for high-speed corner detectionMachine learning for high-speed corner detection
Machine learning for high-speed corner detection
 

Recently uploaded

Types of different blotting techniques.pptx
Types of different blotting techniques.pptxTypes of different blotting techniques.pptx
Types of different blotting techniques.pptxkhadijarafiq2012
 
Stunning ➥8448380779▻ Call Girls In Panchshil Enclave Delhi NCR
Stunning ➥8448380779▻ Call Girls In Panchshil Enclave Delhi NCRStunning ➥8448380779▻ Call Girls In Panchshil Enclave Delhi NCR
Stunning ➥8448380779▻ Call Girls In Panchshil Enclave Delhi NCRDelhi Call girls
 
STERILITY TESTING OF PHARMACEUTICALS ppt by DR.C.P.PRINCE
STERILITY TESTING OF PHARMACEUTICALS ppt by DR.C.P.PRINCESTERILITY TESTING OF PHARMACEUTICALS ppt by DR.C.P.PRINCE
STERILITY TESTING OF PHARMACEUTICALS ppt by DR.C.P.PRINCEPRINCE C P
 
Animal Communication- Auditory and Visual.pptx
Animal Communication- Auditory and Visual.pptxAnimal Communication- Auditory and Visual.pptx
Animal Communication- Auditory and Visual.pptxUmerFayaz5
 
Nanoparticles synthesis and characterization​ ​
Nanoparticles synthesis and characterization​  ​Nanoparticles synthesis and characterization​  ​
Nanoparticles synthesis and characterization​ ​kaibalyasahoo82800
 
All-domain Anomaly Resolution Office U.S. Department of Defense (U) Case: “Eg...
All-domain Anomaly Resolution Office U.S. Department of Defense (U) Case: “Eg...All-domain Anomaly Resolution Office U.S. Department of Defense (U) Case: “Eg...
All-domain Anomaly Resolution Office U.S. Department of Defense (U) Case: “Eg...Sérgio Sacani
 
Physiochemical properties of nanomaterials and its nanotoxicity.pptx
Physiochemical properties of nanomaterials and its nanotoxicity.pptxPhysiochemical properties of nanomaterials and its nanotoxicity.pptx
Physiochemical properties of nanomaterials and its nanotoxicity.pptxAArockiyaNisha
 
Presentation Vikram Lander by Vedansh Gupta.pptx
Presentation Vikram Lander by Vedansh Gupta.pptxPresentation Vikram Lander by Vedansh Gupta.pptx
Presentation Vikram Lander by Vedansh Gupta.pptxgindu3009
 
Isotopic evidence of long-lived volcanism on Io
Isotopic evidence of long-lived volcanism on IoIsotopic evidence of long-lived volcanism on Io
Isotopic evidence of long-lived volcanism on IoSérgio Sacani
 
Call Girls in Munirka Delhi 💯Call Us 🔝9953322196🔝 💯Escort.
Call Girls in Munirka Delhi 💯Call Us 🔝9953322196🔝 💯Escort.Call Girls in Munirka Delhi 💯Call Us 🔝9953322196🔝 💯Escort.
Call Girls in Munirka Delhi 💯Call Us 🔝9953322196🔝 💯Escort.aasikanpl
 
Call Girls in Mayapuri Delhi 💯Call Us 🔝9953322196🔝 💯Escort.
Call Girls in Mayapuri Delhi 💯Call Us 🔝9953322196🔝 💯Escort.Call Girls in Mayapuri Delhi 💯Call Us 🔝9953322196🔝 💯Escort.
Call Girls in Mayapuri Delhi 💯Call Us 🔝9953322196🔝 💯Escort.aasikanpl
 
Work, Energy and Power for class 10 ICSE Physics
Work, Energy and Power for class 10 ICSE PhysicsWork, Energy and Power for class 10 ICSE Physics
Work, Energy and Power for class 10 ICSE Physicsvishikhakeshava1
 
Spermiogenesis or Spermateleosis or metamorphosis of spermatid
Spermiogenesis or Spermateleosis or metamorphosis of spermatidSpermiogenesis or Spermateleosis or metamorphosis of spermatid
Spermiogenesis or Spermateleosis or metamorphosis of spermatidSarthak Sekhar Mondal
 
Labelling Requirements and Label Claims for Dietary Supplements and Recommend...
Labelling Requirements and Label Claims for Dietary Supplements and Recommend...Labelling Requirements and Label Claims for Dietary Supplements and Recommend...
Labelling Requirements and Label Claims for Dietary Supplements and Recommend...Lokesh Kothari
 
Nightside clouds and disequilibrium chemistry on the hot Jupiter WASP-43b
Nightside clouds and disequilibrium chemistry on the hot Jupiter WASP-43bNightside clouds and disequilibrium chemistry on the hot Jupiter WASP-43b
Nightside clouds and disequilibrium chemistry on the hot Jupiter WASP-43bSérgio Sacani
 
Bentham & Hooker's Classification. along with the merits and demerits of the ...
Bentham & Hooker's Classification. along with the merits and demerits of the ...Bentham & Hooker's Classification. along with the merits and demerits of the ...
Bentham & Hooker's Classification. along with the merits and demerits of the ...Nistarini College, Purulia (W.B) India
 
Boyles law module in the grade 10 science
Boyles law module in the grade 10 scienceBoyles law module in the grade 10 science
Boyles law module in the grade 10 sciencefloriejanemacaya1
 
PossibleEoarcheanRecordsoftheGeomagneticFieldPreservedintheIsuaSupracrustalBe...
PossibleEoarcheanRecordsoftheGeomagneticFieldPreservedintheIsuaSupracrustalBe...PossibleEoarcheanRecordsoftheGeomagneticFieldPreservedintheIsuaSupracrustalBe...
PossibleEoarcheanRecordsoftheGeomagneticFieldPreservedintheIsuaSupracrustalBe...Sérgio Sacani
 

Recently uploaded (20)

Types of different blotting techniques.pptx
Types of different blotting techniques.pptxTypes of different blotting techniques.pptx
Types of different blotting techniques.pptx
 
Stunning ➥8448380779▻ Call Girls In Panchshil Enclave Delhi NCR
Stunning ➥8448380779▻ Call Girls In Panchshil Enclave Delhi NCRStunning ➥8448380779▻ Call Girls In Panchshil Enclave Delhi NCR
Stunning ➥8448380779▻ Call Girls In Panchshil Enclave Delhi NCR
 
STERILITY TESTING OF PHARMACEUTICALS ppt by DR.C.P.PRINCE
STERILITY TESTING OF PHARMACEUTICALS ppt by DR.C.P.PRINCESTERILITY TESTING OF PHARMACEUTICALS ppt by DR.C.P.PRINCE
STERILITY TESTING OF PHARMACEUTICALS ppt by DR.C.P.PRINCE
 
Animal Communication- Auditory and Visual.pptx
Animal Communication- Auditory and Visual.pptxAnimal Communication- Auditory and Visual.pptx
Animal Communication- Auditory and Visual.pptx
 
Nanoparticles synthesis and characterization​ ​
Nanoparticles synthesis and characterization​  ​Nanoparticles synthesis and characterization​  ​
Nanoparticles synthesis and characterization​ ​
 
All-domain Anomaly Resolution Office U.S. Department of Defense (U) Case: “Eg...
All-domain Anomaly Resolution Office U.S. Department of Defense (U) Case: “Eg...All-domain Anomaly Resolution Office U.S. Department of Defense (U) Case: “Eg...
All-domain Anomaly Resolution Office U.S. Department of Defense (U) Case: “Eg...
 
Physiochemical properties of nanomaterials and its nanotoxicity.pptx
Physiochemical properties of nanomaterials and its nanotoxicity.pptxPhysiochemical properties of nanomaterials and its nanotoxicity.pptx
Physiochemical properties of nanomaterials and its nanotoxicity.pptx
 
Presentation Vikram Lander by Vedansh Gupta.pptx
Presentation Vikram Lander by Vedansh Gupta.pptxPresentation Vikram Lander by Vedansh Gupta.pptx
Presentation Vikram Lander by Vedansh Gupta.pptx
 
Isotopic evidence of long-lived volcanism on Io
Isotopic evidence of long-lived volcanism on IoIsotopic evidence of long-lived volcanism on Io
Isotopic evidence of long-lived volcanism on Io
 
Call Girls in Munirka Delhi 💯Call Us 🔝9953322196🔝 💯Escort.
Call Girls in Munirka Delhi 💯Call Us 🔝9953322196🔝 💯Escort.Call Girls in Munirka Delhi 💯Call Us 🔝9953322196🔝 💯Escort.
Call Girls in Munirka Delhi 💯Call Us 🔝9953322196🔝 💯Escort.
 
The Philosophy of Science
The Philosophy of ScienceThe Philosophy of Science
The Philosophy of Science
 
Call Girls in Mayapuri Delhi 💯Call Us 🔝9953322196🔝 💯Escort.
Call Girls in Mayapuri Delhi 💯Call Us 🔝9953322196🔝 💯Escort.Call Girls in Mayapuri Delhi 💯Call Us 🔝9953322196🔝 💯Escort.
Call Girls in Mayapuri Delhi 💯Call Us 🔝9953322196🔝 💯Escort.
 
Work, Energy and Power for class 10 ICSE Physics
Work, Energy and Power for class 10 ICSE PhysicsWork, Energy and Power for class 10 ICSE Physics
Work, Energy and Power for class 10 ICSE Physics
 
Spermiogenesis or Spermateleosis or metamorphosis of spermatid
Spermiogenesis or Spermateleosis or metamorphosis of spermatidSpermiogenesis or Spermateleosis or metamorphosis of spermatid
Spermiogenesis or Spermateleosis or metamorphosis of spermatid
 
CELL -Structural and Functional unit of life.pdf
CELL -Structural and Functional unit of life.pdfCELL -Structural and Functional unit of life.pdf
CELL -Structural and Functional unit of life.pdf
 
Labelling Requirements and Label Claims for Dietary Supplements and Recommend...
Labelling Requirements and Label Claims for Dietary Supplements and Recommend...Labelling Requirements and Label Claims for Dietary Supplements and Recommend...
Labelling Requirements and Label Claims for Dietary Supplements and Recommend...
 
Nightside clouds and disequilibrium chemistry on the hot Jupiter WASP-43b
Nightside clouds and disequilibrium chemistry on the hot Jupiter WASP-43bNightside clouds and disequilibrium chemistry on the hot Jupiter WASP-43b
Nightside clouds and disequilibrium chemistry on the hot Jupiter WASP-43b
 
Bentham & Hooker's Classification. along with the merits and demerits of the ...
Bentham & Hooker's Classification. along with the merits and demerits of the ...Bentham & Hooker's Classification. along with the merits and demerits of the ...
Bentham & Hooker's Classification. along with the merits and demerits of the ...
 
Boyles law module in the grade 10 science
Boyles law module in the grade 10 scienceBoyles law module in the grade 10 science
Boyles law module in the grade 10 science
 
PossibleEoarcheanRecordsoftheGeomagneticFieldPreservedintheIsuaSupracrustalBe...
PossibleEoarcheanRecordsoftheGeomagneticFieldPreservedintheIsuaSupracrustalBe...PossibleEoarcheanRecordsoftheGeomagneticFieldPreservedintheIsuaSupracrustalBe...
PossibleEoarcheanRecordsoftheGeomagneticFieldPreservedintheIsuaSupracrustalBe...
 

Calculation of sinuosity in GRASS GIS

  • 1. This and more at my website: https://sites.google.com/site/sorsbysj/ LinkedIn: https://www.linkedin.com/in/skylersorsby Calculating Sinuosity for a stream raster with moving-window analysis in GRASS By Skyler Sorsby Among the many useful hydrological tools present in GRASS GIS, The ‘sinuos’ option of the v.to.db module provides the means to extract channel sinuosity for a segmented vector line. Sinuosity, a measure of channel curviness is expressed by the formula: 𝑆𝑖𝑛𝑢𝑜𝑠𝑖𝑡𝑦 = 𝑃𝑙𝑎𝑛𝑓𝑜𝑟𝑚 𝑑𝑖𝑠𝑡𝑎𝑛𝑐𝑒 𝑆𝑡𝑟𝑎𝑖𝑔ℎ𝑡 𝑙𝑖𝑛𝑒 𝑑𝑖𝑠𝑡𝑎𝑛𝑐𝑒 where distances are measured between two points at different locations along a stream channel’s path. Planform distance describes the space along the river between the two points, while straight line distance is simply the smallest gap between those points “as the crow flies” (Fig. 1). This channel ‘curviness’ parameter is useful for parameterizing stream maturity. Greater curves, or ‘meanders’, indicate more-erodible substrate, lower stream energy, and lower-relief topography proximal to the planform, all else being equal. Additionally, stream channels may become more sinuous as they cross zones of tectonic tilting. Due to the law of conservation of energy, systems tend to resist change. As a floodplain tilts, river channels become more curve-y, such that more of the channel’s reach is perpendicular to the maximum downstream gradient. This has the effect of minimizing the change in stream power (and thus energy level) of the fluvial network. As such, sinuosity bears important tectonic implications. Channel sinuosity values are generally rough estimates, performed by hand. Each calculation requires a reasonably long segment of channel. For example, choosing to calculate over the entire planform extent will give an accurate value for the stream’s sinuosity, yet one that is quite generalized. Conversely, performing the calculation over a short distance may prove unusable if the river fails to curve much in between. A standard Figure 1. Sinuosity is a distance ratio, a river’s ‘curviness’ parameter. Figure 2. River distance ~ straight line distance… for the whole stream! The window is too narrow.
  • 2. This and more at my website: https://sites.google.com/site/sorsbysj/ LinkedIn: https://www.linkedin.com/in/skylersorsby compromise is to measure over a distance equal to one (or one-half) wavelength of the river’s general periodic curve. One problem with making a single calculation over a segment of a river, however, is that it treats change in a discrete manner. Planform geometry, however, varies gradationally along a river’s course. Accordingly, sinuosity measurements, although dependent on adjacent upstream and downstream portions of a river, must be calculated in a way that shows gradational change. My proposed solution to this problem is to utilize a sufficiently long moving-window for each downstream step. With this approach, higher-resolution, continuous sinuosity is calculated over a representative, wavelength-scale reach surrounding each pixel in a stream raster. Here, I offer for review a new method for digitally calculating channel sinuosity, using the r.mapcalc, r.stream.distance, and r.neighbors GRASS modules. Additionally, I provide the Python code to perform this calculation in an automated GRASS script. Sinuosity Workflow: *NOTE: this workflow requires the freely-accessible r.stream.distance GRASS Addon* (Obtain r.stream distance from SettingsAddons extensions g.extention) 1) Derive your stream channel segments vector with r.watershed. Trim it to main channels with the vector editor, such that the necessary moving window size will NOT overlap multiple channels (in many places). Once you’re satisfied, convert your trimmed vector stream map to a raster map (make sure g.region is current!) with VectorMap type conversionsVector to raster. Choose ‘lines’ as the type, the ‘val’ parameter (NOT ‘attr’!), and make sure that the ‘val’ value is set to 1. 1a) Alternatively, if you’re satisfied with your stream segments map directly from r.watershed’s output, convert it to binary (channel pixels=1, all else=0) by hand: Use r.mapcalculator to divide your segments raster map by itself. Figure 3. The stream segments raster is fed through r.mapcalculator.
  • 3. This and more at my website: https://sites.google.com/site/sorsbysj/ LinkedIn: https://www.linkedin.com/in/skylersorsby 2) Generate a ‘Stream distance’ map using r.stream.distance. To do this, you will need a rasterized map of channel outlets. Use the heads-up digitizer to place points squarely on top of each channel outlet (last, lowest) pixel of the new binary stream map. Save your edits, quit the digitizer. Next, use VectorMap type conversionsv.to.rast again, this time to rasterize your points. Next, input your Flow Direction raster (output of r.watershed) and your rasterized channel outlets map in the ‘Required’ tab. In the ‘Optional’ tab, input your DEM (used in r.watershed) as the elevation map. Name the output distance map. Check the –o flag (Calculate parameters for outlets). Hit ‘Run’. Figure 4. My outlets map (still need to convert from vector to raster) Figure 5. r.stream.distance interface. Freely- downloadable, use SettingsAddons extensions g.extention. 3) Now that you have a raster of channel distance, you need to somehow generate maps of Easting and Northing to eventually calculate straight-line distance. Here’s’ how: a) In r.mapcalculator, name your new map (EW_coord, or something like that), and select the x() function. Just leave those three characters by themselves in the calculations window. Just leave ‘em. Hit ‘Run’. This will auto-generate a map of East- West UTM coordinates (You SHOULD be in UTM coordinates from the get-go). b) Type y() into the command window, name your Northings map something memorable, and hit ‘Run’ to auto-generate a map of North-South UTM coordinates.
  • 4. This and more at my website: https://sites.google.com/site/sorsbysj/ LinkedIn: https://www.linkedin.com/in/skylersorsby Figure 6. The syntax for creating Easting and Northing maps is quite simple! 4) Now, impart the Easting, Northing, and River Distance map data to your binary stream channels. This is done in r.mapcalculator by: streams_binary * Eastingmap streams_binary * Northingmap streams_binary * RiverDistancemap You’ll have to run r.mapcalculator three times—one for each calculation (such that a new map is created each time). 5) Now, you should have three stream rasters with Easting, Northing, and stream- parallel distance as their respective pixel values. Now you need to use a moving- window to take these absolute distances and calculate discrete stepwise distances for a specified area around each stream pixel in each of the three rasters. To do this, use r.neighbors. It will get slightly complicated. r.neighbors is simple to use for calculating averages of proximal values in a raster. What it’s not intuitively good at is looking a set distance away from the pixel in question for values, like we would need in order to standardize our distance calculation procedure. To create an “annular” search radius, instead of including every pixel nearby, you need to create a weights file. A weights file is, simply a text file with a series of numbers, each separated by a space. For a 3x3 search window of normal weights, type 1 1 1 1 1 1 1 1 1 . GRASS sees: 1 1 1 1 1 1 1 1 1 The pixel receiving the output of the calculation is always the central one. Subsequently, your moving-average window MUST always have an odd width! For a 5x5 hollow
  • 5. This and more at my website: https://sites.google.com/site/sorsbysj/ LinkedIn: https://www.linkedin.com/in/skylersorsby (“annular”) search window, type 1 1 1 1 1 1 0 0 0 1 1 0 0 0 1 1 0 0 0 1 1 1 1 1 1 . GRASS sees: 1 1 1 1 1 1 0 0 0 1 1 0 0 0 1 1 0 0 0 1 1 1 1 1 1 This will probably not be large enough for a sinuosity calculation; you will have to determine how many pixels the wavelength is, and size your weights file accordingly. Save it somewhere convenient, and use it as an input to r.neighbors. The importance of an annular weights file, and the trick to this methodology: If you let r.neighbors run ‘as is’, with only a numeric value for the window size (i.e., no weights file), you will include every point within your window in the calculation. Since you only want to deal with two points on the stream, you need to hand-make the search window into an annulus. Thus, with a large enough window, only two points on the stream will be consulted for each calculation. With the weighting and size parameters held the same, the corresponding pixels in each raster map will corresponding points on each stream. Another technicality of r.neighbors, the binary weighting scheme I’ve devised will only work for neighborhood statistics that are “unaffected” by weighting: local minimum, local maximum, diversity, interspersion. So, to get my relative Easting and Northing values for my straight-line calculation, I need to use my annular-weighted r.neighbors moving window to find the maximum Easting stream pixel (1 of 2 pixels total) and the minimum Easting stream pixel (2 of 2 pixels total), the maximum Northing stream pixel (1 of 2 pixels total) and minimum Northing pixel (2 of 2 pixels total), and finally the maximum river distance (1 of 2 pixels total) and the minimum river distance total (2 of 2 pixels total). This will require you to run the r.neighbors module six times, unfortunately. On the bright side, compiling these instructions into a Python script (code included at the end of the document) will allow you to perform these steps very rapidly.
  • 6. This and more at my website: https://sites.google.com/site/sorsbysj/ LinkedIn: https://www.linkedin.com/in/skylersorsby Figure 7. Visualization of single pixel width “annular” search window. The desired statistic is assigned to the pixel in the center of the window. Statistics are run for each pixel in the raster map. Figure 8. The six rasters you must produce with r.neighbors. Note that only the two single pixels that intersect the stream on the outermost edge of the window will be factored into the statistics. Figure 9. NS=Northing, EW=Easting. This is the derivation of the straight-line distance from the Pythagorean Theorem Figure 10. River distances are found for the same two pixels, due to the use of the same weight file and window size!
  • 7. This and more at my website: https://sites.google.com/site/sorsbysj/ LinkedIn: https://www.linkedin.com/in/skylersorsby 6) Now, you should have six output maps, containing max and min Northing, max and min Easting, and max and min river distances for corresponding pixels in each stream raster. The problem now, is, the stream lines are suddenly quite thick! Remember that r.neighbors acts upon each cell within the raster—if any of the zero-value cells sees a stream cell intersecting its “annular” search window, it will nab that stream cell’s value. Don’t worry—this doesn’t affect the stream cells. We haven’t run multiple iterations. The fix is simple: multiply each output map by your binary stream map (1’s and 0’s) to extract Northings, Eastings, and stream distances for only stream pixels. 7) Now, use some fancy map algebra and the Pythagorean Theorem to derive a straight-line distance for each pixel in the study area: sqrt( (EastingMax – EastingMin)^2 + (NorthingMax – NorthingMin)^2 ) NOTE: this is too complex for Python scripting, and requires “Expert mode”. I reduce its complexity instead by removing the squaring notation: sqrt( (EastingMax – EastingMin)* (EastingMax – EastingMin) + (NorthingMax – NorthingMin)* (NorthingMax – NorthingMin) ) 8) Use less-fancy map algebra to derive stream distance for each pixel in the study area: StreamDistanceMax – StreamDistanceMin 9) Finally, use Map Algebra to divide StreamDistance by StraighLineDistance: StreamDistance / StraightLineDistance And, voila! You have sinuosity calculated over a desired moving window for each pixel in your stream system, no manual calculations required. Although no more representative than calculating sinuosity for set blocks of vector stream segments with v.to.db, this approach may produce results that are more easily-manipulated and useful to work with!
  • 8. This and more at my website: https://sites.google.com/site/sorsbysj/ LinkedIn: https://www.linkedin.com/in/skylersorsby My Python code for automating the above steps (usable as a GRASS GIS script): #!/usr/bin/env python # # g.parser demo script for python programing #%module #% description: g.parser test script (python) #%end #%option #% key: raster1 #% type: string #% gisprompt: old,cell,raster #% description: Flow Direction Map: #% required : yes #%end #%option #% key: raster2 #% type: string #% gisprompt: old,cell,raster #% description: DEM #% required : yes #%end #%option #% key: raster3 #% type: string #% gisprompt: old,cell,raster #% description: Outlet nodes (rasterized points): #% required : yes #%end #%option #% key: raster4 #% type: string #% gisprompt: old,cell,raster #% description: Stream segment raster (r.watershed output): #% required : yes #%end #%option #% key: windowsize #% type: integer #% description: Width of moving window #% required : yes #%end
  • 9. This and more at my website: https://sites.google.com/site/sorsbysj/ LinkedIn: https://www.linkedin.com/in/skylersorsby #%option #% key: weights #% type: string #% gisprompt: old,file,input #% description: Input weight file (annular): #% required : yes #%end ############################################################################## ## # # MODULE: Sinuosity Calculator # # AUTHOR: Skyler Sorsby # # PURPOSE: GRASS’ wxGUI model builder was ultimately too unreliable and buggy for me # to be satisfied with automating the sinuosity calculator that way. # # DATE: Sat Feb 15 17:39:36 2014 # ############################################################################## ## import sys import os import atexit import grass.script as grass def cleanup(): pass def main(): FloDir=options['raster1'] DEM=options['raster2'] OutletNodes=options['raster3'] WindowSize=options['windowsize'] streamsegs=options['raster4'] grass.run_command("r.mapcalculator", amap = streamsegs, overwrite = True, formula = "A/A", outfile = "streams_binary", help = "-") grass.run_command("r.mapcalculator", overwrite = True,
  • 10. This and more at my website: https://sites.google.com/site/sorsbysj/ LinkedIn: https://www.linkedin.com/in/skylersorsby formula = "x()", outfile = "EW_dist", help = "-") grass.run_command("r.mapcalculator", overwrite = True, formula = "y()", outfile = "NS_dist", help = "-") grass.run_command("r.stream.distance", stream = OutletNodes, dir = FloDir, dem = DEM, flags = 'o', overwrite = True, method = "downstream", distance = "Dist_map") grass.run_command("r.mapcalculator", overwrite = True, amap = "streams_binary", bmap = "EW_dist", formula = "A*B", outfile = "EW_streams", help = "-") grass.run_command("r.mapcalculator", overwrite = True, amap = "streams_binary", bmap = "NS_dist", formula = "A*B", outfile = "NS_streams", help = "-") grass.run_command("r.mapcalculator", overwrite = True, amap = "streams_binary", bmap = "Dist_map", formula = "A*B", outfile = "Dist_streams", help = "-") grass.run_command("r.neighbors", overwrite = True, input = "EW_streams", output = "EW_streams_max", method = "maximum", size = WindowSize, weight = options['weights']) grass.run_command("r.neighbors", overwrite = True,
  • 11. This and more at my website: https://sites.google.com/site/sorsbysj/ LinkedIn: https://www.linkedin.com/in/skylersorsby input = "EW_streams", output = "EW_streams_min", method = "minimum", size = WindowSize, weight = options['weights']) grass.run_command("r.neighbors", overwrite = True, input = "NS_streams", output = "NS_streams_max", method = "maximum", size = WindowSize, weight = options['weights']) grass.run_command("r.neighbors", overwrite = True, input = "NS_streams", output = "NS_streams_min", method = "minimum", size = WindowSize, weight = options['weights']) grass.run_command("r.neighbors", overwrite = True, input = "Dist_streams", output = "Dist_streams_diff", method = "range", size = WindowSize, weight = options['weights']) grass.run_command("r.mapcalculator", overwrite = True, amap = "streams_binary", bmap = "EW_streams_max", formula = "A*B", outfile = "EW_streams_max_thinned", help = "-") grass.run_command("r.mapcalculator", overwrite = True, amap = "streams_binary", bmap = "EW_streams_min", formula = "A*B", outfile = "EW_streams_min_thinned", help = "-") grass.run_command("r.mapcalculator", overwrite = True, amap = "streams_binary", bmap = "NS_streams_max", formula = "A*B", outfile = "NS_streams_max_thinned",
  • 12. This and more at my website: https://sites.google.com/site/sorsbysj/ LinkedIn: https://www.linkedin.com/in/skylersorsby help = "-") grass.run_command("r.mapcalculator", overwrite = True, amap = "streams_binary", bmap = "NS_streams_min", formula = "A*B", outfile = "NS_streams_min_thinned", help = "-") grass.run_command("r.mapcalculator", overwrite = True, amap = "streams_binary", bmap = "Dist_streams_diff", formula = "A*B", outfile = "Dist_streams_diff_thinned", help = "-") grass.run_command("r.mapcalculator", overwrite = True, amap = "EW_streams_max_thinned", bmap = "EW_streams_min_thinned", cmap = "NS_streams_max_thinned", dmap = "NS_streams_min_thinned", formula = "sqrt((A-B)*(A-B)+(C-D)*(C-D))", outfile = "A_straightline_dist", help = "-") grass.run_command("r.mapcalculator", overwrite = True, amap = "Dist_streams_diff_thinned", bmap = "A_straightline_dist", formula = "A/B", outfile = "A_stream_sinuosity", help = "-") return 0 if __name__ == "__main__": options, flags = grass.parser() atexit.register(cleanup) sys.exit(main())
  • 13. This and more at my website: https://sites.google.com/site/sorsbysj/ LinkedIn: https://www.linkedin.com/in/skylersorsby