[GRASS-SVN] r58039 - grass/trunk/lib/python/pygrass/modules/grid

svn_grass at osgeo.org svn_grass at osgeo.org
Fri Oct 18 01:40:16 PDT 2013


Author: zarch
Date: 2013-10-18 01:40:16 -0700 (Fri, 18 Oct 2013)
New Revision: 58039

Modified:
   grass/trunk/lib/python/pygrass/modules/grid/grid.py
Log:
Improving the isolation between processes and clean the code

Modified: grass/trunk/lib/python/pygrass/modules/grid/grid.py
===================================================================
--- grass/trunk/lib/python/pygrass/modules/grid/grid.py	2013-10-18 04:38:35 UTC (rev 58038)
+++ grass/trunk/lib/python/pygrass/modules/grid/grid.py	2013-10-18 08:40:16 UTC (rev 58039)
@@ -11,13 +11,13 @@
 
 from grass.script.setup import write_gisrc
 
-from grass.pygrass.gis import Mapset, Location, make_mapset
+from grass.pygrass.gis import Mapset, Location
 from grass.pygrass.gis.region import Region
 from grass.pygrass.modules import Module
 from grass.pygrass.functions import get_mapset_raster
 
-from split import split_region_tiles
-from patch import rpatch_map
+from grass.pygrass.modules.grid.split import split_region_tiles
+from grass.pygrass.modules.grid.patch import rpatch_map
 
 
 def select(parms, ptype):
@@ -37,12 +37,19 @@
         par = parms[k]
         if par.type == ptype or par.typedesc == ptype and par.value:
             if par.multiple:
-                for p in par.value:
-                    yield p
+                for val in par.value:
+                    yield val
             else:
                 yield par.value
 
 
+def copy_special_mapset_files(path_src, path_dst):
+    """Copy all the special GRASS files that are contained in
+    a mapset to another mapset."""
+    for fil in (fi for fi in os.listdir(path_src) if fi.isupper()):
+        sht.copy(os.path.join(path_src, fil), path_dst)
+
+
 def copy_mapset(mapset, path):
     """Copy mapset to another place without copying raster and vector data.
     """
@@ -54,133 +61,141 @@
         os.makedirs(per_new)
     if not os.path.isdir(map_new):
         os.mkdir(map_new)
-    for f in (fi for fi in os.listdir(per_old) if fi.isupper()):
-        sht.copy(os.path.join(per_old, f), per_new)
-    for f in (fi for fi in os.listdir(map_old) if fi.isupper()):
-        sht.copy(os.path.join(map_old, f), map_new)
+    copy_special_mapset_files(per_old, per_new)
+    copy_special_mapset_files(map_old, map_new)
     gisdbase, location = os.path.split(path)
     return Mapset(mapset.name, location, gisdbase)
 
 
-def copy_groups(groups, src, dst, gisrc_dst=None, region=None):
-    """Copy groupd from one mapset to another, crop the raster to the region.
+def read_gisrc(gisrc):
+    """Read a GISRC file and return a tuple with the mapset, location
+    and gisdbase.
     """
+    with open(gisrc, 'r') as gfile:
+        gis = dict([(k.strip(), v.strip())
+                    for k, v in [row.split(':') for row in gfile]])
+    return gis['MAPSET'], gis['LOCATION_NAME'], gis['GISDBASE']
+
+
+def get_mapset(gisrc_src, gisrc_dst):
+    """Get mapset from a GISRC source to a GISRC destination."""
+    msrc, lsrc, gsrc = read_gisrc(gisrc_src)
+    mdst, ldst, gdst = read_gisrc(gisrc_dst)
+    path_src = os.path.join(gsrc, lsrc, msrc)
+    path_dst = os.path.join(gdst, ldst, mdst)
+    if not os.path.isdir(path_dst):
+        os.makedirs(path_dst)
+        copy_special_mapset_files(path_src, path_dst)
+    src = Mapset(msrc, lsrc, gsrc)
+    dst = Mapset(mdst, ldst, gdst)
+    dst.visible.extend(src.visible)
+    return src, dst
+
+
+def copy_groups(groups, gisrc_src, gisrc_dst, region=None):
+    """Copy group from one mapset to another, crop the raster to the region.
+    """
     env = os.environ.copy()
-    # set region
-    if region:
-        region.set_current()
 
     # instantiate modules
     get_grp = Module('i.group', flags='lg', stdout_=sub.PIPE, run_=False)
     set_grp = Module('i.group')
     get_grp.run_ = True
 
-    # get and set GISRC
-    gisrc_src = env['GISRC']
-    gisrc_dst = gisrc_dst if gisrc_dst else write_gisrc(dst.gisdbase,
-                                                        dst.location,
-                                                        dst.name)
-
     for grp in groups:
         # change gisdbase to src
         env['GISRC'] = gisrc_src
         get_grp(group=grp, env_=env)
         rasts = get_grp.outputs.stdout.split()
+        copy_rasters(rasts, gisrc_src, gisrc_dst, region=region)
         # change gisdbase to dst
         env['GISRC'] = gisrc_dst
-        set_grp(group=grp, input=rasts, env_=env)
-    return gisrc_src, gisrc_dst
+        set_grp(group=grp,
+                input=[r.split('@')[0] if '@' in r else r for r in rasts],
+                env_=env)
 
 
-def copy_rasters(rasters, src, dst, gisrc_dst=None, region=None):
+def set_region(region, gisrc_src, gisrc_dst, env):
+    """Set a region into two different mapsets."""
+    reg_str = "g.region n=%(north)r s=%(south)r " \
+              "e=%(east)r w=%(west)r " \
+              "nsres=%(nsres)r ewres=%(ewres)r"
+    reg_cmd = reg_str % dict(region.items())
+    env['GISRC'] = gisrc_src
+    sub.Popen(reg_cmd, shell=True, env=env)
+    env['GISRC'] = gisrc_dst
+    sub.Popen(reg_cmd, shell=True, env=env)
+
+
+def copy_rasters(rasters, gisrc_src, gisrc_dst, region=None):
     """Copy rasters from one mapset to another, crop the raster to the region.
     """
     env = os.environ.copy()
-    # set region
     if region:
-        region.set_current()
+        set_region(region, gisrc_src, gisrc_dst, env)
 
-    nam = "copy%d__%s" % (id(dst), '%s')
-    expr = "%s=%s"
+    path_dst = os.path.join(*read_gisrc(gisrc_dst))
+    nam = "copy%d__%s" % (id(gisrc_dst), '%s')
 
     # instantiate modules
     mpclc = Module('r.mapcalc')
     rpck = Module('r.pack')
     rupck = Module('r.unpack')
-    rm = Module('g.remove')
+    remove = Module('g.remove')
 
-    # get and set GISRC
-    gisrc_src = env['GISRC']
-    gisrc_dst = gisrc_dst if gisrc_dst else write_gisrc(dst.gisdbase,
-                                                        dst.location,
-                                                        dst.name)
-
-    pdst = dst.path()
     for rast in rasters:
+        rast_clean = rast.split('@')[0] if '@' in rast else rast
         # change gisdbase to src
         env['GISRC'] = gisrc_src
-        name = nam % rast
-        mpclc(expression=expr % (name, rast), overwrite=True, env_=env)
-        file_dst = "%s.pack" % os.path.join(pdst, name)
+        name = nam % rast_clean
+        mpclc(expression="%s=%s" % (name, rast), overwrite=True, env_=env)
+        file_dst = "%s.pack" % os.path.join(path_dst, name)
         rpck(input=name, output=file_dst, overwrite=True, env_=env)
-        rm(rast=name, env_=env)
+        remove(rast=name, env_=env)
         # change gisdbase to dst
         env['GISRC'] = gisrc_dst
-        rupck(input=file_dst, output=rast, overwrite=True, env_=env)
+        rupck(input=file_dst, output=rast_clean, overwrite=True, env_=env)
         os.remove(file_dst)
-    return gisrc_src, gisrc_dst
 
 
-def copy_vectors(vectors, src, dst, gisrc_dst=None, region=None):
+def copy_vectors(vectors, gisrc_src, gisrc_dst):
     """Copy vectors from one mapset to another, crop the raster to the region.
     """
     env = os.environ.copy()
-    # set region
-    if region:
-        region.set_current()
+    path_dst = os.path.join(*read_gisrc(gisrc_dst))
+    nam = "copy%d__%s" % (id(gisrc_dst), '%s')
 
-    nam = "copy%d__%s" % (id(dst), '%s')
-
     # instantiate modules
     vpck = Module('v.pack')
     vupck = Module('v.unpack')
-    rm = Module('g.remove')
+    remove = Module('g.remove')
 
-    # get and set GISRC
-    gisrc_src = env['GISRC']
-    gisrc_dst = gisrc_dst if gisrc_dst else write_gisrc(dst.gisdbase,
-                                                        dst.location,
-                                                        dst.name)
-
-    pdst = dst.path()
     for vect in vectors:
         # change gisdbase to src
         env['GISRC'] = gisrc_src
         name = nam % vect
-        file_dst = "%s.pack" % os.path.join(pdst, name)
+        file_dst = "%s.pack" % os.path.join(path_dst, name)
         vpck(input=name, output=file_dst, overwrite=True, env_=env)
-        rm(vect=name, env_=env)
+        remove(vect=name, env_=env)
         # change gisdbase to dst
         env['GISRC'] = gisrc_dst
         vupck(input=file_dst, output=vect, overwrite=True, env_=env)
         os.remove(file_dst)
-    return gisrc_src, gisrc_dst
 
 
 def get_cmd(cmdd):
-    """Transforma a cmd dictionary to a list of parameters"""
+    """Transform a cmd dictionary to a list of parameters"""
     cmd = [cmdd['name'], ]
     cmd.extend(("%s=%s" % (k, v) for k, v in cmdd['inputs']
                 if not isinstance(v, list)))
     cmd.extend(("%s=%s" % (k, ','.join(vals if isinstance(vals[0], str)
-                                       else map(repr, vals)))
+                                       else [repr(v) for v in vals]))
                 for k, vals in cmdd['inputs']
                 if isinstance(vals, list)))
     cmd.extend(("%s=%s" % (k, v) for k, v in cmdd['outputs']
                 if not isinstance(v, list)))
-    cmd.extend(("%s=%s" % (k, ','.join(map(repr, vals)))
-                for k, vals in cmdd['outputs']
-                if isinstance(vals, list)))
+    cmd.extend(("%s=%s" % (k, ','.join([repr(v) for v in vals]))
+                for k, vals in cmdd['outputs'] if isinstance(vals, list)))
     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
@@ -188,16 +203,10 @@
 
 def cmd_exe(args):
     """Create a mapset, and execute a cmd inside."""
-    bbox, mapnames, msetname, cmd, groups = args
-    mset = Mapset()
-    try:
-        make_mapset(msetname)
-    except:
-        pass
-    ms = Mapset(msetname)
-    ms.visible.extend(mset.visible)
+    bbox, mapnames, gisrc_src, gisrc_dst, cmd, groups = args
+    get_mapset(gisrc_src, gisrc_dst)
     env = os.environ.copy()
-    env['GISRC'] = write_gisrc(mset.gisdbase, mset.location, msetname)
+    env['GISRC'] = gisrc_dst
     if mapnames:
         inputs = dict(cmd['inputs'])
         # reset the inputs to
@@ -207,17 +216,16 @@
         # set the region to the tile
         sub.Popen(['g,region', 'rast=%s' % key], env=env).wait()
     else:
-        #reg = Region() nsres=reg.nsres, ewres=reg.ewres,
         # set the computational region
         lcmd = ['g.region', ]
         lcmd.extend(["%s=%s" % (k, v) for k, v in bbox.iteritems()])
         sub.Popen(lcmd, env=env).wait()
     if groups:
-        src, dst = copy_groups(groups, mset, ms, env['GISRC'])
+        copy_groups(groups, gisrc_src, gisrc_dst)
     # run the grass command
     sub.Popen(get_cmd(cmd), env=env).wait()
     # remove temp GISRC
-    os.remove(env['GISRC'])
+    os.remove(gisrc_dst)
 
 
 class GridModule(object):
@@ -270,20 +278,26 @@
         self.start_row = start_row
         self.start_col = start_col
         self.out_prefix = out_prefix
-        self.n_mset = None
-        self.gisrc_src = self.gisrc_dst = None
         self.log = log
         self.move = move
+        self.gisrc_src = os.environ['GISRC']
+        self.n_mset, self.gisrc_dst = None, None
         if self.move:
             self.n_mset = copy_mapset(self.mset, self.move)
-            rasters = select(self.module.inputs, 'raster')
-            self.gisrc_src, self.gisrc_dst = copy_rasters(rasters,
-                                                          self.mset,
-                                                          self.n_mset,
-                                                          region=self.region)
-            vectors = select(self.module.inputs, 'vector')
-            copy_vectors(vectors, self.mset, self.n_mset,
-                         gisrc_dst=self.gisrc_dst, region=self.region)
+            self.gisrc_dst = write_gisrc(self.n_mset.gisdbase,
+                                         self.n_mset.location,
+                                         self.n_mset.name)
+            rasters = [r for r in select(self.module.inputs, 'raster')]
+            if rasters:
+                copy_rasters(rasters, self.gisrc_src, self.gisrc_dst,
+                             region=self.region)
+            vectors = [v for v in select(self.module.inputs, 'vector')]
+            if vectors:
+                copy_vectors(vectors, self.gisrc_src, self.gisrc_dst)
+            groups = [g for g in select(self.module.inputs, 'group')]
+            if groups:
+                copy_groups(groups, self.gisrc_src, self.gisrc_dst,
+                            region=self.region)
 
         self.bboxes = split_region_tiles(region=region,
                                          width=width, height=height,
@@ -294,6 +308,11 @@
             self.split()
         self.debug = debug
 
+    def __del__(self):
+        if self.gisrc_dst:
+            # remove GISRC file
+            os.remove(self.gisrc_dst)
+
     def clean_location(self, location=None):
         """Remove all created mapsets."""
         location = location if location else Location()
@@ -318,6 +337,10 @@
         """Return a list of tuble with the parameters for cmd_exe function"""
         works = []
         reg = Region()
+        if self.move:
+            mdst, ldst, gdst = read_gisrc(self.gisrc_dst)
+        else:
+            ldst, gdst = self.mset.location, self.mset.gisdbase
         cmd = self.module.get_dict()
         groups = [g for g in select(self.module.inputs, 'group')]
         for row, box_row in enumerate(self.bboxes):
@@ -334,17 +357,20 @@
                 bbox = dict([(k[0], str(v)) for k, v in box.items()[:-2]])
                 bbox['nsres'] = '%f' % reg.nsres
                 bbox['ewres'] = '%f' % reg.ewres
+                new_mset = self.msetstr % (self.start_row + row,
+                                           self.start_col + col),
                 works.append((bbox, inms,
-                              self.msetstr % (self.start_row + row,
-                                              self.start_col + col),
+                              self.gisrc_src,
+                              write_gisrc(gdst, ldst, new_mset),
                               cmd, groups))
         return works
 
     def define_mapset_inputs(self):
+        """Add the mapset information to the input maps
+        """
         for inmap in self.module.inputs:
             inm = self.module.inputs[inmap]
-            # (inm.type == 'raster' or inm.typedesc == 'group') and inm.value:
-            if inm.type == 'raster' and inm.value:
+            if inm.type in ('raster', 'vector') and inm.value:
                 if '@' not in inm.value:
                     mset = get_mapset_raster(inm.value)
                     inm.value = inm.value + '@%s' % mset
@@ -363,18 +389,20 @@
             if not result.successful():
                 raise RuntimeError
 
-        self.mset.current()
-
         if patch:
-            self.patch()
+            if self.move:
+                os.environ['GISRC'] = self.gisrc_dst
+                self.n_mset.current()
+                self.patch()
+                os.environ['GISRC'] = self.gisrc_src
+                self.mset.current()
+                # copy the outputs from dst => src
+                routputs = [self.out_prefix + o
+                            for o in select(self.module.outputs, 'raster')]
+                copy_rasters(routputs, self.gisrc_dst, self.gisrc_src)
+            else:
+                self.patch()
 
-        if self.n_mset is not None:
-            # move the raster outputs to the original mapset
-            routputs = [self.out_prefix + o
-                        for o in select(self.module.outputs, 'raster')]
-            copy_rasters(routputs, self.n_mset, self.mset,
-                         self.gisrc_src, self.region)
-
         if self.log:
             # record in the temp directory
             from grass.lib.gis import G_tempfile
@@ -386,12 +414,11 @@
                     dirpath = os.path.join(tmpdir, par.name)
                     if not os.path.isdir(dirpath):
                         os.makedirs(dirpath)
-                    fp = open(os.path.join(dirpath,
-                                           self.out_prefix + par.value), 'w+')
-                    fp.close()
+                    fil = open(os.path.join(dirpath,
+                                            self.out_prefix + par.value), 'w+')
+                    fil.close()
 
         if clean:
-            self.mset.current()
             self.clean_location()
             self.rm_tiles()
             if self.n_mset:
@@ -405,7 +432,6 @@
 
     def patch(self):
         """Patch the final results."""
-        # patch all the outputs
         bboxes = split_region_tiles(width=self.width, height=self.height)
         for otmap in self.module.outputs:
             otm = self.module.outputs[otmap]



More information about the grass-commit mailing list