Browse Source

Better code and file structure. Fixed several doxygen errors and warnings.
More API documentation.


git-svn-id: https://svn.osgeo.org/grass/grass/trunk@55914 15284696-431f-4ddb-bdfa-cd5b030d7da7

Soeren Gebbert 12 years ago
parent
commit
115ce85a5f

+ 1 - 1
lib/python/temporal/Makefile

@@ -8,7 +8,7 @@ PYDIR = $(ETC)/python
 GDIR = $(PYDIR)/grass
 GDIR = $(PYDIR)/grass
 DSTDIR = $(GDIR)/temporal
 DSTDIR = $(GDIR)/temporal
 
 
-MODULES = base core abstract_dataset abstract_temporal_dataset abstract_map_dataset abstract_space_time_dataset space_time_datasets space_time_datasets_tools metadata spatial_extent temporal_extent datetime_math temporal_granularity temporal_relationships unit_tests aggregation stds_export stds_import extract mapcalc univar_statistics
+MODULES = base core abstract_dataset abstract_temporal_dataset abstract_map_dataset abstract_space_time_dataset space_time_datasets create factory gui_support list register sampling metadata spatial_extent temporal_extent datetime_math temporal_granularity temporal_relationships unit_tests aggregation stds_export stds_import extract mapcalc univar_statistics
 
 
 PYFILES := $(patsubst %,$(DSTDIR)/%.py,$(MODULES) __init__)
 PYFILES := $(patsubst %,$(DSTDIR)/%.py,$(MODULES) __init__)
 PYCFILES := $(patsubst %,$(DSTDIR)/%.pyc,$(MODULES) __init__)
 PYCFILES := $(patsubst %,$(DSTDIR)/%.pyc,$(MODULES) __init__)

+ 6 - 1
lib/python/temporal/__init__.py

@@ -8,10 +8,15 @@ from abstract_temporal_dataset import *
 from abstract_map_dataset import *
 from abstract_map_dataset import *
 from abstract_space_time_dataset import *
 from abstract_space_time_dataset import *
 from space_time_datasets import *
 from space_time_datasets import *
-from space_time_datasets_tools import *
 from datetime_math import *
 from datetime_math import *
 from temporal_granularity import *
 from temporal_granularity import *
 from temporal_relationships import *
 from temporal_relationships import *
+from create import *
+from factory import *
+from gui_support import *
+from list import *
+from register import *
+from sampling import *
 from aggregation import *
 from aggregation import *
 from extract import *
 from extract import *
 from stds_export import *
 from stds_export import *

+ 7 - 5
lib/python/temporal/abstract_map_dataset.py

@@ -66,7 +66,7 @@ class AbstractMapDataset(AbstractTemporalDataset):
            This table stores all space time datasets in 
            This table stores all space time datasets in 
            which this map is registered.
            which this map is registered.
 
 
-           @param ident The name of the register table
+           @param name The name of the register table
         """
         """
         raise ImplementationError(
         raise ImplementationError(
             "This method must be implemented in the subclasses")
             "This method must be implemented in the subclasses")
@@ -165,7 +165,7 @@ class AbstractMapDataset(AbstractTemporalDataset):
            in the file system but not to identify
            in the file system but not to identify
            map information in the temporal database.
            map information in the temporal database.
 
 
-           @return The map id name@mapset
+           @return The map id "name@mapset"
         """
         """
         return self.base.get_map_id()
         return self.base.get_map_id()
 
 
@@ -176,10 +176,10 @@ class AbstractMapDataset(AbstractTemporalDataset):
             string will be reused
             string will be reused
            
            
            @param name The name of the map
            @param name The name of the map
-           @param The mapset in which the map is located
-           @layer The layer of the vector map, use None in case no layer exists
+           @param mapset The mapset in which the map is located
+           @param layer The layer of the vector map, use None in case no layer exists
 
 
-           @return the id of the map as name(:layer)@mapset 
+           @return the id of the map as "name(:layer)@mapset" 
                   while layer is optional
                   while layer is optional
         """
         """
 
 
@@ -383,6 +383,7 @@ class AbstractMapDataset(AbstractTemporalDataset):
            @param start_time a datetime object specifying the start time of the map
            @param start_time a datetime object specifying the start time of the map
            @param end_time a datetime object specifying the end time of the map, None in case or time instance
            @param end_time a datetime object specifying the end time of the map, None in case or time instance
            @param timezone Thee timezone of the map (not used)
            @param timezone Thee timezone of the map (not used)
+           @param dbif The database interface to be used
         """
         """
         dbif, connected = init_dbif(dbif)
         dbif, connected = init_dbif(dbif)
 
 
@@ -463,6 +464,7 @@ class AbstractMapDataset(AbstractTemporalDataset):
 
 
            @param start_time An integer value
            @param start_time An integer value
            @param end_time An integer value, None in case or time instance
            @param end_time An integer value, None in case or time instance
+           @param unit The relative time unit
            @param dbif The database interface to be used
            @param dbif The database interface to be used
         """
         """
         dbif, connected = init_dbif(dbif)
         dbif, connected = init_dbif(dbif)

+ 1 - 1
lib/python/temporal/abstract_space_time_dataset.py

@@ -1086,7 +1086,7 @@ class AbstractSpaceTimeDataset(AbstractDataset):
            This method renames the space time dataset, the map register table
            This method renames the space time dataset, the map register table
            and updates the entries in registered maps stds register.
            and updates the entries in registered maps stds register.
 
 
-           @param ident The new identifier name@mapset
+           @param ident The new identifier "name@mapset"
            @param dbif The database interface to be used
            @param dbif The database interface to be used
         """
         """
 
 

+ 7 - 7
lib/python/temporal/base.py

@@ -68,9 +68,9 @@ class DictSQLSerializer(object):
             >>> t.serialize(type="UPDATE ALL", table="raster_base")
             >>> t.serialize(type="UPDATE ALL", table="raster_base")
             ('UPDATE raster_base SET  name = ?  ,creator = ?  ,creation_time = ?  ,modification_time = ?  ,mapset = ?  ,id = ? ;\\n', ('soil', 'soeren', datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2001, 1, 1, 0, 0), 'PERMANENT', 'soil@PERMANENT'))
             ('UPDATE raster_base SET  name = ?  ,creator = ?  ,creation_time = ?  ,modification_time = ?  ,mapset = ?  ,id = ? ;\\n', ('soil', 'soeren', datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2001, 1, 1, 0, 0), 'PERMANENT', 'soil@PERMANENT'))
             
             
-            @type must be SELECT. INSERT, UPDATE
-            @table The name of the table to select, insert or update
-            @where The optional where statement
+            @param type must be SELECT. INSERT, UPDATE
+            @param table The name of the table to select, insert or update
+            @param where The optional where statement
             @return a tuple containing the SQL string and the arguments
             @return a tuple containing the SQL string and the arguments
             
             
             \endcode
             \endcode
@@ -571,7 +571,7 @@ class DatasetBase(SQLDatabaseInterface):
                           that should be used to store the values
                           that should be used to store the values
             @param ident The unique identifier must be a combination of 
             @param ident The unique identifier must be a combination of 
                           the dataset name, layer name and the mapset 
                           the dataset name, layer name and the mapset 
-                          name@mapset or name:1@mapset
+                          "name@mapset" or "name:layer@mapset"
                           used as as primary key in the temporal database
                           used as as primary key in the temporal database
             @param name The name of the map or dataset
             @param name The name of the map or dataset
             @param mapset The name of the mapset 
             @param mapset The name of the mapset 
@@ -604,7 +604,7 @@ class DatasetBase(SQLDatabaseInterface):
 
 
            @param ident The unique identifier must be a combination 
            @param ident The unique identifier must be a combination 
                          of the dataset name, layer name and the mapset 
                          of the dataset name, layer name and the mapset 
-                         name@mapset or name:1@mapset
+                         "name@mapset" or "name:layer@mapset"
         """
         """
         self.ident = ident
         self.ident = ident
         self.D["id"] = ident
         self.D["id"] = ident
@@ -632,7 +632,7 @@ class DatasetBase(SQLDatabaseInterface):
     def set_mapset(self, mapset):
     def set_mapset(self, mapset):
         """!Set the mapset of the dataset
         """!Set the mapset of the dataset
 
 
-           @param mapsets The name of the mapset in which this dataset is stored
+           @param mapset The name of the mapset in which this dataset is stored
         """
         """
         self.D["mapset"] = mapset
         self.D["mapset"] = mapset
 
 
@@ -699,7 +699,7 @@ class DatasetBase(SQLDatabaseInterface):
         """!Convenient method to get the unique map identifier 
         """!Convenient method to get the unique map identifier 
            without layer information
            without layer information
 
 
-           @return the name of the vector map as name@mapset
+           @return the name of the vector map as "name@mapset"
                   or None in case the id was not set
                   or None in case the id was not set
         """
         """
         if self.id:
         if self.id:

+ 84 - 0
lib/python/temporal/create.py

@@ -0,0 +1,84 @@
+"""!@package grass.temporal
+
+@brief GRASS Python scripting module (temporal GIS functions)
+
+Temporal GIS related functions to be used in Python scripts.
+
+Usage:
+
+@code
+import grass.temporal as tgis
+
+tgis.register_maps_in_space_time_dataset(type, name, maps)
+
+...
+@endcode
+
+(C) 2008-2011 by the GRASS Development Team
+This program is free software under the GNU General Public
+License (>=v2). Read the file COPYING that comes with GRASS
+for details.
+
+@author Soeren Gebbert
+"""
+
+from space_time_datasets import *
+
+###############################################################################
+
+def create_space_time_dataset(name, type, temporaltype, title, descr, semantic,
+                              dbif=None, overwrite=False):
+    """!Create a new space time dataset
+    
+       This function is sensitive to the settings in grass.core.overwrite to
+       overwrute existing space time datasets.
+    
+       @param name The name of the new space time dataset
+       @param type The type (strds, stvds, str3ds) of the new space time dataset
+       @param temporaltype The temporal type (relative or absolute)
+       @param title The title
+       @param descr The dataset description
+       @param semantic Semantical information
+       @param dbif The temporal database interface to be used
+       @param overwrite Flag to allow overwriting
+       
+       @return The new created space time dataset
+       
+       This function will raise a ScriptError in case of an error.
+    """
+    
+    #Get the current mapset to create the id of the space time dataset
+
+    mapset = core.gisenv()["MAPSET"]
+    id = name + "@" + mapset
+
+    sp = dataset_factory(type, id)
+
+    dbif, connected = init_dbif(dbif)
+
+    if sp.is_in_db(dbif) and overwrite == False:
+        if connected:
+            dbif.close()
+        core.fatal(_("Space time %s dataset <%s> is already in the database. "
+                      "Use the overwrite flag.") %
+                    (sp.get_new_map_instance(None).get_type(), name))
+        return None
+
+    if sp.is_in_db(dbif) and overwrite == True:
+        core.warning(_("Overwrite space time %s dataset <%s> "
+                     "and unregister all maps.") %
+                   (sp.get_new_map_instance(None).get_type(), name))
+        sp.delete(dbif)
+        sp = sp.get_new_instance(id)
+
+    core.verbose(_("Create new space time %s dataset.") %
+                  sp.get_new_map_instance(None).get_type())
+
+    sp.set_initial_values(temporal_type=temporaltype, semantic_type=semantic,
+                          title=title, description=descr)
+    sp.insert(dbif)
+
+    if connected:
+        dbif.close()
+        
+    return sp

+ 54 - 0
lib/python/temporal/factory.py

@@ -0,0 +1,54 @@
+"""!@package grass.temporal
+
+@brief GRASS Python scripting module (temporal GIS functions)
+
+Temporal GIS related functions to be used in Python scripts.
+
+Usage:
+
+@code
+import grass.temporal as tgis
+
+tgis.register_maps_in_space_time_dataset(type, name, maps)
+
+...
+@endcode
+
+(C) 2008-2011 by the GRASS Development Team
+This program is free software under the GNU General Public
+License (>=v2). Read the file COPYING that comes with GRASS
+for details.
+
+@author Soeren Gebbert
+"""
+
+from space_time_datasets import *
+
+###############################################################################
+
+
+def dataset_factory(type, id):
+    """!A factory functions to create space time or map datasets
+
+       @param type the dataset type: rast or raster, rast3d,
+                    vect or vector, strds, str3ds, stvds
+       @param id The id of the dataset ("name@mapset")
+    """
+    if type == "strds":
+        sp = SpaceTimeRasterDataset(id)
+    elif type == "str3ds":
+        sp = SpaceTimeRaster3DDataset(id)
+    elif type == "stvds":
+        sp = SpaceTimeVectorDataset(id)
+    elif type == "rast" or type == "raster":
+        sp = RasterDataset(id)
+    elif type == "rast3d":
+        sp = Raster3DDataset(id)
+    elif type == "vect" or type == "vector":
+        sp = VectorDataset(id)
+    else:
+        core.error(_("Unknown dataset type: %s") % type)
+        return None
+
+    return sp
+

+ 111 - 0
lib/python/temporal/gui_support.py

@@ -0,0 +1,111 @@
+"""!@package grass.temporal
+
+@brief GRASS Python scripting module (temporal GIS functions)
+
+Temporal GIS related functions to be used in Python scripts.
+
+
+(C) 2008-2011 by the GRASS Development Team
+This program is free software under the GNU General Public
+License (>=v2). Read the file COPYING that comes with GRASS
+for details.
+
+@author Soeren Gebbert
+"""
+
+from space_time_datasets import *
+
+###############################################################################
+
+def tlist_grouped(type, group_type = False):
+    """!List of temporal elements grouped by mapsets.
+
+    Returns a dictionary where the keys are mapset 
+    names and the values are lists of space time datasets in that
+    mapset. Example:
+
+    @code
+    >>> tgis.tlist_grouped('strds')['PERMANENT']
+    ['precipitation', 'temperature']
+    @endcode
+    
+    @param type element type (strds, str3ds, stvds)
+    @param group_type TBD
+
+    @return directory of mapsets/elements
+    """
+    result = {}
+    
+    mapset = None
+    if type == 'stds':
+        types = ['strds', 'str3ds', 'stvds']
+    else:
+        types = [type]
+    for type in types:
+        try:
+            tlist_result = tlist(type)
+        except core.ScriptError, e:
+            warning(e)
+            continue
+
+        for line in tlist_result:
+            try:
+                name, mapset = line.split('@')
+            except ValueError:
+                warning(_("Invalid element '%s'") % line)
+                continue
+
+            if mapset not in result:
+                if group_type:
+                    result[mapset] = {}
+                else:
+                    result[mapset] = []
+
+            if group_type:
+                if type in result[mapset]:
+                    result[mapset][type].append(name)
+                else:        
+                    result[mapset][type] = [name, ]
+            else:
+                result[mapset].append(name)
+
+    return result
+
+###############################################################################
+
+def tlist(type):
+    """!Return a list of space time datasets of absolute and relative time
+     
+    @param type element type (strds, str3ds, stvds)
+
+    @return a list of space time dataset ids
+    """
+    id = None
+    sp = dataset_factory(type, id)
+
+    dbif = SQLDatabaseInterfaceConnection()
+    dbif.connect()
+
+    output = []
+    temporal_type = ["absolute", 'relative']
+    for type in temporal_type:
+        # Table name
+        if type == "absolute":
+            table = sp.get_type() + "_view_abs_time"
+        else:
+            table = sp.get_type() + "_view_rel_time"
+
+        # Create the sql selection statement
+        sql = "SELECT id FROM " + table
+        sql += " ORDER BY id"
+
+        dbif.cursor.execute(sql)
+        rows = dbif.cursor.fetchall()
+
+        # Append the ids of the space time datasets
+        for row in rows:
+            for col in row:
+                output.append(str(col))
+    dbif.close()
+
+    return output

+ 195 - 0
lib/python/temporal/list.py

@@ -0,0 +1,195 @@
+"""!@package grass.temporal
+
+@brief GRASS Python scripting module (temporal GIS functions)
+
+Temporal GIS related functions to be used in Python scripts.
+
+Usage:
+
+@code
+import grass.temporal as tgis
+
+tgis.register_maps_in_space_time_dataset(type, name, maps)
+
+...
+@endcode
+
+(C) 2008-2011 by the GRASS Development Team
+This program is free software under the GNU General Public
+License (>=v2). Read the file COPYING that comes with GRASS
+for details.
+
+@author Soeren Gebbert
+"""
+
+from space_time_datasets import *
+
+###############################################################################
+
+def list_maps_of_stds(type, input, columns, order, where, separator, method, header, gran=None):
+    """! List the maps of a space time dataset using diffetent methods
+
+        @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 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@mapset") as comma separated string
+            - "delta" Print the map ids ("name@mapset") with start time,
+                       end time, relative length of intervals and the relative
+                       distance to the begin
+            - "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
+        @param gran The user defined granule to be used if method=gran is set, in case gran=None the 
+            granule of the space time dataset is used
+    """
+    mapset = core.gisenv()["MAPSET"]
+
+    if input.find("@") >= 0:
+        id = input
+    else:
+        id = input + "@" + mapset
+
+    dbif, connected = init_dbif(None)
+    
+    sp = dataset_factory(type, id)
+
+    if not sp.is_in_db(dbif=dbif):
+        core.fatal(_("Dataset <%s> not found in temporal database") % (id))
+
+    sp.select(dbif=dbif)
+
+    if separator is None or separator == "":
+        separator = "\t"
+
+    # This method expects a list of objects for gap detection
+    if method == "delta" or method == "deltagaps" or method == "gran":
+        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=where, dbif=dbif)
+        elif method == "delta":
+            maps = sp.get_registered_maps_as_objects(where=where, order="start_time", dbif=dbif)
+        elif method == "gran":
+            if gran is not None and gran != "":
+                maps = sp.get_registered_maps_as_objects_by_granularity(gran=gran, dbif=dbif)
+            else:
+                maps = sp.get_registered_maps_as_objects_by_granularity(dbif=dbif)
+            
+        if header:
+            string = ""
+            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)
+            string += "%s" % ("distance_from_begin")
+            print string
+
+        if maps and len(maps) > 0:
+
+            if isinstance(maps[0], list):
+                if len(maps[0]) > 0:
+                    first_time, dummy = maps[0][0].get_valid_time()
+                else:
+                    core.warning(_("Empty map list."))
+                    return
+            else:
+                first_time, dummy = maps[0].get_valid_time()
+
+            for mymap in maps:
+
+                if isinstance(mymap, list):
+                    if len(mymap) > 0:
+                        map = mymap[0]
+                    else:
+                        core.fatal(_("Empty entry in map list, this should not happen."))
+                else:
+                    map = mymap
+
+                start, end = map.get_valid_time()
+                if end:
+                    delta = end - start
+                else:
+                    delta = None
+                delta_first = start - first_time
+
+                if map.is_time_absolute():
+                    if end:
+                        delta = time_delta_to_relative_time(delta)
+                    delta_first = time_delta_to_relative_time(delta_first)
+
+                string = ""
+                string += "%s%s" % (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)
+                string += "%s" % (delta_first)
+                print string
+
+    else:
+        # In comma separated mode only map ids are needed
+        if method == "comma":
+            columns = "id"
+
+        rows = sp.get_registered_maps(columns, where, order, dbif)
+
+        if rows:
+            if method == "comma":
+                string = ""
+                count = 0
+                for row in rows:
+                    if count == 0:
+                        string += row["id"]
+                    else:
+                        string += ",%s" % row["id"]
+                    count += 1
+                print string
+
+            elif method == "cols":
+                # Print the column names if requested
+                if header:
+                    output = ""
+                    count = 0
+
+                    collist = columns.split(",")
+
+                    for key in collist:
+                        if count > 0:
+                            output += separator + str(key)
+                        else:
+                            output += str(key)
+                        count += 1
+                    print output
+
+                for row in rows:
+                    output = ""
+                    count = 0
+                    for col in row:
+                        if count > 0:
+                            output += separator + str(col)
+                        else:
+                            output += str(col)
+                        count += 1
+
+                    print output
+    if connected:
+        dbif.close()

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

@@ -60,13 +60,13 @@ def dataset_mapcalculator(inputs, output, type, expression, base, method,
        - end_second() - The minute of the end time [0 - 59]
        - end_second() - The minute of the end time [0 - 59]
        
        
 
 
-       @param input The name of the input space time raster/raster3d dataset
+       @param inputs The names of the input space time raster/raster3d datasets
        @param output The name of the extracted new space time raster(3d) dataset
        @param output The name of the extracted new space time raster(3d) dataset
        @param type The type of the dataset: "raster" or "raster3d"
        @param type The type of the dataset: "raster" or "raster3d"
-       @param method The method to be used for temporal sampling
        @param expression The r(3).mapcalc expression
        @param expression The r(3).mapcalc expression
        @param base The base name of the new created maps in case a 
        @param base The base name of the new created maps in case a 
               mapclac expression is provided
               mapclac expression is provided
+       @param method The method to be used for temporal sampling
        @param nprocs The number of parallel processes to be used for 
        @param nprocs The number of parallel processes to be used for 
               mapcalc processing
               mapcalc processing
        @param register_null Set this number True to register empty maps
        @param register_null Set this number True to register empty maps

+ 158 - 14
lib/python/temporal/pythontemporallib.dox

@@ -1,12 +1,29 @@
-/*! \page pythontemporallib GRASS Python Temporal Library
+/*! \page pythontemporallib GRASS GIS Temporal Framework
 
 
 by GRASS Development Team (http://grass.osgeo.org)
 by GRASS Development Team (http://grass.osgeo.org)
 
 
-Python Temporal GIS package
+The GRASS GIS Temporal Framework
 
 
-TODO: add more detailed documentation
+\section PythonTGISIntro Introduction
 
 
-List of modules:
+The GRASS GIS Temporal Framework implements the temporal GIS functionality of GRASS GIS
+and provides an API to implement spatio-temporal processing modules. The framework 
+introduces space time datasets that represent time series of raster, 3D raster or vector maps.
+This framework provides the following functionalities: 
+- Assign time stamp to maps and register maps in the temporal database
+- Modification of time stamps
+- Creation, renaming and deletion of space time datasets
+- Registration and un-registration of maps in space time datasets
+- Query of maps that are registered in space time datasets using SQL where statements
+- Analysis of the spatio-temporal topology of space time datasets
+- Sampling of space time datasets
+- Computation of temporal and spatial relationships between registered maps
+- Higher level functions that are shared between modules
+
+Most of the functions described above are member functions of the maps and space time dataset classes.
+Maps and space time datasets are represented as objects in the temporal framework.
+
+\section PythonTGISPackages Library
 
 
 Core functionality such as the database interface connection to sqlite3 
 Core functionality such as the database interface connection to sqlite3 
 and postgresql as well as the creation of the temporal database are defined here:
 and postgresql as well as the creation of the temporal database are defined here:
@@ -15,18 +32,17 @@ and postgresql as well as the creation of the temporal database are defined here
 
 
 In these modules are the temporal database interfaces for raster maps, 
 In these modules are the temporal database interfaces for raster maps, 
 3D raster maps, vector maps and space time datasets defined. 
 3D raster maps, vector maps and space time datasets defined. 
-
-Additionally the temporal and spatial extent modules implement the topological 
-relationship computation that is needed for spatio-temporal topology computation.
+In addition the temporal and spatial extent modules implement the topological 
+relationship computation that is needed for spatio-temporal topology computation:
 
 
 - python::temporal::base
 - python::temporal::base
 - python::temporal::spatial_extent
 - python::temporal::spatial_extent
 - python::temporal::temporal_extent
 - python::temporal::temporal_extent
 - python::temporal::metadata
 - python::temporal::metadata
 
 
-Several "abstract" modules are defined that implement the shared functionality 
+Several "abstract" classes are defined that implement the shared functionality 
 of time stamped maps and space time datasets, such as temporal and spatial
 of time stamped maps and space time datasets, such as temporal and spatial
-handling and representation. 
+handling and representation:
 
 
 - python::temporal::abstract_dataset
 - python::temporal::abstract_dataset
 - python::temporal::abstract_temporal_dataset
 - python::temporal::abstract_temporal_dataset
@@ -42,27 +58,155 @@ Helper functions to compute temporal granularity, handling of datetime objects
 and their conversion as well as topology computation are defined in these modules:
 and their conversion as well as topology computation are defined in these modules:
 
 
 - python::temporal::datetime_math
 - python::temporal::datetime_math
-- python::temporal::temporal_relationships
 - python::temporal::temporal_granularity
 - python::temporal::temporal_granularity
+- python::temporal::temporal_relationships
 
 
 Functionality that is shared between different temporal GRASS modules, such as
 Functionality that is shared between different temporal GRASS modules, such as
-map listing, map registration and unregistration, aggregation, extraction,
-map calculation, statistics as well as import and export of 
+map listing, space time dataset creation, map registration and unregistration, 
+aggregation, extraction, map calculation, statistics as well as import and export of 
 space time datasets are defined here:
 space time datasets are defined here:
 
 
-- python::temporal::space_time_datasets_tools
 - python::temporal::aggregation
 - python::temporal::aggregation
+- python::temporal::create
 - python::temporal::extract
 - python::temporal::extract
+- python::temporal::factory
+- python::temporal::list
 - python::temporal::mapcalc
 - python::temporal::mapcalc
+- python::temporal::register
+- python::temporal::sampling
 - python::temporal::stds_export
 - python::temporal::stds_export
 - python::temporal::stds_import
 - python::temporal::stds_import
 - python::temporal::univar_statistics
 - python::temporal::univar_statistics
 
 
+Two helper functions to support the listing of space time datasets in the automatically generated GUI:
+
+- python::temporal::gui_support
+
 Lots of unit tests:
 Lots of unit tests:
 
 
 - python::temporal::unit_tests
 - python::temporal::unit_tests
 
 
-\section pythonTempAuthors Authors
+\section PythonTGISExamples Examples
+
+\subsection PythonTGISExamplesSimple Simple example
+
+This simple example shows how to open a space time raster dataset
+to access its registered maps.
+
+\code
+# Lets import the temporal framework and
+# the script framework
+import grass.temporal as tgis
+import grass.script as grass
+
+# Make sure the temporal database exists
+# and set the temporal GIS environment
+tgis.init()
+
+# We create the temporal database interface for fast processing
+dbif = tgis.SQLDatabaseInterfaceConnection()
+dbif.connect()
+
+# The id of a space time raster dataset is build from its name and its mapset
+id = "test@PERMANENT"
+
+# We create a space time raster dataset object 
+strds = tgis.SpaceTimeRasterDataset(id)
+
+# Check if the space time raster dataset is in the temporal database
+if strds.is_in_db(dbif=dbif) == False:
+    dbif.close()
+    grass.fatal(_("Space time %s dataset <%s> not found") % (
+        strds.get_new_map_instance(None).get_type(), id))
+
+# Fill the object with the content from the temporal database
+strds.select(dbif=dbif)
+
+# Print informations about the space time raster dataset to stdout
+strds.print_info()
+
+# Get all maps that are registered in the strds and print
+# informations about the maps to stdout
+maps = strds.get_registered_maps_as_objects(dbif=dbif)
+
+# We iterate over the temporal sorted map list
+for map in maps:
+    # We fill the map object with the content 
+    # from the temporal database. We use the existing
+    # database connection, otherwise a new connection 
+    # will be established for each map object 
+    # which slows the processing down
+    map.select(dbif=dbif)
+    map.print_info()
+
+# Close the database connection
+dbif.close()
+\endcode
+
+
+\subsection PythonTGISExamplesSTDSCreation Creation of a space time dataset
+
+This example shows howto create a space time dataset. The code is generic and works
+for different space time datasets (raster, 3D raster and vector): 
+
+\code
+# Lets import the temporal framework and
+# the script framework
+import grass.temporal as tgis
+import grass.script as grass
+
+# The id of the new space time dataset
+id="test@PERMANENT"
+# The title of the new space time dataset
+title="This is a test dataset" 
+# The description of the space time dataset
+description="The description"
+# The type of the space time dataset (strds, str3ds or stvds)
+type="strds"
+# The temporal type of the space time dataset (absolute or relative)
+temporal_type="absolute"
+
+# Make sure the temporal database exists
+# and set the temporal GIS environment
+tgis.init()
+
+# We use the dataset factory to create an new space time dataset instance of a specific type
+stds = tgis.dataset_factory(type, id)
+
+# We need a dtabase connection to insert the content of the space time dataset
+dbif = tgis.SQLDatabaseInterfaceConnection()
+dbif.connect()
+
+# First we check if the dataset is already in the database
+if stds.is_in_db(dbif=dbif) and overwrite == False:
+    dbif.close()
+    grass.fatal(_("Space time %s dataset <%s> is already in the database. "
+                    "Use the overwrite flag.") %
+                (stds.get_new_map_instance(None).get_type(), name))
+
+# We delete the exiting dataset and create a new one in case we are allowed to overwrite it
+if stds.is_in_db(dbif=dbif) and overwrite == True:
+    grass.warning(_("Overwrite space time %s dataset <%s> "
+                    "and unregister all maps.") %
+                (stds.get_new_map_instance(None).get_type(), name))
+    stds.delete(dbif=dbif)
+    stds = stds.get_new_instance(id)
+
+# We set the initial values. This function also created the command history.
+stds.set_initial_values(temporal_type=temporaltype, semantic_type="mean",
+                        title=title, description=description)
+                        
+# Now we can insert the new space time dataset in the database
+stds.insert(dbif=dbif)
+
+# Close the database connection
+dbif.close()
+    
+\endcode
+
+\section PythonTGISAuthors Authors
 
 
 Soeren Gebbert
 Soeren Gebbert
+
+TODO: add more documentation
 */
 */

+ 419 - 0
lib/python/temporal/register.py

@@ -0,0 +1,419 @@
+"""!@package grass.temporal
+
+@brief GRASS Python scripting module (temporal GIS functions)
+
+Temporal GIS related functions to be used in Python scripts.
+
+Usage:
+
+@code
+import grass.temporal as tgis
+
+tgis.register_maps_in_space_time_dataset(type, name, maps)
+
+...
+@endcode
+
+(C) 2008-2011 by the GRASS Development Team
+This program is free software under the GNU General Public
+License (>=v2). Read the file COPYING that comes with GRASS
+for details.
+
+@author Soeren Gebbert
+"""
+
+from space_time_datasets import *
+
+###############################################################################
+
+
+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="|"):
+    """!Use this method to register maps in space time datasets. 
+
+       Additionally a start time string and an increment string can be specified
+       to assign a time interval automatically to the maps.
+
+       It takes care of the correct update of the space time datasets from all
+       registered maps.
+
+       @param type The type of the maps rast, rast3d or vect
+       @param name The name of the space time dataset
+       @param maps A comma separated list of map names
+       @param file Input file one map with start and optional end time, 
+                    one per line
+       @param start The start date and time of the first raster map
+                    (format absolute: "yyyy-mm-dd HH:MM:SS" or "yyyy-mm-dd",
+                    format relative is integer 5)
+       @param end The end date and time of the first raster map
+                   (format absolute: "yyyy-mm-dd HH:MM:SS" or "yyyy-mm-dd",
+                   format relative is integer 5)
+       @param unit The unit of the relative time: years, months, days,
+                    hours, minutes, seconds
+       @param increment Time increment between maps for time stamp creation
+                         (format absolute: NNN seconds, minutes, hours, days,
+                         weeks, months, years; format relative: 1.0)
+       @param dbif The database interface to be used
+       @param interval If True, time intervals are created in case the start
+                        time and an increment is provided
+       @param fs Field separator used in input file
+    """
+
+    start_time_in_file = False
+    end_time_in_file = False
+
+    if maps and file:
+        core.fatal(_("%s= and %s= are mutually exclusive") % ("maps", "file"))
+
+    if end and increment:
+        core.fatal(_("%s= and %s= are mutually exclusive") % (
+            "end", "increment"))
+
+    if end and not start:
+        core.fatal(_("Please specify %s= and %s=") % ("start_time",
+                                                      "end_time"))
+
+    if not maps and not file:
+        core.fatal(_("Please specify %s= or %s=") % ("maps", "file"))
+
+    # We may need the mapset
+    mapset = core.gisenv()["MAPSET"]
+
+    # The name of the space time dataset is optional
+    if name:
+        # Check if the dataset name contains the mapset as well
+        if name.find("@") < 0:
+            id = name + "@" + mapset
+        else:
+            id = name
+
+        if type == "rast" or type == "raster":
+            sp = dataset_factory("strds", id)
+        elif type == "rast3d":
+            sp = dataset_factory("str3ds", id)
+        elif type == "vect" or type == "vector":
+            sp = dataset_factory("stvds", id)
+        else:
+            core.fatal(_("Unkown map type: %s") % (type))
+
+    dbif, connected = init_dbif(None)
+
+    if name:
+        # Read content from temporal database
+        sp.select(dbif)
+
+        if not sp.is_in_db(dbif):
+            dbif.close()
+            core.fatal(_("Space time %s dataset <%s> no found") %
+                       (sp.get_new_map_instance(None).get_type(), name))
+
+        if sp.is_time_relative() and not unit:
+            dbif.close()
+            core.fatal(_("Space time %s dataset <%s> with relative time found, "
+                         "but no relative unit set for %s maps") %
+                       (sp.get_new_map_instance(None).get_type(),
+                        name, sp.get_new_map_instance(None).get_type()))
+
+    # We need a dummy map object to build the map ids
+    dummy = dataset_factory(type, None)
+
+    maplist = []
+
+    # Map names as comma separated string
+    if maps:
+        if maps.find(",") < 0:
+            maplist = [maps, ]
+        else:
+            maplist = maps.split(",")
+
+        # Build the map list again with the ids
+        for count in range(len(maplist)):
+            row = {}
+            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")
+
+        line = True
+        while True:
+            line = fd.readline()
+            if not line:
+                break
+
+            line_list = line.split(fs)
+
+            # Detect start and end time
+            if len(line_list) == 2:
+                start_time_in_file = True
+                end_time_in_file = False
+            elif len(line_list) == 3:
+                start_time_in_file = True
+                end_time_in_file = True
+            else:
+                start_time_in_file = False
+                end_time_in_file = False
+
+            mapname = line_list[0].strip()
+            row = {}
+
+            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()
+
+            row["id"] = dummy.build_id(mapname, mapset)
+
+            maplist.append(row)
+
+    num_maps = len(maplist)
+    map_object_list = []
+    statement = ""
+    # Store the ids of datasets that must be updated
+    datatsets_to_modify = {}
+
+    core.message(_("Gathering map informations"))
+
+    for count in range(len(maplist)):
+        if count%50 == 0:
+            core.percent(count, num_maps, 1)
+
+        # Get a new instance of the map type
+        map = dataset_factory(type, maplist[count]["id"])
+
+        # Use the time data from file
+        if "start" in maplist[count]:
+            start = maplist[count]["start"]
+        if "end" in maplist[count]:
+            end = maplist[count]["end"]
+
+        is_in_db = False
+
+        # Put the map into the database
+        if not map.is_in_db(dbif):
+            is_in_db = False
+            # Break in case no valid time is provided
+            if start == "" or start is None:
+                dbif.close()
+                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()))
+
+            if unit:
+                map.set_time_to_relative()
+            else:
+                map.set_time_to_absolute()
+
+        else:
+            is_in_db = True
+            
+            # Check the overwrite flag
+            if not core.overwrite():                        
+                if map.get_layer():
+                    core.warning(_("Map is already registered in temporal database. "
+                                   "Unable to update %s map <%s> with layer %s. "
+                                   "Overwrite flag is not set.") %
+                               (map.get_type(), map.get_map_id(), str(map.get_layer())))
+                else:
+                    core.warning(_("Map is already registered in temporal database. "
+                                   "Unable to update %s map <%s>. "
+                                   "Overwrite flag is not set.") %
+                               (map.get_type(), map.get_map_id()))
+                
+                # Simple registration is allowed
+                if name:
+                    map_object_list.append(map)
+                # Jump to next map
+                continue
+            
+            # Select information from temporal database
+            map.select(dbif)
+            
+            # Save the datasets that must be updated
+            datasets = map.get_registered_datasets(dbif)
+            if datasets:
+                for dataset in datasets:
+                    datatsets_to_modify[dataset["id"]] = dataset["id"]
+                
+                if name and map.get_temporal_type() != sp.get_temporal_type():
+                    dbif.close()
+                    if map.get_layer():
+                        core.fatal(_("Unable to update %s map <%s> with layer. "
+                                     "The temporal types are different.") %
+                                   (map.get_type(), map.get_map_id(), map.get_layer()))
+                    else:
+                        core.fatal(_("Unable to update %s map <%s>. "
+                                     "The temporal types are different.") %
+                                   (map.get_type(), map.get_map_id()))
+
+        # Load the data from the grass file database
+        map.load()
+
+        # Set the valid time
+        if start:
+            # In case the time is in the input file we ignore the increment counter
+            if start_time_in_file:
+                count = 1
+            assign_valid_time_to_map(ttype=map.get_temporal_type(),
+                                     map=map, start=start, end=end, unit=unit,
+                                     increment=increment, mult=count,
+                                     interval=interval)
+
+        if is_in_db:
+            #  Gather the SQL update statement
+            statement += map.update_all(dbif=dbif, execute=False)
+        else:
+            #  Gather the SQL insert statement
+            statement += map.insert(dbif=dbif, execute=False)
+
+        # Sqlite3 performace better for huge datasets when committing in small chunks
+        if dbif.dbmi.__name__ == "sqlite3":
+            if count % 100 == 0:
+                if statement is not None and statement != "":
+                    core.message(_("Registering maps in the temporal database")
+                                 )
+                    dbif.execute_transaction(statement)
+                    statement = ""
+
+        # Store the maps in a list to register in a space time dataset
+        if name:
+            map_object_list.append(map)
+
+    core.percent(num_maps, num_maps, 1)
+
+    if statement is not None and statement != "":
+        core.message(_("Register maps in the temporal database"))
+        dbif.execute_transaction(statement)
+
+    # Finally Register the maps in the space time dataset
+    if name and map_object_list:
+        statement = ""
+        count = 0
+        num_maps = len(map_object_list)
+        core.message(_("Register maps in the space time raster dataset"))
+        for map in map_object_list:
+            if count%50 == 0:
+                core.percent(count, num_maps, 1)
+            sp.register_map(map=map, dbif=dbif)
+            count += 1
+
+    # Update the space time tables
+    if name and map_object_list:
+        core.message(_("Update space time raster dataset"))
+        sp.update_from_registered_maps(dbif)
+        sp.update_command_string(dbif=dbif)
+    
+    # Update affected datasets
+    if datatsets_to_modify:
+        for dataset in datatsets_to_modify:
+            if type == "rast" or type == "raster":
+                ds = dataset_factory("strds", dataset)
+            elif type == "rast3d":
+                ds = dataset_factory("str3ds", dataset)
+            elif type == "vect" or type == "vector":
+                ds = dataset_factory("stvds", dataset)
+            ds.select(dbif)
+            ds.update_from_registered_maps(dbif)
+
+    if connected == True:
+        dbif.close()
+
+    core.percent(num_maps, num_maps, 1)
+
+
+###############################################################################
+
+def assign_valid_time_to_map(ttype, map, start, end, unit, increment=None, mult=1, interval=False):
+    """!Assign the valid time to a map dataset
+
+       @param ttype The temporal type which should be assigned
+                     and which the time format is of
+       @param map A map dataset object derived from abstract_map_dataset
+       @param start The start date and time of the first raster map
+                     (format absolute: "yyyy-mm-dd HH:MM:SS" or "yyyy-mm-dd",
+                     format relative is integer 5)
+       @param end The end date and time of the first raster map
+                   (format absolute: "yyyy-mm-dd HH:MM:SS" or "yyyy-mm-dd",
+                   format relative is integer 5)
+       @param unit The unit of the relative time: years, months,
+                    days, hours, minutes, seconds
+       @param increment Time increment between maps for time stamp creation
+                        (format absolute: NNN seconds, minutes, hours, days,
+                        weeks, months, years; format relative is integer 1)
+       @param mult A multiplier for the increment
+       @param interval If True, time intervals are created in case the start
+                        time and an increment is provided
+    """
+
+    if ttype == "absolute":
+        start_time = string_to_datetime(start)
+        if start_time is None:
+            core.fatal(_("Unable to convert string \"%s\"into a "
+                         "datetime object") % (start))
+        end_time = None
+
+        if end:
+            end_time = string_to_datetime(end)
+            if end_time is None:
+                dbif.close()
+                core.fatal(_("Unable to convert string \"%s\"into a "
+                             "datetime object") % (end))
+
+        # Add the increment
+        if increment:
+            start_time = increment_datetime_by_string(
+                start_time, increment, mult)
+            if start_time is None:
+                core.fatal(_("Error in increment computation"))
+            if interval:
+                end_time = increment_datetime_by_string(
+                    start_time, increment, 1)
+                if end_time is None:
+                    core.fatal(_("Error in increment computation"))
+        # Commented because of performance issue calling g.message thousend times
+        #if map.get_layer():
+        #    core.verbose(_("Set absolute valid time for map <%(id)s> with "
+        #                   "layer %(layer)s to %(start)s - %(end)s") %
+        #                 {'id': map.get_map_id(), 'layer': map.get_layer(),
+        #                  'start': str(start_time), 'end': 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.set_absolute_time(start_time, end_time, None)
+    else:
+        start_time = int(start)
+        end_time = None
+
+        if end:
+            end_time = int(end)
+
+        if increment:
+            start_time = start_time + mult * int(increment)
+            if interval:
+                end_time = start_time + int(increment)
+
+        # Commented because of performance issue calling g.message thousend times
+        #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.set_relative_time(start_time, end_time, unit)

+ 169 - 0
lib/python/temporal/sampling.py

@@ -0,0 +1,169 @@
+"""!@package grass.temporal
+
+@brief GRASS Python scripting module (temporal GIS functions)
+
+Temporal GIS related functions to be used in Python scripts.
+
+Usage:
+
+@code
+import grass.temporal as tgis
+
+tgis.register_maps_in_space_time_dataset(type, name, maps)
+
+...
+@endcode
+
+(C) 2008-2011 by the GRASS Development Team
+This program is free software under the GNU General Public
+License (>=v2). Read the file COPYING that comes with GRASS
+for details.
+
+@author Soeren Gebbert
+"""
+
+from space_time_datasets import *
+
+###############################################################################
+
+def sample_stds_by_stds_topology(intype, sampletype, inputs, sampler, header, 
+                                 separator, method, spatial=False, 
+                                 print_only=True):
+    """!Sample the input space time datasets with a sample 
+       space time dataset, return the created map matrix and optionally 
+       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@mapset"
+
+        Attention: Do not use the comma as separator for printing
+
+        @param intype  Type of the input space time dataset (strds, stvds or str3ds)
+        @param sampletype Type of the sample space time dataset (strds, stvds or str3ds)
+        @param inputs Name or comma separated names of space time datasets
+        @param sampler Name of a space time dataset used for temporal sampling
+        @param header Set True to print column names
+        @param separator The field separator character between the columns
+        @param method The method to be used for temporal sampling 
+                       (start,during,contain,overlap,equal)
+        @param spatial Perform spatial overlapping check
+        @param print_only If set True (default) then the result of the sampling will be 
+                    printed to stdout, if set to False the resulting map matrix 
+                    will be returned. 
+                    
+        @return The map matrix or None if nothing found
+    """
+    mapset = core.gisenv()["MAPSET"]
+
+    # Make a method list
+    method = method.split(",")
+
+    # Split the inputs
+    input_list = inputs.split(",")
+    sts = []
+
+    for input in input_list:
+        if input.find("@") >= 0:
+            id = input
+        else:
+            id = input + "@" + mapset
+
+        st = dataset_factory(intype, id)
+        sts.append(st)
+
+    if sampler.find("@") >= 0:
+        sid = sampler
+    else:
+        sid = sampler + "@" + mapset
+
+    sst = dataset_factory(sampletype, sid)
+
+    dbif = SQLDatabaseInterfaceConnection()
+    dbif.connect()
+
+    for st in sts:
+        if st.is_in_db(dbif) == False:
+            core.fatal(_("Dataset <%s> not found in temporal database") % (st.get_id()))
+        st.select(dbif)
+
+    if sst.is_in_db(dbif) == False:
+        core.fatal(_("Dataset <%s> not found in temporal database") % (sid))
+
+    sst.select(dbif)
+
+    if separator is None or separator == "" or separator.find(",") >= 0:
+        separator = " | "
+
+    mapmatrizes = []
+    for st in sts:
+        mapmatrix = st.sample_by_dataset(sst, method, spatial, dbif)
+        if mapmatrix and len(mapmatrix) > 0:
+            mapmatrizes.append(mapmatrix)
+
+    if len(mapmatrizes) > 0:
+        
+        # Simply return the map matrix
+        if not print_only:
+            dbif.close()
+            return mapmatrizes
+
+        if header:
+            string = ""
+            string += "%s%s" % (sst.get_id(), separator)
+            for st in sts:
+                string += "%s%s" % (st.get_id(), separator)
+            string += "%s%s" % ("start_time", separator)
+            string += "%s%s" % ("end_time", separator)
+            string += "%s%s" % ("interval_length", separator)
+            string += "%s" % ("distance_from_begin")
+            print string
+
+        first_time, dummy = mapmatrizes[0][0]["granule"].get_valid_time()
+
+        for i in range(len(mapmatrizes[0])):
+            mapname_list = []
+            for mapmatrix in mapmatrizes:
+                mapnames = ""
+                count = 0
+                entry = mapmatrix[i]
+                for sample in entry["samples"]:
+                    if count == 0:
+                        mapnames += str(sample.get_id())
+                    else:
+                        mapnames += ",%s" % str(sample.get_id())
+                    count += 1
+                mapname_list.append(mapnames)
+
+            entry = mapmatrizes[0][i]
+            map = entry["granule"]
+
+            start, end = map.get_valid_time()
+            if end:
+                delta = end - start
+            else:
+                delta = None
+            delta_first = start - first_time
+
+            if map.is_time_absolute():
+                if end:
+                    delta = time_delta_to_relative_time(delta)
+                delta_first = time_delta_to_relative_time(delta_first)
+
+            string = ""
+            string += "%s%s" % (map.get_id(), separator)
+            for mapnames in mapname_list:
+                string += "%s%s" % (mapnames, separator)
+            string += "%s%s" % (start, separator)
+            string += "%s%s" % (end, separator)
+            string += "%s%s" % (delta, separator)
+            string += "%s" % (delta_first)
+            print string
+
+    dbif.close()
+    if len(mapmatrizes) > 0:
+        return mapmatrizes
+    
+    return None

+ 0 - 917
lib/python/temporal/space_time_datasets_tools.py

@@ -1,917 +0,0 @@
-"""!@package grass.temporal
-
-@brief GRASS Python scripting module (temporal GIS functions)
-
-Temporal GIS related functions to be used in Python scripts.
-
-Usage:
-
-@code
-import grass.temporal as tgis
-
-tgis.register_maps_in_space_time_dataset(type, name, maps)
-
-...
-@endcode
-
-(C) 2008-2011 by the GRASS Development Team
-This program is free software under the GNU General Public
-License (>=v2). Read the file COPYING that comes with GRASS
-for details.
-
-@author Soeren Gebbert
-"""
-
-from space_time_datasets import *
-
-###############################################################################
-
-
-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="|"):
-    """!Use this method to register maps in space time datasets. 
-
-       Additionally a start time string and an increment string can be specified
-       to assign a time interval automatically to the maps.
-
-       It takes care of the correct update of the space time datasets from all
-       registered maps.
-
-       @param type The type of the maps rast, rast3d or vect
-       @param name The name of the space time dataset
-       @param maps A comma separated list of map names
-       @param file Input file one map with start and optional end time, 
-                    one per line
-       @param start The start date and time of the first raster map
-                    (format absolute: "yyyy-mm-dd HH:MM:SS" or "yyyy-mm-dd",
-                    format relative is integer 5)
-       @param end The end date and time of the first raster map
-                   (format absolute: "yyyy-mm-dd HH:MM:SS" or "yyyy-mm-dd",
-                   format relative is integer 5)
-       @param unit The unit of the relative time: years, months, days,
-                    hours, minutes, seconds
-       @param increment Time increment between maps for time stamp creation
-                         (format absolute: NNN seconds, minutes, hours, days,
-                         weeks, months, years; format relative: 1.0)
-       @param dbif The database interface to be used
-       @param interval If True, time intervals are created in case the start
-                        time and an increment is provided
-       @param fs Field separator used in input file
-    """
-
-    start_time_in_file = False
-    end_time_in_file = False
-
-    if maps and file:
-        core.fatal(_("%s= and %s= are mutually exclusive") % ("maps", "file"))
-
-    if end and increment:
-        core.fatal(_("%s= and %s= are mutually exclusive") % (
-            "end", "increment"))
-
-    if end and not start:
-        core.fatal(_("Please specify %s= and %s=") % ("start_time",
-                                                      "end_time"))
-
-    if not maps and not file:
-        core.fatal(_("Please specify %s= or %s=") % ("maps", "file"))
-
-    # We may need the mapset
-    mapset = core.gisenv()["MAPSET"]
-
-    # The name of the space time dataset is optional
-    if name:
-        # Check if the dataset name contains the mapset as well
-        if name.find("@") < 0:
-            id = name + "@" + mapset
-        else:
-            id = name
-
-        if type == "rast" or type == "raster":
-            sp = dataset_factory("strds", id)
-        elif type == "rast3d":
-            sp = dataset_factory("str3ds", id)
-        elif type == "vect" or type == "vector":
-            sp = dataset_factory("stvds", id)
-        else:
-            core.fatal(_("Unkown map type: %s") % (type))
-
-    dbif, connected = init_dbif(None)
-
-    if name:
-        # Read content from temporal database
-        sp.select(dbif)
-
-        if not sp.is_in_db(dbif):
-            dbif.close()
-            core.fatal(_("Space time %s dataset <%s> no found") %
-                       (sp.get_new_map_instance(None).get_type(), name))
-
-        if sp.is_time_relative() and not unit:
-            dbif.close()
-            core.fatal(_("Space time %s dataset <%s> with relative time found, "
-                         "but no relative unit set for %s maps") %
-                       (sp.get_new_map_instance(None).get_type(),
-                        name, sp.get_new_map_instance(None).get_type()))
-
-    # We need a dummy map object to build the map ids
-    dummy = dataset_factory(type, None)
-
-    maplist = []
-
-    # Map names as comma separated string
-    if maps:
-        if maps.find(",") < 0:
-            maplist = [maps, ]
-        else:
-            maplist = maps.split(",")
-
-        # Build the map list again with the ids
-        for count in range(len(maplist)):
-            row = {}
-            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")
-
-        line = True
-        while True:
-            line = fd.readline()
-            if not line:
-                break
-
-            line_list = line.split(fs)
-
-            # Detect start and end time
-            if len(line_list) == 2:
-                start_time_in_file = True
-                end_time_in_file = False
-            elif len(line_list) == 3:
-                start_time_in_file = True
-                end_time_in_file = True
-            else:
-                start_time_in_file = False
-                end_time_in_file = False
-
-            mapname = line_list[0].strip()
-            row = {}
-
-            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()
-
-            row["id"] = dummy.build_id(mapname, mapset)
-
-            maplist.append(row)
-
-    num_maps = len(maplist)
-    map_object_list = []
-    statement = ""
-    # Store the ids of datasets that must be updated
-    datatsets_to_modify = {}
-
-    core.message(_("Gathering map informations"))
-
-    for count in range(len(maplist)):
-        if count%50 == 0:
-            core.percent(count, num_maps, 1)
-
-        # Get a new instance of the map type
-        map = dataset_factory(type, maplist[count]["id"])
-
-        # Use the time data from file
-        if "start" in maplist[count]:
-            start = maplist[count]["start"]
-        if "end" in maplist[count]:
-            end = maplist[count]["end"]
-
-        is_in_db = False
-
-        # Put the map into the database
-        if not map.is_in_db(dbif):
-            is_in_db = False
-            # Break in case no valid time is provided
-            if start == "" or start is None:
-                dbif.close()
-                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()))
-
-            if unit:
-                map.set_time_to_relative()
-            else:
-                map.set_time_to_absolute()
-
-        else:
-            is_in_db = True
-            
-            # Check the overwrite flag
-            if not core.overwrite():                        
-                if map.get_layer():
-                    core.warning(_("Map is already registered in temporal database. "
-                                   "Unable to update %s map <%s> with layer %s. "
-                                   "Overwrite flag is not set.") %
-                               (map.get_type(), map.get_map_id(), str(map.get_layer())))
-                else:
-                    core.warning(_("Map is already registered in temporal database. "
-                                   "Unable to update %s map <%s>. "
-                                   "Overwrite flag is not set.") %
-                               (map.get_type(), map.get_map_id()))
-                
-                # Simple registration is allowed
-                if name:
-                    map_object_list.append(map)
-                # Jump to next map
-                continue
-            
-            # Select information from temporal database
-            map.select(dbif)
-            
-            # Save the datasets that must be updated
-            datasets = map.get_registered_datasets(dbif)
-            if datasets:
-                for dataset in datasets:
-                    datatsets_to_modify[dataset["id"]] = dataset["id"]
-                
-                if name and map.get_temporal_type() != sp.get_temporal_type():
-                    dbif.close()
-                    if map.get_layer():
-                        core.fatal(_("Unable to update %s map <%s> with layer. "
-                                     "The temporal types are different.") %
-                                   (map.get_type(), map.get_map_id(), map.get_layer()))
-                    else:
-                        core.fatal(_("Unable to update %s map <%s>. "
-                                     "The temporal types are different.") %
-                                   (map.get_type(), map.get_map_id()))
-
-        # Load the data from the grass file database
-        map.load()
-
-        # Set the valid time
-        if start:
-            # In case the time is in the input file we ignore the increment counter
-            if start_time_in_file:
-                count = 1
-            assign_valid_time_to_map(ttype=map.get_temporal_type(),
-                                     map=map, start=start, end=end, unit=unit,
-                                     increment=increment, mult=count,
-                                     interval=interval)
-
-        if is_in_db:
-            #  Gather the SQL update statement
-            statement += map.update_all(dbif=dbif, execute=False)
-        else:
-            #  Gather the SQL insert statement
-            statement += map.insert(dbif=dbif, execute=False)
-
-        # Sqlite3 performace better for huge datasets when committing in small chunks
-        if dbif.dbmi.__name__ == "sqlite3":
-            if count % 100 == 0:
-                if statement is not None and statement != "":
-                    core.message(_("Registering maps in the temporal database")
-                                 )
-                    dbif.execute_transaction(statement)
-                    statement = ""
-
-        # Store the maps in a list to register in a space time dataset
-        if name:
-            map_object_list.append(map)
-
-    core.percent(num_maps, num_maps, 1)
-
-    if statement is not None and statement != "":
-        core.message(_("Register maps in the temporal database"))
-        dbif.execute_transaction(statement)
-
-    # Finally Register the maps in the space time dataset
-    if name and map_object_list:
-        statement = ""
-        count = 0
-        num_maps = len(map_object_list)
-        core.message(_("Register maps in the space time raster dataset"))
-        for map in map_object_list:
-            if count%50 == 0:
-                core.percent(count, num_maps, 1)
-            sp.register_map(map=map, dbif=dbif)
-            count += 1
-
-    # Update the space time tables
-    if name and map_object_list:
-        core.message(_("Update space time raster dataset"))
-        sp.update_from_registered_maps(dbif)
-        sp.update_command_string(dbif=dbif)
-    
-    # Update affected datasets
-    if datatsets_to_modify:
-        for dataset in datatsets_to_modify:
-            if type == "rast" or type == "raster":
-                ds = dataset_factory("strds", dataset)
-            elif type == "rast3d":
-                ds = dataset_factory("str3ds", dataset)
-            elif type == "vect" or type == "vector":
-                ds = dataset_factory("stvds", dataset)
-            ds.select(dbif)
-            ds.update_from_registered_maps(dbif)
-
-    if connected == True:
-        dbif.close()
-
-    core.percent(num_maps, num_maps, 1)
-
-
-###############################################################################
-
-def assign_valid_time_to_map(ttype, map, start, end, unit, increment=None, mult=1, interval=False):
-    """!Assign the valid time to a map dataset
-
-       @param ttype The temporal type which should be assigned
-                     and which the time format is of
-       @param map A map dataset object derived from abstract_map_dataset
-       @param start The start date and time of the first raster map
-                     (format absolute: "yyyy-mm-dd HH:MM:SS" or "yyyy-mm-dd",
-                     format relative is integer 5)
-       @param end The end date and time of the first raster map
-                   (format absolute: "yyyy-mm-dd HH:MM:SS" or "yyyy-mm-dd",
-                   format relative is integer 5)
-       @param unit The unit of the relative time: years, months,
-                    days, hours, minutes, seconds
-       @param increment Time increment between maps for time stamp creation
-                        (format absolute: NNN seconds, minutes, hours, days,
-                        weeks, months, years; format relative is integer 1)
-       @param multi A multiplier for the increment
-       @param interval If True, time intervals are created in case the start
-                        time and an increment is provided
-    """
-
-    if ttype == "absolute":
-        start_time = string_to_datetime(start)
-        if start_time is None:
-            core.fatal(_("Unable to convert string \"%s\"into a "
-                         "datetime object") % (start))
-        end_time = None
-
-        if end:
-            end_time = string_to_datetime(end)
-            if end_time is None:
-                dbif.close()
-                core.fatal(_("Unable to convert string \"%s\"into a "
-                             "datetime object") % (end))
-
-        # Add the increment
-        if increment:
-            start_time = increment_datetime_by_string(
-                start_time, increment, mult)
-            if start_time is None:
-                core.fatal(_("Error in increment computation"))
-            if interval:
-                end_time = increment_datetime_by_string(
-                    start_time, increment, 1)
-                if end_time is None:
-                    core.fatal(_("Error in increment computation"))
-        # Commented because of performance issue calling g.message thousend times
-        #if map.get_layer():
-        #    core.verbose(_("Set absolute valid time for map <%(id)s> with "
-        #                   "layer %(layer)s to %(start)s - %(end)s") %
-        #                 {'id': map.get_map_id(), 'layer': map.get_layer(),
-        #                  'start': str(start_time), 'end': 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.set_absolute_time(start_time, end_time, None)
-    else:
-        start_time = int(start)
-        end_time = None
-
-        if end:
-            end_time = int(end)
-
-        if increment:
-            start_time = start_time + mult * int(increment)
-            if interval:
-                end_time = start_time + int(increment)
-
-        # Commented because of performance issue calling g.message thousend times
-        #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.set_relative_time(start_time, end_time, unit)
-
-###############################################################################
-
-
-def dataset_factory(type, id):
-    """!A factory functions to create space time or map datasets
-
-       @param type the dataset type: rast or raster, rast3d,
-                    vect or vector, strds, str3ds, stvds
-       @param id The id of the dataset ("name@mapset")
-    """
-    if type == "strds":
-        sp = SpaceTimeRasterDataset(id)
-    elif type == "str3ds":
-        sp = SpaceTimeRaster3DDataset(id)
-    elif type == "stvds":
-        sp = SpaceTimeVectorDataset(id)
-    elif type == "rast" or type == "raster":
-        sp = RasterDataset(id)
-    elif type == "rast3d":
-        sp = Raster3DDataset(id)
-    elif type == "vect" or type == "vector":
-        sp = VectorDataset(id)
-    else:
-        core.error(_("Unknown dataset type: %s") % type)
-        return None
-
-    return sp
-
-###############################################################################
-
-
-def list_maps_of_stds(type, input, columns, order, where, separator, method, header, gran=None):
-    """! List the maps of a space time dataset using diffetent methods
-
-        @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 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@mapset) as comma separated string
-            - "delta" Print the map ids (name@mapset) with start time,
-                       end time, relative length of intervals and the relative
-                       distance to the begin
-            - "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
-        @param gran The user defined granule to be used if method=gran is set, in case gran=None the 
-            granule of the space time dataset is used
-    """
-    mapset = core.gisenv()["MAPSET"]
-
-    if input.find("@") >= 0:
-        id = input
-    else:
-        id = input + "@" + mapset
-
-    dbif, connected = init_dbif(None)
-    
-    sp = dataset_factory(type, id)
-
-    if not sp.is_in_db(dbif=dbif):
-        core.fatal(_("Dataset <%s> not found in temporal database") % (id))
-
-    sp.select(dbif=dbif)
-
-    if separator is None or separator == "":
-        separator = "\t"
-
-    # This method expects a list of objects for gap detection
-    if method == "delta" or method == "deltagaps" or method == "gran":
-        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=where, dbif=dbif)
-        elif method == "delta":
-            maps = sp.get_registered_maps_as_objects(where=where, order="start_time", dbif=dbif)
-        elif method == "gran":
-            if gran is not None and gran != "":
-                maps = sp.get_registered_maps_as_objects_by_granularity(gran=gran, dbif=dbif)
-            else:
-                maps = sp.get_registered_maps_as_objects_by_granularity(dbif=dbif)
-            
-        if header:
-            string = ""
-            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)
-            string += "%s" % ("distance_from_begin")
-            print string
-
-        if maps and len(maps) > 0:
-
-            if isinstance(maps[0], list):
-                if len(maps[0]) > 0:
-                    first_time, dummy = maps[0][0].get_valid_time()
-                else:
-                    core.warning(_("Empty map list."))
-                    return
-            else:
-                first_time, dummy = maps[0].get_valid_time()
-
-            for mymap in maps:
-
-                if isinstance(mymap, list):
-                    if len(mymap) > 0:
-                        map = mymap[0]
-                    else:
-                        core.fatal(_("Empty entry in map list, this should not happen."))
-                else:
-                    map = mymap
-
-                start, end = map.get_valid_time()
-                if end:
-                    delta = end - start
-                else:
-                    delta = None
-                delta_first = start - first_time
-
-                if map.is_time_absolute():
-                    if end:
-                        delta = time_delta_to_relative_time(delta)
-                    delta_first = time_delta_to_relative_time(delta_first)
-
-                string = ""
-                string += "%s%s" % (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)
-                string += "%s" % (delta_first)
-                print string
-
-    else:
-        # In comma separated mode only map ids are needed
-        if method == "comma":
-            columns = "id"
-
-        rows = sp.get_registered_maps(columns, where, order, dbif)
-
-        if rows:
-            if method == "comma":
-                string = ""
-                count = 0
-                for row in rows:
-                    if count == 0:
-                        string += row["id"]
-                    else:
-                        string += ",%s" % row["id"]
-                    count += 1
-                print string
-
-            elif method == "cols":
-                # Print the column names if requested
-                if header:
-                    output = ""
-                    count = 0
-
-                    collist = columns.split(",")
-
-                    for key in collist:
-                        if count > 0:
-                            output += separator + str(key)
-                        else:
-                            output += str(key)
-                        count += 1
-                    print output
-
-                for row in rows:
-                    output = ""
-                    count = 0
-                    for col in row:
-                        if count > 0:
-                            output += separator + str(col)
-                        else:
-                            output += str(col)
-                        count += 1
-
-                    print output
-    if connected:
-        dbif.close()
-###############################################################################
-
-
-def sample_stds_by_stds_topology(intype, sampletype, inputs, sampler, header, 
-                                 separator, method, spatial=False, 
-                                 print_only=True):
-    """!Sample the input space time datasets with a sample 
-       space time dataset, return the created map matrix and optionally 
-       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@mapset
-
-        Attention: Do not use the comma as separator for printing
-
-        @param intype  Type of the input space time dataset (strds, stvds or str3ds)
-        @param samtype Type of the sample space time dataset (strds, stvds or str3ds)
-        @param inputs Name or comma separated names of space time datasets
-        @param sampler Name of a space time dataset used for temporal sampling
-        @param header Set True to print column names
-        @param separator The field separator character between the columns
-        @param method The method to be used for temporal sampling 
-                       (start,during,contain,overlap,equal)
-        @param spatial Perform spatial overlapping check
-        @param print_only If set True (default) then the result of the sampling will be 
-                    printed to stdout, if set to False the resulting map matrix 
-                    will be returned. 
-                    
-        @return The map matrix or None if nothing found
-    """
-    mapset = core.gisenv()["MAPSET"]
-
-    # Make a method list
-    method = method.split(",")
-
-    # Split the inputs
-    input_list = inputs.split(",")
-    sts = []
-
-    for input in input_list:
-        if input.find("@") >= 0:
-            id = input
-        else:
-            id = input + "@" + mapset
-
-        st = dataset_factory(intype, id)
-        sts.append(st)
-
-    if sampler.find("@") >= 0:
-        sid = sampler
-    else:
-        sid = sampler + "@" + mapset
-
-    sst = dataset_factory(sampletype, sid)
-
-    dbif = SQLDatabaseInterfaceConnection()
-    dbif.connect()
-
-    for st in sts:
-        if st.is_in_db(dbif) == False:
-            core.fatal(_("Dataset <%s> not found in temporal database") % (st.get_id()))
-        st.select(dbif)
-
-    if sst.is_in_db(dbif) == False:
-        core.fatal(_("Dataset <%s> not found in temporal database") % (sid))
-
-    sst.select(dbif)
-
-    if separator is None or separator == "" or separator.find(",") >= 0:
-        separator = " | "
-
-    mapmatrizes = []
-    for st in sts:
-        mapmatrix = st.sample_by_dataset(sst, method, spatial, dbif)
-        if mapmatrix and len(mapmatrix) > 0:
-            mapmatrizes.append(mapmatrix)
-
-    if len(mapmatrizes) > 0:
-        
-        # Simply return the map matrix
-        if not print_only:
-            dbif.close()
-            return mapmatrizes
-
-        if header:
-            string = ""
-            string += "%s%s" % (sst.get_id(), separator)
-            for st in sts:
-                string += "%s%s" % (st.get_id(), separator)
-            string += "%s%s" % ("start_time", separator)
-            string += "%s%s" % ("end_time", separator)
-            string += "%s%s" % ("interval_length", separator)
-            string += "%s" % ("distance_from_begin")
-            print string
-
-        first_time, dummy = mapmatrizes[0][0]["granule"].get_valid_time()
-
-        for i in range(len(mapmatrizes[0])):
-            mapname_list = []
-            for mapmatrix in mapmatrizes:
-                mapnames = ""
-                count = 0
-                entry = mapmatrix[i]
-                for sample in entry["samples"]:
-                    if count == 0:
-                        mapnames += str(sample.get_id())
-                    else:
-                        mapnames += ",%s" % str(sample.get_id())
-                    count += 1
-                mapname_list.append(mapnames)
-
-            entry = mapmatrizes[0][i]
-            map = entry["granule"]
-
-            start, end = map.get_valid_time()
-            if end:
-                delta = end - start
-            else:
-                delta = None
-            delta_first = start - first_time
-
-            if map.is_time_absolute():
-                if end:
-                    delta = time_delta_to_relative_time(delta)
-                delta_first = time_delta_to_relative_time(delta_first)
-
-            string = ""
-            string += "%s%s" % (map.get_id(), separator)
-            for mapnames in mapname_list:
-                string += "%s%s" % (mapnames, separator)
-            string += "%s%s" % (start, separator)
-            string += "%s%s" % (end, separator)
-            string += "%s%s" % (delta, separator)
-            string += "%s" % (delta_first)
-            print string
-
-    dbif.close()
-    if len(mapmatrizes) > 0:
-        return mapmatrizes
-    
-    return None
-
-###############################################################################
-
-def tlist_grouped(type, group_type = False):
-    """!List of temporal elements grouped by mapsets.
-
-    Returns a dictionary where the keys are mapset 
-    names and the values are lists of space time datasets in that
-    mapset. Example:
-
-    @code
-    >>> tgis.tlist_grouped('strds')['PERMANENT']
-    ['precipitation', 'temperature']
-    @endcode
-    
-    @param type element type (strds, str3ds, stvds)
-
-    @return directory of mapsets/elements
-    """
-    result = {}
-    
-    mapset = None
-    if type == 'stds':
-        types = ['strds', 'str3ds', 'stvds']
-    else:
-        types = [type]
-    for type in types:
-        try:
-            tlist_result = tlist(type)
-        except core.ScriptError, e:
-            warning(e)
-            continue
-
-        for line in tlist_result:
-            try:
-                name, mapset = line.split('@')
-            except ValueError:
-                warning(_("Invalid element '%s'") % line)
-                continue
-
-            if mapset not in result:
-                if group_type:
-                    result[mapset] = {}
-                else:
-                    result[mapset] = []
-
-            if group_type:
-                if type in result[mapset]:
-                    result[mapset][type].append(name)
-                else:        
-                    result[mapset][type] = [name, ]
-            else:
-                result[mapset].append(name)
-
-    return result
-
-###############################################################################
-
-def tlist(type):
-    """!Return a list of space time datasets of absolute and relative time
-     
-    @param type element type (strds, str3ds, stvds)
-
-    @return a list of space time dataset ids
-    """
-    id = None
-    sp = dataset_factory(type, id)
-
-    dbif = SQLDatabaseInterfaceConnection()
-    dbif.connect()
-
-    output = []
-    temporal_type = ["absolute", 'relative']
-    for type in temporal_type:
-        # Table name
-        if type == "absolute":
-            table = sp.get_type() + "_view_abs_time"
-        else:
-            table = sp.get_type() + "_view_rel_time"
-
-        # Create the sql selection statement
-        sql = "SELECT id FROM " + table
-        sql += " ORDER BY id"
-
-        dbif.cursor.execute(sql)
-        rows = dbif.cursor.fetchall()
-
-        # Append the ids of the space time datasets
-        for row in rows:
-            for col in row:
-                output.append(str(col))
-    dbif.close()
-
-    return output
-
-###############################################################################
-
-def create_space_time_dataset(name, type, temporaltype, title, descr, semantic,
-                              dbif=None, overwrite=False):
-    """!Create a new space time dataset
-    
-       This function is sensitive to the settings in grass.core.overwrite to
-       overwrute existing space time datasets.
-    
-       @param name The name of the new space time dataset
-       @param type The type (strds, stvds, str3ds) of the new space time dataset
-       @param temporaltype The temporal type (relative or absolute)
-       @param title The title
-       @param descr The dataset description
-       @param semantic Semantical information
-       @param dbif The temporal database interface to be used
-       
-       @return The new created space time dataset
-       
-       This function will raise a ScriptError in case of an error.
-    """
-    
-    #Get the current mapset to create the id of the space time dataset
-
-    mapset = core.gisenv()["MAPSET"]
-    id = name + "@" + mapset
-    
-    print id
-    print overwrite
-
-    sp = dataset_factory(type, id)
-
-    dbif, connected = init_dbif(dbif)
-
-    if sp.is_in_db(dbif) and overwrite == False:
-        if connected:
-            dbif.close()
-        core.fatal(_("Space time %s dataset <%s> is already in the database. "
-                      "Use the overwrite flag.") %
-                    (sp.get_new_map_instance(None).get_type(), name))
-        return None
-
-    if sp.is_in_db(dbif) and overwrite == True:
-        core.warning(_("Overwrite space time %s dataset <%s> "
-                     "and unregister all maps.") %
-                   (sp.get_new_map_instance(None).get_type(), name))
-        sp.delete(dbif)
-        sp = sp.get_new_instance(id)
-
-    core.verbose(_("Create new space time %s dataset.") %
-                  sp.get_new_map_instance(None).get_type())
-
-    sp.set_initial_values(temporal_type=temporaltype, semantic_type=semantic,
-                          title=title, description=descr)
-    sp.insert(dbif)
-
-    if connected:
-        dbif.close()
-        
-    return sp

+ 1 - 1
lib/python/temporal/stds_import.py

@@ -157,7 +157,7 @@ def import_stds(
         @param output The name of the output space time dataset
         @param output The name of the output space time dataset
         @param extrdir The extraction directory
         @param extrdir The extraction directory
         @param title The title of the new created space time dataset
         @param title The title of the new created space time dataset
-        @param description The description of the new created 
+        @param descr The description of the new created 
                             space time dataset
                             space time dataset
         @param location The name of the location that should be created,
         @param location The name of the location that should be created,
                         maps are imported into this location
                         maps are imported into this location