[GRASS-SVN] r55605 - in grass/trunk/lib/python/pygrass/modules: . grid

svn_grass at osgeo.org svn_grass at osgeo.org
Wed Apr 3 03:57:50 PDT 2013


Author: zarch
Date: 2013-04-03 03:57:50 -0700 (Wed, 03 Apr 2013)
New Revision: 55605

Added:
   grass/trunk/lib/python/pygrass/modules/grid/
   grass/trunk/lib/python/pygrass/modules/grid/Makefile
   grass/trunk/lib/python/pygrass/modules/grid/__init__.py
   grass/trunk/lib/python/pygrass/modules/grid/grid.py
   grass/trunk/lib/python/pygrass/modules/grid/patch.py
   grass/trunk/lib/python/pygrass/modules/grid/split.py
Modified:
   grass/trunk/lib/python/pygrass/modules/Makefile
   grass/trunk/lib/python/pygrass/modules/__init__.py
Log:
Add the new GridModule class

Modified: grass/trunk/lib/python/pygrass/modules/Makefile
===================================================================
--- grass/trunk/lib/python/pygrass/modules/Makefile	2013-04-03 10:53:55 UTC (rev 55604)
+++ grass/trunk/lib/python/pygrass/modules/Makefile	2013-04-03 10:57:50 UTC (rev 55605)
@@ -11,7 +11,7 @@
 
 MODULES = shortcuts
 
-CLEAN_SUBDIRS = interface
+CLEAN_SUBDIRS = interface grid
 
 PYFILES := $(patsubst %,$(DSTDIR)/%.py,$(MODULES) __init__)
 PYCFILES := $(patsubst %,$(DSTDIR)/%.pyc,$(MODULES) __init__)

Modified: grass/trunk/lib/python/pygrass/modules/__init__.py
===================================================================
--- grass/trunk/lib/python/pygrass/modules/__init__.py	2013-04-03 10:53:55 UTC (rev 55604)
+++ grass/trunk/lib/python/pygrass/modules/__init__.py	2013-04-03 10:57:50 UTC (rev 55605)
@@ -8,7 +8,7 @@
 import interface
 from interface import Module
 
-#import grid
-#from grid.grid import GridModule
+import grid
+from grid.grid import GridModule
 
 import shortcuts

Added: grass/trunk/lib/python/pygrass/modules/grid/Makefile
===================================================================
--- grass/trunk/lib/python/pygrass/modules/grid/Makefile	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/modules/grid/Makefile	2013-04-03 10:57:50 UTC (rev 55605)
@@ -0,0 +1,32 @@
+MODULE_TOPDIR = ../../../../..
+
+include $(MODULE_TOPDIR)/include/Make/Other.make
+include $(MODULE_TOPDIR)/include/Make/Python.make
+include $(MODULE_TOPDIR)/include/Make/Doxygen.make
+
+PYDIR = $(ETC)/python
+GDIR = $(PYDIR)/grass
+PGDIR = $(GDIR)/pygrass
+DSTDIR= $(PGDIR)/modules/grid
+
+MODULES = split patch grid
+
+PYFILES := $(patsubst %,$(DSTDIR)/%.py,$(MODULES) __init__)
+PYCFILES := $(patsubst %,$(DSTDIR)/%.pyc,$(MODULES) __init__)
+
+default: $(PYFILES) $(PYCFILES) $(GDIR)/__init__.py $(GDIR)/__init__.pyc
+
+$(PYDIR):
+	$(MKDIR) $@
+
+$(GDIR): | $(PYDIR)
+	$(MKDIR) $@
+
+$(DSTDIR): | $(GDIR)
+	$(MKDIR) $@
+
+$(DSTDIR)/%: % | $(DSTDIR)
+	$(INSTALL_DATA) $< $@
+
+#doxygen:
+DOXNAME = pythonpygrass
\ No newline at end of file

Added: grass/trunk/lib/python/pygrass/modules/grid/__init__.py
===================================================================
--- grass/trunk/lib/python/pygrass/modules/grid/__init__.py	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/modules/grid/__init__.py	2013-04-03 10:57:50 UTC (rev 55605)
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Wed Apr  3 10:41:30 2013
+
+ at author: pietro
+"""
+import split
+import patch
+import grid
+from grid import GridModule
\ No newline at end of file

Added: grass/trunk/lib/python/pygrass/modules/grid/grid.py
===================================================================
--- grass/trunk/lib/python/pygrass/modules/grid/grid.py	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/modules/grid/grid.py	2013-04-03 10:57:50 UTC (rev 55605)
@@ -0,0 +1,182 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Thu Mar 28 11:06:00 2013
+
+ at author: pietro
+"""
+import os
+import multiprocessing as mltp
+import subprocess as sub
+
+from grass.script.setup import write_gisrc
+
+from grass.pygrass.gis import Mapset, Location, make_mapset
+from grass.pygrass.modules import Module
+
+from split import split_region_tiles
+from patch import patch_map
+
+
+_GREG = Module('g.region')
+
+
+def get_cmd(cmdd):
+    """Transforma a cmd dictionary to a list of parameters"""
+    cmd = [cmdd['name'], ]
+    cmd.extend(("%s=%s" % (k, v) for k, v in cmdd['inputs']))
+    cmd.extend(("%s=%s" % (k, v) for k, v in cmdd['outputs']))
+    cmd.extend(("%s" % (flg) for flg in cmdd['flags'] if len(flg) == 1))
+    cmd.extend(("--%s" % (flg[0]) for flg in cmdd['flags'] if len(flg) > 1))
+    return cmd
+
+
+def cmd_exe((bbox, mapnames, msetname, cmd)):
+    """Create a mapset, and execute a cmd inside."""
+    mset = Mapset()
+    try:
+        make_mapset(msetname)
+    except:
+        pass
+    env = os.environ.copy()
+    env['GISRC'] = write_gisrc(mset.gisdbase, mset.location, msetname)
+    if mapnames:
+        inputs = dict(cmd['inputs'])
+        # reset the inputs to
+        for key in mapnames:
+            inputs[key] = mapnames[key]
+        cmd['inputs'] = inputs.items()
+        # set the region to the tile
+        _GREG(env_=env, rast=key)
+    else:
+        # set the computational region
+        _GREG(env_=env, **bbox)
+    # run the grass command
+    sub.Popen(get_cmd(cmd), env=env).wait()
+
+
+class GridModule(object):
+    """Run GRASS raster commands in a multiproccessing mode.
+
+    Parameters
+    -----------
+
+    cmd: raster GRASS command
+        Only command staring with r.* are valid.
+    width: integer
+        Width of the tile, in pixel.
+    height: integer
+        Height of the tile, in pixel.
+    overlap: integer
+        Overlap between tiles, in pixel.
+    nthreads: number of threads
+        Default value is equal to the number of processor available.
+    split: boolean
+        If True use r.tile to split all the inputs.
+    run_: boolean
+        If False only instantiate the object.
+    args and kargs: cmd parameters
+        Give all the parameters to the command.
+
+    Examples
+    --------
+
+    ::
+
+        >>> grd = GridModule('r.slope.aspect',
+        ...                  width=500, height=500, overlap=2,
+        ...                  processes=None, split=True,
+        ...                  elevation='elevation',
+        ...                  slope='slope', aspect='aspect', overwrite=True)
+        >>> grd.run()
+    """
+    def __init__(self, cmd, width=None, height=None, overlap=0, processes=None,
+                 split=False, *args, **kargs):
+        kargs['run_'] = False
+        self.mset = Mapset()
+        self.module = Module(cmd, *args, **kargs)
+        self.width = width
+        self.height = height
+        self.overlap = overlap
+        self.processes = processes
+        self.bboxes = split_region_tiles(width=width, height=height,
+                                         overlap=overlap)
+        self.msetstr = cmd.replace('.', '') + "_%03d_%03d"
+        self.inlist = None
+        if split:
+            self.split()
+
+    def clean_location(self):
+        """Remove all created mapsets."""
+        mapsets = Location().mapsets(self.msetstr.split('_')[0] + '_*')
+        for mset in mapsets:
+            Mapset(mset).delete()
+
+    def split(self):
+        """Split all the raster inputs using r.tile"""
+        rtile = Module('r.tile')
+        inlist = {}
+        #import pdb; pdb.set_trace()
+        for inmap in self.module.inputs:
+            inm = self.module.inputs[inmap]
+            if inm.type == 'raster' and inm.value:
+                rtile(input=inm.value, output=inm.value,
+                      width=self.width, height=self.height,
+                      overlap=self.overlap)
+                patt = '%s-*' % inm.value
+                inlist[inm.value] = sorted(self.mset.glist(type='rast',
+                                                           pattern=patt))
+        self.inlist = inlist
+
+    def get_works(self):
+        """Return a list of tuble with the parameters for cmd_exe function"""
+        works = []
+        cmd = self.module.get_dict()
+        for row, box_row in enumerate(self.bboxes):
+            for col, box in enumerate(box_row):
+                inms = None
+                if self.inlist:
+                    inms = {}
+                    cols = len(box_row)
+                    for key in self.inlist:
+                        indx = row * cols + col
+                        inms[key] = "%s@%s" % (self.inlist[key][indx],
+                                               self.mset.name)
+                # set the computational region, prepare the region parameters
+                bbox = dict([(k[0], str(v)) for k, v in box.items()[:-2]])
+                works.append((bbox, inms, self.msetstr % (row, col), cmd))
+        return works
+
+    def run(self, patch=True, clean=True):
+        """Run the GRASS command."""
+        self.module.flags.overwrite = True
+        pool = mltp.Pool(processes=self.processes)
+        result = pool.map_async(cmd_exe, self.get_works())
+        result.wait()
+        if not result.successful():
+            raise RuntimeError
+
+        if patch:
+            self.patch()
+
+        if clean:
+            self.clean_location()
+            self.rm_tiles()
+
+    def patch(self):
+        """Patch the final results."""
+        # patch all the outputs
+        for otmap in self.module.outputs:
+            otm = self.module.outputs[otmap]
+            if otm.type == 'raster' and otm.value:
+                patch_map(otm.value, self.mset.name, self.msetstr,
+                          split_region_tiles(width=self.width,
+                                             height=self.height),
+                          self.module.flags.overwrite)
+
+    def rm_tiles(self):
+        """Remove all the tiles."""
+        # if split, remove tiles
+        if self.inlist:
+            grm = Module('g.remove')
+            for key in self.inlist:
+                grm(rast=self.inlist[key])

Added: grass/trunk/lib/python/pygrass/modules/grid/patch.py
===================================================================
--- grass/trunk/lib/python/pygrass/modules/grid/patch.py	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/modules/grid/patch.py	2013-04-03 10:57:50 UTC (rev 55605)
@@ -0,0 +1,60 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Tue Apr  2 18:57:42 2013
+
+ at author: pietro
+"""
+from grass.pygrass.gis.region import Region
+from grass.pygrass.raster import RasterRow
+from grass.pygrass.functions import coor2pixel
+
+
+def get_start_end_index(bbox_list):
+    """Convert a Bounding Box to a list of the index of
+    column start, end, row start and end
+    """
+    ss_list = []
+    reg = Region()
+    for bbox in bbox_list:
+        r_start, c_start = coor2pixel((bbox.west, bbox.north), reg)
+        r_end, c_end = coor2pixel((bbox.east, bbox.south), reg)
+        ss_list.append((int(r_start), int(r_end), int(c_start), int(c_end)))
+    return ss_list
+
+
+def patch_row(rast, rasts, bboxes):
+    """Patch a row of bound boxes."""
+    sei = get_start_end_index(bboxes)
+    # instantiate two buffer
+    buff = rasts[0][0]
+    rbuff = rasts[0][0]
+    r_start, r_end, c_start, c_end = sei[0]
+    for row in xrange(r_start, r_end):
+        for col, ras in enumerate(rasts):
+            r_start, r_end, c_start, c_end = sei[col]
+            buff = ras.get_row(row, buff)
+            rbuff[c_start:c_end] = buff[c_start:c_end]
+        rast.put_row(rbuff)
+
+
+def patch_map(raster, mapset, mset_str, bbox_list, overwrite=False):
+    """Patch raster using a bounding box list to trim the raster."""
+    # Instantiate the RasterRow input objects
+    rast = RasterRow(raster, mapset)
+    rtype = RasterRow(name=raster, mapset=mset_str % (0, 0))
+    rtype.open('r')
+    rast.open('w', mtype=rtype.mtype, overwrite=overwrite)
+    rtype.close()
+    rasts = []
+    for row, rbbox in enumerate(bbox_list):
+        rrasts = []
+        for col in range(len(rbbox)):
+            rrasts.append(RasterRow(name=raster, mapset=mset_str % (row, col)))
+            rrasts[-1].open('r')
+        rasts.append(rrasts)
+        patch_row(rast, rrasts, rbbox)
+
+    for rrast in rasts:
+        for rast_ in rrast:
+            rast_.close()
+    rast.close()

Added: grass/trunk/lib/python/pygrass/modules/grid/split.py
===================================================================
--- grass/trunk/lib/python/pygrass/modules/grid/split.py	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/modules/grid/split.py	2013-04-03 10:57:50 UTC (rev 55605)
@@ -0,0 +1,55 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Tue Apr  2 19:00:15 2013
+
+ at author: pietro
+"""
+from grass.pygrass.gis.region import Region
+from grass.pygrass.vector.basic import Bbox
+
+
+def get_bbox(reg, row, col, width, height, overlap):
+    """Return a Bbox"""
+    north = reg.north - (row * height - overlap) * reg.nsres
+    south = reg.north - ((row + 1) * height + overlap) * reg.nsres
+    east = reg.west + ((col + 1) * width + overlap) * reg.ewres
+    west = reg.west + (col * width - overlap) * reg.ewres
+    return Bbox(north=north if north <= reg.north else reg.north,
+                south=south if south >= reg.south else reg.south,
+                east=east if east <= reg.east else reg.east,
+                west=west if west >= reg.west else reg.west,)
+
+
+def split_region_tiles(region=None, width=100, height=100, overlap=0):
+    """Spit a region into a list of Bbox. ::
+
+        >>> reg = Region()
+        >>> reg.north = 1350
+        >>> reg.south = 0
+        >>> reg.nsres = 1
+        >>> reg.east = 1500
+        >>> reg.west = 0
+        >>> reg.ewres = 1
+        >>> reg.cols
+        1500
+        >>> reg.rows
+        1350
+        >>> split_region_tiles(region=reg, width=1000, height=700, overlap=0)
+        [[Bbox(1350.0, 650.0, 1000.0, 0.0), Bbox(1350.0, 650.0, 1500.0, 1000.0)],
+         [Bbox(650.0, 0.0, 1000.0, 0.0), Bbox(650.0, 0.0, 1500.0, 1000.0)]]
+        >>> split_region_tiles(region=reg, width=1000, height=700, overlap=10)
+        [[Bbox(1350.0, 640.0, 1010.0, 0.0), Bbox(1350.0, 640.0, 1500.0, 990.0)],
+         [Bbox(660.0, 0.0, 1010.0, 0.0), Bbox(660.0, 0.0, 1500.0, 990.0)]]
+    """
+    reg = region if region else Region()
+    ncols = (reg.cols + width - 1) // width
+    nrows = (reg.rows + height - 1) // height
+    box_list = []
+    #print reg
+    for row in xrange(nrows):
+        row_list = []
+        for col in xrange(ncols):
+            #print 'c', c, 'r', r
+            row_list.append(get_bbox(reg, row, col, width, height, overlap))
+        box_list.append(row_list)
+    return box_list



More information about the grass-commit mailing list