GRASS Programmer's Manual  6.4.2(2012)
vector.py
Go to the documentation of this file.
00001 """!@package grass.script.vector
00002 
00003 @brief GRASS Python scripting module (vector functions)
00004 
00005 Vector related functions to be used in Python scripts.
00006 
00007 Usage:
00008 
00009 @code
00010 from grass.script import vector as grass
00011 
00012 grass.vector_db(map)
00013 ...
00014 @endcode
00015 
00016 (C) 2008-2010 by the GRASS Development Team
00017 This program is free software under the GNU General Public
00018 License (>=v2). Read the file COPYING that comes with GRASS
00019 for details.
00020 
00021 @author Glynn Clements
00022 @author Martin Landa <landa.martin gmail.com>
00023 """
00024 
00025 import os
00026 import types
00027 import __builtin__
00028 
00029 from core import *
00030 
00031 # i18N
00032 import gettext
00033 gettext.install('grasslibs', os.path.join(os.getenv("GISBASE"), 'locale'), unicode=True)
00034 
00035 # run "v.db.connect -g ..." and parse output
00036 
00037 def vector_db(map, **args):
00038     """!Return the database connection details for a vector map
00039     (interface to `v.db.connect -g'). Example:
00040     
00041     \code
00042     >>> grass.vector_db('lakes')
00043     {1: {'layer': '1', 'name': '',
00044     'database': '/home/martin/grassdata/nc_spm_08/PERMANENT/dbf/',
00045     'driver': 'dbf', 'key': 'cat', 'table': 'lakes'}}
00046     \endcode
00047 
00048     @param map vector map
00049     @param args
00050 
00051     @return dictionary { layer : { 'layer', 'table, 'database', 'driver', 'key' }
00052     """
00053     s = read_command('v.db.connect', flags = 'g', map = map, fs = ';', **args)
00054     result = {}
00055     
00056     for l in s.splitlines():
00057         f = l.split(';')
00058         if len(f) != 5:
00059             continue
00060         
00061         if '/' in f[0]:
00062             f1 = f[0].split('/')
00063             layer = f1[0]
00064             name = f1[1]
00065         else:
00066             layer = f[0]
00067             name = ''
00068             
00069         result[int(layer)] = {
00070             'layer'    : layer,
00071             'name'     : name,
00072             'table'    : f[1],
00073             'key'      : f[2],
00074             'database' : f[3],
00075             'driver'   : f[4] }
00076     
00077     return result
00078 
00079 def vector_layer_db(map, layer):
00080     """!Return the database connection details for a vector map layer.
00081     If db connection for given layer is not defined, fatal() is called.
00082     
00083     @param map map name
00084     @param layer layer number
00085     
00086     @return parsed output
00087     """
00088     try:
00089         f = vector_db(map)[int(layer)]
00090     except KeyError:
00091         fatal(_("Database connection not defined for layer %s") % layer)
00092 
00093     return f
00094 
00095 # run "v.info -c ..." and parse output
00096 
00097 def vector_columns(map, layer = None, getDict = True, **args):
00098     """!Return a dictionary (or a list) of the columns for the
00099     database table connected to a vector map (interface to `v.info
00100     -c').
00101 
00102     @code
00103     >>> vector_columns(urbanarea, getDict = True)
00104     {'UA_TYPE': {'index': 4, 'type': 'CHARACTER'}, 'UA': {'index': 2, 'type': 'CHARACTER'}, 'NAME': {'index': 3, 'type': 'CHARACTER'}, 'OBJECTID': {'index': 1, 'type': 'INTEGER'}, 'cat': {'index': 0, 'type': 'INTEGER'}}
00105 
00106     >>> vector_columns(urbanarea, getDict = False)
00107     ['cat', 'OBJECTID', 'UA', 'NAME', 'UA_TYPE']
00108     @endcode
00109     
00110     @param map map name
00111     @param layer layer number or name (None for all layers)
00112     @param getDict True to return dictionary of columns otherwise list of column names is returned
00113     @param args (v.info's arguments)
00114     
00115     @return dictionary/list of columns
00116     """
00117     s = read_command('v.info', flags = 'c', map = map, layer = layer, quiet = True, **args)
00118     if getDict:
00119         result = dict()
00120     else:
00121         result = list()
00122     i = 0
00123     for line in s.splitlines():
00124         ctype, cname = line.split('|')
00125         if getDict:
00126             result[cname] = { 'type' : ctype,
00127                               'index' : i }
00128         else:
00129             result.append(cname)
00130         i+=1
00131     
00132     return result
00133 
00134 # add vector history
00135 
00136 def vector_history(map):
00137     """!Set the command history for a vector map to the command used to
00138     invoke the script (interface to `v.support').
00139 
00140     @param map mapname
00141 
00142     @return v.support output
00143     """
00144     run_command('v.support', map = map, cmdhist = os.environ['CMDLINE'])
00145 
00146 # run "v.info -t" and parse output
00147 
00148 def vector_info_topo(map):
00149     """!Return information about a vector map (interface to `v.info
00150     -t'). Example:
00151 
00152     \code
00153     >>> grass.vector_info_topo('lakes')
00154     {'kernels': 0, 'lines': 0, 'centroids': 15279,
00155     'boundaries': 27764, 'points': 0, 'faces': 0,
00156     'primitives': 43043, 'islands': 7470, 'nodes': 35234, 'map3d': 0, 'areas': 15279}
00157     \endcode
00158     
00159     @param map map name
00160 
00161     @return parsed output
00162     """
00163     s = read_command('v.info', flags = 't', map = map)
00164     ret = parse_key_val(s, val_type = int)
00165     if 'map3d' in ret:
00166         ret['map3d'] = bool(ret['map3d'])
00167     
00168     return ret
00169 
00170 # interface for v.db.select
00171 
00172 def vector_db_select(map, layer = 1, **kwargs):
00173     """!Get attribute data of selected vector map layer.
00174 
00175     Function returns list of columns and dictionary of values ordered by
00176     key column value. Example:
00177 
00178     \code
00179     >>> print grass.vector_select('lakes')['values'][3]
00180     ['3', '19512.86146', '708.44683', '4', '55652', 'LAKE/POND', '39000', '']
00181     \endcode
00182 
00183     @param map map name
00184     @param layer layer number
00185     @param kwargs v.db.select options
00186 
00187     @return dictionary ('columns' and 'values')
00188     """
00189     try:
00190         key = vector_db(map = map)[layer]['key']
00191     except KeyError:
00192         error(_('Missing layer %(layer)d in vector map <%(map)s>') % \
00193                   { 'layer' : layer, 'map' : map })
00194         return { 'columns' : [], 'values' : {} }
00195         
00196     if 'columns' in kwargs:
00197         if key not in kwargs['columns'].split(','):
00198             # add key column if missing
00199             debug("Adding key column to the output")
00200             kwargs['columns'] += ',' + key
00201     
00202     ret = read_command('v.db.select',
00203                        map = map,
00204                        layer = layer,
00205                        **kwargs)
00206     
00207     if not ret:
00208         error(_('vector_select() failed'))
00209         return { 'columns' : [], 'values' : {} }
00210     
00211     columns = []
00212     values = {}
00213     for line in ret.splitlines():
00214         if not columns:
00215             columns = line.split('|')
00216             key_index = columns.index(key)
00217             continue
00218         
00219         value = line.split('|')
00220         key_value = int(value[key_index])
00221         values[key_value] = line.split('|')
00222     
00223     return { 'columns' : columns,
00224              'values' : values }
00225 
00226 # interface to v.what
00227 def vector_what(map, coord, distance = 0.0):
00228     """!Query vector map at given locations
00229     
00230     To query one vector map at one location
00231     @code
00232     print grass.vector_what(map = 'archsites', coord = (595743, 4925281), distance = 250)
00233 
00234     [{'Category': 8, 'Map': 'archsites', 'Layer': 1, 'Key_column': 'cat',
00235       'Database': '/home/martin/grassdata/spearfish60/PERMANENT/dbf/',
00236       'Mapset': 'PERMANENT', 'Driver': 'dbf',
00237       'Attributes': {'str1': 'No_Name', 'cat': '8'},
00238       'Table': 'archsites', 'Type': 'Point', 'Id': 8}]
00239     @endcode
00240 
00241     To query one vector map at more locations
00242     @code
00243     for q in grass.vector_what(map = ('archsites', 'roads'), coord = (595743, 4925281),
00244                                distance = 250):
00245         print q['Map'], q['Attributes']
00246                             
00247     archsites {'str1': 'No_Name', 'cat': '8'}
00248     roads {'label': 'interstate', 'cat': '1'}
00249     @endcode
00250 
00251     To query more vector maps at one location
00252     @code
00253     for q in grass.vector_what(map = 'archsites', coord = [(595743, 4925281), (597950, 4918898)],
00254                                distance = 250):
00255         print q['Map'], q['Attributes']
00256 
00257     archsites {'str1': 'No_Name', 'cat': '8'}
00258     archsites {'str1': 'Bob_Miller', 'cat': '22'}
00259     @endcode
00260 
00261     @param map vector map(s) to query given as string or list/tuple
00262     @param coord coordinates of query given as tuple (easting, northing) or list of tuples
00263     @param distance query threshold distance (in map units)
00264 
00265     @return parsed list
00266     """
00267     if "LC_ALL" in os.environ:
00268         locale = os.environ["LC_ALL"]
00269         os.environ["LC_ALL"] = "C"
00270 
00271     if type(map) in (types.StringType, types.UnicodeType):
00272         map_list = [map]
00273     else:
00274         map_list = map
00275     
00276     coord_list = list()
00277     if type(coord) is types.TupleType:
00278         coord_list.append('%f,%f' % (coord[0], coord[1]))
00279     else:
00280         for e, n in coord:
00281             coord_list.append('%f,%f' % (e, n))
00282     
00283     ret = read_command('v.what',
00284                        quiet      = True,
00285                        flags      = 'ag',
00286                        map        = ','.join(map_list),
00287                        east_north = ','.join(coord_list),
00288                        distance   = float(distance))
00289     
00290     if "LC_ALL" in os.environ:
00291         os.environ["LC_ALL"] = locale
00292         
00293     data = list()
00294     if not ret:
00295         return data
00296     
00297     dict_attrb = None
00298     for item in ret.splitlines():
00299         try:
00300             key, value = __builtin__.map(lambda x: x.strip(), item.split('=', 1))
00301         except ValueError:
00302             continue
00303         if key in ('East', 'North'):
00304             continue
00305         
00306         if key == 'Map':
00307             dict_main  = { 'Map' : value }
00308             dict_attrb = None
00309             data.append(dict_main)
00310             continue
00311         else:
00312             if dict_attrb is not None:
00313                 dict_attrb[key] = value
00314             else:
00315                 if key in ('Category', 'Layer', 'Id'):
00316                     dict_main[key] = int(value)
00317                 else:
00318                     dict_main[key] = value
00319             if key == 'Key_column':
00320                 # skip attributes
00321                 dict_attrb = dict()
00322                 dict_main['Attributes'] = dict_attrb
00323     
00324     return data
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines