i.spectral.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. #!/usr/bin/env python
  2. ############################################################################
  3. #
  4. # MODULE: i.spectral
  5. # AUTHOR(S): Markus Neteler, 18. August 1998
  6. # Converted to Python by Glynn Clements
  7. # PURPOSE: displays spectral response at user specified locations in group or images
  8. # COPYRIGHT: (C) 1999 by 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. # written by Markus Neteler 18. August 1998
  16. # neteler geog.uni-hannover.de
  17. #
  18. # bugfix: 25. Nov.98/20. Jan. 1999
  19. # 3 March 2006: Added multiple images and group support by Francesco Pirotti - CIRGEO
  20. # this script needs gnuplot
  21. #%Module
  22. #% description: Displays spectral response at user specified locations in group or images.
  23. #% keywords: imagery, raster, multispectral
  24. #%End
  25. #%option
  26. #% key: group
  27. #% type: string
  28. #% gisprompt: old,group
  29. #% description: Group input
  30. #% required : no
  31. #%end
  32. #%option
  33. #% key: raster
  34. #% type: string
  35. #% gisprompt: old,cell,raster
  36. #% description: Raster input maps
  37. #% multiple : yes
  38. #% required : no
  39. #%end
  40. #%option
  41. #% key: output
  42. #% type: string
  43. #% gisprompt: new_file,file,PNG
  44. #% description: Write output to PNG image
  45. #% multiple : no
  46. #% required : no
  47. #%end
  48. #%option
  49. #% key: coords
  50. #% type: double
  51. #% key_desc: east,north
  52. #% description: Coordinates
  53. #% multiple : yes
  54. #% required : yes
  55. #%end
  56. #%flag
  57. #%key: c
  58. #%description: Label with coordinates instead of numbering
  59. #%end
  60. #%flag
  61. #%key: g
  62. #%description: Use gnuplot for display
  63. #%end
  64. import sys
  65. import os
  66. import atexit
  67. import glob
  68. from grass.script import core as grass
  69. def cleanup():
  70. grass.try_remove('spectrum.gnuplot')
  71. for name in glob.glob('data_[0-9]*'):
  72. if name[5:].isdigit():
  73. grass.try_remove(name)
  74. grass.try_remove('data_x')
  75. for name in glob.glob('data_y_[0-9]*'):
  76. if name[7:].isdigit():
  77. grass.try_remove(name)
  78. def draw_gnuplot(what, xlabels, output, label):
  79. xrange = 0
  80. for i, row in enumerate(what):
  81. outfile = 'data_%d' % i
  82. outf = file(outfile, 'w')
  83. xrange = max(xrange, len(row) - 2)
  84. for j, val in enumerate(row[3:]):
  85. outf.write("%d %s\n" % (j + 1, val))
  86. outf.close()
  87. # build gnuplot script
  88. lines = []
  89. if output:
  90. lines += [
  91. "set term png large",
  92. "set output '%s'" % output
  93. ]
  94. lines += [
  95. "set xtics (%s)" % xlabels,
  96. "set grid",
  97. "set title 'Spectral signatures'",
  98. "set xrange [0:%d]" % xrange,
  99. "set noclabel",
  100. "set xlabel 'Bands'",
  101. "set ylabel 'DN Value'",
  102. "set data style lines"
  103. ]
  104. cmd = []
  105. for i, row in enumerate(what):
  106. if not label:
  107. title = str(i + 1)
  108. else:
  109. title = str(tuple(row[0:2]))
  110. cmd.append("'data_%d' title '%s'" % (i, title))
  111. cmd = ','.join(cmd)
  112. cmd = ' '.join(['plot', cmd, "with linespoints pt 779"])
  113. lines.append(cmd)
  114. plotfile = 'spectrum.gnuplot'
  115. plotf = file(plotfile, 'w')
  116. for line in lines:
  117. plotf.write(line + '\n')
  118. plotf.close()
  119. if output:
  120. grass.call(['gnuplot', plotfile])
  121. else:
  122. grass.call(['gnuplot', '-persist', plotfile])
  123. def draw_linegraph(what):
  124. yfiles = []
  125. xfile = 'data_x'
  126. xf = file(xfile, 'w')
  127. for j, val in enumerate(what[0][3:]):
  128. xf.write("%d\n" % (j + 1))
  129. xf.close()
  130. for i, row in enumerate(what):
  131. yfile = 'data_y_%d' % i
  132. yf = file(yfile, 'w')
  133. for j, val in enumerate(row[3:]):
  134. yf.write("%s\n" % val)
  135. yf.close()
  136. yfiles.append(yfile)
  137. sienna = '#%02x%02x%02x' % (160, 82, 45)
  138. coral = '#%02x%02x%02x' % (255, 127, 80)
  139. gp_colors = ['red', 'green', 'blue', 'magenta', 'cyan', sienna, 'orange', coral]
  140. colors = gp_colors
  141. while len(what) > len(colors):
  142. colors += gp_colors
  143. colors = colors[0:len(what)]
  144. grass.run_command('d.linegraph', x_file = xfile, y_file = yfiles,
  145. y_color = colors, title = 'Spectral signatures',
  146. x_title = 'Bands', y_title = 'DN Value')
  147. def main():
  148. group = options['group']
  149. raster = options['raster']
  150. output = options['output']
  151. coords = options['coords']
  152. label = flags['c']
  153. gnuplot = flags['g']
  154. if not group and not raster:
  155. grass.fatal("Either group= or raster= is required")
  156. if group and raster:
  157. grass.fatal("group= and raster= are mutually exclusive")
  158. #check if present
  159. if gnuplot and not grass.find_program('gnuplot', ['-V']):
  160. grass.fatal("gnuplot required, please install first")
  161. tmp1 = grass.tempfile()
  162. tmp2 = grass.tempfile()
  163. # get y-data for gnuplot-data file
  164. # get data from group files and set the x-axis labels
  165. if group:
  166. # ## PARSES THE GROUP FILES - gets rid of ugly header info from group list output
  167. maps = []
  168. s = grass.read_command('i.group', flags='l', group = group, quiet = True)
  169. active = False
  170. for l in s.splitlines():
  171. if l == '-------------':
  172. active = not active
  173. continue
  174. if not active:
  175. continue
  176. f = l.replace(' in ','@').split()
  177. maps += f
  178. rastermaps = maps
  179. else:
  180. # ## get data from list of files and set the x-axis labels
  181. rastermaps = raster.split(',')
  182. xlabels = ["'%s' %d" % (n, i + 1) for i, n in enumerate(rastermaps)]
  183. xlabels = ','.join(xlabels)
  184. numbands = len(rastermaps)
  185. what = []
  186. s = grass.read_command('r.what', input = rastermaps, east_north = coords, quiet = True)
  187. for l in s.splitlines():
  188. f = l.split('|')
  189. for i, v in enumerate(f):
  190. if v in ['', '*']:
  191. f[i] = 0
  192. else:
  193. f[i] = float(v)
  194. what.append(f)
  195. # build data files
  196. if gnuplot:
  197. draw_gnuplot(what, xlabels, output, label)
  198. else:
  199. draw_linegraph(what)
  200. if __name__ == "__main__":
  201. options, flags = grass.parser()
  202. atexit.register(cleanup)
  203. main()