vector.py 6.0 KB

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