GRASS Programmer's Manual
6.4.2(2012)
|
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