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

svn_grass at osgeo.org svn_grass at osgeo.org
Thu Jan 26 07:23:10 EST 2012


Author: huhabla
Date: 2012-01-26 04:23:09 -0800 (Thu, 26 Jan 2012)
New Revision: 50467

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/aggregation.py
   grass/trunk/lib/python/temporal/base.py
   grass/trunk/lib/python/temporal/core.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/spatial_extent.py
   grass/trunk/lib/python/temporal/temporal_extent.py
   grass/trunk/lib/python/temporal/temporal_granularity.py
Log:
Implemented handling of time-stamped vector layers



Modified: grass/trunk/lib/python/temporal/abstract_dataset.py
===================================================================
--- grass/trunk/lib/python/temporal/abstract_dataset.py	2012-01-26 12:22:41 UTC (rev 50466)
+++ grass/trunk/lib/python/temporal/abstract_dataset.py	2012-01-26 12:23:09 UTC (rev 50467)
@@ -66,8 +66,41 @@
 	self.metadata.print_self()
 
     def get_id(self):
+	"""Return the unique identifier of the dataset"""
         return self.base.get_id()
 
+    def get_name(self):
+	"""Return the name"""
+        return self.base.get_name()
+
+    def get_mapset(self):
+	"""Return the mapset"""
+        return self.base.get_mapset()
+
+    def build_id(name, mapset, layer=None):
+	"""Build and return the id (primary key) based on name, mapset and layer of a dataset.
+	
+	   @param name: The name of the map
+	   @param mapset: The name of the mapset
+	   @param layer: The name of the layer (optional)
+	
+	   Return None in case the name can not be build (name or mapset are None)
+	"""
+	
+	if not name or not mapset:
+	    return None
+	    
+	# Make sure to extract the pure mapname
+	pure_name = name.split("@")[0].split(":")[0]
+	
+	if layer:
+	    return "%s:%s@%s"%(name, layer, mapset)
+	else:
+	    return "%s@%s"%(name, mapset)
+	
+	return None
+	
+
     def get_valid_time(self):
         """Returns a tuple of the start, the end valid time, this can be either datetime or double values
            @return A tuple of (start_time, end_time)

Modified: grass/trunk/lib/python/temporal/abstract_map_dataset.py
===================================================================
--- grass/trunk/lib/python/temporal/abstract_map_dataset.py	2012-01-26 12:22:41 UTC (rev 50466)
+++ grass/trunk/lib/python/temporal/abstract_map_dataset.py	2012-01-26 12:23:09 UTC (rev 50467)
@@ -58,6 +58,41 @@
         """Load the content of this object from map files"""
         raise IOError("This method must be implemented in the subclasses")
  
+    def get_map_id(self):
+	"""Return the map id. The map id is the unique map identifier in grass and must not be equal to the 
+	   primary key identifier (id) of the map in the database. Since vector maps may have layer information,
+	   the unique id is a combination of name, layer and mapset.
+	   
+	   Use get_map_id() every time your need to access the grass map in the file system but not to identify
+	   map information in the temporal database.
+	
+	"""
+        return self.base.get_map_id()
+
+    def build_id(self, name, mapset, layer=None):
+	"""Convenient method to build the unique identifier
+	
+	    Existing layer and mapset definitions in the name string will be reused
+
+           @param return the id of the vector map as name(:layer)@mapset while layer is optional
+        """
+        
+        # Check if the name includes any mapset
+	if name.find("@") >= 0:
+	    name, mapset = name.split("@")[0]
+
+	if name.find(":") >= 0:
+	    name, layer = name.split(":")[0]
+	    
+        if layer:	    
+	    return "%s:%s@%s"%(name, layer, mapset)
+	else:
+	    return "%s@%s"%(name, mapset)
+	    
+    def get_layer(self):
+	"""Return the layer of the map or None in case no layer is defined"""
+	return self.base.get_layer()
+        
     def print_info(self):
         """Print information about this class in human readable style"""
         
@@ -128,14 +163,23 @@
         
         """
         if start_time and not isinstance(start_time, datetime) :
-            core.fatal(_("Start time must be of type datetime for %s map <%s>") % (self.get_type(), self.get_id()))
+	    if self.get_layer():
+		core.fatal(_("Start time must be of type datetime for %s map <%s> with layer: %s") % (self.get_type(), self.get_map_id(), self.get_layer()))
+	    else:
+		core.fatal(_("Start time must be of type datetime for %s map <%s>") % (self.get_type(), self.get_map_id()))
 
         if end_time and not isinstance(end_time, datetime) :
-            core.fatal(_("End time must be of type datetime for %s map <%s>") % (self.get_type(), self.get_id()))
+	    if self.get_layer():
+		core.fatal(_("End time must be of type datetime for %s map <%s> with layer: %s") % (self.get_type(), self.get_map_id(), self.get_layer()))
+	    else:
+		core.fatal(_("End time must be of type datetime for %s map <%s>") % (self.get_type(), self.get_map_id()))
 
         if start_time and end_time:
             if start_time > end_time:
-                core.fatal(_("End time must be greater than start time for %s map <%s>") % (self.get_type(), self.get_id()))
+		if self.get_layer():
+		    core.fatal(_("End time must be greater than start time for %s map <%s> with layer: %s") % (self.get_type(), self.get_map_id(), self.get_layer()))
+		else:
+		    core.fatal(_("End time must be greater than start time for %s map <%s>") % (self.get_type(), self.get_map_id()))
             else:
                 # Do not create an interval in case start and end time are equal
                 if start_time == end_time:
@@ -182,27 +226,33 @@
             end = datetime_to_grass_datetime_string(end_time)
             start += " / %s"%(end)
 
-        core.run_command(self.get_timestamp_module_name(), map=self.get_id(), date=start)
+        core.run_command(self.get_timestamp_module_name(), map=self.get_map_id(), date=start)
 
     def set_relative_time(self, start_time, end_time, unit):
         """Set the relative time interval 
         
            @param start_time: A double value 
            @param end_time: A double value 
-           @param unit: The unit of the relative time. Supported uits: years, months, days, hours, minutes, seconds
+           @param unit: The unit of the relative time. Supported units: years, months, days, hours, minutes, seconds
 
            Return True for success and False otherwise
 
         """
 
         if not self.check_relative_time_unit(unit):
-            core.error(_("Unsupported relative time unit type for %s map <%s>: %s") % (self.get_type(), self.get_id(), unit))
+	    if self.get_layer():
+		core.error(_("Unsupported relative time unit type for %s map <%s> with layer %s: %s") % (self.get_type(), self.get_id(), self.get_layer(), unit))
+	    else:
+		core.error(_("Unsupported relative time unit type for %s map <%s>: %s") % (self.get_type(), self.get_id(), unit))
             return False
         
 
         if start_time != None and end_time != None:
             if int(start_time) > int(end_time):
-                core.error(_("End time must be greater than start time for %s map <%s>") % (self.get_type(), self.get_id()))
+		if self.get_layer():
+		    core.error(_("End time must be greater than start time for %s map <%s> with layer %s") % (self.get_type(), self.get_id(), self.get_layer()))
+		else:
+		    core.error(_("End time must be greater than start time for %s map <%s>") % (self.get_type(), self.get_id()))
                 return False
             else:
                 # Do not create an interval in case start and end time are equal
@@ -255,7 +305,7 @@
         if end_time:
             end = "%i %s"%(int(end_time), unit)
             start += " / %s"%(end)
-        core.run_command(self.get_timestamp_module_name(), map=self.get_id(), date=start)
+        core.run_command(self.get_timestamp_module_name(), map=self.get_map_id(), date=start)
 
     def set_spatial_extent(self, north, south, east, west, top=0, bottom=0):
         """Set the spatial extent of the map
@@ -265,7 +315,7 @@
            @param east: The eastern edge
            @param west: The western edge
            @param top: The top edge
-           @param bottom: The bottom ege
+           @param bottom: The bottom edge
         """
         self.spatial_extent.set_spatial_extent(north, south, east, west, top, bottom)
         
@@ -279,10 +329,13 @@
         if start != None:
             if end != None:
                 if start >= end:
-                    core.error(_("Map <%s> has incorrect time interval, start time is greater than end time") % (self.get_id()))
+		    if self.get_layer():
+			core.error(_("Map <%s> with layer %s has incorrect time interval, start time is greater than end time") % (self.get_map_id(), self.get_layer()))
+		    else:
+			core.error(_("Map <%s> has incorrect time interval, start time is greater than end time") % (self.get_map_id()))
                     return False
         else:
-            core.error(_("Map <%s> has incorrect start time") % (self.get_id()))
+            core.error(_("Map <%s> has incorrect start time") % (self.get_map_id()))
             return False
 
         return True
@@ -327,7 +380,7 @@
             self.base.delete(dbif)
 
         # Remove the timestamp from the file system
-        core.run_command(self.get_timestamp_module_name(), map=self.get_id(), date="none")
+        core.run_command(self.get_timestamp_module_name(), map=self.get_map_id(), date="none")
 
         self.reset(None)
         dbif.connection.commit()
@@ -339,11 +392,15 @@
 	""" Remove the map entry in each space time dataset in which this map is registered
 
            @param dbif: The database interface to be used
-           @param update: Call for each unregister statement the update_from_registered_maps 
-                          of the space time dataset. This can slow down the unregistration process significantly.
+           @param update: Call for each unregister statement the update from registered maps 
+                          of the space time dataset. This can slow down the un-registration process significantly.
         """
 
-        core.verbose(_("Unregister %s dataset <%s> from space time datasets") % (self.get_type(), self.get_id()))
+	if self.get_layer():
+	    core.verbose(_("Unregister %s map <%s> with layer %s from space time datasets") % \
+	                   (self.get_type(), self.get_map_id(), self.get_layer()))
+	else:
+	    core.verbose(_("Unregister %s map <%s> from space time datasets") % (self.get_type(), self.get_map_id()))
         
         connect = False
 
@@ -368,7 +425,7 @@
                 stds.select(dbif)
                 stds.unregister_map(self, dbif)
                 # Take care to update the space time dataset after
-                # the map has been unregistred
+                # the map has been unregistered
                 if update == True:
                     stds.update_from_registered_maps(dbif)
 

Modified: grass/trunk/lib/python/temporal/abstract_space_time_dataset.py
===================================================================
--- grass/trunk/lib/python/temporal/abstract_space_time_dataset.py	2012-01-26 12:22:41 UTC (rev 50466)
+++ grass/trunk/lib/python/temporal/abstract_space_time_dataset.py	2012-01-26 12:23:09 UTC (rev 50467)
@@ -183,7 +183,7 @@
             self.relative_time.set_unit(unit)
 
     def get_map_time(self):
-        """Return the type of the map time, interval, point, maixed or invalid"""
+        """Return the type of the map time, interval, point, mixed or invalid"""
         
         temporal_type = self.get_temporal_type()
 
@@ -197,7 +197,7 @@
     def print_temporal_relation_matrix(self, maps):
         """Print the temporal relation matrix of all registered maps to stdout
 
-           The temproal relation matrix includes the temporal relations between
+           The temporal relation matrix includes the temporal relations between
            all registered maps. The relations are strings stored in a list of lists.
            
            @param dbif: The database interface to be used
@@ -227,11 +227,11 @@
                 print maps[i].base.get_name()
 
     def get_temporal_relation_matrix(self, maps):
-        """Return the temporal relation matrix of all registered maps as listof lists
+        """Return the temporal relation matrix of all registered maps as list of lists
 
            The map list must be ordered by start time
 
-           The temproal relation matrix includes the temporal relations between
+           The temporal relation matrix includes the temporal relations between
            all registered maps. The relations are strings stored in a list of lists.
            
            @param maps: a ordered by start_time list of map objects
@@ -293,10 +293,10 @@
         return tcount
 
     def count_gaps(self, maps):
-        """Count the number of gaps between temporal neighbours
+        """Count the number of gaps between temporal neighbors
         
            @param maps: A sorted (start_time) list of abstract_dataset objects
-           @return The numbers of gaps between temporal neighbours
+           @return The numbers of gaps between temporal neighbors
         """
 
         gaps = 0
@@ -473,7 +473,7 @@
         use_contain = False
         use_equal = False
 
-        # Inititalize the methods
+        # Initialize the methods
         if method:
             for name in method:
                 if name == "start":
@@ -731,7 +731,7 @@
     def get_registered_maps(self, columns=None, where = None, order = None, dbif=None):
         """Return sqlite rows of all registered maps.
         
-           In case columsn are not specified, each row includes all columns specified in the datatype specific view
+           In case columns are not specified, each row includes all columns specified in the datatype specific view
 
            @param columns: Columns to be selected as SQL compliant string
            @param where: The SQL where statement to select a subset of the registered maps without "WHERE"
@@ -856,14 +856,19 @@
         if map.is_in_db(dbif) == False:
             dbif.close()
             core.fatal(_("Only maps with absolute or relative valid time can be registered"))
+	if map.get_layer():
+	    core.verbose(_("Register %s map <%s> with layer %s in space time %s dataset <%s>") %  (map.get_type(), map.get_map_id(), map.get_layer(), map.get_type(), self.get_id()))
+	else:
+	    core.verbose(_("Register %s map <%s> in space time %s dataset <%s>") %  (map.get_type(), map.get_map_id(), map.get_type(), self.get_id()))
 
-        core.verbose(_("Register %s map <%s> in space time %s dataset <%s>") %  (map.get_type(), map.get_id(), map.get_type(), self.get_id()))
-
         # First select all data from the database
         map.select(dbif)
 
         if not map.check_valid_time():
-            core.fatal(_("Map <%s> has invalid time") % map.get_id())
+	    if map.get_layer():
+		core.fatal(_("Map <%s> with layer %s has invalid time") % map.get_map_id(), map.get_layer())
+	    else:
+		core.fatal(_("Map <%s> has invalid time") % map.get_map_id())
 
         map_id = map.base.get_id()
         map_name = map.base.get_name()
@@ -882,7 +887,10 @@
 
         # Check temporal types
         if stds_ttype != map_ttype:
-            core.fatal(_("Temporal type of space time dataset <%s> and map <%s> are different") % (self.get_id(), map.get_id()))
+	    if map.get_layer():
+		core.fatal(_("Temporal type of space time dataset <%s> and map <%s> with layer %s are different") % (self.get_id(), map.get_map_id(), map.get_layer()))
+	    else:
+		core.fatal(_("Temporal type of space time dataset <%s> and map <%s> are different") % (self.get_id(), map.get_map_id()))
 
         # In case no map has been registered yet, set the relative time unit from the first map
         if self.metadata.get_number_of_maps() == None and self.map_counter == 0 and self.is_time_relative():
@@ -894,7 +902,10 @@
 
         # Check the relative time unit
         if self.is_time_relative() and (stds_rel_time_unit != map_rel_time_unit):
-            core.fatal(_("Relative time units of space time dataset <%s> and map <%s> are different") % (self.get_id(), map.get_id()))
+	    if map.get_layer():
+		core.fatal(_("Relative time units of space time dataset <%s> and map <%s> with layer %s are different") % (self.get_id(), map.get_map_id(), map.get_layer()))
+	    else:
+		core.fatal(_("Relative time units of space time dataset <%s> and map <%s> are different") % (self.get_id(), map.get_map_id()))
 
         #print "STDS register table", stds_register_table
 
@@ -902,7 +913,7 @@
             dbif.close()
             core.fatal(_("Only maps from the same mapset can be registered"))
 
-        # Check if map is already registred
+        # Check if map is already registered
         if stds_register_table:
 	    if dbmi.paramstyle == "qmark":
 		sql = "SELECT id FROM " + stds_register_table + " WHERE id = (?)"
@@ -914,13 +925,17 @@
             if row and row[0] == map_id:
                 if connect == True:
                     dbif.close()
-                core.warning(_("Map <%s> is already registered.") % (map_id))
+                    
+		if map.get_layer():
+		    core.warning(_("Map <%s> with layer %s is already registered.") % (map.get_map_id(), map.get_layer()))
+		else:
+		    core.warning(_("Map <%s> is already registered.") % (map.get_map_id()))
                 return False
 
         # Create tables
         sql_path = get_sql_template_path()
 
-        # We need to create the map raster register table bevor we can register the map
+        # We need to create the map raster register table before we can register the map
         if map_register_table == None:
             # Create a unique id
             uuid_rand = "map_" + str(uuid.uuid4()).replace("-", "")
@@ -943,16 +958,24 @@
             except:
                 if connect == True:
                     dbif.close()
-                core.error(_("Unable to create the space time %s dataset register table for <%s>") % \
-                            (map.get_type(), map.get_id()))
+		if map.get_layer():
+		    core.error(_("Unable to create the space time %s dataset register table for map <%s> with layer %s") % \
+                            (map.get_type(), map.get_map_id(), map.get_layer()))
+                else:
+		    core.error(_("Unable to create the space time %s dataset register table for <%s>") % \
+                            (map.get_type(), map.get_map_id()))
                 raise
 
             # Set the stds register table name and put it into the DB
             map.set_stds_register(map_register_table)
             map.metadata.update(dbif)
             
-            core.verbose(_("Created register table <%s> for %s map <%s>") % \
-                          (map_register_table, map.get_type(), map.get_id()))
+            if map.get_layer():
+		core.verbose(_("Created register table <%s> for %s map <%s> with layer %s") % \
+				(map_register_table, map.get_type(), map.get_map_id(), map.get_layer()))
+	    else:
+		core.verbose(_("Created register table <%s> for %s map <%s>") % \
+				(map_register_table, map.get_type(), map.get_map_id()))
 
         # We need to create the table and register it
         if stds_register_table == None:
@@ -980,8 +1003,12 @@
             except:
                 if connect == True:
                     dbif.close()
-                core.error(_("Unable to create the space time %s dataset register table for <%s>") % \
-                            (map.get_type(), map.get_id()))
+		if map.get_layer():
+		    core.error(_("Unable to create the space time %s dataset register table for map <%s> with layer %s") % \
+                            (map.get_type(), map.get_map_id(), map.get_layer()))
+                else:
+		    core.error(_("Unable to create the space time %s dataset register table for <%s>") % \
+                            (map.get_type(), map.get_map_id()))
                 raise
 
             # Set the map register table name and put it into the DB
@@ -1028,7 +1055,7 @@
     def unregister_map(self, map, dbif = None):
         """Unregister a map from the space time dataset.
 
-           This method takes care of the unregistration of a map
+           This method takes care of the un-registration of a map
            from a space time dataset.
 
            @param map: The map object to unregister
@@ -1043,13 +1070,20 @@
 
         if map.is_in_db(dbif) == False:
             dbif.close()
-            core.fatal(_("Unable to find map <%s> in temporal database") % (map.get_id()))
+            
+	    if map.get_layer():
+		core.fatal(_("Unable to find map <%s> with layer %s in temporal database") % (map.get_map_id(), map.get_layer()))
+	    else:
+		core.fatal(_("Unable to find map <%s> in temporal database") % (map.get_map_id()))
 
-        core.verbose(_("Unregister %s map <%s>") % (map.get_type(), map.get_id()))
+	if map.get_layer():
+	    core.verbose(_("Unregister %s map <%s> with layer %s") % (map.get_type(), map.get_map_id(), map.get_layer()))
+	else:
+	    core.verbose(_("Unregister %s map <%s>") % (map.get_type(), map.get_map_id()))
 
         # First select all data from the database
         map.select(dbif)
-        map_id = map.base.get_id()
+        map_id = map.get_id()
         map_register_table = map.get_stds_register()
         stds_register_table = self.get_map_register()
 
@@ -1063,7 +1097,10 @@
 
         # Break if the map is not registered
         if row == None:
-            core.warning(_("Map <%s> is not registered in space time dataset") %(map_id, self.base.get_id()))
+	    if map.get_layer():
+		core.warning(_("Map <%s> with layer %s is not registered in space time dataset <%s>") %(map.get_map_id(), map.get_layer(), self.base.get_id()))
+	    else:
+		core.warning(_("Map <%s> is not registered in space time dataset <%s>") %(map.get_map_id(), self.base.get_id()))
             if connect == True:
                 dbif.close()
             return False
@@ -1100,9 +1137,9 @@
            will be used. If the end time is earlier than the maximum start time, it will
            be replaced by the maximum start time.
 
-           An other solution to automate this is to use the diactivated trigger
+           An other solution to automate this is to use the deactivated trigger
            in the SQL files. But this will result in a huge performance issue
-           in case many maps are registred (>1000).
+           in case many maps are registered (>1000).
            
            @param dbif: The database interface to be used
         """
@@ -1286,7 +1323,7 @@
 
 def create_temporal_relation_sql_where_statement(start, end, use_start=True, use_during=False, 
                                         use_overlap=False, use_contain=False, use_equal=False):
-    """ Create a SQL WHERE statement for temporal relation selection of maps in space time datastes
+    """ Create a SQL WHERE statement for temporal relation selection of maps in space time datasets
 
         @param start: The start time
         @param end: The end time

Modified: grass/trunk/lib/python/temporal/aggregation.py
===================================================================
--- grass/trunk/lib/python/temporal/aggregation.py	2012-01-26 12:22:41 UTC (rev 50466)
+++ grass/trunk/lib/python/temporal/aggregation.py	2012-01-26 12:23:09 UTC (rev 50467)
@@ -42,7 +42,7 @@
     use_contain = False
     use_equal = False
 
-    # Inititalize the methods
+    # Initialize the methods
     if sampling:
         for name in sampling.split(","):
             if name == "start":

Modified: grass/trunk/lib/python/temporal/base.py
===================================================================
--- grass/trunk/lib/python/temporal/base.py	2012-01-26 12:22:41 UTC (rev 50466)
+++ grass/trunk/lib/python/temporal/base.py	2012-01-26 12:23:09 UTC (rev 50467)
@@ -5,8 +5,8 @@
 Temporal GIS base classes to be used in other
 Python temporal gis packages.
 
-This packages includes all base classes to stor basic information like id, name,
-mapset creation and modification time as well as sql serialization and deserialization
+This packages includes all base classes to store basic information like id, name,
+mapset creation and modification time as well as sql serialization and de-serialization
 and the sql database interface.
 
 Usage:
@@ -35,11 +35,11 @@
         self.D = {}
     def serialize(self, type, table, where=None):
 	"""Convert the internal dictionary into a string of semicolon separated SQL statements
-	   The keys are the colum names and the values are the row entries
+	   The keys are the column names and the values are the row entries
 
 	   @type must be SELECT. INSERT, UPDATE
 	   @table The name of the table to select, insert or update
-	   @where The optinal where statment
+	   @where The optional where statement
 	   @return the sql string
 	"""
 
@@ -142,14 +142,14 @@
     def deserialize(self, row):
 	"""Convert the content of the dbmi dictionary like row into the internal dictionary
 
-           @param row: The dixtionary like row to stoe in the internal dict
+           @param row: The dictionary like row to store in the internal dict
         """
 	self.D = {}
 	for key in row.keys():
 	    self.D[key] = row[key]
 
     def clear(self):
-	"""Inititalize the internal storage"""
+	"""Initialize the internal storage"""
 	self.D = {}
 
     def print_self(self):
@@ -390,6 +390,8 @@
         if ident != None and name == None and mapset == None:
             if ident.find("@") >= 0:
                 name, mapset = ident.split("@")
+            if name.find(":") >= 0:
+                name, layer = ident.split(":")
 	self.set_name(name)
 	self.set_mapset(mapset)
 	self.set_creator(creator)
@@ -401,7 +403,7 @@
     def set_id(self, ident):
 	"""Convenient method to set the unique identifier (primary key)
 
-           @param ident: The unique identififer should be a combination of the dataset name and the mapset name at mapset
+           @param ident: The unique identifier should be a combination of the dataset name, layer name and the mapset name at mapset
         """
 	self.ident = ident
 	self.D["id"] = ident
@@ -416,10 +418,19 @@
     def set_mapset(self, mapset):
 	"""Set the mapset of the dataset
 
-           @param mapsets: The name of the mapset in whoch this dataset is stored
+           @param mapsets: The name of the mapset in which this dataset is stored
         """
 	self.D["mapset"] = mapset
 
+    def set_layer(self, layer):
+	"""Convenient method to set the layer of the map (part of primary key)
+	
+	   Layer are currently supported for vector maps
+
+           @param layer: The layer of the map
+        """
+	self.D["layer"] = layer
+
     def set_creator(self, creator):
 	"""Set the creator of the dataset
 
@@ -468,6 +479,30 @@
         else:
 	    return None
 
+    def get_map_id(self):
+	"""Convenient method to get the unique map identifier without layer information
+
+           @param return the name of the vector map as name at mapset
+        """
+        id = self.get_id()
+        if id.find(":") >= 0:
+	    # Remove the layer identifier from the id
+	    return id.split("@")[0].split(":")[0] + "@" + id.split("@")[1]
+	else:
+	    return id
+	    
+    def get_layer(self):
+	"""Convenient method to get the layer of the map (part of primary key)
+	
+	   Layer are currently supported for vector maps
+        
+	   @return None if not found
+	"""
+	if self.D.has_key("layer"):
+	    return self.D["layer"]
+        else:
+	    return None
+
     def get_name(self):
 	"""Get the name of the dataset
 	   @return None if not found"""
@@ -531,6 +566,8 @@
         print " | Id: ........................ " + str(self.get_id())
         print " | Name: ...................... " + str(self.get_name())
         print " | Mapset: .................... " + str(self.get_mapset())
+        if self.get_layer():
+	    print " | Layer:...................... " + str(self.get_layer())
         print " | Creator: ................... " + str(self.get_creator())
         print " | Creation time: ............. " + str(self.get_ctime())
 #        print " | Modification time: ......... " + str(self.get_mtime())
@@ -542,6 +579,8 @@
         print "id=" + str(self.get_id())
         print "name=" + str(self.get_name())
         print "mapset=" + str(self.get_mapset())
+        if self.get_layer():
+	    print "layer=" + str(self.get_layer())
         print "creator=" + str(self.get_creator())
         print "creation_time=" + str(self.get_ctime())
 #        print "modification_time=" + str(self.get_mtime())
@@ -563,11 +602,23 @@
 	            modification_time, temporal_type, revision)
 
 class vector_base(dataset_base):
-    def __init__(self, ident=None, name=None, mapset=None, creator=None, creation_time=None,\
+    def __init__(self, ident=None, name=None, mapset=None, layer=None, creator=None, creation_time=None,\
 		    modification_time=None, temporal_type=None, revision=1):
         dataset_base.__init__(self, "vector_base", ident, name, mapset, creator, creation_time,\
 	            modification_time, temporal_type, revision)
 
+	self.set_id(ident)
+        if ident != None and name == None and mapset == None:
+            if ident.find("@") >= 0:
+                name, mapset = ident.split("@")
+            if layer == None:
+		if name.find(":") >= 0:
+		    name, layer = name.split(":")
+	self.set_name(name)
+	self.set_mapset(mapset)
+	# Layer currently only in use by vector maps
+	self.set_layer(layer)
+
 ###############################################################################
 
 class stds_base(dataset_base):

Modified: grass/trunk/lib/python/temporal/core.py
===================================================================
--- grass/trunk/lib/python/temporal/core.py	2012-01-26 12:22:41 UTC (rev 50466)
+++ grass/trunk/lib/python/temporal/core.py	2012-01-26 12:23:09 UTC (rev 50467)
@@ -2,7 +2,7 @@
 
 @brief GRASS Python scripting module (temporal GIS functions)
 
-Temporal GIS core functions to be used in Python sripts.
+Temporal GIS core functions to be used in Python scripts.
 
 Usage:
 
@@ -27,7 +27,7 @@
 
 ###############################################################################
 
-# The chosen DBMI backend can be defined on runtime
+# The chosen DBMI back-end can be defined on runtime
 # Check the grass environment before import
 core.run_command("t.connect", flags="c")
 kv = core.parse_command("t.connect", flags="pg")
@@ -79,7 +79,7 @@
     """This function creates the grass location database structure for raster, vector and raster3d maps
        as well as for the space-time datasets strds, str3ds and stvds
 
-       This functions must be called befor any spatio-temporal processing is started
+       This functions must be called before any spatio-temporal processing is started
     """
     
     database = get_temporal_dbmi_init_string()

Modified: grass/trunk/lib/python/temporal/datetime_math.py
===================================================================
--- grass/trunk/lib/python/temporal/datetime_math.py	2012-01-26 12:22:41 UTC (rev 50466)
+++ grass/trunk/lib/python/temporal/datetime_math.py	2012-01-26 12:23:09 UTC (rev 50467)
@@ -2,7 +2,7 @@
 
 @brief GRASS Python scripting module (temporal GIS functions)
 
-Temporal GIS datetime math functions to be used in Python sripts.
+Temporal GIS datetime math functions to be used in Python scripts.
 
 Usage:
 
@@ -51,7 +51,7 @@
 
 def increment_datetime_by_string(mydate, increment, mult = 1):
     """Return a new datetime object incremented with the provided relative dates specified as string.
-       Additional a multiplier can be specified to multiply the increment bevor adding to the provided datetime object.
+       Additional a multiplier can be specified to multiply the increment before adding to the provided datetime object.
 
        @param mydate A datetime object to incremented
        @param increment A string providing increment information:
@@ -126,7 +126,7 @@
         # Make a deep copy of the datetime object
         dt1 = copy.copy(mydate)
 
-        # Make sure the montha starts with a 1
+        # Make sure the month starts with a 1
         if residual_months == 0:
             residual_months = 1
 
@@ -321,7 +321,7 @@
 def string_to_datetime(time_string):
     """Convert a string into a datetime object using the dateutil parser. Return None in case of failure"""
 
-    # BC is not suported
+    # BC is not supported
     if time_string.find("bc") > 0:
         core.error("Dates Before Christ are not supported in the temporal database")
         return None
@@ -340,7 +340,7 @@
     # GRASS datetime month names
     month_names  = ["", "jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec"]
 
-    # Check for time zone infor in the datetime object
+    # Check for time zone info in the datetime object
     if dt.tzinfo != None:
         string = "%.2i %s %.2i %.2i:%.2i:%.2i %+.4i"%(dt.day, month_names[dt.month], dt.year, \
                  dt.hour, dt.minute, dt.second, dt.tzinfo._offset.seconds/60)

Modified: grass/trunk/lib/python/temporal/space_time_datasets.py
===================================================================
--- grass/trunk/lib/python/temporal/space_time_datasets.py	2012-01-26 12:22:41 UTC (rev 50466)
+++ grass/trunk/lib/python/temporal/space_time_datasets.py	2012-01-26 12:23:09 UTC (rev 50467)
@@ -78,7 +78,7 @@
         """Load all info from an existing raster map into the internal structure"""
 
         # Get the data from an existing raster map
-        kvp = raster.raster_info(self.ident)
+        kvp = raster.raster_info(self.get_map_id())
 
         # Fill base information
 
@@ -156,7 +156,7 @@
         """Load all info from an existing raster3d map into the internal structure"""
 
         # Get the data from an existing raster map
-        kvp = raster3d.raster3d_info(self.ident)
+        kvp = raster3d.raster3d_info(self.get_map_id())
 
         # Fill base information
 
@@ -224,6 +224,10 @@
         """Return the name of the C-module to set the time stamp in the file system"""
         return "v.timestamp"
 
+    def get_layer(self):
+        """Return the layer"""
+        return self.base.get_layer()
+
     def reset(self, ident):
 	"""Reset the internal structure and set the identifier"""
 	self.ident = ident
@@ -238,11 +242,14 @@
         """Load all info from an existing vector map into the internal structure"""
 
         # Get the data from an existing raster map
-        kvp = vector.vector_info(self.ident)
+        kvp = vector.vector_info(self.get_map_id())
 
         # Fill base information
-
-        self.base.set_name(self.ident.split("@")[0])
+	if self.ident.find(":") >= 0:
+	    self.base.set_name(self.ident.split("@")[0].split(":")[0])
+	    self.base.set_layer(self.ident.split("@")[0].split(":")[1])
+	else:
+	    self.base.set_name(self.ident.split("@")[0])
         self.base.set_mapset(self.ident.split("@")[1])
         self.base.set_creator(str(getpass.getuser()))
 

Modified: grass/trunk/lib/python/temporal/space_time_datasets_tools.py
===================================================================
--- grass/trunk/lib/python/temporal/space_time_datasets_tools.py	2012-01-26 12:22:41 UTC (rev 50466)
+++ grass/trunk/lib/python/temporal/space_time_datasets_tools.py	2012-01-26 12:23:09 UTC (rev 50467)
@@ -26,7 +26,9 @@
 
 ###############################################################################
 
-def register_maps_in_space_time_dataset(type, name, maps=None, file=None, start=None, end=None, unit=None, increment=None, dbif = None, interval=False, fs="|"):
+def register_maps_in_space_time_dataset(type, name, maps=None, layer=None, file=None, start=None, \
+                                        end=None, unit=None, increment=None, dbif = None, \
+                                        interval=False, fs="|"):
     """Use this method to register maps in space time datasets. This function is generic and
 
        Additionally a start time string and an increment string can be specified
@@ -50,6 +52,7 @@
 
     start_time_in_file = False
     end_time_in_file = False
+    layer_in_file = False
 
     if maps and file:
         core.fatal(_("%s= and %s= are mutually exclusive") % ("input","file"))
@@ -63,6 +66,9 @@
     if not maps and not file:
         core.fatal(_("Please specify %s= or %s=") % ("input","file"))
 
+    if layer and layer == "file":
+        layer_in_file = True
+        
     if start and start == "file":
         start_time_in_file = True
 
@@ -94,15 +100,39 @@
         dbif.close()
         core.fatal(_("Space time %s dataset <%s> no found") % (sp.get_new_map_instance(None).get_type(), name))
 
+    dummy = sp.get_new_map_instance(None)
+        
     maplist = []
-
+    layerlist = []
+    
     # Map names as comma separated string
     if maps:
-        if maps.find(",") == -1:
-            maplist = (maps,)
+        if maps.find(",") < 0:
+            maplist = [maps,]
         else:
-            maplist = tuple(maps.split(","))
+            maplist = maps.split(",")
 
+	# Layer as comma separated string
+	if layer:
+	    if layer.find(",") < 0:
+		layerlist = (layer,)
+	    else:
+		layerlist = layer.split(",")
+		
+	    if len(maplist) != len(layerlist):
+		core.fatal(_("Number of %s= and %s= must be equal") % ("maps","layer"))
+	    
+	# Build the maplist again with the ids
+	for count in range(len(maplist)):
+	    row = {}
+	    if layer:
+		mapid = dummy.build_id(maplist[count], mapset, layerlist[count])
+            else:
+		mapid = dummy.build_id(maplist[count], mapset, None)
+		
+	    row["id"] = mapid
+            maplist[count] = row
+            
     # Read the map list from file
     if file:
         fd = open(file, "r")
@@ -117,66 +147,73 @@
 
             mapname = line_list[0].strip()
 
-            if mapname.find("@") < 0:
-                mapid = mapname + "@" + mapset
-            else:
-                mapid = mapname
-
             row = {}
-            row["id"] = mapid
+            
+	    if layer_in_file:
+		row["layer"] = line_list[1].strip()
+		if start_time_in_file and  end_time_in_file:
+		    row["start"] = line_list[2].strip()
+		    row["end"] = line_list[3].strip()
 
-            if start_time_in_file and  end_time_in_file:
-                row["start"] = line_list[1].strip()
-                row["end"] = line_list[2].strip()
+		if start_time_in_file and  not end_time_in_file:
+		    row["start"] = line_list[2].strip()
+		    
+		row["id"] = dummy.build_id(mapname, mapset, row["layer"])
+	    else:
+		if start_time_in_file and  end_time_in_file:
+		    row["start"] = line_list[1].strip()
+		    row["end"] = line_list[2].strip()
 
-            if start_time_in_file and  not end_time_in_file:
-                row["start"] = line_list[1].strip()
+		if start_time_in_file and  not end_time_in_file:
+		    row["start"] = line_list[1].strip()
+		
+		row["id"] = dummy.build_id(mapname, mapset)
 
             maplist.append(row)
     
     num_maps = len(maplist)
-    count = 0
-    for entry in maplist:
+    for count in range(len(maplist)):
 	core.percent(count, num_maps, 1)
 
         # Get a new instance of the space time dataset map type
-        if file:
-            map = sp.get_new_map_instance(entry["id"])
-        else:
-            if entry.find("@") < 0:
-                mapid = entry + "@" + mapset
-            else:
-                mapid = entry
+        map = sp.get_new_map_instance(maplist[count]["id"])
 
-            map = sp.get_new_map_instance(mapid)
-
         # Use the time data from file
         if start_time_in_file:
-            start = entry["start"]
+            start = maplist[count]["start"]
         if end_time_in_file:
-            end = entry["end"]
+            end = maplist[count]["end"]
 
         # Put the map into the database
         if map.is_in_db(dbif) == False:
             # Break in case no valid time is provided
             if start == "" or start == None:
                 dbif.close()
-                core.fatal(_("Unable to register %s map <%s>. The map has no valid time and the start time is not set.") % \
-                            (map.get_type(), map.get_id() ))
+                if map.get_layer():
+		    core.fatal(_("Unable to register %s map <%s> with layer %s. The map has no valid time and the start time is not set.") % \
+				(map.get_type(), map.get_map_id(), map.get_layer() ))
+		else:
+		    core.fatal(_("Unable to register %s map <%s>. The map has no valid time and the start time is not set.") % \
+				(map.get_type(), map.get_map_id() ))
             # Load the data from the grass file database
             map.load()
-
+	    
             if sp.get_temporal_type() == "absolute":
                 map.set_time_to_absolute()
             else:
                 map.set_time_to_relative()
+                
             #  Put it into the temporal database
             map.insert(dbif)
         else:
             map.select(dbif)
             if map.get_temporal_type() != sp.get_temporal_type():
                 dbif.close()
-                core.fatal(_("Unable to register %s map <%s>. The temporal types are different.") %  (map.get_type(), map.get_id()))
+                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()))
+		    core.fatal(_("Unable to register %s map <%s>. The temporal types are different.") %  \
+		                 (map.get_type(), map.get_map_id()))
 
         # In case the time is in the input file we ignore the increment counter
         if start_time_in_file:
@@ -188,7 +225,6 @@
 
         # Finally Register map in the space time dataset
         sp.register_map(map, dbif)
-        count += 1
 
     # Update the space time tables
     sp.update_from_registered_maps(dbif)
@@ -200,7 +236,7 @@
         
 ###############################################################################
 
-def unregister_maps_from_space_time_datasets(type, name, maps, file=None, dbif = None):
+def unregister_maps_from_space_time_datasets(type, name, maps, layer=None, file=None, dbif=None):
     """Unregister maps from a single space time dataset or, in case no dataset name is provided,
        unregister from all datasets within the maps are registered.
 
@@ -220,6 +256,11 @@
         dbif.connect()
         connect = True
 
+    layer_in_file = False
+    
+    if layer and layer == "file":
+        layer_in_file = True
+        
     # In case a space time dataset is specified
     if name:
         # Check if the dataset name contains the mapset as well
@@ -240,14 +281,38 @@
             core.fatal("Space time " + sp.get_new_map_instance(None).get_type() + " dataset <" + name + "> not found")
 
     maplist = []
+    layerlist = []
 
+    dummy = raster_dataset(None)
+
     # Map names as comma separated string
-    if maps:
-        if maps.find(",") == -1:
-            maplist = (maps,)
-        else:
-            maplist = tuple(maps.split(","))
-
+    if maps != None:
+	if maps.find(",") == -1:
+	    maplist = [maps,]
+	else:
+	    maplist = maps.split(",")
+	    
+	if layer:
+	    if layer.find(",") < 0:
+		layerlist = (layer,)
+	    else:
+		layerlist = layer.split(",")
+		
+	    if len(maplist) != len(layerlist):
+		core.fatal(_("Number of %s= and %s= must be equal") % ("maps","layer"))
+		
+	# Build the maplist
+	for count in range(len(maplist)):
+	    mapname = maplist[count]
+	    
+	    if layer:
+		mylayer = layerlist[count]
+		mapid = dummy.build_id(mapname, mapset, mylayer)
+	    else:
+		mapid = dummy.build_id(mapname, mapset)
+		
+            maplist[count] = mapid
+            
     # Read the map list from file
     if file:
         fd = open(file, "r")
@@ -260,19 +325,21 @@
 
             line_list = line.split(fs)
             mapname = line_list[0].strip()
-            maplist.append(mapname)
     
+	    if layer_in_file:
+		mylayer = line_list[1].strip()
+		mapid = dummy.build_id(mapname, mapset, mylayer)
+	    else:
+		mapid = dummy.build_id(mapname, mapset)
+
+            maplist.append(mapid)
+            
     num_maps = len(maplist)
     count = 0
-    for mapname in maplist:
+    for mapid in maplist:
 	core.percent(count, num_maps, 1)
-        mapname = mapname.strip()
-        # Check if the map name contains the mapset as well
-        if mapname.find("@") < 0:
-            mapid = mapname + "@" + mapset
-        else:
-            mapid = mapname
             
+        print mapid
         map = dataset_factory(type, mapid)
 
         # Unregister map if in database
@@ -497,8 +564,11 @@
             start_time = increment_datetime_by_string(start_time, increment, mult)
             if interval:
                 end_time = increment_datetime_by_string(start_time, increment, 1)
-
-        core.verbose(_("Set absolute valid time for map <%s> to %s - %s") % (map.get_id(), str(start_time), str(end_time)))
+	if map.get_layer():
+	    core.verbose(_("Set absolute valid time for map <%s> with layer %s to %s - %s") % (map.get_map_id(), map.get_layer(), str(start_time), str(end_time)))
+        else:
+	    core.verbose(_("Set absolute valid time for map <%s> to %s - %s") % (map.get_map_id(), str(start_time), str(end_time)))
+        
         map.update_absolute_time(start_time, end_time, None, dbif)
     else:
         start_time = int(start)
@@ -512,7 +582,11 @@
             if interval:
                 end_time = start_time + int(increment)
 
-        core.verbose(_("Set relative valid time for map <%s> to %i - %s with unit %s") % (map.get_id(), start_time,  str(end_time), unit))
+	if map.get_layer():
+	    core.verbose(_("Set relative valid time for map <%s> with layer %s to %i - %s with unit %s") % (map.get_map_id(), map.get_layer(), start_time,  str(end_time), unit))
+        else:
+	    core.verbose(_("Set relative valid time for map <%s> to %i - %s with unit %s") % (map.get_map_id(), start_time,  str(end_time), unit))
+	    
         map.update_relative_time(start_time, end_time, unit, dbif)
 
     if connect == True:
@@ -552,14 +626,14 @@
         @param type: The type of the maps raster, raster3d or vector
         @param input: Name of a space time raster dataset
         @param columns: A comma separated list of columns to be printed to stdout 
-        @param order: A comma seoarated list of columns to order the space time dataset by category 
+        @param order: A comma separated list of columns to order the space time dataset by category 
         @param where: A where statement for selected listing without "WHERE" e.g: start_time < "2001-01-01" and end_time > "2001-01-01"
         @param separator: The field separator character between the columns
         @param method: String identifier to select a method out of cols,comma,delta or deltagaps
             * "cols": Print preselected columns specified by columns
             * "comma": Print the map ids (name at mapset) as comma separated string
             * "delta": Print the map ids (name at mapset) with start time, end time, relative length of intervals and the relative distance to the begin
-            * "deltagaps": Same as "delta" with addtitionakl listing of gaps. Gaps can be simply identified as the id is "None"
+            * "deltagaps": Same as "delta" with additional listing of gaps. Gaps can be simply identified as the id is "None"
             * "gran": List map using the granularity of the space time dataset, columns are identical to deltagaps 
         @param header: Set True to print column names 
     """
@@ -582,7 +656,10 @@
            
     # This method expects a list of objects for gap detection
     if method == "delta" or method == "deltagaps" or method == "gran":
-        columns = "id,start_time,end_time"
+	if type == "stvds":
+	    columns = "id,name,layer,mapset,start_time,end_time"
+	else:
+	    columns = "id,name,mapset,start_time,end_time"
         if method == "deltagaps":
             maps = sp.get_registered_maps_as_objects_with_gaps(where, None)
         elif method == "delta":
@@ -592,7 +669,11 @@
 
         if header:
             string = ""
-            string += "%s%s" % ("id", separator)
+	    string += "%s%s" % ("id", separator)
+	    string += "%s%s" % ("name", separator)
+            if type == "stvds":
+		string += "%s%s" % ("layer", separator)
+	    string += "%s%s" % ("mapset", separator)
             string += "%s%s" % ("start_time", separator)
             string += "%s%s" % ("end_time", separator)
             string += "%s%s" % ("interval_length", separator)
@@ -627,6 +708,10 @@
 
                 string = ""
                 string += "%s%s" % (map.get_id(), separator)
+                string += "%s%s" % (map.get_name(), separator)
+		if type == "stvds":
+		    string += "%s%s" % (map.get_layer(), separator)
+                string += "%s%s" % (map.get_mapset(), separator)
                 string += "%s%s" % (start, separator)
                 string += "%s%s" % (end, separator)
                 string += "%s%s" % (delta, separator)
@@ -686,6 +771,8 @@
     """ 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.
+        
+        In case a layer is present, the names map ids are extended in this form: name:layer at mapset 
 
         Attention: Do not use the comma as separator
 

Modified: grass/trunk/lib/python/temporal/spatial_extent.py
===================================================================
--- grass/trunk/lib/python/temporal/spatial_extent.py	2012-01-26 12:22:41 UTC (rev 50466)
+++ grass/trunk/lib/python/temporal/spatial_extent.py	2012-01-26 12:23:09 UTC (rev 50467)
@@ -122,7 +122,7 @@
 	self.D["north"] = north
 
     def set_south(self, sourth):
-	"""Set the sourthern edge of the map"""
+	"""Set the southern edge of the map"""
 	self.D["south"] = sourth
 
     def set_west(self, west):

Modified: grass/trunk/lib/python/temporal/temporal_extent.py
===================================================================
--- grass/trunk/lib/python/temporal/temporal_extent.py	2012-01-26 12:22:41 UTC (rev 50466)
+++ grass/trunk/lib/python/temporal/temporal_extent.py	2012-01-26 12:23:09 UTC (rev 50467)
@@ -103,7 +103,7 @@
 	    return False
 
     def before(self, map):
-	"""Return True if this time object is temporal located bevor the provided time object
+	"""Return True if this time object is temporal located before the provided time object
 	   A  |---------|
 	   B             |---------|
 	"""
@@ -235,7 +235,7 @@
 	    return False
 
     def overlapped(self, map):
-	"""Return True if this time object is temporal overlaped by the provided time object
+	"""Return True if this time object is temporal overlapped by the provided time object
 	   A    |---------|
            B  |---------|
 	"""
@@ -250,7 +250,7 @@
 
     def temporal_relation(self, map):
 	"""Returns the temporal relation between temporal objects
-	   Temporal relationsships are implemented after [Allen and Ferguson 1994 Actions and Events in Interval Temporal Logic]
+	   Temporal relationships are implemented after [Allen and Ferguson 1994 Actions and Events in Interval Temporal Logic]
 	"""
         
         # First check for correct time
@@ -505,7 +505,7 @@
 
     def temporal_relation(self, map):
 	"""Returns the temporal relation between temporal objects
-	   Temporal relationsships are implemented after [Allen and Ferguson 1994 Actions and Events in Interval Temporal Logic]
+	   Temporal relationships are implemented after [Allen and Ferguson 1994 Actions and Events in Interval Temporal Logic]
 	"""
         
         # Check units for relative time

Modified: grass/trunk/lib/python/temporal/temporal_granularity.py
===================================================================
--- grass/trunk/lib/python/temporal/temporal_granularity.py	2012-01-26 12:22:41 UTC (rev 50466)
+++ grass/trunk/lib/python/temporal/temporal_granularity.py	2012-01-26 12:23:09 UTC (rev 50467)
@@ -28,7 +28,7 @@
 def compute_relative_time_granularity(maps):            
     """ Compute the relative granularity"""
 
-    # The intervaltime must be scaled to days resoltuion
+    # The interval time must be scaled to days resolution
     granularity = None
 
     delta = []



More information about the grass-commit mailing list