#!/usr/bin/env python ############################################################################ # # MODULE: i.spectral # AUTHOR(S): Markus Neteler, 18. August 1998 # Converted to Python by Glynn Clements # PURPOSE: Displays spectral response at user specified locations in # group or raster images # COPYRIGHT: (C) 1999-2013 by the GRASS Development Team # # This program is free software under the GNU General Public # License (>=v2). Read the file COPYING that comes with GRASS # for details. # ############################################################################# # # this script needs gnuplot for pretty rendering # TODO: use PyPlot like the wxGUI Profiling tool # # written by Markus Neteler 18. August 1998 # neteler geog.uni-hannover.de # # bugfix: 25. Nov.98/20. Jan. 1999 # 3 March 2006: Added multiple images and group support by Francesco Pirotti - CIRGEO # #%Module #% description: Displays spectral response at user specified locations in group or images. #% keyword: imagery #% keyword: querying #% keyword: raster #% keyword: multispectral #%End #%option G_OPT_I_GROUP #% required : no #% guisection: Input #%end #%option G_OPT_I_SUBGROUP #% required : no #% guisection: Input #%end #%option G_OPT_R_INPUTS #% key: raster #% required : no #% guisection: Input #%end #%option G_OPT_M_COORDS #% multiple: yes #% required: yes #% guisection: Input #%end #%option G_OPT_F_OUTPUT #% key: output #% description: Name for output image (or text file for -t) #% guisection: Output #% required : no #%end #%Option #% key: format #% type: string #% description: Graphics format for output file #% options: png,eps,svg #% answer: png #% multiple: no #% guisection: Output #%End #%flag #% key: c #% description: Show sampling coordinates instead of numbering in the legend #%end #% flag #% key: g #% description: Use gnuplot for display #%end #% flag #% key: t #% description: output to text file #%end import os import atexit from grass.script.utils import try_rmdir from grass.script import core as gcore def cleanup(): try_rmdir(tmp_dir) def write2textf(what, output): outf = open(output, 'w') i = 0 for row in enumerate(what): i = i + 1 outf.write("%d, %s\n" % (i, row)) outf.close() def draw_gnuplot(what, xlabels, output, img_format, coord_legend): xrange = 0 for i, row in enumerate(what): outfile = os.path.join(tmp_dir, 'data_%d' % i) outf = open(outfile, 'w') xrange = max(xrange, len(row) - 2) for j, val in enumerate(row[3:]): outf.write("%d %s\n" % (j + 1, val)) outf.close() # build gnuplot script lines = [] if output: if img_format == 'png': term_opts = "png truecolor large size 825,550" elif img_format == 'eps': term_opts = "postscript eps color solid size 6,4" elif img_format == 'svg': term_opts = "svg size 825,550 dynamic solid" else: gcore.fatal(_("Programmer error (%s)") % img_format) lines += [ "set term " + term_opts, "set output '%s'" % output ] lines += [ "set xtics (%s)" % xlabels, "set grid", "set title 'Spectral signatures'", "set xrange [0.5 : %d - 0.5]" % xrange, "set noclabel", "set xlabel 'Bands'", "set xtics rotate by -40", "set ylabel 'DN Value'", "set style data lines" ] cmd = [] for i, row in enumerate(what): if not coord_legend: title = 'Pick ' + str(i + 1) else: title = str(tuple(row[0:2])) x_datafile = os.path.join(tmp_dir, 'data_%d' % i) cmd.append(" '%s' title '%s'" % (x_datafile, title)) cmd = ','.join(cmd) cmd = ' '.join(['plot', cmd, "with linespoints pt 779"]) lines.append(cmd) plotfile = os.path.join(tmp_dir, 'spectrum.gnuplot') plotf = open(plotfile, 'w') for line in lines: plotf.write(line + '\n') plotf.close() if output: gcore.call(['gnuplot', plotfile]) else: gcore.call(['gnuplot', '-persist', plotfile]) def draw_linegraph(what): yfiles = [] xfile = os.path.join(tmp_dir, 'data_x') xf = open(xfile, 'w') for j, val in enumerate(what[0][3:]): xf.write("%d\n" % (j + 1)) xf.close() for i, row in enumerate(what): yfile = os.path.join(tmp_dir, 'data_y_%d' % i) yf = open(yfile, 'w') for j, val in enumerate(row[3:]): yf.write("%s\n" % val) yf.close() yfiles.append(yfile) sienna = '#%02x%02x%02x' % (160, 82, 45) coral = '#%02x%02x%02x' % (255, 127, 80) gp_colors = ['red', 'green', 'blue', 'magenta', 'cyan', sienna, 'orange', coral] colors = gp_colors while len(what) > len(colors): colors += gp_colors colors = colors[0:len(what)] gcore.run_command('d.linegraph', x_file=xfile, y_file=yfiles, y_color=colors, title=_("Spectral signatures"), x_title=_("Bands"), y_title=_("DN Value")) def main(): group = options['group'] subgroup = options['subgroup'] raster = options['raster'] output = options['output'] coords = options['coordinates'] img_fmt = options['format'] coord_legend = flags['c'] gnuplot = flags['g'] textfile = flags['t'] global tmp_dir tmp_dir = gcore.tempdir() if not group and not raster: gcore.fatal(_("Either group= or raster= is required")) if group and raster: gcore.fatal(_("group= and raster= are mutually exclusive")) # -t needs an output filename if textfile and not output: gcore.fatal(_("Writing to text file requires output=filename")) # check if gnuplot is present if gnuplot and not gcore.find_program('gnuplot', '-V'): gcore.fatal(_("gnuplot required, please install first")) # get data from group listing and set the x-axis labels if group: # Parse the group list output if subgroup: s = gcore.read_command('i.group', flags='g', group=group, subgroup=subgroup, quiet=True) else: s = gcore.read_command('i.group', flags='g', group=group, quiet=True) rastermaps = s.splitlines() else: # get data from list of files and set the x-axis labels rastermaps = raster.split(',') xlabels = ["'%s' %d" % (n, i + 1) for i, n in enumerate(rastermaps)] xlabels = ','.join(xlabels) # get y-data for gnuplot-data file what = [] s = gcore.read_command('r.what', map=rastermaps, coordinates=coords, null='0', quiet=True) if len(s) == 0: gcore.fatal(_('No data returned from query')) for l in s.splitlines(): f = l.split('|') for i, v in enumerate(f): if v in ['', '*']: f[i] = 0 else: f[i] = float(v) what.append(f) # build data files if gnuplot: draw_gnuplot(what, xlabels, output, img_fmt, coord_legend) elif textfile: write2textf(what, output) else: draw_linegraph(what) if __name__ == "__main__": options, flags = gcore.parser() atexit.register(cleanup) main()