[GRASS-SVN] r73642 - sandbox/wenzeslaus/r.mapcalculator
svn_grass at osgeo.org
svn_grass at osgeo.org
Sun Nov 4 19:36:19 PST 2018
Author: wenzeslaus
Date: 2018-11-04 19:36:19 -0800 (Sun, 04 Nov 2018)
New Revision: 73642
Modified:
sandbox/wenzeslaus/r.mapcalculator/Makefile
sandbox/wenzeslaus/r.mapcalculator/r.mapcalculator.html
sandbox/wenzeslaus/r.mapcalculator/r.mapcalculator.py
Log:
r.mapcalculator: complete rewrite for Python and version 7.6
Modified: sandbox/wenzeslaus/r.mapcalculator/Makefile
===================================================================
--- sandbox/wenzeslaus/r.mapcalculator/Makefile 2018-11-05 03:16:21 UTC (rev 73641)
+++ sandbox/wenzeslaus/r.mapcalculator/Makefile 2018-11-05 03:36:19 UTC (rev 73642)
@@ -1,6 +1,6 @@
MODULE_TOPDIR = ../..
-PGM=r.mapcalculator
+PGM = r.mapcalculator
include $(MODULE_TOPDIR)/include/Make/Script.make
Modified: sandbox/wenzeslaus/r.mapcalculator/r.mapcalculator.html
===================================================================
--- sandbox/wenzeslaus/r.mapcalculator/r.mapcalculator.html 2018-11-05 03:16:21 UTC (rev 73641)
+++ sandbox/wenzeslaus/r.mapcalculator/r.mapcalculator.html 2018-11-05 03:36:19 UTC (rev 73642)
@@ -1,43 +1,116 @@
<h2>DESCRIPTION</h2>
-<em>r.mapcalculator</em> provides a GUI frontend to <em>r.mapcalc</em>.
-Up to 5 maps can be combined using simple expressions.
-In the expert mode, it runs <em>r.mapcalc</em> for more complex expressions.
+<em>r.mapcalculator</em> provides a wrapper to <em>r.mapcalc</em>.
+Up to 6 maps can be combined using simple expressions.
-Enter an <em>r.mapcalc</em> expression in the formula field using the
-format:<br>
-<tt>A+B</tt> or <tt>exp(A+C)+(B-2)*7</tt> where A, B, C are raster maps
-entered in the A field, B field, and C field.
<p>
-Do not enter output file in the formula field, hence:
+The general syntax for the <b>expression</b> follows
+<em><a href="r.mapcalc.html">r.mapcalc</a></em> expression format,
+for example, <tt>A + B</tt> or <tt>exp(A + B)</tt> are valid.
+The variables A, B, ..., F represent raster maps which are provided
+as options <b>a</b>, <b>b</b>, ..., <b>f</b>.
+
+<p>
+The result name, i.e. the output raster map, is provided using the
+option <b>output</b> and, unlike <em>r.mapcalc</em> it is not part
+of the expression.
+
+<p>
+This module is meant for convenience (for users and programmers) while
+the <em>r.mapcalc</em> module is a better choice for more complex
+expressions and advanced usage.
+
+
+<h2>NOTES</h2>
+
+Differences to <em>r.mapcalc</em> module:
+
<ul>
-<li>correct: <tt>A+B</tt></li>
-<li>incorrect: <tt>newfile = A+B</tt></li>
-<li>Use no spaces or blanks.</li>
+ <li>The input raster map names and the output map raster name are
+ separate from the expression (formula) which uses generic
+ variable names (A, B, C, ...).
+ <li>The output raster name is not included in the expression.
+ <li>The expression is expected to be a single short one liner
+ without the function <tt>eval()</tt>.
</ul>
-<p>
-The expert mode runs <em>r.mapcalc</em> for more complex expressions.
+Differences to <em>r.mapcalculator</em> module in GRASS GIS 5 and 6:
+<ul>
+ <li>The primary purpose is not being a GUI front end to
+ <em>r.mapcalc</em>, but a wrapper which allows easy building of
+ interfaces to <em>r.mapcalc</em> (including GUIs).
+ <li>Whitespace (most notably spaces) are allowed
+ (in the same way as for <em>r.mapcalc</em>).
+ <li>The variable names are case-insensitive to allow the original
+ uppercase as well as lowercase as in option names
+ (unless the <b>-c</b> flag is used).
+ <li>Option names for each map are just one letter (not amap, etc.).
+ <li>Output option name is <b>output</b> as for other modules
+ (not outfile).
+ <li>Raster map names can be optionally quoted (the <b>-q</b> flag).
+ <li>There is no expert mode
+ (which was just running <em>r.mapcalc</em>).
+</ul>
+
+
<h2>EXAMPLES</h2>
+
+<h3>Basic examples</h3>
+
<div class="code"><pre>
+r.mapcalculator expression="0" output=zeros
+r.mapcalculator expression="1" output=ones
+r.mapcalculator expression="2" output=twos
+</pre></div>
+
+<div class="code"><pre>
+r.mapcalculator expression="A + B + C" a=zeros b=ones, c=twos output=result1
+</pre></div>
+
+<div class="code"><pre>
+r.mapcalculator expression="(A * B) / 2 + 3 * C" a=zeros b=ones, c=twos output=result2
+</pre></div>
+
+
+<h3>Example expressions</h3>
+
+Addition:
+
+<div class="code"><pre>
+A + B
+</pre></div>
+
+No spaces around operators are not recommended for readability,
+but allowed in the expression:
+
+<div class="code"><pre>
A+B
</pre></div>
+More complex expression with a function:
+
<p>
<div class="code"><pre>
exp(A+C)+(B-2)*7
</pre></div>
+
<h2>SEE ALSO</h2>
-<em><a href="r.mapcalc.html">r.mapcalc</a></em>
+<em>
+<a href="r.mapcalc.html">r.mapcalc</a>,
+<a href="r3.mapcalc.html">r3.mapcalc</a>,
+<a href="t.rast.mapcalc.html">t.rast.mapcalc</a>,
+<a href="g.region.html">g.region</a>
+</em>
-<h2>AUTHOR</h2>
+<h2>AUTHORS</h2>
-R. Brunzema (r.brunzema at web.de)<br>
-Updated to GRASS 5.7 by Michael Barton, Arizona State University
+Vaclav Petras, <a href="https://geospatial.ncsu.edu/geoforall/">NCSU GeoForAll Lab</a><br>
+R. Brunzema (original 5.0 Bash version)<br>
+Michael Barton, Arizona State University (updated to GRASS 5.7)
<p><i>Last changed: $Date$</i>
Modified: sandbox/wenzeslaus/r.mapcalculator/r.mapcalculator.py
===================================================================
--- sandbox/wenzeslaus/r.mapcalculator/r.mapcalculator.py 2018-11-05 03:16:21 UTC (rev 73641)
+++ sandbox/wenzeslaus/r.mapcalculator/r.mapcalculator.py 2018-11-05 03:36:19 UTC (rev 73642)
@@ -1,203 +1,144 @@
-#!/bin/sh
-############################################################################
-#
-# MODULE: r.mapcalculator v.1.0 for GRASS 5.7 (2004/05/15)
-# based on mapcalculator.sh for GRASS 5
-# AUTHOR(S): R. Brunzema (r.brunzema at web.de);
-# updated to GRASS 5.7 by Michael Barton (michael.barton at asu.edu)
-# removed bashism by Huidae Cho (grass4u at gmail.com)
-# PURPOSE: Provides GUI front-end to r.mapcalc
-# COPYRIGHT: (C) 2004 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.
-#
-#############################################################################
+#!/usr/bin/env python
-#%Module
-#% description: Calculate new raster map from a r.mapcalc expression.
-#%End
+"""
+MODULE: r.mapcalculator
+
+AUTHOR(S): Vaclav Petras <wenzeslaus gmail com>
+ R. Brunzema <r.brunzema web de> (original 5.0 version)
+ Michael Barton <michael.barton asu edu> (update to GRASS 5.7)
+ Huidae Cho <grass4u gmail com> (removed bashism)
+
+PURPOSE: Provides wrapper friendly wrapper to r.mapcalc
+
+COPYRIGHT: (C) 2018 by Vaclav Petras and 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.
+"""
+
+#%module
+#% description: Calculate new raster map from a r.mapcalc expression
+#% keyword: raster
+#% keyword: algebra
+#%end
#%option
-#% key: amap
+#% key: expression
#% type: string
-#% gisprompt: old,cell,raster
+#% description: Formula (e.g. A-B or A*C+B)
+#% required : yes
+#%end
+#%option G_OPT_R_INPUT
+#% key: a
#% description: A
#% required : no
#%end
-#%option
-#% key: bmap
-#% type: string
-#% gisprompt: old,cell,raster
+#%option G_OPT_R_INPUT
+#% key: b
#% description: B
#% required : no
#%end
-#%option
-#% key: cmap
-#% type: string
-#% gisprompt: old,cell,raster
+#%option G_OPT_R_INPUT
+#% key: c
#% description: C
#% required : no
#%end
-#%option
-#% key: dmap
-#% type: string
-#% gisprompt: old,cell,raster
+#%option G_OPT_R_INPUT
+#% key: d
#% description: D
#% required : no
#%end
-#%option
-#% key: emap
-#% type: string
-#% gisprompt: old,cell,raster
+#%option G_OPT_R_INPUT
+#% key: e
#% description: E
#% required : no
#%end
-#%option
-#% key: fmap
-#% type: string
-#% gisprompt: old,cell,raster
+#%option G_OPT_R_INPUT
+#% key: f
#% description: F
#% required : no
#%end
#%option
-#% key: formula
-#% type: string
-#% description: Formula (e.g. A-B or A*C+B)
-#% required : yes
-#%end
-#%option
-#% key: outfile
-#% type: string
-#% gisprompt: new,cell,raster
+#% key: output
#% description: Name for output raster map
#% required : yes
#%end
#%option
-#% key: help
-#% type: string
-#% description: Show help
-#% options: -,help,man
-#% answer: -
-#% required : no
+#% key: seed
+#% type: integer
+#% required: no
+#% multiple: no
+#% description: Seed for rand() function
#%end
#%flag
-#% key: e
-#% description: Expert mode (enter a set of r.mapcalc expressions)
+#% key: s
+#% description: Generate random seed (result is non-deterministic)
#%end
#%flag
-#% key: o
-#% description: Do not overwrite existing map
+#% key: q
+#% description: Quote the map names
#%end
+#%flag
+#% key: c
+#% description: Case sensitive variable names
+#%end
+import sys
+import re
-display_help(){
- echo "" >&2
- echo "BRIEF HELP" >&2
- echo "" >&2
- echo "Enter an r.mapcalc expression in the" >&2
- echo "formula field using this format:" >&2
- echo "A+C or (more complex:) exp(A+C)+(B-2)*7" >&2
- echo "Where A, B, C are raster maps entered" >&2
- echo "in the A field, B field, and C field." >&2
- echo "" >&2
- echo "Do not enter output file in the formula field:" >&2
- echo "Correct: A+B" >&2
- echo "Incorrect: newfile = A+B" >&2
- echo "Use no blanks!" >&2
- echo "" >&2
- echo "For details on creating an r.mapcalc expression," >&2
- echo "select 'man' in the help field to see the r.mapcalc manual page" >&2
- echo "(or type g.manual r.mapcalc from the command line)." >&2
-}
+import grass.script as gs
-if [ -z "$GISBASE" ]
-then
- echo "You must be in GRASS GIS to run this program" >&2
- exit 1
-fi
-if [ "$1" != "@ARGS_PARSED@" ]
-then
- exec g.parser "$0" "$@"
-fi
+def name_quote(name):
+ return '"{}"'.format(name)
-case $GIS_OPT_HELP in
- help)
- display_help
- exit 0
- ;;
- man)
- g.manual r.mapcalc
- exit
- ;;
-esac
-# use old style mapcalc
+def main():
+ options, flags = gs.parser()
+ expr = options['expression']
+ if not expr:
+ gs.fatal(_("The expression is an empty string"))
+ output = options['output']
+ quote = flags['q']
+ re_flags = 0
+ if flags['c']:
+ re_flags = re.IGNORECASE
-if [ "$GIS_FLAG_E" = 1 ] ; then
- exec "$GISBASE/etc/grass-xterm-wrapper" -e r.mapcalc &
- exit
-fi
+ if quote:
+ output = name_quote(output)
+ seed = None
+ if options['seed']:
+ seed = options['seed']
+ elif flags['s']:
+ seed = 'auto'
-# Check for required arguments
-if [ -z "$GIS_OPT_FORMULA" ]; then
- g.message -e message='Missing formula!'
- g.message -e "Please enter a formula in the field formula"
- exit 1
-fi
+ variables = []
+ for key in "ABCDEF":
+ name = options[key.lower()]
+ if name:
+ if quote:
+ name = name_quote(name)
+ variables.append((key, name))
-if [ -z "$GIS_OPT_OUTFILE" ]; then
- g.message -e message='Missing name of outputfile!'
- g.message -e "Please enter a name for the resulting map and try again."
- exit 1
-elif [ "$GIS_FLAG_O" = 1 ]; then
- echo `g.list type=rast | grep -w "$GIS_OPT_OUTFILE" `
- outtest=`g.list type=rast | grep -w $GIS_OPT_OUTFILE`
- if [ -n "$outtest" ]; then
- g.message -e "File $GIS_OPT_OUTFILE exists. Exiting."
- exit 0
- fi
-fi
+ for key, name in variables:
+ find = r'([^a-zA-Z0-9]|^){key}([^a-zA-Z0-9]|$)'.format(key=key)
+ replace = r'\1{}\2'.format(name)
+ # we need to do the substitution twice because we are matching
+ # also the char before and after which fails when there is only
+ # one char between the two usages of the same var (e.g. A*A)
+ expr = re.sub(find, replace, expr, flags=re_flags)
+ expr = re.sub(find, replace, expr, flags=re_flags)
+ print("Expression ({find}, {replace}): {expr}".format(**locals()))
-# replace map names: two passes are needed to make sure that sed parses all map
-# names. e.g., A+B => amap+B => amap+bmap
-command=`
-echo "(${GIS_OPT_FORMULA})" | sed \
- -e "s/\([^a-zA-Z0-9]\)A\([^a-zA-Z0-9]\)/\1 \"$GIS_OPT_AMAP\" \2/g" \
- -e "s/\([^a-zA-Z0-9]\)A\([^a-zA-Z0-9]\)/\1 \"$GIS_OPT_AMAP\" \2/g" \
- -e "s/\([^a-zA-Z0-9]\)B\([^a-zA-Z0-9]\)/\1 \"$GIS_OPT_BMAP\" \2/g" \
- -e "s/\([^a-zA-Z0-9]\)B\([^a-zA-Z0-9]\)/\1 \"$GIS_OPT_BMAP\" \2/g" \
- -e "s/\([^a-zA-Z0-9]\)C\([^a-zA-Z0-9]\)/\1 \"$GIS_OPT_CMAP\" \2/g" \
- -e "s/\([^a-zA-Z0-9]\)C\([^a-zA-Z0-9]\)/\1 \"$GIS_OPT_CMAP\" \2/g" \
- -e "s/\([^a-zA-Z0-9]\)D\([^a-zA-Z0-9]\)/\1 \"$GIS_OPT_DMAP\" \2/g" \
- -e "s/\([^a-zA-Z0-9]\)D\([^a-zA-Z0-9]\)/\1 \"$GIS_OPT_DMAP\" \2/g" \
- -e "s/\([^a-zA-Z0-9]\)E\([^a-zA-Z0-9]\)/\1 \"$GIS_OPT_EMAP\" \2/g" \
- -e "s/\([^a-zA-Z0-9]\)E\([^a-zA-Z0-9]\)/\1 \"$GIS_OPT_EMAP\" \2/g" \
- -e "s/\([^a-zA-Z0-9]\)F\([^a-zA-Z0-9]\)/\1 \"$GIS_OPT_FMAP\" \2/g" \
- -e "s/\([^a-zA-Z0-9]\)F\([^a-zA-Z0-9]\)/\1 \"$GIS_OPT_FMAP\" \2/g"
-`
+ expr = '{lhs} = {rhs}'.format(lhs=output, rhs=expr)
+ gs.verbose(_("Expression: {}").format(expr))
+ gs.mapcalc(expr, seed=seed)
+ # g.message -e "Calculating $GIS_OPT_OUTFILE. Try expert mode."
-if [ -z "$GRASS_VERBOSE" ] ; then
- GRASS_VERBOSE=2 # default
-fi
+ return 0
-if [ "$GRASS_VERBOSE" -ge 1 ] ; then
- # Show the resulting commandline
- g.message message="r.mapcalc \"$GIS_OPT_OUTFILE\" = \"$command\""
-fi
-r.mapcalc "$GIS_OPT_OUTFILE" = "$command" # Start the command
+if __name__ == "__main__":
+ sys.exit(main())
-# Check for errors
-if [ $? -ne 0 ]; then
- g.message -e "Calculating $GIS_OPT_OUTFILE. Try expert mode."
- exit 1
-fi
-
-if [ "$GRASS_VERBOSE" -ge 2 ] ; then
- g.message "Done."
-fi
-
-exit 0
More information about the grass-commit
mailing list