Pārlūkot izejas kodu

Code cleanup. The temporal map type (single point of time, time interval or mixed) is now computed and stored in space time datasets.

git-svn-id: https://svn.osgeo.org/grass/grass/trunk@48675 15284696-431f-4ddb-bdfa-cd5b030d7da7
Soeren Gebbert 13 gadi atpakaļ
vecāks
revīzija
ee60743b2d

+ 59 - 17
lib/python/temporal/abstract_datasets.py

@@ -7,7 +7,7 @@ Temporal GIS related functions to be used in temporal GIS Python library package
 Usage:
 Usage:
 
 
 @code
 @code
-from grass.script import tgis_abstract_datasets as grass
+import grass.temporal as tgis
 
 
 ...
 ...
 @endcode
 @endcode
@@ -496,7 +496,7 @@ class abstract_space_time_dataset(abstract_dataset):
         return granularity, temporal_type, semantic_type, title, description
         return granularity, temporal_type, semantic_type, title, description
 
 
     def get_temporal_relation_matrix(self, dbif=None):
     def get_temporal_relation_matrix(self, dbif=None):
-        """Return the temporal relation matrix between all registered maps
+        """Return the temporal relation matrix of all registered maps as list
         """
         """
 
 
         connect = False
         connect = False
@@ -593,6 +593,8 @@ class abstract_space_time_dataset(abstract_dataset):
                 dbif.cursor.execute(sql)
                 dbif.cursor.execute(sql)
                 rows = dbif.cursor.fetchall()
                 rows = dbif.cursor.fetchall()
             except:
             except:
+                if connect == True:
+                    dbif.close()
                 core.error(_("Unable to get map ids from register table <%s>") % (self.get_map_register()))
                 core.error(_("Unable to get map ids from register table <%s>") % (self.get_map_register()))
                 raise
                 raise
 
 
@@ -628,6 +630,8 @@ class abstract_space_time_dataset(abstract_dataset):
                 sql = "DROP TABLE " + self.get_map_register()
                 sql = "DROP TABLE " + self.get_map_register()
                 dbif.cursor.execute(sql)
                 dbif.cursor.execute(sql)
             except:
             except:
+                if connect == True:
+                    dbif.close()
                 core.error(_("Unable to drop table <%s>") % (self.get_map_register()))
                 core.error(_("Unable to drop table <%s>") % (self.get_map_register()))
                 raise
                 raise
 
 
@@ -655,6 +659,7 @@ class abstract_space_time_dataset(abstract_dataset):
             connect = True
             connect = True
 
 
         if map.is_in_db(dbif) == False:
         if map.is_in_db(dbif) == False:
+            dbif.close()
             core.fatal(_("Only maps with absolute or relative valid time can be registered"))
             core.fatal(_("Only maps with absolute or relative valid time can be registered"))
 
 
         core.verbose(_("Register %s map <%s> in space time %s dataset <%s>") %  (map.get_type(), map.get_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()))
@@ -676,6 +681,7 @@ class abstract_space_time_dataset(abstract_dataset):
         #print "STDS register table", stds_register_table
         #print "STDS register table", stds_register_table
 
 
         if stds_mapset != map_mapset:
         if stds_mapset != map_mapset:
+            dbif.close()
             core.fatal(_("Only maps from the same mapset can be registered"))
             core.fatal(_("Only maps from the same mapset can be registered"))
 
 
         # Check if map is already registred
         # Check if map is already registred
@@ -688,6 +694,8 @@ class abstract_space_time_dataset(abstract_dataset):
             row = dbif.cursor.fetchone()
             row = dbif.cursor.fetchone()
             # In case of no entry make a new one
             # In case of no entry make a new one
             if row and row[0] == map_id:
             if row and row[0] == map_id:
+                if connect == True:
+                    dbif.close()
                 core.warning(_("Map <%s> is already registered.") % (map_id))
                 core.warning(_("Map <%s> is already registered.") % (map_id))
                 return False
                 return False
 
 
@@ -710,7 +718,7 @@ class abstract_space_time_dataset(abstract_dataset):
             sql = sql.replace("MAP_ID", map_id)
             sql = sql.replace("MAP_ID", map_id)
             sql = sql.replace("STDS", self.get_type())
             sql = sql.replace("STDS", self.get_type())
             try:
             try:
-		if dbmi.paramstyle == "qmark":
+		if dbmi.__name__ == "sqlite3":
 		    dbif.cursor.executescript(sql)
 		    dbif.cursor.executescript(sql)
 		else:
 		else:
 		    dbif.cursor.execute(sql)
 		    dbif.cursor.execute(sql)
@@ -720,14 +728,18 @@ class abstract_space_time_dataset(abstract_dataset):
                     sql = "DROP TABLE " + map_register_table
                     sql = "DROP TABLE " + map_register_table
                     dbif.cursor.execute(sql)
                     dbif.cursor.execute(sql)
                 except:
                 except:
+                    if connect == True:
+                        dbif.close()
                     core.error(_("Unable to drop table <%s>" % (map_register_table)))
                     core.error(_("Unable to drop table <%s>" % (map_register_table)))
                     raise
                     raise
                 try:
                 try:
-		    if dbmi.paramstyle == "qmark":
+		    if dbmi.__name__ == "sqlite3":
 			dbif.cursor.executescript(sql_script)
 			dbif.cursor.executescript(sql_script)
 		    else:
 		    else:
 			dbif.cursor.execute(sql_script)
 			dbif.cursor.execute(sql_script)
                 except:
                 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()))
                     core.error(_("Unable to create the space time %s dataset register table for <%s>") % (map.get_type(), map.get_id()))
                     raise
                     raise
 
 
@@ -750,12 +762,12 @@ class abstract_space_time_dataset(abstract_dataset):
             sql = sql.replace("STDS", self.get_type())
             sql = sql.replace("STDS", self.get_type())
 
 
             sql_script = ""
             sql_script = ""
-            #sql_script += "BEGIN TRANSACTION;\n"
+            sql_script += "BEGIN TRANSACTION;\n"
             sql_script += sql
             sql_script += sql
-            #sql_script += "\n"
-            #sql_script += "END TRANSACTION;"
+            sql_script += "\n"
+            sql_script += "END TRANSACTION;"
             try:
             try:
-		if dbmi.paramstyle == "qmark":
+		if dbmi.__name__ == "sqlite3":
 		    dbif.cursor.executescript(sql_script)
 		    dbif.cursor.executescript(sql_script)
 		else:
 		else:
 		    dbif.cursor.execute(sql_script)
 		    dbif.cursor.execute(sql_script)
@@ -766,14 +778,18 @@ class abstract_space_time_dataset(abstract_dataset):
 		    print sql
 		    print sql
                     dbif.cursor.execute(sql)
                     dbif.cursor.execute(sql)
                 except:
                 except:
+                    if connect == True:
+                        dbif.close()
                     core.error(_("Unable to drop table <%s>" % (stds_register_table)))
                     core.error(_("Unable to drop table <%s>" % (stds_register_table)))
                     raise
                     raise
                 try:
                 try:
-		    if dbmi.paramstyle == "qmark":
+		    if dbmi.__name__ == "sqlite3":
 			dbif.cursor.executescript(sql_script)
 			dbif.cursor.executescript(sql_script)
 		    else:
 		    else:
 			dbif.cursor.execute(sql_script)
 			dbif.cursor.execute(sql_script)
                 except:
                 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()))
                     core.error(_("Unable to create the space time %s dataset register table for <%s>") % (map.get_type(), map.get_id()))
                     raise
                     raise
 
 
@@ -844,6 +860,7 @@ class abstract_space_time_dataset(abstract_dataset):
             connect = True
             connect = True
 
 
         if map.is_in_db(dbif) == False:
         if map.is_in_db(dbif) == False:
+            dbif.close()
             core.fatal(_("Unable to find map <%s> in temporal database") % (map.get_id()))
             core.fatal(_("Unable to find map <%s> in temporal database") % (map.get_id()))
 
 
         core.verbose(_("Unregister %s map <%s>") % (map.get_type(), map.get_id()))
         core.verbose(_("Unregister %s map <%s>") % (map.get_type(), map.get_id()))
@@ -852,8 +869,6 @@ class abstract_space_time_dataset(abstract_dataset):
         map.select(dbif)
         map.select(dbif)
         map_id = map.base.get_id()
         map_id = map.base.get_id()
         map_register_table = map.get_stds_register()
         map_register_table = map.get_stds_register()
-
-        # Get basic info
         stds_register_table = self.get_map_register()
         stds_register_table = self.get_map_register()
 
 
         # Check if the map is registered in the space time raster dataset
         # Check if the map is registered in the space time raster dataset
@@ -867,6 +882,8 @@ class abstract_space_time_dataset(abstract_dataset):
         # Break if the map is not registered
         # Break if the map is not registered
         if row == None:
         if row == None:
             core.warning(_("Map <%s> is not registered in space time dataset") %(map_id, self.base.get_id()))
             core.warning(_("Map <%s> is not registered in space time dataset") %(map_id, self.base.get_id()))
+            if connect == True:
+                dbif.close()
             return False
             return False
 
 
         # Remove the space time raster dataset from the raster dataset register
         # Remove the space time raster dataset from the raster dataset register
@@ -915,6 +932,7 @@ class abstract_space_time_dataset(abstract_dataset):
             dbif.connect()
             dbif.connect()
             connect = True
             connect = True
 
 
+        map_time = None
 
 
         use_start_time = False
         use_start_time = False
 
 
@@ -950,12 +968,11 @@ class abstract_space_time_dataset(abstract_dataset):
 
 
         sql_script += "END TRANSACTION;"
         sql_script += "END TRANSACTION;"
 
 
-	if dbmi.paramstyle == "qmark":
+	if dbmi.__name__ == "sqlite3":
 	    dbif.cursor.executescript(sql_script)
 	    dbif.cursor.executescript(sql_script)
 	else:
 	else:
 	    dbif.cursor.execute(sql_script)
 	    dbif.cursor.execute(sql_script)
 	    
 	    
-
         # Read and validate the selected end time
         # Read and validate the selected end time
         self.select()
         self.select()
 
 
@@ -984,7 +1001,8 @@ class abstract_space_time_dataset(abstract_dataset):
             row = dbif.cursor.fetchone()
             row = dbif.cursor.fetchone()
 
 
             if row != None:
             if row != None:
-		if dbmi.paramstyle == "qmark":
+                # This seems to be a bug in sqlite3 Python driver
+		if dbmi.__name__ == "sqlite3":
 		    tstring = row[0]
 		    tstring = row[0]
 		    # Convert the unicode string into the datetime format
 		    # Convert the unicode string into the datetime format
 		    if tstring.find(":") > 0:
 		    if tstring.find(":") > 0:
@@ -995,10 +1013,13 @@ class abstract_space_time_dataset(abstract_dataset):
 		    max_start_time = datetime.strptime(tstring, time_format)
 		    max_start_time = datetime.strptime(tstring, time_format)
 		else:
 		else:
 		    max_start_time = row[0]
 		    max_start_time = row[0]
-		    
+
 		if end_time < max_start_time:
 		if end_time < max_start_time:
+                    map_time = "mixed"
 		    use_start_time = True
 		    use_start_time = True
-
+                else:
+                    map_time = "interval"
+		    
         # Set the maximum start time as end time
         # Set the maximum start time as end time
         if use_start_time:
         if use_start_time:
             if self.is_time_absolute():
             if self.is_time_absolute():
@@ -1020,10 +1041,31 @@ class abstract_space_time_dataset(abstract_dataset):
                 sql = sql.replace("SPACETIME_ID", self.base.get_id())
                 sql = sql.replace("SPACETIME_ID", self.base.get_id())
                 sql = sql.replace("STDS", self.get_type())
                 sql = sql.replace("STDS", self.get_type())
 
 
-	    if dbmi.paramstyle == "qmark":
+	    if dbmi.__name__ == "sqlite3":
 		dbif.cursor.executescript(sql)
 		dbif.cursor.executescript(sql)
 	    else:
 	    else:
 		dbif.cursor.execute(sql)
 		dbif.cursor.execute(sql)
 
 
+            if end_time == None:
+                map_time = "point"
+
+        # Set the map time type
+        if self.is_time_absolute():
+            self.absolute_time.select(dbif)
+            self.metadata.select(dbif)
+            if self.metadata.get_number_of_maps() > 0:
+                self.absolute_time.set_map_time(map_time)
+            else:
+                self.absolute_time.set_map_time(None)
+            self.absolute_time.update_all(dbif)
+        else:
+            self.relative_time.select(dbif)
+            self.metadata.select(dbif)
+            if self.metadata.get_number_of_maps() > 0:
+                self.relative_time.set_map_time(map_time)
+            else:
+                self.relative_time.set_map_time(None)
+            self.relative_time.update_all(dbif)
+
         if connect == True:
         if connect == True:
             dbif.close()
             dbif.close()

+ 5 - 4
lib/python/temporal/base.py

@@ -12,9 +12,9 @@ and the sql database interface.
 Usage:
 Usage:
 
 
 @code
 @code
-from grass.script import tgis_core as grass
+import grass.temporal as tgis
 
 
-rbase = grass.raster_base(ident="soil")
+rbase = tgis.raster_base(ident="soil")
 ...
 ...
 @endcode
 @endcode
 
 
@@ -187,11 +187,12 @@ class sql_database_interface(dict_sql_serializer):
 
 
     def connect(self):
     def connect(self):
         #print "Connect to",  self.database
         #print "Connect to",  self.database
-	if dbmi.paramstyle == "qmark":
+        if dbmi.__name__ == "sqlite3":
 	    self.connection = dbmi.connect(self.database, detect_types=dbmi.PARSE_DECLTYPES|dbmi.PARSE_COLNAMES)
 	    self.connection = dbmi.connect(self.database, detect_types=dbmi.PARSE_DECLTYPES|dbmi.PARSE_COLNAMES)
 	    self.connection.row_factory = dbmi.Row
 	    self.connection.row_factory = dbmi.Row
+            self.connection.isolation_level = None
 	    self.cursor = self.connection.cursor()
 	    self.cursor = self.connection.cursor()
-	else:
+        elif dbmi.__name__ == "psycopg2":
 	    self.connection = dbmi.connect(self.database)
 	    self.connection = dbmi.connect(self.database)
 	    self.connection.set_isolation_level(dbmi.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
 	    self.connection.set_isolation_level(dbmi.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
 	    self.cursor = self.connection.cursor(cursor_factory=dbmi.extras.DictCursor)
 	    self.cursor = self.connection.cursor(cursor_factory=dbmi.extras.DictCursor)

+ 35 - 22
lib/python/temporal/core.py

@@ -7,9 +7,9 @@ Temporal GIS core functions to be used in Python sripts.
 Usage:
 Usage:
 
 
 @code
 @code
-from grass.script import tgis_core as grass
+import grass.temporal as tgis
 
 
-grass.create_temporal_database()
+tgis.create_temporal_database()
 ...
 ...
 @endcode
 @endcode
 
 
@@ -21,22 +21,23 @@ for details.
 @author Soeren Gebbert
 @author Soeren Gebbert
 """
 """
 import os
 import os
+import copy
+from datetime import datetime, date, time, timedelta
+import grass.script.core as core
+
 import sqlite3 as dbmi
 import sqlite3 as dbmi
 #import psycopg2 as dbmi
 #import psycopg2 as dbmi
 # Needed for dictionary like cursors
 # Needed for dictionary like cursors
 #import psycopg2.extras
 #import psycopg2.extras
-import grass.script.core as core
-import copy
-from datetime import datetime, date, time, timedelta
 
 
 ###############################################################################
 ###############################################################################
 
 
 def get_grass_location_db_path():
 def get_grass_location_db_path():
-    if dbmi.paramstyle == "qmark":
+    if dbmi.__name__ == "sqlite3":
 	grassenv = core.gisenv()
 	grassenv = core.gisenv()
 	dbpath = os.path.join(grassenv["GISDBASE"], grassenv["LOCATION_NAME"])
 	dbpath = os.path.join(grassenv["GISDBASE"], grassenv["LOCATION_NAME"])
 	return os.path.join(dbpath, "grass.db")
 	return os.path.join(dbpath, "grass.db")
-    else:
+    elif dbmi.__name__ == "psycopg2":
 	return "dbname=grass_test user=soeren password=abcdefgh"
 	return "dbname=grass_test user=soeren password=abcdefgh"
 
 
 ###############################################################################
 ###############################################################################
@@ -46,6 +47,8 @@ def get_sql_template_path():
     base_etc  = os.path.join(base, "etc")
     base_etc  = os.path.join(base, "etc")
     return os.path.join(base_etc, "sql")
     return os.path.join(base_etc, "sql")
 
 
+###############################################################################
+
 def test_increment_datetime_by_string():
 def test_increment_datetime_by_string():
 
 
     dt = datetime(2001, 9, 1, 0, 0, 0)
     dt = datetime(2001, 9, 1, 0, 0, 0)
@@ -59,16 +62,18 @@ def test_increment_datetime_by_string():
     if delta.days != 0 or delta.seconds != 0:
     if delta.days != 0 or delta.seconds != 0:
         core.fatal("increment computation is wrong")
         core.fatal("increment computation is wrong")
 
 
+###############################################################################
+
 def increment_datetime_by_string(mydate, increment, mult = 1):
 def increment_datetime_by_string(mydate, increment, mult = 1):
     """Return a new datetime object incremented with the provided relative dates specified as string.
     """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 bevor adding to the provided datetime object.
 
 
-       @mydate A datetime object to incremented
-       @increment A string providing increment information:
+       @param mydate A datetime object to incremented
+       @param increment A string providing increment information:
                   The string may include comma separated values of type seconds, minutes, hours, days, weeks, months and years
                   The string may include comma separated values of type seconds, minutes, hours, days, weeks, months and years
                   Example: Increment the datetime 2001-01-01 00:00:00 with "60 seconds, 4 minutes, 12 hours, 10 days, 1 weeks, 5 months, 1 years"
                   Example: Increment the datetime 2001-01-01 00:00:00 with "60 seconds, 4 minutes, 12 hours, 10 days, 1 weeks, 5 months, 1 years"
                   will result in the datetime 2003-02-18 12:05:00
                   will result in the datetime 2003-02-18 12:05:00
-        @mult A multiplier, default is 1
+       @param mult A multiplier, default is 1
     """
     """
 
 
     if increment:
     if increment:
@@ -103,7 +108,8 @@ def increment_datetime_by_string(mydate, increment, mult = 1):
             elif inc[1].find("years") >= 0:
             elif inc[1].find("years") >= 0:
                 years = mult * int(inc[0])
                 years = mult * int(inc[0])
             else:
             else:
-                core.fatal(_("Wrong increment format: %s") % (increment))
+                core.error(_("Wrong increment format: %s") % (increment))
+                return None
 
 
         return increment_datetime(mydate, years, months, weeks, days, hours, minutes, seconds)
         return increment_datetime(mydate, years, months, weeks, days, hours, minutes, seconds)
     
     
@@ -160,15 +166,24 @@ def create_temporal_database():
     
     
     database = get_grass_location_db_path()
     database = get_grass_location_db_path()
 
 
-    build_db = False
+    db_exists = False
 
 
-    # Check if it already exists
-    if dbmi.paramstyle == "qmark":
+    # Check if the database already exists
+    if dbmi.__name__ == "sqlite3":
 	# Check path of the sqlite database
 	# Check path of the sqlite database
-	if not os.path.exists(database):
-	    build_db = True
-    
-    if build_db == False:
+	if os.path.exists(database):
+	    db_exists = True
+    elif dbmi.__name__ == "psycopg2":
+        # Connect to database
+        connection = dbmi.connect(database)
+        cursor = connection.cursor()
+        # Check for raster_base table
+        cursor.execute("SELECT EXISTS(SELECT * FROM information_schema.tables WHERE table_name=%s)", ('raster_base',))
+        db_exists = cursor.fetchone()[0]
+        connection.commit()
+        cursor.close()
+
+    if db_exists == True:
 	return
 	return
     
     
     # Read all SQL scripts and templates
     # Read all SQL scripts and templates
@@ -181,7 +196,6 @@ def create_temporal_database():
     str3ds_metadata_sql = open(os.path.join(get_sql_template_path(), "str3ds_metadata_table.sql"), 'r').read()
     str3ds_metadata_sql = open(os.path.join(get_sql_template_path(), "str3ds_metadata_table.sql"), 'r').read()
     stvds_metadata_sql = open(os.path.join(get_sql_template_path(), "stvds_metadata_table.sql"), 'r').read()
     stvds_metadata_sql = open(os.path.join(get_sql_template_path(), "stvds_metadata_table.sql"), 'r').read()
     
     
-
     # Create the raster, raster3d and vector tables
     # Create the raster, raster3d and vector tables
     raster_tables_sql = map_tables_template_sql.replace("GRASS_MAP", "raster")
     raster_tables_sql = map_tables_template_sql.replace("GRASS_MAP", "raster")
     vector_tables_sql = map_tables_template_sql.replace("GRASS_MAP", "vector")
     vector_tables_sql = map_tables_template_sql.replace("GRASS_MAP", "vector")
@@ -196,8 +210,7 @@ def create_temporal_database():
     connection = dbmi.connect(database)
     connection = dbmi.connect(database)
     cursor = connection.cursor()
     cursor = connection.cursor()
 
 
-    
-    if dbmi.paramstyle == "qmark":
+    if dbmi.__name__ == "sqlite3":
 	
 	
 	sqlite3_delete_trigger_sql = open(os.path.join(get_sql_template_path(), "sqlite3_delete_trigger.sql"), 'r').read()
 	sqlite3_delete_trigger_sql = open(os.path.join(get_sql_template_path(), "sqlite3_delete_trigger.sql"), 'r').read()
 	
 	
@@ -217,7 +230,7 @@ def create_temporal_database():
 	cursor.executescript(str3ds_tables_sql)
 	cursor.executescript(str3ds_tables_sql)
 	cursor.executescript(str3ds_metadata_sql)
 	cursor.executescript(str3ds_metadata_sql)
 	cursor.executescript(sqlite3_delete_trigger_sql)
 	cursor.executescript(sqlite3_delete_trigger_sql)
-    else:
+    elif dbmi.__name__ == "psycopg2":
 	# Execute the SQL statements for postgresql
 	# Execute the SQL statements for postgresql
 	# Create the global tables for the native grass datatypes
 	# Create the global tables for the native grass datatypes
 	cursor.execute(raster_tables_sql)
 	cursor.execute(raster_tables_sql)

+ 2 - 2
lib/python/temporal/metadata.py

@@ -7,9 +7,9 @@ Temporal GIS related metadata functions to be used in Python scripts and tgis pa
 Usage:
 Usage:
 
 
 @code
 @code
-from grass.script import tgis_metadata as grass
+import grass.temporal as tgis
 
 
-meta = grass.raster_metadata()
+meta = tgis.raster_metadata()
 ...
 ...
 @endcode
 @endcode
 
 

+ 8 - 2
lib/python/temporal/space_time_datasets.py

@@ -7,9 +7,9 @@ Temporal GIS related functions to be used in Python scripts.
 Usage:
 Usage:
 
 
 @code
 @code
-from grass.script import tgis_space_time_dataset as grass
+import grass.temporal as tgis
 
 
-strds = grass.space_time_raster_dataset("soils_1950_2010")
+strds = tgis.space_time_raster_dataset("soils_1950_2010")
 
 
 ...
 ...
 @endcode
 @endcode
@@ -419,6 +419,7 @@ def register_maps_in_space_time_dataset(type, name, maps, start=None, increment=
     sp.select(dbif)
     sp.select(dbif)
 
 
     if sp.is_in_db(dbif) == False:
     if sp.is_in_db(dbif) == False:
+        dbif.close()
         core.fatal("Space time " + sp.get_new_map_instance(None).get_type() + " dataset <" + name + "> not found")
         core.fatal("Space time " + sp.get_new_map_instance(None).get_type() + " dataset <" + name + "> not found")
 
 
     if maps.find(",") == -1:
     if maps.find(",") == -1:
@@ -445,6 +446,7 @@ def register_maps_in_space_time_dataset(type, name, maps, start=None, increment=
         if map.is_in_db(dbif) == False:
         if map.is_in_db(dbif) == False:
             # Break in case no valid time is provided
             # Break in case no valid time is provided
             if start == "" or start == None:
             if start == "" or start == None:
+                dbif.close()
                 core.fatal("Unable to register " + map.get_type() + " map <" + map.get_id() + ">. The map has no valid time and the start time is not set.")
                 core.fatal("Unable to register " + map.get_type() + " map <" + map.get_id() + ">. The map has no valid time and the start time is not set.")
             # Load the data from the grass file database
             # Load the data from the grass file database
             map.load()
             map.load()
@@ -458,6 +460,7 @@ def register_maps_in_space_time_dataset(type, name, maps, start=None, increment=
         else:
         else:
             map.select(dbif)
             map.select(dbif)
             if map.get_temporal_type() != sp.get_temporal_type():
             if map.get_temporal_type() != sp.get_temporal_type():
+                dbif.close()
                 core.fatal("Unable to register " + map.get_type() + " map <" + map.get_id() + ">. The temporal types are different.")
                 core.fatal("Unable to register " + map.get_type() + " map <" + map.get_id() + ">. The temporal types are different.")
 
 
         # Set the valid time
         # Set the valid time
@@ -509,6 +512,7 @@ def unregister_maps_from_space_time_datasets(type, name, maps, dbif = None):
             sp = space_time_vector_dataset(id)
             sp = space_time_vector_dataset(id)
 
 
         if sp.is_in_db(dbif) == False:
         if sp.is_in_db(dbif) == False:
+            dbif.close()
             core.fatal("Space time " + sp.get_new_map_instance(None).get_type() + " dataset <" + name + "> not found")
             core.fatal("Space time " + sp.get_new_map_instance(None).get_type() + " dataset <" + name + "> not found")
 
 
     # Build the list of maps
     # Build the list of maps
@@ -576,6 +580,8 @@ def assign_valid_time_to_maps(type, maps, ttype, start, end=None, increment=None
     """
     """
 
 
     if end and increment:
     if end and increment:
+        if dbif:
+            dbif.close()
         core.fatal(_("Valid end time and increment are mutual exclusive"))
         core.fatal(_("Valid end time and increment are mutual exclusive"))
 
 
     # List of space time datasets to be updated
     # List of space time datasets to be updated

+ 2 - 2
lib/python/temporal/spatial_extent.py

@@ -7,9 +7,9 @@ Temporal GIS related spatial extent functions to be used in Python scripts and t
 Usage:
 Usage:
 
 
 @code
 @code
-from grass.script import tgis_spatial_extent as grass
+import grass.temporal as tgis
 
 
-extent = grass.raster_spatial_extent()
+extent = tgis.raster_spatial_extent()
 ...
 ...
 @endcode
 @endcode
 
 

+ 64 - 8
lib/python/temporal/temporal_extent.py

@@ -7,9 +7,9 @@ Temporal GIS related temporal extent functions to be used in Python scripts and
 Usage:
 Usage:
 
 
 @code
 @code
-from grass.script import tgis_temporal_extent as grass
+import grass.temporal as tgis
 
 
-grass.raster_temporal_extent()
+tgis.raster_temporal_extent()
 ...
 ...
 @endcode
 @endcode
 
 
@@ -383,15 +383,28 @@ class vector_absolute_time(absolute_temporal_extent):
 ###############################################################################
 ###############################################################################
 
 
 class stds_absolute_time(absolute_temporal_extent):
 class stds_absolute_time(absolute_temporal_extent):
-    def __init__(self, table=None, ident=None, start_time=None, end_time=None, granularity=None, timezone=None):
+    def __init__(self, table=None, ident=None, start_time=None, end_time=None, granularity=None, timezone=None, map_time=None):
         absolute_temporal_extent.__init__(self, table, ident, start_time, end_time, timezone)
         absolute_temporal_extent.__init__(self, table, ident, start_time, end_time, timezone)
 
 
 	self.set_granularity(granularity)
 	self.set_granularity(granularity)
+        self.set_map_time(map_time)
 
 
     def set_granularity(self, granularity):
     def set_granularity(self, granularity):
 	"""Set the granularity of the space time dataset"""
 	"""Set the granularity of the space time dataset"""
 	self.D["granularity"] = granularity
 	self.D["granularity"] = granularity
 
 
+    def set_map_time(self, map_time):
+	"""Set the type of the map time
+
+           Registered maps may have different types of time:
+           Single point of time "point"
+           Time intervals "interval"
+           Or single point and interval time "mixed"
+
+           This variable will be set automatically when maps are registered.
+        """
+	self.D["map_time"] = map_time
+
     def get_granularity(self):
     def get_granularity(self):
 	"""Get the granularity of the space time dataset
 	"""Get the granularity of the space time dataset
 	   @return None if not found"""
 	   @return None if not found"""
@@ -400,16 +413,33 @@ class stds_absolute_time(absolute_temporal_extent):
         else:
         else:
 	    return None
 	    return None
 
 
+    def get_map_time(self):
+	"""Get the type of the map time
+
+           Registered maps may have different types of time:
+           Single point of time "point"
+           Time intervals "interval"
+           Or single point and interval time "mixed"
+
+           This variable will be set automatically when maps are registered.
+        """
+	if self.D.has_key("map_time"):
+	    return self.D["map_time"]
+        else:
+	    return None
+
     def print_info(self):
     def print_info(self):
         """Print information about this class in human readable style"""
         """Print information about this class in human readable style"""
         absolute_temporal_extent.print_info(self)
         absolute_temporal_extent.print_info(self)
         #      0123456789012345678901234567890
         #      0123456789012345678901234567890
         print " | Granularity:................ " + str(self.get_granularity())
         print " | Granularity:................ " + str(self.get_granularity())
+        print " | Temporal type of maps:...... " + str(self.get_map_time())
 
 
     def print_shell_info(self):
     def print_shell_info(self):
         """Print information about this class in shell style"""
         """Print information about this class in shell style"""
         absolute_temporal_extent.print_shell_info(self)
         absolute_temporal_extent.print_shell_info(self)
         print "granularity=" + str(self.get_granularity())
         print "granularity=" + str(self.get_granularity())
+        print "map_time=" + str(self.get_map_time())
 
 
 ###############################################################################
 ###############################################################################
 
 
@@ -427,7 +457,6 @@ class stvds_absolute_time(stds_absolute_time):
 
 
 ###############################################################################
 ###############################################################################
 
 
-
 class relative_temporal_extent(abstract_temporal_extent):
 class relative_temporal_extent(abstract_temporal_extent):
     """This is the relative time class for all maps and spacetime datasets
     """This is the relative time class for all maps and spacetime datasets
 
 
@@ -437,14 +466,12 @@ class relative_temporal_extent(abstract_temporal_extent):
 
 
 	abstract_temporal_extent.__init__(self, table, ident, start_time, end_time)
 	abstract_temporal_extent.__init__(self, table, ident, start_time, end_time)
 
 
-
     def print_info(self):
     def print_info(self):
         """Print information about this class in human readable style"""
         """Print information about this class in human readable style"""
         #      0123456789012345678901234567890
         #      0123456789012345678901234567890
         print " +-------------------- Reltive time ------------------------------------------+"
         print " +-------------------- Reltive time ------------------------------------------+"
         abstract_temporal_extent.print_info(self)
         abstract_temporal_extent.print_info(self)
 
 
-
 ###############################################################################
 ###############################################################################
 
 
 class raster_relative_time(relative_temporal_extent):
 class raster_relative_time(relative_temporal_extent):
@@ -462,15 +489,28 @@ class vector_relative_time(relative_temporal_extent):
 ###############################################################################
 ###############################################################################
 
 
 class stds_relative_time(relative_temporal_extent):
 class stds_relative_time(relative_temporal_extent):
-    def __init__(self, table=None, ident=None, start_time=None, end_time=None, granularity=None):
+    def __init__(self, table=None, ident=None, start_time=None, end_time=None, granularity=None, map_time=None):
         relative_temporal_extent.__init__(self, table, ident, start_time, end_time)
         relative_temporal_extent.__init__(self, table, ident, start_time, end_time)
 
 
 	self.set_granularity(granularity)
 	self.set_granularity(granularity)
+        self.set_map_time(map_time)
 
 
     def set_granularity(self, granularity):
     def set_granularity(self, granularity):
 	"""Set the granularity of the space time dataset"""
 	"""Set the granularity of the space time dataset"""
 	self.D["granularity"] = granularity
 	self.D["granularity"] = granularity
 
 
+    def set_map_time(self, map_time):
+	"""Set the type of the map time
+
+           Registered maps may have different types of time:
+           Single point of time "point"
+           Time intervals "interval"
+           Or single point and interval time "mixed"
+
+           This variable will be set automatically when maps are registered.
+        """
+	self.D["map_time"] = map_time
+
     def get_granularity(self):
     def get_granularity(self):
 	"""Get the granularity of the space time dataset
 	"""Get the granularity of the space time dataset
 	   @return None if not found"""
 	   @return None if not found"""
@@ -479,16 +519,33 @@ class stds_relative_time(relative_temporal_extent):
         else:
         else:
 	    return None
 	    return None
 
 
+    def get_map_time(self):
+	"""Get the type of the map time
+
+           Registered maps may have different types of time:
+           Single point of time "point"
+           Time intervals "interval"
+           Or single point and interval time "mixed"
+
+           This variable will be set automatically when maps are registered.
+        """
+	if self.D.has_key("map_time"):
+	    return self.D["map_time"]
+        else:
+	    return None
+
     def print_info(self):
     def print_info(self):
         """Print information about this class in human readable style"""
         """Print information about this class in human readable style"""
         relative_temporal_extent.print_info(self)
         relative_temporal_extent.print_info(self)
         #      0123456789012345678901234567890
         #      0123456789012345678901234567890
         print " | Granularity:................ " + str(self.get_granularity())
         print " | Granularity:................ " + str(self.get_granularity())
+        print " | Temporal type of maps:...... " + str(self.get_map_time())
 
 
     def print_shell_info(self):
     def print_shell_info(self):
         """Print information about this class in shell style"""
         """Print information about this class in shell style"""
         relative_temporal_extent.print_shell_info(self)
         relative_temporal_extent.print_shell_info(self)
         print "granularity=" + str(self.get_granularity())
         print "granularity=" + str(self.get_granularity())
+        print "map_time=" + str(self.get_map_time())
 
 
 ###############################################################################
 ###############################################################################
 
 
@@ -503,4 +560,3 @@ class str3ds_relative_time(stds_relative_time):
 class stvds_relative_time(stds_relative_time):
 class stvds_relative_time(stds_relative_time):
     def __init__(self, ident=None, start_time=None, end_time=None, granularity=None):
     def __init__(self, ident=None, start_time=None, end_time=None, granularity=None):
         stds_relative_time.__init__(self, "stvds_relative_time", ident, start_time, end_time, granularity)
         stds_relative_time.__init__(self, "stvds_relative_time", ident, start_time, end_time, granularity)
-

+ 4 - 1
lib/temporal/stds_tables_template.sql

@@ -19,7 +19,7 @@ CREATE TABLE  STDS_base (
   creation_time TIMESTAMP NOT NULL,    -- The time of creation of the space-time dataset
   creation_time TIMESTAMP NOT NULL,    -- The time of creation of the space-time dataset
 -- Uncommented due to performance issues
 -- Uncommented due to performance issues
 --  modification_time TIMESTAMP NOT NULL,  -- The time of the last modification of the grass map
 --  modification_time TIMESTAMP NOT NULL,  -- The time of the last modification of the grass map
+--  revision SMALLINT NOT NULL,            -- The revision number        -- The revision number
   PRIMARY KEY (id)
   PRIMARY KEY (id)
 );
 );
 
 
@@ -27,7 +27,8 @@ CREATE TABLE  STDS_relative_time (
   id VARCHAR NOT NULL,            -- Id of the space-time dataset, this is the primary foreign key
   id VARCHAR NOT NULL,            -- Id of the space-time dataset, this is the primary foreign key
   start_time DOUBLE PRECISION,    -- The relative valid start time in [days]
   start_time DOUBLE PRECISION,    -- The relative valid start time in [days]
   end_time DOUBLE PRECISION,      -- The relative valid end time in [days]
   end_time DOUBLE PRECISION,      -- The relative valid end time in [days]
-  granularity DOUBLE PRECISION,             -- The granularity in [days]
+  granularity DOUBLE PRECISION,   -- The granularity in [days]
+  map_time VARCHAR,               -- The temporal type of the registered maps, may be interval, point or mixed
   PRIMARY KEY (id),  
   PRIMARY KEY (id),  
   FOREIGN KEY (id) REFERENCES  STDS_base (id) ON DELETE CASCADE
   FOREIGN KEY (id) REFERENCES  STDS_base (id) ON DELETE CASCADE
 );
 );
@@ -38,6 +39,7 @@ CREATE TABLE  STDS_absolute_time (
   end_time TIMESTAMP,             -- End of the valid time, can be NULL if no map is registered
   end_time TIMESTAMP,             -- End of the valid time, can be NULL if no map is registered
   granularity VARCHAR,            -- The granularity "NNN seconds, NNN minutes, NNN hours, NNN days, NNN weeks, NNN months, NNN years"
   granularity VARCHAR,            -- The granularity "NNN seconds, NNN minutes, NNN hours, NNN days, NNN weeks, NNN months, NNN years"
   timezone SMALLINT,              -- The time zone number
   timezone SMALLINT,              -- The time zone number
+  map_time VARCHAR,               -- The temporal type of the registered maps, may be interval, point or mixed
   PRIMARY KEY (id),  
   PRIMARY KEY (id),  
   FOREIGN KEY (id) REFERENCES  STDS_base (id) ON DELETE CASCADE
   FOREIGN KEY (id) REFERENCES  STDS_base (id) ON DELETE CASCADE
 );
 );

+ 12 - 1
raster/r.series/test.r.series.sh

@@ -38,7 +38,6 @@ r.series -z --o --v input=prec_1,prec_2,prec_3,prec_4,prec_5,prec_6 output=test_
 r.series    --o --v input=prec_1,prec_2,prec_3,prec_4,prec_5,prec_6 output=test_1_prec_count method=count
 r.series    --o --v input=prec_1,prec_2,prec_3,prec_4,prec_5,prec_6 output=test_1_prec_count method=count
 r.series -z --o --v input=prec_1,prec_2,prec_3,prec_4,prec_5,prec_6 output=test_1_prec_range method=range
 r.series -z --o --v input=prec_1,prec_2,prec_3,prec_4,prec_5,prec_6 output=test_1_prec_range method=range
 r.series    --o --v input=prec_1,prec_2,prec_3,prec_4,prec_5,prec_6 output=test_1_prec_sum method=sum
 r.series    --o --v input=prec_1,prec_2,prec_3,prec_4,prec_5,prec_6 output=test_1_prec_sum method=sum
-
 #r.out.ascii --o input=test_1_prec_mean output=test_1_prec_mean.ref dp=3
 #r.out.ascii --o input=test_1_prec_mean output=test_1_prec_mean.ref dp=3
 #r.out.ascii --o input=test_1_prec_max output=test_1_prec_max.ref dp=3
 #r.out.ascii --o input=test_1_prec_max output=test_1_prec_max.ref dp=3
 #r.out.ascii --o input=test_1_prec_min output=test_1_prec_min.ref dp=3
 #r.out.ascii --o input=test_1_prec_min output=test_1_prec_min.ref dp=3
@@ -60,3 +59,15 @@ r.series    --o --v file=$TMP_FILE output=test_2_prec_sum method=sum
 #r.out.ascii --o input=test_2_prec_count output=test_2_prec_count.ref dp=3
 #r.out.ascii --o input=test_2_prec_count output=test_2_prec_count.ref dp=3
 #r.out.ascii --o input=test_2_prec_range output=test_2_prec_range.ref dp=3
 #r.out.ascii --o input=test_2_prec_range output=test_2_prec_range.ref dp=3
 #r.out.ascii --o input=test_2_prec_sum output=test_2_prec_sum.ref dp=3
 #r.out.ascii --o input=test_2_prec_sum output=test_2_prec_sum.ref dp=3
+
+
+# The third @test with multiple methods and outputs
+r.series    --o --v input=prec_1,prec_2,prec_3,prec_4,prec_5,prec_6 output=test_3_prec_mean,test_3_prec_max,test_3_prec_min method=average,maximum,minimum
+r.series -z --o --v file=$TMP_FILE output=test_4_prec_mean,test_4_prec_max,test_4_prec_min method=average,maximum,minimum
+
+#r.out.ascii --o input=test_1_prec_mean output=test_3_prec_mean.ref dp=3
+#r.out.ascii --o input=test_1_prec_max output=test_3_prec_max.ref dp=3
+#r.out.ascii --o input=test_1_prec_min output=test_3_prec_min.ref dp=3
+#r.out.ascii --o input=test_2_prec_mean output=test_4_prec_mean.ref dp=3
+#r.out.ascii --o input=test_2_prec_max output=test_4_prec_max.ref dp=3
+#r.out.ascii --o input=test_2_prec_min output=test_4_prec_min.ref dp=3

+ 14 - 0
raster/r.series/test_3_prec_max.ref

@@ -0,0 +1,14 @@
+north: 80N
+south: 0
+east: 120E
+west: 0
+rows: 8
+cols: 12
+600 600 600 600 600 600 600 600 600 600 600 600 
+600 600 600 600 600 600 600 600 600 600 600 600 
+600 600 600 600 600 600 600 600 600 600 600 600 
+600 600 600 600 600 600 600 600 600 600 600 600 
+600 600 600 600 600 600 600 600 600 600 600 600 
+600 600 600 600 600 600 600 600 600 600 600 600 
+600 600 600 600 600 600 600 600 600 600 600 600 
+600 600 600 600 600 600 600 600 600 600 600 600 

+ 14 - 0
raster/r.series/test_3_prec_mean.ref

@@ -0,0 +1,14 @@
+north: 80N
+south: 0
+east: 120E
+west: 0
+rows: 8
+cols: 12
+350 350 350 350 350 350 350 350 350 350 350 350 
+350 350 350 350 350 350 350 350 350 350 350 350 
+350 350 350 350 350 350 350 350 350 350 350 350 
+350 350 350 350 350 350 350 350 350 350 350 350 
+350 350 350 350 350 350 350 350 350 350 350 350 
+350 350 350 350 350 350 350 350 350 350 350 350 
+350 350 350 350 350 350 350 350 350 350 350 350 
+350 350 350 350 350 350 350 350 350 350 350 350 

+ 14 - 0
raster/r.series/test_3_prec_min.ref

@@ -0,0 +1,14 @@
+north: 80N
+south: 0
+east: 120E
+west: 0
+rows: 8
+cols: 12
+100 100 100 100 100 100 100 100 100 100 100 100 
+100 100 100 100 100 100 100 100 100 100 100 100 
+100 100 100 100 100 100 100 100 100 100 100 100 
+100 100 100 100 100 100 100 100 100 100 100 100 
+100 100 100 100 100 100 100 100 100 100 100 100 
+100 100 100 100 100 100 100 100 100 100 100 100 
+100 100 100 100 100 100 100 100 100 100 100 100 
+100 100 100 100 100 100 100 100 100 100 100 100 

+ 14 - 0
raster/r.series/test_4_prec_max.ref

@@ -0,0 +1,14 @@
+north: 80N
+south: 0
+east: 120E
+west: 0
+rows: 8
+cols: 12
+600 600 600 600 600 600 600 600 600 600 600 600 
+600 600 600 600 600 600 600 600 600 600 600 600 
+600 600 600 600 600 600 600 600 600 600 600 600 
+600 600 600 600 600 600 600 600 600 600 600 600 
+600 600 600 600 600 600 600 600 600 600 600 600 
+600 600 600 600 600 600 600 600 600 600 600 600 
+600 600 600 600 600 600 600 600 600 600 600 600 
+600 600 600 600 600 600 600 600 600 600 600 600 

+ 14 - 0
raster/r.series/test_4_prec_mean.ref

@@ -0,0 +1,14 @@
+north: 80N
+south: 0
+east: 120E
+west: 0
+rows: 8
+cols: 12
+350 350 350 350 350 350 350 350 350 350 350 350 
+350 350 350 350 350 350 350 350 350 350 350 350 
+350 350 350 350 350 350 350 350 350 350 350 350 
+350 350 350 350 350 350 350 350 350 350 350 350 
+350 350 350 350 350 350 350 350 350 350 350 350 
+350 350 350 350 350 350 350 350 350 350 350 350 
+350 350 350 350 350 350 350 350 350 350 350 350 
+350 350 350 350 350 350 350 350 350 350 350 350 

+ 14 - 0
raster/r.series/test_4_prec_min.ref

@@ -0,0 +1,14 @@
+north: 80N
+south: 0
+east: 120E
+west: 0
+rows: 8
+cols: 12
+100 100 100 100 100 100 100 100 100 100 100 100 
+100 100 100 100 100 100 100 100 100 100 100 100 
+100 100 100 100 100 100 100 100 100 100 100 100 
+100 100 100 100 100 100 100 100 100 100 100 100 
+100 100 100 100 100 100 100 100 100 100 100 100 
+100 100 100 100 100 100 100 100 100 100 100 100 
+100 100 100 100 100 100 100 100 100 100 100 100 
+100 100 100 100 100 100 100 100 100 100 100 100 

+ 1 - 0
temporal/t.create/t.create.py

@@ -116,6 +116,7 @@ def main():
     dbif.connect()
     dbif.connect()
 
 
     if sp.is_in_db(dbif) and grass.overwrite() == False:
     if sp.is_in_db(dbif) and grass.overwrite() == False:
+        dbif.close()
         grass.fatal("Space time " + sp.get_new_map_instance(None).get_type() + " dataset <" + name + "> is already in the database. Use the overwrite flag.")
         grass.fatal("Space time " + sp.get_new_map_instance(None).get_type() + " dataset <" + name + "> is already in the database. Use the overwrite flag.")
 
 
     if sp.is_in_db(dbif) and grass.overwrite() == True:
     if sp.is_in_db(dbif) and grass.overwrite() == True:

+ 1 - 0
temporal/t.remove/t.remove.py

@@ -79,6 +79,7 @@ def main():
             ds = tgis.vector_dataset(id)
             ds = tgis.vector_dataset(id)
 
 
         if ds.is_in_db(dbif) == False:
         if ds.is_in_db(dbif) == False:
+            dbif.close()
             grass.fatal(ds.get_type() + " dataset <" + name + "> not found in temporal database")
             grass.fatal(ds.get_type() + " dataset <" + name + "> not found in temporal database")
 
 
         # We need to read some data from the temporal database
         # We need to read some data from the temporal database

+ 3 - 6
temporal/tr.extract/tr.extract.py

@@ -89,7 +89,7 @@ def main():
     sp = tgis.space_time_raster_dataset(id)
     sp = tgis.space_time_raster_dataset(id)
     
     
     if sp.is_in_db() == False:
     if sp.is_in_db() == False:
-        grass.fatal(_("Dataset <%s> not found in temporal database") % (id))
+        grass.fatal(_("Space time arster dataset <%s> not found in temporal database") % (id))
 
 
     if expression and not base:
     if expression and not base:
         grass.fatal(_("Please specify base="))
         grass.fatal(_("Please specify base="))
@@ -156,14 +156,11 @@ def main():
 
 
                 grass.verbose(_("Apply r.mapcalc expression: \"%s\"") % expr)
                 grass.verbose(_("Apply r.mapcalc expression: \"%s\"") % expr)
 
 
-                if grass.overwrite() == True:
-                    ret = grass.run_command("r.mapcalc", expression=expr, overwrite=True, quiet=True)
-                else:
-                    ret = grass.run_command("r.mapcalc", expression=expr, overwrite=False, quiet=True)
+                ret = grass.run_command("r.mapcalc", expression=expr, overwrite=grass.overwrite(), quiet=True)
 
 
                 if ret != 0:
                 if ret != 0:
                     grass.error(_("Error while r.mapcalc computation, continue with next map"))
                     grass.error(_("Error while r.mapcalc computation, continue with next map"))
-                    continue
+                    break
 
 
                 # Read the raster map data
                 # Read the raster map data
                 new_map.load()
                 new_map.load()

+ 34 - 37
temporal/tr.series/tr.series.py

@@ -5,7 +5,7 @@
 # MODULE:	tr.series
 # MODULE:	tr.series
 # AUTHOR(S):	Soeren Gebbert
 # AUTHOR(S):	Soeren Gebbert
 #
 #
-# PURPOSE:	Performe different aggregation algorithms from r.series on all raster maps of a space time raster dataset
+# PURPOSE:	Performe different aggregation algorithms from r.series on all or a selected subset of raster maps in a space time raster dataset
 # COPYRIGHT:	(C) 2011 by the GRASS Development Team
 # COPYRIGHT:	(C) 2011 by the GRASS Development Team
 #
 #
 #		This program is free software under the GNU General Public
 #		This program is free software under the GNU General Public
@@ -15,7 +15,7 @@
 #############################################################################
 #############################################################################
 
 
 #%module
 #%module
-#% description: Performe different aggregation algorithms from r.series on all raster maps of a space time raster dataset
+#% description: Performe different aggregation algorithms from r.series on all or a subset of raster maps in a space time raster dataset
 #% keywords: spacetime raster dataset
 #% keywords: spacetime raster dataset
 #% keywords: raster
 #% keywords: raster
 #% keywords: extract
 #% keywords: extract
@@ -32,7 +32,7 @@
 #%option
 #%option
 #% key: method
 #% key: method
 #% type: string
 #% type: string
-#% description: Aggregate operation on all raster maps of a space time raster dataset
+#% description: Aggregate operation to be peformed on the raster maps
 #% required: yes
 #% required: yes
 #% multiple: no
 #% multiple: no
 #% options: average,count,median,mode,minimum,min_raster,maximum,max_raster,stddev,range,sum,variance,diversity,slope,offset,detcoeff,quart1,quart3,perc90,quantile,skewness,kurtosis
 #% options: average,count,median,mode,minimum,min_raster,maximum,max_raster,stddev,range,sum,variance,diversity,slope,offset,detcoeff,quart1,quart3,perc90,quantile,skewness,kurtosis
@@ -57,7 +57,7 @@
 
 
 #%flag
 #%flag
 #% key: t
 #% key: t
-#% description: Assign the space time raster dataset time interval to the output map
+#% description: Assign the space time raster dataset start and end time to the output map
 #%end
 #%end
 
 
 import grass.script as grass
 import grass.script as grass
@@ -87,19 +87,14 @@ def main():
     sp = tgis.space_time_raster_dataset(id)
     sp = tgis.space_time_raster_dataset(id)
 
 
     if sp.is_in_db() == False:
     if sp.is_in_db() == False:
-        grass.fatal(_("Dataset <%s> not found in temporal database") % (id))
+        grass.fatal(_("Space time raster dataset <%s> not found in temporal database") % (id))
 
 
     sp.select()
     sp.select()
-    
-    if add_time:
-	if sp.is_time_absolute():
-	    start_time, end_time, tz = sp.get_absolute_time()
-	else:
-	    start_time, end_time = sp.get_relative_time()
 
 
     rows = sp.get_registered_maps(None, where, sort)
     rows = sp.get_registered_maps(None, where, sort)
 
 
     if rows:
     if rows:
+        # Create the r.series input file
         filename = grass.tempfile(True)
         filename = grass.tempfile(True)
         file = open(filename, 'w')
         file = open(filename, 'w')
 
 
@@ -109,32 +104,34 @@ def main():
         
         
         file.close()
         file.close()
 
 
-        if grass.overwrite() == True:
-            grass.run_command("r.series", flags="z", file=filename, output=output, overwrite=True, method=method)
-        else:
-            grass.run_command("r.series", flags="z", file=filename, output=output, overwrite=False, method=method)
-
-    if add_time:
-	# Create the time range for the output map
-	if output.find("@") >= 0:
-	    id = output
-	else:
-	    mapset =  grass.gisenv()["MAPSET"]
-	    id = output + "@" + mapset
-
-	map = sp.get_new_map_instance(id)
-
-	map.load()
-	if sp.is_time_absolute():
-	    map.set_absolute_time(start_time, end_time, tz)
-	else:
-	    map.set_relative_time(start_time, end_time)
-
-	# Register the map in the temporal database
-	if map.is_in_db():
-	    map.update()
-	else:
-	    map.insert()    
+        ret = grass.run_command("r.series", flags="z", file=filename, output=output, overwrite=grass.overwrite(), method=method)
+
+        if ret == 0 and add_time:
+            if sp.is_time_absolute():
+                start_time, end_time, tz = sp.get_absolute_time()
+            else:
+                start_time, end_time = sp.get_relative_time()
+                
+            # Create the time range for the output map
+            if output.find("@") >= 0:
+                id = output
+            else:
+                mapset =  grass.gisenv()["MAPSET"]
+                id = output + "@" + mapset
+
+            map = sp.get_new_map_instance(id)
+
+            map.load()
+            if sp.is_time_absolute():
+                map.set_absolute_time(start_time, end_time, tz)
+            else:
+                map.set_relative_time(start_time, end_time)
+
+            # Register the map in the temporal database
+            if map.is_in_db():
+                map.update()
+            else:
+                map.insert()
 
 
 if __name__ == "__main__":
 if __name__ == "__main__":
     options, flags = grass.parser()
     options, flags = grass.parser()