Difference between revisions of "Using GRASS GIS through Python and tangible interfaces (workshop at FOSS4G NA 2016)"

From GRASS-Wiki
Jump to navigation Jump to search
(initial content, python scripting library)
 
Line 1: Line 1:
{{ToModify}}
{{ToModify}}
Learn about scripting, graphical and tangible (!) interfaces for GRASS GIS, the powerful desktop GIS and geoprocessing backend. We will start with the Python interface and finish with Tangible Landscape, a new tangible interface for GRASS GIS.
This is material for FOSS4G NA 2016 workshop Using GRASS GIS through Python and tangible interfaces held in Raleigh May 2, 2016 - 09:00 to 13:00.
 
Learn about scripting, graphical and tangible (!) interfaces for GRASS GIS, the powerful desktop GIS and geoprocessing backend. We will start with the Python interface and finish with [https://geospatial.ncsu.edu/osgeorel/tangible-landscape.html Tangible Landscape], a new tangible interface for GRASS GIS.
Python is the primary scripting language for GRASS GIS. We will demonstrate how to use Python to automate your geoprocessing workflows with GRASS GIS modules and develop custom algorithms using a Pythonic interface to access low level GRASS GIS library functions. We will also review several tips and tricks for parallelization.
Python is the primary scripting language for GRASS GIS. We will demonstrate how to use Python to automate your geoprocessing workflows with GRASS GIS modules and develop custom algorithms using a Pythonic interface to access low level GRASS GIS library functions. We will also review several tips and tricks for parallelization.
Tangible Landscape is an example of how the GRASS GIS Python API can be used to build new, cutting edge tools and advanced applications. Tangible Landscape is a collaborative 3D sketching tool which couples a 3D scanner, a projector and a physical 3D model with GRASS GIS. The workshop will be a truly hands-on experience – you will play with Tangible Landscape, using your hands to shape a sand model and drive geospatial processes.
[https://geospatial.ncsu.edu/osgeorel/tangible-landscape.html Tangible Landscape] is an example of how the GRASS GIS Python API can be used to build new, cutting edge tools and advanced applications. Tangible Landscape is a collaborative 3D sketching tool which couples a 3D scanner, a projector and a physical 3D model with GRASS GIS. The workshop will be a truly hands-on experience – you will play with Tangible Landscape, using your hands to shape a sand model and drive geospatial processes.
 
'''Software''': [https://grass.osgeo.org GRASS GIS 7]
 
'''Data''': Download [https://grass.osgeo.org/sampledata/north_carolina/nc_spm_08_grass7.zip complete North Carolina sample dataset].


= GRASS GIS introduction =
= GRASS GIS introduction =
You need to create a GRASS database we will use for the tutorial. Please download the [https://grass.osgeo.org/sampledata/north_carolina/nc_spm_08_grass7.zip dataset] for the workshop, noting where the files are located on your local directory.
Now, create (unless you already have it) a directory named <tt>grassdata</tt> (GRASS database) in your home folder (or Documents), unzip the downloaded data into this directory. You should now have a Location futures_ncspm in grassdata.
= GRASS GIS Python API =
= GRASS GIS Python API =
== Python Scripting library ==
== Python Scripting library ==
[[File:GRASS GUI Python shell.png|thumbnail|right|Python shell in GRASS GIS GUI]]
[[File:GRASS GUI Python shell.png|thumbnail|right|Python shell in GRASS GIS GUI]]
Line 26: Line 35:
</source>
</source>


Before running any GRASS raster modules, you need to set the computational region using {{cmd|g.region}}. In this example, we set the computational extent and resolution to the raster layer <tt>elevation_30m</tt>.
Before running any GRASS raster modules, you need to set the computational region using {{cmd|g.region}}. In this example, we set the computational extent and resolution to the raster layer <tt>elevation</tt>.
<source lang="python">
<source lang="python">
gscript.run_command('g.region', raster='elevation_30m')
gscript.run_command('g.region', raster='elevation')
</source>
</source>


The run_command() function is the most commonly used one. Here, we apply the focal operation average ({{cmd|r.neighbors}}) to smooth the elevation raster layer. Note that the syntax is similar to bash syntax, just the flags are specified in a parameter.
The run_command() function is the most commonly used one. Here, we apply the focal operation average ({{cmd|r.neighbors}}) to smooth the elevation raster layer. Note that the syntax is similar to bash syntax, just the flags are specified in a parameter.
<source lang="python">
<source lang="python">
gscript.run_command('r.neighbors', input='elevation_30m', output='elev_smoothed', method='average', flags='c')
gscript.run_command('r.neighbors', input='elevation', output='elev_smoothed', method='average', flags='c')
</source>
</source>
If we run the Python commands from GUI Python console, we can use <tt>AddLayer</tt> to add the newly created layer:
If we run the Python commands from GUI Python console, we can use <tt>AddLayer</tt> to add the newly created layer:
Line 61: Line 70:
Certain modules require the text input be in a file or provided as standard input. Using the write_command() function we can conveniently pass the string to the module. Here, we are creating a new vector with one point with {{cmd|v.in.ascii}}. Note that ''stdin'' parameter is not used as a module parameter, but its content is passed as standard input to the subprocess.
Certain modules require the text input be in a file or provided as standard input. Using the write_command() function we can conveniently pass the string to the module. Here, we are creating a new vector with one point with {{cmd|v.in.ascii}}. Note that ''stdin'' parameter is not used as a module parameter, but its content is passed as standard input to the subprocess.
<source lang="python">
<source lang="python">
gscript.write_command('v.in.ascii', input='-', stdin='%s|%s' % (283730, 208920), output='point')
gscript.write_command('v.in.ascii', input='-', stdin='%s|%s' % (635818, 221342), output='point')
</source>
</source>


Line 71: Line 80:
=== Convenient wrapper functions ===
=== Convenient wrapper functions ===
Some modules have wrapper functions to simplify frequent tasks.
Some modules have wrapper functions to simplify frequent tasks.
For example we can obtain the information about a raster layer with [https://grass.osgeo.org/grass70/manuals/libpython/script.html?highlight=mapcalc#script.raster.raster_info raster_info] which is a wrapper of {{cmd|r.info}}.
For example we can obtain the information about a raster layer with [https://grass.osgeo.org/grass70/manuals/libpython/script.html?highlight=mapcalc#script.raster.raster_info raster_info] which is a wrapper of {{cmd|r.info}},
or a vector layer with [https://grass.osgeo.org/grass70/manuals/libpython/script.html?script.vector.vector_info vector_info].
<source lang="python">
<source lang="python">
gscript.raster_info('elevation_30m')
gscript.raster_info('elevation')
gscript.vector_info('point')
</source>
</source>


Another example is using [https://grass.osgeo.org/grass70/manuals/libpython/script.html?highlight=mapcalc#script.raster.mapcalc r.mapcalc wrapper] for raster algebra:
Another example is using [https://grass.osgeo.org/grass70/manuals/libpython/script.html?highlight=mapcalc#script.raster.mapcalc r.mapcalc wrapper] for raster algebra:
<source lang="python">
<source lang="python">
gscript.mapcalc("forest_2011 = if(landuse_2011 >= 41 && landuse_2011 <= 43, 1, null())")
gscript.mapcalc("elev_strip = if(elevation > 100 && elevation < 125, elevation, null())")
gscript.read_command('r.univar', map='elev_strip', flags='g')
</source>
</source>


Line 100: Line 112:
gscript.list_pairs('raster', mapset=current_mapset)
gscript.list_pairs('raster', mapset=current_mapset)
</source>
</source>
=== Exercise ===


== PyGRASS ==
== PyGRASS ==

Revision as of 20:56, 19 April 2016

This is material for FOSS4G NA 2016 workshop Using GRASS GIS through Python and tangible interfaces held in Raleigh May 2, 2016 - 09:00 to 13:00.

Learn about scripting, graphical and tangible (!) interfaces for GRASS GIS, the powerful desktop GIS and geoprocessing backend. We will start with the Python interface and finish with Tangible Landscape, a new tangible interface for GRASS GIS. Python is the primary scripting language for GRASS GIS. We will demonstrate how to use Python to automate your geoprocessing workflows with GRASS GIS modules and develop custom algorithms using a Pythonic interface to access low level GRASS GIS library functions. We will also review several tips and tricks for parallelization. Tangible Landscape is an example of how the GRASS GIS Python API can be used to build new, cutting edge tools and advanced applications. Tangible Landscape is a collaborative 3D sketching tool which couples a 3D scanner, a projector and a physical 3D model with GRASS GIS. The workshop will be a truly hands-on experience – you will play with Tangible Landscape, using your hands to shape a sand model and drive geospatial processes.

Software: GRASS GIS 7

Data: Download complete North Carolina sample dataset.

GRASS GIS introduction

You need to create a GRASS database we will use for the tutorial. Please download the dataset for the workshop, noting where the files are located on your local directory. Now, create (unless you already have it) a directory named grassdata (GRASS database) in your home folder (or Documents), unzip the downloaded data into this directory. You should now have a Location futures_ncspm in grassdata.

GRASS GIS Python API

Python Scripting library

Python shell in GRASS GIS GUI

The GRASS GIS 7 Python Scripting Library provides functions to call GRASS modules within scripts as subprocesses. The most often used functions include:

  • run_command: most often used with modules which output raster/vector data where text output is not expected
  • read_command: used when we are interested in text output
  • parse_command: used with modules producing text output as key=value pair
  • write_command: for modules expecting text input from either standard input or file

Besides, this library provides several wrapper functions for often called modules.

Calling GRASS GIS modules

We will use GRASS GUI Python Shell to run the commands. For longer scripts, you can create a text file, save it into your current working directory and run it with python myscript.py from the GUI command console or terminal.

Tip: When copying Python code snippets to GUI Python shell, right click at the position and select Paste Plus in the context menu. Otherwise multiline code snippets won't work.

We start by importing GRASS GIS Python Scripting Library:

import grass.script as gscript

Before running any GRASS raster modules, you need to set the computational region using g.region. In this example, we set the computational extent and resolution to the raster layer elevation.

gscript.run_command('g.region', raster='elevation')

The run_command() function is the most commonly used one. Here, we apply the focal operation average (r.neighbors) to smooth the elevation raster layer. Note that the syntax is similar to bash syntax, just the flags are specified in a parameter.

gscript.run_command('r.neighbors', input='elevation', output='elev_smoothed', method='average', flags='c')

If we run the Python commands from GUI Python console, we can use AddLayer to add the newly created layer:

AddLayer('elev_smoothed')

Calling GRASS GIS modules with textual input or output

Textual output from modules can be captured using the read_command() function.

gscript.read_command('g.region', flags='p')
gscript.read_command('r.univar', map='elev_smoothed', flags='g')

Certain modules can produce output in key-value format which is enabled by the -g flag. The parse_command() function automatically parses this output and returns a dictionary. In this example, we call g.proj to display the projection parameters of the actual location.

gscript.parse_command('g.proj', flags='g')

For comparison, below is the same example, but using the read_command() function.

gscript.read_command('g.proj', flags='g')

Certain modules require the text input be in a file or provided as standard input. Using the write_command() function we can conveniently pass the string to the module. Here, we are creating a new vector with one point with v.in.ascii. Note that stdin parameter is not used as a module parameter, but its content is passed as standard input to the subprocess.

gscript.write_command('v.in.ascii', input='-', stdin='%s|%s' % (635818, 221342), output='point')

If we run the Python commands from GUI Python console, we can use AddLayer to add the newly created layer:

AddLayer('point')

Convenient wrapper functions

Some modules have wrapper functions to simplify frequent tasks. For example we can obtain the information about a raster layer with raster_info which is a wrapper of r.info, or a vector layer with vector_info.

gscript.raster_info('elevation')
gscript.vector_info('point')

Another example is using r.mapcalc wrapper for raster algebra:

gscript.mapcalc("elev_strip = if(elevation > 100 && elevation < 125, elevation, null())")
gscript.read_command('r.univar', map='elev_strip', flags='g')

Function region is a convenient way to retrieve the current region settings (i.e., computational region). It returns a dictionary with values converted to appropriate types (floats and ints). Paste line by line if using GUI Python shell.

region = gscript.region()
print region
# cell area in map units (in projected Locations)
region['nsres'] * region['ewres']

We can list data stored in a GRASS GIS location with g.list wrappers. With list_grouped, the map layers are grouped by mapsets (in this example, raster layers):

gscript.list_grouped(type=['raster'])
gscript.list_grouped(type=['raster'], pattern="landuse*")

Here is an example of a different g.list wrapper list_pairs which structures the output as list of pairs (name, mapset). We obtain current mapset with g.gisenv wrapper.

current_mapset = gscript.gisenv()['MAPSET']
gscript.list_pairs('raster', mapset=current_mapset)

Exercise

PyGRASS