Bladeren bron

r3.to.rast: test and doc for multiply, add and type options

git-svn-id: https://svn.osgeo.org/grass/grass/trunk@70132 15284696-431f-4ddb-bdfa-cd5b030d7da7
Vaclav Petras 8 jaren geleden
bovenliggende
commit
236388fbe2
2 gewijzigde bestanden met toevoegingen van 199 en 0 verwijderingen
  1. 39 0
      raster3d/r3.to.rast/r3.to.rast.html
  2. 160 0
      raster3d/r3.to.rast/testsuite/test_integer_rounding.py

+ 39 - 0
raster3d/r3.to.rast/r3.to.rast.html

@@ -15,13 +15,51 @@ The user can force <em>r3.to.rast</em> to use the 2D resolution of the input
 </table>
 </table>
 </center>
 </center>
 
 
+<h3>Map type conversions</h3>
+
+Type of resulting 2D raster maps is determined by the type of the
+input 3D raster, i.e. 3D raster of type DCELL (double) will result in
+DCELL 2D rasters. A specific type for 2D rasters can be requested using
+the <b>type</b> option.
+
+<p>
+The <b>type</b> option is especially advantageous when the 3D raster
+map stores categories (which need to be stored as floating point numbers)
+and the 2D raster map should be also categorical, i.e. use integers.
+The type is set to <tt>CELL</tt> in this case. 
+
+
+<h3>Modifying the values</h3>
+
+The values in the 3D raster map can be modified prior to storing in
+the 2D raster map. The values can be scaled using the option <b>multiply</b>
+and a constant value can be added using the option <b>add</b>.
+The new value is computed using the following equation:
+
+<pre>
+y = ax + b
+</pre>
+
+where <em>x</em> is the original value, <em>a</em> is the value of
+<b>multiply</b> option, <em>b</em> is the value of <b>add</b> option,
+and <em>y</em> is the new value. When <b>multiply</b> is not provided,
+the value of <em>a</em> is 1. When <b>add</b> is not provided, the value
+of <em>b</em> is 0.
+
+
 <h2>NOTES</h2>
 <h2>NOTES</h2>
+
 Every slice of the 3D raster map is copied to one 2D raster map. The maps
 Every slice of the 3D raster map is copied to one 2D raster map. The maps
 are named like <b>output</b><em>_slicenumber</em>. Slices are counted from bottom
 are named like <b>output</b><em>_slicenumber</em>. Slices are counted from bottom
 to the top, so the bottom slice has number 1. 
 to the top, so the bottom slice has number 1. 
 
 
+<p>
 The number of slices is equal to the number of depths.
 The number of slices is equal to the number of depths.
 
 
+<p>
+To round floating point values to integers when using <tt>type=CELL</tt>,
+the <b>add</b> option should be set to 0.5.
+
 <h2>SEE ALSO</h2>
 <h2>SEE ALSO</h2>
 
 
 <em>
 <em>
@@ -33,5 +71,6 @@ The number of slices is equal to the number of depths.
 
 
 <h2>AUTHOR</h2>
 <h2>AUTHOR</h2>
 S&ouml;ren Gebbert
 S&ouml;ren Gebbert
+Vaclav Petras, <a href="http://geospatial.ncsu.edu/osgeorel/">NCSU GeoForAll Lab</a>
 
 
 <p><i>Last changed: $Date$</i>
 <p><i>Last changed: $Date$</i>

+ 160 - 0
raster3d/r3.to.rast/testsuite/test_integer_rounding.py

@@ -0,0 +1,160 @@
+#!/usr/bin/env python
+
+############################################################################
+#
+# MODULE:        test_integer_rounding
+# AUTHOR:        Vaclav Petras
+# PURPOSE:       Fast test of rounding integers based on a small example
+# COPYRIGHT:     (C) 2016 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.
+#
+#############################################################################
+
+from grass.gunittest.case import TestCase
+from grass.gunittest.main import test
+from grass.script import list_strings
+
+# generated by
+# g.region n=12 s=9 e=21 w=18 t=8 b=4 res=1 res3=1 -p3
+# r3.mapcalc "x = rand(0,5.)" seed=100 && r3.out.ascii x prec=2
+INPUT = """\
+version: grass7
+order: nsbt
+north: 12.000000
+south: 9.000000
+east: 21.000000
+west: 18.000000
+top: 8.000000
+bottom: 4.000000
+rows: 3
+cols: 3
+levels: 4
+1.26 1.04 4.70
+2.11 1.98 1.91
+1.16 2.68 2.67
+4.31 4.81 1.58
+3.68 3.27 0.25
+2.27 4.03 3.28
+4.06 4.15 0.40
+1.02 3.40 3.26
+4.88 0.43 1.02
+1.16 0.07 0.78
+0.07 3.52 0.45
+2.86 4.79 1.43
+"""
+
+# created from the above and template from
+# r.mapcalc "x = rand(0,10)" seed=100 && r.out.ascii x prec=0
+OUTPUTS = [
+"""\
+north: 12
+south: 9
+east: 21
+west: 18
+rows: 3
+cols: 3
+1 1 5
+2 2 2
+1 3 3
+""",
+"""\
+north: 12
+south: 9
+east: 21
+west: 18
+rows: 3
+cols: 3
+4 5 2
+4 3 0
+2 4 3
+""",
+"""\
+north: 12
+south: 9
+east: 21
+west: 18
+rows: 3
+cols: 3
+4 4 0
+1 3 3
+5 0 1
+""",
+"""\
+north: 12
+south: 9
+east: 21
+west: 18
+rows: 3
+cols: 3
+1 0 1
+0 4 0
+3 5 1
+""",
+]
+
+
+class TestR3ToRastIntegerRounding(TestCase):
+    # TODO: replace by unified handing of maps
+    # mixing class and object attributes
+    to_remove_3d = []
+    to_remove_2d = []
+    rast3d = 'r3_to_rast_test_int_round'
+    rast2d = 'r3_to_rast_test_int_round'
+    rast2d_ref = 'r3_to_rast_test_int_round_ref'
+    rast2d_refs = []
+
+    def setUp(self):
+        self.use_temp_region()
+        self.runModule('r3.in.ascii', input='-', stdin_=INPUT,
+                       output=self.rast3d)
+        self.to_remove_3d.append(self.rast3d)
+        self.runModule('g.region', raster_3d=self.rast3d)
+
+        for i, data in enumerate(OUTPUTS):
+            rast = "%s_%d" % (self.rast2d_ref, i)
+            self.runModule('r.in.ascii', input='-', stdin_=data,
+                           output=rast, type='CELL')
+            self.to_remove_2d.append(rast)
+            self.rast2d_refs.append(rast)
+
+    def tearDown(self):
+        if self.to_remove_3d:
+            self.runModule('g.remove', flags='f', type='raster_3d',
+                           name=','.join(self.to_remove_3d), verbose=True)
+        if self.to_remove_2d:
+            self.runModule('g.remove', flags='f', type='raster',
+                           name=','.join(self.to_remove_2d), verbose=True)
+        self.del_temp_region()
+
+    def test_rounding(self):
+        self.assertModule('r3.to.rast', input=self.rast3d,
+                          output=self.rast2d, type='CELL', add=0.5)
+        rasts = list_strings('raster', mapset=".",
+                             pattern="%s_*" % self.rast2d,
+                             exclude="%s_*" % self.rast2d_ref)
+        self.assertEquals(len(rasts), 4,
+                          msg="Wrong number of 2D rasters present"
+                              " in the mapset")
+        ref_info = dict(cells=9)
+        ref_univar = dict(cells=9, null_cells=0)
+        for rast in rasts:
+            self.assertRasterExists(rast)
+            # the following doesn't make much sense because we just listed them
+            self.to_remove_2d.append(rast)
+            self.assertRasterFitsInfo(raster=rast, reference=ref_info,
+                                      precision=0)
+            self.assertRasterFitsUnivar(raster=rast, reference=ref_univar,
+                                        precision=0)
+
+        # check the actual values
+        for rast_ref, rast in zip(self.rast2d_refs, rasts):
+            self.assertRastersNoDifference(actual=rast,
+                                           reference=rast_ref,
+                                           precision=0.1)
+
+
+if __name__ == '__main__':
+    test()