Geospatial Analysis I: global, zonal and focal operations, map algebra
Resources:
- GRASS GIS overview and manual
- Recommendations and tutorial how to use GUI from the first assignment
To run r.mapcalc expressions, you can either run the entire command in the GUI Console, or in case of any problems, type or copy the expression (without the r.mapcalc) in the GRASS GIS Raster Map Calculator which can be launched from Layer Manager toolbar.
Text files with color rules:
Start GRASS GIS
In startup pannel set GRASS GIS Database Directory to path to datasets, for example on MS Windows,C:\Users\myname\grassdata
.
For GRASS Location select nc_spm_08_grass7 (North Carolina, State Plane, meters) and
for GRASS Mapset create a new mapset (called e.g. HW_map_algebra) and
click Start GRASS session.
grass83
Change working directory:
Settings > GRASS working environment > Change working directory > select/create any directory
or type cd
(stands for change directory) into the GUI
Console and hit Enter:
cd
Download all text files with color rules (see above) to the selected directory. Now you can use the commands from the assignment requiring the text file without the need to specify the full path to the file.
Compute summaries
Compute areas for each category at two different resolutions.Are results equal? Explain in detail why (see also Lecture 1). Copy and paste the report from the output window or save the report in a text file: Output window > Save. Use fixed width font (e.g., Courier, Andale Mono in your report to preserve formatting).
g.region raster=landuse96_28m res=12 -ap
r.report landuse96_28m unit=c,h,p
g.region raster=landuse96_28m res=30 -ap
r.report landuse96_28m unit=c,h,p
Compute areas for each category of land use for each zipcode. Compare 27601 Raleigh with 27511 Cary. Include only the relevant part of the table in your report.
r.report zipcodes,landuse96_28m unit=h,p
Compute zonal statistics maps representing
average slope for each basin.
Add legends using Add map elements in Map Display toolbar.
Reminder: d.out.file means Save to graphics file for your report.
g.region raster=slope -p
r.stats.zonal base=basin_50K cover=slope method=average output=slope_avgbasin
r.colors slope_avgbasin color=gyr
d.rast slope_avgbasin
d.legend slope_avgbasin at=90,50,5,8
d.vect streams color=15:25:110
d.out.file slope_avgbasin
Compute zonal statistics maps representing most common land use for each basin.
To get the best result, make sure you use all the flags from the example below.
g.region raster=landuse96_28m -p
r.mode base=basin_50K cover=landuse96_28m output=landuse96_modebasin
d.rast landuse96_modebasin
d.vect streams
d.legend landuse96_modebasin at=40,20,2,5 -n -f -c
d.out.file landuse96_modezip
Apply neighborhood operators
Use neighborhood operator to compute land use diversity map and create a map of locations with the most homogeneous (single category) landuse.Which land use covers the largest area with a single landuse category(most homogeneous areas)?
First, remove all previously added map layers from the Layer Manager, then compute and display the land use diversity map. Use map algebra to extract the single category areas and find out the area totals for each category using the report tool. Adjust the legend size and placement as needed using right click and mouse.
d.erase
r.info -g landuse96_28m
g.region raster=landuse96_28m -p
r.neighbors landuse96_28m output=lu_divers method=diversity size=7
d.rast lu_divers
d.legend lu_divers at=70,15,5,10 -v
d.vect streets_wake co=white
r.report lu_divers unit=p
d.out.file lu_diversity_map
r.mapcalc "landuse_1cat = if(lu_divers == 1, landuse96_28m, null())"
r.colors landuse_1cat raster=landuse96_28m
r.category landuse_1cat raster=landuse96_28m
r.report landuse_1cat unit=h,p -n
d.rast landuse_1cat
d.legend -c landuse_1cat
d.out.file lu_signle_map
Visualy compare the SRTM elevation map "elev_srtm_30m" with lidar-based elevation map "elevation". Use neighborhood operator to smooth the SRTM elevation map and compare the summary statistical measures for the original and smoothed SRTM DEM. How does the size of the neighborhood influence the result? (You can test different sizes yourself.)
d.erase
g.region raster=elev_srtm_30m -p
d.rast elevation
d.legend elevation
r.colors elev_srtm_30m raster=elevation
d.rast elev_srtm_30m
d.legend elev_srtm_30m
d.out.file srtm_dem_original
r.neighbors elev_srtm_30m output=elev_srtm30m_sm5 method=average size=5
d.rast elev_srtm30m_sm5
d.out.file srtm_dem_smoothed
r.univar elev_srtm_30m
r.univar elev_srtm30m_sm5
Patch multiple raster layers into a single raster
Patch raster tiles for lidar based, 6m res. DEM for Centennial Campus.d.erase
g.region raster=el_D793_6m,el_D783_6m,el_D782_6m,el_D792_6m -p
r.patch input=el_D793_6m,el_D783_6m,el_D782_6m,el_D792_6m output=elevlidD_6m
r.colors elevlidD_6m raster=elevation
d.rast elevlidD_6m
Map Algebra
See r.mapcalc manual page for syntax and functions. If you are getting en error when running r.mapcalc in GUI Console or the system command line, launch the GUI version from Layer Manager toolbar.NDVI
Compute Normalized Difference Vegetation Index (NDVI).Explain the difference between floating point and integer handling in ndvi1, ndvi2 and ndvi3 result. Make sure to zoom into computational area after changing the region.
d.erase
g.region raster=lsat7_2002_40 -p
r.mapcalc "ndvi1 = (lsat7_2002_40 - lsat7_2002_30) / (lsat7_2002_40 + lsat7_2002_30)"
r.mapcalc "ndvi2 = 1.0 * (lsat7_2002_40 - lsat7_2002_30) / (lsat7_2002_40 + lsat7_2002_30)"
r.mapcalc "ndvi3 = float(lsat7_2002_40 - lsat7_2002_30) / float(lsat7_2002_40 + lsat7_2002_30)"
r.info -r ndvi1
r.info -r ndvi2
r.info -r ndvi3
r.colors ndvi3 color=ndvi
d.rast ndvi3
d.legend ndvi3
d.out.file ndvi3
Note that this is a simplified, map algebra example, for computing various vegetation indices
in GRASS GIS, we would use the i.vi module
after performing atmospheric corrections.
Difference between DEM and DSM
Explore the difference between the SRTM DSM "elev_srtm_30m" and lidar-based NED DEM "elev_ned_30m". First, compute the map of elevation differences:g.region raster=elev_ned_30m -p
r.mapcalc "srtm_ned30_dif = elev_srtm_30m - elev_ned_30m"
Find the range of differences and create a divergent color table to distinguish the negative and positive values:
r.info -r srtm_ned30_dif
Assign custom color table srtmneddiff_color.txt.
GUI: Right click on layer > Properties > Set color table > Colors > Path to rules file.
r.colors srtm_ned30_dif rules=srtmneddiff_color.txt
Zoom to computational region and switch off previous map layers. Display the difference map layer:
d.erase
d.rast srtm_ned30_dif
d.legend srtm_ned30_dif at=70,15,5,10
d.out.file srtm_ned30_dif
r.univar elev_srtm_30m
r.univar elev_ned_30m
d.histogram srtm_ned30_dif
Are the elevations in "elev_srtm_30m" mostly higher or mostly lower than in "elev_ned_30m"? Which result will you use to answer the above question - the "srtm_ned30_dif" map or the numbers provided by r.univar or the histogram? Are there any values in the maps used or generated in this section that are not realistic?
Working with if statements
Create map of urban areas (high density and low density class) with 0 class elsewhere.g.region raster=landuse96_28m -p
r.mapcalc "urban1_30m = if(landuse96_28m == 1,1,0) + if(landuse96_28m == 2,2,0)"
d.rast urban1_30m
d.legend urban1_30m at=10,30,5,8
Alternatively with logical 'or' operator and null elsewhere:
r.mapcalc "urban2_30m = if(landuse96_28m == 1 || landuse96_28m == 2,landuse96_28m,null())"
d.rast urban2_30m
Handling null values
Create mask for low lying developed areas (e.g. vulnerable to flooding)
with elevation between 60 and 100m and land use 1 or 2.
Set the region, display the input maps and create a MASK.
Before you start new computations, remove or switch off previous map layers
in the Layer Manger.
You may also zoom to computational region in Map Display
once you set a new one.
g.region raster=elevation -p
d.erase
d.rast elevation
d.rast landuse96_28m
r.mapcalc "low_elev_developed = if((elevation < 100 && elevation > 60) && (landuse96_28m == 1 || landuse96_28m == 2),1,null())"
r.mask raster=low_elev_developed
Command r.mask creates a raster map "MASK" in your mapset.
Remove "low_elev_developed" layer if it was added.
Display watersheds to see the mask effect:
d.rast basin_50K
d.out.file basin_masked
Disable mask, and display basin_50K again to show that the mask was removed.
r.mask -r
d.rast basin_50K
Using coordinates of moving window in map algebra
Replace section of SRTM DSM with NED DEM elevation.Try to explain how this r.mapcalc expression works.
r.mapcalc "elev_combined = if(y() < 224274. && x() > 637455., elevation, elev_srtm_30m)"
Optional - various additional useful tasks
Tilted plane
Create a raster map representing tilted plane (e.g., geologic fault):g.region rural_1m -p
r.mapcalc "tiltplane = 0.2*(0.1*row()+col())+50"
r.mapcalc "tiltpl_under = if(tiltplane < elev_lid792_1m + 2,tiltplane,null())"
View the elevation surface and subsurface plane in 3D. Switch off all layers in the layer manager except for elev_lid792_1m and tiltpl_under. Change display to 3D view, adjust viewing position to a view from South. Save an image for your report.
Map subsets
Use map algebra to create map subsets.Change region to the airphoto tile 792 and resolution 10m. Since we will work in different area, it is a good idea to remove all previously used map layers from Layers in the Layer Manager.
g.region raster=ortho_2001_t792_1m res=10 -ap
d.erase
d.rast ortho_2001_t792_1m
Create a subset of the map elevation for this subregion.
r.mapcalc "elevation_792_10m = elevation"
d.rast elevation_792_10m
Zoom out to see that it is a subset.
Work with NULL and MASK
Set the mask and check its effect.d.rast elevation
d.vect streets_wake
r.mask raster=urban maskcats=55
d.rast elevation
Remove mask:
r.mask -r
Zonal statistics
First, set the computational region:g.region raster=urban2_30m
Then, compute % area for each category in each zipcode.
r.stats -pl zipcodes,urban2_30m
Working with relative coordinates
Enter the expression on a single line without \Again, it is a good idea to remove the previously used map layers before we start to work on a new task.
g.region raster=elev_srtm_30m -p
d.erase
r.mapcalc "elev_srtm30m_smooth = (elev_srtm_30m[-1,-1] \
+ elev_srtm_30m[-1,0] + elev_srtm_30m[-1,1] \
+ elev_srtm_30m[0,-1] + elev_srtm_30m[0,0] \
+ elev_srtm_30m[0,1] + elev_srtm_30m[1,-1] \
+ elev_srtm_30m[1,0] + elev_srtm_30m[1,1])/9."
Assign the resulting map the same color table as the original. Compare global statistics
r.colors elev_srtm30m_smooth raster=elev_srtm_30m
r.univar elev_srtm_30m
r.univar elev_srtm30m_smooth
d.rast elev_srtm_30m
d.rast elev_srtm30m_smooth