[GRASS-SVN] r66645 - grass-addons/grass7/raster/r.category.trim

svn_grass at osgeo.org svn_grass at osgeo.org
Wed Oct 28 10:41:22 PDT 2015


Author: pvanbosgeo
Date: 2015-10-28 10:41:22 -0700 (Wed, 28 Oct 2015)
New Revision: 66645

Added:
   grass-addons/grass7/raster/r.category.trim/Makefile
   grass-addons/grass7/raster/r.category.trim/r.category.trim.html
   grass-addons/grass7/raster/r.category.trim/r.category.trim.py
Log:
addon to trim categories and colours of non-existing categories and optionally to export the category colors and labels as qgis color map text file

Added: grass-addons/grass7/raster/r.category.trim/Makefile
===================================================================
--- grass-addons/grass7/raster/r.category.trim/Makefile	                        (rev 0)
+++ grass-addons/grass7/raster/r.category.trim/Makefile	2015-10-28 17:41:22 UTC (rev 66645)
@@ -0,0 +1,7 @@
+MODULE_TOPDIR = ../..
+
+PGM = r.category.trim
+
+include $(MODULE_TOPDIR)/include/Make/Script.make
+
+default: script


Property changes on: grass-addons/grass7/raster/r.category.trim/Makefile
___________________________________________________________________
Added: svn:eol-style
   + native

Added: grass-addons/grass7/raster/r.category.trim/r.category.trim.html
===================================================================
--- grass-addons/grass7/raster/r.category.trim/r.category.trim.html	                        (rev 0)
+++ grass-addons/grass7/raster/r.category.trim/r.category.trim.html	2015-10-28 17:41:22 UTC (rev 66645)
@@ -0,0 +1,65 @@
+<h2>DESCRIPTION</h2>
+
+<p>In GRASS you can 'cut out' a subset of a larger raster layer by 
+setting the extent to something smaller then the extent of the 
+original map using g.region and/or by setting a mask using r.mask, 
+after which you simply run r.mapcalc "newmap = oldmap".
+
+<p>You may have noticed that when creating the new map, all category 
+category labels and colour table of the original map are copied over 
+to the new map, even for category values that are not in the new 
+map. If you are working with categorical maps, this may not be what 
+you want. See <a href=
+"https://pvanb.wordpress.com/2015/09/22/categorical-maps-and-legends/"
+>here</a> for a more detailed discussion.
+
+<p>With this addon you can trim the category and colour tables so it 
+only contains category labels and colour definitions for the values 
+present in the new map. You can do this on the input map, or do this 
+on a copy of the map.
+
+<p>If you prefer the map to have consecutive values (i.e., without 
+gaps), there is the option to change the category values to a 
+consecutive series by setting the n-flag. For example, if the map 
+has the following categories values and labels (after the redundant 
+category labels have been removed):
+
+<div class="code"><pre>2 label2
+5 label5
+9 label9
+</pre></div>
+
+<p>Then the new recoded layer will have the category values and labels:
+
+<div class="code"><pre>1 label2
+2 label5
+3 label9
+</pre></div>
+
+<p>Although it is possible to <a href= 
+"https://pvanb.wordpress.com/2015/10/18/the-qgis-grass-plugin-is-back/
+">open GRASS GIS raster layers directly in QGIS</a>, the legend in 
+QGIS will show the right colours, but not the category labels. The 
+addon let's you export the categories, category labels and colours 
+as QGIS colour map file. This is just a simple text file with the 
+raster categories and corresponding colour definitions and category 
+labels. QGIS can use this to set the colour and labels for a raster 
+layer. See <a href="https://pvanb.wordpress.com/?p=3650">this 
+blogpost</a> for more details how to use the colour map file in 
+QGIS. Alternatively, you can also export the categories and category 
+labels in a normal csv file.
+
+
+<h2>NOTE</h2>
+The file is only useful for categorical maps. Therefore only integer maps are accepted as input.
+    
+<h2>SEE ALSO</h2>
+
+<a href="https://pvanb.wordpress.com/?p=3650">GRASS GIS categorical raster layers in QGIS </a></em>
+<a href="https://pvanb.wordpress.com/2015/09/22/categorical-maps-and-legends/">GRASS GIS categorical maps and legends</a></em>
+
+<h2>AUTHOR</h2>
+
+Paulo van Breugel, paulo at ecodiv.org
+
+<p><em>Last changed: $Date$</em>


Property changes on: grass-addons/grass7/raster/r.category.trim/r.category.trim.html
___________________________________________________________________
Added: svn:eol-style
   + native

Added: grass-addons/grass7/raster/r.category.trim/r.category.trim.py
===================================================================
--- grass-addons/grass7/raster/r.category.trim/r.category.trim.py	                        (rev 0)
+++ grass-addons/grass7/raster/r.category.trim/r.category.trim.py	2015-10-28 17:41:22 UTC (rev 66645)
@@ -0,0 +1,229 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+########################################################################
+#
+# MODULE:       r.category.clean
+# AUTHOR(S):    Paulo van Breugel
+# DESCRIPTION:  Trim a cut out raster layer by removing non-existing categories
+#               and their color defintions. Optionally, a new map can be
+#               created to ensure consecutive categories values, but retaining
+#               the category labels and colors.
+#               The user can opt to export the categories, category labels and
+#               color codes (RGB) as csv file or as a QGIS color map file. The
+#               latter can be used in QGIS to define the colors and category
+#               labels of the raster.
+#
+# COPYRIGHT: (C) 2015 Paulo van Breugel
+#            http://ecodiv.org
+#            http://pvanb.wordpress.com/
+#
+#            This program is free software under the GNU General Public
+#            License (>=v2). Read the file COPYING that comes with GRASS
+#            for details.
+#
+########################################################################
+#
+#%Module
+#% description: Removing non-existing categories and their color defintions
+#% keyword: raster
+#% keyword: color
+#% keyword: category
+#% keyword: raster
+#%End
+
+#%option
+#% key: input
+#% type: string
+#% gisprompt: old,cell,raster
+#% description: input map
+#% key_desc: name
+#% required: yes
+#% multiple: no
+#% guisection: Raster
+#%end
+
+#%option
+#% key: output
+#% type: string
+#% gisprompt: new,cell,raster
+#% description: output map
+#% key_desc: name
+#% required: no
+#% multiple: no
+#% guisection: Raster
+#%end
+
+#%option G_OPT_F_OUTPUT
+#% key:csv
+#% description: Attribute table (csv format)
+#% key_desc: name
+#% required: no
+#% guisection: Export
+#%end
+
+#%option G_OPT_F_OUTPUT
+#% key:qgis
+#% description: QGIS color file (txt format)
+#% key_desc: name
+#% required: no
+#% guisection: Export
+#%end
+
+#%flag:
+#% key: n
+#% description: Recode layer to get consecutive category values
+#%end
+
+#%rules
+#% requires_all: -n, output
+#%end
+
+#----------------------------------------------------------------------------
+#Test
+#----------------------------------------------------------------------------
+#options = {"input":"test", "output":"test3", "csv":"test.csv", "qgis":"qgiscolor.txt"}
+#flags = {"n":True}
+
+#=======================================================================
+## General
+#=======================================================================
+
+# import libraries
+import os
+import sys
+from subprocess import PIPE
+from grass.pygrass.modules import Module
+import grass.script as grass
+
+# Check if running in GRASS
+if not os.environ.has_key("GISBASE"):
+    grass.message("You must be in GRASS GIS to run this program.")
+    sys.exit(1)
+
+# main function
+def main():
+
+    # Input
+    IP = options['input']
+    OP = options['output']
+    CSV = options['csv']
+    QGIS = options['qgis']
+    flags_n = flags['n']
+
+    # Check if raster is integer
+    iscell = grass.raster.raster_info(IP)["datatype"]
+    if iscell != u'CELL':
+        grass.error('Input should be an integer raster layer')
+
+    # Get category values that are actually in the map, and their category
+    # labels
+    CATV = Module('r.category', map=IP, stdout_=PIPE).outputs.stdout
+    RCAT = CATV.split('\n')
+    RCAT = filter(None,RCAT)
+    RID = [z.split('\t')[0] for z in RCAT]
+    RIDI = map(int, RID)
+
+    # Get list of all colors in the color table (i.e., this includes
+    # colors defined for categories that are not in the map
+    RCOL = grass.read_command("r.colors.out", map=IP).split('\n')
+    RCOL = [ x for x in RCOL if "nv" not in x and 'default' not in x]
+    RCOL = filter(None, RCOL)
+    CCAT = [z.split(' ')[0] for z in RCOL]
+    CCAT = map(int, CCAT)
+    CR = ""
+    CV = []
+
+    # If attribute values should be recoded to consecutive numbers
+    if flags_n:
+        RIDN = range(1, len(RID) + 1)
+        RECO = ""
+        CL = ""
+        RLAB = [z.split('\t')[1] for z in RCAT] # Category labels
+        for j in xrange(len(RID)):
+            RECO = RECO + RID[j] + ":" + RID[j] + ":" + str(RIDN[j]) + "\n"
+            A = map(int, [i for i, x in enumerate(CCAT) if x == RIDI[j]])
+            CV.append(RCOL[A[0]].split(' ')[1])
+            CR = CR + str(RIDN[j]) + " " + CV[j] + "\n"
+            CL = CL + str(RIDN[j]) + "|" + RLAB[j] + "\n"
+
+        CR = CR + 'nv 255:255:255\ndefault 255:255:255\n'
+        Module("r.recode", input=IP, output=OP, rules="-", stdin_=RECO, quiet=True)
+        Module("r.colors", map=OP, rules="-", stdin_=CR, quiet=True)
+        Module("r.category", map=OP, rules="-", stdin_=CL, quiet=True, separator="pipe")
+    else:
+        # Check if new layer should be created
+        if len(OP) > 0:
+            k = IP + "," + OP
+            grass.run_command("g.copy", raster=k)
+        else:
+            OP = IP
+
+        # Remove redundant categories
+        Module('r.category', map=OP, rules="-", stdin_=CATV, quiet=True)
+
+        # Write color rules and assign colors
+        for j in xrange(len(RIDI)):
+            A = map(int, [i for i, x in enumerate(CCAT) if x == RIDI[j]])
+            CV.append(RCOL[A[0]].split(' ')[1])
+            CR = CR + str(RIDI[j]) + " " + CV[j] + "\n"
+        CR = CR + 'nv 255:255:255\ndefault 255:255:255\n'
+        Module("r.colors", map=OP, rules="-", stdin_=CR, quiet=True)
+
+    # If attribute table (csv format) should be written
+    if len(CSV) > 0:
+        if flags_n:
+            RCAT1 = CL.split('\n'); RCAT1 = filter(None,RCAT1)
+            RCAT1 = [w.replace('|', ',') for w in RCAT1]
+        else:
+            RCAT1 = [w.replace('\t', ',') for w in RCAT]
+        RCAT1.insert(0, "CATEGORY,CATEGORY LABEL")
+        CV1 = CV; CV1.insert(0,"RGB")
+        text_file = open(CSV, "w")
+        for k in xrange(len(RCAT1)):
+            text_file.write(RCAT1[k] + "," + CV1[k] + "\n")
+        text_file.close()
+
+    # If QGIS Color Map text files should be written
+    if len(QGIS) > 0:
+        RGB = [w.replace(':', ',') for w in CV]
+        if flags_n:
+            RCAT = CL.split('\n'); RCAT = filter(None,RCAT)
+            RCAT = [w.replace('|', ',') for w in RCAT]
+        else:
+            RCAT = [w.replace('\t', ',') for w in RCAT]
+        text_file = open(QGIS, "w")
+        text_file.write("# QGIS color map for " + OP + " raster, generated by r.category.trim\n")
+        text_file.write("INTERPOLATION:EXACT\n")
+        for k in xrange(len(RCAT)):
+            RC2 = RCAT[k].split(',')
+            text_file.write(RC2[0] + "," + RGB[k] + ",255," + RC2[1] + "\n")
+        text_file.close()
+
+if __name__ == "__main__":
+    options, flags = grass.parser()
+    sys.exit(main())
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


Property changes on: grass-addons/grass7/raster/r.category.trim/r.category.trim.py
___________________________________________________________________
Added: svn:executable
   + *
Added: svn:eol-style
   + native



More information about the grass-commit mailing list