v.report.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. #!/usr/bin/env python
  2. #
  3. ############################################################################
  4. #
  5. # MODULE: v.report
  6. # AUTHOR(S): Markus Neteler, converted to Python by Glynn Clements
  7. # PURPOSE: Reports geometry statistics for vector maps
  8. # COPYRIGHT: (C) 2005, 2007 by MN and the GRASS Development Team
  9. #
  10. # This program is free software under the GNU General Public
  11. # License (>=v2). Read the file COPYING that comes with GRASS
  12. # for details.
  13. #
  14. #############################################################################
  15. #%Module
  16. #% description: Reports geometry statistics for vectors.
  17. #% keywords: vector, report, statistics
  18. #%End
  19. #%Flag
  20. #% key: r
  21. #% description: Reverse sort the result
  22. #%End
  23. #%Flag
  24. #% key: s
  25. #% description: Sort the result
  26. #%End
  27. #%option
  28. #% key: map
  29. #% type: string
  30. #% gisprompt: old,vector,vector
  31. #% description: Name of input vector map
  32. #% required: yes
  33. #%end
  34. #%option
  35. #% key: layer
  36. #% type: integer
  37. #% answer: 1
  38. #% description: Layer number
  39. #% required: no
  40. #%end
  41. #%option
  42. #% key: option
  43. #% type: string
  44. #% description: Value to calculate
  45. #% options: area,length,coor
  46. #% required: yes
  47. #%end
  48. #%option
  49. #% key: units
  50. #% type: string
  51. #% description: mi(les),f(eet),me(ters),k(ilometers),a(cres),h(ectares),p(ercent)
  52. #% options: mi,miles,f,feet,me,meters,k,kilometers,a,acres,h,hectares,p,percent
  53. #% required: no
  54. #%end
  55. import sys
  56. import os
  57. import grass
  58. def uniq(l):
  59. result = []
  60. last = None
  61. for i in l:
  62. if i != last:
  63. result.append(i)
  64. last = i
  65. return result
  66. def main():
  67. if flags['r'] and flags['s']:
  68. grass.fatal("Either -r or -s flag")
  69. mapname = options['map']
  70. option = options['option']
  71. layer = options['layer']
  72. units = options['units']
  73. nuldev = file(os.devnull, 'w')
  74. if not grass.find_file(mapname, 'vector')['file']:
  75. grass.fatal("Vector map '%s' not found in mapset search path." % mapname)
  76. table_exists = grass.vector_columns(mapname, layer, stderr = nuldev)
  77. if table_exists:
  78. colnames = [f[1] for f in grass.vector_columns(mapname, layer, stderr = nuldev)]
  79. else:
  80. colnames = ['cat']
  81. if option == 'coor':
  82. columns = ['dummy1','dummy2','dummy3']
  83. extracolnames = ['x','y','z']
  84. else:
  85. columns = ['dummy1']
  86. extracolnames = [option]
  87. if units in ['p','percent']:
  88. unitsp = 'meters'
  89. elif units:
  90. unitsp = units
  91. else:
  92. unitsp = None
  93. # NOTE: we suppress -1 cat and 0 cat
  94. if table_exists:
  95. p = grass.pipe_command('v.db.select', flags='c', map = mapname, layer = layer)
  96. records1 = []
  97. for line in p.stdout:
  98. cols = line.rstrip('\r\n').split('|')
  99. if cols[0] == '0':
  100. continue
  101. records1.append([int(cols[0])] + cols[1:])
  102. p.wait()
  103. records1.sort()
  104. if len(records1) == 0:
  105. f = grass.vector_db(mapname, layer)
  106. key = f[2]
  107. grass.fatal("There is a table connected to input vector map '%s', but" +
  108. "there are no categories present in the key column '%s'. Consider using" +
  109. "v.to.db to correct this." % (mapname, key))
  110. #fetch the requested attribute sorted by cat:
  111. p = grass.pipe_command('v.to.db', flags = 'p',
  112. map = mapname, option = option, columns = columns,
  113. layer = layer, units = unitsp)
  114. records2 = []
  115. for line in p.stdout:
  116. fields = line.rstrip('\r\n').split('|')
  117. if fields[0] in ['cat', '-1', '0']:
  118. continue
  119. records2.append([int(fields[0])] + fields[1:])
  120. p.wait()
  121. records2.sort()
  122. #make pre-table
  123. records3 = [r1 + r2[1:] for r1, r2 in zip(records1, records2)]
  124. else:
  125. records1 = []
  126. p = grass.pipe_command('v.category', inp = mapname, layer = layer, option = 'print')
  127. for line in p.stdout:
  128. field = int(line.rstrip())
  129. if field > 0:
  130. records1.append(field)
  131. p.wait()
  132. records1.sort()
  133. records1 = uniq(records1)
  134. #make pre-table
  135. p = grass.pipe_command('v.to.db', flags = 'p',
  136. map = mapname, option = option, columns = columns,
  137. layer = layer, units = unitsp)
  138. records3 = []
  139. for line in p.stdout:
  140. fields = line.split('|')
  141. if fields[0] in ['cat', '-1', '0']:
  142. continue
  143. records3.append([int(fields[0])] + fields[1:])
  144. p.wait()
  145. records3.sort()
  146. # print table header
  147. sys.stdout.write('|'.join(colnames + extracolnames) + '\n')
  148. #make and print the table:
  149. numcols = len(colnames) + len(extracolnames)
  150. # calculate percents if requested
  151. if units != '' and units in ['p','percent']:
  152. # calculate total area value
  153. areatot = 0
  154. for r in records3:
  155. areatot += float(r[-1])
  156. # calculate area percentages
  157. records4 = [float(r[-1]) * 100 / areatot for r in records3]
  158. records3 = [r1 + [r4] for r1, r4 in zip(records1, records4)]
  159. if flags['s']:
  160. # sort
  161. records3.sort(key = lambda r: (r[0], r[-1]))
  162. elif flags['r']:
  163. # reverse sort
  164. records3.sort(key = lambda r: (r[0], r[-1]), reverse = True)
  165. for r in records3:
  166. sys.stdout.write('|'.join(map(str,r)) + '\n')
  167. if __name__ == "__main__":
  168. options, flags = grass.parser()
  169. main()