The Modules module permits to work directly with the GRASS GIS module
from IPython.display import Image
from pprint import pprint
from subprocess import PIPE
import numpy as np
from show import show
GRASS6 and GRASS7, the traditional way for scripting.
Import grass script module, which has some useful functions:
from grass import script
import subprocess
Let's have a look which function containing the word command are available, with:
script.list_pairs(type='rast')
print script.read_command('r.info', map='elevation')
script.make_command('r.info', map='elevation', flags='r')
Popen
object¶script.start_command('r.info', map='elevation')
process = script.start_command('r.info', map='elevation', flags='r', stdout=PIPE)
stdout = process.stdout
print([line.strip().split('=') for line in stdout])
script.parse_command('r.info', map='elevation', flags='g', delimiter='=')
script.parse_command('g.region', flags='p', delimiter=':')
region = script.pipe_command('r.info', map='elevation', flags='r')
region
stdout = ''.join(line for line in region.stdout)
print(stdout)
stdout = script.read_command('r.info', map='elevation', flags='r')
print(stdout)
mrange = dict([line.split('=') for line in stdout.split('\n') if line != ''])
for k in mrange:
mrange[k] = float(mrange[k])
mrange
Write the rules that we want to use for the reclassification:
keys = ['low', 'medium low', 'medium', 'medium high', 'high']
vals = np.linspace(mrange['min']-1, mrange['max']+1, num=len(keys)+1, endpoint=True)
rvals = [(int(vals[i-1])+1, int(vals[i]), i, keys[i-1]) for i in range(1, len(vals))]
rules = '\n'.join(['%3d thru %3d = %2d %s' % v for v in rvals])
print(rules)
Now we can pass as input for the r.reclass the rules using the function write_command
:
script.write_command('r.reclass', input='elevation', output='elev', rules='-', overwrite=True, stdin=rules)
Start a new virtual monitor that generate a file: view.png
that we can display inside the ipython notebook.
script.run_command('d.mon', start='png', output='view.png', overwrite=True)
script.run_command('d.rast', map='elevation')
Image('view.png')
script.run_command('d.rast', map='elev')
Image('view.png')
script.run_command('d.mon', stop='png')
User who just wants to replace BASH with python has to import modules in the following manner:
from grass.pygrass.modules.shortcuts import raster as r, vector as v, general as g, display as d
from grass.pygrass.modules import Module
And then call the grass modules
g.region(raster='elevation', flags='p')
print(g.region(flags='p', stdout_=PIPE).outputs.stdout)
If the name of the grass module contains "." you should replace it with "_". See the example bellow:
r.slope_aspect(elevation='elevation', slope='slope', aspect='aspect', overwrite=True)
r.mapcalc("slope_gt_10 = if(slope > 10, slope, null())", overwrite=True)
print(r.info(map='slope_gt_10', flags='r', stdout_=PIPE).outputs.stdout)
show('slope_gt_10', flags='n')
show('slope')
Some small tips of the new interface in python/ipython:
r.slope_aspect?
Do something with the vectors:
script.list_pairs(type='vect')
v.to_rast(input='hospitals', output='hospitals', type="point", use='cat', overwrite=True, quiet=True)
script.list_pairs(type='rast')
If you have a python script and want to convert it to use the new python interface, you just need to transform:
#from grass.script.core import run_command
from grass.pygrass.modules import Module as run_command
run_command("r.info", map='elevation')
#etc...
Import the Module class, and instantiate the command, the name of the GRASS module is required.
from grass.pygrass.modules import Module
slp = Module("r.slope.aspect")
slp.name
slp.description
slp.keywords
slp.label
# get the documentation of the module
slp?
The instantiated module splits the parameters in:
both parameters are an OrderedDict python object. Additionally, the 'required' attribute returns a list of the parameters that are required.
pprint(dict(slp.inputs))
pprint(dict(slp.outputs))
slp.required
slp.inputs['elevation']
slp.inputs.elevation = "elevation"
slp.inputs.elevation
slp.inputs["format"]
slp.inputs.format = 'percent'
slp.outputs.slope = 'slope'
slp.flags.g = True
slp.flags.a = True
print slp.flags.overwrite # --overwrite, --verbose, --quite
slp.flags.overwrite = True
# run the module
slp.run()
print slp # __str__
repr(slp) # __repr__
from grass.pygrass.modules import Module
slp = Module("r.slope.aspect")
slp(elevation='elevation',
slope='slp', aspect='asp',
format='percent', overwrite=True,
verbose=False, flags='a', run_=False)
print slp.get_bash()
print slp.get_python()
slp(elevation='elevation', slope='slp', aspect='asp', format='percent', overwrite=True)
slp(elevation='elevation', slope='slp', aspect='asp', format='percent', overwrite=True, run_=False)
slp(elevation='elevation', slope='slp', aspect='asp', format='percent', overwrite=True, run_=True, finish_=False)
slp.popen.wait() # .kill()
stdin_
, stdout_
, stderr_
¶slp(elevation='elevation', slope='slp', aspect='asp',
format='percent', overwrite=True, stderr_=PIPE, run_=True)
print(slp.outputs.stderr)
gmapset = g.mapset(mapset='_', flags='p', stdout_=PIPE)
gmapset.outputs.stdout.strip()
We have seen:
Transform the following Bash script:
into a Python one:
!g.region -p
Read the output of g.region and return a dictionary.
%%file mygrassmodule.py
#!/usr/bin/env python
# -- coding: utf-8 --
#
############################################################################
#
# MODULE: <name of your module>
#
# AUTHOR(S): <your name>
#
# COPYRIGHT: (C) 2013 by the GRASS Development Team
#
# This program is free software under the GNU General Public
# License (>=v2). Read the file COPYING that comes with GRASS
# for details.
#
#############################################################################
##-----------------------
## DESCRIPTION
##-----------------------
#%Module
#% description: <description>
#% keywords: <keyword 1>
#% keywords: <keyword 1>
#% keywords: <keyword 1>
#% overwrite: yes
#%End
##-----------------------
## VECTOR INPUT
##-----------------------
#%option G_OPT_V_MAP
#% key: key0
#% description: <parameter description>
#% required: yes
#%end
##-----------------------
## MULTI RASTER INPUT
##-----------------------
#%option G_OPT_R_INPUTS
#% key: key1
#% description: <parameter description>
#% multiple: yes
#% required: no
#%end
##-----------------------
## STRING INPUT
##-----------------------
#%option
#% key: key2
#% description: <parameter description>
#% type: string
#% multiple: yes
#% required: no
#%end
from pprint import pprint
from grass.script import parser
def main(opts, flgs):
print('OPTIONS:')
pprint(opts)
print('FLAGS:')
pprint(flgs)
if __name__ == "__main__":
opts, flgs = parser()
main(opts, flgs)
!python2 mygrassmodule.py --h
!python2 mygrassmodule.py key0=pippo key1=pluto,topolino key2=minni,clarabella