Unit 10 - Python intro

:wikipedia-en:`Python` programming/scripting language is very popular in the field of GIS and a science in general. Python is also the main scripting platform for Esri product (see arcpy package). GRASS is not an exception. In reality, many GRASS modules are simple Python scripts, eg. r.mask (see Source Code section).

GRASS Python environment includes various libraries, see GRASS documentation for details. We will focus on three main libraries related to this workshop:

Let’s do our first steps from “safe” GRASS GUI environment which we already know. Switch in Layer Manager to Python tab.


Fig. 73 Python shell in Layer Manager.

As initial step we try to script simple computation workflow:

  1. Set computation extent to Jena city region, align region to Sentinel band
  2. Extend computation region by 1km offset
  3. Set mask based on cloud vector map
  4. Compute NDVI index
  5. Compute NDVI values statistics, print min, max and mean NDVI values

It turns into bunch of GRASS commands (map names shorten):

# 1.
g.region vector=jena_boundary align=B04_10m
# 2.
g.region n=n+1000 s=s-1000 e=e+1000 w=w-1000
# 3.
r.mask --overwrite -i vector=MaskFeature
# 4.
i.vi --overwrite red=B04_10m output=ndvi viname=ndvi nir=B08_10m
# 5.
r.univar map=ndvi


You can log GRASS modules run from Console and GUI dialogs into file by Log file (click to start/stop logging). Then you can use logged commands as a starting point for your first Python script.


Fig. 74 Log GRASS commands into file.

We turn these commands into Python syntax. In this part we will focus on GRASS Scripting Library which is simple enough for beginners.

GRASS commands can be run by core.run_command function.

# 1.
grass.run_command('g.region', vector='jena_boundary', align='L2A_T32UPB_20170706T102021_B04_10m')
# 2.
grass.run_command('g.region', n='n+1000', s='s-1000', e='e+1000', w='w-1000')
# 3.
grass.run_command('r.mask', flags='i', vector='MaskFeature', overwrite=True)
# 4.
grass.run_command('i.vi', red='L2A_T32UPB_20170706T102021_B04_10m', output='ndvi',
                  viname='ndvi', nir='L2A_T32UPB_20170706T102021_B08_10m', overwrite=True)
# 5.
grass.run_command('r.univar', map='ndvi')


Function core.run_command prints return code of run command, 0 value is fine ;-)


Python shell has its history, you can browse previous commands by Alt+P, next commands by Alt+N.

There is a weak point in our first script. Module r.univar is run by function core.run_command. In the result output of this command is discarded, only return code is printed. That’s not what we want. A solution is to run r.univar by core.read_command which does not discard command output. Instead of return code, the output is returned by this function. But it is still not perfect, statistics is printed to standard output. It would be nice to manage command output as Python object, eg. a directory. To fulfill this requirement we need to change two issues:

  • run r.univar with -g to enable shell script (parse-able) output
  • use core.parse_command function which parses output and store result as Python directory object
# 5.
stats = grass.parse_command('r.univar', flags='g', map='ndvi')
print ('NDVI min value: {0:.4f}'.format(float(stats['min'])))
print ('NDVI max value: {0:.4f}'.format(float(stats['max'])))
print ('NDVI mean value: {0:.4f}'.format(float(stats['mean'])))

Fig. 75 Running Python code in Layer Manager.

At end we can display resultant NDVI raster map by calling AddLayer() function directly from Python shell.


Graphical Modeler and Python

It is good to know that a model created in Graphical Modeler can be easily turned into Python script. Let’s open the one of models created in Unit 09 - Model tuning: ndvi-v2.gxm and go to Python editor tab.

You can easily modify generated Python script in simple editor, Run original or modified script. Script can be also saved as file (Save as).


Fig. 76 Python editor integrated in Graphical Modeler.