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

svn_grass at osgeo.org svn_grass at osgeo.org
Wed Nov 2 17:32:12 EDT 2011


Author: huhabla
Date: 2011-11-02 14:32:12 -0700 (Wed, 02 Nov 2011)
New Revision: 49056

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/space_time_datasets_tools.py
Log:
Added temporal sampling methods.


Modified: grass/trunk/lib/python/temporal/abstract_dataset.py
===================================================================
--- grass/trunk/lib/python/temporal/abstract_dataset.py	2011-11-02 20:51:27 UTC (rev 49055)
+++ grass/trunk/lib/python/temporal/abstract_dataset.py	2011-11-02 21:32:12 UTC (rev 49056)
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
 """!@package grass.temporal
 
 @brief GRASS Python scripting module (temporal GIS functions)
@@ -100,7 +101,12 @@
         bottom = self.spatial_extent.get_bottom()
         
         return (north, south, east, west, top, bottom)
+
+    def spatial_overlap(self, dataset):
+        """Return True if the spatial extents overlap"""
         
+        north = self.spatial_extent.overlap(dataset.spatial_extent)
+        
     def select(self, dbif=None):
 	"""Select temporal dataset entry from database and fill up the internal structure"""
 

Modified: grass/trunk/lib/python/temporal/abstract_map_dataset.py
===================================================================
--- grass/trunk/lib/python/temporal/abstract_map_dataset.py	2011-11-02 20:51:27 UTC (rev 49055)
+++ grass/trunk/lib/python/temporal/abstract_map_dataset.py	2011-11-02 21:32:12 UTC (rev 49056)
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
 """!@package grass.temporal
 
 @brief GRASS Python scripting module (temporal GIS functions)
@@ -48,6 +49,10 @@
         """
         raise IOError("This method must be implemented in the subclasses")
         
+    def load(self):
+        """Load the content of this object from map files"""
+        raise IOError("This method must be implemented in the subclasses")
+
     def set_absolute_time(self, start_time, end_time=None, timezone=None):
         """Set the absolute time interval with start time and end time
         

Modified: grass/trunk/lib/python/temporal/abstract_space_time_dataset.py
===================================================================
--- grass/trunk/lib/python/temporal/abstract_space_time_dataset.py	2011-11-02 20:51:27 UTC (rev 49055)
+++ grass/trunk/lib/python/temporal/abstract_space_time_dataset.py	2011-11-02 21:32:12 UTC (rev 49056)
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
 """!@package grass.temporal
 
 @brief GRASS Python scripting module (temporal GIS functions)
@@ -39,13 +40,6 @@
     def __init__(self, ident):
 	self.reset(ident)
 
-    def get_new_instance(self, ident=None):
-        """Return a new instance with the type of this class
-
-           @param ident: The unique identifier of the new object
-        """
-        raise IOError("This method must be implemented in the subclasses")
-
     def get_new_map_instance(self, ident=None):
         """Return a new instance of a map dataset which is associated with the type of this class
 
@@ -345,10 +339,154 @@
 
         return True
 
+    def sample_by_dataset_topology_simple(self, stds, dbif=None):
+        """Sample this space time dataset with the temporal topology of a second space time dataset
+
+           Only the start time of the registered maps of the dataset is considered. So that maps with end time 
+           in a sample granule are not listed.
+        
+           Return all registered maps as ordered (by start_time) object list with 
+           "gap" map objects (id==None). Each list entry is a list of map objects
+           which are potentially located in each granule of the second space time dataset.
+
+           A valid temporal topology (no overlapping or inclusion allowed) is needed to get correct results. 
+    
+           The sample dataset must have "interval" as temporal map type, so all sample maps have valid interval time.
+
+           Gaps between maps are identified as unregistered maps with id==None.
+
+           The objects are initialized with the id and the temporal extent (temporal type, start time, end time).
+           In case more map informations are needed, use the select() method for each listed object.
+
+           @param stds: The space time dataset to be used for temporal sampling
+           @param dbif: The database interface to be used
+
+           In case nothing found None is returned
+        """
+
+        if self.get_temporal_type() != stds.get_temporal_type():
+            core.error(_("The space time datasets must be of the same temporal type"))
+            return None
+
+        if stds.get_map_time() != "interval":
+            core.error(_("The temporal map type of the sample dataset must be interval"))
+            return None
+
+
+        connect = False
+
+        if dbif == None:
+            dbif = sql_database_interface()
+            dbif.connect()
+            connect = True
+
+        obj_list = []
+        sample_maps = stds.get_registered_maps_as_objects_with_gaps(where=None, dbif=dbif)
+        
+
+        for sample in sample_maps:
+            start, end = sample.get_valid_time()
+
+            where = "((start_time >= '%s' and start_time < '%s'))" % (start, end)
+            rows = self.get_registered_maps("id", where, "start_time", dbif)
+
+            if rows:
+                maplist = []
+                for row in rows:
+                    map = self.get_new_map_instance(row["id"])
+
+                    if self.is_time_absolute():
+                        map.set_absolute_time(start, end)
+                    elif self.is_time_relative():
+                        map.set_relative_time(start, end)
+
+                    maplist.append(copy.copy(map))
+
+                obj_list.append(copy.copy(maplist))
+
+        if connect == True:
+            dbif.close()
+
+        return obj_list
+
+
+    def sample_by_dataset_topology(self, stds, dbif=None):
+        """Sample this space time dataset with the temporal topology of a second space time dataset
+
+           This dataset and the sample dataset must have "interval" as temporal map type, so all maps have valid interval time.
+        
+           Return all registered maps as ordered (by start_time) object list with 
+           "gap" map objects (id==None). Each list entry is a list of map objects
+           which are potentially located in each granule of the second space time dataset.
+
+           A valid temporal topology (no overlapping or inclusion allowed) is needed to get correct results. 
+    
+           Gaps between maps are identified as unregistered maps with id==None.
+
+           The objects are initialized with the id and the temporal extent (temporal type, start time, end time).
+           In case more map informations are needed, use the select() method for each listed object.
+
+           @param stds: The space time dataset to be used for temporal sampling
+           @param dbif: The database interface to be used
+
+           In case nothing found None is returned
+        """
+
+        if self.get_temporal_type() != stds.get_temporal_type():
+            core.error(_("The space time datasets must be of the same temporal type"))
+            return None
+
+        if self.get_map_time() != "interval":
+            core.error(_("The temporal map type of the dataset must be interval"))
+            return None
+
+        if stds.get_map_time() != "interval":
+            core.error(_("The temporal map type of the sample dataset must be interval"))
+            return None
+
+
+        connect = False
+
+        if dbif == None:
+            dbif = sql_database_interface()
+            dbif.connect()
+            connect = True
+
+        obj_list = []
+        sample_maps = stds.get_registered_maps_as_objects_with_gaps(where=None, dbif=dbif)
+        
+
+        for sample in sample_maps:
+            start, end = sample.get_valid_time()
+
+            where = "((start_time <= '%s' and end_time >= '%s') OR (start_time >= '%s' and end_time <= '%s') OR (start_time < '%s' and end_time >= '%s') OR (start_time <= '%s' and end_time > '%s'))" % (start, end, start, end, end, end, start, start)
+            rows = self.get_registered_maps("id", where, "start_time", dbif)
+
+            if rows:
+                maplist = []
+                for row in rows:
+                    map = self.get_new_map_instance(row["id"])
+
+                    if self.is_time_absolute():
+                        map.set_absolute_time(start, end)
+                    elif self.is_time_relative():
+                        map.set_relative_time(start, end)
+
+                    maplist.append(copy.copy(map))
+
+                obj_list.append(copy.copy(maplist))
+
+        if connect == True:
+            dbif.close()
+
+        return obj_list
+
+
     def get_registered_maps_as_objects_by_granularity(self, gran=None, dbif=None):
         """Return all registered maps as ordered (by start_time) object list with 
            "gap" map objects (id==None) for temporal topological operations using the
-           granularity of the space time dataset as increment
+           granularity of the space time dataset as increment. Each list entry is a list of map objects
+           which are potentially located in the actual granule.
 
            A valid temporal topology (no overlapping or inclusion allowed) is needed to get correct results. 
     
@@ -374,11 +512,6 @@
 
         obj_list = []
 
-        if self.get_map_time() != "interval":
-            core.error(_("The temporal map type must be interval"))
-            #TODO: Check for valid topology too?
-            return None
-        
         if gran == None:
             gran = self.get_granularity()
 
@@ -390,26 +523,28 @@
             else:
                 next = start + gran
 
-            where = "(start_time <= '%s' and end_time >= '%s')" % (start, next)
+            where = "((start_time <= '%s' and end_time >= '%s') OR (start_time >= '%s' and end_time <= '%s') OR (start_time < '%s' and end_time >= '%s') OR (start_time <= '%s' and end_time > '%s'))" % (start, end, start, end, end, end, start, start)
 
             rows = self.get_registered_maps("id", where, "start_time", dbif)
 
             if rows:
                 if len(rows) > 1:
-                    core.error(_("More than one map found in a granule. Temporal granularity seems to be invalid or the chosen granularity is not a greatest common divider of all intervals and gaps in the dataset."))
-                # Take the first map    
-                map = self.get_new_map_instance(rows[0]["id"])
-            else:
-                # In case of a gap, create a dummy map with identifier None
-                map = self.get_new_map_instance(None)
+                    core.warning(_("More than one map found in a granule. Temporal granularity seems to be invalid or the chosen granularity is not a greatest common divider of all intervals and gaps in the dataset."))
+ 
+                maplist = []
+                for row in rows:
+                   # Take the first map    
+                    map = self.get_new_map_instance(rows[0]["id"])
 
-            if self.is_time_absolute():
-                map.set_absolute_time(start, next)
-            elif self.is_time_relative():
-                map.set_relative_time(start, next)
+                    if self.is_time_absolute():
+                        map.set_absolute_time(start, next)
+                    elif self.is_time_relative():
+                        map.set_relative_time(start, next)
 
-            obj_list.append(copy.copy(map))
+                    maplist.append(copy.copy(map))
 
+            obj_list.append(copy.copy(maplist))
+
             start = next
 
         if connect == True:

Modified: grass/trunk/lib/python/temporal/space_time_datasets_tools.py
===================================================================
--- grass/trunk/lib/python/temporal/space_time_datasets_tools.py	2011-11-02 20:51:27 UTC (rev 49055)
+++ grass/trunk/lib/python/temporal/space_time_datasets_tools.py	2011-11-02 21:32:12 UTC (rev 49056)
@@ -597,9 +597,18 @@
 
         if maps and len(maps) > 0:
 
-            first_time, dummy = maps[0].get_valid_time()
+            if isinstance(maps[0], list):
+                first_time, dummy = maps[0][0].get_valid_time()
+            else:
+                first_time, dummy = maps[0].get_valid_time()
 
-            for map in maps:
+            for mymap in maps:
+
+                if isinstance(mymap, list):
+                    map = mymap[0]
+                else:
+                    map = mymap
+
                 start, end = map.get_valid_time()
                 if end:
                     delta = end -start
@@ -668,3 +677,99 @@
                     print output
 
 
+def sample_stds_by_stds_topology(intype, sampletype, input, sampler, header, separator, use_simple):
+    """ Sample the input space time dataset with a sample space time dataset and print the result to stdout
+
+        In case multiple maps are located in the current granule, the map names are separated by comma.
+
+        Attention: Do not use the comma as separator
+
+        @param input: Name of a space time dataset
+        @param sampler: Name of a space time dataset used for temporal sampling
+    """
+    mapset =  core.gisenv()["MAPSET"]
+
+    if input.find("@") >= 0:
+        id = input
+    else:
+        id = input + "@" + mapset
+
+    sp = dataset_factory(intype, id)
+
+    if sampler.find("@") >= 0:
+        sid = sampler
+    else:
+        sid = sampler + "@" + mapset
+
+    ssp = dataset_factory(sampletype, sid)
+
+    dbif = sql_database_interface()
+    dbif.connect()
+
+
+    if sp.is_in_db(dbif) == False:
+        core.fatal(_("Dataset <%s> not found in temporal database") % (id))
+
+    if ssp.is_in_db(dbif) == False:
+        core.fatal(_("Dataset <%s> not found in temporal database") % (sid))
+
+    sp.select(dbif)
+    ssp.select(dbif)
+
+    if separator == None or separator == "" or separator.find(",") >= 0:
+        separator = " | "
+       
+    if use_simple:
+        mapmatrix = sp.sample_by_dataset_topology_simple(ssp, dbif)
+    else:
+        mapmatrix = sp.sample_by_dataset_topology(ssp, dbif)
+    samplerlist = ssp.get_registered_maps_as_objects_with_gaps(dbif=dbif)
+
+    if mapmatrix and len(mapmatrix) > 0:
+
+        if header:
+            string = ""
+            string += "%s%s" % ("sample_id", separator)
+            string += "%s%s" % ("ids", separator)
+            string += "%s%s" % ("start_time", separator)
+            string += "%s%s" % ("end_time", separator)
+            string += "%s%s" % ("interval_length", separator)
+            string += "%s"   % ("distance_from_begin")
+            print string
+
+        first_time, dummy = mapmatrix[0][0].get_valid_time()
+
+        for i in range(len(mapmatrix)):
+            mapnames = ""
+            count = 0
+            for map in mapmatrix[i]:
+                if count == 0:
+                    mapnames += map.get_id()
+                else:
+                    mapnames += ",%s" % map.get_id()
+                count += 1
+            
+            map = mapmatrix[i][0]
+
+            start, end = map.get_valid_time()
+            if end:
+                delta = end - start
+            else:
+                delta = None
+            delta_first = start - first_time
+
+            if map.is_time_absolute():
+                if end:
+                    delta = time_delta_to_relative_time(delta)
+                delta_first = time_delta_to_relative_time(delta_first)
+
+            string = ""
+            string += "%s%s" % (samplerlist[i].get_id(), separator)
+            string += "%s%s" % (mapnames, separator)
+            string += "%s%s" % (start, separator)
+            string += "%s%s" % (end, separator)
+            string += "%s%s" % (delta, separator)
+            string += "%s"   % (delta_first)
+            print string
+
+    dbif.close()



More information about the grass-commit mailing list