[GRASS-SVN] r65357 - in grass-addons/grass7/raster: . r.sample.category r.sample.category/testsuite

svn_grass at osgeo.org svn_grass at osgeo.org
Wed Jun 3 08:46:33 PDT 2015


Author: wenzeslaus
Date: 2015-06-03 08:46:33 -0700 (Wed, 03 Jun 2015)
New Revision: 65357

Added:
   grass-addons/grass7/raster/r.sample.category/
   grass-addons/grass7/raster/r.sample.category/Makefile
   grass-addons/grass7/raster/r.sample.category/r.sample.category.html
   grass-addons/grass7/raster/r.sample.category/r.sample.category.png
   grass-addons/grass7/raster/r.sample.category/r.sample.category.py
   grass-addons/grass7/raster/r.sample.category/testsuite/
   grass-addons/grass7/raster/r.sample.category/testsuite/test_numbers.sh
Log:
r.sample.category: create points per category in raster map

Basic implementation works and is tested (Bash test included) but there is a lot of to improve (see TODOs in code and documentation).

Documentation contains example and picture but description and use cases are missing.

Code goes through 'pep8 file.py' and 'pylint -r n file.py' in an acceptable way.


Added: grass-addons/grass7/raster/r.sample.category/Makefile
===================================================================
--- grass-addons/grass7/raster/r.sample.category/Makefile	                        (rev 0)
+++ grass-addons/grass7/raster/r.sample.category/Makefile	2015-06-03 15:46:33 UTC (rev 65357)
@@ -0,0 +1,7 @@
+MODULE_TOPDIR = ../..
+
+PGM=r.sample.category
+
+include $(MODULE_TOPDIR)/include/Make/Script.make
+
+default: script

Added: grass-addons/grass7/raster/r.sample.category/r.sample.category.html
===================================================================
--- grass-addons/grass7/raster/r.sample.category/r.sample.category.html	                        (rev 0)
+++ grass-addons/grass7/raster/r.sample.category/r.sample.category.html	2015-06-03 15:46:33 UTC (rev 65357)
@@ -0,0 +1,76 @@
+<h2>DESCRIPTION</h2>
+
+<p>
+<em>r.sample.category</em> generates points at random locations.
+Each category (class) in a raster map will contain specified number
+of random points.
+
+
+<h2>NOTES</h2>
+
+Mask (<em><a href="r.mask.html">r.mask</a></em>) to create points in areas
+with each category, thus mask cannot be active when the module is used.
+
+
+<h2>EXAMPLE</h2>
+
+Generate three points at random location for each category (class)
+in the raster map:
+
+<div class="code"><pre>
+r.sample.category input=landclass96 output=landclass_points npoints=3
+</pre></div>
+
+Show the result:
+
+<div class="code"><pre>
+d.rast map=landclass96
+d.vect map=landclass_points icon=basic/circle fill_color=aqua color=blue size=10
+</pre></div>
+
+<!--
+export GRASS_RENDER_IMMEDIATE=cairo
+export GRASS_RENDER_FILE=r.sample.category.png
+export GRASS_RENDER_WIDTH=800
+export GRASS_RENDER_HEIGHT=800
+export GRASS_RENDER_FILE_READ=TRUE
+d.rast map=landclass96
+d.vect map=landclass_points icon=basic/circle fill_color=aqua color=blue size=10
+mogrify -trim r.sample.category.png
+optipng -o9 r.sample.category.png
+-->
+
+<p>
+<center>
+<img src="r.sample.category.png"><br>
+Figure: Three random points in each category of landclass raster map
+</center>
+
+<h2>KNOWN ISSUES</h2>
+
+The module does not respect mask. More precisely it does not allow mask
+to be active when it is started because it sets the mask by itself
+for its own purposes. The mask is removed at the end of execution
+but all other modules executed in parallel with this module (such
+as rendering maps in GUI) will be influenced by the mask set
+by this module.
+
+
+<h2>SEE ALSO</h2>
+
+<em>
+<a href="v.sample.html">v.sample</a>,
+<a href="r.random.html">r.random</a>,
+<a href="r.random.cells.html">r.random.cells</a>,
+<a href="v.random.html">v.random</a>,
+<a href="v.what.rast.html">v.what.rast</a>
+</em>
+
+
+<h2>AUTHORS</h2>
+<p>
+Vaclav Petras, <a href="http://gis.ncsu.edu/osgeorel/">NCSU OSGeoREL</a>,<br>
+Anna Petrasova, <a href="http://gis.ncsu.edu/osgeorel/">NCSU OSGeoREL</a>
+</p>
+
+<p><i>Last changed: $Date: 2013-12-19 17:46:26 -0500 (Thu, 19 Dec 2013) $</i>

Added: grass-addons/grass7/raster/r.sample.category/r.sample.category.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/raster/r.sample.category/r.sample.category.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: grass-addons/grass7/raster/r.sample.category/r.sample.category.py
===================================================================
--- grass-addons/grass7/raster/r.sample.category/r.sample.category.py	                        (rev 0)
+++ grass-addons/grass7/raster/r.sample.category/r.sample.category.py	2015-06-03 15:46:33 UTC (rev 65357)
@@ -0,0 +1,139 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+##############################################################################
+#
+# MODULE:     r.sample.category
+# AUTHOR(S):  Vaclav Petras <wenzeslaus gmail com>
+#             Anna Petrasova <kratochanna gmail com>
+# PURPOSE:    Sample points from each category
+# COPYRIGHT:  (C) 2015 by Vaclav Petras, and the GRASS Development Team
+#
+#             This program is free software under the GNU General Public
+#             License (>=v2). Read the COPYING file that comes with GRASS
+#             for details.
+#
+##############################################################################
+
+
+#%module
+#% description: Create sampling points from each category in a raster map
+#% keyword: raster
+#% keyword: sampling
+#% keyword: random
+#% keyword: points
+#% keyword: vector
+#%end
+#%option G_OPT_R_INPUT
+#% description: Name of input raster map with categories (classes)
+#%end
+#%option G_OPT_V_OUTPUT
+#% description: Name of output vector map with points at random locations
+#%end
+#%option G_OPT_R_INPUTS
+#% description: Names of input raster maps to be sampled
+#% key: sampled
+#% required: no
+#%end
+#%option
+#% description: Number of sampling points per category in the input map
+#% key: npoints
+#% required: yes
+#% type: integer
+#%end
+
+# TODO: Python tests for more advanced things such as overwrite or attributes
+# TODO: only optional sampling of the category raster
+# TODO: preserver original raster categories as vector point categories
+# TODO: ensure/check minimum number of points in each category
+# TODO: specify number of points and distribute them uniformly
+# TODO: specify number of points and distribute them according to histogram
+# TODO: ensure/check minimum and maximum number of of points when doing histogram
+# TODO: be less verbose
+# TODO: create function to check for mask
+# TODO: move escape and mask functions to library
+
+import os
+import atexit
+
+import grass.script as gscript
+
+
+TMP = []
+
+
+def cleanup():
+    if gscript.find_file(name='MASK', element='cell', mapset=gscript.gisenv()['MAPSET'])['name']:
+        gscript.run_command('r.mask', flags='r')
+    if TMP:
+        gscript.run_command('g.remove', flags='f', type=['raster', 'vector'], name=TMP)
+
+
+def escape_sql_column(name):
+    name = name.replace('.', '_')
+    return name
+
+
+def main():
+    options, flags = gscript.parser()
+
+    input_raster = options['input']
+    points = options['output']
+    if options['sampled']:
+        sampled_rasters = options['sampled'].split(',')
+    else:
+        sampled_rasters = []
+    npoints_0 = int(options['npoints'])
+
+    if gscript.find_file(name='MASK', element='cell', mapset=gscript.gisenv()['MAPSET'])['name']:
+        gscript.fatal(_("MASK is active. Please remove it before proceeding."))
+
+    # we clean up mask too, so register after we know that mask is not present
+    atexit.register(cleanup)
+
+    temp_name = 'tmp_r_sample_category_{}_'.format(os.getpid())
+    points_nocats = temp_name + 'points_nocats'
+    TMP.append(points_nocats)
+
+    # input must be CELL
+    rdescribe = gscript.read_command('r.describe', map=input_raster, flags='d1')
+    categories = []
+    for line in rdescribe.splitlines():
+        try:
+            categories.append(int(line))
+        except ValueError:
+            pass
+
+    vectors = []
+    for cat in categories:
+        # change mask to sample zeroes and then change again to sample ones
+        # overwrite mask for an easy loop
+        gscript.run_command('r.mask', raster=input_raster, maskcats=cat, overwrite=True)
+        vector = temp_name + str(cat)
+        vectors.append(vector)
+        gscript.run_command('r.random', input=input_raster, npoints=npoints_0, vector=vector)
+        TMP.append(vector)
+
+    gscript.run_command('r.mask', flags='r')
+
+    gscript.run_command('v.patch', input=vectors, output=points)
+    # remove and add gain cats so that they are unique
+    gscript.run_command('v.category', input=points, option='del', cat=-1, output=points_nocats)
+    # overwrite to reuse the map
+    gscript.run_command('v.category', input=points_nocats, option='add', output=points, overwrite=True)
+
+    columns = []
+    column_names = []
+    sampled_rasters.insert(0, input_raster)
+    for predictor in sampled_rasters:
+        column = escape_sql_column(predictor.lower())
+        column_names.append(column)
+        # TODO: column type according to map type
+        columns.append("{column} double precision".format(column=column))
+    gscript.run_command('v.db.addtable', map=points, columns=','.join(columns))
+    for raster, column in zip(sampled_rasters, column_names):
+        gscript.run_command('v.what.rast', map=points, type='point', raster=raster, column=column)
+
+
+if __name__ == '__main__':
+    main()

Added: grass-addons/grass7/raster/r.sample.category/testsuite/test_numbers.sh
===================================================================
--- grass-addons/grass7/raster/r.sample.category/testsuite/test_numbers.sh	                        (rev 0)
+++ grass-addons/grass7/raster/r.sample.category/testsuite/test_numbers.sh	2015-06-03 15:46:33 UTC (rev 65357)
@@ -0,0 +1,20 @@
+#!/usr/bin/env sh
+
+num_points_expected=42
+num_cats_expected=7
+
+r.sample.category input=landclass96 output=landclass_points npoints=6
+
+num_points=$(v.db.select -c landclass_points | wc -l)
+
+if [ $num_points -ne $num_points_expected ]; then
+    >&2 echo "number of points ($num_points) != requested points per category times number of categories ($num_points_expected)"
+    exit 1
+fi
+
+num_cats=$(v.db.select -c landclass_points | sed "s/.*|//g" | uniq | wc -l)
+
+if [ $num_cats -ne $num_cats_expected ]; then
+    >&2 echo "number of sampled categories ($num_cats) != number of categories in raster ($num_cats_expected)"
+    exit 1
+fi


Property changes on: grass-addons/grass7/raster/r.sample.category/testsuite/test_numbers.sh
___________________________________________________________________
Added: svn:executable
   + *



More information about the grass-commit mailing list