[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