GRASS and Python: Difference between revisions

From GRASS-Wiki
Jump to navigation Jump to search
No edit summary
(vector example)
Line 104: Line 104:
* Attempts to eliminate the tedium of writing extension modules.
* Attempts to eliminate the tedium of writing extension modules.


'''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 [http://freegis.org/cgi-bin/viewcvs.cgi/grass6/gui/wxpython/ GRASS 6 wxPython interface] for inspiration. Important is to auto-generate the GRASS-Python class at compile time with a Python script.
Sample script for raster access (use within GRASS, Spearfish session):
 
#!/usr/bin/python
Sample script (use within GRASS):
 
  import python_grass6 as g6lib
  import python_grass6 as g6lib
   
   
Line 113: Line 111:
  mapset = 'PERMANENT'
  mapset = 'PERMANENT'
   
   
# initialize
  g6lib.G_gisinit('')
  g6lib.G_gisinit('')
  infd = g6lib.G_open_cell_old(input, mapset)
  infd = g6lib.G_open_cell_old(input, mapset)
  cell = g6lib.G_allocate_cell_buf()
  cell = g6lib.G_allocate_cell_buf()
   
   
  rown=0
  rown=0
# the API still needs error checking to be added
  while 1:
  while 1:
     myrow = g6lib.G_get_map_row_nomask(infd, cell, rown)
     myrow = g6lib.G_get_map_row_nomask(infd, cell, rown)
Line 127: Line 126:
  g6lib.G_close_cell(infd)
  g6lib.G_close_cell(infd)
  g6lib.G_free(cell)
  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 [http://freegis.org/cgi-bin/viewcvs.cgi/grass6/gui/wxpython/ 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 ===
=== Python-GRASS add-ons ===

Revision as of 11:57, 4 October 2006

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 between shell and C programms. For C part - it can handle GRASS C functions via swig. For shell part, it can be processed with g.parser, so automatic input check and help generation (apart from translation) can be processed.

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

#!/usr/bin/python

import sys
import os

#%Module
#%  description: g.parser test script
#%  keywords: keyword1, keyword2
#%End
#%flag
#%  key: f
#%  description: a flag
#%END
#%option
#% key: raster
#% type: string
#% gisprompt: old,cell,raster
#% description: raster input map
#% required : yes
#%end
#%option
#% key: vector
#% type: string
#% gisprompt: old,vector,vector
#% description: vector input map
#% required : yes
#%end
#%option
#% key: option1
#% type: string
#% description: an option
#% required : yes
#%end

def main(): 

    #add your code here
    print "" 

    if ( os.getenv("GIS_FLAG_f") != "0" ):
        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_vect:    %s" % os.getenv("GIS_OPT_vect")

    #end of your code
    return 

if __name__ == "__main__":
    args = ""
    for arg in sys.argv:
        args += arg+" "
    try:
        if ( sys.argv[1] != "@ARGS_PARSED@" ):
            os.system("g.parser %s " % (args))
    except IndexError:
        os.system("g.parser %s" % (args)) 

    if sys.argv[1] == "@ARGS_PARSED@":
        main();

Python extensions for GRASS GIS

wxPython GUI development for GRASS

Link to wxPython prototype GUI for GRASS 6

Update 18:02, 14 August 2006 (CEST) New version implements double buffered drawing to fix display issues on Debian, including flickering why panning and display being erased by overlaying windows. Output to PNG file added. Better looking zoom rectangles.

*****The wxPython code is moving to the GRASS CVS. You should look for the newest versions there. Volunteers to help with the new GUI are welcomed!***** Cmbarton

Update 00:50, 9 August 2006 (CEST) New version will run directly from GRASS prompt with new startup script. Now put gism.py and associated files into $GISBASE/etc/gmwxp and add a new script (gm.wxp) to the $GISBASE/scripts folder. Then simply type gm.wxp& from the GRASS command prompt to get the new prototype wxPython GUI for GRASS. See instructions in today's package update. Cmbarton

Update 23:59, 7 August 2006 (CEST) New version with nearly complete raster menu by Yann Chemin. Cmbarton

Update 19:02, 7 August 2006 (CEST)I just uploaded a new version of gism.py and related files. I'll keep an archive and so am changing the link to go to the folder rather than the file itself so I won't have to keep changing the link. This update includes the following changes:

  • The biggest change in wrapping in grassgui.py. This provides autogenerated wxPython GUI dialogs for all grass commands.

This can now be called from the command console (just type in the command name with no arguments as you do now) or the prototype menus. I updated grassgui.py to current wxPython syntax (mostly) and added methods to make it callable from other modules.

  • Methods added to gism.py and grassgui.py that automatically restart them with pythonw for the Mac

--Cmbarton 19:02, 7 August 2006 (CEST)

Initial development has begun on the next generation UI for GRASS. wxPython is the leading contender for a platform in which to continue development of the GRASS GUI. wxPython is a Python implementation of the well known wxWidgets (formerly wxWindows) interface development platform for C++. An initial demonstration was developed by Jachym Cepicky to show the possibility of controling GRASS via wxPython. A second generation prototype has been completed, building on Jachym's work. It is available for testing and further development at link above. --Cmbarton 07:15, 4 August 2006 (CEST)

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, etc...
  • Attempts to eliminate the tedium of writing extension modules.

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://les-ejk.cz/?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://les-ejk.cz/?cat=pywps)

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

Presentations

From FOSS4G2006: