Parcourir la source

Added temporal raster and 3D raster algebra classes and tests

git-svn-id: https://svn.osgeo.org/grass/grass/trunk@58971 15284696-431f-4ddb-bdfa-cd5b030d7da7
Soeren Gebbert il y a 11 ans
Parent
commit
047fa04d74

Fichier diff supprimé car celui-ci est trop grand
+ 1 - 1
lib/python/temporal/Makefile


+ 4 - 0
lib/python/temporal/__init__.py

@@ -28,3 +28,7 @@ from c_libraries_interface import *
 from temporal_algebra import *
 from temporal_vector_algebra import *
 from temporal_vector_operator import *
+from temporal_raster_operator import *
+from temporal_raster_base_algebra import *
+from temporal_raster_algebra import *
+from temporal_raster3d_algebra import *

+ 4 - 6
lib/python/temporal/open_stds.py

@@ -30,7 +30,7 @@ def open_old_space_time_dataset(name, type, dbif=None):
     """!This function opens an existing space time dataset and return the
        created and intialized object of the specified type.
 
-       This function will raise a ScriptError in case the type is wrong,
+       This function will call exit() or raise a grass.pygrass.messages.FatalError in case the type is wrong,
        or the space time dataset was not found.
 
        @param name The name of the space time dataset, if the name does not
@@ -112,7 +112,7 @@ def check_new_space_time_dataset(name, type, dbif=None, overwrite=False):
     elif type == "stvds" or type == "vect" or type == "vector":
         sp = dataset_factory("stvds", id)
     else:
-        core.error(_("Unkown type: %s") % (type))
+        msgr.error(_("Unkown type: %s") % (type))
         return None
 
     dbif, connected = init_dbif(dbif)
@@ -142,12 +142,10 @@ def open_new_space_time_dataset(name, type, temporaltype, title, descr, semantic
        @param semantic Semantical information
        @param dbif The temporal database interface to be used
        @param overwrite Flag to allow overwriting
-       @param dry Do not create the space time dataset in the temporal database,
-                  make a dry run with including all checks
 
        @return The new created space time dataset
 
-       This function will raise a ScriptError in case of an error.
+       This function will raise a FatalError in case of an error.
     """
     dbif, connected = init_dbif(dbif)
     msgr = get_tgis_message_interface()
@@ -177,7 +175,7 @@ def open_new_space_time_dataset(name, type, temporaltype, title, descr, semantic
 
 ############################################################################
 
-def check_new_map_dataset(name, layer=None, type="raster", 
+def check_new_map_dataset(name, layer=None, type="raster",
                           overwrite=False, dbif=None):
     """!Check if a new map dataset of a specific type can be created in
         the temporal database

+ 147 - 44
lib/python/temporal/temporal_algebra.py

@@ -390,10 +390,7 @@ try:
 except:
     pass
 
-import re
-import sys
 import os
-import grass.pygrass.modules as pygrass
 import grass.script as grass
 from space_time_datasets import *
 from factory import *
@@ -608,6 +605,7 @@ class TemporalAlgebraLexer(object):
              print tok
 
 ###############################################################################
+
 class GlobalTemporalVar(object):
     """ This class handles global temporal variable conditional expressions,
         like start_doy() == 3.
@@ -650,11 +648,23 @@ class GlobalTemporalVar(object):
 
         return(valuelist)
 
+    def __str__(self):
+        return str(self.tfunc) + str(self.compop) + str(self.value)
+
 ###############################################################################
 
 class TemporalAlgebraParser(object):
     """The temporal algebra class"""
 
+    # Get the tokens from the lexer class
+    tokens = TemporalAlgebraLexer.tokens
+
+    # Setting equal precedence level for select and hash operations.
+    precedence = (
+        ('left', 'T_SELECT_OPERATOR', 'T_SELECT', 'T_NOT_SELECT'), # 1
+        ('left', 'AND', 'OR', 'T_COMP_OPERATOR'), #2
+        )
+
     def __init__(self, pid=None, run = True, debug = False, spatial = False, null = False):
         self.run = run
         self.debug = debug
@@ -674,11 +684,12 @@ class TemporalAlgebraParser(object):
         if self.dbif.connected:
             self.dbif.close()
 
-    def parse(self, expression, stdstype = 'strds', basename = None):
+    def parse(self, expression, stdstype = 'strds', basename = None, overwrite=False):
         self.lexer = TemporalAlgebraLexer()
         self.lexer.build()
         self.parser = yacc.yacc(module=self, debug=self.debug)
 
+        self.overwrite = overwrite
         self.count = 0
         self.stdstype = stdstype
         self.basename = basename
@@ -701,14 +712,87 @@ class TemporalAlgebraParser(object):
         self.names[name] = name
         return name
 
-    # Get the tokens from the lexer class
-    tokens = TemporalAlgebraLexer.tokens
+    def generate_new_map(self, base_map, bool_op = 'and', copy = True):
+        """!Generate a new map using the spatio-temporal extent of the base map
 
-    # Setting equal precedence level for select and hash operations.
-    precedence = (
-        ('left', 'T_SELECT_OPERATOR', 'T_SELECT', 'T_NOT_SELECT'), # 1
-        ('left', 'AND', 'OR', 'T_COMP_OPERATOR'), #2
-        )
+           @param base_map This map is used to create the new map
+        """
+        # Generate an intermediate name for the result map list.
+        name = self.generate_map_name()
+        # Check for mapset in given stds input.
+        mapname = name + "@" + self.mapset
+        # Create new map based on the related map list.
+        map_new = base_map.get_new_instance(mapname)
+        # Set initial map extend of new vector map.
+        self.overlay_map_extent(map_new, base_map, bool_op = bool_op, copy = copy)
+
+        return map_new
+
+    def overlay_map_extent(self, mapA, mapB, bool_op = None, temp_op = '=',
+                            copy = False):
+        """!Compute the spatio-temporal extent of two topological related maps
+
+           @param mapA The first map
+           @param mapB The second maps
+           @param bool_op The boolean operator specifying the spatial extent
+                  operation (intersection, union, disjoint union)
+           @param temp_op The temporal operator specifying the temporal
+                  extent operation (intersection, union, disjoint union)
+           @param copy Specifies if the temporal extent of mapB should be
+                  copied to mapA
+           @return 0 if there is no overlay
+        """
+        returncode = 1
+        if copy:
+            map_extent_temporal = mapB.get_temporal_extent()
+            map_extent_spatial = mapB.get_spatial_extent()
+            # Set initial map extend of new vector map.
+            mapA.set_spatial_extent(map_extent_spatial)
+            mapA.set_temporal_extent(map_extent_temporal)
+            if "cmd_list" in dir(mapB):
+                mapA.cmd_list = mapB.cmd_list
+        else:
+            # Calculate spatial extent for different overlay operations.
+            if bool_op == 'and':
+                overlay_ext = mapA.spatial_intersection(mapB)
+                if overlay_ext != None:
+                    mapA.set_spatial_extent(overlay_ext)
+                else:
+                    returncode = 0
+            elif bool_op in ['or', 'xor']:
+                overlay_ext = mapA.spatial_union(mapB)
+                if overlay_ext != None:
+                    mapA.set_spatial_extent(overlay_ext)
+                else:
+                    returncode = 0
+            elif bool_op == 'disor':
+                overlay_ext = mapA.spatial_disjoint_union(mapB)
+                if overlay_ext != None:
+                    mapA.set_spatial_extent(overlay_ext)
+                else:
+                    returncode = 0
+
+            # Calculate temporal extent for different temporal operators.
+            if temp_op == '&':
+                temp_ext = mapA.temporal_intersection(mapB)
+                if temp_ext != None:
+                    mapA.set_temporal_extent(temp_ext)
+                else:
+                    returncode = 0
+            elif temp_op == '|':
+                temp_ext = mapA.temporal_union(mapB)
+                if temp_ext != None:
+                    mapA.set_temporal_extent(temp_ext)
+                else:
+                    returncode = 0
+            elif temp_op == '+':
+                temp_ext = mapA.temporal_disjoint_union(mapB)
+                if temp_ext != None:
+                    mapA.set_temporal_extent(temp_ext)
+                else:
+                    returncode = 0
+
+        return(returncode)
 
     ######################### Temporal functions ##############################
 
@@ -1671,6 +1755,7 @@ class TemporalAlgebraParser(object):
             return(inverselist)
         else:
             return(resultlist)
+
     ###########################################################################
 
     def p_statement_assign(self, t):
@@ -1682,8 +1767,8 @@ class TemporalAlgebraParser(object):
         if self.run:
             resultstds = open_new_space_time_dataset(t[1], self.stdstype, \
                                                         self.temporaltype, "", "", \
-                                                        'mean', None, \
-                                                        overwrite = grass.overwrite())
+                                                        'mean', dbif=self.dbif, \
+                                                        overwrite = self.overwrite)
             if isinstance(t[3], list):
                 num = len(t[3])
                 count = 0
@@ -1702,9 +1787,11 @@ class TemporalAlgebraParser(object):
                         dbif.close()
             t[0] = t[3]
 
+        else:
+            t[0] = t[3]
+
         if self.debug:
             print t[1], "=", t[3]
-            t[0] = t[3]
 
     def p_stds_1(self, t):
         # Definition of a space time dataset
@@ -1780,11 +1867,12 @@ class TemporalAlgebraParser(object):
                     map_i.map_value = gvar
 
             t[0] = maplist
+        else:
+            t[0] = "td(" + str(t[3]) + ")"
 
         if self.debug:
-            print "td(" + t[3] + ")"
+            print "td(" + str(t[3]) + ")"
 
-            t[0] = "td(" + t[3] + ")"
 
     def p_t_time_var(self, t):
         # Temporal variables that return a double or integer value
@@ -1862,13 +1950,14 @@ class TemporalAlgebraParser(object):
                 gvar.compop = t[4]
                 gvar.value  = t[5]
                 t[0] = gvar
+        else:
+            t[0] = True
 
         if self.debug:
             if len(t) == 6:
                 print t[1], t[4], t[5]
             if len(t) == 4:
                 print t[1], t[2], t[3]
-            t[0] = True
 
     def p_t_var_expr_time1(self, t):
         # Examples:
@@ -1889,10 +1978,11 @@ class TemporalAlgebraParser(object):
             gvar.compop = t[4]
             gvar.value  = t[5]
             t[0] = gvar
+        else:
+            t[0] = True
 
         if self.debug:
             print t[1], t[4], t[5]
-            t[0] = True
 
     def p_t_var_expr_time2(self, t):
         """
@@ -1911,11 +2001,12 @@ class TemporalAlgebraParser(object):
             gvar.compop = reverseop[t[2]]
             gvar.value  = t[1]
             t[0] = gvar
+        else:
+            t[0] = True
 
         if self.debug:
             print(t[4])
             print t[1], t[4], t[5]
-            t[0] = True
 
     def p_t_var_expr_comp(self, t):
         """
@@ -1934,10 +2025,11 @@ class TemporalAlgebraParser(object):
             resultlist.append(tvarexprB)
 
             t[0] = resultlist
+        else:
+            t[0] = True
 
         if self.debug:
             print t[1], t[2] + t[3], t[4]
-            t[0] = True
 
     def p_t_var_expr_comp_op(self, t):
         """
@@ -1958,10 +2050,11 @@ class TemporalAlgebraParser(object):
             resultlist.append(tvarexprB)
 
             t[0] = resultlist
+        else:
+            t[0] = True
 
         if self.debug:
             print t[1], t[2], t[3]
-            t[0] = True
 
     def p_expr_t_select(self, t):
         # Temporal equal selection
@@ -1984,10 +2077,11 @@ class TemporalAlgebraParser(object):
             selectlist = self.perform_temporal_selection(maplistA, maplistB)
             # Return map list.
             t[0] = selectlist
+        else:
+            t[0] = t[1] + "*"
 
         if self.debug:
             print t[1] + "* = ", t[1], t[2], t[3]
-            t[0] = t[1] + "*"
 
     def p_expr_t_not_select(self, t):
         # Temporal equal selection
@@ -2009,10 +2103,11 @@ class TemporalAlgebraParser(object):
                                                          inverse = True)
             # Return map list.
             t[0] = selectlist
+        else:
+            t[0] = t[1] + "*"
 
         if self.debug:
             print t[1] + "* = ", t[1], t[2], t[3]
-            t[0] = t[1] + "*"
 
 
     def p_expr_t_select_operator(self, t):
@@ -2050,10 +2145,11 @@ class TemporalAlgebraParser(object):
 
             # Return map list.
             t[0] = selectlist
+        else:
+            t[0] = t[1] + "*"
 
         if self.debug:
             print t[1] + "* = ", t[1], t[2], t[3]
-            t[0] = t[1] + "*"
 
 
     def p_expr_condition_if(self, t):
@@ -2074,10 +2170,11 @@ class TemporalAlgebraParser(object):
             resultlist   = self.check_stds(thenresult, clear = True)
             # Return resulting map list.
             t[0] = resultlist
+        else:
+            t[0] = t[5] + "*"
 
         if self.debug:
-            print t[5] + "* = ", "if condition", t[3], ' then ', t[5]
-            t[0] = t[5] + "*"
+            print str(t[5]) + "* = ", "if condition", str(t[3]), ' then ', str(t[5])
 
     def p_expr_condition_if_relation(self, t):
         # Examples
@@ -2098,10 +2195,11 @@ class TemporalAlgebraParser(object):
             resultlist   = self.check_stds(thenresult, clear = True)
             # Return resulting map list.
             t[0] = resultlist
+        else:
+            t[0] = t[7] + "*"
 
         if self.debug:
-            print t[5] + "* = ", "if condition", t[3], ' then ', t[5]
-            t[0] = t[5] + "*"
+            print "result* = ", "if ", str(t[3]),  "condition", str(t[5]), " then ", str(t[7])
 
     def p_expr_condition_elif(self, t):
         # Examples
@@ -2130,10 +2228,11 @@ class TemporalAlgebraParser(object):
             resultlist   = self.check_stds(resultlist, clear = True)
             # Return resulting map list.
             t[0] = resultlist
+        else:
+            t[0] = t[5] + "*"
 
         if self.debug:
-            print t[5] + "* = ", "if condition", t[3], " then ", t[5], ' else ', t[7]
-            t[0] = t[5] + "*"
+            print str(t[5]) + "* = ", "if condition", str(t[3]), " then ", str(t[5]), ' else ', str(t[7])
 
     def p_expr_condition_elif_relation(self, t):
         # Examples
@@ -2165,15 +2264,18 @@ class TemporalAlgebraParser(object):
             resultlist   = self.check_stds(resultlist, clear = True)
             # Return resulting map list.
             t[0] = resultlist
-
-        if self.debug:
+        else:
             if t[5]:
-                print t[7], "* = ", "if condition", t[5], " then ", t[7], ' else ', t[9]
                 t[0] = str(t[7])
             else:
-                print t[9], "* = ", "if condition", t[5], " then ", t[7], ' else ', t[9]
                 t[0] = str(t[9])
 
+        if self.debug:
+            if t[5]:
+                print str(t[7]), "* = ", "if condition", str(t[5]), " then ", str(t[7]), ' else ', str(t[9])
+            else:
+                print str(t[9]), "* = ", "if condition", str(t[5]), " then ", str(t[7]), ' else ', str(t[9])
+
     def p_expr_t_buff(self, t):
         # Examples
         # buff_t(A : B, "10 minutes")  # Select the part of A that is temporally
@@ -2196,13 +2298,14 @@ class TemporalAlgebraParser(object):
                 # Perform buffering.
                 map.temporal_buffer(increment)
             t[0] = bufflist
+        else:
+            t[0] = t[3] + "*"
 
         if self.debug:
             if len(t) == 10:
-                print t[3] + "* = buff_t(", t[3], "," , '"', t[6], t[7], '"', ")"
+                print str(t[3]) + "* = buff_t(", str(t[3]), "," , '"', str(t[6]), str(t[7]), '"', ")"
             elif len(t) == 7:
-                print t[3] + "* = buff_t(", t[3], ",", t[5], ")"
-            t[0] = t[3] + "*"
+                print str(t[3]) + "* = buff_t(", str(t[3]), ",", str(t[5]), ")"
 
     def p_expr_t_snap(self, t):
         # Examples
@@ -2217,10 +2320,11 @@ class TemporalAlgebraParser(object):
             # Perform snapping.
             snaplist = AbstractSpaceTimeDataset.snap_map_list(maplist)
             t[0] = snaplist
+        else:
+            t[0] = t[3] + "*"
 
         if self.debug:
-            print t[3] + "* = tsnap(", t[3], ")"
-            t[0] = t[3] + "*"
+            print str(t[3]) + "* = tsnap(", str(t[3]), ")"
 
     def p_expr_t_shift(self, t):
         # Examples
@@ -2243,13 +2347,14 @@ class TemporalAlgebraParser(object):
             # Perform shifting.
             shiftlist = AbstractSpaceTimeDataset.shift_map_list(maplist, increment)
             t[0] = shiftlist
+        else:
+            t[0] = t[3] + "*"
 
         if self.debug:
             if len(t) == 10:
-                print t[3] + "* = tshift(", t[3], "," , '"', t[6], t[7], '"', ")"
+                print str(t[3]) + "* = tshift(", str(t[3]), "," , '"', str(t[6]), str(t[7]), '"', ")"
             elif len(t) == 7:
-                print t[3] + "* = tshift(", t[3], ",", t[5], ")"
-            t[0] = t[3] + "*"
+                print str(t[3]) + "* = tshift(", str(t[3]), ",", str(t[5]), ")"
 
     # Handle errors.
     def p_error(self, t):
@@ -2261,5 +2366,3 @@ class TemporalAlgebraParser(object):
 if __name__ == "__main__":
     import doctest
     doctest.testmod()
-
-

+ 110 - 0
lib/python/temporal/temporal_raster3d_algebra.py

@@ -0,0 +1,110 @@
+"""!@package grass.temporal
+
+Temporal raster algebra
+
+(C) 2013 by the GRASS Development Team
+This program is free software under the GNU General Public
+License (>=v2). Read the file COPYING that comes with GRASS
+for details.
+
+@author Thomas Leppelt and Soeren Gebbert
+
+"""
+
+from temporal_raster_base_algebra import *
+
+###############################################################################
+
+class TemporalRaster3DAlgebraParser(TemporalRasterBaseAlgebraParser):
+    """The temporal raster algebra class"""
+
+    def __init__(self, pid=None, run=False, debug=True, spatial = False):
+        TemporalRasterBaseAlgebraParser.__init__(self, pid, run, debug, spatial)
+
+        self.m_mapcalc = pygrass.Module('r3.mapcalc')
+
+    def parse(self, expression, basename = None, overwrite=False):
+        self.lexer = TemporalRasterAlgebraLexer()
+        self.lexer.build()
+        self.parser = yacc.yacc(module=self, debug=self.debug)
+
+        self.overwrite = overwrite
+        self.count = 0
+        self.stdstype = "str3ds"
+        self.basename = basename
+        self.expression = expression
+        self.parser.parse(expression)
+
+    ######################### Temporal functions ##############################
+
+    def p_statement_assign(self, t):
+        # The expression should always return a list of maps.
+        """
+        statement : stds EQUALS expr
+        """
+        TemporalRasterBaseAlgebraParser.p_statement_assign(self, t)
+
+    def p_ts_neighbor_operation(self, t):
+        # Examples:
+        # A[1,0,-1]
+        # B[-2]
+        # C[1,-2,1,3]
+        """
+        expr : stds L_SPAREN number COMMA number COMMA number R_SPAREN
+             | stds L_SPAREN number R_SPAREN
+             | stds L_SPAREN number COMMA number COMMA number COMMA number R_SPAREN
+        """
+        # Check input stds.
+        maplist = self.check_stds(t[1])
+        t_neighbor = 0
+        row_neighbor = None
+        col_neighbor = None
+        depth_neighbor = None
+        if len(t) == 5:
+            t_neighbor = t[3]
+        elif len(t) == 9:
+            row_neighbor = t[3]
+            col_neighbor = t[5]
+            depth_neighbor = t[7]
+        elif len(t) == 11:
+            t_neighbor = t[9]
+            row_neighbor = t[3]
+            col_neighbor = t[5]
+            depth_neighbor = t[7]
+        if self.run:
+            resultlist = []
+            max_index = len(maplist)
+            for map_i in maplist:
+                # Get map index and temporal extent.
+                map_index = maplist.index(map_i)
+                new_index = map_index + t_neighbor
+                if new_index < max_index and new_index >= 0:
+                    map_i_t_extent = map_i.get_temporal_extent()
+                    # Get neighboring map and set temporal extent.
+                    map_n = maplist[new_index]
+                    # Generate an intermediate map for the result map list.
+                    map_new = self.generate_new_map(map_n, bool_op = 'and', copy = True)
+                    map_new.set_temporal_extent(map_i_t_extent)
+                    # Create r.mapcalc expression string for the operation.
+                    if "cmd_list" in dir(map_new) and len(t) == 5:
+                        cmdstring = "%s" %(map_new.cmd_list)
+                    elif "cmd_list" not in dir(map_new) and len(t) == 5:
+                        cmdstring = "%s" %(map_n.get_id())
+                    elif "cmd_list" in dir(map_new) and len(t) in (9,11):
+                        cmdstring = "%s[%s,%s,%s]" %(map_new.cmd_list, row_neighbor, col_neighbor, depth_neighbor)
+                    elif "cmd_list" not in dir(map_new) and len(t) in (9,11):
+                        cmdstring = "%s[%s,%s,%s]" %(map_n.get_id(), row_neighbor, col_neighbor, depth_neighbor)
+                    # Set new command list for map.
+                    map_new.cmd_list = cmdstring
+                    # Append map with updated command list to result list.
+                    resultlist.append(map_new)
+
+            t[0] = resultlist
+
+###############################################################################
+
+if __name__ == "__main__":
+    import doctest
+    doctest.testmod()
+
+

+ 149 - 0
lib/python/temporal/temporal_raster_algebra.py

@@ -0,0 +1,149 @@
+"""!@package grass.temporal
+
+Temporal raster algebra
+
+(C) 2013 by the GRASS Development Team
+This program is free software under the GNU General Public
+License (>=v2). Read the file COPYING that comes with GRASS
+for details.
+
+@author Thomas Leppelt and Soeren Gebbert
+
+@code
+
+    >>> p = TemporalRasterAlgebraLexer()
+    >>> p.build()
+    >>> p.debug = True
+    >>> expression =  'R = A[0,1,0] / B[0,0,1] * 20 + C[0,1,1] - 2.45'
+    >>> p.test(expression)
+    R = A[0,1,0] / B[0,0,1] * 20 + C[0,1,1] - 2.45
+    LexToken(NAME,'R',1,0)
+    LexToken(EQUALS,'=',1,2)
+    LexToken(NAME,'A',1,4)
+    LexToken(L_SPAREN,'[',1,5)
+    LexToken(INT,0,1,6)
+    LexToken(COMMA,',',1,7)
+    LexToken(INT,1,1,8)
+    LexToken(COMMA,',',1,9)
+    LexToken(INT,0,1,10)
+    LexToken(R_SPAREN,']',1,11)
+    LexToken(DIV,'/',1,13)
+    LexToken(NAME,'B',1,15)
+    LexToken(L_SPAREN,'[',1,16)
+    LexToken(INT,0,1,17)
+    LexToken(COMMA,',',1,18)
+    LexToken(INT,0,1,19)
+    LexToken(COMMA,',',1,20)
+    LexToken(INT,1,1,21)
+    LexToken(R_SPAREN,']',1,22)
+    LexToken(MULT,'*',1,24)
+    LexToken(INT,20,1,26)
+    LexToken(ADD,'+',1,29)
+    LexToken(NAME,'C',1,31)
+    LexToken(L_SPAREN,'[',1,32)
+    LexToken(INT,0,1,33)
+    LexToken(COMMA,',',1,34)
+    LexToken(INT,1,1,35)
+    LexToken(COMMA,',',1,36)
+    LexToken(INT,1,1,37)
+    LexToken(R_SPAREN,']',1,38)
+    LexToken(SUB,'-',1,40)
+    LexToken(FLOAT,2.45,1,42)
+
+@endcode
+"""
+
+from temporal_raster_base_algebra import *
+
+###############################################################################
+
+class TemporalRasterAlgebraParser(TemporalRasterBaseAlgebraParser):
+    """The temporal raster algebra class"""
+
+    def __init__(self, pid=None, run=False, debug=True, spatial = False):
+        TemporalRasterBaseAlgebraParser.__init__(self, pid, run, debug, spatial)
+
+        self.m_mapcalc = pygrass.Module('r.mapcalc')
+
+    def parse(self, expression, basename = None, overwrite=False):
+        self.lexer = TemporalRasterAlgebraLexer()
+        self.lexer.build()
+        self.parser = yacc.yacc(module=self, debug=self.debug)
+
+        self.overwrite = overwrite
+        self.count = 0
+        self.stdstype = "strds"
+        self.basename = basename
+        self.expression = expression
+        self.parser.parse(expression)
+
+    ######################### Temporal functions ##############################
+
+    def p_statement_assign(self, t):
+        # The expression should always return a list of maps.
+        """
+        statement : stds EQUALS expr
+        """
+        TemporalRasterBaseAlgebraParser.p_statement_assign(self, t)
+
+    def p_ts_neighbour_operation(self, t):
+        # Examples:
+        # A[1,0]
+        # B[-2]
+        # C[-2,1,3]
+        """
+        expr : stds L_SPAREN number COMMA number R_SPAREN
+             | stds L_SPAREN number R_SPAREN
+             | stds L_SPAREN number COMMA number COMMA number R_SPAREN
+        """
+        # Check input stds.
+        maplist = self.check_stds(t[1])
+        row_neigbour = None
+        col_neigbour = None
+        if len(t) == 5:
+            t_neighbour = t[3]
+        elif len(t) == 7:
+            t_neighbour = 0
+            row_neigbour = t[3]
+            col_neigbour = t[5]
+        elif len(t) == 9:
+            t_neighbour = t[7]
+            row_neigbour = t[3]
+            col_neigbour = t[5]
+        if self.run:
+            resultlist = []
+            max_index = len(maplist)
+            for map_i in maplist:
+                # Get map index and temporal extent.
+                map_index = maplist.index(map_i)
+                new_index = map_index + t_neighbour
+                if new_index < max_index and new_index >= 0:
+                    map_i_t_extent = map_i.get_temporal_extent()
+                    # Get neighbouring map and set temporal extent.
+                    map_n = maplist[new_index]
+                    # Generate an intermediate map for the result map list.
+                    map_new = self.generate_new_map(map_n, bool_op = 'and', copy = True)
+                    map_new.set_temporal_extent(map_i_t_extent)
+                    # Create r.mapcalc expression string for the operation.
+                    if "cmd_list" in dir(map_new) and len(t) == 5:
+                        cmdstring = "%s" %(map_new.cmd_list)
+                    elif "cmd_list" not in dir(map_new) and len(t) == 5:
+                        cmdstring = "%s" %(map_n.get_id())
+                    elif "cmd_list" in dir(map_new) and len(t) in (7, 9):
+                        cmdstring = "%s[%s,%s]" %(map_new.cmd_list, row_neigbour, col_neigbour)
+                    elif "cmd_list" not in dir(map_new) and len(t) in (7, 9):
+                        cmdstring = "%s[%s,%s]" %(map_n.get_id(), row_neigbour, col_neigbour)
+                    # Set new command list for map.
+                    map_new.cmd_list = cmdstring
+                    # Append map with updated command list to result list.
+                    resultlist.append(map_new)
+
+            t[0] = resultlist
+
+###############################################################################
+
+if __name__ == "__main__":
+    import doctest
+    doctest.testmod()
+
+

Fichier diff supprimé car celui-ci est trop grand
+ 2590 - 0
lib/python/temporal/temporal_raster_base_algebra.py


+ 390 - 0
lib/python/temporal/temporal_raster_operator.py

@@ -0,0 +1,390 @@
+"""!@package grass.temporal
+
+Temporal operator evaluation with PLY
+
+(C) 2013 by the GRASS Development Team
+This program is free software under the GNU General Public
+License (>=v2). Read the file COPYING that comes with GRASS
+for details.
+
+@author Thomas Leppelt and Soeren Gebbert
+
+@code
+    >>> p = TemporalRasterOperatorParser()
+    >>> expression =  "{equal| during | follows,+!:}"
+    >>> p.parse(expression)
+    >>> print(p.relations, p.temporal, p.function)
+    (['equal', 'during', 'follows'], '+', '!:')
+    >>> expression =  "{equal| during,!:}"
+    >>> p.parse(expression)
+    >>> print(p.relations, p.temporal, p.function)
+    (['equal', 'during'], '=', '!:')
+    >>> expression =  "{!:}"
+    >>> p.parse(expression)
+    >>> print(p.relations, p.temporal, p.function)
+    (['equal'], '=', '!:')
+    >>> expression =  "{|#}"
+    >>> p.parse(expression)
+    >>> print(p.relations, p.temporal, p.function)
+    (['equal'], '|', '#')
+    >>> expression =  "{equal|during,=!:}"
+    >>> p.parse(expression)
+    >>> print(p.relations, p.temporal, p.function)
+    (['equal', 'during'], '=', '!:')
+    >>> expression =  "{equal|during|starts}"
+    >>> p.parse(expression)
+    >>> print(p.relations, p.temporal, p.function)
+    (['equal', 'during', 'starts'], None, None)
+    >>> expression =  "{equal,++}"
+    >>> p.parse(expression)
+    >>> print(p.relations, p.temporal, p.function)
+    (['equal'], '+', '+')
+    >>> expression =  "{equal | during,|%}"
+    >>> p.parse(expression)
+    >>> print(p.relations, p.temporal, p.function)
+    (['equal', 'during'], '|', '%')
+    >>> expression =  "{||}"
+    >>> p.parse(expression)
+    >>> print(p.relations, p.temporal, p.function)
+    (['equal'], '=', '||')
+    >>> expression =  "{equal,||}"
+    >>> p.parse(expression)
+    >>> print(p.relations, p.temporal, p.function)
+    (['equal'], '=', '||')
+    >>> expression =  "{equal | during | contains,&&}"
+    >>> p.parse(expression)
+    >>> print(p.relations, p.temporal, p.function)
+    (['equal', 'during', 'contains'], '=', '&&')
+    >>> expression =  "{equal | during | contains,/}"
+    >>> p.parse(expression)
+    >>> print(p.relations, p.temporal, p.function)
+    (['equal', 'during', 'contains'], '=', '/')
+    >>> expression =  "{equal | during | contains,|*}"
+    >>> p.parse(expression)
+    >>> print(p.relations, p.temporal, p.function)
+    (['equal', 'during', 'contains'], '|', '*')
+
+@endcode
+"""
+
+try:
+    import ply.lex as lex
+    import ply.yacc as yacc
+except:
+    pass
+
+class TemporalRasterOperatorLexer(object):
+    """!Lexical analyzer for the GRASS GIS temporal operator"""
+
+    # Functions that defines topological relations.
+    relations = {
+        'equal'      : "EQUAL",
+        'follows'    : "FOLLOWS",
+        'precedes'   : "PRECEDES",
+        'overlaps'   : "OVERLAPS",
+        'overlapped' : "OVERLAPPED",
+        'during'     : "DURING",
+        'starts'     : "STARTS",
+        'finishes'   : "FINISHES",
+        'contains'   : "CONTAINS",
+        'started'    : "STARTED",
+        'finished'   : "FINISHED",
+        'over'       : "OVER"
+        }
+
+    # This is the list of token names.
+    tokens = (
+        'COMMA',
+        'LEFTREF',
+        'HASH',
+        'OR',
+        'AND',
+        'MOD',
+        'DIV',
+        'MULT',
+        'ADD',
+        'SUB',
+        'T_SELECT',
+        'T_NOT_SELECT',
+        'CLPAREN',
+        'CRPAREN',
+    )
+
+    # Build the token list
+    tokens = tokens + tuple(relations.values())
+
+    # Regular expression rules for simple tokens
+    t_T_SELECT           = r':'
+    t_T_NOT_SELECT       = r'!:'
+    t_COMMA              = r','
+    t_LEFTREF             = r'='
+    t_HASH               = r'\#'
+    t_OR                 = r'[\|]'
+    t_AND                = r'[&]'
+    t_MOD                = r'[\%]'
+    t_DIV                = r'[\/]'
+    t_MULT               = r'[\*]'
+    t_ADD                = r'[\+]'
+    t_SUB                = r'[-]'
+    t_CLPAREN             = r'\{'
+    t_CRPAREN             = r'\}'
+
+    # These are the things that should be ignored.
+    t_ignore = ' \t'
+
+    # Track line numbers.
+    def t_newline(self, t):
+        r'\n+'
+        t.lineno += len(t.value)
+
+    def t_NAME(self, t):
+        r'[a-zA-Z_][a-zA-Z_0-9]*'
+        self.temporal_symbol(t)
+        return t
+
+    # Parse symbols
+    def temporal_symbol(self, t):
+        # Check for reserved words
+        if t.value in TemporalRasterOperatorLexer.relations.keys():
+            t.type = TemporalRasterOperatorLexer.relations.get(t.value)
+        #else:
+        #    t.type = 'NAME'
+        return(t)
+
+    # Handle errors.
+    def t_error(self, t):
+        raise SyntaxError("syntax error on line %d near '%s'" %
+            (t.lineno, t.value))
+
+    # Build the lexer
+    def build(self,**kwargs):
+        self.lexer = lex.lex(module=self, **kwargs)
+
+    # Just for testing
+    def test(self,data):
+        self.name_list = {}
+        print(data)
+        self.lexer.input(data)
+        while True:
+             tok = self.lexer.token()
+             if not tok: break
+             print tok
+
+###############################################################################
+
+class TemporalRasterOperatorParser(object):
+    """The temporal algebra class"""
+
+    def __init__(self):
+        self.lexer = TemporalRasterOperatorLexer()
+        self.lexer.build()
+        self.parser = yacc.yacc(module=self)
+
+    def parse(self, expression, comparison = False):
+        self.comparison = comparison
+        self.parser.parse(expression)
+
+    # Error rule for syntax errors.
+    def p_error(self, t):
+        raise SyntaxError("invalid syntax")
+
+    # Get the tokens from the lexer class
+    tokens = TemporalRasterOperatorLexer.tokens
+
+    def p_relation_only(self, t):
+        # The expression should always return a list of maps.
+        """
+        operator : CLPAREN relation CRPAREN
+                 | CLPAREN relationlist CRPAREN
+        """
+        # Set three operator components.
+        if isinstance(t[2], list):
+            self.relations = t[2]
+        else:
+            self.relations = [t[2]]
+        self.temporal  = None
+        self.function  = None
+
+        t[0] = t[2]
+
+
+    def p_operator(self, t):
+        # The expression should always return a list of maps.
+        """
+        operator : CLPAREN select CRPAREN
+                 | CLPAREN HASH CRPAREN
+                 | CLPAREN arithmetic CRPAREN
+        """
+        # Set three operator components.
+        self.relations = ['equal']
+        self.temporal  = "="
+        self.function  = t[2]
+
+        t[0] = t[2]
+
+    def p_comparison(self, t):
+        # The expression should always return a list of maps.
+        """
+        operator : CLPAREN temporal AND CRPAREN
+                 | CLPAREN temporal OR CRPAREN
+        """
+        # Set three operator components.
+        self.relations = ['equal']
+        self.temporal  = "="
+        if t[2] == t[3]:
+            self.function  = t[2] + t[3]
+        else:
+            raise SyntaxError("syntax error on line %d near '%s'" %
+                                (t.lineno, t.value))
+
+        t[0] = t[2]
+
+    def p_operator_temporal(self, t):
+        # The expression should always return a list of maps.
+        """
+        operator : CLPAREN temporal select CRPAREN
+                 | CLPAREN temporal HASH CRPAREN
+                 | CLPAREN temporal arithmetic CRPAREN
+        """
+        # Set three operator components.
+        self.relations = ['equal']
+        self.temporal = t[2]
+        self.function = t[3]
+
+        t[0] = t[3]
+
+    def p_operator_relation(self, t):
+        # The expression should always return a list of maps.
+        """
+        operator : CLPAREN relation COMMA select CRPAREN
+                 | CLPAREN relationlist COMMA select CRPAREN
+                 | CLPAREN relation COMMA HASH CRPAREN
+                 | CLPAREN relationlist COMMA HASH CRPAREN
+                 | CLPAREN relation COMMA arithmetic CRPAREN
+                 | CLPAREN relationlist COMMA arithmetic CRPAREN
+        """
+        # Set three operator components.
+        if isinstance(t[2], list):
+            self.relations = t[2]
+        else:
+            self.relations = [t[2]]
+        self.temporal  = "="
+        self.function  = t[4]
+
+        t[0] = t[4]
+
+    def p_comparison_relation(self, t):
+        # The expression should always return a list of maps.
+        """
+        operator : CLPAREN relation COMMA temporal AND CRPAREN
+                 | CLPAREN relation COMMA temporal OR CRPAREN
+                 | CLPAREN relationlist COMMA temporal AND CRPAREN
+                 | CLPAREN relationlist COMMA temporal OR CRPAREN
+        """
+        # Set three operator components.
+        if isinstance(t[2], list):
+            self.relations = t[2]
+        else:
+            self.relations = [t[2]]
+        self.temporal  = "="
+        if t[4] == t[5]:
+            self.function  = t[4] + t[5]
+        else:
+            raise SyntaxError("syntax error on line %d near '%s'" %
+                                (t.lineno, t.value))
+
+        t[0] = t[4]
+
+    def p_operator_relation_temporal(self, t):
+        # The expression should always return a list of maps.
+        """
+        operator : CLPAREN relation COMMA temporal select CRPAREN
+                 | CLPAREN relationlist COMMA temporal select CRPAREN
+                 | CLPAREN relation COMMA temporal HASH CRPAREN
+                 | CLPAREN relationlist COMMA temporal HASH CRPAREN
+                 | CLPAREN relation COMMA temporal arithmetic CRPAREN
+                 | CLPAREN relationlist COMMA temporal arithmetic CRPAREN
+        """
+        # Set three operator components.
+        if isinstance(t[2], list):
+            self.relations = t[2]
+        else:
+            self.relations = [t[2]]
+        self.temporal = t[4]
+        self.function = t[5]
+        t[0] = t[5]
+
+    def p_relation(self, t):
+        # The list of relations.
+        """
+        relation : EQUAL
+                 | FOLLOWS
+                 | PRECEDES
+                 | OVERLAPS
+                 | OVERLAPPED
+                 | DURING
+                 | STARTS
+                 | FINISHES
+                 | CONTAINS
+                 | STARTED
+                 | FINISHED
+        """
+        t[0] = t[1]
+
+    def p_over(self, t):
+        # The list of relations.
+        """
+        relation : OVER
+        """
+        over_list = ["overlaps", "overlapped"]
+        t[0] = over_list
+
+    def p_relationlist(self, t):
+        # The list of relations.
+        """
+        relationlist : relation OR relation
+                     | relation OR relationlist
+        """
+        rel_list = []
+        rel_list.append(t[1])
+        if isinstance(t[3], list):
+            rel_list = rel_list + t[3]
+        else:
+            rel_list.append(t[3])
+        t[0] =  rel_list
+
+    def p_temporal_operator(self, t):
+        # The list of relations.
+        """
+        temporal : LEFTREF
+                 | OR
+                 | AND
+                 | ADD
+        """
+        t[0] = t[1]
+
+    def p_select_operator(self, t):
+        # The list of relations.
+        """
+        select : T_SELECT
+               | T_NOT_SELECT
+        """
+        t[0] = t[1]
+
+    def p_arithmetic_operator(self, t):
+        # The list of relations.
+        """
+        arithmetic : MOD
+                   | DIV
+                   | MULT
+                   | ADD
+                   | SUB
+        """
+        t[0] = t[1]
+
+###############################################################################
+
+if __name__ == "__main__":
+    import doctest
+    doctest.testmod()
+

+ 26 - 104
lib/python/temporal/temporal_vector_algebra.py

@@ -419,17 +419,7 @@ for details.
 @endcode
 """
 
-try:
-    import ply.yacc as yacc
-except:
-    pass
-
 import grass.pygrass.modules as pygrass
-import grass.script as grass
-from space_time_datasets import *
-from factory import *
-from open_stds import *
-import copy
 from temporal_vector_operator import *
 from temporal_algebra import *
 
@@ -482,6 +472,8 @@ class TemporalVectorAlgebraLexer(TemporalAlgebraLexer):
             t.type = 'NAME'
         return t
 
+##############################################################################
+
 class TemporalVectorAlgebraParser(TemporalAlgebraParser):
     """The temporal algebra class"""
 
@@ -504,13 +496,14 @@ class TemporalVectorAlgebraParser(TemporalAlgebraParser):
         self.m_mremove = pygrass.Module('g.mremove', quiet=True, run_=False)
         self.m_buffer = pygrass.Module('v.buffer', quiet=True, run_=False)
 
-    def parse(self, expression, stdstype = 'strds', basename = None):
+    def parse(self, expression, basename = None, overwrite = False):
         self.lexer = TemporalVectorAlgebraLexer()
         self.lexer.build()
         self.parser = yacc.yacc(module=self, debug=self.debug)
 
+        self.overwrite = overwrite
         self.count = 0
-        self.stdstype = stdstype
+        self.stdstype = "stvds"
         self.basename = basename
         self.expression = expression
         self.parser.parse(expression)
@@ -613,59 +606,15 @@ class TemporalVectorAlgebraParser(TemporalAlgebraParser):
            @param copy Specifies if the temporal extent of mapB should be
                   copied to mapA
         """
-        returncode = 1
-        if copy:
-            map_extent_temporal = mapB.get_temporal_extent()
-            map_extent_spatial = mapB.get_spatial_extent()
-            # Set initial map extend of new vector map.
-            mapA.set_spatial_extent(map_extent_spatial)
-            mapA.set_temporal_extent(map_extent_temporal)
-            if "cmd_list" in dir(mapB):
-                mapA.cmd_list = mapB.cmd_list
-        else:
-            # Calculate spatial extent for different overlay operations.
-            if bool_op == 'and':
-                overlay_ext = mapA.spatial_intersection(mapB)
-                if overlay_ext != None:
-                    mapA.set_spatial_extent(overlay_ext)
-                else:
-                    returncode = 0
-            elif bool_op in ['or', 'xor']:
-                overlay_ext = mapA.spatial_union(mapB)
-                if overlay_ext != None:
-                    mapA.set_spatial_extent(overlay_ext)
-                else:
-                    returncode = 0
-            elif bool_op == 'disor':
-                overlay_ext = mapA.spatial_disjoint_union(mapB)
-                if overlay_ext != None:
-                    mapA.set_spatial_extent(overlay_ext)
-                else:
-                    returncode = 0
+        returncode = TemporalAlgebraParser.overlay_map_extent(self, mapA, mapB,
+                                                              bool_op, temp_op,
+                                                              copy)
+        if not copy and returncode == 1:
             # Conditional append of command list.
             if "cmd_list" in dir(mapA) and "cmd_list" in dir(mapB):
                 mapA.cmd_list = mapA.cmd_list + mapB.cmd_list
             elif "cmd_list" not in dir(mapA) and "cmd_list" in dir(mapB):
                 mapA.cmd_list = mapB.cmd_list
-            # Calculate temporal extent for different temporal operators.
-            if temp_op == '&':
-                temp_ext = mapA.temporal_intersection(mapB)
-                if temp_ext != None:
-                    mapA.set_temporal_extent(temp_ext)
-                else:
-                    returncode = 0
-            elif temp_op == '|':
-                temp_ext = mapA.temporal_union(mapB)
-                if temp_ext != None:
-                    mapA.set_temporal_extent(temp_ext)
-                else:
-                    returncode = 0
-            elif temp_op == '+':
-                temp_ext = mapA.temporal_disjoint_union(mapB)
-                if temp_ext != None:
-                    mapA.set_temporal_extent(temp_ext)
-                else:
-                    returncode = 0
 
         return(returncode)
 
@@ -688,7 +637,7 @@ class TemporalVectorAlgebraParser(TemporalAlgebraParser):
                     # Check if resultmap names exist in GRASS database.
                     vectorname = self.basename + "_" + str(i)
                     vectormap = VectorDataset(vectorname + "@" + get_current_mapset())
-                    if vectormap.map_exists() and grass.overwrite() == False:
+                    if vectormap.map_exists() and self.overwrite == False:
                         self.msgr.fatal(_("Error vector maps with basename %s exist. "
                                       "Use --o flag to overwrite existing file") \
                                       %(vectorname))
@@ -741,10 +690,10 @@ class TemporalVectorAlgebraParser(TemporalAlgebraParser):
                             newident = self.basename + "_" + str(count)
                             m = copy.deepcopy(self.m_rename)
                             m.inputs["vect"].value = (map_i.get_name(),newident)
-                            m.flags["overwrite"].value = grass.overwrite()
+                            m.flags["overwrite"].value = self.overwrite
                             m.run()
                             #m(vect = (map_i.get_name(),newident), \
-                            #    overwrite = grass.overwrite)
+                            #    overwrite = self.overwrite)
                             map_i.set_id(newident + "@" + mapset)
                             count += 1
                             register_list.append(map_i)
@@ -758,16 +707,16 @@ class TemporalVectorAlgebraParser(TemporalAlgebraParser):
                     resultstds = open_new_space_time_dataset(t[1], self.stdstype, \
                                                                 'absolute', t[1], t[1], \
                                                                 "temporal vector algebra", dbif=dbif,
-                                                                overwrite = grass.overwrite())
+                                                                overwrite = self.overwrite)
                     for map_i in register_list:
                         # Check if modules should be executed from command list.
                         if "cmd_list" in dir(map_i):
                             # Get meta data from grass database.
                             map_i.load()
-                            if map_i.is_in_db(dbif=dbif) and grass.overwrite():
+                            if map_i.is_in_db(dbif=dbif) and self.overwrite:
                                 # Update map in temporal database.
                                 map_i.update_all(dbif=dbif)
-                            elif map_i.is_in_db(dbif=dbif) and grass.overwrite() == False:
+                            elif map_i.is_in_db(dbif=dbif) and self.overwrite == False:
                                 # Raise error if map exists and no overwrite flag is given.
                                 self.msgr.fatal(_("Error vector map %s exist in temporal database. "
                                                   "Use overwrite flag.  : \n%s") \
@@ -789,14 +738,6 @@ class TemporalVectorAlgebraParser(TemporalAlgebraParser):
                 self.remove_intermediate_vector_maps()
             t[0] = register_list
 
-        if self.debug:
-            if isinstance(t[3], list):
-                for map_i in t[3]:
-                    print(map_i.get_id())
-            else:
-                print(t[1] + " = " + str(t[3]))
-            t[0] = t[3]
-
     def p_overlay_operation(self, t):
         """
         expr : stds AND stds
@@ -826,7 +767,7 @@ class TemporalVectorAlgebraParser(TemporalAlgebraParser):
 
         if self.run:
             t[0] = self.create_overlay_operations(maplistA, maplistB, ("EQUAL",), "=", t[2])
-        if self.debug:
+        else:
             t[0] = t[1]
 
     def p_overlay_operation_relation(self, t):
@@ -843,7 +784,7 @@ class TemporalVectorAlgebraParser(TemporalAlgebraParser):
 
         if self.run:
             t[0] = self.create_overlay_operations(maplistA, maplistB, relations, temporal, function)
-        if self.debug:
+        else:
             t[0] = t[1]
 
     def create_overlay_operations(self, maplistA, maplistB, relations, temporal, function):
@@ -875,15 +816,8 @@ class TemporalVectorAlgebraParser(TemporalAlgebraParser):
             resultlist = []
             for map_i in topolist:
                 # Generate an intermediate name for the result map list.
-                name = self.generate_map_name()
-                # Get mapset input.
-                mapset = get_current_mapset()
-                # Check for mapset in given stds input.
-                mapname = name + "@" + mapset
-                # Create new map based on the related map list.
-                map_new = map_i.get_new_instance(mapname)
-                # Set initial map extend of new vector map.
-                self.overlay_map_extent(map_new, map_i, bool_op = opname, copy = True)
+                map_new = self.generate_new_map(base_map=map_i, bool_op=opname,
+                                                copy=True)
                 # Set first input for overlay module.
                 mapainput = map_i.get_id()
                 # Loop over temporal related maps and create overlay modules.
@@ -915,14 +849,14 @@ class TemporalVectorAlgebraParser(TemporalAlgebraParser):
                                 m.inputs["ainput"].value = str(mapainput)
                                 m.inputs["binput"].value = str(mapbinput)
                                 m.outputs["output"].value = name
-                                m.flags["overwrite"].value = grass.overwrite()
+                                m.flags["overwrite"].value = self.overwrite
                             else:
                                 patchinput = str(mapainput) + ',' + str(mapbinput)
                                 m = copy.deepcopy(self.m_patch)
                                 m.run_ = False
                                 m.inputs["input"].value = patchinput
                                 m.outputs["output"].value = name
-                                m.flags["overwrite"].value = grass.overwrite()
+                                m.flags["overwrite"].value = self.overwrite
                             # Conditional append of module command.
                             if "cmd_list" in dir(map_new):
                                 map_new.cmd_list.append(m)
@@ -952,16 +886,9 @@ class TemporalVectorAlgebraParser(TemporalAlgebraParser):
             resultlist = []
 
             for map_i in bufflist:
-                # Generate an intermediate name
-                name = self.generate_map_name()
-                # Get mapset input.
-                mapset = get_current_mapset()
-                # Check for mapset in given stds input.
-                mapname = name + "@" + mapset
-                # Create new map based on the related map list.
-                map_new = map_i.get_new_instance(mapname)
-                # Set initial map extend of new vector map.
-                self.overlay_map_extent(map_new, map_i, copy = True)
+                # Generate an intermediate name for the result map list.
+                map_new = self.generate_new_map(base_map=map_i, bool_op=None,
+                                                copy=True)
                 # Change spatial extent based on buffer size.
                 map_new.spatial_buffer(float(t[5]))
                 # Check buff type.
@@ -976,8 +903,8 @@ class TemporalVectorAlgebraParser(TemporalAlgebraParser):
                 m.inputs["type"].value = buff_type
                 m.inputs["input"].value = str(map_i.get_id())
                 m.inputs["distance"].value = float(t[5])
-                m.outputs["output"].value = name
-                m.flags["overwrite"].value = grass.overwrite()
+                m.outputs["output"].value = map_new.get_name()
+                m.flags["overwrite"].value = self.overwrite
 
                 # Conditional append of module command.
                 if "cmd_list" in dir(map_new):
@@ -988,9 +915,6 @@ class TemporalVectorAlgebraParser(TemporalAlgebraParser):
 
             t[0] = resultlist
 
-        if self.debug:
-            pass
-
     def p_buff_function(self, t):
         """buff_function    : BUFF_POINT
                             | BUFF_LINE
@@ -1008,5 +932,3 @@ class TemporalVectorAlgebraParser(TemporalAlgebraParser):
 if __name__ == "__main__":
     import doctest
     doctest.testmod()
-
-

+ 84 - 0
lib/python/temporal/unittests_temporal_raster3d_algebra.py

@@ -0,0 +1,84 @@
+"""!Unit test to register raster maps with absolute and relative
+   time using tgis.register_maps_in_space_time_dataset()
+
+(C) 2013 by the GRASS Development Team
+This program is free software under the GNU General Public
+License (>=v2). Read the file COPYING that comes with GRASS
+for details.
+
+@author Soeren Gebbert
+"""
+
+import grass.script
+import grass.temporal as tgis
+import unittest
+import datetime
+import os
+
+class TestRegisterFunctions(unittest.TestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        """!Initiate the temporal GIS and set the region
+        """
+        tgis.init(True) # Raise on error instead of exit(1)
+        grass.script.use_temp_region()
+        ret = grass.script.run_command("g.region", n=80.0, s=0.0, e=120.0,
+                                       w=0.0, t=100.0, b=0.0, res=10.0)
+
+        ret += grass.script.run_command("r3.mapcalc", overwrite=True, quiet=True, expression="a1 = 1")
+        ret += grass.script.run_command("r3.mapcalc", overwrite=True, quiet=True, expression="a2 = 2")
+        ret += grass.script.run_command("r3.mapcalc", overwrite=True, quiet=True, expression="a3 = 3")
+        ret += grass.script.run_command("r3.mapcalc", overwrite=True, quiet=True, expression="a4 = 4")
+
+
+        tgis.open_new_space_time_dataset(name="A", type="str3ds", temporaltype="absolute",
+                                         title="A", descr="A", semantic="field", overwrite=True)
+
+        tgis.register_maps_in_space_time_dataset(type="rast3d", name="A", maps="a1,a2,a3,a4",
+                                                 start="2001-01-01", increment="1 day", interval=True)
+
+    def test_temporal_neighbors_1(self):
+        """Simple temporal neighborhood computation test"""
+        tra = tgis.TemporalRaster3DAlgebraParser(run = True, debug = True)
+        tra.parse(expression='D = A[-1] + A[1]',
+                  basename="d", overwrite=True)
+
+        D = tgis.open_old_space_time_dataset("D", type="str3ds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 4)  # 1 + 3
+        self.assertEqual(D.metadata.get_max_max(), 6) # 2 + 4
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 2))
+        self.assertEqual(end, datetime.datetime(2001, 1, 4))
+
+    def test_temporal_neighbors_2(self):
+        """Simple temporal neighborhood computation test"""
+        tra = tgis.TemporalRaster3DAlgebraParser(run = True, debug = True)
+        tra.parse(expression='D = A[0,0,0,-1] + A[0,0,0,1]',
+                  basename="d", overwrite=True)
+
+        D = tgis.open_old_space_time_dataset("D", type="str3ds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 4)  # 1 + 3
+        self.assertEqual(D.metadata.get_max_max(), 6) # 2 + 4
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 2))
+        self.assertEqual(end, datetime.datetime(2001, 1, 4))
+
+    def tearDown(self):
+        ret = grass.script.run_command("t.remove", type="str3ds", flags="rf", input="D", quiet=True)
+
+    @classmethod
+    def tearDownClass(cls):
+        """!Remove the temporary region
+        """
+        ret = grass.script.run_command("t.remove", type="str3ds", flags="rf", input="A", quiet=True)
+        grass.script.del_temp_region()
+
+if __name__ == '__main__':
+    unittest.main()
+
+

+ 282 - 0
lib/python/temporal/unittests_temporal_raster_algebra.py

@@ -0,0 +1,282 @@
+"""!Unit test to register raster maps with absolute and relative
+   time using tgis.register_maps_in_space_time_dataset()
+
+(C) 2013 by the GRASS Development Team
+This program is free software under the GNU General Public
+License (>=v2). Read the file COPYING that comes with GRASS
+for details.
+
+@author Soeren Gebbert
+"""
+
+import grass.script
+import grass.temporal as tgis
+import unittest
+import datetime
+import os
+
+class TestRegisterFunctions(unittest.TestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        """!Initiate the temporal GIS and set the region
+        """
+        tgis.init(True) # Raise on error instead of exit(1)
+        grass.script.use_temp_region()
+        ret = grass.script.run_command("g.region", n=80.0, s=0.0, e=120.0,
+                                       w=0.0, t=1.0, b=0.0, res=10.0)
+
+        ret += grass.script.run_command("r.mapcalc", overwrite=True, quiet=True, expression="a1 = 1")
+        ret += grass.script.run_command("r.mapcalc", overwrite=True, quiet=True, expression="a2 = 2")
+        ret += grass.script.run_command("r.mapcalc", overwrite=True, quiet=True, expression="a3 = 3")
+        ret += grass.script.run_command("r.mapcalc", overwrite=True, quiet=True, expression="a4 = 4")
+        ret += grass.script.run_command("r.mapcalc", overwrite=True, quiet=True, expression="b1 = 5")
+        ret += grass.script.run_command("r.mapcalc", overwrite=True, quiet=True, expression="b2 = 6")
+        ret += grass.script.run_command("r.mapcalc", overwrite=True, quiet=True, expression="c1 = 7")
+
+
+        tgis.open_new_space_time_dataset(name="A", type="strds", temporaltype="absolute",
+                                         title="A", descr="A", semantic="field", overwrite=True)
+        tgis.open_new_space_time_dataset(name="B", type="strds", temporaltype="absolute",
+                                         title="B", descr="B", semantic="field", overwrite=True)
+        tgis.open_new_space_time_dataset(name="C", type="strds", temporaltype="absolute",
+                                         title="B", descr="C", semantic="field", overwrite=True)
+
+        tgis.register_maps_in_space_time_dataset(type="rast", name="A", maps="a1,a2,a3,a4",
+                                                 start="2001-01-01", increment="1 day", interval=True)
+        tgis.register_maps_in_space_time_dataset(type="rast", name="B", maps="b1,b2",
+                                                 start="2001-01-01", increment="2 day", interval=True)
+
+        tgis.register_maps_in_space_time_dataset(type="rast", name="C", maps="c1",
+                                                 start="2001-01-02", increment="2 day", interval=True)
+
+    def test_simple_arith_if_1(self):
+        """Simple arithmetic test with if condition"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='D = if({equal}, start_date() >= "2001-01-02", A + A)', basename="d", overwrite=True)
+
+        D = tgis.open_old_space_time_dataset("D", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 3)
+        self.assertEqual(D.metadata.get_min_min(), 4)
+        self.assertEqual(D.metadata.get_max_max(), 8)
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 2))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+
+    def test_simple_arith_if_2(self):
+        """Simple arithmetic test with if condition"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='D = if({equal}, A#A == 1, A - A)', basename="d", overwrite=True)
+
+        D = tgis.open_old_space_time_dataset("D", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 4)
+        self.assertEqual(D.metadata.get_min_min(), 0)
+        self.assertEqual(D.metadata.get_max_max(), 0)
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+
+    def test_complex_arith_if_1(self):
+        """Complex arithmetic test with if condition"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='D = if(start_date() < "2001-01-03" && A#A == 1, A{starts,=+}C, A{finishes,=+}C)', \
+                  basename="d", overwrite=True)
+
+        D = tgis.open_old_space_time_dataset("D", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 9)  # 2 + 7 a2 + c1
+        self.assertEqual(D.metadata.get_max_max(), 10) # 3 + 7 a3 + c1
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 2))
+        self.assertEqual(end, datetime.datetime(2001, 1, 4))
+
+    def test_simple_arith_1(self):
+        """Simple arithmetic test"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression="D = A {equal,*} A {equal,+} A", basename="d", overwrite=True)
+
+        D = tgis.open_old_space_time_dataset("D", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 4)
+        self.assertEqual(D.metadata.get_min_min(), 2)  # 1*1 + 1
+        self.assertEqual(D.metadata.get_max_max(), 20) # 4*4 + 4
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+
+    def test_simple_arith_2(self):
+        """Simple arithmetic test that creates an empty strds"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression="D = A {during,*} A {during,+} A", basename="d", overwrite=True)
+        D = tgis.open_old_space_time_dataset("D", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 0)
+
+    def test_simple_arith_3(self):
+        """Simple arithmetic test"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression="D = A / A + A*A/A", basename="d", overwrite=True)
+
+        D = tgis.open_old_space_time_dataset("D", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 4)
+        self.assertEqual(D.metadata.get_min_min(), 2) # 1/1 + 1*1/1
+        self.assertEqual(D.metadata.get_max_max(), 5) # 4/4 + 4*4/4
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+
+    def test_temporal_intersection_1(self):
+        """Simple temporal intersection test"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression="D = A {equal,&+} B", basename="d", overwrite=True)
+        D = tgis.open_old_space_time_dataset("D", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 0)
+
+    def test_temporal_intersection_2(self):
+        """Simple temporal intersection test"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression="D = A {during,&+} B", basename="d", overwrite=True)
+
+        D = tgis.open_old_space_time_dataset("D", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 4)
+        self.assertEqual(D.metadata.get_min_min(), 6) # 1 + 5
+        self.assertEqual(D.metadata.get_max_max(), 10) # 4 + 6
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+
+    def test_temporal_intersection_3(self):
+        """Simple temporal intersection test"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression="D = A {starts,&+} B", basename="d", overwrite=True)
+
+        D = tgis.open_old_space_time_dataset("D", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 6) # 1 + 5
+        self.assertEqual(D.metadata.get_max_max(), 9) # 3 + 6
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 4))
+
+    def test_temporal_intersection_4(self):
+        """Simple temporal intersection test"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression="D = A {finishes,&+} B", basename="d", overwrite=True)
+
+        D = tgis.open_old_space_time_dataset("D", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 7)  # 2 + 5
+        self.assertEqual(D.metadata.get_max_max(), 10) # 4 + 6
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 2))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+
+    def test_temporal_intersection_5(self):
+        """Simple temporal intersection test"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression="D = A {starts|finishes,&+} B", basename="d", overwrite=True)
+
+        D = tgis.open_old_space_time_dataset("D", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 4)
+        self.assertEqual(D.metadata.get_min_min(), 6)  # 1 + 5
+        self.assertEqual(D.metadata.get_max_max(), 10) # 4 + 6
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+
+    def test_temporal_intersection_6(self):
+        """Simple temporal intersection test"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression="D = B {overlaps,|+} C", basename="d", overwrite=True)
+
+        D = tgis.open_old_space_time_dataset("D", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 1)
+        self.assertEqual(D.metadata.get_min_min(), 12) # 5 + 7
+        self.assertEqual(D.metadata.get_max_max(), 12) # 5 + 7
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 4))
+
+    def test_temporal_intersection_7(self):
+        """Simple temporal intersection test"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression="D = B {overlapped,|+} C", basename="d", overwrite=True)
+
+        D = tgis.open_old_space_time_dataset("D", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 1)
+        self.assertEqual(D.metadata.get_min_min(), 13) # 6 + 7
+        self.assertEqual(D.metadata.get_max_max(), 13) # 6 + 7
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 2))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+
+    def test_temporal_intersection_8(self):
+        """Simple temporal intersection test"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='D = A {during,=+} buff_t(C, "1 day") ',
+                  basename="d", overwrite=True)
+
+        D = tgis.open_old_space_time_dataset("D", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 4)
+        self.assertEqual(D.metadata.get_min_min(), 8)  # 1 + 7  a1 + c1
+        self.assertEqual(D.metadata.get_max_max(), 11) # 4 + 7  a4 + c1
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+
+    def test_temporal_neighbors_1(self):
+        """Simple temporal neighborhood computation test"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='D = A[-1] + A[1]',
+                  basename="d", overwrite=True)
+
+        D = tgis.open_old_space_time_dataset("D", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 4)  # 1 + 3
+        self.assertEqual(D.metadata.get_max_max(), 6) # 2 + 4
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 2))
+        self.assertEqual(end, datetime.datetime(2001, 1, 4))
+
+    def test_temporal_neighbors_2(self):
+        """Simple temporal neighborhood computation test"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='D = A[0,0,-1] + A[0,0,1]',
+                  basename="d", overwrite=True)
+
+        D = tgis.open_old_space_time_dataset("D", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 4)  # 1 + 3
+        self.assertEqual(D.metadata.get_max_max(), 6) # 2 + 4
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 2))
+        self.assertEqual(end, datetime.datetime(2001, 1, 4))
+
+    def tearDown(self):
+        ret = grass.script.run_command("t.remove", flags="rf", input="D", quiet=True)
+
+    @classmethod
+    def tearDownClass(cls):
+        """!Remove the temporary region
+        """
+        ret = grass.script.run_command("t.remove", flags="rf", input="A,B,C", quiet=True)
+        grass.script.del_temp_region()
+
+if __name__ == '__main__':
+    unittest.main()
+
+