Browse Source

pygrass: sync relbr7 with trunk

git-svn-id: https://svn.osgeo.org/grass/grass/branches/releasebranch_7_0@63613 15284696-431f-4ddb-bdfa-cd5b030d7da7
Pietro Zambelli 10 years ago
parent
commit
5354c28aab

+ 10 - 10
lib/python/pygrass/gis/__init__.py

@@ -15,11 +15,11 @@ libgis.G_gisinit('')
 from grass.pygrass.errors import GrassError
 from grass.pygrass.errors import GrassError
 
 
 
 
-ETYPE = {'rast': libgis.G_ELEMENT_RASTER,
-         'rast3d': libgis.G_ELEMENT_RASTER3D,
-         'vect': libgis.G_ELEMENT_VECTOR,
-         'oldvect': libgis.G_ELEMENT_OLDVECTOR,
-         'asciivect': libgis.G_ELEMENT_ASCIIVECTOR,
+ETYPE = {'raster': libgis.G_ELEMENT_RASTER,
+         'raster_3d': libgis.G_ELEMENT_RASTER3D,
+         'vector': libgis.G_ELEMENT_VECTOR,
+         'oldvector': libgis.G_ELEMENT_OLDVECTOR,
+         'asciivector': libgis.G_ELEMENT_ASCIIVECTOR,
          'icon': libgis.G_ELEMENT_ICON,
          'icon': libgis.G_ELEMENT_ICON,
          'labels': libgis.G_ELEMENT_LABEL,
          'labels': libgis.G_ELEMENT_LABEL,
          'sites': libgis.G_ELEMENT_SITE,
          'sites': libgis.G_ELEMENT_SITE,
@@ -309,17 +309,17 @@ class Mapset(object):
     def glist(self, type, pattern=None):
     def glist(self, type, pattern=None):
         """Return a list of grass types like:
         """Return a list of grass types like:
 
 
-            * 'asciivect',
+            * 'asciivector',
             * 'group',
             * 'group',
             * 'icon',
             * 'icon',
             * 'labels',
             * 'labels',
-            * 'oldvect',
-            * 'rast',
-            * 'rast3d',
+            * 'oldvector',
+            * 'raster',
+            * 'raster_3d',
             * 'region',
             * 'region',
             * 'region3d',
             * 'region3d',
             * 'sites',
             * 'sites',
-            * 'vect',
+            * 'vector',
             * 'view3d'
             * 'view3d'
 
 
         :param type: the type of element to query
         :param type: the type of element to query

+ 0 - 4
lib/python/pygrass/messages/__init__.py

@@ -81,10 +81,6 @@ def message_server(lock, conn):
         if isinstance(message,  type(" ")):
         if isinstance(message,  type(" ")):
             if len(message) >= 2000:
             if len(message) >= 2000:
                 message = message[:1999]
                 message = message[:1999]
-        # libgis limitation
-        if isinstance(message,  type(" ")):
-            if len(message) >= 2000:
-                message = message[:1999]
 
 
         if message_type == "PERCENT":
         if message_type == "PERCENT":
             n = int(data[1])
             n = int(data[1])

+ 2 - 1
lib/python/pygrass/modules/interface/module.py

@@ -697,7 +697,7 @@ class Module(object):
                 args.append(str(self.flags[flg]))
                 args.append(str(self.flags[flg]))
         return args
         return args
 
 
-    @mdebug(1, extra=_get_bash)
+    # @mdebug(1, extra=_get_bash)
     def run(self):
     def run(self):
         """Run the module
         """Run the module
 
 
@@ -711,6 +711,7 @@ class Module(object):
         termination. The handling of stdout and stderr must then be done
         termination. The handling of stdout and stderr must then be done
         outside of this function.
         outside of this function.
         """
         """
+        get_msgr().debug(1, self.get_bash())
         if self.inputs['stdin'].value:
         if self.inputs['stdin'].value:
             self.stdin = self.inputs['stdin'].value
             self.stdin = self.inputs['stdin'].value
             self.stdin_ = PIPE
             self.stdin_ = PIPE

+ 0 - 211
lib/python/pygrass/raster/__init__.py

@@ -457,217 +457,6 @@ class RasterSegment(RasterAbstractBase):
         self._fd = None
         self._fd = None
 
 
 
 
-FLAGS = {1: {'b': 'i', 'i': 'i', 'u': 'i'},
-         2: {'b': 'i', 'i': 'i', 'u': 'i'},
-         4: {'f': 'f', 'i': 'i', 'b': 'i', 'u': 'i'},
-         8: {'f': 'd'}, }
-
-
-class RasterNumpy(np.memmap, RasterAbstractBase):
-    """Raster_cached_narray": Inherits "Raster_abstract_base" and
-    "numpy.memmap". Its purpose is to allow numpy narray like access to
-    raster maps without loading the map into the main memory.
-
-    * Behaves like a numpy array and supports all kind of mathematical
-      operations: __add__, ...
-    * Overrides the open and close methods
-    * Be aware of the 2Gig file size limit
-
-    >>> import grass.pygrass as pygrass
-    >>> elev = pygrass.raster.RasterNumpy('elevation')
-    >>> elev.open()
-    >>> elev[:5, :3]
-    RasterNumpy([[ 141.99613953,  141.27848816,  141.37904358],
-           [ 142.90461731,  142.39450073,  142.68611145],
-           [ 143.81854248,  143.54707336,  143.83972168],
-           [ 144.56524658,  144.58493042,  144.86477661],
-           [ 144.99488831,  145.22894287,  145.57142639]], dtype=float32)
-    >>> el = elev < 144
-    >>> el[:5, :3]
-    RasterNumpy([[1, 1, 1],
-           [1, 1, 1],
-           [1, 1, 1],
-           [0, 0, 0],
-           [0, 0, 0]], dtype=int32)
-    >>> el.exist()
-    False
-    >>> el.close('elev_bool', overwrite=True)
-    >>> el.exist()
-    True
-    >>> el.remove()
-    """
-    def __new__(cls, name, mapset="", mtype='CELL', mode='r+',
-                overwrite=False):
-        reg = Region()
-        shape = (reg.rows, reg.cols)
-        mapset = libgis.G_find_raster(name, mapset)
-        gtype = None
-        if mapset:
-            # map exist, set the map type
-            gtype = libraster.Rast_map_type(name, mapset)
-            mtype = RTYPE_STR[gtype]
-        filename = grasscore.tempfile()
-        obj = np.memmap.__new__(cls, filename=filename,
-                                dtype=RTYPE[mtype]['numpy'],
-                                mode=mode,
-                                shape=shape)
-        obj.mtype = mtype.upper()
-        obj.gtype = gtype if gtype else RTYPE[mtype]['grass type']
-        obj._rows = reg.rows
-        obj._cols = reg.cols
-        obj.filename = filename
-        obj._name = name
-        obj.mapset = mapset
-        obj.reg = reg
-        obj.overwrite = overwrite
-        return obj
-
-    def __array_finalize__(self, obj):
-        if hasattr(obj, '_mmap'):
-            self._mmap = obj._mmap
-            self.filename = grasscore.tempfile()
-            self.offset = obj.offset
-            self.mode = obj.mode
-            self._rows = obj._rows
-            self._cols = obj._cols
-            self._name = None
-            self.mapset = ''
-            self.reg = obj.reg
-            self.overwrite = obj.overwrite
-            self.mtype = obj.mtype
-            self._fd = obj._fd
-        else:
-            self._mmap = None
-
-    def _get_mode(self):
-        return self._mode
-
-    def _set_mode(self, mode):
-        if mode.lower() not in ('r', 'w+', 'r+', 'c'):
-            raise ValueError(_("Mode type: {0} not supported.").format(mode))
-        self._mode = mode
-
-    mode = property(fget=_get_mode, fset=_set_mode,
-                    doc="Set or obtain the opening mode of raster")
-
-    def __array_wrap__(self, out_arr, context=None):
-        """See:
-        http://docs.scipy.org/doc/numpy/user/
-        basics.subclassing.html#array-wrap-for-ufuncs"""
-        if out_arr.dtype.kind in 'bui':
-            # there is not support for boolean maps, so convert into integer
-            out_arr = out_arr.astype(np.int32)
-            out_arr.mtype = 'CELL'
-        #out_arr.p = out_arr.ctypes.data_as(out_arr.pointer_type)
-        return np.ndarray.__array_wrap__(self, out_arr, context)
-
-    def __init__(self, name, *args, **kargs):
-        ## Private attribute `_fd` that return the file descriptor of the map
-        self._fd = None
-        rows, cols = self._rows, self._cols
-        RasterAbstractBase.__init__(self, name)
-        self._rows, self._cols = rows, cols
-
-    def __unicode__(self):
-        return RasterAbstractBase.__unicode__(self)
-
-    def __str__(self):
-        return self.__unicode__()
-
-    def _get_flags(self, size, kind):
-        if size in FLAGS:
-            if kind in FLAGS[size]:
-                return size, FLAGS[size][kind]
-            else:
-                raise ValueError(_('Invalid type {0}'.format(kind)))
-        else:
-            raise ValueError(_('Invalid size {0}'.format(size)))
-
-    def _read(self):
-        """!Read raster map into array
-
-        :return: 0 on success
-        :return: non-zero code on failure
-        """
-        with RasterRow(self.name, self.mapset, mode='r') as rst:
-            buff = rst[0]
-            for i in range(len(rst)):
-                self[i] = rst.get_row(i, buff)
-
-    def _write(self, name, overwrite):
-        """Write the numpy array into map
-        """
-        if not self.exist() or self.mode != 'r':
-            self.flush()
-            buff = Buffer(self[0].shape, mtype=self.mtype)
-            with RasterRow(name, self.mapset, mode='w',
-                           mtype=self.mtype, overwrite=overwrite) as rst:
-                for i in range(len(rst)):
-                    buff[:] = self[i][:]
-                    rst.put_row(buff[:])
-            self.name = name
-
-    def open(self, mtype='', null=None, overwrite=None):
-        """Open the map, if the map already exist: determine the map type
-        and copy the map to the segment files;
-        else, open a new segment map.
-
-        :param mtype: specify the map type, valid only for new maps: CELL,
-                      FCELL, DCELL;
-        :type mtype: str
-        :param null:
-        :type null:
-        :param overwrite: use this flag to set the overwrite mode of existing
-                          raster maps
-        :type overwrite: bool
-        """
-        if overwrite is not None:
-            self.overwrite = overwrite
-        self.null = null
-        # rows and cols already set in __new__
-        if self.exist():
-            self.info.read()
-            self.cats.mtype = self.mtype
-            self.cats.read()
-            self.hist.read()
-            self._read()
-        else:
-            if mtype:
-                self.mtype = mtype
-            self._gtype = RTYPE[self.mtype]['grass type']
-        # set _fd, because this attribute is used to check
-        # if the map is open or not
-        self._fd = 1
-
-    def close(self, name='', overwrite=False):
-        """Function to close the map
-
-        :param name: the name of raster
-        :type name: str
-        """
-        if self.is_open():
-            name = name if name else self.name
-            if not name:
-                raise RuntimeError('Raster name not set neither '
-                                   'given as parameter.')
-            self._write(name, overwrite)
-            os.remove(self.filename)
-            self._fd = None
-
-    def get_value(self, point, region=None):
-        """This method returns the pixel value of a given pair of coordinates:
-
-        :param point: pair of coordinates in tuple object
-        :type point: tuple
-        :param region: the region to crop the request
-        :type region: Region object
-        """
-        if not region:
-            region = Region()
-        x, y = utils.coor2pixel(point.coords(), region)
-        return self[x][y]
-
-
 def random_map_only_columns(mapname, mtype, overwrite=True, factor=100):
 def random_map_only_columns(mapname, mtype, overwrite=True, factor=100):
     region = Region()
     region = Region()
     random_map = RasterRow(mapname)
     random_map = RasterRow(mapname)

+ 4 - 2
lib/python/pygrass/raster/buffer.py

@@ -4,8 +4,10 @@ import ctypes
 import numpy as np
 import numpy as np
 
 
 
 
-CELL = (np.int, np.int0, np.int8, np.int16, np.int32, np.int64)
-FCELL = (np.float, np.float16, np.float32)
+_CELL = ('int', 'int0', 'int8', 'int16', 'int32', 'int64')
+CELL = tuple([getattr(np, attr) for attr in _CELL if hasattr(np, attr)])
+_FCELL = 'float', 'float16', 'float32'
+FCELL = tuple([getattr(np, attr) for attr in _FCELL if hasattr(np, attr)])
 _DCELL = 'float64', 'float128'
 _DCELL = 'float64', 'float128'
 DCELL = tuple([getattr(np, attr) for attr in _DCELL if hasattr(np, attr)])
 DCELL = tuple([getattr(np, attr) for attr in _DCELL if hasattr(np, attr)])
 
 

+ 16 - 0
lib/python/pygrass/utils.py

@@ -286,6 +286,22 @@ def get_lib_path(modname, libname):
     return path
     return path
 
 
 
 
+def set_path(modulename, dirname, path='.'):
+    import sys
+    """Set sys.path looking in the the local directory GRASS directories."""
+    pathlib = os.path.join(path, dirname)
+    if os.path.exists(pathlib):
+        # we are running the script from the script directory
+        sys.path.append(os.path.abspath(path))
+    else:
+        # running from GRASS GIS session
+        from grass.pygrass.utils import get_lib_path
+        path = get_lib_path(modulename, dirname)
+        if path is None:
+            raise ImportError("Not able to find the path %s directory." % path)
+        sys.path.append(path)
+
+
 def split_in_chunk(iterable, lenght=10):
 def split_in_chunk(iterable, lenght=10):
     """Split a list in chunk.
     """Split a list in chunk.
 
 

+ 37 - 13
lib/python/pygrass/vector/geometry.py

@@ -7,6 +7,7 @@ Created on Wed Jul 18 10:46:25 2012
 """
 """
 import ctypes
 import ctypes
 import re
 import re
+from collections import namedtuple
 
 
 import numpy as np
 import numpy as np
 
 
@@ -19,6 +20,8 @@ from grass.pygrass.vector.basic import Ilist, Bbox, Cats
 from grass.pygrass.vector import sql
 from grass.pygrass.vector import sql
 
 
 
 
+LineDist = namedtuple('LineDist', 'point dist spdist sldist')
+
 WKT = {'POINT\((.*)\)': 'point',  # 'POINT\(\s*([+-]*\d+\.*\d*)+\s*\)'
 WKT = {'POINT\((.*)\)': 'point',  # 'POINT\(\s*([+-]*\d+\.*\d*)+\s*\)'
        'LINESTRING\((.*)\)': 'line'}
        'LINESTRING\((.*)\)': 'line'}
 
 
@@ -763,18 +766,20 @@ class Line(Geo):
         :param pnt: the point to calculate distance
         :param pnt: the point to calculate distance
         :type pnt: a Point object or a tuple with the coordinates
         :type pnt: a Point object or a tuple with the coordinates
 
 
-        Return a tuple with:
+        Return a namedtuple with:
 
 
-            * the closest point on the line,
-            * the distance between these two points,
-            * distance of point from segment beginning
-            * distance of point from line
+            * point: the closest point on the line,
+            * dist: the distance between these two points,
+            * spdist: distance to point on line from segment beginning
+            * sldist: distance to point on line form line beginning along line
 
 
         The distance is compute using the ``Vect_line_distance`` C function.
         The distance is compute using the ``Vect_line_distance`` C function.
 
 
-            >>> line = Line([(0, 0), (0, 2)])
-            >>> line.distance(Point(1, 1))
-            (Point(0.000000, 1.000000), 1.0, 1.0, 1.0)
+            >>> point = Point(2.3, 0.5)
+            >>> line = Line([(0, 0), (2, 0), (3, 0)])
+            >>> line.distance(point)           #doctest: +NORMALIZE_WHITESPACE
+            LineDist(point=Point(2.300000, 0.000000),
+                     dist=0.5, spdist=0.2999999999999998, sldist=2.3)
 
 
         """
         """
         # instantite outputs
         # instantite outputs
@@ -795,7 +800,7 @@ class Line(Geo):
         # instantiate the Point class
         # instantiate the Point class
         point = Point(cx.value, cy.value, cz.value)
         point = Point(cx.value, cy.value, cz.value)
         point.is2D = self.is2D
         point.is2D = self.is2D
-        return point, dist.value, sp_dist.value, lp_dist.value
+        return LineDist(point, dist.value, sp_dist.value, lp_dist.value)
 
 
     def get_first_cat(self):
     def get_first_cat(self):
         """Fetches FIRST category number for given vector line and field, using
         """Fetches FIRST category number for given vector line and field, using
@@ -919,8 +924,27 @@ class Line(Geo):
         libvect.Vect_line_reverse(self.c_points)
         libvect.Vect_line_reverse(self.c_points)
 
 
     def segment(self, start, end):
     def segment(self, start, end):
-        # TODO improve documentation
         """Create line segment. using the ``Vect_line_segment`` C function.
         """Create line segment. using the ``Vect_line_segment`` C function.
+        :param start: distance from the begining of the line where
+                      the segment start
+        :type start: float
+        :param end: distance from the begining of the line where
+                    the segment end
+        :type end: float
+
+        ::
+            #            x (1, 1)
+            #            |
+            #            |-
+            #            |
+            #   x--------x (1, 0)
+            # (0, 0) ^
+
+            >>> line = Line([(0, 0), (1, 0), (1, 1)])
+            >>> line.segment(0.5, 1.5)         #doctest: +NORMALIZE_WHITESPACE
+            Line([Point(0.500000, 0.000000),
+                  Point(1.000000, 0.000000),
+                  Point(1.000000, 0.500000)])
         """
         """
         line = Line()
         line = Line()
         libvect.Vect_line_segment(self.c_points, start, end, line.c_points)
         libvect.Vect_line_segment(self.c_points, start, end, line.c_points)
@@ -1122,7 +1146,7 @@ class Node(object):
         :type only_out: bool
         :type only_out: bool
         """
         """
         for iline in self.ilines(only_in, only_out):
         for iline in self.ilines(only_in, only_out):
-            yield Line(id=abs(iline), c_mapinfo=self.c_mapinfo)
+            yield Line(v_id=abs(iline), c_mapinfo=self.c_mapinfo)
 
 
     def angles(self):
     def angles(self):
         """Return a generator with all lines angles in a node."""
         """Return a generator with all lines angles in a node."""
@@ -1321,7 +1345,7 @@ class Isle(Geo):
         """Return the perimeter value of an Isle.
         """Return the perimeter value of an Isle.
         """
         """
         border = self.points()
         border = self.points()
-        return libvect.Vect_area_perimeter(border.c_points)
+        return libvect.Vect_line_geodesic_length(border.c_points)
 
 
 
 
 class Isles(object):
 class Isles(object):
@@ -1562,7 +1586,7 @@ class Area(Geo):
 
 
         """
         """
         border = self.get_points()
         border = self.get_points()
-        return libvect.Vect_area_perimeter(border.c_points)
+        return libvect.Vect_line_geodesic_length(border.c_points)
 
 
     def read(self, line=None, centroid=None, isles=None):
     def read(self, line=None, centroid=None, isles=None):
         self.boundary = self.get_points(line)
         self.boundary = self.get_points(line)

+ 16 - 22
lib/python/pygrass/vector/table.py

@@ -398,7 +398,7 @@ class Columns(object):
         >>> remove('mycensus', 'vect')
         >>> remove('mycensus', 'vect')
 
 
         """
         """
-        def check_col(col_type):
+        def check(col_type):
             """Check the column type if it is supported by GRASS
             """Check the column type if it is supported by GRASS
 
 
             :param col_type: the type of column
             :param col_type: the type of column
@@ -407,26 +407,19 @@ class Columns(object):
             valid_type = ('DOUBLE PRECISION', 'DOUBLE', 'INT', 'INTEGER',
             valid_type = ('DOUBLE PRECISION', 'DOUBLE', 'INT', 'INTEGER',
                           'DATE')
                           'DATE')
             if 'VARCHAR' in col_type or col_type.upper() not in valid_type:
             if 'VARCHAR' in col_type or col_type.upper() not in valid_type:
-                str_err = "Type is not supported, supported types are: %s"
-                raise TypeError(str_err % ", ".join(valid_type))
-
-        if isinstance(col_name, unicode):
-            check_col(col_type)
-        else:
-            if len(col_name) == len(col_type):
-                cvars = []
-                for name, ctype in zip(col_name, col_type):
-                    check_col(ctype)
-                    cvars.append('%s %s' % (name, ctype))
-                col_name = ''
-                col_type = ','.join(cvars)
-            else:
-                str_err = "The lenghts of the columns are different:\n%r\n%r"
-                raise TypeError(str_err % (col_name, col_type))
+                str_err = ("Type: %r is not supported."
+                           "\nSupported types are: %s")
+                raise TypeError(str_err % (col_type, ", ".join(valid_type)))
+            return col_type
+
+        col_type = ([check(col_type), ] if isinstance(col_type, (str, unicode))
+                    else [check(col) for col in col_type])
+        col_name = ([col_name, ] if isinstance(col_name, (str, unicode))
+                    else col_name)
+        sqlcode = [sql.ADD_COL.format(tname=self.tname, cname=cn, ctype=ct)
+                   for cn, ct in zip(col_name, col_type)]
         cur = self.conn.cursor()
         cur = self.conn.cursor()
-        cur.execute(sql.ADD_COL.format(tname=self.tname,
-                                       cname=col_name,
-                                       ctype=col_type))
+        cur.executescript('\n'.join(sqlcode))
         self.conn.commit()
         self.conn.commit()
         cur.close()
         cur.close()
         self.update_odict()
         self.update_odict()
@@ -1022,7 +1015,7 @@ class Table(object):
         cur = cursor if cursor else self.conn.cursor()
         cur = cursor if cursor else self.conn.cursor()
         if self.exist(cursor=cur):
         if self.exist(cursor=cur):
             used = db_table_in_vector(self.name)
             used = db_table_in_vector(self.name)
-            if len(used) > 0 and not force:
+            if used is not None and len(used) > 0 and not force:
                 print(_("Deleting table <%s> which is attached"
                 print(_("Deleting table <%s> which is attached"
                         " to following map(s):") % self.name)
                         " to following map(s):") % self.name)
                 for vect in used:
                 for vect in used:
@@ -1125,7 +1118,8 @@ class Table(object):
         :type cursor: Cursor object
         :type cursor: Cursor object
         """
         """
         cur = cursor if cursor else self.conn.cursor()
         cur = cursor if cursor else self.conn.cursor()
-        return cur.execute(self.columns.update_str, values)
+        vals = list(values) + [key, ]
+        return cur.execute(self.columns.update_str, vals)
 
 
     def create(self, cols, name=None, overwrite=False, cursor=None):
     def create(self, cols, name=None, overwrite=False, cursor=None):
         """Create a new table
         """Create a new table