[GRASS-SVN] r56596 - in grass/trunk: lib/python/temporal temporal/t.rast.aggregate.ds temporal/t.rast.to.rast3 temporal/t.vect.observe.strds

svn_grass at osgeo.org svn_grass at osgeo.org
Wed Jun 5 01:36:44 PDT 2013


Author: huhabla
Date: 2013-06-05 01:36:44 -0700 (Wed, 05 Jun 2013)
New Revision: 56596

Modified:
   grass/trunk/lib/python/temporal/abstract_dataset.py
   grass/trunk/lib/python/temporal/abstract_map_dataset.py
   grass/trunk/lib/python/temporal/abstract_space_time_dataset.py
   grass/trunk/lib/python/temporal/list.py
   grass/trunk/lib/python/temporal/sampling.py
   grass/trunk/lib/python/temporal/space_time_datasets.py
   grass/trunk/lib/python/temporal/spatial_extent.py
   grass/trunk/lib/python/temporal/spatio_temporal_relationships.py
   grass/trunk/lib/python/temporal/stds_export.py
   grass/trunk/lib/python/temporal/temporal_extent.py
   grass/trunk/lib/python/temporal/temporal_granularity.py
   grass/trunk/lib/python/temporal/unit_tests.py
   grass/trunk/temporal/t.rast.aggregate.ds/t.rast.aggregate.ds.py
   grass/trunk/temporal/t.rast.to.rast3/t.rast.to.rast3.py
   grass/trunk/temporal/t.vect.observe.strds/test.t.vect.observe.strds.sh
Log:
Added spatial and temporal extent intersection, union and disjoint union. Renamed some functions.


Modified: grass/trunk/lib/python/temporal/abstract_dataset.py
===================================================================
--- grass/trunk/lib/python/temporal/abstract_dataset.py	2013-06-04 19:31:49 UTC (rev 56595)
+++ grass/trunk/lib/python/temporal/abstract_dataset.py	2013-06-05 08:36:44 UTC (rev 56596)
@@ -170,9 +170,34 @@
            @param dataset The abstract dataset to check spatial overlapping
            @return True if self and the provided dataset spatial overlap
         """
+        raise ImplementationError("This method must be implemented in the subclasses")
 
+    def spatial_intersection(self, dataset):
+        """!Return the spatial intersection as spatial_extent 
+           object or None in case no intersection was found.
+           
+           @param dataset The abstract dataset to intersect with
+           @return The intersection spatial extent
+        """
         raise ImplementationError("This method must be implemented in the subclasses")
 
+    def spatial_union(self, dataset):
+        """!Return the spatial union as spatial_extent 
+           object or None in case the extents does not overlap or meet.
+       
+           @param dataset The abstract dataset to create a union with
+           @return The union spatial extent
+        """
+        raise ImplementationError("This method must be implemented in the subclasses")
+    
+    def spatial_disjoint_union(self, dataset):
+        """!Return the spatial union as spatial_extent object.
+       
+           @param dataset The abstract dataset to create a union with
+           @return The union spatial extent
+        """
+        raise ImplementationError("This method must be implemented in the subclasses")
+    
     def spatial_relation(self, dataset):
         """!Return the spatial relationship between self and dataset
         
@@ -196,10 +221,7 @@
 
     def set_id(self, ident):
         self.base.set_id(ident)
-        if self.is_time_absolute():
-            self.absolute_time.set_id(ident)
-        if self.is_time_relative():
-            self.relative_time.set_id(ident)
+        self.temporal_extent.set_id(ident)
         self.spatial_extent.set_id(ident)
         self.metadata.set_id(ident)
 
@@ -221,7 +243,7 @@
         """
         return self.base.get_mapset()
 
-    def get_valid_time(self):
+    def get_temporal_extent_as_tuple(self):
         """!Returns a tuple of the valid start and end time
         
            Start and end time can be either of type datetime or of type integer,
@@ -229,17 +251,8 @@
            
            @return A tuple of (start_time, end_time)
         """
-
-        start = None
-        end = None
-
-        if self.is_time_absolute():
-            start = self.absolute_time.get_start_time()
-            end = self.absolute_time.get_end_time()
-        if self.is_time_relative():
-            start = self.relative_time.get_start_time()
-            end = self.relative_time.get_end_time()
-
+        start = self.temporal_extent.get_start_time()
+        end = self.temporal_extent.get_end_time()
         return (start, end)
 
     def get_absolute_time(self):
@@ -309,14 +322,14 @@
         """
         return self.base.get_ttype()
 
-    def get_spatial_extent(self):
+    def get_spatial_extent_as_tuple(self):
         """!Return the spatial extent as tuple
         
            Top and bottom are set to 0 in case of a two dimensional spatial extent.
            
            @return A the spatial extent as tuple (north, south, east, west, top, bottom) 
         """
-        return self.spatial_extent.get_spatial_extent()
+        return self.spatial_extent.get_spatial_extent_as_tuple()
 
     def select(self, dbif=None):
         """!Select temporal dataset entry from database and fill 
@@ -332,10 +345,7 @@
         dbif, connected = init_dbif(dbif)
 
         self.base.select(dbif)
-        if self.is_time_absolute():
-            self.absolute_time.select(dbif)
-        if self.is_time_relative():
-            self.relative_time.select(dbif)
+        self.temporal_extent.select(dbif)
         self.spatial_extent.select(dbif)
         self.metadata.select(dbif)
 
@@ -368,12 +378,7 @@
 
         # Build the INSERT SQL statement
         statement = self.base.get_insert_statement_mogrified(dbif)
-        if self.is_time_absolute():
-            statement += self.absolute_time.get_insert_statement_mogrified(
-                dbif)
-        if self.is_time_relative():
-            statement += self.relative_time.get_insert_statement_mogrified(
-                dbif)
+        statement += self.temporal_extent.get_insert_statement_mogrified(dbif)
         statement += self.spatial_extent.get_insert_statement_mogrified(dbif)
         statement += self.metadata.get_insert_statement_mogrified(dbif)
         
@@ -403,12 +408,8 @@
 
         # Build the UPDATE SQL statement
         statement = self.base.get_update_statement_mogrified(dbif, ident)
-        if self.is_time_absolute():
-            statement += self.absolute_time.get_update_statement_mogrified(
-                dbif, ident)
-        if self.is_time_relative():
-            statement += self.relative_time.get_update_statement_mogrified(
-                dbif, ident)
+        statement += self.temporal_extent.get_update_statement_mogrified(dbif, 
+                                                                         ident)
         statement += self.spatial_extent.get_update_statement_mogrified(dbif, 
                                                                         ident)
         statement += self.metadata.get_update_statement_mogrified(dbif, ident)
@@ -439,12 +440,8 @@
 
         # Build the UPDATE SQL statement
         statement = self.base.get_update_all_statement_mogrified(dbif, ident)
-        if self.is_time_absolute():
-            statement += self.absolute_time.get_update_all_statement_mogrified(
-                dbif, ident)
-        if self.is_time_relative():
-            statement += self.relative_time.get_update_all_statement_mogrified(
-                dbif, ident)
+        statement += self.temporal_extent.get_update_all_statement_mogrified(dbif, 
+                                                                             ident)
         statement += self.spatial_extent.get_update_all_statement_mogrified(
             dbif, ident)
         statement += self.metadata.get_update_all_statement_mogrified(dbif, ident)
@@ -486,32 +483,55 @@
             return self.base.get_ttype() == "relative"
         else:
             return None
+    
+    def _get_temporal_extent(self):
+        """!Return the temporal extent of the correct internal type
+        """
+        if self.is_time_absolute():
+            return self.absolute_time
+        if self.is_time_relative():
+            return self.relative_time
+        return None
+    
+    temporal_extent = property(fget=_get_temporal_extent)
 
     def temporal_relation(self, dataset):
         """!Return the temporal relation of self and the provided dataset
         
             @return The temporal relation as string
         """
-        if self.is_time_absolute() and dataset.is_time_absolute():
-            return self.absolute_time.temporal_relation(dataset.absolute_time)
-        if self.is_time_relative() and dataset.is_time_relative():
-            return self.relative_time.temporal_relation(dataset.relative_time)
-        return None
-
+        return self.temporal_extent.temporal_relation(dataset.temporal_extent)
+    
     def temporal_intersection(self, dataset):
-        """!Intersect self with the provided datasetand
+        """!Intersect self with the provided dataset and
            return a new temporal extent with the new start and end time
            
            @param dataset The abstract dataset to temporal intersect with
            @return The new temporal extent with start and end time, 
                    or None in case of no intersection
         """
-        if self.is_time_absolute() and dataset.is_time_absolute():
-            return self.absolute_time.intersect(dataset.absolute_time)
-        if self.is_time_relative() and dataset.is_time_relative():
-            return self.relative_time.intersect(dataset.relative_time)
-        return None
+        return self.temporal_extent.intersect(dataset.temporal_extent)
         
+    def temporal_union(self, dataset):
+        """!Creates a union with the provided dataset and
+           return a new temporal extent with the new start and end time.
+           
+           @param dataset The abstract dataset to create temporal union with
+           @return The new temporal extent with start and end time, 
+                   or None in case of no intersection
+        """
+        return self.temporal_extent.union(dataset.temporal_extent)
+        
+    def temporal_disjoint_union(self, dataset):
+        """!Creates a union with the provided dataset and
+           return a new temporal extent with the new start and end time.
+           
+           @param dataset The abstract dataset to create temporal union with
+           @return The new temporal extent with start and end time, 
+                   or None in case of no intersection
+        """
+        return self.temporal_extent.disjoint_union(dataset.temporal_extent)
+        
 ###############################################################################
 
 class AbstractDatasetComparisonKeyStartTime(object):
@@ -531,33 +551,33 @@
         self.obj = obj
 
     def __lt__(self, other):
-        startA, endA = self.obj.get_valid_time()
-        startB, endB = other.obj.get_valid_time()
+        startA, endA = self.obj.get_temporal_extent_as_tuple()
+        startB, endB = other.obj.get_temporal_extent_as_tuple()
         return startA < startB
 
     def __gt__(self, other):
-        startA, endA = self.obj.get_valid_time()
-        startB, endB = other.obj.get_valid_time()
+        startA, endA = self.obj.get_temporal_extent_as_tuple()
+        startB, endB = other.obj.get_temporal_extent_as_tuple()
         return startA > startB
 
     def __eq__(self, other):
-        startA, endA = self.obj.get_valid_time()
-        startB, endB = other.obj.get_valid_time()
+        startA, endA = self.obj.get_temporal_extent_as_tuple()
+        startB, endB = other.obj.get_temporal_extent_as_tuple()
         return startA == startB
 
     def __le__(self, other):
-        startA, endA = self.obj.get_valid_time()
-        startB, endB = other.obj.get_valid_time()
+        startA, endA = self.obj.get_temporal_extent_as_tuple()
+        startB, endB = other.obj.get_temporal_extent_as_tuple()
         return startA <= startB
 
     def __ge__(self, other):
-        startA, endA = self.obj.get_valid_time()
-        startB, endB = other.obj.get_valid_time()
+        startA, endA = self.obj.get_temporal_extent_as_tuple()
+        startB, endB = other.obj.get_temporal_extent_as_tuple()
         return startA >= startB
 
     def __ne__(self, other):
-        startA, endA = self.obj.get_valid_time()
-        startB, endB = other.obj.get_valid_time()
+        startA, endA = self.obj.get_temporal_extent_as_tuple()
+        startB, endB = other.obj.get_temporal_extent_as_tuple()
         return startA != startB
 
 ###############################################################################
@@ -579,33 +599,33 @@
         self.obj = obj
 
     def __lt__(self, other):
-        startA, endA = self.obj.get_valid_time()
-        startB, endB = other.obj.get_valid_time()
+        startA, endA = self.obj.get_temporal_extent_as_tuple()
+        startB, endB = other.obj.get_temporal_extent_as_tuple()
         return endA < endB
 
     def __gt__(self, other):
-        startA, endA = self.obj.get_valid_time()
-        startB, endB = other.obj.get_valid_time()
+        startA, endA = self.obj.get_temporal_extent_as_tuple()
+        startB, endB = other.obj.get_temporal_extent_as_tuple()
         return endA > endB
 
     def __eq__(self, other):
-        startA, endA = self.obj.get_valid_time()
-        startB, endB = other.obj.get_valid_time()
+        startA, endA = self.obj.get_temporal_extent_as_tuple()
+        startB, endB = other.obj.get_temporal_extent_as_tuple()
         return endA == endB
 
     def __le__(self, other):
-        startA, endA = self.obj.get_valid_time()
-        startB, endB = other.obj.get_valid_time()
+        startA, endA = self.obj.get_temporal_extent_as_tuple()
+        startB, endB = other.obj.get_temporal_extent_as_tuple()
         return endA <= endB
 
     def __ge__(self, other):
-        startA, endA = self.obj.get_valid_time()
-        startB, endB = other.obj.get_valid_time()
+        startA, endA = self.obj.get_temporal_extent_as_tuple()
+        startB, endB = other.obj.get_temporal_extent_as_tuple()
         return endA >= endB
 
     def __ne__(self, other):
-        startA, endA = self.obj.get_valid_time()
-        startB, endB = other.obj.get_valid_time()
+        startA, endA = self.obj.get_temporal_extent_as_tuple()
+        startB, endB = other.obj.get_temporal_extent_as_tuple()
         return endA != endB
 
 ###############################################################################

Modified: grass/trunk/lib/python/temporal/abstract_map_dataset.py
===================================================================
--- grass/trunk/lib/python/temporal/abstract_map_dataset.py	2013-06-04 19:31:49 UTC (rev 56595)
+++ grass/trunk/lib/python/temporal/abstract_map_dataset.py	2013-06-05 08:36:44 UTC (rev 56596)
@@ -219,10 +219,7 @@
             print " +-------------------- Vector Dataset ----------------------------------------+"
         print " |                                                                            |"
         self.base.print_info()
-        if self.is_time_absolute():
-            self.absolute_time.print_info()
-        if self.is_time_relative():
-            self.relative_time.print_info()
+        self.temporal_extent.print_info()
         if self.is_topology_build():
             self.print_topology_info()
         self.spatial_extent.print_info()
@@ -246,10 +243,7 @@
     def print_shell_info(self):
         """!Print information about this object in shell style"""
         self.base.print_shell_info()
-        if self.is_time_absolute():
-            self.absolute_time.print_shell_info()
-        if self.is_time_relative():
-            self.relative_time.print_shell_info()
+        self.temporal_extent.print_shell_info()
         self.spatial_extent.print_shell_info()
         self.metadata.print_shell_info()
         datasets = self.get_registered_datasets()
@@ -494,8 +488,8 @@
         self.spatial_extent.set_spatial_extent(
             north, south, east, west, top, bottom)
 
-    def check_valid_time(self):
-        """!Check for correct valid time"""
+    def check_for_correct_time(self):
+        """!Check for correct time"""
         if self.is_time_absolute():
             start, end, tz = self.get_absolute_time()
         else:

Modified: grass/trunk/lib/python/temporal/abstract_space_time_dataset.py
===================================================================
--- grass/trunk/lib/python/temporal/abstract_space_time_dataset.py	2013-06-04 19:31:49 UTC (rev 56595)
+++ grass/trunk/lib/python/temporal/abstract_space_time_dataset.py	2013-06-05 08:36:44 UTC (rev 56596)
@@ -84,10 +84,7 @@
     def print_self(self):
         """!Print the content of the internal structure to stdout"""
         self.base.print_self()
-        if self.is_time_absolute():
-            self.absolute_time.print_self()
-        if self.is_time_relative():
-            self.relative_time.print_self()
+        self.temporal_extent.print_self()
         self.spatial_extent.print_self()
         self.metadata.print_self()
 
@@ -108,10 +105,7 @@
             print " +-------------------- Space Time Vector Dataset -----------------------------+"
         print " |                                                                            |"
         self.base.print_info()
-        if self.is_time_absolute():
-            self.absolute_time.print_info()
-        if self.is_time_relative():
-            self.relative_time.print_info()
+        self.temporal_extent.print_info()
         self.spatial_extent.print_info()
         self.metadata.print_info()
         print " +----------------------------------------------------------------------------+"
@@ -119,10 +113,7 @@
     def print_shell_info(self):
         """!Print information about this class in shell style"""
         self.base.print_shell_info()
-        if self.is_time_absolute():
-            self.absolute_time.print_shell_info()
-        if self.is_time_relative():
-            self.relative_time.print_shell_info()
+        self.temporal_extent.print_shell_info()
         self.spatial_extent.print_shell_info()
         self.metadata.print_shell_info()
 
@@ -241,15 +232,8 @@
            @return The granularity 
         """
 
-        temporal_type = self.get_temporal_type()
+        return self.temporal_extent.get_granularity()
 
-        if temporal_type == "absolute":
-            granularity = self.absolute_time.get_granularity()
-        elif temporal_type == "relative":
-            granularity = self.relative_time.get_granularity()
-
-        return granularity
-
     def set_granularity(self, granularity):
         """!Set the granularity
         
@@ -275,12 +259,12 @@
 
         if temporal_type == "absolute":
             self.set_time_to_absolute()
-            self.absolute_time.set_granularity(granularity)
         elif temporal_type == "relative":
             self.set_time_to_relative()
-            self.relative_time.set_granularity(granularity)
         else:
             core.fatal(_("Unknown temporal type \"%s\"") % (temporal_type))
+            
+        self.temporal_extent.set_granularity(granularity)
 
     def set_relative_time_unit(self, unit):
         """!Set the relative time unit which may be of type: 
@@ -305,15 +289,8 @@
     def get_map_time(self):
         """!Return the type of the map time, interval, point, mixed or invalid"""
 
-        temporal_type = self.get_temporal_type()
+        return self.temporal_extent.get_map_time()
 
-        if temporal_type == "absolute":
-            map_time = self.absolute_time.get_map_time()
-        elif temporal_type == "relative":
-            map_time = self.relative_time.get_map_time()
-
-        return map_time
-
     def count_temporal_types(self, maps=None, dbif=None):
         """!Return the temporal type of the registered maps as dictionary
 
@@ -666,7 +643,7 @@
             # Read the spatial extent
             if spatial:
                 granule.spatial_extent.select(dbif)
-            start, end = granule.get_valid_time()
+            start, end = granule.get_temporal_extent_as_tuple()
 
             where = create_temporal_relation_sql_where_statement(
                 start, end, use_start,
@@ -762,7 +739,7 @@
         if not check:
             core.fatal(_("Wrong granularity: \"%s\"") % str(gran))
 
-        start, end = self.get_valid_time()
+        start, end = self.get_temporal_extent_as_tuple()
         
         if start is None or end is None:
             return None
@@ -932,8 +909,8 @@
                 if i < len(maps) - 1:
                     relation = maps[i + 1].temporal_relation(maps[i])
                     if relation == "after":
-                        start1, end1 = maps[i].get_valid_time()
-                        start2, end2 = maps[i + 1].get_valid_time()
+                        start1, end1 = maps[i].get_temporal_extent_as_tuple()
+                        start2, end2 = maps[i + 1].get_temporal_extent_as_tuple()
                         end = start2
                         if end1 is not None:
                             start = end1
@@ -1133,7 +1110,7 @@
         # in the middle of the update process when the increment
         # results in wrong number of days in a month
         for map in maps:
-            start, end = map.get_valid_time()
+            start, end = map.get_temporal_extent_as_tuple()
             
             if self.is_time_absolute():
                 start = increment_datetime_by_string(start, gran)
@@ -1172,8 +1149,8 @@
         date_list = []
         
         for i in range(len(maps) - 1):
-            start, end = maps[i].get_valid_time()
-            start_next, end = maps[i + 1].get_valid_time()
+            start, end = maps[i].get_temporal_extent_as_tuple()
+            start_next, end = maps[i + 1].get_temporal_extent_as_tuple()
             
             # Maps with equal time stamps can not be snapped
             if start != start_next:
@@ -1183,7 +1160,7 @@
                 date_list.append((start, end))
         
         # Last map
-        start, end = maps[-1].get_valid_time()
+        start, end = maps[-1].get_temporal_extent_as_tuple()
         # We increment the start time with the dataset 
         # granularity if the end time is None
         if end is None:
@@ -1391,7 +1368,7 @@
         # First select all data from the database
         map.select(dbif)
 
-        if not map.check_valid_time():
+        if not map.check_for_correct_time():
             if map.get_layer():
                 core.fatal(_("Map <%s> with layer %s has invalid time")
                            % (map.get_map_id(), map.get_layer()))
@@ -1874,26 +1851,15 @@
             gran = None
 
         # Set the map time type and update the time objects
-        if self.is_time_absolute():
-            self.absolute_time.select(dbif)
-            self.metadata.select(dbif)
-            if self.metadata.get_number_of_maps() > 0:
-                self.absolute_time.set_map_time(map_time)
-                self.absolute_time.set_granularity(gran)
-            else:
-                self.absolute_time.set_map_time(None)
-                self.absolute_time.set_granularity(None)
-            self.absolute_time.update_all(dbif)
+        self.temporal_extent.select(dbif)
+        self.metadata.select(dbif)
+        if self.metadata.get_number_of_maps() > 0:
+            self.temporal_extent.set_map_time(map_time)
+            self.temporal_extent.set_granularity(gran)
         else:
-            self.relative_time.select(dbif)
-            self.metadata.select(dbif)
-            if self.metadata.get_number_of_maps() > 0:
-                self.relative_time.set_map_time(map_time)
-                self.relative_time.set_granularity(gran)
-            else:
-                self.relative_time.set_map_time(None)
-                self.relative_time.set_granularity(None)
-            self.relative_time.update_all(dbif)
+            self.temporal_extent.set_map_time(None)
+            self.temporal_extent.set_granularity(None)
+        self.temporal_extent.update_all(dbif)
 
         if connected:
             dbif.close()

Modified: grass/trunk/lib/python/temporal/list.py
===================================================================
--- grass/trunk/lib/python/temporal/list.py	2013-06-04 19:31:49 UTC (rev 56595)
+++ grass/trunk/lib/python/temporal/list.py	2013-06-05 08:36:44 UTC (rev 56596)
@@ -105,12 +105,12 @@
 
             if isinstance(maps[0], list):
                 if len(maps[0]) > 0:
-                    first_time, dummy = maps[0][0].get_valid_time()
+                    first_time, dummy = maps[0][0].get_temporal_extent_as_tuple()
                 else:
                     core.warning(_("Empty map list."))
                     return
             else:
-                first_time, dummy = maps[0].get_valid_time()
+                first_time, dummy = maps[0].get_temporal_extent_as_tuple()
 
             for mymap in maps:
 
@@ -122,7 +122,7 @@
                 else:
                     map = mymap
 
-                start, end = map.get_valid_time()
+                start, end = map.get_temporal_extent_as_tuple()
                 if end:
                     delta = end - start
                 else:

Modified: grass/trunk/lib/python/temporal/sampling.py
===================================================================
--- grass/trunk/lib/python/temporal/sampling.py	2013-06-04 19:31:49 UTC (rev 56595)
+++ grass/trunk/lib/python/temporal/sampling.py	2013-06-05 08:36:44 UTC (rev 56596)
@@ -122,7 +122,7 @@
             string += "%s" % ("distance_from_begin")
             print string
 
-        first_time, dummy = mapmatrizes[0][0]["granule"].get_valid_time()
+        first_time, dummy = mapmatrizes[0][0]["granule"].get_temporal_extent_as_tuple()
 
         for i in range(len(mapmatrizes[0])):
             mapname_list = []
@@ -141,7 +141,7 @@
             entry = mapmatrizes[0][i]
             map = entry["granule"]
 
-            start, end = map.get_valid_time()
+            start, end = map.get_temporal_extent_as_tuple()
             if end:
                 delta = end - start
             else:

Modified: grass/trunk/lib/python/temporal/space_time_datasets.py
===================================================================
--- grass/trunk/lib/python/temporal/space_time_datasets.py	2013-06-04 19:31:49 UTC (rev 56595)
+++ grass/trunk/lib/python/temporal/space_time_datasets.py	2013-06-05 08:36:44 UTC (rev 56596)
@@ -97,7 +97,7 @@
         >>> rmap.get_stds_register()
         >>> rmap.get_absolute_time()
         (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2012, 1, 1, 0, 0), None)
-        >>> rmap.get_valid_time()
+        >>> rmap.get_temporal_extent_as_tuple()
         (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2012, 1, 1, 0, 0))
         >>> rmap.get_name()
         'strds_map_test_case'
@@ -105,7 +105,7 @@
         True
         >>> rmap.get_temporal_type()
         'absolute'
-        >>> rmap.get_spatial_extent()
+        >>> rmap.get_spatial_extent_as_tuple()
         (80.0, 0.0, 120.0, 0.0, 0.0, 0.0)
         >>> rmap.is_time_absolute()
         True
@@ -146,14 +146,38 @@
 
     def spatial_overlapping(self, dataset):
         """!Return True if the spatial extents 2d overlap"""
-
         return self.spatial_extent.overlapping_2d(dataset.spatial_extent)
 
     def spatial_relation(self, dataset):
         """!Return the two dimensional spatial relation"""
-
         return self.spatial_extent.spatial_relation_2d(dataset.spatial_extent)
 
+    def spatial_intersection(self, dataset):
+        """!Return the two dimensional intersection as spatial_extent 
+           object or None in case no intersection was found.
+           
+           @param dataset The abstract dataset to intersect with
+           @return The intersection spatial extent or None
+        """
+        return self.spatial_extent.intersect_2d(dataset.spatial_extent)
+
+    def spatial_union(self, dataset):
+        """!Return the two dimensional union as spatial_extent 
+           object or None in case the extents does not overlap or meet.
+       
+           @param dataset The abstract dataset to create a union with
+           @return The union spatial extent or None
+        """
+        return self.spatial_extent.union_2d(dataset.spatial_extent)
+    
+    def spatial_disjoint_union(self, dataset):
+        """!Return the two dimensional union as spatial_extent object.
+       
+           @param dataset The abstract dataset to create a union with
+           @return The union spatial extent
+        """
+        return self.spatial_extent.disjoint_union_2d(dataset.spatial_extent)
+    
     def get_np_array(self):
         """!Return this raster map as memmap numpy style array to access the raster
            values in numpy style without loading the whole map in the RAM.
@@ -382,7 +406,6 @@
 
     def spatial_overlapping(self, dataset):
         """!Return True if the spatial extents overlap"""
-
         if self.get_type() == dataset.get_type() or dataset.get_type() == "str3ds":
             return self.spatial_extent.overlapping(dataset.spatial_extent)
         else:
@@ -390,12 +413,46 @@
 
     def spatial_relation(self, dataset):
         """!Return the two or three dimensional spatial relation"""
-
         if self.get_type() == dataset.get_type() or dataset.get_type() == "str3ds":
             return self.spatial_extent.spatial_relation(dataset.spatial_extent)
         else:
             return self.spatial_extent.spatial_relation_2d(dataset.spatial_extent)
 
+    def spatial_intersection(self, dataset):
+        """!Return the three or two dimensional intersection as spatial_extent 
+           object or None in case no intersection was found.
+           
+           @param dataset The abstract dataset to intersect with
+           @return The intersection spatial extent or None
+        """
+        if self.get_type() == dataset.get_type() or dataset.get_type() == "str3ds":
+            return self.spatial_extent.intersect(dataset.spatial_extent)
+        else:
+            return self.spatial_extent.intersect_2d(dataset.spatial_extent)
+
+    def spatial_union(self, dataset):
+        """!Return the three or two dimensional union as spatial_extent 
+           object or None in case the extents does not overlap or meet.
+       
+           @param dataset The abstract dataset to create a union with
+           @return The union spatial extent or None
+        """
+        if self.get_type() == dataset.get_type() or dataset.get_type() == "str3ds":
+            return self.spatial_extent.union(dataset.spatial_extent)
+        else:
+            return self.spatial_extent.union_2d(dataset.spatial_extent)
+        
+    def spatial_disjoint_union(self, dataset):
+        """!Return the three or two dimensional union as spatial_extent object.
+       
+           @param dataset The abstract dataset to create a union with
+           @return The union spatial extent
+        """
+        if self.get_type() == dataset.get_type() or dataset.get_type() == "str3ds":
+            return self.spatial_extent.disjoint_union(dataset.spatial_extent)
+        else:
+            return self.spatial_extent.disjoint_union_2d(dataset.spatial_extent)
+    
     def get_np_array(self):
         """!Return this 3D raster map as memmap numpy style array to access the 3D raster
            values in numpy style without loading the whole map in the RAM.
@@ -638,6 +695,32 @@
 
         return self.spatial_extent.spatial_relation_2d(dataset.spatial_extent)
 
+    def spatial_intersection(self, dataset):
+        """!Return the two dimensional intersection as spatial_extent 
+           object or None in case no intersection was found.
+           
+           @param dataset The abstract dataset to intersect with
+           @return The intersection spatial extent or None
+        """
+        return self.spatial_extent.intersect_2d(dataset.spatial_extent)
+
+    def spatial_union(self, dataset):
+        """!Return the two dimensional union as spatial_extent 
+           object or None in case the extents does not overlap or meet.
+       
+           @param dataset The abstract dataset to create a union with
+           @return The union spatial extent or None
+        """
+        return self.spatial_extent.union_2d(dataset.spatial_extent)
+        
+    def spatial_disjoint_union(self, dataset):
+        """!Return the two dimensional union as spatial_extent object.
+       
+           @param dataset The abstract dataset to create a union with
+           @return The union spatial extent
+        """
+        return self.spatial_extent.disjoint_union_2d(dataset.spatial_extent)
+        
     def reset(self, ident):
         """!Reset the internal structure and set the identifier"""
         self.base = VectorBase(ident=ident)
@@ -862,14 +945,38 @@
 
     def spatial_overlapping(self, dataset):
         """!Return True if the spatial extents 2d overlap"""
-
         return self.spatial_extent.overlapping_2d(dataset.spatial_extent)
 
     def spatial_relation(self, dataset):
         """!Return the two dimensional spatial relation"""
-
         return self.spatial_extent.spatial_relation_2d(dataset.spatial_extent)
 
+    def spatial_intersection(self, dataset):
+        """!Return the two dimensional intersection as spatial_extent 
+           object or None in case no intersection was found.
+           
+           @param dataset The abstract dataset to intersect with
+           @return The intersection spatial extent or None
+        """
+        return self.spatial_extent.intersect_2d(dataset.spatial_extent)
+
+    def spatial_union(self, dataset):
+        """!Return the two dimensional union as spatial_extent 
+           object or None in case the extents does not overlap or meet.
+       
+           @param dataset The abstract dataset to create a union with
+           @return The union spatial extent or None
+        """
+        return self.spatial_extent.union_2d(dataset.spatial_extent)
+        
+    def spatial_disjoint_union(self, dataset):
+        """!Return the two dimensional union as spatial_extent object.
+       
+           @param dataset The abstract dataset to create a union with
+           @return The union spatial extent
+        """
+        return self.spatial_extent.disjoint_union_2d(dataset.spatial_extent)
+    
     def reset(self, ident):
 
         """!Reset the internal structure and set the identifier"""
@@ -926,6 +1033,41 @@
         else:
             return self.spatial_extent.spatial_relation_2d(dataset.spatial_extent)
 
+    def spatial_intersection(self, dataset):
+        """!Return the three or two dimensional intersection as spatial_extent 
+           object or None in case no intersection was found.
+           
+           @param dataset The abstract dataset to intersect with
+           @return The intersection spatial extent or None
+        """
+        if self.get_type() == dataset.get_type() or dataset.get_type() == "raster3d":
+            return self.spatial_extent.intersect(dataset.spatial_extent)
+        else:
+            return self.spatial_extent.intersect_2d(dataset.spatial_extent)
+
+    def spatial_union(self, dataset):
+        """!Return the three or two dimensional union as spatial_extent 
+           object or None in case the extents does not overlap or meet.
+       
+           @param dataset The abstract dataset to create a union with
+           @return The union spatial extent or None
+        """
+        if self.get_type() == dataset.get_type() or dataset.get_type() == "raster3d":
+            return self.spatial_extent.union(dataset.spatial_extent)
+        else:
+            return self.spatial_extent.union_2d(dataset.spatial_extent)
+        
+    def spatial_disjoint_union(self, dataset):
+        """!Return the three or two dimensional union as spatial_extent object.
+       
+           @param dataset The abstract dataset to create a union with
+           @return The union spatial extent
+        """
+        if self.get_type() == dataset.get_type() or dataset.get_type() == "raster3d":
+            return self.spatial_extent.disjoint_union(dataset.spatial_extent)
+        else:
+            return self.spatial_extent.disjoint_union_2d(dataset.spatial_extent)
+    
     def reset(self, ident):
 
         """!Reset the internal structure and set the identifier"""
@@ -968,14 +1110,38 @@
 
     def spatial_overlapping(self, dataset):
         """!Return True if the spatial extents 2d overlap"""
-
         return self.spatial_extent.overlapping_2d(dataset.spatial_extent)
 
     def spatial_relation(self, dataset):
         """!Return the two dimensional spatial relation"""
-
         return self.spatial_extent.spatial_relation_2d(dataset.spatial_extent)
 
+    def spatial_intersection(self, dataset):
+        """!Return the two dimensional intersection as spatial_extent 
+           object or None in case no intersection was found.
+           
+           @param dataset The abstract dataset to intersect with
+           @return The intersection spatial extent or None
+        """
+        return self.spatial_extent.intersect_2d(dataset.spatial_extent)
+
+    def spatial_union(self, dataset):
+        """!Return the two dimensional union as spatial_extent 
+           object or None in case the extents does not overlap or meet.
+       
+           @param dataset The abstract dataset to create a union with
+           @return The union spatial extent or None
+        """
+        return self.spatial_extent.union_2d(dataset.spatial_extent)
+        
+    def spatial_disjoint_union(self, dataset):
+        """!Return the two dimensional union as spatial_extent object.
+       
+           @param dataset The abstract dataset to create a union with
+           @return The union spatial extent
+        """
+        return self.spatial_extent.disjoint_union_2d(dataset.spatial_extent)
+    
     def reset(self, ident):
 
         """!Reset the internal structure and set the identifier"""

Modified: grass/trunk/lib/python/temporal/spatial_extent.py
===================================================================
--- grass/trunk/lib/python/temporal/spatial_extent.py	2013-06-04 19:31:49 UTC (rev 56595)
+++ grass/trunk/lib/python/temporal/spatial_extent.py	2013-06-05 08:36:44 UTC (rev 56596)
@@ -198,10 +198,10 @@
 
     def intersect_2d(self, extent):
         """!Return the two dimensional intersection as spatial_extent 
-        object or None in case no intersection was found.
+           object or None in case no intersection was found.
        
         @param extent The spatial extent to intersect with
-         @return The intersection spatial extent
+        @return The intersection spatial extent
         """
 
         if not self.overlapping_2d(extent):
@@ -342,7 +342,181 @@
         new.set_bottom(nB)
 
         return new
+        
+    def union_2d(self, extent):
+        """!Return the two dimensional union as spatial_extent 
+           object or None in case the extents does not overlap or meet.
+       
+        @param extent The spatial extent to create a union with
+        @return The union spatial extent
+        """
+        if not self.overlapping_2d(extent) and not self.meet_2d(extent):
+            return None
+        
+        return self.disjoint_union_2d(extent)
+    
+    def disjoint_union_2d(self, extent):
+        """!Return the two dimensional union as spatial_extent.
+       
+        @param extent The spatial extent to create a union with
+        @return The union spatial extent
+        """
+        eN = extent.get_north()
+        eS = extent.get_south()
+        eE = extent.get_east()
+        eW = extent.get_west()
 
+        N = self.get_north()
+        S = self.get_south()
+        E = self.get_east()
+        W = self.get_west()
+
+        # Adjust the east and west in case of LL projection
+        if self.get_projection() == "LL":
+            while eE < W:
+                eE += 360.0
+                eW += 360.0
+
+            while eW > E:
+                eE -= 360.0
+                eW -= 360.0
+
+        # Compute the extent
+        nN = N
+        nS = S
+        nE = E
+        nW = W
+
+        if W > eW:
+            nW = eW
+        if E < eE:
+            nE = eE
+        if N < eN:
+            nN = eN
+        if S > eS:
+            nS = eS
+
+        new = SpatialExtent(north=nN, south=nS, east=nE, west=nW,
+                             top=0, bottom=0, proj=self.get_projection())
+        return new
+
+    def union(self, extent):
+        """!Return the three dimensional union as spatial_extent 
+           object or None in case the extents does not overlap or meet.
+       
+        @param extent The spatial extent to create a union with
+        @return The union spatial extent
+        """
+        if not self.overlapping(extent) and not self.meet(extent):
+            return None
+        
+        return self.disjoint_union(extent)
+    
+    def disjoint_union(self, extent):
+        """!Return the three dimensional union as spatial_extent .
+        
+        Usage:
+        
+        @code
+        
+        >>> A = SpatialExtent(north=80, south=20, east=60, west=10, 
+        ... bottom=-50, top=50)
+        >>> B = SpatialExtent(north=80, south=20, east=60, west=10, 
+        ... bottom=-50, top=50)
+        >>> C = A.disjoint_union(B)
+        >>> C.print_info()
+         +-------------------- Spatial extent ----------------------------------------+
+         | North:...................... 80.0
+         | South:...................... 20.0
+         | East:.. .................... 60.0
+         | West:....................... 10.0
+         | Top:........................ 50.0
+         | Bottom:..................... -50.0
+        >>> B = SpatialExtent(north=40, south=30, east=60, west=10, 
+        ... bottom=-50, top=50)
+        >>> C = A.disjoint_union(B)
+        >>> C.print_info()
+         +-------------------- Spatial extent ----------------------------------------+
+         | North:...................... 80.0
+         | South:...................... 20.0
+         | East:.. .................... 60.0
+         | West:....................... 10.0
+         | Top:........................ 50.0
+         | Bottom:..................... -50.0
+        >>> B = SpatialExtent(north=40, south=30, east=60, west=30, 
+        ... bottom=-50, top=50)
+        >>> C = A.disjoint_union(B)
+        >>> C.print_info()
+         +-------------------- Spatial extent ----------------------------------------+
+         | North:...................... 80.0
+         | South:...................... 20.0
+         | East:.. .................... 60.0
+         | West:....................... 10.0
+         | Top:........................ 50.0
+         | Bottom:..................... -50.0
+        >>> B = SpatialExtent(north=40, south=30, east=60, west=30, 
+        ... bottom=-30, top=50)
+        >>> C = A.disjoint_union(B)
+        >>> C.print_info()
+         +-------------------- Spatial extent ----------------------------------------+
+         | North:...................... 80.0
+         | South:...................... 20.0
+         | East:.. .................... 60.0
+         | West:....................... 10.0
+         | Top:........................ 50.0
+         | Bottom:..................... -50.0
+        >>> B = SpatialExtent(north=40, south=30, east=60, west=30, 
+        ... bottom=-30, top=30)
+        >>> C = A.disjoint_union(B)
+        >>> C.print_info()
+         +-------------------- Spatial extent ----------------------------------------+
+         | North:...................... 80.0
+         | South:...................... 20.0
+         | East:.. .................... 60.0
+         | West:....................... 10.0
+         | Top:........................ 50.0
+         | Bottom:..................... -50.0
+        >>> A = SpatialExtent(north=80, south=20, east=60, west=10, 
+        ... bottom=-50, top=50)
+        >>> B = SpatialExtent(north=90, south=80, east=70, west=20, 
+        ... bottom=-30, top=60)
+        >>> C = A.disjoint_union(B)
+        >>> C.print_info()
+         +-------------------- Spatial extent ----------------------------------------+
+         | North:...................... 90.0
+         | South:...................... 20.0
+         | East:.. .................... 70.0
+         | West:....................... 10.0
+         | Top:........................ 60.0
+         | Bottom:..................... -50.0
+         
+         @endcode
+         
+         @param extent The spatial extent to create a disjoint union with
+         @return The union spatial extent
+        """
+
+        new = self.disjoint_union_2d(extent)
+
+        eT = extent.get_top()
+        eB = extent.get_bottom()
+
+        T = self.get_top()
+        B = self.get_bottom()
+
+        nT = T
+        nB = B
+
+        if B > eB:
+            nB = eB
+        if T < eT:
+            nT = eT
+
+        new.set_top(nT)
+        new.set_bottom(nB)
+
+        return new
+    
     def is_in_2d(self, extent):
         """!Return True if this extent (A) is located in the provided spatial
         extent (B) in two dimensions.
@@ -1497,7 +1671,7 @@
 
         area = self.get_area()
 
-        bbox = self.get_spatial_extent()
+        bbox = self.get_spatial_extent_as_tuple()
 
         z = abs(bbox[4] - bbox[5])
 
@@ -1513,14 +1687,14 @@
             core.error(_("Area computation is not supported "
                          "for LL projections"))
 
-        bbox = self.get_spatial_extent()
+        bbox = self.get_spatial_extent_as_tuple()
 
         y = abs(bbox[0] - bbox[1])
         x = abs(bbox[2] - bbox[3])
 
         return x * y
 
-    def get_spatial_extent(self):
+    def get_spatial_extent_as_tuple(self):
         """!Return a tuple (north, south, east, west, top, bottom) 
            of the spatial extent"""
 
@@ -1528,7 +1702,7 @@
             self.north, self.south, self.east, self.west,
             self.top, self.bottom)
 
-    def get_spatial_extent_2d(self):
+    def get_spatial_extent_as_tuple_2d(self):
         """!Return a tuple (north, south, east, west,) of the 2d spatial extent
         """
         return (self.north, self.south, self.east, self.west)

Modified: grass/trunk/lib/python/temporal/spatio_temporal_relationships.py
===================================================================
--- grass/trunk/lib/python/temporal/spatio_temporal_relationships.py	2013-06-04 19:31:49 UTC (rev 56595)
+++ grass/trunk/lib/python/temporal/spatio_temporal_relationships.py	2013-06-05 08:36:44 UTC (rev 56596)
@@ -162,7 +162,7 @@
         """
         rect = vector.RTreeAllocRect(tree)
 
-        start, end = map_.get_valid_time()
+        start, end = map_.get_temporal_extent_as_tuple()
 
         if not end:
             end = start
@@ -174,11 +174,11 @@
         if spatial is None:
             vector.RTreeSetRect1D(rect, tree, float(start), float(end))
         elif spatial == "2D":
-            north, south, east, west, top, bottom = map_.get_spatial_extent()
+            north, south, east, west, top, bottom = map_.get_spatial_extent_as_tuple()
             vector.RTreeSetRect3D(rect, tree, west, east, south, north, 
                                   float(start), float(end))
         elif spatial == "3D":
-            north, south, east, west, top, bottom = map_.get_spatial_extent()
+            north, south, east, west, top, bottom = map_.get_spatial_extent_as_tuple()
             vector.RTreeSetRect4D(rect, tree, west, east, south, north, 
                                   bottom, top, float(start), float(end))
 

Modified: grass/trunk/lib/python/temporal/stds_export.py
===================================================================
--- grass/trunk/lib/python/temporal/stds_export.py	2013-06-04 19:31:49 UTC (rev 56595)
+++ grass/trunk/lib/python/temporal/stds_export.py	2013-06-05 08:36:44 UTC (rev 56596)
@@ -320,7 +320,7 @@
     if sp.is_time_relative():
 	string += "%s=%s\n" % ("relative_time_unit", sp.get_relative_time_unit())
     string += "%s=%s\n" % ("number_of_maps", sp.metadata.get_number_of_maps())
-    north, south, east, west, top, bottom = sp.get_spatial_extent()
+    north, south, east, west, top, bottom = sp.get_spatial_extent_as_tuple()
     string += "%s=%s\n" % ("north", north)
     string += "%s=%s\n" % ("south", south)
     string += "%s=%s\n" % ("east", east)

Modified: grass/trunk/lib/python/temporal/temporal_extent.py
===================================================================
--- grass/trunk/lib/python/temporal/temporal_extent.py	2013-06-04 19:31:49 UTC (rev 56595)
+++ grass/trunk/lib/python/temporal/temporal_extent.py	2013-06-05 08:36:44 UTC (rev 56596)
@@ -195,7 +195,186 @@
             end = self.D["end_time"]
         
         return AbstractTemporalExtent(start_time=start, end_time=end)
+    
+    def disjoint_union(self, extent):
+        """!Creates a disjoint union with this temporal extent and the provided one.
+           Return a new temporal extent with the new start and end time.
+           
+           @param extent The temporal extent to create a union with
+           @return The new temporal extent with start and end time           
+           
+           Usage:
+           
+           @code
+
+           >>> A = AbstractTemporalExtent(start_time=5, end_time=6 )
+           >>> inter = A.intersect(A)
+           >>> inter.print_info()
+            | Start time:................. 5
+            | End time:................... 6
+            
+           >>> A = AbstractTemporalExtent(start_time=5, end_time=6 )
+           >>> B = AbstractTemporalExtent(start_time=5, end_time=7 )
+           >>> inter = A.disjoint_union(B)
+           >>> inter.print_info()
+            | Start time:................. 5
+            | End time:................... 7
+           >>> inter = B.disjoint_union(A)
+           >>> inter.print_info()
+            | Start time:................. 5
+            | End time:................... 7
+             
+           >>> A = AbstractTemporalExtent(start_time=3, end_time=6 )
+           >>> B = AbstractTemporalExtent(start_time=5, end_time=7 )
+           >>> inter = A.disjoint_union(B)
+           >>> inter.print_info()
+            | Start time:................. 3
+            | End time:................... 7
+           >>> inter = B.disjoint_union(A)
+           >>> inter.print_info()
+            | Start time:................. 3
+            | End time:................... 7
+             
+           >>> A = AbstractTemporalExtent(start_time=3, end_time=8 )
+           >>> B = AbstractTemporalExtent(start_time=5, end_time=6 )
+           >>> inter = A.disjoint_union(B)
+           >>> inter.print_info()
+            | Start time:................. 3
+            | End time:................... 8
+           >>> inter = B.disjoint_union(A)
+           >>> inter.print_info()
+            | Start time:................. 3
+            | End time:................... 8
+            
+           >>> A = AbstractTemporalExtent(start_time=5, end_time=8 )
+           >>> B = AbstractTemporalExtent(start_time=3, end_time=6 )
+           >>> inter = A.disjoint_union(B)
+           >>> inter.print_info()
+            | Start time:................. 3
+            | End time:................... 8
+           >>> inter = B.disjoint_union(A)
+           >>> inter.print_info()
+            | Start time:................. 3
+            | End time:................... 8
+
+           >>> A = AbstractTemporalExtent(start_time=5, end_time=None )
+           >>> B = AbstractTemporalExtent(start_time=3, end_time=6 )
+           >>> inter = A.disjoint_union(B)
+           >>> inter.print_info()
+            | Start time:................. 3
+            | End time:................... 6
+           >>> inter = B.disjoint_union(A)
+           >>> inter.print_info()
+            | Start time:................. 3
+            | End time:................... 6
+            
+           >>> A = AbstractTemporalExtent(start_time=5, end_time=8 )
+           >>> B = AbstractTemporalExtent(start_time=3, end_time=4 )
+           >>> inter = A.disjoint_union(B)
+           >>> inter.print_info()
+            | Start time:................. 3
+            | End time:................... 8
+           >>> inter = B.disjoint_union(A)
+           >>> inter.print_info()
+            | Start time:................. 3
+            | End time:................... 8
+           >>> A = AbstractTemporalExtent(start_time=5, end_time=8 )
+           >>> B = AbstractTemporalExtent(start_time=3, end_time=None )
+           >>> inter = A.disjoint_union(B)
+           >>> inter.print_info()
+            | Start time:................. 3
+            | End time:................... 8
+           >>> inter = B.disjoint_union(A)
+           >>> inter.print_info()
+            | Start time:................. 3
+            | End time:................... 8
+           >>> A = AbstractTemporalExtent(start_time=5, end_time=None )
+           >>> B = AbstractTemporalExtent(start_time=3, end_time=8 )
+           >>> inter = A.disjoint_union(B)
+           >>> inter.print_info()
+            | Start time:................. 3
+            | End time:................... 8
+           >>> inter = B.disjoint_union(A)
+           >>> inter.print_info()
+            | Start time:................. 3
+            | End time:................... 8
+           >>> A = AbstractTemporalExtent(start_time=5, end_time=None )
+           >>> B = AbstractTemporalExtent(start_time=3, end_time=None )
+           >>> inter = A.disjoint_union(B)
+           >>> inter.print_info()
+            | Start time:................. 3
+            | End time:................... 5
+           >>> inter = B.disjoint_union(A)
+           >>> inter.print_info()
+            | Start time:................. 3
+            | End time:................... 5
+            
+           @endcoe
+        """
         
+        start = None
+        end = None
+        
+        if self.D["start_time"] < extent.D["start_time"]:
+            start = self.D["start_time"]
+        else:
+            start = extent.D["start_time"]
+        
+        # End time handling
+        if self.D["end_time"] is None and extent.D["end_time"] is None:
+            if self.D["start_time"] > extent.D["start_time"]:
+                end = self.D["start_time"]
+            else:
+                end = extent.D["start_time"]
+        elif self.D["end_time"] is None:
+            if self.D["start_time"] > extent.D["end_time"]:
+                end = self.D["start_time"]
+            else:
+                end = extent.D["end_time"]
+        elif extent.D["end_time"] is None:
+            if self.D["end_time"] > extent.D["start_time"]:
+                end = self.D["end_time"]
+            else:
+                end = extent.D["start_time"]
+        elif self.D["end_time"] < extent.D["end_time"]:
+            end = extent.D["end_time"]
+        else:
+            end = self.D["end_time"]
+        
+        return AbstractTemporalExtent(start_time=start, end_time=end)
+    
+    def union(self, extent):
+        """!Creates a union with this temporal extent and the provided one.
+           Return a new temporal extent with the new start and end time.
+           
+           @param extent The temporal extent to create a union with
+           @return The new temporal extent with start and end time, 
+                   or None in case the temporal extents are unrelated (before or after)
+                   
+           @code
+           
+           >>> A = AbstractTemporalExtent(start_time=5, end_time=8 )
+           >>> B = AbstractTemporalExtent(start_time=3, end_time=4 )
+           >>> inter = A.intersect(B)
+           >>> print inter
+           None
+           
+           >>> A = AbstractTemporalExtent(start_time=5, end_time=8 )
+           >>> B = AbstractTemporalExtent(start_time=3, end_time=None )
+           >>> inter = A.intersect(B)
+           >>> print inter
+           None
+           
+           @endcode
+        """
+
+        relation = self.temporal_relation(extent)
+        
+        if relation == "after" or relation == "before":
+            return None
+
+        return self.disjoint_union(extent)
+    
     def starts(self, extent):
         """!Return True if this temporal extent (A) starts at the start of the 
            provided temporal extent (B) and finishes within it

Modified: grass/trunk/lib/python/temporal/temporal_granularity.py
===================================================================
--- grass/trunk/lib/python/temporal/temporal_granularity.py	2013-06-04 19:31:49 UTC (rev 56595)
+++ grass/trunk/lib/python/temporal/temporal_granularity.py	2013-06-05 08:36:44 UTC (rev 56596)
@@ -202,7 +202,7 @@
     delta = []
     # First we compute the timedelta of the intervals
     for map in maps:
-        start, end = map.get_valid_time()
+        start, end = map.get_temporal_extent_as_tuple()
         if start and end:
             t = abs(end - start)
             delta.append(int(t))
@@ -212,8 +212,8 @@
         if i < len(maps) - 1:
             relation = maps[i + 1].temporal_relation(maps[i])
             if relation == "after":
-                start1, end1 = maps[i].get_valid_time()
-                start2, end2 = maps[i + 1].get_valid_time()
+                start1, end1 = maps[i].get_temporal_extent_as_tuple()
+                start2, end2 = maps[i + 1].get_temporal_extent_as_tuple()
                 # Gaps are between intervals, intervals and 
                 # points, points and points
                 if end1 and start2:
@@ -338,7 +338,7 @@
     datetime_delta = []
     # First we compute the timedelta of the intervals
     for map in maps:
-        start, end = map.get_valid_time()
+        start, end = map.get_temporal_extent_as_tuple()
         if start and end:
             delta.append(end - start)
             datetime_delta.append(compute_datetime_delta(start, end))
@@ -348,8 +348,8 @@
         if i < len(maps) - 1:
             relation = maps[i + 1].temporal_relation(maps[i])
             if relation == "after":
-                start1, end1 = maps[i].get_valid_time()
-                start2, end2 = maps[i + 1].get_valid_time()
+                start1, end1 = maps[i].get_temporal_extent_as_tuple()
+                start2, end2 = maps[i + 1].get_temporal_extent_as_tuple()
                 # Gaps are between intervals, intervals and 
                 # points, points and points
                 if end1 and start2:

Modified: grass/trunk/lib/python/temporal/unit_tests.py
===================================================================
--- grass/trunk/lib/python/temporal/unit_tests.py	2013-06-04 19:31:49 UTC (rev 56595)
+++ grass/trunk/lib/python/temporal/unit_tests.py	2013-06-05 08:36:44 UTC (rev 56596)
@@ -1495,11 +1495,11 @@
 
     print "Original"
     for _map in map_list:
-        print _map.get_valid_time()[0], _map.get_valid_time()[1]
+        print _map.get_temporal_extent_as_tuple()[0], _map.get_temporal_extent_as_tuple()[1]
     print "Sorted by start time"
     new_list = sorted(map_list, key=AbstractDatasetComparisonKeyStartTime)
     for _map in new_list:
-        print _map.get_valid_time()[0], _map.get_valid_time()[1]
+        print _map.get_temporal_extent_as_tuple()[0], _map.get_temporal_extent_as_tuple()[1]
 
     if new_list[0] != map_list[1]:
         core.fatal("Sorting by start time failed")
@@ -1511,7 +1511,7 @@
     print "Sorted by end time"
     new_list = sorted(map_list, key=AbstractDatasetComparisonKeyEndTime)
     for _map in new_list:
-        print _map.get_valid_time()[0], _map.get_valid_time()[1]
+        print _map.get_temporal_extent_as_tuple()[0], _map.get_temporal_extent_as_tuple()[1]
 
     if new_list[0] != map_list[1]:
         core.fatal("Sorting by end time failed")

Modified: grass/trunk/temporal/t.rast.aggregate.ds/t.rast.aggregate.ds.py
===================================================================
--- grass/trunk/temporal/t.rast.aggregate.ds/t.rast.aggregate.ds.py	2013-06-04 19:31:49 UTC (rev 56595)
+++ grass/trunk/temporal/t.rast.aggregate.ds/t.rast.aggregate.ds.py	2013-06-05 08:36:44 UTC (rev 56596)
@@ -121,12 +121,7 @@
                       "the same temporal type"))
 
     # Check if intervals are present
-    if sampler_sp.get_temporal_type() == "absolute":
-        map_time = sampler_sp.absolute_time.get_map_time()
-    else:
-        map_time = sampler_sp.relative_time.get_map_time()
-
-    if map_time != "interval":
+    if sample.temporal_extent.get_map_time() != "interval":
         dbif.close()
         grass.fatal(_("All registered maps of the aggregation dataset "
                       "must have time intervals"))

Modified: grass/trunk/temporal/t.rast.to.rast3/t.rast.to.rast3.py
===================================================================
--- grass/trunk/temporal/t.rast.to.rast3/t.rast.to.rast3.py	2013-06-04 19:31:49 UTC (rev 56595)
+++ grass/trunk/temporal/t.rast.to.rast3/t.rast.to.rast3.py	2013-06-05 08:36:44 UTC (rev 56596)
@@ -80,7 +80,7 @@
 
     # Compatible temporal units are : days, hours, minutes and seconds
     # Incompatible are years and moths
-    start, end = sp.get_valid_time()
+    start, end = sp.get_temporal_extent_as_tuple()
 
     if sp.is_time_absolute():
         unit = granularity.split(" ")[1]
@@ -164,7 +164,7 @@
     else:
         id = output + "@" + mapset
 
-    start, end = sp.get_valid_time()
+    start, end = sp.get_temporal_extent_as_tuple()
     r3ds = tgis.Raster3DDataset(id)
 
     if r3ds.is_in_db():

Modified: grass/trunk/temporal/t.vect.observe.strds/test.t.vect.observe.strds.sh
===================================================================
--- grass/trunk/temporal/t.vect.observe.strds/test.t.vect.observe.strds.sh	2013-06-04 19:31:49 UTC (rev 56595)
+++ grass/trunk/temporal/t.vect.observe.strds/test.t.vect.observe.strds.sh	2013-06-05 08:36:44 UTC (rev 56596)
@@ -5,17 +5,19 @@
 # The region setting should work for UTM and LL test locations
 g.region s=0 n=80 w=0 e=120 b=0 t=50 res=10 res3=10 -p3
 
-r.mapcalc --o expr="prec_1 = 100.0"
-r.mapcalc --o expr="prec_2 = 200.0"
-r.mapcalc --o expr="prec_3 = 300"
-r.mapcalc --o expr="prec_4 = 400"
-r.mapcalc --o expr="prec_5 = 500.0"
-r.mapcalc --o expr="prec_6 = 600.0"
+export GRASS_OVERWRITE=1
 
-v.random --o output=prec n=5 seed=1
-v.random --o -z output=test_1 column=test n=5 seed=1 
+r.mapcalc  expr="prec_1 = 100.0"
+r.mapcalc  expr="prec_2 = 200.0"
+r.mapcalc  expr="prec_3 = 300"
+r.mapcalc  expr="prec_4 = 400"
+r.mapcalc  expr="prec_5 = 500.0"
+r.mapcalc  expr="prec_6 = 600.0"
 
-t.create --o type=strds temporaltype=absolute output=precip_abs1 title="A test" descr="A test"
+v.random output=prec n=5 seed=1
+v.random -z output=test_1 column=test n=5 seed=1 
+
+t.create type=strds temporaltype=absolute output=precip_abs1 title="A test" descr="A test"
 t.register -i input=precip_abs1 maps=prec_1,prec_2,prec_3,prec_4,prec_5,prec_6 start="2001-03-01 00:00:00" increment="1 months"
 
 # The @test



More information about the grass-commit mailing list