[GRASS-SVN] r72661 - grass-addons/grass7/raster/r.tri

svn_grass at osgeo.org svn_grass at osgeo.org
Tue May 1 22:19:17 PDT 2018


Author: spawley
Date: 2018-05-01 22:19:17 -0700 (Tue, 01 May 2018)
New Revision: 72661

Modified:
   grass-addons/grass7/raster/r.tri/r.tri.py
Log:
r.tri deal with null values as part of mapcalc expression

Modified: grass-addons/grass7/raster/r.tri/r.tri.py
===================================================================
--- grass-addons/grass7/raster/r.tri/r.tri.py	2018-05-02 04:24:16 UTC (rev 72660)
+++ grass-addons/grass7/raster/r.tri/r.tri.py	2018-05-02 05:19:17 UTC (rev 72661)
@@ -38,22 +38,19 @@
 #%end
 
 #%flag
-#% key: p
-#% label: Cell padding
-#% description: Use cell padding to reduce edge effect
-#% guisection: Optional
+#% key: c
+#% description: Use circular neighborhood
 #%end
 
-
+from grass.pygrass.modules.shortcuts import general as g
+from grass.pygrass.modules.shortcuts import raster as r
+from grass.pygrass.gis.region import Region
+from grass.pygrass.raster import RasterRow
 import sys
 import atexit
 import random
 import string
 import grass.script as gs
-from grass.pygrass.modules.shortcuts import general as g
-from grass.pygrass.modules.shortcuts import raster as r
-from grass.pygrass.gis.region import Region
-from grass.pygrass.raster import RasterRow
 
 TMP_RAST = []
 
@@ -73,60 +70,78 @@
     return (tmp)
 
 
+def focal_expr(radius, window_square=False):
+    """Returns array offsets relative to centre pixel (0,0) for a matrix of
+    size radius
+
+    Args
+    ----
+    radius : int
+        Radius of the focal function
+    window_square : bool. Optional (default is False)
+        Boolean to use a circular or square window
+
+    Returns
+    -------
+    offsets : list
+        List of pixel positions (row, col) relative to the center pixel
+        ( 1, -1)  ( 1, 0)  ( 1, 1)
+        ( 0, -1)  ( 0, 0)  ( 0, 1)
+        (-1, -1)  (-1, 0)  (-1, 1)"""
+
+    offsets = []
+
+    # generate a list of spatial neighbourhood offsets for the chosen radius
+    # ignoring the centre cell
+    if window_square:
+        
+        for i in range(-radius, radius+1):
+            for j in range(-radius, radius+1):
+                if (i,j) != (0,0):
+                    offsets.append((i, j))
+    
+    else:
+
+        for i in range(-radius, radius+1):
+            for j in range(-radius, radius+1):
+                row = i + radius
+                col = j + radius
+
+                if pow(row - radius, 2) + pow(col - radius, 2) <= \
+                    pow(radius, 2) and (i, j) != (0,0):
+                    offsets.append((j, i))
+
+    return offsets
+
+
 def main():
     dem = options['input']
     tri = options['output']
     size = int(options['size'])
-    p = flags['p']
+    circular = flags['c']
 
     radius = (size-1)/2
-    ncells = size**2
 
-    # store current region settings
-    current_reg = Region()
-
-    if p:
-        # check for existing mask
-        if RasterRow('MASK').exist():
-            gs.fatal('Cell padding option cannot be used with existing mask...please remove first')
-
-        # grow the map to remove border effects
-        gs.message('Growing DEM to avoid edge effects...')
-        dem_grown = temp_map('tmp_elevation_grown')
-        g.region(n=current_reg.north + (current_reg.nsres * (radius+2)),
-                 s=current_reg.south - (current_reg.nsres * (radius+2)),
-                 w=current_reg.west - (current_reg.ewres * (radius+2)),
-                 e=current_reg.east + (current_reg.ewres * (radius+2)))
-        r.grow(input=dem, output=dem_grown, radius=radius+2, quiet=True)
-        dem = dem_grown
-
     # calculate TRI based on map calc statements
     gs.message("Calculating the Topographic Ruggedness Index...")
 
-    # generate a list of spatial neighbourhood indexs for the chosen radius
+    # generate a list of spatial neighbourhood offsets for the chosen radius
     # ignoring the center cell
-    offsets = []
-    for j in range(-radius, radius+1):
-        for i in range(-radius, radius+1):
-            if (j,i) != (0,0):
-                offsets.append((j,i))
+    offsets = focal_expr(radius = radius, window_square=not circular)
+    terms = []
+    for d in offsets:
+        valid = ','.join(map(str, d))        
+        invalid = ','.join([str(-d[0]), str(-d[1])])
+        terms.append(
+            "if(isnull({dem}[{d}]), if(isnull({dem}[{e}]), (median({dem})-{dem})^2, ({dem}[{e}]-{dem}^2)), ({dem}[{d}]-{dem})^2)".format(
+            dem=dem, d=valid, e=invalid))
 
-    # define the calculation term
-    terms = ["($dem - $dem[%d,%d])^2" % d for d in offsets]
-
     # define the calculation expression
+    ncells = len(offsets)+1
     expr = "$tri = sqrt((%s" % " + ".join(terms) + ") / $ncells)"
 
     # perform the r.mapcalc calculation with the moving window
-    if p:
-        output_tmp = temp_map('tmp')
-        gs.mapcalc(expr, tri=output_tmp, dem=dem, ncells=ncells)
-        r.mask(raster=options['input'], quiet=True)
-        r.mapcalc('{x}={y}'.format(x=tri, y=output_tmp))
-        r.mask(flags='r', quiet=True)
-        Region.write(current_reg)
-    else:
-        gs.mapcalc(expr, tri=tri, dem=dem, ncells=ncells)
+    gs.mapcalc(expr, tri=tri, dem=dem, ncells=ncells)
 
     return 0
 



More information about the grass-commit mailing list