GRASS and Python: Difference between revisions

From GRASS-Wiki
Jump to navigation Jump to search
(OSGeo Python Library)
(Replace example script with real-world case (d.shadedmap) using "grass" module)
Line 24: Line 24:
=== Example ===
=== Example ===


Example of python script, which is processed by g.parser:
Example of Python script, which is processed by g.parser:
  #!/usr/bin/python
 
  #!/usr/bin/env python
#
  ############################################################################
  ############################################################################
  #
  #
  # MODULE:       g.example
  # MODULE: d.shadedmap
#
  # AUTHOR(S): Unknown; updated to GRASS 5.7 by Michael Barton
  # AUTHOR(S):   Jane GrassUser
  # Converted to Python by Glynn Clements
  #
  # PURPOSE: Uses d.his to drape a color raster over a shaded relief map
  # PURPOSE:     Demonstrates GRASS parser usage in a Python script
  # COPYRIGHT: (C) 2004,2008 by the GRASS Development Team
#
  # COPYRIGHT:   (c) 2007 The GRASS Development Team
  #
  #
  #               This program is free software under the GNU General Public
  # This program is free software under the GNU General Public
  #               License (>=v2). Read the file COPYING that comes with GRASS
  # License (>=v2). Read the file COPYING that comes with GRASS
  #               for details.
  # for details.
  #
  #
  ############################################################################
  #############################################################################
#
# REQUIREMENTS:
#      - footool: http://www.example.org
   
   
  #%Module
  #%Module
  #% description: g.parser test script
  #% description: Drapes a color raster over a shaded relief map using d.his
#%  keywords: keyword1, keyword2
  #%End
  #%End
#%flag
#%  key: f
#%  description: a flag
#%END
  #%option
  #%option
  #% key: raster
  #% key: reliefmap
  #% type: string
  #% type: string
  #% gisprompt: old,cell,raster
  #% gisprompt: old,cell,raster
  #% description: raster input map
  #% description: Name of shaded relief or aspect map
  #% required : yes
  #% required : yes
  #%end
  #%end
  #%option
  #%option
  #% key: vector
  #% key: drapemap
  #% type: string
  #% type: string
  #% gisprompt: old,vector,vector
  #% gisprompt: old,cell,raster
  #% description: vector input map
  #% description: Name of raster to drape over relief map
  #% required : yes
  #% required : yes
  #%end
  #%end
  #%option
  #%option
  #% key: option1
  #% key: brighten
  #% type: string
  #% type: integer
  #% description: an option
  #% description: Percent to brighten
  #%  required : yes
  #% options: -99-99
  #% answer: 0
  #%end
  #%end
   
   
  import sys
  import sys
  import os
  import grass
def main():
    #### add your code here ####
    print ""
    if ( os.getenv("GIS_FLAG_F") == "1" ):
        print "Flag -f set"
    else:
        print "Flag -f not set"
    print "Value of GIS_OPT_OPTION1: %s" % os.getenv("GIS_OPT_OPTION1")
    print "Value of GIS_OPT_RASTER:  %s" % os.getenv("GIS_OPT_RASTER")
    print "Value of GIS_OPT_VECTOR:  %s" % os.getenv("GIS_OPT_VECTOR")
   
   
     #### end of your code ####
def main():
     return
    drape_map = options['drapemap']
    relief_map = options['reliefmap']
    brighten = options['brighten']
     ret = grass.run_command("d.his", h_map = drapemap,  i_map = relief_map, brighten = brighten)
     sys.exit(ret)
   
   
  if __name__ == "__main__":
  if __name__ == "__main__":
     if ( len(sys.argv) <= 1 or sys.argv[1] != "@ARGS_PARSED@" ):
     options, flags = grass.parser()
        os.execvp("g.parser", [sys.argv[0]] + sys.argv)
     main()
     else:
main();


==Python extensions for GRASS GIS==
==Python extensions for GRASS GIS==

Revision as of 12:26, 8 October 2008

(for discussions on the new GRASS GUI, see here)

Python SIGs

Python Special Interest Groups are focused collaborative efforts to develop, improve, or maintain specific Python resources. Each SIG has a charter, a coordinator, a mailing list, and a directory on the Python website. SIG membership is informal, defined by subscription to the SIG's mailing list. Anyone can join a SIG, and participate in the development discussions via the SIG's mailing list. Below is the list of currently active Python SIGs, with links to their resources.

See more at http://www.python.org/community/sigs/

Writing Python scripts in GRASS

Python is a programming language which is more powerful than shell scripting but easier and more forgiving than C. The Python script can contain simple module description definitions which will be processed with g.parser, as shown in the example below. In this way with no extra coding a GUI can be built, inputs checked, and a skeleton help page can be generated automatically. In addition it adds links to the GRASS message translation system. For code which needs access to the power of C, you can access the GRASS C library functions via the SWIG interface.

Have a look at SUBMITTING_PYTHON.

Running external commands from Python

For information on running external commands from Python, see: http://docs.python.org/lib/module-subprocess.html

Avoid using the older os.* functions. Section 17.1.3 lists equivalents using the Popen() interface, which is more robust (particularly on Windows).

Example

Example of Python script, which is processed by g.parser:

#!/usr/bin/env python
#
############################################################################
#
# MODULE:	d.shadedmap
# AUTHOR(S):	Unknown; updated to GRASS 5.7 by Michael Barton
#		Converted to Python by Glynn Clements
# PURPOSE:	Uses d.his to drape a color raster over a shaded relief map
# COPYRIGHT:	(C) 2004,2008 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.
#
#############################################################################

#%Module
#% description: Drapes a color raster over a shaded relief map using d.his
#%End
#%option
#% key: reliefmap
#% type: string
#% gisprompt: old,cell,raster
#% description: Name of shaded relief or aspect map
#% required : yes
#%end
#%option
#% key: drapemap
#% type: string
#% gisprompt: old,cell,raster
#% description: Name of raster to drape over relief map
#% required : yes
#%end
#%option
#% key: brighten
#% type: integer
#% description: Percent to brighten
#% options: -99-99
#% answer: 0
#%end

import sys
import grass

def main():
    drape_map = options['drapemap']
    relief_map = options['reliefmap']
    brighten = options['brighten']
    ret = grass.run_command("d.his", h_map = drapemap,  i_map = relief_map, brighten = brighten)
    sys.exit(ret)

if __name__ == "__main__":
    options, flags = grass.parser()
    main()

Python extensions for GRASS GIS

wxPython GUI development for GRASS

Python-SWIG-GRASS interface

There is a prototype GRASS-SWIG interface available (thanks to Sajith VK), find it in GRASS 6-CVS: swig/python/. Draft documentation is here. It now wraps both raster and vector data C functions plus the general GIS (G_*()) functions.

Background: SWIG (Simplified Wrapper and Interface Generator) is:

  • A compiler that turns ANSI C/C++ declarations into scripting language interfaces.
  • Completely automated (produces a fully working Python extension module).
  • Language neutral. SWIG can also target Tcl, Perl, Guile, MATLAB (try PyLab+Matplotlib from python), etc...
  • Attempts to eliminate the tedium of writing extension modules.

Python-SWIG examples

Sample script for raster access (use within GRASS, Spearfish session):

#!/usr/bin/python
import python_grass6 as g6lib

input = 'roads'
mapset = 'PERMANENT'

# initialize
g6lib.G_gisinit('')
infd = g6lib.G_open_cell_old(input, mapset)
cell = g6lib.G_allocate_cell_buf()

rown=0
# the API still needs error checking to be added
while 1:
    myrow = g6lib.G_get_map_row_nomask(infd, cell, rown)
    print rown,myrow[0:10]
    rown = rown+1
    if rown==476:break

g6lib.G_close_cell(infd)
g6lib.G_free(cell)

Sample script for vector access (use within GRASS, Spearfish session):

#!/usr/bin/python
import python_grass6 as g6lib

input = 'soils'
mapset = 'PERMANENT'

# initialize
g6lib.G_gisinit('')

# define map structure
map = g6lib.Map_info()

# define open level (level 2: topology)
g6lib.Vect_set_open_level (2)

# open existing map
g6lib.Vect_open_old(map, input, mapset)

# query
print 'Vect is 3D: ', g6lib.Vect_is_3d (map)
print 'Vect DB links: ', g6lib.Vect_get_num_dblinks(map)
print 'Map Scale:  1:', g6lib.Vect_get_scale(map)

# close map
g6lib.Vect_close(map)


TODO

  • Implement modules support in a Python class using --interface-description and a Python-XML parser. This should be a generic class with module's name as parameter, returning back an object which describes the module (description, flags, parameters, status of not/required). See GRASS 6 wxPython interface for inspiration. Important is to auto-generate the GRASS-Python class at compile time with a Python script.

Python-GRASS add-ons

Stand-alone addons:

  1. Jáchym Čepický's G-ps.map, a GUI to typeset printable maps with ps.map (http://193.84.38.2/~jachym/index.py?cat=gpsmap)
  2. Jáchym Čepický's v.pydigit, a GUI to v.edit (http://les-ejk.cz/?cat=vpydigit)
  3. Jáchym Čepický's PyWPS, GRASS-Web Processing Service (http://pywps.wald.intevation.org)

Using Grass gui.tcl in python

Here is some example code to use the grass automatically generated guis in python code. This could (should) all be bundled up and abstracted away so that the implementation can be replaced later.

import Tkinter
import os

# Startup (once):

tk = Tkinter.Tk()
tk.eval ("wm withdraw .")
tk.eval ("source $env(GISBASE)/etc/gui.tcl")
# Here you could do various things to change what the gui does
# See gui.tcl and README.GUI

# Make a gui (per dialog)
# This sets up a window for the command.
# This can be different to integrate with tkinter:
tk.eval ('set path ".dialog$dlg"')
tk.eval ('toplevel .dialog$dlg')
# Load the code for this command:
fd = os.popen ("d.vect --tcltk")
gui = fd.read()
# Run it
tk.eval(gui)
dlg = tk.eval('set dlg') # This is used later to get and set 

# Get the current command in the gui we just made:
currentcommand = tk.eval ("dialog_get_command " + dlg)

# Set the command in the dialog we just made:
tk.eval ("dialog_set_command " + dlg + " {d.vect map=roads}")

Links

Programming

More Python tutorials for programmers
  • RPy - Python interface to the R-statistics programming language

Presentations

From FOSS4G2006: