i.spectral.py 5.5 KB

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