vector.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. """!@package grass.script.vector
  2. @brief GRASS Python scripting module
  3. Vector related functions to be used in Python scripts.
  4. Usage:
  5. @code
  6. from grass.script import vector as grass
  7. grass.vector_db(map)
  8. ...
  9. @endcode
  10. (C) 2008-2009 by the GRASS Development Team
  11. This program is free software under the GNU General Public
  12. License (>=v2). Read the file COPYING that comes with GRASS
  13. for details.
  14. @author Glynn Clements
  15. @author Martin Landa <landa.martin gmail.com>
  16. """
  17. import os
  18. from core import *
  19. # run "v.db.connect -g ..." and parse output
  20. def vector_db(map, **args):
  21. """!Return the database connection details for a vector map
  22. (interface to `v.db.connect -g'). Example:
  23. \code
  24. >>> grass.vector_db('lakes')
  25. {1: {'layer': '1', 'name': '',
  26. 'database': '/home/martin/grassdata/nc_spm_08/PERMANENT/dbf/',
  27. 'driver': 'dbf', 'key': 'cat', 'table': 'lakes'}}
  28. \endcode
  29. @param map vector map
  30. @param args
  31. @return dictionary { layer : { 'layer', 'table, 'database', 'driver', 'key' }
  32. """
  33. s = read_command('v.db.connect', flags = 'g', map = map, fs = ';', **args)
  34. result = {}
  35. for l in s.splitlines():
  36. f = l.split(';')
  37. if len(f) != 5:
  38. continue
  39. if '/' in f[0]:
  40. f1 = f[0].split('/')
  41. layer = f1[0]
  42. name = f1[1]
  43. else:
  44. layer = f[0]
  45. name = ''
  46. result[int(layer)] = {
  47. 'layer' : layer,
  48. 'name' : name,
  49. 'table' : f[1],
  50. 'key' : f[2],
  51. 'database' : f[3],
  52. 'driver' : f[4] }
  53. return result
  54. def vector_layer_db(map, layer):
  55. """!Return the database connection details for a vector map layer.
  56. If db connection for given layer is not defined, fatal() is called.
  57. @param map map name
  58. @param layer layer number
  59. @return parsed output
  60. """
  61. try:
  62. f = vector_db(map)[int(layer)]
  63. except KeyError:
  64. grass.fatal("Database connection not defined for layer %s" % layer)
  65. return f
  66. # run "v.info -c ..." and parse output
  67. def vector_columns(map, layer = None, getDict = True, **args):
  68. """!Return a dictionary (or a list) of the columns for the
  69. database table connected to a vector map (interface to `v.info
  70. -c').
  71. @code
  72. >>> vector_columns(urbanarea, getDict = True)
  73. {'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'}}
  74. >>> vector_columns(urbanarea, getDict = False)
  75. ['cat', 'OBJECTID', 'UA', 'NAME', 'UA_TYPE']
  76. @endcode
  77. @param map map name
  78. @param layer layer number or name (None for all layers)
  79. @param getDict True to return dictionary of columns otherwise list of column names is returned
  80. @param args (v.info's arguments)
  81. @return dictionary/list of columns
  82. """
  83. s = read_command('v.info', flags = 'c', map = map, layer = layer, quiet = True, **args)
  84. if getDict:
  85. result = dict()
  86. else:
  87. result = list()
  88. i = 0
  89. for line in s.splitlines():
  90. ctype, cname = line.split('|')
  91. if getDict:
  92. result[cname] = { 'type' : ctype,
  93. 'index' : i }
  94. else:
  95. result.append(cname)
  96. i+=1
  97. return result
  98. # add vector history
  99. def vector_history(map):
  100. """!Set the command history for a vector map to the command used to
  101. invoke the script (interface to `v.support').
  102. @param map mapname
  103. @return v.support output
  104. """
  105. run_command('v.support', map = map, cmdhist = os.environ['CMDLINE'])
  106. # run "v.info -t" and parse output
  107. def vector_info_topo(map):
  108. """!Return information about a vector map (interface to `v.info
  109. -t'). Example:
  110. \code
  111. >>> grass.vector_info_topo('lakes')
  112. {'kernels': 0, 'lines': 0, 'centroids': 15279,
  113. 'boundaries': 27764, 'points': 0, 'faces': 0,
  114. 'primitives': 43043, 'islands': 7470, 'nodes': 35234, 'map3d': 0, 'areas': 15279}
  115. \endcode
  116. @param map map name
  117. @return parsed output
  118. """
  119. s = read_command('v.info', flags = 't', map = map)
  120. return parse_key_val(s, val_type = int)
  121. # interface for v.db.select
  122. def vector_db_select(map, layer = 1, **kwargs):
  123. """!Get attribute data of selected vector map layer.
  124. Function returns list of columns and dictionary of values ordered by
  125. key column value. Example:
  126. \code
  127. >>> print grass.vector_select('lakes')['values'][3]
  128. ['3', '19512.86146', '708.44683', '4', '55652', 'LAKE/POND', '39000', '']
  129. \endcode
  130. @param map map name
  131. @param layer layer number
  132. @param kwargs v.db.select options
  133. @return dictionary ('columns' and 'values')
  134. """
  135. try:
  136. key = vector_db(map = map)[layer]['key']
  137. except KeyError:
  138. error('Missing layer %d in vector map <%s>' % (layer, map))
  139. return { 'columns' : [], 'values' : {} }
  140. if kwargs.has_key('columns'):
  141. if key not in kwargs['columns'].split(','):
  142. # add key column if missing
  143. debug("Adding key column to the output")
  144. kwargs['columns'] += ',' + key
  145. ret = read_command('v.db.select',
  146. map = map,
  147. layer = layer,
  148. fs = '|', **kwargs)
  149. if not ret:
  150. error('vector_select() failed')
  151. return { 'columns' : [], 'values' : {} }
  152. columns = []
  153. values = {}
  154. for line in ret.splitlines():
  155. if not columns:
  156. columns = line.split('|')
  157. key_index = columns.index(key)
  158. continue
  159. value = line.split('|')
  160. key_value = int(value[key_index])
  161. values[key_value] = line.split('|')
  162. return { 'columns' : columns,
  163. 'values' : values }