[GRASS-SVN] r51527 - grass/trunk/lib/python/temporal

svn_grass at osgeo.org svn_grass at osgeo.org
Tue Apr 24 18:55:15 EDT 2012


Author: huhabla
Date: 2012-04-24 15:55:15 -0700 (Tue, 24 Apr 2012)
New Revision: 51527

Modified:
   grass/trunk/lib/python/temporal/abstract_map_dataset.py
   grass/trunk/lib/python/temporal/datetime_math.py
   grass/trunk/lib/python/temporal/space_time_datasets.py
   grass/trunk/lib/python/temporal/space_time_datasets_tools.py
   grass/trunk/lib/python/temporal/temporal_extent.py
   grass/trunk/lib/python/temporal/temporal_relationships.py
   grass/trunk/lib/python/temporal/unit_tests.py
Log:
Extended abstract_map_dataset with temporal topology structure. Implemented a temporal topology builder.
Small temporal relationships computation fix.


Modified: grass/trunk/lib/python/temporal/abstract_map_dataset.py
===================================================================
--- grass/trunk/lib/python/temporal/abstract_map_dataset.py	2012-04-24 21:23:22 UTC (rev 51526)
+++ grass/trunk/lib/python/temporal/abstract_map_dataset.py	2012-04-24 22:55:15 UTC (rev 51527)
@@ -23,13 +23,318 @@
 from abstract_dataset import *
 from datetime_math import *
 
+class temporal_map_relations(abstract_dataset):
+    """!This class implements a temporal topology access structure
+    
+       This object will be set up by temporal topology creation methods.
+       
+       If correctly initialize the calls get_next() and get_prev() let the user walk temporally forward
+       and backward in time.
+       
+       The following temporal relations with access methods are supported:
+       * equal
+       * follows
+       * precedes
+       * overlaps
+       * overlapped
+       * during (including starts, finishes)
+       * contains (including started, finished)
+       
+       
+       Code:
+       # We have build the temporal topology and we know the first map
+       start = first
+       while start:
+       
+	   # Print all maps this map temporally contains
+           dlist = start.get_contains()
+           for _map in dlist:
+               _map.print_info()
+               
+           start = start.get_next()       
+    """
+
+    def __init__(self):
+        self.reset_temporal_topology()
+        
+    def reset_temporal_topology(self):
+	"""!Reset any information about temporal topology"""
+        self._temporal_topology = {}
+        self._has_temporal_topology = False
+        
+    def set_temporal_topology_build_true(self):
+	"""!Same as name"""
+	self._has_temporal_topology = True
+	
+    def set_temporal_topology_build_false(self):
+	"""!Same as name"""
+	self._has_temporal_topology = False
+
+    def is_temporal_topology_build(self):
+	"""!Check if the temporal topology was build"""
+	return self._has_temporal_topology
+
+    def set_next(self, _map):
+	"""!Set the map that is temporally as closest located after this map.
+	
+	   Temporally located means that the start time of the "next" map is 
+	   temporally located AFTER the start time of this map, but temporally 
+	   near than other maps of the same dataset.
+	   
+	   @param _map This object should be of type abstract_map_dataset or derived classes
+	"""
+        self._temporal_topology["NEXT"] = _map
+
+    def set_prev(self, _map):
+	"""!Set the map that is temporally as closest located before this map.
+	
+	   Temporally located means that the start time of the "previous" map is 
+	   temporally located BEFORE the start time of this map, but temporally 
+	   near than other maps of the same dataset.
+	   
+	   @param _map This object should be of type abstract_map_dataset or derived classes
+	"""
+        self._temporal_topology["PREV"] = _map
+
+    def next(self):
+	"""!Return the map with a start time temporally located after
+	   the start time of this map, but temporal closer than other maps
+	   
+	   @return A map object or None
+	"""
+        if not self._temporal_topology.has_key("NEXT"):
+            return None
+        return self._temporal_topology["NEXT"]
+
+    def prev(self):
+	"""!Return the map with a start time temporally located before
+	   the start time of this map, but temporal closer than other maps
+	   
+	   @return A map object or None
+	"""
+        if not self._temporal_topology.has_key("PREV"):
+            return None
+        return self._temporal_topology["PREV"]
+
+    def append_equivalent(self, _map): 
+	"""!Append a map with equivalent temporal extent as this map
+	
+	   @param _map This object should be of type abstract_map_dataset or derived classes
+	"""
+        if not self._temporal_topology.has_key("EQUAL"):
+            self._temporal_topology["EQUAL"] = []
+        self._temporal_topology["EQUAL"].append(_map)
+
+    def get_equivalent(self):
+	"""!Return a list of map objects with equivalent temporal extent as this map
+	
+	   @return A list of map objects or None
+	"""
+        if not self._temporal_topology.has_key("EQUAL"):
+            return None
+        return self._temporal_topology["EQUAL"]
+
+    def append_overlaps(self, _map): 
+	"""!Append a map that this map temporally overlaps
+	
+	   @param _map This object should be of type abstract_map_dataset or derived classes
+	"""
+        if not self._temporal_topology.has_key("OVERLAPS"):
+            self._temporal_topology["OVERLAPS"] = []
+        self._temporal_topology["OVERLAPS"].append(_map)
+
+    def get_overlaps(self): 
+	"""!Return a list of map objects that this map temporally overlaps
+	
+	   @return A list of map objects or None
+	"""
+        if not self._temporal_topology.has_key("OVERLAPS"):
+            return None
+        return self._temporal_topology["OVERLAPS"]
+
+    def append_overlapped(self, _map): 
+	"""!Append a map that this map temporally overlapped
+	
+	   @param _map This object should be of type abstract_map_dataset or derived classes
+	""" 
+        if not self._temporal_topology.has_key("OVERLAPPED"):
+            self._temporal_topology["OVERLAPPED"] = []
+        self._temporal_topology["OVERLAPPED"].append(_map)
+
+    def get_overlapped(self): 
+	"""!Return a list of map objects that this map temporally overlapped
+	
+	   @return A list of map objects or None
+	"""
+        if not self._temporal_topology.has_key("OVERLAPPED"):
+            return None
+        return self._temporal_topology["OVERLAPPED"]
+    
+    def append_follows(self, _map): 
+	"""!Append a map that this map temporally follows
+	
+	   @param _map This object should be of type abstract_map_dataset or derived classes
+	""" 
+        if not self._temporal_topology.has_key("FOLLOWS"):
+            self._temporal_topology["FOLLOWS"] = []
+        self._temporal_topology["FOLLOWS"].append(_map)
+
+    def get_follows(self): 
+	"""!Return a list of map objects that this map temporally follows
+	
+	   @return A list of map objects or None
+	"""
+        if not self._temporal_topology.has_key("FOLLOWS"):
+            return None
+        return self._temporal_topology["FOLLOWS"]
+    
+    def append_precedes(self, _map): 
+	"""!Append a map that this map temporally precedes
+	
+	   @param _map This object should be of type abstract_map_dataset or derived classes
+	""" 
+        if not self._temporal_topology.has_key("PRECEDES"):
+            self._temporal_topology["PRECEDES"] = []
+        self._temporal_topology["PRECEDES"].append(_map)
+
+    def get_precedes(self): 
+	"""!Return a list of map objects that this map temporally precedes
+	
+	   @return A list of map objects or None
+	"""
+        if not self._temporal_topology.has_key("PRECEDES"):
+            return None
+        return self._temporal_topology["PRECEDES"]
+    
+    def append_during(self, _map):  
+	"""!Append a map that this map is temporally located during
+	   This includes temporal relationships starts and finishes
+	
+	   @param _map This object should be of type abstract_map_dataset or derived classes
+	""" 
+        if not self._temporal_topology.has_key("DURING"):
+            self._temporal_topology["DURING"] = []
+        self._temporal_topology["DURING"].append(_map)
+
+    def get_during(self): 
+	"""!Return a list of map objects that this map is temporally located during
+	   This includes temporally relationships starts and finishes
+	
+	   @return A list of map objects or None
+	"""
+        if not self._temporal_topology.has_key("DURING"):
+            return None
+        return self._temporal_topology["DURING"]
+    
+    def append_contains(self, _map):   
+	"""!Append a map that this map temporally contains
+	   This includes temporal relationships started and finished
+	
+	   @param _map This object should be of type abstract_map_dataset or derived classes
+	""" 
+        if not self._temporal_topology.has_key("CONTAINS"):
+            self._temporal_topology["CONTAINS"] = []
+        self._temporal_topology["CONTAINS"].append(_map)
+
+    def get_contains(self): 
+	"""!Return a list of map objects that this map temporally contains
+	   This includes temporal relationships started and finished
+	
+	   @return A list of map objects or None
+	"""
+        if not self._temporal_topology.has_key("CONTAINS"):
+            return None
+        return self._temporal_topology["CONTAINS"]
+
+    def _generate_map_list_string(self, map_list, line_wrap = True):
+	count = 0
+	string = ""
+	for _map in map_list:
+	    if line_wrap and count > 0 and count % 3 == 0:
+		string += "\n | ............................ "
+		count = 0
+	    if count == 0:
+		string += _map.get_id()
+	    else:
+		string += ",%s" % _map.get_id()
+	    count += 1
+	    
+	return string
+                
+    def print_temporal_topology_info(self):
+        """!Print information about this class in human shell style"""
+        _next = self.next()
+        _prev = self.prev()
+        _equal = self.get_equivalent()
+        _follows = self.get_follows()
+        _precedes = self.get_precedes()
+        _overlaps = self.get_overlaps()
+        _overlapped = self.get_overlapped()
+        _during = self.get_during()
+        _contains = self.get_contains()
+        
+        print " +-------------------- Temporal Topology -------------------------------------+"
+        #          0123456789012345678901234567890
+        if _next:
+	    print " | Next: ...................... " + str(_next.get_id())
+        if _prev:
+	    print " | Previous: .................. " + str(_prev.get_id())
+        if _equal:
+	    print " | Equivalent: ................ " + self._generate_map_list_string(_equal)
+        if _follows:
+	    print " | Follows: ................... " + self._generate_map_list_string(_follows)
+        if _precedes:
+	    print " | Precedes: .................. " + self._generate_map_list_string(_precedes)
+        if _overlaps:
+	    print " | Overlaps: .................. " + self._generate_map_list_string(_overlaps)
+        if _overlapped:
+	    print " | Overlapped: ................ " + self._generate_map_list_string(_overlapped)
+        if _during:
+	    print " | During: .................... " + self._generate_map_list_string(_during)
+        if _contains:
+	    print " | Contains: .................. " + self._generate_map_list_string(_contains)
+         
+    def print_temporal_topology_shell_info(self):
+        """!Print information about this class in human readable style"""
+        
+        _next = self.next()
+        _prev = self.prev()
+        _equal = self.get_equivalent()
+        _follows = self.get_follows()
+        _precedes = self.get_precedes()
+        _overlaps = self.get_overlaps()
+        _overlapped = self.get_overlapped()
+        _during = self.get_during()
+        _contains = self.get_contains()
+        
+        if _next:
+	    print "next=" + _next.get_id()
+        if _prev:
+	    print "prev=" + _prev.get_id()
+        if _equal:
+	    print "equivalent=" +self._generate_map_list_string(_equal, False)
+        if _follows:
+	    print "follows=" +self._generate_map_list_string(_follows, False)
+        if _precedes:
+	    print "precedes=" +self._generate_map_list_string(_precedes, False)
+        if _overlaps:
+	    print "overlaps=" +self._generate_map_list_string(_overlaps, False)
+        if _overlapped:
+	    print "overlapped=" +self._generate_map_list_string(_overlapped, False)
+        if _during:
+	    print "during=" +self._generate_map_list_string(_during, False)
+        if _contains:
+	    print "contains=" +self._generate_map_list_string(_contains, False)
+                
 ###############################################################################
 
-class abstract_map_dataset(abstract_dataset):
+class abstract_map_dataset(temporal_map_relations):
     """!This is the base class for all maps (raster, vector, raster3d) 
        providing additional function to set the valid time and the spatial extent.
     """
-      
+    def __init__(self):
+	temporal_map_relations.__init__(self)
+	
     def get_new_stds_instance(self, ident):
         """!Return a new space time dataset instance in which maps are stored with the type of this class
 
@@ -193,6 +498,8 @@
                     string += ",%s" % ds["id"]
                 count += 1
         print " | Registered datasets ........ " + string
+        if self.is_temporal_topology_build():
+	    self.print_temporal_topology_info()
         print " +----------------------------------------------------------------------------+"
 
     def print_shell_info(self):
@@ -207,14 +514,18 @@
         datasets = self.get_registered_datasets()
         count = 0
         string = ""
-        for ds in datasets:
-            if count == 0:
-                string += ds["id"]
-            else:
-                string += ",%s" % ds["id"]
-            count += 1
-        print "registered_datasets=" + string
+        if datasets:
+	    for ds in datasets:
+		if count == 0:
+		    string += ds["id"]
+		else:
+		    string += ",%s" % ds["id"]
+		count += 1
+	    print "registered_datasets=" + string
 
+        if self.is_temporal_topology_build():
+	    self.print_temporal_topology_shell_info()
+	    
     def insert(self, dbif=None, execute=True):
         """!Insert temporal dataset entry into database from the internal structure
 

Modified: grass/trunk/lib/python/temporal/datetime_math.py
===================================================================
--- grass/trunk/lib/python/temporal/datetime_math.py	2012-04-24 21:23:22 UTC (rev 51526)
+++ grass/trunk/lib/python/temporal/datetime_math.py	2012-04-24 22:55:15 UTC (rev 51527)
@@ -198,11 +198,11 @@
         elif has_hours: # Start at 0 minutes and seconds
             seconds = 0
             minutes = 0
-        elif has_days: # Start at 0 hours, minuts and seconds
+        elif has_days: # Start at 0 hours, minutes and seconds
             seconds = 0
             minutes = 0
             hours = 0
-        elif has_weeks: # Start at the first day of the week (monday) at 00:00:00
+        elif has_weeks: # Start at the first day of the week (Monday) at 00:00:00
             seconds = 0
             minutes = 0
             hours = 0

Modified: grass/trunk/lib/python/temporal/space_time_datasets.py
===================================================================
--- grass/trunk/lib/python/temporal/space_time_datasets.py	2012-04-24 21:23:22 UTC (rev 51526)
+++ grass/trunk/lib/python/temporal/space_time_datasets.py	2012-04-24 22:55:15 UTC (rev 51527)
@@ -42,6 +42,7 @@
        map information and valid time stamps into the SQL temporal database.
     """
     def __init__(self, ident):
+	abstract_map_dataset.__init__(self)
 	self.reset(ident)
 
     def get_type(self):
@@ -248,6 +249,7 @@
        map information and valid time stamps into the SQL temporal database.
     """
     def __init__(self, ident):
+	abstract_map_dataset.__init__(self)
 	self.reset(ident)
 
     def get_type(self):
@@ -462,6 +464,7 @@
        map information and valid time stamps into the SQL temporal database.
     """
     def __init__(self, ident):
+	abstract_map_dataset.__init__(self)
 	self.reset(ident)
 
     def get_type(self):

Modified: grass/trunk/lib/python/temporal/space_time_datasets_tools.py
===================================================================
--- grass/trunk/lib/python/temporal/space_time_datasets_tools.py	2012-04-24 21:23:22 UTC (rev 51526)
+++ grass/trunk/lib/python/temporal/space_time_datasets_tools.py	2012-04-24 22:55:15 UTC (rev 51527)
@@ -112,7 +112,7 @@
         else:
             maplist = maps.split(",")
 
-	# Build the maplist again with the ids
+	# Build the map list again with the ids
 	for count in range(len(maplist)):
 	    row = {}
 	    mapid = dummy.build_id(maplist[count], mapset, None)
@@ -203,6 +203,7 @@
                 if map.get_layer():
 		    core.fatal(_("Unable to register %s map <%s> with layer. The temporal types are different.") %  \
 		                 (map.get_type(), map.get_map_id(), map.get_layer()))
+		else:
 		    core.fatal(_("Unable to register %s map <%s>. The temporal types are different.") %  \
 		                 (map.get_type(), map.get_map_id()))
 

Modified: grass/trunk/lib/python/temporal/temporal_extent.py
===================================================================
--- grass/trunk/lib/python/temporal/temporal_extent.py	2012-04-24 21:23:22 UTC (rev 51526)
+++ grass/trunk/lib/python/temporal/temporal_extent.py	2012-04-24 22:55:15 UTC (rev 51527)
@@ -134,7 +134,7 @@
 	    return False
 
     def follows(self, extent):
-	"""!Return True if this time object is temporal follows the provided time object
+	"""!Return True if this time object temporally follows the provided time object
 	   A            |---------|
 	   B  |---------|
 	"""
@@ -220,8 +220,8 @@
         else:
 	    return False
 
-    def overlaps(self, extent):
-	"""!Return True if this time object is temporal overlaps the provided time object
+    def overlapped(self, extent):
+	"""!Return True if this time object temporally overlapped the provided time object
            A  |---------|
 	   B    |---------|
 	"""
@@ -234,8 +234,8 @@
         else:
 	    return False
 
-    def overlapped(self, extent):
-	"""!Return True if this time object is temporal overlapped by the provided time object
+    def overlaps(self, extent):
+	"""!Return True if this time object temporally overlaps the provided time object
 	   A    |---------|
            B  |---------|
 	"""

Modified: grass/trunk/lib/python/temporal/temporal_relationships.py
===================================================================
--- grass/trunk/lib/python/temporal/temporal_relationships.py	2012-04-24 21:23:22 UTC (rev 51526)
+++ grass/trunk/lib/python/temporal/temporal_relationships.py	2012-04-24 22:55:15 UTC (rev 51527)
@@ -20,17 +20,194 @@
 
 @author Soeren Gebbert
 """
-from abstract_dataset import *
+from abstract_map_dataset import *
 from datetime_math import *
 
+class temporal_topology_builder(object):
+    """!This class is designed to build the temporal topology based on a list of maps
+    
+	Example:
+	
+	# We have a space time raster dataset and build a map list
+	# from all registered maps ordered by start time
+	maps = strds.get_registered_maps_as_objects()
+	
+	# Now lets build the temporal topology of the maps in the list
+	tb = temporal_topology_builder()
+	tb.build(maps, True)
+	
+	for _map in tb:
+	    _map.print_temporal_topology_info()
+	    _follows = _map.get_follows()
+	    if _follows:
+		for f in _follows:
+		    f.print_temporal_topology_info()
+	    
+	# Using the next and previous methods, we can iterate over the 
+	# topological related maps in this way
+	
+	_first = tb.get_first()
+	
+	while _first:
+	    _first.print_temporal_topology_info()
+	    _first = _first.next()
+	
+	# Dictionary like accessed
+	_map = tb["name at mapset"]
+	       
+    
+    """
+    def __init__(self):
+	self._reset()
+        
+    def _reset(self):
+        self._store = {}
+        self._first = None
 
+    def _set_first(self, first):
+        self._first = first
+        self._insert(first)        
+        
+    def _detect_first(self):
+	if len(self) > 0:
+	    _prev = self._store.values()[0]
+	    while _prev != None:
+		self._first = _prev
+		_prev = _prev.prev()
+		
+    def _insert(self, t):
+        self._store[t.get_id()] = t
+        
+    def get_first(self):
+	"""!Return the first map with the earliest start time
+	
+	   @return The map with the earliest start time
+	"""
+	return self._first
+	
+    def build(self, maps, is_sorted = False):
+	"""!Build the temporal topology structure
+	
+	   This method builds the temporal topology based on all maps in the provided map list.
+	   The temporal topology structure of each map, defined in class temporal_map_relations,
+	   will be reseted and rebuild. 
+	   
+	   After building the temporal topology the modified map objects can be accessed 
+	   in the same way as a dictionary using there id. The implemented iterator assures 
+	   the chronological iteration over the maps.
+	   
+	   
+	   @param maps: A list of abstract_dataset objects with initiated temporal extent
+	   @param is_sorted Set to True if the map list is sorted by start time, sorting will dramatically reduce computation time
+	"""
+	for _map in maps:
+	    _map.reset_temporal_topology()
+	
+	for i in xrange(len(maps)):
+	    if is_sorted:
+		offset = i + 1
+		found_next = False
+	    else:
+		offset = 0
+		# Needed for "next" computation 
+		start0, end0 = maps[i].get_valid_time()
+	    
+	    for j in xrange(offset, len(maps)):
+		
+		# Do not build topology of the same maps
+		if maps[i] == maps[j]:
+		    continue
+		
+		# Get the temporal relationship
+		relation = maps[j].temporal_relation(maps[i])
+		
+		# We can skip several relationships if not sorted
+		if not is_sorted:
+		    if relation == "before":
+			continue
+		    if relation == "precedes":
+			continue
+		    if relation == "overlapped":
+			continue
+		    if relation == "finished":
+			continue
+		
+		# Build the next reference
+		if is_sorted:
+		    if not found_next and relation != "equivalent" and relation != "started":
+			maps[i].set_next(maps[j])
+			found_next = True
+		else: 
+		    start2, end2 = maps[j].get_valid_time()
+		    if maps[i].next():
+			start1, end1 = maps[i].next().get_valid_time()
+			if start2 > start0 and start2 < start1:
+			    maps[i].set_next(maps[j])
+		    else:
+			if start2 > start0:
+			    maps[i].set_next(maps[j])
+			    
+		# The start time of map j is equal or later than map i
+		if relation == "equivalent":
+		    maps[j].append_equivalent(maps[i])
+		    maps[i].append_equivalent(maps[j])
+		elif relation == "follows":
+		    maps[j].append_follows(maps[i])
+		    maps[i].append_precedes(maps[j])
+		elif relation == "during" or relation == "starts" or relation == "finishes":
+		    maps[j].append_during(maps[i])
+		    maps[i].append_contains(maps[j])
+		elif relation == "started":
+		    # Consider equal start time, in case "started" map j contains map i
+		    maps[j].append_contains(maps[i])
+		    maps[i].append_during(maps[j])
+		elif relation == "overlaps":
+		    maps[j].append_overlaps(maps[i])
+		    maps[i].append_overlapped(maps[j])
+
+		# Break if the last map follows
+		if relation == "follows":
+		    if j < len(maps) - 1:
+			relation = maps[j + 1].temporal_relation(maps[i])
+			if relation == "after":
+			    break
+		# Break if the the next map is after
+		if relation == "after":
+		    break 
+	
+	# Build the previous pointer and store the map internally
+	for _map in maps:
+	    _next = _map.next()
+	    if _next:
+		_next.set_prev(_map)
+	    _map.set_temporal_topology_build_true()
+	    self._insert(_map)
+	
+	# Detect the first map
+	self._detect_first()
+	
+    def __iter__(self):
+        _start = self._first
+        while _start != None:
+            yield _start
+            _start = _start.next()
+
+    def __getitem__(self, index):
+        return self._store[index.get_id()]
+
+    def __len__(self):
+        return len(self._store)
+
+    def __contains__(self, _map):
+        return _map in self._store.values()
+
+
 def print_temporal_relations(maps1, maps2):
     """!Print the temporal relation matrix of the temporal ordered map lists maps1 and maps2
        to stdout.
 	
-	@param maps1: a ordered by start_time list of map objects
-	@param maps2: a ordered by start_time list of map objects
-	@param dbif: The database interface to be used
+	@param maps1: a ordered by start_time list of map objects with initiated temporal extent
+	@param maps2: a ordered by start_time list of map objects with initiated temporal extent
     """
     
     identical = False
@@ -64,16 +241,16 @@
 		break
 
 def get_temporal_relation_matrix(maps1, maps2):
-    """!Return the temporal relation matrix of all registered maps as list of lists
+    """!Return the temporal relation matrix of two map lists
 
-	The map list must be ordered by start time
+	Booth map lists must be ordered by start time
 
-	The temporal relation matrix includes the temporal relations between
-	all registered maps. Returned is a nested dict representing 
+	The temporal relationship matrix includes the temporal relations between
+	the two map lists. Returned is a nested dict representing 
 	a sparse (upper right side in case maps1 == maps2) relationship matrix.
 	
-	@param maps: a ordered by start_time list of map objects
-	@param dbif: The database interface to be used
+	@param maps1: A sorted (start_time) list of abstract_dataset objects with initiated temporal extent
+	@param maps2: A sorted (start_time) list of abstract_dataset objects with initiated temporal extent
     """
 
     matrix = {}
@@ -110,13 +287,13 @@
     return matrix
 
 def count_temporal_relations(maps1, maps2):
-    """!Count the temporal relations between the registered maps.
+    """!Count the temporal relations between the two lists of maps
 
 	The map lists must be ordered by start time. Temporal relations are counted 
 	by analyzing the sparse (upper right side in case maps1 == maps2) temporal relationships matrix.
 
-	@param maps: A sorted (start_time) list of abstract_dataset objects
-	@param dbif: The database interface to be used
+	@param maps1: A sorted (start_time) list of abstract_dataset objects with initiated temporal extent
+	@param maps2: A sorted (start_time) list of abstract_dataset objects with initiated temporal extent
 	@return A dictionary with counted temporal relationships
     """
     
@@ -134,6 +311,9 @@
 	for j in range(start, len(maps2)):
 	    relation = maps1[j].temporal_relation(maps2[i])
 
+	    if relation == "before":
+		continue
+	    
 	    if tcount.has_key(relation):
 		tcount[relation] = tcount[relation] + 1
 	    else:

Modified: grass/trunk/lib/python/temporal/unit_tests.py
===================================================================
--- grass/trunk/lib/python/temporal/unit_tests.py	2012-04-24 21:23:22 UTC (rev 51526)
+++ grass/trunk/lib/python/temporal/unit_tests.py	2012-04-24 22:55:15 UTC (rev 51527)
@@ -1411,13 +1411,83 @@
     print relation
     if relation!= "meet":
 	core.error("Wrong spatial relation: %s"%(relation))
+	
+def test_temporal_topology_builder():
+    map_list = []
+    count = 0
+    for year in xrange(0,1):
+	for month in xrange(1,6):
+	    start = datetime(2001 + year, month, 01)
+	    end = datetime(2001 + year, month + 1, 01)
+	    _map = raster_dataset("%d at A"%(count))
+	    _map.set_absolute_time(start, end)
+	    map_list.append(_map)
+	    count += 1
+
+    tb = temporal_topology_builder()
+    tb.build(map_list, True)
+
+    for _map in tb:
+	_map.print_info()
  
+    map_list = []
+    for year in xrange(0,1):
+	for month in xrange(1,6):
+	    start = datetime(2001 + year, month, 01)
+	    end = datetime(2001 + year, month + 1, 01)
+	    _map = raster_dataset("%d at A"%(count))
+	    _map.set_absolute_time(start, end)
+	    map_list.append(_map)
+	    count += 1
+	    
+	    start = datetime(2001 + year, month, 14)
+	    end = datetime(2001 + year, month + 1, 14)
+	    _map = raster_dataset("%d at A"%(count))
+	    _map.set_absolute_time(start, end)
+	    map_list.append(_map)
+	    count += 1
+	    
+	    start = datetime(2001 + year, month, 8)
+	    end = datetime(2001 + year, month + 1, 21)
+	    _map = raster_dataset("%d at A"%(count))
+	    _map.set_absolute_time(start, end)
+	    map_list.append(_map)
+	    count += 1
+
+    tb = temporal_topology_builder()
+    tb.build(map_list, False)
+    for _map in tb:
+	
+	print _map.get_id()
+	_map.absolute_time.print_info()
+	_map.print_temporal_topology_info()
+	
+    # Test the performance of many overlapping maps
+    count = 0
+    for year in xrange(0,200):
+	for month in xrange(1,12):
+	    start = datetime(1901 + year, month, 01)
+	    end = datetime(1904 + year, month + 1, 01)
+	    _map = raster_dataset("%d at A"%(count))
+	    _map.set_absolute_time(start, end)
+	    map_list.append(_map)
+	    count += 1
+	    
+    print "Build temporal topology with sorting for %i maps"%count
+    tb = temporal_topology_builder()
+    tb.build(map_list, True)
+	
+    print "Build temporal topology without sorting for %i maps"%count
+    tb = temporal_topology_builder()
+    tb.build(map_list, False)
+    
 if __name__ == "__main__":
     test_increment_datetime_by_string()
     test_adjust_datetime_to_granularity()
     test_spatial_extent_intersection()
-    #test_compute_relative_time_granularity()
+    ##test_compute_relative_time_granularity()
     test_compute_absolute_time_granularity()
     test_compute_datetime_delta()
     test_spatial_extent_intersection()
     test_spatial_relations()
+    test_temporal_topology_builder()
\ No newline at end of file



More information about the grass-commit mailing list