Explorar o código

temporal framework: Backport of all modifications of the temporal framework from trunk to enable mapset specific temporal databases. This backport includes the new temporal algebra.

git-svn-id: https://svn.osgeo.org/grass/grass/branches/releasebranch_7_0@62864 15284696-431f-4ddb-bdfa-cd5b030d7da7
Soeren Gebbert %!s(int64=10) %!d(string=hai) anos
pai
achega
99a1c301eb
Modificáronse 50 ficheiros con 13641 adicións e 11014 borrados
  1. 1 1
      lib/python/temporal/Makefile
  2. 6 7
      lib/python/temporal/__init__.py
  3. 189 172
      lib/python/temporal/abstract_dataset.py
  4. 373 350
      lib/python/temporal/abstract_map_dataset.py
  5. 606 574
      lib/python/temporal/abstract_space_time_dataset.py
  6. 173 35
      lib/python/temporal/aggregation.py
  7. 340 321
      lib/python/temporal/base.py
  8. 482 289
      lib/python/temporal/c_libraries_interface.py
  9. 563 259
      lib/python/temporal/core.py
  10. 368 336
      lib/python/temporal/datetime_math.py
  11. 37 38
      lib/python/temporal/extract.py
  12. 10 15
      lib/python/temporal/factory.py
  13. 45 41
      lib/python/temporal/gui_support.py
  14. 92 79
      lib/python/temporal/list_stds.py
  15. 77 78
      lib/python/temporal/mapcalc.py
  16. 671 678
      lib/python/temporal/metadata.py
  17. 69 66
      lib/python/temporal/open_stds.py
  18. 137 78
      lib/python/temporal/register.py
  19. 30 30
      lib/python/temporal/sampling.py
  20. 470 463
      lib/python/temporal/space_time_datasets.py
  21. 617 631
      lib/python/temporal/spatial_extent.py
  22. 141 148
      lib/python/temporal/spatial_topology_dataset_connector.py
  23. 531 512
      lib/python/temporal/spatio_temporal_relationships.py
  24. 55 51
      lib/python/temporal/stds_export.py
  25. 88 85
      lib/python/temporal/stds_import.py
  26. 1216 798
      lib/python/temporal/temporal_algebra.py
  27. 667 661
      lib/python/temporal/temporal_extent.py
  28. 499 226
      lib/python/temporal/temporal_granularity.py
  29. 615 0
      lib/python/temporal/temporal_operator.py
  30. 16 20
      lib/python/temporal/temporal_raster3d_algebra.py
  31. 17 22
      lib/python/temporal/temporal_raster_algebra.py
  32. 800 1845
      lib/python/temporal/temporal_raster_base_algebra.py
  33. 0 390
      lib/python/temporal/temporal_raster_operator.py
  34. 211 221
      lib/python/temporal/temporal_topology_dataset_connector.py
  35. 298 615
      lib/python/temporal/temporal_vector_algebra.py
  36. 0 349
      lib/python/temporal/temporal_vector_operator.py
  37. 50 0
      lib/python/temporal/testsuite/test_doctests.py
  38. 302 0
      lib/python/temporal/testsuite/test_register_function.py
  39. 13 20
      lib/python/temporal/unittests_register.py
  40. 354 0
      lib/python/temporal/testsuite/unittests_temporal_algebra.py
  41. 228 0
      lib/python/temporal/testsuite/unittests_temporal_algebra_grs.py
  42. 356 0
      lib/python/temporal/testsuite/unittests_temporal_conditionals.py
  43. 27 28
      lib/python/temporal/unittests_temporal_raster3d_algebra.py
  44. 711 0
      lib/python/temporal/testsuite/unittests_temporal_raster_algebra.py
  45. 277 0
      lib/python/temporal/testsuite/unittests_temporal_raster_algebra_grs.py
  46. 498 0
      lib/python/temporal/testsuite/unittests_temporal_raster_conditionals.py
  47. 209 0
      lib/python/temporal/testsuite/unittests_temporal_vector_algebra.py
  48. 46 49
      lib/python/temporal/unit_tests.py
  49. 0 374
      lib/python/temporal/unittests_temporal_raster_algebra.py
  50. 60 59
      lib/python/temporal/univar_statistics.py

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1 - 1
lib/python/temporal/Makefile


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

@@ -1,17 +1,12 @@
 from core import *
 from base import *
-from temporal_extent import *
 from spatial_extent import *
 from metadata import *
-from temporal_topology_dataset_connector import *
-from spatial_topology_dataset_connector import *
 from abstract_dataset import *
 from abstract_map_dataset import *
 from abstract_space_time_dataset import *
 from space_time_datasets import *
 from datetime_math import *
-from temporal_granularity import *
-from spatio_temporal_relationships import *
 from open_stds import *
 from factory import *
 from gui_support import *
@@ -25,10 +20,14 @@ from stds_import import *
 from mapcalc import *
 from univar_statistics import *
 from c_libraries_interface import *
+from spatio_temporal_relationships import *
+from spatial_topology_dataset_connector import *
+from temporal_extent import *
+from temporal_topology_dataset_connector import *
+from temporal_granularity import *
 from temporal_algebra import *
 from temporal_vector_algebra import *
-from temporal_vector_operator import *
-from temporal_raster_operator import *
 from temporal_raster_base_algebra import *
 from temporal_raster_algebra import *
 from temporal_raster3d_algebra import *
+from temporal_operator import *

+ 189 - 172
lib/python/temporal/abstract_dataset.py

@@ -1,20 +1,15 @@
 # -*- coding: utf-8 -*-
-"""!@package grass.temporal
-
-@brief GRASS Python scripting module (temporal GIS functions)
-
-Temporal GIS related functions to be used in temporal GIS Python library package.
-
+"""
+The abstract_dataset module provides the AbstractDataset class
+that is the base class for all map layer and Space Time Datasets.
 
 (C) 2011-2013 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
+:authors: Soeren Gebbert
 """
-import uuid
-import copy
 from abc import ABCMeta, abstractmethod
 from temporal_extent import *
 from spatial_extent import *
@@ -22,12 +17,12 @@ from metadata import *
 from temporal_topology_dataset_connector import *
 from spatial_topology_dataset_connector import *
 
-from grass.exceptions import ImplementationError
-
 ###############################################################################
 
-class AbstractDataset(SpatialTopologyDatasetConnector, TemporalTopologyDatasetConnector):
-    """!This is the base class for all datasets
+
+class AbstractDataset(SpatialTopologyDatasetConnector,
+                      TemporalTopologyDatasetConnector):
+    """This is the base class for all datasets
        (raster, vector, raster3d, strds, stvds, str3ds)"""
 
     __metaclass__ = ABCMeta
@@ -38,68 +33,72 @@ class AbstractDataset(SpatialTopologyDatasetConnector, TemporalTopologyDatasetCo
         self.msgr = get_tgis_message_interface()
 
     def reset_topology(self):
-        """!Reset any information about temporal topology"""
+        """Reset any information about temporal topology"""
+
         self.reset_spatial_topology()
         self.reset_temporal_topology()
 
     def get_number_of_relations(self):
-        """! Return a dictionary in which the keys are the relation names and the value
-        are the number of relations.
+        """Return a dictionary in which the keys are the relation names and the
+        value are the number of relations.
 
         The following relations are available:
 
-        Spatial relations
-        - equivalent
-        - overlap
-        - in
-        - contain
-        - meet
-        - cover
-        - covered
-
-        Temporal relations
-        - equal
-        - follows
-        - precedes
-        - overlaps
-        - overlapped
-        - during (including starts, finishes)
-        - contains (including started, finished)
-        - starts
-        - started
-        - finishes
-        - finished
-
-        To access topological information the spatial, temporal or booth topologies must be build first
-        using the SpatioTemporalTopologyBuilder.
-
-        @return the dictionary with relations as keys and number as values or None in case the topology  wasn't build
+        Spatial relations:
+
+            - equivalent
+            - overlap
+            - in
+            - contain
+            - meet
+            - cover
+            - covered
+
+        Temporal relations:
+
+            - equal
+            - follows
+            - precedes
+            - overlaps
+            - overlapped
+            - during (including starts, finishes)
+            - contains (including started, finished)
+            - starts
+            - started
+            - finishes
+            - finished
+
+        To access topological information the spatial, temporal or booth
+        topologies must be build first using the SpatioTemporalTopologyBuilder.
+
+        :return: The dictionary with relations as keys and number as values or
+                 None in case the topology  wasn't build
         """
         if self.is_temporal_topology_build() and not self.is_spatial_topology_build():
             return self.get_number_of_temporal_relations()
         elif self.is_spatial_topology_build() and not self.is_temporal_topology_build():
             self.get_number_of_spatial_relations()
         else:
-            return  self.get_number_of_temporal_relations() + \
-                    self.get_number_of_spatial_relations()
+            return self.get_number_of_temporal_relations() + \
+                   self.get_number_of_spatial_relations()
 
         return None
 
     def set_topology_build_true(self):
-        """!Use this method when the spatio-temporal topology was build"""
+        """Use this method when the spatio-temporal topology was build"""
         self.set_spatial_topology_build_true()
         self.set_temporal_topology_build_true()
 
-
     def set_topology_build_false(self):
-        """!Use this method when the spatio-temporal topology was not build"""
+        """Use this method when the spatio-temporal topology was not build"""
         self.set_spatial_topology_build_false()
         self.set_temporal_topology_build_false()
 
     def is_topology_build(self):
-        """!Check if the spatial and temporal topology was build
+        """Check if the spatial and temporal topology was build
 
-           @return A dictionary with "spatial" and "temporal" as keys that have boolen values
+           :return: A dictionary with "spatial" and "temporal" as keys that
+                    have boolen values
         """
         d = {}
         d["spatial"] = self.is_spatial_topology_build()
@@ -107,7 +106,6 @@ class AbstractDataset(SpatialTopologyDatasetConnector, TemporalTopologyDatasetCo
 
         return d
 
-
     def print_topology_info(self):
         if self.is_temporal_topology_build():
             self.print_temporal_topology_info()
@@ -122,7 +120,7 @@ class AbstractDataset(SpatialTopologyDatasetConnector, TemporalTopologyDatasetCo
 
     @abstractmethod
     def reset(self, ident):
-        """!Reset the internal structure and set the identifier
+        """Reset the internal structure and set the identifier
 
             This method creates the dataset specific internal objects
             that store the base information, the spatial and temporal extent
@@ -130,95 +128,99 @@ class AbstractDataset(SpatialTopologyDatasetConnector, TemporalTopologyDatasetCo
             specific subclasses. This is the code for the
             vector dataset:
 
-            self.base = VectorBase(ident=ident)
-            self.absolute_time = VectorAbsoluteTime(ident=ident)
-            self.relative_time = VectorRelativeTime(ident=ident)
-            self.spatial_extent = VectorSpatialExtent(ident=ident)
-            self.metadata = VectorMetadata(ident=ident)
+            .. code-block:: python
+
+                self.base = VectorBase(ident=ident)
+                self.absolute_time = VectorAbsoluteTime(ident=ident)
+                self.relative_time = VectorRelativeTime(ident=ident)
+                self.spatial_extent = VectorSpatialExtent(ident=ident)
+                self.metadata = VectorMetadata(ident=ident)
 
-           @param ident The identifier of the dataset that  "name@mapset" or in case of vector maps "name:layer@mapset"
+           :param ident: The identifier of the dataset that  "name@mapset" or
+                         in case of vector maps "name:layer@mapset"
         """
 
     @abstractmethod
     def is_stds(self):
-        """!Return True if this class is a space time dataset
+        """Return True if this class is a space time dataset
 
-           @return True if this class is a space time dataset, False otherwise
+           :return: True if this class is a space time dataset, False otherwise
         """
 
     @abstractmethod
     def get_type(self):
-        """!Return the type of this class as string
+        """Return the type of this class as string
 
-           The type can be "vect", "rast", "rast3d", "stvds", "strds" or "str3ds"
+           The type can be "vector", "raster", "raster3d", "stvds", "strds" or "str3ds"
 
-           @return "vect", "rast", "rast3d", "stvds", "strds" or "str3ds"
+           :return: "vector", "raster", "raster3d", "stvds", "strds" or "str3ds"
         """
 
     @abstractmethod
     def get_new_instance(self, ident):
-        """!Return a new instance with the type of this class
+        """Return a new instance with the type of this class
 
-           @param ident The identifier of the new dataset instance
-           @return A new instance with the type of this object
+           :param ident: The identifier of the new dataset instance
+           :return: A new instance with the type of this object
         """
 
     @abstractmethod
     def spatial_overlapping(self, dataset):
-        """!Return True if the spatial extents overlap
+        """Return True if the spatial extents overlap
 
-           @param dataset The abstract dataset to check spatial overlapping
-           @return True if self and the provided dataset spatial overlap
+           :param dataset: The abstract dataset to check spatial overlapping
+           :return: True if self and the provided dataset spatial overlap
         """
 
     @abstractmethod
     def spatial_intersection(self, dataset):
-        """!Return the spatial intersection as spatial_extent
+        """Return the spatial intersection as spatial_extent
            object or None in case no intersection was found.
 
-           @param dataset The abstract dataset to intersect with
-           @return The intersection spatial extent
+           :param dataset: The abstract dataset to intersect with
+           :return: The intersection spatial extent
         """
 
     @abstractmethod
     def spatial_union(self, dataset):
-        """!Return the spatial union as spatial_extent
+        """Return the spatial union as spatial_extent
            object or None in case the extents does not overlap or meet.
 
-           @param dataset The abstract dataset to create a union with
-           @return The union spatial extent
+           :param dataset: The abstract dataset to create a union with
+           :return: The union spatial extent
         """
 
     @abstractmethod
     def spatial_disjoint_union(self, dataset):
-        """!Return the spatial union as spatial_extent object.
+        """Return the spatial union as spatial_extent object.
 
-           @param dataset The abstract dataset to create a union with
-           @return The union spatial extent
+           :param dataset: The abstract dataset to create a union with
+           :return: The union spatial extent
         """
 
     @abstractmethod
     def spatial_relation(self, dataset):
-        """!Return the spatial relationship between self and dataset
+        """Return the spatial relationship between self and dataset
 
-           @param dataset The abstract dataset to compute the spatial relation with self
-           @return The spatial relationship as string
+           :param dataset: The abstract dataset to compute the spatial
+                           relation with self
+           :return: The spatial relationship as string
         """
 
     @abstractmethod
     def print_info(self):
-        """!Print information about this class in human readable style"""
+        """Print information about this class in human readable style"""
 
     @abstractmethod
     def print_shell_info(self):
-        """!Print information about this class in shell style"""
+        """Print information about this class in shell style"""
 
     @abstractmethod
     def print_self(self):
-        """!Print the content of the internal structure to stdout"""
+        """Print the content of the internal structure to stdout"""
 
     def set_id(self, ident):
-        """!Set the identifier of the dataset"""
+        """Set the identifier of the dataset"""
         self.base.set_id(ident)
         self.temporal_extent.set_id(ident)
         self.spatial_extent.set_id(ident)
@@ -227,37 +229,37 @@ class AbstractDataset(SpatialTopologyDatasetConnector, TemporalTopologyDatasetCo
             self.stds_register.set_id(ident)
 
     def get_id(self):
-        """!Return the unique identifier of the dataset
-           @return The id of the dataset "name(:layer)@mapset" as string
+        """Return the unique identifier of the dataset
+           :return: The id of the dataset "name(:layer)@mapset" as string
         """
         return self.base.get_id()
 
     def get_name(self):
-        """!Return the name
-           @return The name of the dataset as string
+        """Return the name
+           :return: The name of the dataset as string
         """
         return self.base.get_name()
 
     def get_mapset(self):
-        """!Return the mapset
-           @return The mapset in which the dataset was created as string
+        """Return the mapset
+           :return: The mapset in which the dataset was created as string
         """
         return self.base.get_mapset()
 
     def get_temporal_extent_as_tuple(self):
-        """!Returns a tuple of the valid start and end time
+        """Returns a tuple of the valid start and end time
 
-           Start and end time can be either of type datetime or of type integer,
-           depending on the temporal type.
+           Start and end time can be either of type datetime or of type
+           integer, depending on the temporal type.
 
-           @return A tuple of (start_time, end_time)
+           :return: A tuple of (start_time, end_time)
         """
         start = self.temporal_extent.get_start_time()
         end = self.temporal_extent.get_end_time()
         return (start, end)
 
     def get_absolute_time(self):
-        """!Returns the start time, the end
+        """Returns the start time, the end
            time of the map as tuple
 
            The start time is of type datetime.
@@ -265,7 +267,7 @@ class AbstractDataset(SpatialTopologyDatasetConnector, TemporalTopologyDatasetCo
            The end time is of type datetime in case of interval time,
            or None on case of a time instance.
 
-           @return A tuple of (start_time, end_time)
+           :return: A tuple of (start_time, end_time)
         """
 
         start = self.absolute_time.get_start_time()
@@ -274,7 +276,7 @@ class AbstractDataset(SpatialTopologyDatasetConnector, TemporalTopologyDatasetCo
         return (start, end)
 
     def get_relative_time(self):
-        """!Returns the start time, the end
+        """Returns the start time, the end
            time and the temporal unit of the dataset as tuple
 
            The start time is of type integer.
@@ -282,7 +284,7 @@ class AbstractDataset(SpatialTopologyDatasetConnector, TemporalTopologyDatasetCo
            The end time is of type integer in case of interval time,
            or None on case of a time instance.
 
-           @return A tuple of (start_time, end_time, unit)
+           :return: A tuple of (start_time, end_time, unit)
         """
 
         start = self.relative_time.get_start_time()
@@ -292,17 +294,17 @@ class AbstractDataset(SpatialTopologyDatasetConnector, TemporalTopologyDatasetCo
         return (start, end, unit)
 
     def get_relative_time_unit(self):
-        """!Returns the relative time unit
-           @return The relative time unit as string, None if not present
+        """Returns the relative time unit
+           :return: The relative time unit as string, None if not present
         """
         return self.relative_time.get_unit()
 
     def check_relative_time_unit(self, unit):
-        """!Check if unit is of type  year(s), month(s), day(s), hour(s),
+        """Check if unit is of type  year(s), month(s), day(s), hour(s),
            minute(s) or second(s)
 
-           @param unit The unit string
-           @return True if success, False otherwise
+           :param unit: The unit string
+           :return: True if success, False otherwise
         """
         # Check unit
         units = ["year", "years", "month", "months", "day", "days", "hour",
@@ -312,37 +314,39 @@ class AbstractDataset(SpatialTopologyDatasetConnector, TemporalTopologyDatasetCo
         return True
 
     def get_temporal_type(self):
-        """!Return the temporal type of this dataset
+        """Return the temporal type of this dataset
 
            The temporal type can be absolute or relative
 
-           @return The temporal type of the dataset as string
+           :return: The temporal type of the dataset as string
         """
         return self.base.get_ttype()
 
     def get_spatial_extent_as_tuple(self):
-        """!Return the spatial extent as tuple
+        """Return the spatial extent as tuple
 
-           Top and bottom are set to 0 in case of a two dimensional spatial extent.
+           Top and bottom are set to 0 in case of a two dimensional spatial
+           extent.
 
-           @return A the spatial extent as tuple (north, south, east, west, top, bottom)
+           :return: A the spatial extent as tuple (north, south, east, west,
+                    top, bottom)
         """
         return self.spatial_extent.get_spatial_extent_as_tuple()
 
     def get_spatial_extent(self):
-        """!Return the spatial extent
+        """Return the spatial extent
         """
         return self.spatial_extent
 
     def select(self, dbif=None):
-        """!Select temporal dataset entry from database and fill
+        """Select temporal dataset entry from database and fill
            the internal structure
 
            The content of every dataset is stored in the temporal database.
            This method must be used to fill this object with the content
            from the temporal database.
 
-           @param dbif The database interface to be used
+           :param dbif: The database interface to be used
         """
 
         dbif, connected = init_dbif(dbif)
@@ -358,31 +362,34 @@ class AbstractDataset(SpatialTopologyDatasetConnector, TemporalTopologyDatasetCo
             dbif.close()
 
     def is_in_db(self, dbif=None):
-        """!Check if the dataset is registered in the database
+        """Check if the dataset is registered in the database
 
-           @param dbif The database interface to be used
-           @return True if the dataset is registered in the database
+           :param dbif: The database interface to be used
+           :return: True if the dataset is registered in the database
         """
         return self.base.is_in_db(dbif)
 
     @abstractmethod
     def delete(self):
-        """!Delete dataset from database if it exists"""
+        """Delete dataset from database if it exists"""
 
     def insert(self, dbif=None, execute=True):
-        """!Insert dataset into database
+        """Insert dataset into database
 
-           @param dbif The database interface to be used
-           @param execute If True the SQL statements will be executed.
+           :param dbif: The database interface to be used
+           :param execute: If True the SQL statements will be executed.
                            If False the prepared SQL statements are returned
                            and must be executed by the caller.
-            @return The SQL insert statement in case execute=False, or an empty string otherwise
+           :return: The SQL insert statement in case execute=False, or an
+                    empty string otherwise
         """
 
         if get_enable_mapset_check() is True and self.get_mapset() != get_current_mapset():
-            self.msgr.fatal(_("Unable to insert dataset <%(ds)s> of type %(type)s in the temporal database."
-                         " The mapset of the dataset does not match the current mapset")%\
-                         {"ds":self.get_id(), "type":self.get_type()})
+            self.msgr.fatal(_("Unable to insert dataset <%(ds)s> of type "
+                              "%(type)s in the temporal database. The mapset "
+                              "of the dataset does not match the current "
+                              "mapset") % {"ds": self.get_id(),
+                                           "type": self.get_type()})
 
         dbif, connected = init_dbif(dbif)
 
@@ -405,22 +412,24 @@ class AbstractDataset(SpatialTopologyDatasetConnector, TemporalTopologyDatasetCo
         return statement
 
     def update(self, dbif=None, execute=True, ident=None):
-        """!Update the dataset entry in the database from the internal structure
+        """Update the dataset entry in the database from the internal structure
            excluding None variables
 
-           @param dbif The database interface to be used
-           @param execute If True the SQL statements will be executed.
+           :param dbif: The database interface to be used
+           :param execute: If True the SQL statements will be executed.
                            If False the prepared SQL statements are returned
                            and must be executed by the caller.
-           @param ident The identifier to be updated, useful for renaming
-           @return The SQL update statement in case execute=False, or an empty string otherwise
+           :param ident: The identifier to be updated, useful for renaming
+           :return: The SQL update statement in case execute=False, or an
+                    empty string otherwise
         """
 
         if get_enable_mapset_check() is True and self.get_mapset() != get_current_mapset():
-            self.msgr.fatal(_("Unable to update dataset <%(ds)s> of type %(type)s in the temporal database."
-                         " The mapset of the dataset does not match the current mapset")%\
-                                 {"ds":self.get_id(), "type":self.get_type()})
-
+            self.msgr.fatal(_("Unable to update dataset <%(ds)s> of type "
+                              "%(type)s in the temporal database. The mapset "
+                              "of the dataset does not match the current "
+                              "mapset") % {"ds": self.get_id(),
+                                           "type": self.get_type()})
 
         dbif, connected = init_dbif(dbif)
 
@@ -446,21 +455,24 @@ class AbstractDataset(SpatialTopologyDatasetConnector, TemporalTopologyDatasetCo
         return statement
 
     def update_all(self, dbif=None, execute=True, ident=None):
-        """!Update the dataset entry in the database from the internal structure
+        """Update the dataset entry in the database from the internal structure
            and include None variables.
 
-           @param dbif The database interface to be used
-           @param execute If True the SQL statements will be executed.
+           :param dbif: The database interface to be used
+           :param execute: If True the SQL statements will be executed.
                            If False the prepared SQL statements are returned
                            and must be executed by the caller.
-           @param ident The identifier to be updated, useful for renaming
-           @return The SQL update statement in case execute=False, or an empty string otherwise
+           :param ident: The identifier to be updated, useful for renaming
+           :return: The SQL update statement in case execute=False, or an
+                    empty string otherwise
         """
 
         if get_enable_mapset_check() is True and self.get_mapset() != get_current_mapset():
-            self.msgr.fatal(_("Unable to update dataset <%(ds)s> of type %(type)s in the temporal database."
-                         " The mapset of the dataset does not match the current mapset")%\
-                         {"ds":self.get_id(), "type":self.get_type()})
+            self.msgr.fatal(_("Unable to update dataset <%(ds)s> of type "
+                              "%(type)s in the temporal database. The mapset"
+                              " of the dataset does not match the current "
+                              "mapset") % {"ds": self.get_id(),
+                                           "type": self.get_type()})
 
         dbif, connected = init_dbif(dbif)
 
@@ -468,9 +480,10 @@ class AbstractDataset(SpatialTopologyDatasetConnector, TemporalTopologyDatasetCo
         statement = self.base.get_update_all_statement_mogrified(dbif, ident)
         statement += self.temporal_extent.get_update_all_statement_mogrified(dbif,
                                                                              ident)
-        statement += self.spatial_extent.get_update_all_statement_mogrified(
-            dbif, ident)
-        statement += self.metadata.get_update_all_statement_mogrified(dbif, ident)
+        statement += self.spatial_extent.get_update_all_statement_mogrified(dbif,
+                                                                            ident)
+        statement += self.metadata.get_update_all_statement_mogrified(dbif,
+                                                                      ident)
 
         if self.is_stds() is False:
             statement += self.stds_register.get_update_all_statement_mogrified(dbif, ident)
@@ -486,9 +499,9 @@ class AbstractDataset(SpatialTopologyDatasetConnector, TemporalTopologyDatasetCo
         return statement
 
     def is_time_absolute(self):
-        """!Return True in case the temporal type is absolute
+        """Return True in case the temporal type is absolute
 
-            @return True if temporal type is absolute, False otherwise
+           :return: True if temporal type is absolute, False otherwise
         """
         if "temporal_type" in self.base.D:
             return self.base.get_ttype() == "absolute"
@@ -496,9 +509,9 @@ class AbstractDataset(SpatialTopologyDatasetConnector, TemporalTopologyDatasetCo
             return None
 
     def is_time_relative(self):
-        """!Return True in case the temporal type is relative
+        """Return True in case the temporal type is relative
 
-            @return True if temporal type is relative, False otherwise
+           :return: True if temporal type is relative, False otherwise
         """
         if "temporal_type" in self.base.D:
             return self.base.get_ttype() == "relative"
@@ -506,7 +519,7 @@ class AbstractDataset(SpatialTopologyDatasetConnector, TemporalTopologyDatasetCo
             return None
 
     def get_temporal_extent(self):
-        """!Return the temporal extent of the correct internal type
+        """Return the temporal extent of the correct internal type
         """
         if self.is_time_absolute():
             return self.absolute_time
@@ -517,55 +530,57 @@ class AbstractDataset(SpatialTopologyDatasetConnector, TemporalTopologyDatasetCo
     temporal_extent = property(fget=get_temporal_extent)
 
     def temporal_relation(self, dataset):
-        """!Return the temporal relation of self and the provided dataset
+        """Return the temporal relation of self and the provided dataset
 
-            @return The temporal relation as string
+           :return: The temporal relation as string
         """
         return self.temporal_extent.temporal_relation(dataset.temporal_extent)
 
     def temporal_intersection(self, dataset):
-        """!Intersect self with the provided dataset and
+        """Intersect self with the provided dataset and
            return a new temporal extent with the new start and end time
 
-           @param dataset The abstract dataset to temporal intersect with
-           @return The new temporal extent with start and end time,
-                   or None in case of no intersection
+           :param dataset: The abstract dataset to temporal intersect with
+           :return: The new temporal extent with start and end time,
+                    or None in case of no intersection
         """
         return self.temporal_extent.intersect(dataset.temporal_extent)
 
     def temporal_union(self, dataset):
-        """!Creates a union with the provided dataset and
+        """Creates a union with the provided dataset and
            return a new temporal extent with the new start and end time.
 
-           @param dataset The abstract dataset to create temporal union with
-           @return The new temporal extent with start and end time,
-                   or None in case of no intersection
+           :param dataset: The abstract dataset to create temporal union with
+           :return: The new temporal extent with start and end time,
+                    or None in case of no intersection
         """
         return self.temporal_extent.union(dataset.temporal_extent)
 
     def temporal_disjoint_union(self, dataset):
-        """!Creates a union with the provided dataset and
+        """Creates a union with the provided dataset and
            return a new temporal extent with the new start and end time.
 
-           @param dataset The abstract dataset to create temporal union with
-           @return The new temporal extent with start and end time
+           :param dataset: The abstract dataset to create temporal union with
+           :return: The new temporal extent with start and end time
         """
         return self.temporal_extent.disjoint_union(dataset.temporal_extent)
 
 ###############################################################################
 
+
 class AbstractDatasetComparisonKeyStartTime(object):
-    """!This comparison key can be used to sort lists of abstract datasets
+    """This comparison key can be used to sort lists of abstract datasets
        by start time
 
         Example:
 
-        # Return all maps in a space time raster dataset as map objects
-        map_list = strds.get_registered_maps_as_objects()
+        .. code-block:: python
+
+            # Return all maps in a space time raster dataset as map objects
+            map_list = strds.get_registered_maps_as_objects()
 
-        # Sort the maps in the list by start time
-        sorted_map_list = sorted(
-            map_list, key=AbstractDatasetComparisonKeyStartTime)
+            # Sort the maps in the list by start time
+            sorted_map_list = sorted(map_list, key=AbstractDatasetComparisonKeyStartTime)
     """
     def __init__(self, obj, *args):
         self.obj = obj
@@ -602,18 +617,20 @@ class AbstractDatasetComparisonKeyStartTime(object):
 
 ###############################################################################
 
+
 class AbstractDatasetComparisonKeyEndTime(object):
-    """!This comparison key can be used to sort lists of abstract datasets
+    """This comparison key can be used to sort lists of abstract datasets
        by end time
 
         Example:
 
-        # Return all maps in a space time raster dataset as map objects
-        map_list = strds.get_registered_maps_as_objects()
+        .. code-block:: python
+
+            # Return all maps in a space time raster dataset as map objects
+            map_list = strds.get_registered_maps_as_objects()
 
-        # Sort the maps in the list by end time
-        sorted_map_list = sorted(
-            map_list, key=AbstractDatasetComparisonKeyEndTime)
+            # Sort the maps in the list by end time
+            sorted_map_list = sorted(map_list, key=AbstractDatasetComparisonKeyEndTime)
     """
     def __init__(self, obj, *args):
         self.obj = obj

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 373 - 350
lib/python/temporal/abstract_map_dataset.py


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 606 - 574
lib/python/temporal/abstract_space_time_dataset.py


+ 173 - 35
lib/python/temporal/aggregation.py

@@ -1,44 +1,39 @@
-"""!@package grass.temporal
-
-@brief GRASS Python scripting module (temporal GIS functions)
-
-Temporal GIS related functions to be used in Python scripts.
+"""
+Aggregation methods for space time raster datasets
 
 Usage:
 
-@code
-import grass.temporal as tgis
+.. code-block:: python
 
-tgis.aggregate_raster_maps(dataset, mapset, inputs, base, start, end,
-    count, method, register_null, dbif)
+    import grass.temporal as tgis
 
-...
-@endcode
+    tgis.aggregate_raster_maps(dataset, mapset, inputs, base, start, end, count, method, register_null, dbif)
 
 (C) 2012-2013 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
+:author: Soeren Gebbert
 """
 
 from space_time_datasets import *
+import grass.script as gscript
 from grass.exceptions import CalledModuleError
 
 ###############################################################################
 
 
 def collect_map_names(sp, dbif, start, end, sampling):
-    """!Gather all maps from dataset using a specific sample method
+    """Gather all maps from dataset using a specific sample method
 
-       @param sp The space time raster dataset to select aps from
-       @param dbif The temporal database interface to use
-       @param start The start time of the sample interval, may be relative or
+       :param sp: The space time raster dataset to select aps from
+       :param dbif: The temporal database interface to use
+       :param start: The start time of the sample interval, may be relative or
               absolute
-       @param end The end time of the sample interval, may be relative or
+       :param end: The end time of the sample interval, may be relative or
               absolute
-       @param sampling The sampling methods to use
+       :param sampling: The sampling methods to use
     """
 
     use_start = False
@@ -104,21 +99,21 @@ def collect_map_names(sp, dbif, start, end, sampling):
 
 def aggregate_raster_maps(inputs, base, start, end, count, method,
                           register_null, dbif,  offset=0):
-    """!Aggregate a list of raster input maps with r.series
+    """Aggregate a list of raster input maps with r.series
 
-       @param inputs The names of the raster maps to be aggregated
-       @param base The basename of the new created raster maps
-       @param start The start time of the sample interval, may be relative or
+       :param inputs: The names of the raster maps to be aggregated
+       :param base: The basename of the new created raster maps
+       :param start: The start time of the sample interval, may be relative or
                     absolute
-       @param end The end time of the sample interval, may be relative or
+       :param end: The end time of the sample interval, may be relative or
                   absolute
-       @param count The number to be attached to the basename of the new
+       :param count: The number to be attached to the basename of the new
                     created raster map
-       @param method The aggreation method to be used by r.series
-       @param register_null If true null maps will be registered in the space
+       :param method: The aggreation method to be used by r.series
+       :param register_null: If true null maps will be registered in the space
                             time raster dataset, if false not
-       @param dbif The temporal database interface to use
-       @param offset Offset to be added to the map counter to create the map ids
+       :param dbif: The temporal database interface to use
+       :param offset: Offset to be added to the map counter to create the map ids
     """
 
     msgr = get_tgis_message_interface()
@@ -132,20 +127,21 @@ def aggregate_raster_maps(inputs, base, start, end, count, method,
 
     # Check if new map is in the temporal database
     if new_map.is_in_db(dbif):
-        if core.overwrite() == True:
+        if gscript.overwrite() is True:
             # Remove the existing temporal database entry
             new_map.delete(dbif)
             new_map = RasterDataset(map_id)
         else:
-            msgr.error(_("Raster map <%s> is already in temporal database, " \
-                         "use overwrite flag to overwrite"))
+            msgr.error(_("Raster map <%(name)s> is already in temporal "
+                         "database, use overwrite flag to overwrite" %
+                       ({"name": new_map.get_name()})))
             return
 
     msgr.verbose(_("Computing aggregation of maps between %(st)s - %(end)s" % {
                    'st': str(start), 'end': str(end)}))
 
     # Create the r.series input file
-    filename = core.tempfile(True)
+    filename = gscript.tempfile(True)
     file = open(filename, 'w')
 
     for name in inputs:
@@ -153,7 +149,6 @@ def aggregate_raster_maps(inputs, base, start, end, count, method,
         file.write(string)
 
     file.close()
-    
     # Run r.series
     try:
         if len(inputs) > 1000:
@@ -173,9 +168,152 @@ def aggregate_raster_maps(inputs, base, start, end, count, method,
     new_map.load()
 
     # In case of a null map continue, do not register null maps
-    if new_map.metadata.get_min() is None and new_map.metadata.get_max() is None:
+    if new_map.metadata.get_min() is None and \
+       new_map.metadata.get_max() is None:
         if not register_null:
-            core.run_command("g.remove", type="rast", name=output, flags="f")
+            gscript.run_command("g.remove", flags='f', type='rast',
+                                name=output)
             return None
 
     return new_map
+
+##############################################################################
+
+
+def aggregate_by_topology(granularity_list, granularity, map_list, topo_list,
+                          basename, time_suffix, offset=0, method="average",
+                          nprocs=1, spatial=None, dbif=None, overwrite=False):
+    """Aggregate a list of raster input maps with r.series
+
+       :param granularity_list: A list of AbstractMapDataset objects.
+                                The temporal extents of the objects are used
+                                to build the spatio-temporal topology with the
+                                map list objects
+       :param granularity: The granularity of the granularity list
+       :param map_list: A list of RasterDataset objects that contain the raster
+                        maps that should be aggregated
+       :param topo_list: A list of strings of topological relations that are
+                         used to select the raster maps for aggregation
+       :param basename: The basename of the new generated raster maps
+       :param time_suffix: Use the granularity truncated start time of the
+                           actual granule to create the suffix for the basename
+       :param offset: Use a numerical offset for suffix generation
+                      (overwritten by time_suffix)
+       :param method: The aggregation method of r.series (average,min,max, ...)
+       :param nprocs: The number of processes used for parallel computation
+       :param spatial: This indicates if the spatial topology is created as
+                       well: spatial can be None (no spatial topology), "2D"
+                       using west, east, south, north or "3D" using west,
+                       east, south, north, bottom, top
+       :param dbif: The database interface to be used
+       :param overwrite: Overwrite existing raster maps
+       :return: A list of RasterDataset objects that contain the new map names
+                and the temporal extent for map registration
+    """
+    import grass.pygrass.modules as pymod
+    import copy
+
+    msgr = get_tgis_message_interface()
+
+    dbif, connected = init_dbif(dbif)
+
+    topo_builder = SpatioTemporalTopologyBuilder()
+    topo_builder.build(mapsA=granularity_list, mapsB=map_list, spatial=spatial)
+
+    # The module queue for parallel execution
+    process_queue = pymod.ParallelModuleQueue(int(nprocs))
+
+    # Dummy process object that will be deep copied
+    # and be put into the process queue
+    r_series = pymod.Module("r.series", output="spam", method=[method],
+                            overwrite=overwrite, quiet=True, run_=False,
+                            finish_=False)
+    g_copy = pymod.Module("g.copy", rast=['spam', 'spamspam'],
+                          quiet=True, run_=False, finish_=False)
+    output_list = []
+    count = 0
+
+    for granule in granularity_list:
+        msgr.percent(count, len(granularity_list), 1)
+        count += 1
+
+        aggregation_list = []
+
+        if "equal" in topo_list and granule.equal:
+            for map_layer in granule.equal:
+                aggregation_list.append(map_layer.get_name())
+        if "contains" in topo_list and granule.contains:
+            for map_layer in granule.contains:
+                aggregation_list.append(map_layer.get_name())
+        if "during" in topo_list and granule.during:
+            for map_layer in granule.during:
+                aggregation_list.append(map_layer.get_name())
+        if "starts" in topo_list and granule.starts:
+            for map_layer in granule.starts:
+                aggregation_list.append(map_layer.get_name())
+        if "started" in topo_list and granule.started:
+            for map_layer in granule.started:
+                aggregation_list.append(map_layer.get_name())
+        if "finishes" in topo_list and granule.finishes:
+            for map_layer in granule.finishes:
+                aggregation_list.append(map_layer.get_name())
+        if "finished" in topo_list and granule.finished:
+            for map_layer in granule.finished:
+                aggregation_list.append(map_layer.get_name())
+        if "overlaps" in topo_list and granule.overlaps:
+            for map_layer in granule.overlaps:
+                aggregation_list.append(map_layer.get_name())
+        if "overlapped" in topo_list and granule.overlapped:
+            for map_layer in granule.overlapped:
+                aggregation_list.append(map_layer.get_name())
+
+        if aggregation_list:
+            msgr.verbose(_("Aggregating %(len)i raster maps from %(start)s to"
+                           " %(end)s")  %({"len": len(aggregation_list),
+                           "start": str(granule.temporal_extent.get_start_time()),
+                           "end": str(granule.temporal_extent.get_end_time())}))
+
+            if granule.is_time_absolute() is True and time_suffix is True:
+                suffix = create_suffix_from_datetime(granule.temporal_extent.get_start_time(),
+                                                     granularity)
+            else:
+                suffix = gscript.get_num_suffix(count + int(offset),
+                                                len(granularity_list) + int(offset))
+            output_name = "%s_%s" % (basename, suffix)
+
+            map_layer = RasterDataset("%s@%s" % (output_name,
+                                                 get_current_mapset()))
+            map_layer.set_temporal_extent(granule.get_temporal_extent())
+
+            if map_layer.map_exists() is True and overwrite is False:
+                msgr.fatal(_("Unable to perform aggregation. Output raster "
+                             "map <%(name)s> exists and overwrite flag was "
+                             "not set" % ({"name": output_name})))
+
+            output_list.append(map_layer)
+
+            if len(aggregation_list) > 1:
+                # Create the r.series input file
+                filename = gscript.tempfile(True)
+                file = open(filename, 'w')
+                for name in aggregation_list:
+                    string = "%s\n" % (name)
+                    file.write(string)
+                file.close()
+
+                mod = copy.deepcopy(r_series)
+                mod(file=filename, output=output_name)
+                if len(aggregation_list) > 1000:
+                    mod(flags="z")
+                process_queue.put(mod)
+            else:
+                mod = copy.deepcopy(g_copy)
+                mod(rast=[aggregation_list[0],  output_name])
+                process_queue.put(mod)
+
+    if connected:
+        dbif.close()
+
+    msgr.percent(1, 1, 1)
+
+    return output_list

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 340 - 321
lib/python/temporal/base.py


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 482 - 289
lib/python/temporal/c_libraries_interface.py


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 563 - 259
lib/python/temporal/core.py


+ 368 - 336
lib/python/temporal/datetime_math.py

@@ -1,17 +1,14 @@
-"""!@package grass.temporal
-
-@brief GRASS Python scripting module (temporal GIS functions)
-
-Temporal GIS datetime math functions to be used in library functions and modules.
+"""
+Functions for mathematical datetime operations
 
 (C) 2011-2013 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
+:authors: Soeren Gebbert
 """
-from datetime import datetime, date, time, timedelta
+from datetime import datetime, timedelta
 from core import *
 import copy
 
@@ -26,8 +23,9 @@ SECOND_AS_DAY = 1.1574074074074073e-05
 
 ###############################################################################
 
+
 def relative_time_to_time_delta(value):
-    """!Convert the double value representing days
+    """Convert the double value representing days
        into a timedelta object.
     """
 
@@ -41,7 +39,7 @@ def relative_time_to_time_delta(value):
 
 
 def time_delta_to_relative_time(delta):
-    """!Convert the time delta into a
+    """Convert the time delta into a
        double value, representing days.
     """
 
@@ -51,7 +49,7 @@ def time_delta_to_relative_time(delta):
 
 
 def relative_time_to_time_delta_seconds(value):
-    """!Convert the double value representing seconds
+    """Convert the double value representing seconds
        into a timedelta object.
     """
 
@@ -64,7 +62,7 @@ def relative_time_to_time_delta_seconds(value):
 
 
 def time_delta_to_relative_time_seconds(delta):
-    """!Convert the time delta into a
+    """Convert the time delta into a
        double value, representing seconds.
     """
 
@@ -72,163 +70,167 @@ def time_delta_to_relative_time_seconds(delta):
 
 ###############################################################################
 
+
 def decrement_datetime_by_string(mydate, increment, mult=1):
 
-    """!Return a new datetime object decremented with the provided
+    """Return a new datetime object decremented with the provided
        relative dates specified as string.
        Additional a multiplier can be specified to multiply the increment
        before adding to the provided datetime object.
 
        Usage:
 
-       @code
-
-        >>> dt = datetime(2001, 1, 1, 0, 0, 0)
-        >>> string = "31 days"
-        >>> decrement_datetime_by_string(dt, string)
-        datetime.datetime(2000, 12, 1, 0, 0)
-
-        >>> dt = datetime(2001, 1, 1, 0, 0, 0)
-        >>> string = "1 month"
-        >>> decrement_datetime_by_string(dt, string)
-        datetime.datetime(2000, 12, 1, 0, 0)
-
-        >>> dt = datetime(2001, 1, 1, 0, 0, 0)
-        >>> string = "2 month"
-        >>> decrement_datetime_by_string(dt, string)
-        datetime.datetime(2000, 11, 1, 0, 0)
-
-        >>> dt = datetime(2001, 1, 1, 0, 0, 0)
-        >>> string = "24 months"
-        >>> decrement_datetime_by_string(dt, string)
-        datetime.datetime(1999, 1, 1, 0, 0)
-
-        >>> dt = datetime(2001, 1, 1, 0, 0, 0)
-        >>> string = "48 months"
-        >>> decrement_datetime_by_string(dt, string)
-        datetime.datetime(1997, 1, 1, 0, 0)
-
-        >>> dt = datetime(2001, 6, 1, 0, 0, 0)
-        >>> string = "5 months"
-        >>> decrement_datetime_by_string(dt, string)
-        datetime.datetime(2001, 1, 1, 0, 0)
-
-        >>> dt = datetime(2001, 6, 1, 0, 0, 0)
-        >>> string = "7 months"
-        >>> decrement_datetime_by_string(dt, string)
-        datetime.datetime(2000, 11, 1, 0, 0)
-
-        >>> dt = datetime(2001, 1, 1, 0, 0, 0)
-        >>> string = "1 year"
-        >>> decrement_datetime_by_string(dt, string)
-        datetime.datetime(2000, 1, 1, 0, 0)
-
-        @endcode
-
-       @param mydate A datetime object to incremented
-       @param increment A string providing increment information:
-                  The string may include comma separated values of type seconds,
-                  minutes, hours, days, weeks, months and years
-                  Example: Increment the datetime 2001-01-01 00:00:00
-                  with "60 seconds, 4 minutes, 12 hours, 10 days, 1 weeks, 5 months, 1 years"
-                  will result in the datetime 2003-02-18 12:05:00
-       @param mult A multiplier, default is 1
-       @return The new datetime object or none in case of an error
+       .. code-block:: python
+
+            >>> dt = datetime(2001, 1, 1, 0, 0, 0)
+            >>> string = "31 days"
+            >>> decrement_datetime_by_string(dt, string)
+            datetime.datetime(2000, 12, 1, 0, 0)
+
+            >>> dt = datetime(2001, 1, 1, 0, 0, 0)
+            >>> string = "1 month"
+            >>> decrement_datetime_by_string(dt, string)
+            datetime.datetime(2000, 12, 1, 0, 0)
+
+            >>> dt = datetime(2001, 1, 1, 0, 0, 0)
+            >>> string = "2 month"
+            >>> decrement_datetime_by_string(dt, string)
+            datetime.datetime(2000, 11, 1, 0, 0)
+
+            >>> dt = datetime(2001, 1, 1, 0, 0, 0)
+            >>> string = "24 months"
+            >>> decrement_datetime_by_string(dt, string)
+            datetime.datetime(1999, 1, 1, 0, 0)
+
+            >>> dt = datetime(2001, 1, 1, 0, 0, 0)
+            >>> string = "48 months"
+            >>> decrement_datetime_by_string(dt, string)
+            datetime.datetime(1997, 1, 1, 0, 0)
+
+            >>> dt = datetime(2001, 6, 1, 0, 0, 0)
+            >>> string = "5 months"
+            >>> decrement_datetime_by_string(dt, string)
+            datetime.datetime(2001, 1, 1, 0, 0)
+
+            >>> dt = datetime(2001, 6, 1, 0, 0, 0)
+            >>> string = "7 months"
+            >>> decrement_datetime_by_string(dt, string)
+            datetime.datetime(2000, 11, 1, 0, 0)
+
+            >>> dt = datetime(2001, 1, 1, 0, 0, 0)
+            >>> string = "1 year"
+            >>> decrement_datetime_by_string(dt, string)
+            datetime.datetime(2000, 1, 1, 0, 0)
+
+
+       :param mydate: A datetime object to incremented
+       :param increment: A string providing increment information:
+                         The string may include comma separated values of type
+                         seconds, minutes, hours, days, weeks, months and years
+                         Example: Increment the datetime 2001-01-01 00:00:00
+                         with "60 seconds, 4 minutes, 12 hours, 10 days,
+                         1 weeks, 5 months, 1 years" will result in the
+                         datetime 2003-02-18 12:05:00
+       :param mult: A multiplier, default is 1
+       :return: The new datetime object or none in case of an error
     """
     return modify_datetime_by_string(mydate, increment, mult, sign=int(-1))
 
 ###############################################################################
 
+
 def increment_datetime_by_string(mydate, increment, mult=1):
-    """!Return a new datetime object incremented with the provided
+    """Return a new datetime object incremented with the provided
        relative dates specified as string.
        Additional a multiplier can be specified to multiply the increment
        before adding to the provided datetime object.
 
        Usage:
 
-       @code
-
-        >>> dt = datetime(2001, 9, 1, 0, 0, 0)
-        >>> string = "60 seconds, 4 minutes, 12 hours, 10 days, 1 weeks, 5 months, 1 years"
-        >>> increment_datetime_by_string(dt, string)
-        datetime.datetime(2003, 2, 18, 12, 5)
-
-        >>> dt = datetime(2001, 11, 1, 0, 0, 0)
-        >>> string = "1 months"
-        >>> increment_datetime_by_string(dt, string)
-        datetime.datetime(2001, 12, 1, 0, 0)
-
-        >>> dt = datetime(2001, 11, 1, 0, 0, 0)
-        >>> string = "13 months"
-        >>> increment_datetime_by_string(dt, string)
-        datetime.datetime(2002, 12, 1, 0, 0)
-
-        >>> dt = datetime(2001, 1, 1, 0, 0, 0)
-        >>> string = "72 months"
-        >>> increment_datetime_by_string(dt, string)
-        datetime.datetime(2007, 1, 1, 0, 0)
-
-        >>> dt = datetime(2001, 1, 1, 0, 0, 0)
-        >>> string = "72 months"
-        >>> increment_datetime_by_string(dt, string)
-        datetime.datetime(2007, 1, 1, 0, 0)
-
-        >>> dt = datetime(2001, 1, 1, 0, 0, 0)
-        >>> string = "5 minutes"
-        >>> increment_datetime_by_string(dt, string)
-        datetime.datetime(2001, 1, 1, 0, 5)
-
-        >>> dt = datetime(2001, 1, 1, 0, 0, 0)
-        >>> string = "49 hours"
-        >>> increment_datetime_by_string(dt, string)
-        datetime.datetime(2001, 1, 3, 1, 0)
-
-        >>> dt = datetime(2001, 1, 1, 0, 0, 0)
-        >>> string = "3600 seconds"
-        >>> increment_datetime_by_string(dt, string)
-        datetime.datetime(2001, 1, 1, 1, 0)
-
-        >>> dt = datetime(2001, 1, 1, 0, 0, 0)
-        >>> string = "30 days"
-        >>> increment_datetime_by_string(dt, string)
-        datetime.datetime(2001, 1, 31, 0, 0)
-
-        @endcode
-
-       @param mydate A datetime object to incremented
-       @param increment A string providing increment information:
-                  The string may include comma separated values of type seconds,
-                  minutes, hours, days, weeks, months and years
-                  Example: Increment the datetime 2001-01-01 00:00:00
-                  with "60 seconds, 4 minutes, 12 hours, 10 days, 1 weeks, 5 months, 1 years"
-                  will result in the datetime 2003-02-18 12:05:00
-       @param mult A multiplier, default is 1
-       @return The new datetime object or none in case of an error
+       .. code-block:: python
+
+            >>> dt = datetime(2001, 9, 1, 0, 0, 0)
+            >>> string = "60 seconds, 4 minutes, 12 hours, 10 days, 1 weeks, 5 months, 1 years"
+            >>> increment_datetime_by_string(dt, string)
+            datetime.datetime(2003, 2, 18, 12, 5)
+
+            >>> dt = datetime(2001, 11, 1, 0, 0, 0)
+            >>> string = "1 months"
+            >>> increment_datetime_by_string(dt, string)
+            datetime.datetime(2001, 12, 1, 0, 0)
+
+            >>> dt = datetime(2001, 11, 1, 0, 0, 0)
+            >>> string = "13 months"
+            >>> increment_datetime_by_string(dt, string)
+            datetime.datetime(2002, 12, 1, 0, 0)
+
+            >>> dt = datetime(2001, 1, 1, 0, 0, 0)
+            >>> string = "72 months"
+            >>> increment_datetime_by_string(dt, string)
+            datetime.datetime(2007, 1, 1, 0, 0)
+
+            >>> dt = datetime(2001, 1, 1, 0, 0, 0)
+            >>> string = "72 months"
+            >>> increment_datetime_by_string(dt, string)
+            datetime.datetime(2007, 1, 1, 0, 0)
+
+            >>> dt = datetime(2001, 1, 1, 0, 0, 0)
+            >>> string = "5 minutes"
+            >>> increment_datetime_by_string(dt, string)
+            datetime.datetime(2001, 1, 1, 0, 5)
+
+            >>> dt = datetime(2001, 1, 1, 0, 0, 0)
+            >>> string = "49 hours"
+            >>> increment_datetime_by_string(dt, string)
+            datetime.datetime(2001, 1, 3, 1, 0)
+
+            >>> dt = datetime(2001, 1, 1, 0, 0, 0)
+            >>> string = "3600 seconds"
+            >>> increment_datetime_by_string(dt, string)
+            datetime.datetime(2001, 1, 1, 1, 0)
+
+            >>> dt = datetime(2001, 1, 1, 0, 0, 0)
+            >>> string = "30 days"
+            >>> increment_datetime_by_string(dt, string)
+            datetime.datetime(2001, 1, 31, 0, 0)
+
+
+       :param mydate: A datetime object to incremented
+       :param increment: A string providing increment information:
+                         The string may include comma separated values of type
+                         seconds, minutes, hours, days, weeks, months and years
+                         Example: Increment the datetime 2001-01-01 00:00:00
+                         with "60 seconds, 4 minutes, 12 hours, 10 days,
+                         1 weeks, 5 months, 1 years" will result in the
+                         datetime 2003-02-18 12:05:00
+       :param mult: A multiplier, default is 1
+       :return: The new datetime object or none in case of an error
     """
     return modify_datetime_by_string(mydate, increment, mult, sign=int(1))
 
 ###############################################################################
 
+
 def modify_datetime_by_string(mydate, increment, mult=1, sign=1):
-    """!Return a new datetime object incremented with the provided
+    """Return a new datetime object incremented with the provided
        relative dates specified as string.
        Additional a multiplier can be specified to multiply the increment
        before adding to the provided datetime object.
 
-       @param mydate A datetime object to incremented
-       @param increment A string providing increment information:
-                  The string may include comma separated values of type seconds,
-                  minutes, hours, days, weeks, months and years
-                  Example: Increment the datetime 2001-01-01 00:00:00
-                  with "60 seconds, 4 minutes, 12 hours, 10 days, 1 weeks, 5 months, 1 years"
-                  will result in the datetime 2003-02-18 12:05:00
-       @param mult A multiplier, default is 1
-       @param sign Choose 1 for positive sign (incrementing) or -1 for negative
-                   sign (decrementing).
-       @return The new datetime object or none in case of an error
+       :param mydate: A datetime object to incremented
+       :param increment: A string providing increment information:
+                         The string may include comma separated values of type
+                         seconds, minutes, hours, days, weeks, months and years
+                         Example: Increment the datetime 2001-01-01 00:00:00
+                         with "60 seconds, 4 minutes, 12 hours, 10 days,
+                         1 weeks, 5 months, 1 years" will result in the
+                         datetime 2003-02-18 12:05:00
+       :param mult: A multiplier, default is 1
+       :param sign: Choose 1 for positive sign (incrementing) or -1 for
+                    negative sign (decrementing).
+       :return: The new datetime object or none in case of an error
     """
-    sign  = int(sign)
+    sign = int(sign)
     if sign != 1 and sign != -1:
         return None
 
@@ -271,15 +273,17 @@ def modify_datetime_by_string(mydate, increment, mult=1, sign=1):
                 msgr.error(_("Wrong increment format: %s") % (increment))
                 return None
 
-        return modify_datetime(mydate, years, months, weeks, days, hours, minutes, seconds)
+        return modify_datetime(mydate, years, months, weeks, days, hours,
+                               minutes, seconds)
 
     return mydate
 
 ###############################################################################
 
+
 def modify_datetime(mydate, years=0, months=0, weeks=0, days=0, hours=0,
-                       minutes=0, seconds=0):
-    """!Return a new datetime object incremented with the provided
+                    minutes=0, seconds=0):
+    """Return a new datetime object incremented with the provided
        relative dates and times"""
 
     tdelta_seconds = timedelta(seconds=seconds)
@@ -334,7 +338,8 @@ def modify_datetime(mydate, years=0, months=0, weeks=0, days=0, hours=0,
             residual_months += 12
 
         try:
-            dt1 = dt1.replace(year=year - years_to_remove, month=residual_months)
+            dt1 = dt1.replace(year=year - years_to_remove,
+                              month=residual_months)
         except:
             raise
 
@@ -354,7 +359,7 @@ def modify_datetime(mydate, years=0, months=0, weeks=0, days=0, hours=0,
 
 
 def adjust_datetime_to_granularity(mydate, granularity):
-    """!Modify the datetime object to fit the given granularity
+    """Modify the datetime object to fit the given granularity
 
         - Years will start at the first of Januar
         - Months will start at the first day of the month
@@ -364,43 +369,42 @@ def adjust_datetime_to_granularity(mydate, granularity):
 
         Usage:
 
-        @code
+        .. code-block:: python
 
-        >>> dt = datetime(2001, 8, 8, 12,30,30)
-        >>> adjust_datetime_to_granularity(dt, "5 seconds")
-        datetime.datetime(2001, 8, 8, 12, 30, 30)
+            >>> dt = datetime(2001, 8, 8, 12,30,30)
+            >>> adjust_datetime_to_granularity(dt, "5 seconds")
+            datetime.datetime(2001, 8, 8, 12, 30, 30)
 
-        >>> adjust_datetime_to_granularity(dt, "20 minutes")
-        datetime.datetime(2001, 8, 8, 12, 30)
+            >>> adjust_datetime_to_granularity(dt, "20 minutes")
+            datetime.datetime(2001, 8, 8, 12, 30)
 
-        >>> adjust_datetime_to_granularity(dt, "20 minutes")
-        datetime.datetime(2001, 8, 8, 12, 30)
+            >>> adjust_datetime_to_granularity(dt, "20 minutes")
+            datetime.datetime(2001, 8, 8, 12, 30)
 
-        >>> adjust_datetime_to_granularity(dt, "3 hours")
-        datetime.datetime(2001, 8, 8, 12, 0)
+            >>> adjust_datetime_to_granularity(dt, "3 hours")
+            datetime.datetime(2001, 8, 8, 12, 0)
 
-        >>> adjust_datetime_to_granularity(dt, "5 days")
-        datetime.datetime(2001, 8, 8, 0, 0)
+            >>> adjust_datetime_to_granularity(dt, "5 days")
+            datetime.datetime(2001, 8, 8, 0, 0)
 
-        >>> adjust_datetime_to_granularity(dt, "2 weeks")
-        datetime.datetime(2001, 8, 6, 0, 0)
+            >>> adjust_datetime_to_granularity(dt, "2 weeks")
+            datetime.datetime(2001, 8, 6, 0, 0)
 
-        >>> adjust_datetime_to_granularity(dt, "6 months")
-        datetime.datetime(2001, 8, 1, 0, 0)
+            >>> adjust_datetime_to_granularity(dt, "6 months")
+            datetime.datetime(2001, 8, 1, 0, 0)
 
-        >>> adjust_datetime_to_granularity(dt, "2 years")
-        datetime.datetime(2001, 1, 1, 0, 0)
+            >>> adjust_datetime_to_granularity(dt, "2 years")
+            datetime.datetime(2001, 1, 1, 0, 0)
 
-        >>> adjust_datetime_to_granularity(dt, "2 years, 3 months, 5 days, 3 hours, 3 minutes, 2 seconds")
-        datetime.datetime(2001, 8, 8, 12, 30, 30)
+            >>> adjust_datetime_to_granularity(dt, "2 years, 3 months, 5 days, 3 hours, 3 minutes, 2 seconds")
+            datetime.datetime(2001, 8, 8, 12, 30, 30)
 
-        >>> adjust_datetime_to_granularity(dt, "3 months, 5 days, 3 minutes")
-        datetime.datetime(2001, 8, 8, 12, 30)
+            >>> adjust_datetime_to_granularity(dt, "3 months, 5 days, 3 minutes")
+            datetime.datetime(2001, 8, 8, 12, 30)
 
-        >>> adjust_datetime_to_granularity(dt, "3 weeks, 5 days")
-        datetime.datetime(2001, 8, 8, 0, 0)
+            >>> adjust_datetime_to_granularity(dt, "3 weeks, 5 days")
+            datetime.datetime(2001, 8, 8, 0, 0)
 
-        @endcode
     """
 
     if granularity:
@@ -480,142 +484,141 @@ def adjust_datetime_to_granularity(mydate, granularity):
 
         dt = copy.copy(mydate)
         return dt.replace(year=years, month=months, day=days,
-                            hour=hours, minute=minutes, second=seconds)
+                          hour=hours, minute=minutes, second=seconds)
 
 ###############################################################################
 
 
 def compute_datetime_delta(start, end):
-    """!Return a dictionary with the accumulated delta in year, month, day,
+    """Return a dictionary with the accumulated delta in year, month, day,
        hour, minute and second
 
         Usage:
 
-        @code
-
-        >>> start = datetime(2001, 1, 1, 00,00,00)
-        >>> end = datetime(2001, 1, 1, 00,00,00)
-        >>> compute_datetime_delta(start, end)
-        {'hour': 0, 'month': 0, 'second': 0, 'max_days': 0, 'year': 0, 'day': 0, 'minute': 0}
-
-        >>> start = datetime(2001, 1, 1, 00,00,14)
-        >>> end = datetime(2001, 1, 1, 00,00,44)
-        >>> compute_datetime_delta(start, end)
-        {'hour': 0, 'month': 0, 'second': 30, 'max_days': 0, 'year': 0, 'day': 0, 'minute': 0}
-
-        >>> start = datetime(2001, 1, 1, 00,00,44)
-        >>> end = datetime(2001, 1, 1, 00,01,14)
-        >>> compute_datetime_delta(start, end)
-        {'hour': 0, 'month': 0, 'second': 30, 'max_days': 0, 'year': 0, 'day': 0, 'minute': 1}
-
-        >>> start = datetime(2001, 1, 1, 00,00,30)
-        >>> end = datetime(2001, 1, 1, 00,05,30)
-        >>> compute_datetime_delta(start, end)
-        {'hour': 0, 'month': 0, 'second': 300, 'max_days': 0, 'year': 0, 'day': 0, 'minute': 5}
-
-        >>> start = datetime(2001, 1, 1, 00,00,00)
-        >>> end = datetime(2001, 1, 1, 00,01,00)
-        >>> compute_datetime_delta(start, end)
-        {'hour': 0, 'month': 0, 'second': 0, 'max_days': 0, 'year': 0, 'day': 0, 'minute': 1}
-
-        >>> start = datetime(2011,10,31, 00,45,00)
-        >>> end = datetime(2011,10,31, 01,45,00)
-        >>> compute_datetime_delta(start, end)
-        {'hour': 1, 'second': 0, 'max_days': 0, 'year': 0, 'day': 0, 'minute': 60}
-
-        >>> start = datetime(2011,10,31, 00,45,00)
-        >>> end = datetime(2011,10,31, 01,15,00)
-        >>> compute_datetime_delta(start, end)
-        {'hour': 1, 'second': 0, 'max_days': 0, 'year': 0, 'day': 0, 'minute': 30}
-
-        >>> start = datetime(2011,10,31, 00,45,00)
-        >>> end = datetime(2011,10,31, 12,15,00)
-        >>> compute_datetime_delta(start, end)
-        {'hour': 12, 'second': 0, 'max_days': 0, 'year': 0, 'day': 0, 'minute': 690}
-
-        >>> start = datetime(2011,10,31, 00,00,00)
-        >>> end = datetime(2011,10,31, 01,00,00)
-        >>> compute_datetime_delta(start, end)
-        {'hour': 1, 'second': 0, 'max_days': 0, 'year': 0, 'day': 0, 'minute': 0}
-
-        >>> start = datetime(2011,10,31, 00,00,00)
-        >>> end = datetime(2011,11,01, 01,00,00)
-        >>> compute_datetime_delta(start, end)
-        {'hour': 25, 'second': 0, 'max_days': 1, 'year': 0, 'day': 1, 'minute': 0}
-
-        >>> start = datetime(2011,10,31, 12,00,00)
-        >>> end = datetime(2011,11,01, 06,00,00)
-        >>> compute_datetime_delta(start, end)
-        {'hour': 18, 'second': 0, 'max_days': 0, 'year': 0, 'day': 0, 'minute': 0}
-
-        >>> start = datetime(2011,11,01, 00,00,00)
-        >>> end = datetime(2011,12,01, 01,00,00)
-        >>> compute_datetime_delta(start, end)
-        {'hour': 721, 'month': 1, 'second': 0, 'max_days': 30, 'year': 0, 'day': 0, 'minute': 0}
-
-        >>> start = datetime(2011,11,01, 00,00,00)
-        >>> end = datetime(2011,11,05, 00,00,00)
-        >>> compute_datetime_delta(start, end)
-        {'hour': 0, 'second': 0, 'max_days': 4, 'year': 0, 'day': 4, 'minute': 0}
-
-        >>> start = datetime(2011,10,06, 00,00,00)
-        >>> end = datetime(2011,11,05, 00,00,00)
-        >>> compute_datetime_delta(start, end)
-        {'hour': 0, 'second': 0, 'max_days': 30, 'year': 0, 'day': 30, 'minute': 0}
-
-        >>> start = datetime(2011,12,02, 00,00,00)
-        >>> end = datetime(2012,01,01, 00,00,00)
-        >>> compute_datetime_delta(start, end)
-        {'hour': 0, 'second': 0, 'max_days': 30, 'year': 1, 'day': 30, 'minute': 0}
-
-        >>> start = datetime(2011,01,01, 00,00,00)
-        >>> end = datetime(2011,02,01, 00,00,00)
-        >>> compute_datetime_delta(start, end)
-        {'hour': 0, 'month': 1, 'second': 0, 'max_days': 31, 'year': 0, 'day': 0, 'minute': 0}
-
-        >>> start = datetime(2011,12,01, 00,00,00)
-        >>> end = datetime(2012,01,01, 00,00,00)
-        >>> compute_datetime_delta(start, end)
-        {'hour': 0, 'month': 1, 'second': 0, 'max_days': 31, 'year': 1, 'day': 0, 'minute': 0}
-
-        >>> start = datetime(2011,12,01, 00,00,00)
-        >>> end = datetime(2012,06,01, 00,00,00)
-        >>> compute_datetime_delta(start, end)
-        {'hour': 0, 'month': 6, 'second': 0, 'max_days': 183, 'year': 1, 'day': 0, 'minute': 0}
-
-        >>> start = datetime(2011,06,01, 00,00,00)
-        >>> end = datetime(2021,06,01, 00,00,00)
-        >>> compute_datetime_delta(start, end)
-        {'hour': 0, 'month': 120, 'second': 0, 'max_days': 3653, 'year': 10, 'day': 0, 'minute': 0}
-
-        >>> start = datetime(2011,06,01, 00,00,00)
-        >>> end = datetime(2012,06,01, 12,00,00)
-        >>> compute_datetime_delta(start, end)
-        {'hour': 8796, 'month': 12, 'second': 0, 'max_days': 366, 'year': 1, 'day': 0, 'minute': 0}
-
-        >>> start = datetime(2011,06,01, 00,00,00)
-        >>> end = datetime(2012,06,01, 12,30,00)
-        >>> compute_datetime_delta(start, end)
-        {'hour': 8796, 'month': 12, 'second': 0, 'max_days': 366, 'year': 1, 'day': 0, 'minute': 527790}
-
-        >>> start = datetime(2011,06,01, 00,00,00)
-        >>> end = datetime(2012,06,01, 12,00,05)
-        >>> compute_datetime_delta(start, end)
-        {'hour': 8796, 'month': 12, 'second': 31665605, 'max_days': 366, 'year': 1, 'day': 0, 'minute': 0}
-
-        >>> start = datetime(2011,06,01, 00,00,00)
-        >>> end = datetime(2012,06,01, 00,30,00)
-        >>> compute_datetime_delta(start, end)
-        {'hour': 0, 'month': 12, 'second': 0, 'max_days': 366, 'year': 1, 'day': 0, 'minute': 527070}
-
-        >>> start = datetime(2011,06,01, 00,00,00)
-        >>> end = datetime(2012,06,01, 00,00,05)
-        >>> compute_datetime_delta(start, end)
-        {'hour': 0, 'month': 12, 'second': 31622405, 'max_days': 366, 'year': 1, 'day': 0, 'minute': 0}
-
-        @endcode
-
-       @return A dictionary with year, month, day, hour, minute and second as keys()
+        .. code-block:: python
+
+            >>> start = datetime(2001, 1, 1, 00,00,00)
+            >>> end = datetime(2001, 1, 1, 00,00,00)
+            >>> compute_datetime_delta(start, end)
+            {'hour': 0, 'month': 0, 'second': 0, 'max_days': 0, 'year': 0, 'day': 0, 'minute': 0}
+
+            >>> start = datetime(2001, 1, 1, 00,00,14)
+            >>> end = datetime(2001, 1, 1, 00,00,44)
+            >>> compute_datetime_delta(start, end)
+            {'hour': 0, 'month': 0, 'second': 30, 'max_days': 0, 'year': 0, 'day': 0, 'minute': 0}
+
+            >>> start = datetime(2001, 1, 1, 00,00,44)
+            >>> end = datetime(2001, 1, 1, 00,01,14)
+            >>> compute_datetime_delta(start, end)
+            {'hour': 0, 'month': 0, 'second': 30, 'max_days': 0, 'year': 0, 'day': 0, 'minute': 1}
+
+            >>> start = datetime(2001, 1, 1, 00,00,30)
+            >>> end = datetime(2001, 1, 1, 00,05,30)
+            >>> compute_datetime_delta(start, end)
+            {'hour': 0, 'month': 0, 'second': 300, 'max_days': 0, 'year': 0, 'day': 0, 'minute': 5}
+
+            >>> start = datetime(2001, 1, 1, 00,00,00)
+            >>> end = datetime(2001, 1, 1, 00,01,00)
+            >>> compute_datetime_delta(start, end)
+            {'hour': 0, 'month': 0, 'second': 0, 'max_days': 0, 'year': 0, 'day': 0, 'minute': 1}
+
+            >>> start = datetime(2011,10,31, 00,45,00)
+            >>> end = datetime(2011,10,31, 01,45,00)
+            >>> compute_datetime_delta(start, end)
+            {'hour': 1, 'second': 0, 'max_days': 0, 'year': 0, 'day': 0, 'minute': 60}
+
+            >>> start = datetime(2011,10,31, 00,45,00)
+            >>> end = datetime(2011,10,31, 01,15,00)
+            >>> compute_datetime_delta(start, end)
+            {'hour': 1, 'second': 0, 'max_days': 0, 'year': 0, 'day': 0, 'minute': 30}
+
+            >>> start = datetime(2011,10,31, 00,45,00)
+            >>> end = datetime(2011,10,31, 12,15,00)
+            >>> compute_datetime_delta(start, end)
+            {'hour': 12, 'second': 0, 'max_days': 0, 'year': 0, 'day': 0, 'minute': 690}
+
+            >>> start = datetime(2011,10,31, 00,00,00)
+            >>> end = datetime(2011,10,31, 01,00,00)
+            >>> compute_datetime_delta(start, end)
+            {'hour': 1, 'second': 0, 'max_days': 0, 'year': 0, 'day': 0, 'minute': 0}
+
+            >>> start = datetime(2011,10,31, 00,00,00)
+            >>> end = datetime(2011,11,01, 01,00,00)
+            >>> compute_datetime_delta(start, end)
+            {'hour': 25, 'second': 0, 'max_days': 1, 'year': 0, 'day': 1, 'minute': 0}
+
+            >>> start = datetime(2011,10,31, 12,00,00)
+            >>> end = datetime(2011,11,01, 06,00,00)
+            >>> compute_datetime_delta(start, end)
+            {'hour': 18, 'second': 0, 'max_days': 0, 'year': 0, 'day': 0, 'minute': 0}
+
+            >>> start = datetime(2011,11,01, 00,00,00)
+            >>> end = datetime(2011,12,01, 01,00,00)
+            >>> compute_datetime_delta(start, end)
+            {'hour': 721, 'month': 1, 'second': 0, 'max_days': 30, 'year': 0, 'day': 0, 'minute': 0}
+
+            >>> start = datetime(2011,11,01, 00,00,00)
+            >>> end = datetime(2011,11,05, 00,00,00)
+            >>> compute_datetime_delta(start, end)
+            {'hour': 0, 'second': 0, 'max_days': 4, 'year': 0, 'day': 4, 'minute': 0}
+
+            >>> start = datetime(2011,10,06, 00,00,00)
+            >>> end = datetime(2011,11,05, 00,00,00)
+            >>> compute_datetime_delta(start, end)
+            {'hour': 0, 'second': 0, 'max_days': 30, 'year': 0, 'day': 30, 'minute': 0}
+
+            >>> start = datetime(2011,12,02, 00,00,00)
+            >>> end = datetime(2012,01,01, 00,00,00)
+            >>> compute_datetime_delta(start, end)
+            {'hour': 0, 'second': 0, 'max_days': 30, 'year': 1, 'day': 30, 'minute': 0}
+
+            >>> start = datetime(2011,01,01, 00,00,00)
+            >>> end = datetime(2011,02,01, 00,00,00)
+            >>> compute_datetime_delta(start, end)
+            {'hour': 0, 'month': 1, 'second': 0, 'max_days': 31, 'year': 0, 'day': 0, 'minute': 0}
+
+            >>> start = datetime(2011,12,01, 00,00,00)
+            >>> end = datetime(2012,01,01, 00,00,00)
+            >>> compute_datetime_delta(start, end)
+            {'hour': 0, 'month': 1, 'second': 0, 'max_days': 31, 'year': 1, 'day': 0, 'minute': 0}
+
+            >>> start = datetime(2011,12,01, 00,00,00)
+            >>> end = datetime(2012,06,01, 00,00,00)
+            >>> compute_datetime_delta(start, end)
+            {'hour': 0, 'month': 6, 'second': 0, 'max_days': 183, 'year': 1, 'day': 0, 'minute': 0}
+
+            >>> start = datetime(2011,06,01, 00,00,00)
+            >>> end = datetime(2021,06,01, 00,00,00)
+            >>> compute_datetime_delta(start, end)
+            {'hour': 0, 'month': 120, 'second': 0, 'max_days': 3653, 'year': 10, 'day': 0, 'minute': 0}
+
+            >>> start = datetime(2011,06,01, 00,00,00)
+            >>> end = datetime(2012,06,01, 12,00,00)
+            >>> compute_datetime_delta(start, end)
+            {'hour': 8796, 'month': 12, 'second': 0, 'max_days': 366, 'year': 1, 'day': 0, 'minute': 0}
+
+            >>> start = datetime(2011,06,01, 00,00,00)
+            >>> end = datetime(2012,06,01, 12,30,00)
+            >>> compute_datetime_delta(start, end)
+            {'hour': 8796, 'month': 12, 'second': 0, 'max_days': 366, 'year': 1, 'day': 0, 'minute': 527790}
+
+            >>> start = datetime(2011,06,01, 00,00,00)
+            >>> end = datetime(2012,06,01, 12,00,05)
+            >>> compute_datetime_delta(start, end)
+            {'hour': 8796, 'month': 12, 'second': 31665605, 'max_days': 366, 'year': 1, 'day': 0, 'minute': 0}
+
+            >>> start = datetime(2011,06,01, 00,00,00)
+            >>> end = datetime(2012,06,01, 00,30,00)
+            >>> compute_datetime_delta(start, end)
+            {'hour': 0, 'month': 12, 'second': 0, 'max_days': 366, 'year': 1, 'day': 0, 'minute': 527070}
+
+            >>> start = datetime(2011,06,01, 00,00,00)
+            >>> end = datetime(2012,06,01, 00,00,05)
+            >>> compute_datetime_delta(start, end)
+            {'hour': 0, 'month': 12, 'second': 31622405, 'max_days': 366, 'year': 1, 'day': 0, 'minute': 0}
+
+       :return: A dictionary with year, month, day, hour, minute and second as
+                keys()
     """
     comp = {}
 
@@ -631,7 +634,7 @@ def compute_datetime_delta(start, end):
     # Count full months
     if start.month == 1 and end.month == 1:
         comp["month"] = 0
-    elif   start.day == 1 and end.day == 1:
+    elif start.day == 1 and end.day == 1:
         d = end.month - start.month
         if d < 0:
             d = d + 12 * comp["year"]
@@ -640,7 +643,7 @@ def compute_datetime_delta(start, end):
         comp["month"] = d
 
     # Count full days
-    if  start.day == 1 and end.day == 1:
+    if start.day == 1 and end.day == 1:
         comp["day"] = 0
     else:
         comp["day"] = day_diff
@@ -702,36 +705,37 @@ def compute_datetime_delta(start, end):
 
 
 def check_datetime_string(time_string):
-    """!Check if  a string can be converted into a datetime object
+    """Check if  a string can be converted into a datetime object
 
         Supported ISO string formats are:
+
         - YYYY-mm-dd
         - YYYY-mm-dd HH:MM:SS
 
         Time zones are not supported
 
-        @param time_string The time string to be checked for conversion
-        @return datetime object or an error message string in case of an error
+        :param time_string: The time string to be checked for conversion
+        :return: datetime: object or an error message string in case of an error
     """
 
     global has_dateutil
-        
+
     if has_dateutil:
-        # First check if there is only a single number, which specifies relative time.
-        # dateutil will interprete a single number as a valid time string, so we have
-        # to catch this case beforehand
+        # First check if there is only a single number, which specifies
+        # relative time. dateutil will interprete a single number as a valid
+        # time string, so we have to catch this case beforehand
         try:
             value = int(time_string)
             return _("Time string seems to specify relative time")
         except ValueError:
             pass
-        
+
         try:
             time_object = parser.parse(time_string)
         except Exception as inst:
             time_object = str(inst)
         return time_object
-        
+
     # BC is not supported
     if time_string.find("bc") > 0:
         return _("Dates Before Christ (BC) are not supported")
@@ -746,27 +750,28 @@ def check_datetime_string(time_string):
         time_format = "%Y-%m-%d"
 
     try:
-        return  datetime.strptime(time_string, time_format)
+        return datetime.strptime(time_string, time_format)
     except:
-        return _("Unable to parse time string: %s"%time_string)
+        return _("Unable to parse time string: %s" % time_string)
 
 ###############################################################################
 
 
 def string_to_datetime(time_string):
-    """!Convert a string into a datetime object
+    """Convert a string into a datetime object
 
         In case datutil is not installed the supported ISO string formats are:
+
         - YYYY-mm-dd
         - YYYY-mm-dd HH:MM:SS
         - Time zones are not supported
-        
+
         If dateutil is installed, all string formats of the dateutil module
         are supported, as well as time zones
 
-        @param time_string The time string to convert
-        @return datetime object or None in case the string 
-                         could not be converted
+        :param time_string: The time string to convert
+        :return: datetime object or None in case the string
+                 could not be converted
     """
 
     if not isinstance(time_string, str):
@@ -784,26 +789,25 @@ def string_to_datetime(time_string):
 
 
 def datetime_to_grass_datetime_string(dt):
-    """!Convert a python datetime object into a GRASS datetime string
-    
-    @code
-    
-    >>> import grass.temporal as tgis
-    >>> import dateutil.parser as parser
-    >>> dt = parser.parse("2011-01-01 10:00:00 +01:30")
-    >>> tgis.datetime_to_grass_datetime_string(dt)
-    '01 jan 2011 10:00:00 +0090'
-    >>> dt = parser.parse("2011-01-01 10:00:00 +02:30")
-    >>> tgis.datetime_to_grass_datetime_string(dt)
-    '01 jan 2011 10:00:00 +0150'
-    >>> dt = parser.parse("2011-01-01 10:00:00 +12:00")
-    >>> tgis.datetime_to_grass_datetime_string(dt)
-    '01 jan 2011 10:00:00 +0720'
-    >>> dt = parser.parse("2011-01-01 10:00:00 -01:30")
-    >>> tgis.datetime_to_grass_datetime_string(dt)
-    '01 jan 2011 10:00:00 -0090'
-    
-    @endcode
+    """Convert a python datetime object into a GRASS datetime string
+
+    .. code-block:: python
+
+        >>> import grass.temporal as tgis
+        >>> import dateutil.parser as parser
+        >>> dt = parser.parse("2011-01-01 10:00:00 +01:30")
+        >>> tgis.datetime_to_grass_datetime_string(dt)
+        '01 jan 2011 10:00:00 +0090'
+        >>> dt = parser.parse("2011-01-01 10:00:00 +02:30")
+        >>> tgis.datetime_to_grass_datetime_string(dt)
+        '01 jan 2011 10:00:00 +0150'
+        >>> dt = parser.parse("2011-01-01 10:00:00 +12:00")
+        >>> tgis.datetime_to_grass_datetime_string(dt)
+        '01 jan 2011 10:00:00 +0720'
+        >>> dt = parser.parse("2011-01-01 10:00:00 -01:30")
+        >>> tgis.datetime_to_grass_datetime_string(dt)
+        '01 jan 2011 10:00:00 -0090'
+
     """
     # GRASS datetime month names
     month_names = ["", "jan", "feb", "mar", "apr", "may", "jun",
@@ -811,16 +815,18 @@ def datetime_to_grass_datetime_string(dt):
 
     # Check for time zone info in the datetime object
     if dt.tzinfo is not None:
-        
+
         tz = dt.tzinfo.utcoffset(0)
         if tz.seconds > 86400 / 2:
             tz = (tz.seconds - 86400) / 60
         else:
             tz = tz.seconds/60
-            
+
         string = "%.2i %s %.2i %.2i:%.2i:%.2i %+.4i" % (dt.day,
-                 month_names[dt.month], dt.year,
-                 dt.hour, dt.minute, dt.second, tz)
+                                                        month_names[dt.month],
+                                                        dt.year, dt.hour,
+                                                        dt.minute, dt.second,
+                                                        tz)
     else:
         string = "%.2i %s %.4i %.2i:%.2i:%.2i" % (dt.day, month_names[
             dt.month], dt.year, dt.hour, dt.minute, dt.second)
@@ -828,6 +834,32 @@ def datetime_to_grass_datetime_string(dt):
     return string
 
 ###############################################################################
+suffix_units = {"years": "%Y",
+                "year": "%Y",
+                "months": "%Y_%m",
+                "month": "%Y_%m",
+                "weeks": "%Y_%m_%d",
+                "week": "%Y_%m_%d",
+                "days": "%Y_%m_%d",
+                "day": "%Y_%m_%d",
+                "hours": "%Y_%m_%d_%H",
+                "hour": "%Y_%m_%d_%H",
+                "minutes": "%Y_%m_%d_%H_%M",
+                "minute": "%Y_%m_%d_%H_%M"}
+
+
+def create_suffix_from_datetime(start_time,  granularity):
+    """Create a datetime string based on a datetime object and a provided
+       granularity that can be used as suffix for map names.
+
+       dateteime=2001-01-01 00:00:00, granularity="1 month" returns "2001_01"
+
+       :param start_time: The datetime object
+       :param granularity: The granularity for example "1 month" or "100 seconds"
+       :return: A string
+    """
+    global suffix_units
+    return start_time.strftime(suffix_units[granularity.split(' ')[1]])
 
 if __name__ == "__main__":
     import doctest

+ 37 - 38
lib/python/temporal/extract.py

@@ -1,15 +1,12 @@
-"""!@package grass.temporal
-
-@brief GRASS Python scripting module (temporal GIS functions)
-
-Temporal GIS related functions to be used in Python scripts.
+"""
+Extract functions for space time raster, 3d raster and vector datasets
 
 (C) 2012-2013 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
+:authors: Soeren Gebbert
 """
 
 from grass.script.utils import get_num_suffix
@@ -25,28 +22,28 @@ from grass.exceptions import CalledModuleError
 def extract_dataset(input, output, type, where, expression, base, nprocs=1,
                     register_null=False, layer=1,
                     vtype="point,line,boundary,centroid,area,face"):
-    """!Extract a subset of a space time raster, raster3d or vector dataset
+    """Extract a subset of a space time raster, raster3d or vector dataset
 
        A mapcalc expression can be provided to process the temporal extracted
        maps.
        Mapcalc expressions are supported for raster and raster3d maps.
 
-       @param input The name of the input space time raster/raster3d dataset
-       @param output The name of the extracted new space time raster/raster3d
+       :param input: The name of the input space time raster/raster3d dataset
+       :param output: The name of the extracted new space time raster/raster3d
                      dataset
-       @param type The type of the dataset: "raster", "raster3d" or vector
-       @param where The temporal SQL WHERE statement for subset extraction
-       @param expression The r(3).mapcalc expression or the v.extract where
+       :param type: The type of the dataset: "raster", "raster3d" or vector
+       :param where: The temporal SQL WHERE statement for subset extraction
+       :param expression: The r(3).mapcalc expression or the v.extract where
                          statement
-       @param base The base name of the new created maps in case a mapclac
+       :param base: The base name of the new created maps in case a mapclac
                    expression is provided
-       @param nprocs The number of parallel processes to be used for mapcalc
+       :param nprocs: The number of parallel processes to be used for mapcalc
                      processing
-       @param register_null Set this number True to register empty maps
+       :param register_null: Set this number True to register empty maps
                             (only raster and raster3d maps)
-       @param layer The vector layer number to be used when no timestamped
+       :param layer: The vector layer number to be used when no timestamped
               layer is present, default is 1
-       @param vtype The feature type to be extracted for vector maps, default
+       :param vtype: The feature type to be extracted for vector maps, default
               is point,line,boundary,centroid,area and face
     """
 
@@ -61,10 +58,9 @@ def extract_dataset(input, output, type, where, expression, base, nprocs=1,
     dbif = SQLDatabaseInterfaceConnection()
     dbif.connect()
 
-    sp = open_old_space_time_dataset(input, type, dbif)
+    sp = open_old_stds(input, type, dbif)
     # Check the new stds
-    new_sp = check_new_space_time_dataset(output, type, dbif,
-                                          gscript.overwrite())
+    new_sp = check_new_stds(output, type, dbif, gscript.overwrite())
     if type == "vector":
         rows = sp.get_registered_maps(
             "id,name,mapset,layer", where, "start_time", dbif)
@@ -90,7 +86,8 @@ def extract_dataset(input, output, type, where, expression, base, nprocs=1,
                     msgr.percent(count, num_rows, 1)
 
                 map_name = "{base}_{suffix}".format(base=base,
-                                                    suffix=get_num_suffix(count, num_rows))
+                                                    suffix=get_num_suffix(count,
+                                                                          num_rows))
 
                 # We need to modify the r(3).mapcalc expression
                 if type != "vector":
@@ -102,7 +99,8 @@ def extract_dataset(input, output, type, where, expression, base, nprocs=1,
                     # We need to build the id
                     map_id = AbstractMapDataset.build_id(map_name, mapset)
                 else:
-                    map_id = AbstractMapDataset.build_id(map_name, mapset, row["layer"])
+                    map_id = AbstractMapDataset.build_id(map_name, mapset,
+                                                         row["layer"])
 
                 new_map = sp.get_new_map_instance(map_id)
 
@@ -134,16 +132,16 @@ def extract_dataset(input, output, type, where, expression, base, nprocs=1,
                                  % expression)
                     if row["layer"]:
                         proc_list.append(Process(target=run_vector_extraction,
-                                                 args=(row["name"] + "@" + \
-                                                       row["mapset"],
-                                                 map_name, row["layer"],
-                                                 vtype, expression)))
+                                                 args=(row["name"] + "@" +
+                                                       row["mapset"], map_name,
+                                                       row["layer"], vtype,
+                                                       expression)))
                     else:
                         proc_list.append(Process(target=run_vector_extraction,
-                                                 args=(row["name"] + "@" + \
-                                                       row["mapset"],
-                                                 map_name, layer, vtype,
-                                                 expression)))
+                                                 args=(row["name"] + "@" +
+                                                       row["mapset"], map_name,
+                                                       layer, vtype,
+                                                       expression)))
 
                 proc_list[proc_count].start()
                 proc_count += 1
@@ -169,11 +167,9 @@ def extract_dataset(input, output, type, where, expression, base, nprocs=1,
         msgr.percent(0, num_rows, 1)
 
         temporal_type, semantic_type, title, description = sp.get_initial_values()
-        new_sp = open_new_space_time_dataset(output, type,
-                                             sp.get_temporal_type(),
-                                             title, description,
-                                             semantic_type, dbif,
-                                             gscript.overwrite())
+        new_sp = open_new_stds(output, type, sp.get_temporal_type(), title, 
+                               description, semantic_type, dbif,
+                               gscript.overwrite())
 
         # collect empty maps to remove them
         empty_maps = []
@@ -238,11 +234,14 @@ def extract_dataset(input, output, type, where, expression, base, nprocs=1,
                     names += ",%s" % (map.get_name())
                 count += 1
             if type == "raster":
-                gscript.run_command("g.remove", type='rast', name=names, quiet=True, flags='f')
+                gscript.run_command("g.remove", flags='f', type='rast',
+                                    name=names, quiet=True)
             elif type == "raster3d":
-                gscript.run_command("g.remove", type='rast3d', name=names, quiet=True, flags='f')
+                gscript.run_command("g.remove", flags='f', type='rast3d',
+                                    name=names, quiet=True)
             elif type == "vector":
-                gscript.run_command("g.remove", type='vect', name=names, quiet=True, flags='f')
+                gscript.run_command("g.remove", flags='f', type='vect',
+                                    name=names, quiet=True)
 
     dbif.close()
 

+ 10 - 15
lib/python/temporal/factory.py

@@ -1,25 +1,21 @@
-"""!@package grass.temporal
-
-@brief GRASS Python scripting module (temporal GIS functions)
-
-Temporal GIS related functions to be used in Python scripts.
+"""
+Object factory
 
 Usage:
 
-@code
-import grass.temporal as tgis
+.. code-block:: python
 
-tgis.register_maps_in_space_time_dataset(type, name, maps)
+    import grass.temporal as tgis
+
+    tgis.register_maps_in_space_time_dataset(type, name, maps)
 
-...
-@endcode
 
 (C) 2012-2013 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
+:authors: Soeren Gebbert
 """
 
 from space_time_datasets import *
@@ -28,11 +24,11 @@ from space_time_datasets import *
 
 
 def dataset_factory(type, id):
-    """!A factory functions to create space time or map datasets
+    """A factory functions to create space time or map datasets
 
-       @param type the dataset type: rast or raster, rast3d,
+       :param type: the dataset type: rast or raster, rast3d,
                     vect or vector, strds, str3ds, stvds
-       @param id The id of the dataset ("name@mapset")
+       :param id: The id of the dataset ("name@mapset")
     """
     if type == "strds":
         sp = SpaceTimeRasterDataset(id)
@@ -52,4 +48,3 @@ def dataset_factory(type, id):
         return None
 
     return sp
-

+ 45 - 41
lib/python/temporal/gui_support.py

@@ -1,8 +1,5 @@
-"""!@package grass.temporal
-
-@brief GRASS Python scripting module (temporal GIS functions)
-
-Temporal GIS related functions to be used in Python scripts.
+"""
+GUI support functions
 
 
 (C) 2008-2011 by the GRASS Development Team
@@ -10,34 +7,36 @@ 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
+:authors: Soeren Gebbert
 """
 
 from space_time_datasets import *
 from factory import *
+import grass.script as gscript
 
 ###############################################################################
 
-def tlist_grouped(type, group_type = False, dbif=None):
-    """!List of temporal elements grouped by mapsets.
 
-    Returns a dictionary where the keys are mapset 
+def tlist_grouped(type, group_type=False, dbif=None):
+    """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
+    .. code-block:: python
 
-    @return directory of mapsets/elements
+        >>> tgis.tlist_grouped('strds')['PERMANENT']
+        ['precipitation', 'temperature']
+
+    :param type: element type (strds, str3ds, stvds)
+    :param group_type: TBD
+
+    :return: directory of mapsets/elements
     """
     result = {}
     dbif, connected = init_dbif(dbif)
-    
+
     mapset = None
     if type == 'stds':
         types = ['strds', 'str3ds', 'stvds']
@@ -46,7 +45,7 @@ def tlist_grouped(type, group_type = False, dbif=None):
     for type in types:
         try:
             tlist_result = tlist(type=type, dbif=dbif)
-        except core.ScriptError as e:
+        except gscript.ScriptError as e:
             warning(e)
             continue
 
@@ -66,7 +65,7 @@ def tlist_grouped(type, group_type = False, dbif=None):
             if group_type:
                 if type in result[mapset]:
                     result[mapset][type].append(name)
-                else:        
+                else:
                     result[mapset][type] = [name, ]
             else:
                 result[mapset].append(name)
@@ -78,37 +77,42 @@ def tlist_grouped(type, group_type = False, dbif=None):
 
 ###############################################################################
 
+
 def tlist(type, dbif=None):
-    """!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 datasets of absolute and relative time
+
+    :param type: element type (strds, str3ds, stvds)
 
-    @return a list of space time dataset ids
+    :return: a list of space time dataset ids
     """
     id = None
     sp = dataset_factory(type, id)
     dbif, connected = init_dbif(dbif)
 
+    mapsets = get_available_temporal_mapsets()
+
     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))
+        # For each available mapset
+        for mapset in mapsets.keys():
+            # 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.execute(sql,  mapset=mapset)
+            rows = dbif.fetchall(mapset=mapset)
+
+            # Append the ids of the space time datasets
+            for row in rows:
+                for col in row:
+                    output.append(str(col))
 
     if connected is True:
         dbif.close()

+ 92 - 79
lib/python/temporal/list_stds.py

@@ -1,25 +1,21 @@
-"""!@package grass.temporal
-
-@brief GRASS Python scripting module (temporal GIS functions)
-
-Temporal GIS related functions to be used in Python scripts.
+"""
+Functions to create space time dataset lists
 
 Usage:
 
-@code
-import grass.temporal as tgis
+.. code-block:: python
+
+    import grass.temporal as tgis
 
-tgis.register_maps_in_space_time_dataset(type, name, maps)
+    tgis.register_maps_in_space_time_dataset(type, name, maps)
 
-...
-@endcode
 
 (C) 2012-2013 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
+:authors: Soeren Gebbert
 """
 
 from space_time_datasets import *
@@ -28,54 +24,62 @@ from open_stds import *
 
 ###############################################################################
 
-def get_dataset_list(type,  temporal_type,  columns=None,  where=None,  order=None):
-    """! Return a list of time stamped maps or space time datasets of a specific temporal type
-         that are registred in the temporal database
-    
-         This method returns a dictionary, the keys are the available mapsets, 
-         the values are the rows from the SQL database query.
-
-        @param type The type of the datasets (strds, str3ds, stvds, rast, rast3d, vect)
-        @param temporal_type The temporal type of the datasets (absolute, relative)
-        @param columns A comma separated list of columns that will be selected
-        @param where A where statement for selected listing without "WHERE"
-        @param order A comma separated list of columns to order the
-                               datasets by category
-                      
-        @return A dictionary with the rows of the SQL query for each available mapset
-        
-        >>> import grass.temporal as tgis
-        >>> tgis.init()
-        >>> name = "list_stds_test"
-        >>> sp = tgis.open_new_space_time_dataset(name=name, type="strds", 
-        ... temporaltype="absolute", title="title", descr="descr", semantic="mean", dbif=None, overwrite=True)
-        >>> mapset = tgis.get_current_mapset()
-        >>> stds_list = tgis.get_dataset_list("strds", "absolute", columns="name")
-        >>> rows =  stds_list[mapset]
-        >>> for row in rows:
-        ...     if row["name"] == name:
-        ...         print True
-        True
-        >>> stds_list = tgis.get_dataset_list("strds", "absolute", columns="name,mapset", where="mapset = '%s'"%(mapset))
-        >>> rows =  stds_list[mapset]
-        >>> for row in rows:
-        ...     if row["name"] == name and row["mapset"] == mapset:
-        ...         print True
-        True
-        >>> check = sp.delete()
+
+def get_dataset_list(type, temporal_type, columns=None, where=None,
+                     order=None):
+    """ Return a list of time stamped maps or space time datasets of a specific
+        temporal type that are registred in the temporal database
+
+        This method returns a dictionary, the keys are the available mapsets,
+        the values are the rows from the SQL database query.
+
+        :param type: The type of the datasets (strds, str3ds, stvds, rast,
+                     rast3d, vect)
+        :param temporal_type: The temporal type of the datasets (absolute,
+                              relative)
+        :param columns: A comma separated list of columns that will be selected
+        :param where: A where statement for selected listing without "WHERE"
+        :param order: A comma separated list of columns to order the
+                      datasets by category
+
+        :return: A dictionary with the rows of the SQL query for each
+                 available mapset
+
+        .. code-block:: python
+
+            >>> import grass.temporal as tgis
+            >>> tgis.init()
+            >>> name = "list_stds_test"
+            >>> sp = tgis.open_new_stds(name=name, type="strds",
+            ... temporaltype="absolute", title="title", descr="descr", semantic="mean", dbif=None, overwrite=True)
+            >>> mapset = tgis.get_current_mapset()
+            >>> stds_list = tgis.get_dataset_list("strds", "absolute", columns="name")
+            >>> rows =  stds_list[mapset]
+            >>> for row in rows:
+            ...     if row["name"] == name:
+            ...         print True
+            True
+            >>> stds_list = tgis.get_dataset_list("strds", "absolute", columns="name,mapset", where="mapset = '%s'"%(mapset))
+            >>> rows =  stds_list[mapset]
+            >>> for row in rows:
+            ...     if row["name"] == name and row["mapset"] == mapset:
+            ...         print True
+            True
+            >>> check = sp.delete()
+
     """
     id = None
     sp = dataset_factory(type, id)
 
     dbif = SQLDatabaseInterfaceConnection()
     dbif.connect()
-    
-    mapsets = get_tgis_c_library_interface().available_mapsets()
-    
+
+    mapsets = get_available_temporal_mapsets()
+
     result = {}
-    
-    for mapset in mapsets:
-        
+
+    for mapset in mapsets.keys():
+
         if temporal_type == "absolute":
             table = sp.get_type() + "_view_abs_time"
         else:
@@ -88,54 +92,59 @@ def get_dataset_list(type,  temporal_type,  columns=None,  where=None,  order=No
 
         if where:
             sql += " WHERE " + where
-            sql += " AND mapset = '%s'"%(mapset)
+            sql += " AND mapset = '%s'" % (mapset)
         else:
-            sql += " WHERE mapset = '%s'"%(mapset)
+            sql += " WHERE mapset = '%s'" % (mapset)
 
         if order:
             sql += " ORDER BY " + order
 
-        dbif.cursor.execute(sql)
-        rows = dbif.cursor.fetchall()
-        
+        dbif.execute(sql,  mapset=mapset)
+        rows = dbif.fetchall(mapset=mapset)
+
         if rows:
             result[mapset] = rows
-        
+
     return result
-        
+
 ###############################################################################
 
-def list_maps_of_stds(type, input, columns, order, where, separator, method, no_header=False, 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
+def list_maps_of_stds(type, input, columns, order, where, separator,
+                      method, no_header=False, 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
                       maps by category
-        @param where A where statement for selected listing without "WHERE"
+        :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,
+        :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
+               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"
+              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 no_header Supress the printing of 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
+              columns are identical to deltagaps
+
+        :param no_header: Supress the printing of 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
     """
 
     dbif, connected = init_dbif(None)
     msgr = get_tgis_message_interface()
 
-    sp = open_old_space_time_dataset(input, type, dbif)
+    sp = open_old_stds(input, type, dbif)
 
     if separator is None or separator == "":
         separator = "\t"
@@ -147,12 +156,16 @@ def list_maps_of_stds(type, input, columns, order, where, separator, method, no_
         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)
+            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)
+            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)
+                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)
 

+ 77 - 78
lib/python/temporal/mapcalc.py

@@ -1,15 +1,12 @@
-"""!@package grass.temporal
-
-@brief GRASS Python scripting module (temporal GIS functions)
-
-Temporal GIS related functions to be used in Python scripts.
+"""
+Raster and 3d raster mapcalculation functions
 
 (C) 2012-2013 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
+:authors: Soeren Gebbert
 """
 
 from space_time_datasets import *
@@ -23,7 +20,7 @@ from grass.exceptions import CalledModuleError
 
 def dataset_mapcalculator(inputs, output, type, expression, base, method,
                           nprocs=1, register_null=False, spatial=False):
-    """!Perform map-calculations of maps from different space time
+    """Perform map-calculations of maps from different space time
        raster/raster3d datasets, using a specific sampling method
        to select temporal related maps.
 
@@ -32,6 +29,7 @@ def dataset_mapcalculator(inputs, output, type, expression, base, method,
        the r.mapcalc operators:
 
        Supported operators for relative and absolute time are:
+
        - td() - the time delta of the current interval in days
                 and fractions of days or the unit in case of relative time
        - start_time() - The start time of the interval from the begin of
@@ -42,6 +40,7 @@ def dataset_mapcalculator(inputs, output, type, expression, base, method,
                       unit in case of relative time
 
        Supported operators for absolute time:
+
        - start_doy() - Day of year (doy) from the start time [1 - 366]
        - start_dow() - Day of week (dow) from the start time [1 - 7],
                        the start of the week is monday == 1
@@ -64,17 +63,17 @@ def dataset_mapcalculator(inputs, output, type, expression, base, method,
        - end_minute() - The minute of the end time [0 - 59]
        - end_second() - The minute of the end time [0 - 59]
 
-       @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 type The type of the dataset: "raster" or "raster3d"
-       @param expression The r(3).mapcalc expression
-       @param base The base name of the new created maps in case a
+       :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 type: The type of the dataset: "raster" or "raster3d"
+       :param expression: The r(3).mapcalc expression
+       :param base: The base name of the new created maps in case a
               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 method: The method to be used for temporal sampling
+       :param nprocs: The number of parallel processes to be used for
               mapcalc processing
-       @param register_null Set this number True to register empty maps
-       @param spatial Check spatial overlap
+       :param register_null: Set this number True to register empty maps
+       :param spatial: Check spatial overlap
     """
 
     # We need a database interface for fast computation
@@ -86,7 +85,7 @@ def dataset_mapcalculator(inputs, output, type, expression, base, method,
 
     input_name_list = inputs.split(",")
 
-    first_input = open_old_space_time_dataset(input_name_list[0], type, dbif)
+    first_input = open_old_stds(input_name_list[0], type, dbif)
 
     # All additional inputs in reverse sorted order to avoid
     # wrong name substitution
@@ -96,11 +95,10 @@ def dataset_mapcalculator(inputs, output, type, expression, base, method,
     input_list = []
 
     for input in input_name_list:
-        sp = open_old_space_time_dataset(input, type, dbif)
+        sp = open_old_stds(input, type, dbif)
         input_list.append(copy.copy(sp))
 
-    new_sp = check_new_space_time_dataset(output, type, dbif,
-                                         gscript.overwrite())
+    new_sp = check_new_stds(output, type, dbif, gscript.overwrite())
 
     # Sample all inputs by the first input and create a sample matrix
     if spatial:
@@ -284,10 +282,8 @@ def dataset_mapcalculator(inputs, output, type, expression, base, method,
 
         temporal_type, semantic_type, title, description = first_input.get_initial_values()
 
-        new_sp = open_new_space_time_dataset(output, type,
-                                         temporal_type, title, description,
-                                         semantic_type, dbif,
-                                         gscript.overwrite())
+        new_sp = open_new_stds(output, type, temporal_type, title, description,
+                               semantic_type, dbif, gscript.overwrite())
         count = 0
 
         # collect empty maps to remove them
@@ -332,9 +328,11 @@ def dataset_mapcalculator(inputs, output, type, expression, base, method,
                     names += ",%s" % (map.get_name())
                 count += 1
             if type == "raster":
-                gscript.run_command("g.remove", type='rast', name=names, quiet=True, flags='f')
+                gscript.run_command("g.remove", flags='f', type='rast',
+                                    name=names, quiet=True)
             elif type == "raster3d":
-                gscript.run_command("g.remove", type='rast3d', name=names, quiet=True, flags='f')
+                gscript.run_command("g.remove", flags='f', type='rast3d',
+                                    name=names, quiet=True)
 
     dbif.close()
 
@@ -368,37 +366,38 @@ def _operator_parser(expr, first, current):
        the temporal operators with numerical values.
 
        Supported operators for relative and absolute time are:
-       * td() - the time delta of the current interval in days
+
+       - td() - the time delta of the current interval in days
          and fractions of days or the unit in case of relative time
-       * start_time() - The start time of the interval from the begin of the
+       - start_time() - The start time of the interval from the begin of the
                         time series in days and fractions of days or the unit
                         in case of relative time
-       * end_time() - The end time of the current interval from the begin of
+       - end_time() - The end time of the current interval from the begin of
                       the time series in days and fractions of days or the
                       unit in case of relative time
 
        Supported operators for absolute time:
-       * start_doy() - Day of year (doy) from the start time [1 - 366]
-       * start_dow() - Day of week (dow) from the start time [1 - 7],
+
+       - start_doy() - Day of year (doy) from the start time [1 - 366]
+       - start_dow() - Day of week (dow) from the start time [1 - 7],
                        the start of the week is monday == 1
-       * start_year() - The year of the start time [0 - 9999]
-       * start_month() - The month of the start time [1 - 12]
-       * start_week() - Week of year of the start time [1 - 54]
-       * start_day() - Day of month from the start time [1 - 31]
-       * start_hour() - The hour of the start time [0 - 23]
-       * start_minute() - The minute of the start time [0 - 59]
-       * start_second() - The second of the start time [0 - 59]
-
-       * end_doy() - Day of year (doy) from the end time [1 - 366]
-       * end_dow() - Day of week (dow) from the end time [1 - 7],
+       - start_year() - The year of the start time [0 - 9999]
+       - start_month() - The month of the start time [1 - 12]
+       - start_week() - Week of year of the start time [1 - 54]
+       - start_day() - Day of month from the start time [1 - 31]
+       - start_hour() - The hour of the start time [0 - 23]
+       - start_minute() - The minute of the start time [0 - 59]
+       - start_second() - The second of the start time [0 - 59]
+       - end_doy() - Day of year (doy) from the end time [1 - 366]
+       - end_dow() - Day of week (dow) from the end time [1 - 7],
                      the start of the week is monday == 1
-       * end_year() - The year of the end time [0 - 9999]
-       * end_month() - The month of the end time [1 - 12]
-       * end_week() - Week of year of the end time [1 - 54]
-       * end_day() - Day of month from the end time [1 - 31]
-       * end_hour() - The hour of the end time [0 - 23]
-       * end_minute() - The minute of the end time [0 - 59]
-       * end_second() - The minute of the end time [0 - 59]
+       - end_year() - The year of the end time [0 - 9999]
+       - end_month() - The month of the end time [1 - 12]
+       - end_week() - Week of year of the end time [1 - 54]
+       - end_day() - Day of month from the end time [1 - 31]
+       - end_hour() - The hour of the end time [0 - 23]
+       - end_minute() - The minute of the end time [0 - 59]
+       - end_second() - The minute of the end time [0 - 59]
 
        The modified expression is returned.
 
@@ -419,16 +418,16 @@ def _operator_parser(expr, first, current):
 def _parse_start_operators(expr, is_time_absolute, current):
     """
        Supported operators for absolute time:
-       * start_doy() - Day of year (doy) from the start time [1 - 366]
-       * start_dow() - Day of week (dow) from the start time [1 - 7],
+       - start_doy() - Day of year (doy) from the start time [1 - 366]
+       - start_dow() - Day of week (dow) from the start time [1 - 7],
                        the start of the week is monday == 1
-       * start_year() - The year of the start time [0 - 9999]
-       * start_month() - The month of the start time [1 - 12]
-       * start_week() - Week of year of the start time [1 - 54]
-       * start_day() - Day of month from the start time [1 - 31]
-       * start_hour() - The hour of the start time [0 - 23]
-       * start_minute() - The minute of the start time [0 - 59]
-       * start_second() - The second of the start time [0 - 59]
+       - start_year() - The year of the start time [0 - 9999]
+       - start_month() - The month of the start time [1 - 12]
+       - start_week() - Week of year of the start time [1 - 54]
+       - start_day() - Day of month from the start time [1 - 31]
+       - start_hour() - The hour of the start time [0 - 23]
+       - start_minute() - The minute of the start time [0 - 59]
+       - start_second() - The second of the start time [0 - 59]
     """
 
     start, end = current.get_absolute_time()
@@ -436,55 +435,55 @@ def _parse_start_operators(expr, is_time_absolute, current):
 
     if expr.find("start_year()") >= 0:
         if not is_time_absolute:
-            msgr.fatal(_("The temporal operators <%s> support only absolute "\
+            msgr.fatal(_("The temporal operators <%s> support only absolute "
                          "time." % ("start_*")))
         expr = expr.replace("start_year()", str(start.year))
 
     if expr.find("start_month()") >= 0:
         if not is_time_absolute:
-            msgr.fatal(_("The temporal operators <%s> support only absolute "\
+            msgr.fatal(_("The temporal operators <%s> support only absolute "
                          "time." % ("start_*")))
         expr = expr.replace("start_month()", str(start.month))
 
     if expr.find("start_week()") >= 0:
         if not is_time_absolute:
-            msgr.fatal(_("The temporal operators <%s> support only absolute "\
+            msgr.fatal(_("The temporal operators <%s> support only absolute "
                          "time." % ("start_*")))
         expr = expr.replace("start_week()", str(start.isocalendar()[1]))
 
     if expr.find("start_day()") >= 0:
         if not is_time_absolute:
-            msgr.fatal(_("The temporal operators <%s> support only absolute "\
+            msgr.fatal(_("The temporal operators <%s> support only absolute "
                          "time." % ("start_*")))
         expr = expr.replace("start_day()", str(start.day))
 
     if expr.find("start_hour()") >= 0:
         if not is_time_absolute:
-            msgr.fatal(_("The temporal operators <%s> support only absolute "\
+            msgr.fatal(_("The temporal operators <%s> support only absolute "
                          "time." % ("start_*")))
         expr = expr.replace("start_hour()", str(start.hour))
 
     if expr.find("start_minute()") >= 0:
         if not is_time_absolute:
-            msgr.fatal(_("The temporal operators <%s> support only absolute "\
+            msgr.fatal(_("The temporal operators <%s> support only absolute "
                          "time." % ("start_*")))
         expr = expr.replace("start_minute()", str(start.minute))
 
     if expr.find("start_second()") >= 0:
         if not is_time_absolute:
-            msgr.fatal(_("The temporal operators <%s> support only absolute "\
+            msgr.fatal(_("The temporal operators <%s> support only absolute "
                          "time." % ("start_*")))
         expr = expr.replace("start_second()", str(start.second))
 
     if expr.find("start_dow()") >= 0:
         if not is_time_absolute:
-            msgr.fatal(_("The temporal operators <%s> support only absolute "\
+            msgr.fatal(_("The temporal operators <%s> support only absolute "
                          "time." % ("start_*")))
         expr = expr.replace("start_dow()", str(start.isoweekday()))
 
     if expr.find("start_doy()") >= 0:
         if not is_time_absolute:
-            msgr.fatal(_("The temporal operators <%s> support only absolute "\
+            msgr.fatal(_("The temporal operators <%s> support only absolute "
                          "time." % ("start_*")))
         year = datetime(start.year, 1, 1)
         delta = start - year
@@ -510,7 +509,7 @@ def _parse_end_operators(expr, is_time_absolute, current):
        - end_minute() - The minute of the end time [0 - 59]
        - end_second() - The minute of the end time [0 - 59]
 
-       In case of time instances the end_* expression will be replaced by
+       In case of time instances the end* expression will be replaced by
        null()
     """
 
@@ -519,7 +518,7 @@ def _parse_end_operators(expr, is_time_absolute, current):
 
     if expr.find("end_year()") >= 0:
         if not is_time_absolute:
-            msgr.fatal(_("The temporal operators <%s> support only absolute "\
+            msgr.fatal(_("The temporal operators <%s> support only absolute "
                          "time." % ("end_*")))
         if not end:
             expr = expr.replace("end_year()", "null()")
@@ -528,7 +527,7 @@ def _parse_end_operators(expr, is_time_absolute, current):
 
     if expr.find("end_month()") >= 0:
         if not is_time_absolute:
-            msgr.fatal(_("The temporal operators <%s> support only absolute "\
+            msgr.fatal(_("The temporal operators <%s> support only absolute "
                          "time." % ("end_*")))
         if not end:
             expr = expr.replace("end_month()", "null()")
@@ -537,7 +536,7 @@ def _parse_end_operators(expr, is_time_absolute, current):
 
     if expr.find("end_week()") >= 0:
         if not is_time_absolute:
-            msgr.fatal(_("The temporal operators <%s> support only absolute "\
+            msgr.fatal(_("The temporal operators <%s> support only absolute "
                          "time." % ("end_*")))
         if not end:
             expr = expr.replace("end_week()", "null()")
@@ -546,7 +545,7 @@ def _parse_end_operators(expr, is_time_absolute, current):
 
     if expr.find("end_day()") >= 0:
         if not is_time_absolute:
-            msgr.fatal(_("The temporal operators <%s> support only absolute "\
+            msgr.fatal(_("The temporal operators <%s> support only absolute "
                          "time." % ("end_*")))
         if not end:
             expr = expr.replace("end_day()", "null()")
@@ -555,7 +554,7 @@ def _parse_end_operators(expr, is_time_absolute, current):
 
     if expr.find("end_hour()") >= 0:
         if not is_time_absolute:
-            msgr.fatal(_("The temporal operators <%s> support only absolute "\
+            msgr.fatal(_("The temporal operators <%s> support only absolute "
                          "time." % ("end_*")))
         if not end:
             expr = expr.replace("end_hour()", "null()")
@@ -564,7 +563,7 @@ def _parse_end_operators(expr, is_time_absolute, current):
 
     if expr.find("end_minute()") >= 0:
         if not is_time_absolute:
-            msgr.fatal(_("The temporal operators <%s> support only absolute "\
+            msgr.fatal(_("The temporal operators <%s> support only absolute "
                          "time." % ("end_*")))
         if not end:
             expr = expr.replace("end_minute()", "null()")
@@ -573,7 +572,7 @@ def _parse_end_operators(expr, is_time_absolute, current):
 
     if expr.find("end_second()") >= 0:
         if not is_time_absolute:
-            msgr.fatal(_("The temporal operators <%s> support only absolute "\
+            msgr.fatal(_("The temporal operators <%s> support only absolute "
                          "time." % ("end_*")))
         if not end:
             expr = expr.replace("end_second()", "null()")
@@ -582,7 +581,7 @@ def _parse_end_operators(expr, is_time_absolute, current):
 
     if expr.find("end_dow()") >= 0:
         if not is_time_absolute:
-            msgr.fatal(_("The temporal operators <%s> support only absolute "\
+            msgr.fatal(_("The temporal operators <%s> support only absolute "
                          "time." % ("end_*")))
         if not end:
             expr = expr.replace("end_dow()", "null()")
@@ -591,7 +590,7 @@ def _parse_end_operators(expr, is_time_absolute, current):
 
     if expr.find("end_doy()") >= 0:
         if not is_time_absolute:
-            msgr.fatal(_("The temporal operators <%s> support only absolute "\
+            msgr.fatal(_("The temporal operators <%s> support only absolute "
                          "time." % ("end_*")))
         if not end:
             expr = expr.replace("end_doy()", "null()")
@@ -618,11 +617,11 @@ def _parse_td_operator(expr, is_time_absolute, first, current):
         td = "null()"
         if is_time_absolute:
             start, end = current.get_absolute_time()
-            if end != None:
+            if end is not None:
                 td = time_delta_to_relative_time(end - start)
         else:
             start, end, unit = current.get_relative_time()
-            if end != None:
+            if end is not None:
                 td = end - start
         expr = expr.replace("td()", str(td))
 

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 671 - 678
lib/python/temporal/metadata.py


+ 69 - 66
lib/python/temporal/open_stds.py

@@ -1,44 +1,44 @@
-"""!@package grass.temporal
-
-@brief GRASS Python scripting module (temporal GIS functions)
-
-Temporal GIS related functions to be used in Python scripts.
+"""
+Functions to open or create space time datasets
 
 Usage:
 
-@code
-import grass.temporal as tgis
+.. code-block:: python
 
-tgis.register_maps_in_space_time_dataset(type, name, maps)
+    import grass.temporal as tgis
+
+    tgis.register_maps_in_space_time_dataset(type, name, maps)
 
-...
-@endcode
 
 (C) 2012-2014 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
+:authors: Soeren Gebbert
 """
 
 from factory import *
 
 ###############################################################################
 
-def open_old_space_time_dataset(name, type, dbif=None):
-    """!This function opens an existing space time dataset and return the
+
+def open_old_stds(name, type, dbif=None):
+    """This function opens an existing space time dataset and return the
        created and intialized object of the specified type.
 
-       This function will call exit() or raise a grass.pygrass.messages.FatalError in case the type is wrong,
+       This function will call exit() or raise a
+       grass.pygrass.messages.FatalError in case the type is wrong,
        or the space time dataset was not found.
 
-       @param name The name of the space time dataset, if the name does not
+       :param name: The name of the space time dataset, if the name does not
                     contain the mapset (name@mapset) then the current mapset
                     will be used to identifiy the space time dataset
-       @param type The type of the space time dataset (strd, str3ds, stvds,
-                                                       raster, vector, raster3d)
-       @param dbif The optional database interface to be used
+       :param type: The type of the space time dataset (strd, str3ds, stvds,
+                    raster, vector, raster3d)
+       :param dbif: The optional database interface to be used
+       
+       :return: New stds object
 
     """
     mapset = get_current_mapset()
@@ -64,8 +64,8 @@ def open_old_space_time_dataset(name, type, dbif=None):
     if not sp.is_in_db(dbif):
         dbif.close()
         msgr.fatal(_("Space time %(sp)s dataset <%(name)s> no found") %
-                     {'sp': sp.get_new_map_instance(None).get_type(),
-                      'name': name})
+                   {'sp': sp.get_new_map_instance(None).get_type(),
+                    'name': name})
 
     # Read content from temporal database
     sp.select(dbif)
@@ -76,22 +76,23 @@ def open_old_space_time_dataset(name, type, dbif=None):
 
 ###############################################################################
 
-def check_new_space_time_dataset(name, type, dbif=None, overwrite=False):
-    """!Check if a new space time dataset of a specific type can be created
 
-       @param name The name of the new space time dataset
-       @param type The type of the new space time dataset (strd, str3ds, stvds,
-                                                      raster, vector, raster3d)
-       @param dbif The temporal database interface to be used
-       @param overwrite Flag to allow overwriting
+def check_new_stds(name, type, dbif=None, overwrite=False):
+    """Check if a new space time dataset of a specific type can be created
+
+       :param name: The name of the new space time dataset
+       :param type: The type of the new space time dataset (strd, str3ds,
+                    stvds, raster, vector, raster3d)
+       :param dbif: The temporal database interface to be used
+       :param overwrite: Flag to allow overwriting
 
-       @return A space time dataset object that must be filled with
+       :return: A space time dataset object that must be filled with
                content before insertion in the temporal database
 
-       This function will raise a ScriptError in case of an error.
+       This function will raise a FatalError in case of an error.
     """
 
-    #Get the current mapset to create the id of the space time dataset
+    # Get the current mapset to create the id of the space time dataset
 
     mapset = get_current_mapset()
     msgr = get_tgis_message_interface()
@@ -119,9 +120,9 @@ def check_new_space_time_dataset(name, type, dbif=None, overwrite=False):
 
     if sp.is_in_db(dbif) and overwrite is False:
         msgr.fatal(_("Space time %(sp)s dataset <%(name)s> is already in the"
-                      " database. Use the overwrite flag.") % {
-                      'sp': sp.get_new_map_instance(None).get_type(),
-                      'name': name})
+                     " database. Use the overwrite flag.") % {
+                   'sp': sp.get_new_map_instance(None).get_type(),
+                   'name': name})
     if connected:
         dbif.close()
 
@@ -129,39 +130,40 @@ def check_new_space_time_dataset(name, type, dbif=None, overwrite=False):
 
 ###############################################################################
 
-def open_new_space_time_dataset(name, type, temporaltype, title, descr, semantic,
-                              dbif=None, overwrite=False):
-    """!Create a new space time dataset of a specific type
 
-       @param name The name of the new space time dataset
-       @param type The type of the new space time dataset (strd, str3ds, stvds,
-                                                      raster, vector, raster3d)
-       @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
+def open_new_stds(name, type, temporaltype, title, descr, semantic,
+                  dbif=None, overwrite=False):
+    """Create a new space time dataset of a specific type
+
+       :param name: The name of the new space time dataset
+       :param type: The type of the new space time dataset (strd, str3ds,
+                    stvds, raster, vector, raster3d)
+       :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
+       :return: The new created space time dataset
 
        This function will raise a FatalError in case of an error.
     """
     dbif, connected = init_dbif(dbif)
     msgr = get_tgis_message_interface()
-    sp =  check_new_space_time_dataset(name, type, dbif, overwrite)
+    sp = check_new_stds(name, type, dbif, overwrite)
 
     if sp.is_in_db(dbif):
         msgr.warning(_("Overwriting space time %(sp)s dataset <%(name)s> and "
                        "unregistering all maps") % {
-                       'sp': sp.get_new_map_instance(None).get_type(),
-                       'name': name})
+                     'sp': sp.get_new_map_instance(None).get_type(),
+                     'name': name})
         id = sp.get_id()
         sp.delete(dbif)
         sp = sp.get_new_instance(id)
 
     msgr.verbose(_("Creating a new space time %s dataset") %
-                   sp.get_new_map_instance(None).get_type())
+                 sp.get_new_map_instance(None).get_type())
 
     sp.set_initial_values(temporal_type=temporaltype, semantic_type=semantic,
                           title=title, description=descr)
@@ -175,20 +177,21 @@ def open_new_space_time_dataset(name, type, temporaltype, title, descr, semantic
 
 ############################################################################
 
+
 def check_new_map_dataset(name, layer=None, type="raster",
                           overwrite=False, dbif=None):
-    """!Check if a new map dataset of a specific type can be created in
+    """Check if a new map dataset of a specific type can be created in
         the temporal database
 
-       @param name The name of the new map dataset
-       @param layer The layer of the new map dataset
-       @param type The type of the new map dataset (raster, vector, raster3d)
-       @param dbif The temporal database interface to be used
-       @param overwrite Flag to allow overwriting
+       :param name: The name of the new map dataset
+       :param layer: The layer of the new map dataset
+       :param type: The type of the new map dataset (raster, vector, raster3d)
+       :param dbif: The temporal database interface to be used
+       :param overwrite: Flag to allow overwriting
 
-       @return A map dataset object
+       :return: A map dataset object
 
-       This function will raise a ScriptError in case of an error.
+       This function will raise a FatalError in case of an error.
     """
     mapset = get_current_mapset()
     msgr = get_tgis_message_interface()
@@ -212,21 +215,21 @@ def check_new_map_dataset(name, layer=None, type="raster",
 
 ############################################################################
 
+
 def open_new_map_dataset(name, layer=None, type="raster",
                          temporal_extent=None, overwrite=False,
                          dbif=None):
-    """!Create a new map dataset object of a specific type that can be
+    """Create a new map dataset object of a specific type that can be
         registered in the temporal database
 
-       @param name The name of the new map dataset
-       @param layer The layer of the new map dataset
-       @param type The type of the new map dataset (raster, vector, raster3d)
-       @param dbif The temporal database interface to be used
-       @param overwrite Flag to allow overwriting
+       :param name: The name of the new map dataset
+       :param layer: The layer of the new map dataset
+       :param type: The type of the new map dataset (raster, vector, raster3d)
+       :param dbif: The temporal database interface to be used
+       :param overwrite: Flag to allow overwriting
 
-       @return A map dataset object
+       :return: A map dataset object
 
-       This function will raise a ScriptError in case of an error.
     """
 
     mapset = get_current_mapset()

+ 137 - 78
lib/python/temporal/register.py

@@ -1,28 +1,24 @@
-"""!@package grass.temporal
-
-@brief GRASS Python scripting module (temporal GIS functions)
-
-Temporal GIS related functions to be used in Python scripts.
+"""
+Functions to register map layer in space time datasets and the temporal database
 
 Usage:
 
-@code
-import grass.temporal as tgis
+.. code-block:: python
 
-tgis.register_maps_in_space_time_dataset(type, name, maps)
+    import grass.temporal as tgis
 
-...
-@endcode
+    tgis.register_maps_in_space_time_dataset(type, name, maps)
 
 (C) 2012-2013 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
+:authors: Soeren Gebbert
 """
 
 from open_stds import *
+import grass.script as gscript
 
 ###############################################################################
 
@@ -31,7 +27,7 @@ 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="|", update_cmd_list=True):
-    """!Use this method to register maps in space time datasets.
+    """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.
@@ -39,29 +35,30 @@ def register_maps_in_space_time_dataset(
        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. Maps will be registered in the
-                   temporal database if the name was set to None
-       @param maps A comma separated list of map names
-       @param file Input file, one map per line map with start and optional
+       :param type: The type of the maps rast, rast3d or vect
+       :param name: The name of the space time dataset. Maps will be
+                    registered in the temporal database if the name was set
+                    to None
+       :param maps: A comma separated list of map names
+       :param file: Input file, one map per line map with start and optional
                    end time
-       @param start The start date and time of the first raster map
+       :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
+       :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,
+       :param unit: The unit of the relative time: years, months, days,
                    hours, minutes, seconds
-       @param increment Time increment between maps for time stamp creation
+       :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
+       :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
-       @param update_cmd_list If is True, the command that was invoking this process
-                              will be written to the process history
+       :param fs: Field separator used in input file
+       :param update_cmd_list: If is True, the command that was invoking this
+                               process will be written to the process history
     """
     start_time_in_file = False
     end_time_in_file = False
@@ -76,35 +73,32 @@ def register_maps_in_space_time_dataset(
         increment = str(increment)
 
     if maps and file:
-        msgr.fatal(_("%(m)s= and %(f)s= are mutually exclusive") % {'m': "maps",
-                                                                    'f': "file"})
+        msgr.fatal(_("%s= and %s= are mutually exclusive") % ("maps", "file"))
 
     if end and increment:
-        msgr.fatal(_("%(e)s= and %(i)s= are mutually exclusive") % {'e': "end",
-                   'i': "increment"})
+        msgr.fatal(_("%s= and %s= are mutually exclusive") % ("end",
+                                                              "increment"))
 
     if end and not start:
-        msgr.fatal(_("Please specify %(st)s= and %(e)s=") % {'st': "start_time",
-                                                             'e': "end_time"})
+        msgr.fatal(_("Please specify %s= and %s=") % ("start_time",
+                                                      "end_time"))
 
     if not maps and not file:
-        msgr.fatal(_("Please specify %(m)s= or %(f)s=") % {'m': "maps",
-                                                           'f': "file"})
+        msgr.fatal(_("Please specify %s= or %s=") % ("maps", "file"))
     # We may need the mapset
     mapset = get_current_mapset()
     dbif, connected = init_dbif(None)
 
     # The name of the space time dataset is optional
     if name:
-        sp = open_old_space_time_dataset(name, type, dbif)
+        sp = open_old_stds(name, type, dbif)
 
         if sp.is_time_relative() and (start or end) and not unit:
             dbif.close()
             msgr.fatal(_("Space time %(sp)s dataset <%(name)s> with relative"
                          " time found, but no relative unit set for %(sp)s "
-                         "maps") % {
-                         'sp': sp.get_new_map_instance(None).get_type(),
-                         'name': name})
+                         "maps") % {'name': name,
+                       'sp': sp.get_new_map_instance(None).get_type()})
 
     maplist = []
 
@@ -174,12 +168,11 @@ def register_maps_in_space_time_dataset(
 
         # Get a new instance of the map type
         map = dataset_factory(type, maplist[count]["id"])
-        
+
         if map.map_exists() is not True:
             msgr.fatal(_("Unable to update %(t)s map <%(id)s>. "
-                            "The map does not exist.") %
-                            {'t': map.get_type(),
-                            'id': map.get_map_id()})
+                         "The map does not exist.") % {'t': map.get_type(),
+                                                       'id': map.get_map_id()})
 
         # Use the time data from file
         if "start" in maplist[count]:
@@ -198,20 +191,22 @@ def register_maps_in_space_time_dataset(
                     msgr.fatal(_("Unable to register %(t)s map <%(id)s> with "
                                  "layer %(l)s. The map has timestamp and "
                                  "the start time is not set.") % {
-                                 't': map.get_type(), 'id': map.get_map_id(),
-                                 'l': map.get_layer()})
+                               't': map.get_type(), 'id': map.get_map_id(),
+                               'l': map.get_layer()})
                 else:
                     msgr.fatal(_("Unable to register %(t)s map <%(id)s>. The"
                                  " map has no timestamp and the start time "
                                  "is not set.") % {'t': map.get_type(),
                                                    'id': map.get_map_id()})
-            if start != "" and start != None:
+            if start != "" and start is not None:
                 # We need to check if the time is absolute and the unit was specified
                 time_object = check_datetime_string(start)
                 if isinstance(time_object, datetime) and unit:
-                    msgr.fatal(_("%(u)s= can only be set for relative time") % {'u': "unit"})
+                    msgr.fatal(_("%(u)s= can only be set for relative time") %
+                               {'u': "unit"})
                 if not isinstance(time_object, datetime) and not unit:
-                    msgr.fatal(_("%(u)s= must be set in case of relative time stamps") % {'u': "unit"})
+                    msgr.fatal(_("%(u)s= must be set in case of relative time"
+                                 " stamps") % {'u': "unit"})
 
                 if unit:
                     map.set_time_to_relative()
@@ -221,7 +216,7 @@ def register_maps_in_space_time_dataset(
         else:
             is_in_db = True
             # Check the overwrite flag
-            if not core.overwrite():
+            if not gscript.overwrite():
                 if map.get_layer():
                     msgr.warning(_("Map is already registered in temporal "
                                    "database. Unable to update %(t)s map "
@@ -232,8 +227,8 @@ def register_maps_in_space_time_dataset(
                 else:
                     msgr.warning(_("Map is already registered in temporal "
                                    "database. Unable to update %(t)s map "
-                                   "<%(id)s>. Overwrite flag is not set.") % {
-                                   't': map.get_type(), 'id': map.get_map_id()})
+                                   "<%(id)s>. Overwrite flag is not set.") %
+                                 {'t': map.get_type(), 'id': map.get_map_id()})
 
                 # Simple registration is allowed
                 if name:
@@ -257,13 +252,13 @@ def register_maps_in_space_time_dataset(
                         msgr.fatal(_("Unable to update %(t)s map <%(id)s> "
                                      "with layer %(l)s. The temporal types "
                                      "are different.") % {'t': map.get_type(),
-                                                        'id': map.get_map_id(),
-                                                        'l': map.get_layer()})
+                                                          'id': map.get_map_id(),
+                                                          'l': map.get_layer()})
                     else:
                         msgr.fatal(_("Unable to update %(t)s map <%(id)s>. "
                                      "The temporal types are different.") %
-                                     {'t': map.get_type(),
-                                      'id': map.get_map_id()})
+                                   {'t': map.get_type(),
+                                    'id': map.get_map_id()})
 
         # Load the data from the grass file database
         map.load()
@@ -293,7 +288,7 @@ def register_maps_in_space_time_dataset(
 
         # Sqlite3 performance is better for huge datasets when committing in
         # small chunks
-        if dbif.dbmi.__name__ == "sqlite3":
+        if dbif.get_dbmi().__name__ == "sqlite3":
             if count % 100 == 0:
                 if statement is not None and statement != "":
                     dbif.execute_transaction(statement)
@@ -339,7 +334,7 @@ def register_maps_in_space_time_dataset(
             ds.select(dbif)
             ds.update_from_registered_maps(dbif)
 
-    if connected == True:
+    if connected is True:
         dbif.close()
 
     msgr.percent(num_maps, num_maps, 1)
@@ -349,24 +344,24 @@ def register_maps_in_space_time_dataset(
 
 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
+    """Assign the valid time to a map dataset
 
-       @param ttype The temporal type which should be assigned
+       :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
+       :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
+       :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,
+       :param unit: The unit of the relative time: years, months,
                     days, hours, minutes, seconds
-       @param increment Time increment between maps for time stamp creation
+       :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
+       :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
     """
 
@@ -382,7 +377,6 @@ def assign_valid_time_to_map(ttype, map, start, end, unit, increment=None,
         if end:
             end_time = string_to_datetime(end)
             if end_time is None:
-                dbif.close()
                 msgr.fatal(_("Unable to convert string \"%s\"into a "
                              "datetime object") % (end))
 
@@ -400,12 +394,12 @@ def assign_valid_time_to_map(ttype, map, start, end, unit, increment=None,
 
         if map.get_layer():
             msgr.debug(1, _("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)})
+                            "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:
-            msgr.debug(1, _("Set absolute valid time for map <%s> to %s - %s") %
-                         (map.get_map_id(), str(start_time), str(end_time)))
+            msgr.debug(1, _("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)
     else:
@@ -421,19 +415,84 @@ def assign_valid_time_to_map(ttype, map, start, end, unit, increment=None,
                 end_time = start_time + int(increment)
 
         if map.get_layer():
-            msgr.debug(1, _("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))
+            msgr.debug(1, _("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:
             msgr.debug(1, _("Set relative valid time for map <%s> to %i - %s "
-                           "with unit %s") % (map.get_map_id(), start_time,
-                                              str(end_time), unit))
+                            "with unit %s") % (map.get_map_id(), start_time,
+                                               str(end_time), unit))
 
         map.set_relative_time(start_time, end_time, unit)
 
 
-###############################################################################
+##############################################################################
+
+def register_map_object_list(type,  map_list, output_stds,
+                             delete_empty, unit, dbif=None):
+    """Register a list of AbstractMapDataset objects in the temporal database
+       and optional in a space time dataset.
+
+       :param type: The type of the map layer (rast, rast3d, vect)
+       :param map_list: List of AbstractMapDataset objects
+       :param output_stds: The output stds
+       :param delete_empty: Set True to delete empty map layer found in the map_list
+       :param unit: The temporal unit of the space time dataset
+       :param dbif: The database interface to be used
+
+    """
+    import grass.pygrass.modules as pymod
+    import copy
+
+    dbif,  connected = init_dbif(dbif)
+
+    filename = gscript.tempfile(True)
+    file = open(filename, 'w')
+
+    empty_maps = []
+    for map_layer in map_list:
+        # Read the raster map data
+        map_layer.load()
+        # In case of a empty map continue, do not register empty maps
+
+        if delete_empty:
+            if map_layer.metadata.get_min() is None and \
+               map_layer.metadata.get_max() is None:
+                empty_maps.append(map_layer)
+                continue
+
+        start,  end = map_layer.get_temporal_extent_as_tuple()
+        id = map_layer.get_id()
+        if not end:
+            end = start
+        string = "%s|%s|%s\n" % (id,  str(start),  str(end))
+        file.write(string)
+    file.close()
+
+    if output_stds:
+        output_stds_id = output_stds.get_id()
+    else:
+        output_stds_id = None
+
+    register_maps_in_space_time_dataset(type, output_stds_id, unit=unit,
+                                        file=filename, dbif=dbif)
+
+    g_remove = pymod.Module("g.remove", flags='f', quiet=True,
+                            run_=False, finish_=True)
+
+    # Remove empty maps
+    if len(empty_maps) > 0:
+        for map in empty_maps:
+            if map.is_in_db(dbif):
+                map.delete(dbif)
+            mod = copy.deepcopy(g_remove)
+            if map.get_name():
+                mod(type='rast', name=map.get_name())
+                mod.run()
+
+    if connected:
+        dbif.close()
 
 if __name__ == "__main__":
     import doctest

+ 30 - 30
lib/python/temporal/sampling.py

@@ -1,33 +1,29 @@
-"""!@package grass.temporal
-
-@brief GRASS Python scripting module (temporal GIS functions)
-
-Temporal GIS related functions to be used in Python scripts.
+"""
+Sampling functions for space time datasets
 
 Usage:
 
-@code
-import grass.temporal as tgis
+.. code-block:: python
 
-tgis.register_maps_in_space_time_dataset(type, name, maps)
+    import grass.temporal as tgis
 
-...
-@endcode
+    tgis.register_maps_in_space_time_dataset(type, name, maps)
 
 (C) 2012-2013 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
+:authors: Soeren Gebbert
 """
 
 from factory 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
+    """Sample the input space time datasets with a sample
        space time dataset, return the created map matrix and optionally
        print the result to stdout
 
@@ -39,21 +35,24 @@ def sample_stds_by_stds_topology(intype, sampletype, inputs, sampler, header,
 
         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 datasets (strds, stvds or str3ds)
-        @param inputs Name or comma separated names of space time datasets or a list of map names
-        @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) as comma separated string
-                       or as a list of methods
-        @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
+        :param intype: Type of the input space time dataset (strds, stvds or
+                       str3ds)
+        :param sampletype: Type of the sample space time datasets (strds,
+                           stvds or str3ds)
+        :param inputs: Name or comma separated names of space time datasets or
+                       a list of map names
+        :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) as comma separated
+                       string or as a list of methods
+        :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 = get_current_mapset()
     msgr = get_tgis_message_interface()
@@ -88,11 +87,12 @@ def sample_stds_by_stds_topology(intype, sampletype, inputs, sampler, header,
     dbif.connect()
 
     for st in sts:
-        if st.is_in_db(dbif) == False:
-            msgr.fatal(_("Dataset <%s> not found in temporal database") % (st.get_id()))
+        if st.is_in_db(dbif) is False:
+            msgr.fatal(_("Dataset <%s> not found in temporal database")
+                       % (st.get_id()))
         st.select(dbif)
 
-    if sst.is_in_db(dbif) == False:
+    if sst.is_in_db(dbif) is False:
         msgr.fatal(_("Dataset <%s> not found in temporal database") % (sid))
 
     sst.select(dbif)

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 470 - 463
lib/python/temporal/space_time_datasets.py


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 617 - 631
lib/python/temporal/spatial_extent.py


+ 141 - 148
lib/python/temporal/spatial_topology_dataset_connector.py

@@ -1,9 +1,6 @@
 # -*- coding: utf-8 -*-
-"""!@package grass.temporal
-
-@brief GRASS Python scripting module (temporal GIS functions)
-
-Temporal GIS related functions to be used in temporal GIS Python library package.
+"""
+Spatial topology connector class
 
 Usage:
 
@@ -15,17 +12,20 @@ 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
+:authors: Soeren Gebbert
 """
 import copy
 
+
 class SpatialTopologyDatasetConnector(object):
-    """!This class implements a spatial topology access structure to connect spatial related datasets
+    """This class implements a spatial topology access structure to connect
+       spatial related datasets
 
-       This object will be set up by spatial topology creation method provided by the 
-       SpatioTemporalTopologyBuilder.
+       This object will be set up by spatial topology creation method provided
+       by the SpatioTemporalTopologyBuilder.
 
        The following spatial relations with access methods are supported:
+
        - equivalent
        - overlap
        - in
@@ -33,265 +33,264 @@ class SpatialTopologyDatasetConnector(object):
        - meet
        - cover
        - covered
-            
+
         Usage:
-        
-        @code
-        
-        >>> import grass.temporal as tgis
-        >>> tgis.init()
-        >>> map = tgis.RasterDataset("a@P")
-        >>> tmr = tgis.SpatialTopologyDatasetConnector()
-        >>> tmr.append_equivalent(map)
-        >>> tmr.append_overlap(map)
-        >>> tmr.append_in(map)
-        >>> tmr.append_contain(map)
-        >>> tmr.append_meet(map)
-        >>> tmr.append_cover(map)
-        >>> tmr.append_covered(map)
-        >>> tmr.print_spatial_topology_info()
-         +-------------------- Spatial Topology --------------------------------------+
-         | Equivalent: ................ a@P
-         | Cover: ..................... a@P
-         | Covered: ................... a@P
-         | Overlap: ................... a@P
-         | In: ........................ a@P
-         | Contain: ................... a@P
-         | Meet: ...................... a@P
-        >>> tmr.print_spatial_topology_shell_info()
-        equivalent=a@P
-        cover=a@P
-        covered=a@P
-        overlap=a@P
-        in=a@P
-        contain=a@P
-        meet=a@P
-        >>> rlist = tmr.get_spatial_relations()
-        >>> if "COVER" in rlist.keys():
-        ...    print rlist["COVER"][0].get_id()
-        a@P
-
-        
-        @endcode
+
+        .. code-block:: python
+
+            >>> import grass.temporal as tgis
+            >>> tgis.init()
+            >>> map = tgis.RasterDataset("a@P")
+            >>> tmr = tgis.SpatialTopologyDatasetConnector()
+            >>> tmr.append_equivalent(map)
+            >>> tmr.append_overlap(map)
+            >>> tmr.append_in(map)
+            >>> tmr.append_contain(map)
+            >>> tmr.append_meet(map)
+            >>> tmr.append_cover(map)
+            >>> tmr.append_covered(map)
+            >>> tmr.print_spatial_topology_info()
+             +-------------------- Spatial Topology --------------------------------------+
+             | Equivalent: ................ a@P
+             | Cover: ..................... a@P
+             | Covered: ................... a@P
+             | Overlap: ................... a@P
+             | In: ........................ a@P
+             | Contain: ................... a@P
+             | Meet: ...................... a@P
+            >>> tmr.print_spatial_topology_shell_info()
+            equivalent=a@P
+            cover=a@P
+            covered=a@P
+            overlap=a@P
+            in=a@P
+            contain=a@P
+            meet=a@P
+            >>> rlist = tmr.get_spatial_relations()
+            >>> if "COVER" in rlist.keys():
+            ...    print rlist["COVER"][0].get_id()
+            a@P
+
     """
 
     def __init__(self):
         self.reset_spatial_topology()
 
     def reset_spatial_topology(self):
-        """!Reset any information about temporal topology"""
+        """Reset any information about temporal topology"""
         self._spatial_topology = {}
         self._has_spatial_topology = False
-        
+
     def get_spatial_relations(self):
-        """!Return the dictionary of spatial relationships
-        
-            Keys are the spatial relationships in upper case,
-            values are abstract map objects.
-            
-            @return The spatial relations dictionary
+        """Return the dictionary of spatial relationships
+
+           Keys are the spatial relationships in upper case,
+           values are abstract map objects.
+
+           :return: The spatial relations dictionary
         """
         return copy.copy(self._spatial_topology)
-    
+
     def get_number_of_spatial_relations(self):
-        """! Return a dictionary in which the keys are the relation names and the value
-        are the number of relations.
-        
-        The following relations are available:
-       - equivalent
-       - overlap
-       - in
-       - contain
-       - meet
-       - cover
-       - covered
-        
-        To access topological information the spatial topology must be build first
-        using the SpatialTopologyBuilder.
-        
-        @return the dictionary with relations as keys and number as values or None in case the topology wasn't build
+        """ Return a dictionary in which the keys are the relation names and the value
+            are the number of relations.
+
+            The following relations are available:
+
+            - equivalent
+            - overlap
+            - in
+            - contain
+            - meet
+            - cover
+            - covered
+
+            To access topological information the spatial topology must be
+            build first using the SpatialTopologyBuilder.
+
+            :return: the dictionary with relations as keys and number as
+                     values or None in case the topology wasn't build
         """
-        if self._has_spatial_topology == False:
+        if self._has_spatial_topology is False:
             return None
-    
+
         relations = {}
         try:
-            relations["equivalent"] = len(self._spatial_topology["EQUIVALENT"]) 
+            relations["equivalent"] = len(self._spatial_topology["EQUIVALENT"])
         except:
             relations["equivalent"] = 0
-        try: 
-            relations["overlap"] = len(self._spatial_topology["OVERLAP"]) 
-        except: 
+        try:
+            relations["overlap"] = len(self._spatial_topology["OVERLAP"])
+        except:
             relations["overlap"] = 0
-        try: 
+        try:
             relations["in"] = len(self._spatial_topology["IN"])
-        except: 
+        except:
             relations["in"] = 0
-        try: 
+        try:
             relations["contain"] = len(self._spatial_topology["CONTAIN"])
-        except: 
+        except:
             relations["contain"] = 0
-        try: 
+        try:
             relations["meet"] = len(self._spatial_topology["MEET"])
-        except: 
+        except:
             relations["meet"] = 0
-        try: 
+        try:
             relations["cover"] = len(self._spatial_topology["COVER"])
-        except: 
+        except:
             relations["cover"] = 0
-        try: 
+        try:
             relations["covered"] = len(self._spatial_topology["COVERED"])
-        except: 
+        except:
             relations["covered"] = 0
-            
+
         return relations
 
     def set_spatial_topology_build_true(self):
-        """!Same as name"""
+        """Same as name"""
         self._has_spatial_topology = True
 
     def set_spatial_topology_build_false(self):
-        """!Same as name"""
+        """Same as name"""
         self._has_spatial_topology = False
 
     def is_spatial_topology_build(self):
-        """!Check if the temporal topology was build"""
+        """Check if the temporal topology was build"""
         return self._has_spatial_topology
 
     def append_equivalent(self, map):
-        """!Append a map with equivalent spatial extent as this map
+        """Append a map with equivalent spatial extent as this map
 
-           @param map This object should be of type AbstractMapDataset 
-                        or derived classes
+           :param map: This object should be of type AbstractMapDataset
+                       or derived classes
         """
         if "EQUIVALENT" not in self._spatial_topology:
             self._spatial_topology["EQUIVALENT"] = []
         self._spatial_topology["EQUIVALENT"].append(map)
 
     def get_equivalent(self):
-        """!Return a list of map objects with equivalent spatial extent as this map
+        """Return a list of map objects with equivalent spatial extent as this map
 
-           @return A list of map objects or None
+           :return: A list of map objects or None
         """
         if "EQUIVALENT" not in self._spatial_topology:
             return None
         return self._spatial_topology["EQUIVALENT"]
 
     def append_overlap(self, map):
-        """!Append a map that this spatial overlap with this map
+        """Append a map that this spatial overlap with this map
 
-           @param map This object should be of type AbstractMapDataset 
-                        or derived classes
+           :param map: This object should be of type AbstractMapDataset
+                       or derived classes
         """
         if "OVERLAP" not in self._spatial_topology:
             self._spatial_topology["OVERLAP"] = []
         self._spatial_topology["OVERLAP"].append(map)
 
     def get_overlap(self):
-        """!Return a list of map objects that this map spatial overlap with
+        """Return a list of map objects that this map spatial overlap with
 
-           @return A list of map objects or None
+           :return: A list of map objects or None
         """
         if "OVERLAP" not in self._spatial_topology:
             return None
         return self._spatial_topology["OVERLAP"]
 
     def append_in(self, map):
-        """!Append a map that this is spatial in this map
+        """Append a map that this is spatial in this map
 
-           @param map This object should be of type AbstractMapDataset 
-                        or derived classes
+           :param map: This object should be of type AbstractMapDataset
+                       or derived classes
         """
         if "IN" not in self._spatial_topology:
             self._spatial_topology["IN"] = []
         self._spatial_topology["IN"].append(map)
 
     def get_in(self):
-        """!Return a list of map objects that are spatial in this map
+        """Return a list of map objects that are spatial in this map
 
-           @return A list of map objects or None
+           :return: A list of map objects or None
         """
         if "IN" not in self._spatial_topology:
             return None
         return self._spatial_topology["IN"]
 
     def append_contain(self, map):
-        """!Append a map that this map spatially contains
+        """Append a map that this map spatially contains
 
-           @param map This object should be of type AbstractMapDataset 
-                        or derived classes
+           :param map: This object should be of type AbstractMapDataset
+                       or derived classes
         """
         if "CONTAIN" not in self._spatial_topology:
             self._spatial_topology["CONTAIN"] = []
         self._spatial_topology["CONTAIN"].append(map)
 
     def get_contain(self):
-        """!Return a list of map objects that this map contains
+        """Return a list of map objects that this map contains
 
-           @return A list of map objects or None
+           :return: A list of map objects or None
         """
         if "CONTAIN" not in self._spatial_topology:
             return None
         return self._spatial_topology["CONTAIN"]
 
     def append_meet(self, map):
-        """!Append a map that spatially meet with this map
+        """Append a map that spatially meet with this map
 
-           @param map This object should be of type AbstractMapDataset 
-                        or derived classes
+           :param map: This object should be of type AbstractMapDataset
+                       or derived classes
         """
         if "MEET" not in self._spatial_topology:
             self._spatial_topology["MEET"] = []
         self._spatial_topology["MEET"].append(map)
 
     def get_meet(self):
-        """!Return a list of map objects that spatially meet with this map
+        """Return a list of map objects that spatially meet with this map
 
-           @return A list of map objects or None
+           :return: A list of map objects or None
         """
         if "MEET" not in self._spatial_topology:
             return None
         return self._spatial_topology["MEET"]
 
     def append_cover(self, map):
-        """!Append a map that spatially cover this map
+        """Append a map that spatially cover this map
 
-           @param map This object should be of type AbstractMapDataset 
-                        or derived classes
+           :param map: This object should be of type AbstractMapDataset
+                       or derived classes
         """
         if "COVER" not in self._spatial_topology:
             self._spatial_topology["COVER"] = []
         self._spatial_topology["COVER"].append(map)
 
     def get_cover(self):
-        """!Return a list of map objects that spatially cover this map
+        """Return a list of map objects that spatially cover this map
 
-           @return A list of map objects or None
+           :return: A list of map objects or None
         """
         if "COVER" not in self._spatial_topology:
             return None
         return self._spatial_topology["COVER"]
 
     def append_covered(self, map):
-        """!Append a map that is spatially covered by this map
+        """Append a map that is spatially covered by this map
 
-           @param map This object should be of type AbstractMapDataset 
-                        or derived classes
+           :param map: This object should be of type AbstractMapDataset
+                       or derived classes
         """
         if "COVERED" not in self._spatial_topology:
             self._spatial_topology["COVERED"] = []
         self._spatial_topology["COVERED"].append(map)
 
     def get_covered(self):
-        """!Return a list of map objects that are spatially covered by this map
+        """Return a list of map objects that are spatially covered by this map
 
-           @return A list of map objects or None
+           :return: A list of map objects or None
         """
         if "COVERED" not in self._spatial_topology:
             return None
         return self._spatial_topology["COVERED"]
 
-
     def _generate_map_list_string(self, map_list, line_wrap=True):
         count = 0
         string = ""
@@ -306,26 +305,19 @@ class SpatialTopologyDatasetConnector(object):
             count += 1
 
         return string
-    
+
     # Set the properties
-    equivalent = property(fget=get_equivalent, 
-                                       fset=append_equivalent)
-    cover = property(fget=get_cover, 
-                                     fset=append_cover)
-    covered = property(fget=get_covered, 
-                                       fset=append_covered)
-    overlap = property(fget=get_overlap, 
-                                     fset=append_overlap)
-    in_ = property(fget=get_in, 
-                                     fset=append_in)
-    contain = property(fget=get_contain, 
-                                     fset=append_contain)
-    meet = property(fget=get_meet, 
-                                     fset=append_meet)
+    equivalent = property(fget=get_equivalent, fset=append_equivalent)
+    cover = property(fget=get_cover, fset=append_cover)
+    covered = property(fget=get_covered, fset=append_covered)
+    overlap = property(fget=get_overlap, fset=append_overlap)
+    in_ = property(fget=get_in, fset=append_in)
+    contain = property(fget=get_contain, fset=append_contain)
+    meet = property(fget=get_meet, fset=append_meet)
 
     def print_spatial_topology_info(self):
-        """!Print information about this class in human readable style"""
-        
+        """Print information about this class in human readable style"""
+
         print " +-------------------- Spatial Topology --------------------------------------+"
         #          0123456789012345678901234567890
         if self.equivalent is not None:
@@ -351,10 +343,11 @@ class SpatialTopologyDatasetConnector(object):
                 self._generate_map_list_string(self.meet)
 
     def print_spatial_topology_shell_info(self):
-        """!Print information about this class in shell style"""
+        """Print information about this class in shell style"""
 
         if self.equivalent is not None:
-            print "equivalent=" + self._generate_map_list_string(self.equivalent, False)
+            print "equivalent=" + self._generate_map_list_string(self.equivalent,
+                                                                 False)
         if self.cover is not None:
             print "cover=" + self._generate_map_list_string(
                 self.cover, False)

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 531 - 512
lib/python/temporal/spatio_temporal_relationships.py


+ 55 - 51
lib/python/temporal/stds_export.py

@@ -1,31 +1,28 @@
-"""!@package grass.temporal
+"""
+Export functions for space time datasets
 
-@brief GRASS Python scripting module (temporal GIS functions)
+Usage:
 
-Temporal GIS export functions to be used in temporal modules
+.. code-block:: python
 
-Usage:
+    import grass.temporal as tgis
 
-@code
-import grass.temporal as tgis
+    input="temp_1950_2012@PERMANENT"
+    output="/tmp/temp_1950_2012.tar.gz"
+    compression="gzip"
+    workdir="/tmp"
+    where=None
+    format_="GTiff"
+    type_="strds"
+    tgis.export_stds(input, output, compression, workdir, where, format_, type_)
 
-input="temp_1950_2012@PERMANENT"
-output="/tmp/temp_1950_2012.tar.gz"
-compression="gzip"
-workdir="/tmp"
-where=None
-format_="GTiff"
-type_="strds"
-tgis.export_stds(input, output, compression, workdir, where, format_, type_)
-...
-@endcode
 
 (C) 2012-2013 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
+:authors: Soeren Gebbert
 """
 
 import shutil
@@ -36,6 +33,7 @@ import tempfile
 from space_time_datasets import *
 from factory import *
 from open_stds import *
+import grass.script as gscript
 from grass.exceptions import CalledModuleError
 
 
@@ -98,7 +96,7 @@ def _export_raster_maps_as_gdal(rows, tar, list_file, new_cwd, fs, format_):
         except CalledModuleError:
             shutil.rmtree(new_cwd)
             tar.close()
-            core.fatal(_("Unable to export raster map <%s>" % name))
+            gscript.fatal(_("Unable to export raster map <%s>" % name))
 
         tar.add(out_name)
 
@@ -109,13 +107,14 @@ def _export_raster_maps_as_gdal(rows, tar, list_file, new_cwd, fs, format_):
         except CalledModuleError:
             shutil.rmtree(new_cwd)
             tar.close()
-            core.fatal(_("Unable to export color rules for raster "
-                         "map <%s> r.out.gdal" % name))
+            gscript.fatal(_("Unable to export color rules for raster "
+                            "map <%s> r.out.gdal" % name))
 
         tar.add(out_name)
 
 ############################################################################
 
+
 def _export_raster_maps(rows, tar, list_file, new_cwd, fs):
     for row in rows:
         name = row["name"]
@@ -132,13 +131,14 @@ def _export_raster_maps(rows, tar, list_file, new_cwd, fs):
         except CalledModuleError:
             shutil.rmtree(new_cwd)
             tar.close()
-            core.fatal(_("Unable to export raster map <%s> with r.pack" %
-                         name))
+            gscript.fatal(_("Unable to export raster map <%s> with r.pack" %
+                          name))
 
         tar.add(name + ".pack")
 
 ############################################################################
 
+
 def _export_vector_maps_as_gml(rows, tar, list_file, new_cwd, fs):
     for row in rows:
         name = row["name"]
@@ -159,14 +159,15 @@ def _export_vector_maps_as_gml(rows, tar, list_file, new_cwd, fs):
         except CalledModuleError:
             shutil.rmtree(new_cwd)
             tar.close()
-            core.fatal(_("Unable to export vector map <%s> as "
-                         "GML with v.out.ogr" % name))
+            gscript.fatal(_("Unable to export vector map <%s> as "
+                            "GML with v.out.ogr" % name))
 
         tar.add(name + ".xml")
         tar.add(name + ".xsd")
 
 ############################################################################
 
+
 def _export_vector_maps(rows, tar, list_file, new_cwd, fs):
     for row in rows:
         name = row["name"]
@@ -191,8 +192,8 @@ def _export_vector_maps(rows, tar, list_file, new_cwd, fs):
         except CalledModuleError:
             shutil.rmtree(new_cwd)
             tar.close()
-            core.fatal(_("Unable to export vector map <%s> with v.pack" %
-                         name))
+            gscript.fatal(_("Unable to export vector map <%s> with v.pack" %
+                          name))
 
         tar.add(name + ".pack")
 
@@ -217,8 +218,8 @@ def _export_raster3d_maps(rows, tar, list_file, new_cwd, fs):
         except CalledModuleError:
             shutil.rmtree(new_cwd)
             tar.close()
-            core.fatal(_("Unable to export raster map <%s> with r3.pack" %
-                         name))
+            gscript.fatal(_("Unable to export raster map <%s> with r3.pack" %
+                          name))
 
         tar.add(name + ".pack")
 
@@ -227,36 +228,39 @@ def _export_raster3d_maps(rows, tar, list_file, new_cwd, fs):
 
 def export_stds(input, output, compression, workdir, where, format_="pack",
                 type_="strds"):
-    """
-            !Export space time datasets as tar archive with optional compression
+    """Export space time datasets as tar archive with optional compression
 
-            This method should be used to export space time datasets
-            of type raster and vector as tar archive that can be reimported
-            with the method import_stds().
+        This method should be used to export space time datasets
+        of type raster and vector as tar archive that can be reimported
+        with the method import_stds().
+
+        :param input: The name of the space time dataset to export
+        :param output: The name of the archive file
+        :param compression: The compression of the archive file:
 
-            @param input The name of the space time dataset to export
-            @param output The name of the archive file
-            @param compression The compression of the archive file:
               - "no"  no compression
               - "gzip" GNU zip compression
               - "bzip2" Bzip compression
-            @param workdir The working directory used for extraction and packing
-            @param where The temporal WHERE SQL statement to select a subset
-                          of maps from the space time dataset
-            @param format_ The export format:
+
+        :param workdir: The working directory used for extraction and packing
+        :param where: The temporal WHERE SQL statement to select a subset
+                      of maps from the space time dataset
+        :param format_: The export format:
+
               - "GTiff" Geotiff format, only for raster maps
               - "AAIGrid" Arc/Info ASCII Grid format, only for raster maps
               - "pack" The GRASS raster, 3D raster or vector Pack format,
                        this is the default setting
               - "GML" GML file export format, only for vector maps,
                       v.out.ogr export option
-            @param type_ The space time dataset type
+
+        :param type_: The space time dataset type
+
               - "strds" Space time raster dataset
               - "str3ds" Space time 3D raster dataset
               - "stvds" Space time vector dataset
     """
 
-
     # Save current working directory path
     old_cwd = os.getcwd()
 
@@ -271,7 +275,7 @@ def export_stds(input, output, compression, workdir, where, format_="pack",
     else:
         columns = "name,start_time,end_time"
 
-    sp = open_old_space_time_dataset(input, type_)
+    sp = open_old_stds(input, type_)
     rows = sp.get_registered_maps(columns, where, "start_time", None)
 
     if compression == "gzip":
@@ -305,7 +309,7 @@ def export_stds(input, output, compression, workdir, where, format_="pack",
     list_file.close()
 
     # Write projection and metadata
-    proj = core.read_command("g.proj", flags="j")
+    proj = gscript.read_command("g.proj", flags="j")
 
     proj_file = open(proj_file_name, "w")
     proj_file.write(proj)
@@ -314,11 +318,11 @@ def export_stds(input, output, compression, workdir, where, format_="pack",
     init_file = open(init_file_name, "w")
     # Create the init string
     string = ""
-     # This is optional, if not present strds will be assumed for backward
-     # compatibility
+    # This is optional, if not present strds will be assumed for backward
+    # compatibility
     string += "%s=%s\n" % ("stds_type", sp.get_type())
-     # This is optional, if not present gtiff will be assumed for
-     # backward compatibility
+    # This is optional, if not present gtiff will be assumed for
+    # backward compatibility
     string += "%s=%s\n" % ("format", format_)
     string += "%s=%s\n" % ("temporal_type", sp.get_temporal_type())
     string += "%s=%s\n" % ("semantic_type", sp.get_semantic_type())
@@ -334,7 +338,7 @@ def export_stds(input, output, compression, workdir, where, format_="pack",
     init_file.write(string)
     init_file.close()
 
-    metadata = core.read_command("t.info", type=type_, input=sp.get_id())
+    metadata = gscript.read_command("t.info", type=type_, input=sp.get_id())
     metadata_file = open(metadata_file_name, "w")
     metadata_file.write(metadata)
     metadata_file.close()
@@ -353,13 +357,13 @@ def export_stds(input, output, compression, workdir, where, format_="pack",
     read_file.write("Files:\n")
     if type_ == "strds":
         if format_ == "GTiff":
-                                #123456789012345678901234567890
+                                # 123456789012345678901234567890
             read_file.write("       *.tif  -- GeoTIFF raster files\n")
             read_file.write("     *.color  -- GRASS GIS raster color rules\n")
         elif format_ == "pack":
             read_file.write("      *.pack  -- GRASS raster files packed with r.pack\n")
     elif type_ == "stvds":
-                                #123456789012345678901234567890
+                                # 123456789012345678901234567890
         if format_ == "GML":
             read_file.write("       *.xml  -- Vector GML files\n")
         else:

+ 88 - 85
lib/python/temporal/stds_import.py

@@ -1,35 +1,32 @@
-"""!@package grass.temporal
+"""
+Space time dataset import functions
+
+Usage:
 
-@brief GRASS Python scripting module (temporal GIS functions)
+.. code-block:: python
 
-Temporal GIS export functions to be used in temporal modules
+    import grass.temporal as tgis
 
-Usage:
+    input="/tmp/temp_1950_2012.tar.gz"
+    output="temp_1950_2012"
+    extrdir="/tmp"
+    title="My new dataset"
+    descr="May new shiny dataset"
+    location=None
+    link=True
+    exp=True
+    overr=False
+    create=False
+    tgis.import_stds(input, output, extrdir, title, descr, location,
+                    link, exp, overr, create, "strds")
 
-@code
-import grass.temporal as tgis
-
-input="/tmp/temp_1950_2012.tar.gz"
-output="temp_1950_2012"
-extrdir="/tmp"
-title="My new dataset"
-descr="May new shiny dataset"
-location=None
-link=True
-exp=True
-overr=False
-create=False
-tgis.import_stds(input, output, extrdir, title, descr, location,
-                link, exp, overr, create, "strds")
-...
-@endcode
 
 (C) 2012-2013 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
+:authors: Soeren Gebbert
 """
 
 import os
@@ -55,7 +52,7 @@ imported_maps = {}
 ############################################################################
 
 
-def _import_raster_maps_from_gdal(maplist, overr, exp, location, link, format_, 
+def _import_raster_maps_from_gdal(maplist, overr, exp, location, link, format_,
                                   set_current_region=False):
     impflags = ""
     if overr:
@@ -66,7 +63,7 @@ def _import_raster_maps_from_gdal(maplist, overr, exp, location, link, format_,
         name = row["name"]
         if format_ == "GTiff":
             filename = row["filename"] + ".tif"
-        elif format_=="AAIGrid":
+        elif format_ == "AAIGrid":
             filename = row["filename"] + ".asc"
             if not overr:
                 impflags += "o"
@@ -84,8 +81,8 @@ def _import_raster_maps_from_gdal(maplist, overr, exp, location, link, format_,
                                     overwrite=gscript.overwrite())
 
         except CalledModuleError:
-            gscript.fatal(_("Unable to import/link raster map <%s> from file %s.") %(name, 
-                                                                     filename))
+            gscript.fatal(_("Unable to import/link raster map <%s> from file"
+                            " %s.") % (name, filename))
 
         # Set the color rules if present
         filename = row["filename"] + ".color"
@@ -96,7 +93,7 @@ def _import_raster_maps_from_gdal(maplist, overr, exp, location, link, format_,
                                     overwrite=gscript.overwrite())
             except CalledModuleError:
                 gscript.fatal(_("Unable to set the color rules for "
-                             "raster map <%s>.") % name)
+                                "raster map <%s>.") % name)
 
     # Set the computational region from the last map imported
     if set_current_region is True:
@@ -119,8 +116,8 @@ def _import_raster_maps(maplist, set_current_region=False):
                                 verbose=True)
 
         except CalledModuleError:
-            gscript.fatal(_("Unable to unpack raster map <%s> from file %s.") % (name, 
-                                                                              filename))
+            gscript.fatal(_("Unable to unpack raster map <%s> from file "
+                            "%s.") % (name, filename))
 
     # Set the computational region from the last map imported
     if set_current_region is True:
@@ -143,8 +140,8 @@ def _import_vector_maps_from_gml(maplist, overr, exp, location, link):
                                 overwrite=gscript.overwrite())
 
         except CalledModuleError:
-            gscript.fatal(_("Unable to import vector map <%s> from file %s.") % (name,
-                                                                              filename))
+            gscript.fatal(_("Unable to import vector map <%s> from file "
+                            "%s.") % (name, filename))
 
 ############################################################################
 
@@ -167,36 +164,36 @@ def _import_vector_maps(maplist):
                                 verbose=True)
 
         except CalledModuleError:
-            gscript.fatal(_("Unable to unpack vector map <%s> from file %s.") % (name, 
-                                                                              filename))
+            gscript.fatal(_("Unable to unpack vector map <%s> from file "
+                            "%s.") % (name, filename))
 
         imported_maps[name] = name
 ############################################################################
 
 
 def import_stds(input, output, extrdir, title=None, descr=None, location=None,
-        link=False, exp=False, overr=False, create=False, stds_type="strds", 
-        base=None, set_current_region=False):
-    """!Import space time datasets of type raster and vector
-
-        @param input Name of the input archive file
-        @param output The name of the output space time dataset
-        @param extrdir The extraction directory
-        @param title The title of the new created space time dataset
-        @param descr The description of the new created
+                link=False, exp=False, overr=False, create=False,
+                stds_type="strds", base=None, set_current_region=False):
+    """Import space time datasets of type raster and vector
+
+        :param input: Name of the input archive file
+        :param output: The name of the output space time dataset
+        :param extrdir: The extraction directory
+        :param title: The title of the new created space time dataset
+        :param descr: The description of the new created
                      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
-        @param link Switch to link raster maps instead importing them
-        @param exp Extend location extents based on new dataset
-        @param overr Override projection (use location's projection)
-        @param create Create the location specified by the "location"
+        :param link: Switch to link raster maps instead importing them
+        :param exp: Extend location extents based on new dataset
+        :param overr: Override projection (use location's projection)
+        :param create: Create the location specified by the "location"
                       parameter and exit.
                       Do not import the space time datasets.
-        @param stds_type The type of the space time dataset that
+        :param stds_type: The type of the space time dataset that
                          should be imported
-        @param base The base name of the new imported maps, it will be extended
-                    using a numerical index.
+        :param base: The base name of the new imported maps, it will be
+                     extended using a numerical index.
     """
 
     global raise_on_error
@@ -206,7 +203,7 @@ def import_stds(input, output, extrdir, title=None, descr=None, location=None,
     # Check if input file and extraction directory exits
     if not os.path.exists(input):
         gscript.fatal(_("Space time raster dataset archive <%s> not found")
-                   % input)
+                      % input)
     if not create and not os.path.exists(extrdir):
         gscript.fatal(_("Extraction directory <%s> not found") % extrdir)
 
@@ -243,15 +240,18 @@ def import_stds(input, output, extrdir, title=None, descr=None, location=None,
         p.communicate()
         temp_file.close()
 
-        if not gscript.compare_key_value_text_files(temp_name, proj_name, sep="="):
+        if not gscript.compare_key_value_text_files(temp_name, proj_name,
+                                                    sep="="):
             if overr:
                 gscript.warning(_("Projection information does not match. "
-                               "Proceeding..."))
+                                  "Proceeding..."))
             else:
                 diff = ''.join(gscript.diff_files(temp_name, proj_name))
-                gscript.warning(_("Difference between PROJ_INFO file of imported map "
-                               "and of current location:\n{diff}").format(diff=diff))
-                gscript.fatal(_("Projection information does not match. Aborting."))
+                gscript.warning(_("Difference between PROJ_INFO file of "
+                                  "imported map and of current location:"
+                                  "\n{diff}").format(diff=diff))
+                gscript.fatal(_("Projection information does not match. "
+                                "Aborting."))
 
     # Create a new location based on the projection information and switch
     # into it
@@ -260,15 +260,15 @@ def import_stds(input, output, extrdir, title=None, descr=None, location=None,
         try:
             proj4_string = open(proj_file_name, 'r').read()
             gscript.create_location(dbase=old_env["GISDBASE"],
-                                 location=location,
-                                 proj4=proj4_string)
+                                    location=location,
+                                    proj4=proj4_string)
             # Just create a new location and return
             if create:
                 os.chdir(old_cwd)
                 return
         except Exception as e:
             gscript.fatal(_("Unable to create location %(l)s. Reason: %(e)s")
-                         % {'l': location, 'e': str(e)})
+                          % {'l': location, 'e': str(e)})
         # Switch to the new created location
         try:
             gscript.run_command("g.mapset", mapset="PERMANENT",
@@ -281,7 +281,7 @@ def import_stds(input, output, extrdir, title=None, descr=None, location=None,
             gscript.run_command("t.connect", flags="d")
         except CalledModuleError:
             gscript.fatal(_("Unable to create default temporal database "
-                         "in new location %s") % location)
+                            "in new location %s") % location)
 
     try:
         # Make sure the temporal database exists
@@ -313,8 +313,9 @@ def import_stds(input, output, extrdir, title=None, descr=None, location=None,
             # that must be extended by the file suffix
             filename = line_list[0].strip().split(":")[0]
             if base:
-                mapname = "%s_%s" % (base, gscript.get_num_suffix(line_count + 1, max_count))
-                mapid= "%s@%s"%(mapname, mapset)
+                mapname = "%s_%s" % (base, gscript.get_num_suffix(line_count + 1,
+                                                                  max_count))
+                mapid = "%s@%s" % (mapname, mapset)
             else:
                 mapname = filename
                 mapid = mapname + "@" + mapset
@@ -325,16 +326,16 @@ def import_stds(input, output, extrdir, title=None, descr=None, location=None,
             row["id"] = mapid
             row["start"] = line_list[1].strip()
             row["end"] = line_list[2].strip()
-            
-            new_list_file.write("%s%s%s%s%s\n"%(mapname,fs, row["start"], 
-                                              fs, row["end"]))
+
+            new_list_file.write("%s%s%s%s%s\n" % (mapname, fs, row["start"],
+                                                  fs, row["end"]))
 
             maplist.append(row)
             line_count += 1
 
         list_file.close()
         new_list_file.close()
-        
+
         # Read the init file
         fs = "="
         init = {}
@@ -353,9 +354,9 @@ def import_stds(input, output, extrdir, title=None, descr=None, location=None,
            "semantic_type" not in init or \
            "number_of_maps" not in init:
             gscript.fatal(_("Key words %(t)s, %(s)s or %(n)s not found in init"
-                         " file.") % {'t': "temporal_type",
-                                      's': "semantic_type",
-                                      'n': "number_of_maps"})
+                            " file.") % {'t': "temporal_type",
+                                         's': "semantic_type",
+                                         'n': "number_of_maps"})
 
         if line_count != int(init["number_of_maps"]):
             gscript.fatal(_("Number of maps mismatch in init and list file."))
@@ -369,7 +370,8 @@ def import_stds(input, output, extrdir, title=None, descr=None, location=None,
             format_ = init["format"]
 
         if stds_type != type_:
-            gscript.fatal(_("The archive file is of wrong space time dataset type"))
+            gscript.fatal(_("The archive file is of wrong space time dataset"
+                            " type"))
 
         # Check the existence of the files
         if format_ == "GTiff":
@@ -377,19 +379,19 @@ def import_stds(input, output, extrdir, title=None, descr=None, location=None,
                 filename = row["filename"] + ".tif"
                 if not os.path.exists(filename):
                     gscript.fatal(_("Unable to find GeoTIFF raster file "
-                                 "<%s> in archive.") % filename)
+                                    "<%s> in archive.") % filename)
         elif format_ == "AAIGrid":
             for row in maplist:
                 filename = row["filename"] + ".asc"
                 if not os.path.exists(filename):
                     gscript.fatal(_("Unable to find AAIGrid raster file "
-                                 "<%s> in archive.") % filename)
+                                    "<%s> in archive.") % filename)
         elif format_ == "GML":
             for row in maplist:
                 filename = row["filename"] + ".xml"
                 if not os.path.exists(filename):
                     gscript.fatal(_("Unable to find GML vector file "
-                                 "<%s> in archive.") % filename)
+                                    "<%s> in archive.") % filename)
         elif format_ == "pack":
             for row in maplist:
                 if type_ == "stvds":
@@ -398,22 +400,22 @@ def import_stds(input, output, extrdir, title=None, descr=None, location=None,
                     filename = row["filename"] + ".pack"
                 if not os.path.exists(filename):
                     gscript.fatal(_("Unable to find GRASS package file "
-                                 "<%s> in archive.") % filename)
+                                    "<%s> in archive.") % filename)
         else:
             gscript.fatal(_("Unsupported input format"))
 
         # Check the space time dataset
         id = output + "@" + mapset
         sp = dataset_factory(type_, id)
-        if sp.is_in_db() and gscript.overwrite() == False:
-            gscript.fatal(_("Space time %(t)s dataset <%(sp)s> is already in the "
-                         "database. Use the overwrite flag.") % {'t': type_,
-                                                                 'sp': sp.get_id()})
+        if sp.is_in_db() and gscript.overwrite() is False:
+            gscript.fatal(_("Space time %(t)s dataset <%(sp)s> is already in"
+                            " the database. Use the overwrite flag.") %
+                          {'t': type_, 'sp': sp.get_id()})
 
         # Import the maps
         if type_ == "strds":
             if format_ == "GTiff" or format_ == "AAIGrid":
-                _import_raster_maps_from_gdal(maplist, overr, exp, location, 
+                _import_raster_maps_from_gdal(maplist, overr, exp, location,
                                               link, format_, set_current_region)
             if format_ == "pack":
                 _import_raster_maps(maplist, set_current_region)
@@ -425,11 +427,11 @@ def import_stds(input, output, extrdir, title=None, descr=None, location=None,
                 _import_vector_maps(maplist)
 
         # Create the space time dataset
-        if sp.is_in_db() and gscript.overwrite() == True:
+        if sp.is_in_db() and gscript.overwrite() is True:
             gscript.info(_("Overwrite space time %(sp)s dataset "
-                        "<%(id)s> and unregister all maps.") % {
-                        'sp': sp.get_new_map_instance(None).get_type(),
-                        'id': sp.get_id()})
+                           "<%(id)s> and unregister all maps.") %
+                         {'sp': sp.get_new_map_instance(None).get_type(),
+                          'id': sp.get_id()})
             sp.delete()
             sp = sp.get_new_instance(id)
 
@@ -438,12 +440,13 @@ def import_stds(input, output, extrdir, title=None, descr=None, location=None,
         relative_time_unit = None
         if temporal_type == "relative":
             if "relative_time_unit" not in init:
-                gscript.fatal(_("Key word %s not found in init file.") % ("relative_time_unit"))
+                gscript.fatal(_("Key word %s not found in init file.") %
+                              ("relative_time_unit"))
             relative_time_unit = init["relative_time_unit"]
             sp.set_relative_time_unit(relative_time_unit)
 
         gscript.verbose(_("Create space time %s dataset.") %
-                     sp.get_new_map_instance(None).get_type())
+                        sp.get_new_map_instance(None).get_type())
 
         sp.set_initial_values(temporal_type=temporal_type,
                               semantic_type=semantic_type, title=title,

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1216 - 798
lib/python/temporal/temporal_algebra.py


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 667 - 661
lib/python/temporal/temporal_extent.py


+ 499 - 226
lib/python/temporal/temporal_granularity.py

@@ -1,75 +1,73 @@
-"""!@package grass.temporal
+"""
+Functions to compute the temporal granularity of a map list
 
-@brief GRASS Python scripting module (temporal GIS functions)
+Usage:
 
-Temporal GIS related functions to be used in temporal GIS Python library package.
+.. code-block:: python
 
-Usage:
+    import grass.temporal as tgis
 
-@code
-import grass.temporal as tgis
+    tgis.compute_relative_time_granularity(maps)
 
-tgis.compute_relative_time_granularity(maps)
-...
-@endcode
 
 (C) 2012-2013 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
+:authors: Soeren Gebbert
 """
 from abstract_dataset import *
 from datetime_math import *
 
 ###############################################################################
 
+
 def check_granularity_string(granularity, temporal_type):
-    """!Check if the granularity string is valid
-
-        @param granularity The granularity string
-        @param temporal_type The temporal type of the granularity relative or absolute
-        @return True if valid, False if invalid
-
-        @code
-
-        >>> check_granularity_string("1 year", "absolute")
-        True
-        >>> check_granularity_string("1 month", "absolute")
-        True
-        >>> check_granularity_string("1 day", "absolute")
-        True
-        >>> check_granularity_string("1 minute", "absolute")
-        True
-        >>> check_granularity_string("1 hour", "absolute")
-        True
-        >>> check_granularity_string("1 second", "absolute")
-        True
-        >>> check_granularity_string("5 months", "absolute")
-        True
-        >>> check_granularity_string("5 days", "absolute")
-        True
-        >>> check_granularity_string("5 minutes", "absolute")
-        True
-        >>> check_granularity_string("5 years", "absolute")
-        True
-        >>> check_granularity_string("5 hours", "absolute")
-        True
-        >>> check_granularity_string("2 seconds", "absolute")
-        True
-        >>> check_granularity_string("1 secondo", "absolute")
-        False
-        >>> check_granularity_string("bla second", "absolute")
-        False
-        >>> check_granularity_string("bla", "absolute")
-        False
-        >>> check_granularity_string(1, "relative")
-        True
-        >>> check_granularity_string("bla", "relative")
-        False
-
-        @endcode
+    """Check if the granularity string is valid
+
+        :param granularity: The granularity string
+        :param temporal_type: The temporal type of the granularity relative or
+                              absolute
+        :return: True if valid, False if invalid
+
+        .. code-block:: python
+
+            >>> check_granularity_string("1 year", "absolute")
+            True
+            >>> check_granularity_string("1 month", "absolute")
+            True
+            >>> check_granularity_string("1 day", "absolute")
+            True
+            >>> check_granularity_string("1 minute", "absolute")
+            True
+            >>> check_granularity_string("1 hour", "absolute")
+            True
+            >>> check_granularity_string("1 second", "absolute")
+            True
+            >>> check_granularity_string("5 months", "absolute")
+            True
+            >>> check_granularity_string("5 days", "absolute")
+            True
+            >>> check_granularity_string("5 minutes", "absolute")
+            True
+            >>> check_granularity_string("5 years", "absolute")
+            True
+            >>> check_granularity_string("5 hours", "absolute")
+            True
+            >>> check_granularity_string("2 seconds", "absolute")
+            True
+            >>> check_granularity_string("1 secondo", "absolute")
+            False
+            >>> check_granularity_string("bla second", "absolute")
+            False
+            >>> check_granularity_string("bla", "absolute")
+            False
+            >>> check_granularity_string(1, "relative")
+            True
+            >>> check_granularity_string("bla", "relative")
+            False
+
     """
     temporal_type
 
@@ -102,113 +100,124 @@ def check_granularity_string(granularity, temporal_type):
 
 ###############################################################################
 
+
 def compute_relative_time_granularity(maps):
-    """!Compute the relative time granularity
+    """Compute the relative time granularity
 
         Attention: The computation of the granularity
         is only correct in case of not overlapping intervals.
         Hence a correct temporal topology is required for computation.
 
-        @param maps a ordered by start_time list of map objects
-        @return An integer
-
-
-        @code
-
-        >>> import grass.temporal as tgis
-        >>> tgis.init()
-        >>> maps = []
-        >>> for i in range(5):
-        ...   map = tgis.RasterDataset("a%i@P"%i)
-        ...   check = map.set_relative_time(i,i + 1,"seconds")
-        ...   if check:
-        ...     maps.append(map)
-        >>> tgis.compute_relative_time_granularity(maps)
-        1
-
-        >>> maps = []
-        >>> count = 0
-        >>> timelist = ((0,3), (3,6), (6,9))
-        >>> for t in timelist:
-        ...   map = tgis.RasterDataset("a%i@P"%count)
-        ...   check = map.set_relative_time(t[0],t[1],"years")
-        ...   if check:
-        ...     maps.append(map)
-        ...   count += 1
-        >>> tgis.compute_relative_time_granularity(maps)
-        3
-
-        >>> maps = []
-        >>> count = 0
-        >>> timelist = ((0,3), (4,6), (8,11))
-        >>> for t in timelist:
-        ...   map = tgis.RasterDataset("a%i@P"%count)
-        ...   check = map.set_relative_time(t[0],t[1],"years")
-        ...   if check:
-        ...     maps.append(map)
-        ...   count += 1
-        >>> tgis.compute_relative_time_granularity(maps)
-        1
-
-        >>> maps = []
-        >>> count = 0
-        >>> timelist = ((0,8), (2,6), (5,9))
-        >>> for t in timelist:
-        ...   map = tgis.RasterDataset("a%i@P"%count)
-        ...   check = map.set_relative_time(t[0],t[1],"months")
-        ...   if check:
-        ...     maps.append(map)
-        ...   count += 1
-        >>> tgis.compute_relative_time_granularity(maps)
-        4
-
-        >>> maps = []
-        >>> count = 0
-        >>> timelist = ((0,8), (8,12), (12,18))
-        >>> for t in timelist:
-        ...   map = tgis.RasterDataset("a%i@P"%count)
-        ...   check = map.set_relative_time(t[0],t[1],"days")
-        ...   if check:
-        ...     maps.append(map)
-        ...   count += 1
-        >>> tgis.compute_relative_time_granularity(maps)
-        2
-
-        >>> maps = []
-        >>> count = 0
-        >>> timelist = ((0,None), (8,None), (12,None), (24,None))
-        >>> for t in timelist:
-        ...   map = tgis.RasterDataset("a%i@P"%count)
-        ...   check = map.set_relative_time(t[0],t[1],"minutes")
-        ...   if check:
-        ...     maps.append(map)
-        ...   count += 1
-        >>> tgis.compute_relative_time_granularity(maps)
-        4
-
-        >>> maps = []
-        >>> count = 0
-        >>> timelist = ((0,None), (8,14), (18,None), (24,None))
-        >>> for t in timelist:
-        ...   map = tgis.RasterDataset("a%i@P"%count)
-        ...   check = map.set_relative_time(t[0],t[1],"hours")
-        ...   if check:
-        ...     maps.append(map)
-        ...   count += 1
-        >>> tgis.compute_relative_time_granularity(maps)
-        2
-
-        @endcode
+        :param maps: a ordered by start_time list of map objects
+        :return: An integer
+
+
+        .. code-block:: python
+
+            >>> import grass.temporal as tgis
+            >>> tgis.init()
+            >>> maps = []
+            >>> for i in range(5):
+            ...   map = tgis.RasterDataset("a%i@P"%i)
+            ...   check = map.set_relative_time(i,i + 1,"seconds")
+            ...   if check:
+            ...     maps.append(map)
+            >>> tgis.compute_relative_time_granularity(maps)
+            1
+
+            >>> maps = []
+            >>> count = 0
+            >>> timelist = ((0,3), (3,6), (6,9))
+            >>> for t in timelist:
+            ...   map = tgis.RasterDataset("a%i@P"%count)
+            ...   check = map.set_relative_time(t[0],t[1],"years")
+            ...   if check:
+            ...     maps.append(map)
+            ...   count += 1
+            >>> tgis.compute_relative_time_granularity(maps)
+            3
+
+            >>> maps = []
+            >>> count = 0
+            >>> timelist = ((0,3), (4,6), (8,11))
+            >>> for t in timelist:
+            ...   map = tgis.RasterDataset("a%i@P"%count)
+            ...   check = map.set_relative_time(t[0],t[1],"years")
+            ...   if check:
+            ...     maps.append(map)
+            ...   count += 1
+            >>> tgis.compute_relative_time_granularity(maps)
+            1
+
+            >>> maps = []
+            >>> count = 0
+            >>> timelist = ((0,8), (2,6), (5,9))
+            >>> for t in timelist:
+            ...   map = tgis.RasterDataset("a%i@P"%count)
+            ...   check = map.set_relative_time(t[0],t[1],"months")
+            ...   if check:
+            ...     maps.append(map)
+            ...   count += 1
+            >>> tgis.compute_relative_time_granularity(maps)
+            4
+
+            >>> maps = []
+            >>> count = 0
+            >>> timelist = ((0,8), (8,12), (12,18))
+            >>> for t in timelist:
+            ...   map = tgis.RasterDataset("a%i@P"%count)
+            ...   check = map.set_relative_time(t[0],t[1],"days")
+            ...   if check:
+            ...     maps.append(map)
+            ...   count += 1
+            >>> tgis.compute_relative_time_granularity(maps)
+            2
+
+            >>> maps = []
+            >>> count = 0
+            >>> timelist = ((0,None), (8,None), (12,None), (24,None))
+            >>> for t in timelist:
+            ...   map = tgis.RasterDataset("a%i@P"%count)
+            ...   check = map.set_relative_time(t[0],t[1],"minutes")
+            ...   if check:
+            ...     maps.append(map)
+            ...   count += 1
+            >>> tgis.compute_relative_time_granularity(maps)
+            4
+
+            >>> maps = []
+            >>> count = 0
+            >>> timelist = ((0,None), (8,14), (18,None), (24,None))
+            >>> for t in timelist:
+            ...   map = tgis.RasterDataset("a%i@P"%count)
+            ...   check = map.set_relative_time(t[0],t[1],"hours")
+            ...   if check:
+            ...     maps.append(map)
+            ...   count += 1
+            >>> tgis.compute_relative_time_granularity(maps)
+            2
+
+            >>> maps = []
+            >>> count = 0
+            >>> timelist = ((0,21),)
+            >>> for t in timelist:
+            ...   map = tgis.RasterDataset("a%i@P"%count)
+            ...   check = map.set_relative_time(t[0],t[1],"hours")
+            ...   if check:
+            ...     maps.append(map)
+            ...   count += 1
+            >>> tgis.compute_relative_time_granularity(maps)
+            21
+
     """
 
     # The interval time must be scaled to days resolution
     granularity = None
-
     delta = []
     # First we compute the timedelta of the intervals
     for map in maps:
         start, end = map.get_temporal_extent_as_tuple()
-        if start and end:
+        if (start == 0 or start) and end:
             t = abs(end - start)
             delta.append(int(t))
 
@@ -244,85 +253,84 @@ def compute_relative_time_granularity(maps):
 
 
 def compute_absolute_time_granularity(maps):
-    """!Compute the absolute time granularity
+    """Compute the absolute time granularity
 
         Attention: The computation of the granularity
         is only correct in case of not overlapping intervals.
         Hence a correct temporal topology is required for computation.
 
-        The computed granularity is returned as number of seconds or minutes or hours
-        or days or months or years.
-
-        @param maps a ordered by start_time list of map objects
-        @return The temporal topology as string "integer unit"
-
-        @code
-
-        >>> import grass.temporal as tgis
-        >>> import datetime
-        >>> dt = datetime.datetime
-        >>> tgis.init()
-        >>> maps = []
-        >>> count = 0
-        >>> timelist = ((dt(2000,01,01),None), (dt(2000,02,01),None))
-        >>> for t in timelist:
-        ...   map = tgis.RasterDataset("a%i@P"%count)
-        ...   check = map.set_absolute_time(t[0],t[1])
-        ...   if check:
-        ...     maps.append(map)
-        ...   count += 1
-        >>> tgis.compute_absolute_time_granularity(maps)
-        '1 month'
-
-        >>> maps = []
-        >>> count = 0
-        >>> timelist = ((dt(2000,01,01),None), (dt(2000,01,02),None), (dt(2000,01,03),None))
-        >>> for t in timelist:
-        ...   map = tgis.RasterDataset("a%i@P"%count)
-        ...   check = map.set_absolute_time(t[0],t[1])
-        ...   if check:
-        ...     maps.append(map)
-        ...   count += 1
-        >>> tgis.compute_absolute_time_granularity(maps)
-        '1 day'
-
-        >>> maps = []
-        >>> count = 0
-        >>> timelist = ((dt(2000,01,01),None), (dt(2000,01,02),None), (dt(2000,05,04,0,5,30),None))
-        >>> for t in timelist:
-        ...   map = tgis.RasterDataset("a%i@P"%count)
-        ...   check = map.set_absolute_time(t[0],t[1])
-        ...   if check:
-        ...     maps.append(map)
-        ...   count += 1
-        >>> tgis.compute_absolute_time_granularity(maps)
-        '30 seconds'
-
-        >>> maps = []
-        >>> count = 0
-        >>> timelist = ((dt(2000,01,01),dt(2000,05,02)), (dt(2000,05,04,2),None))
-        >>> for t in timelist:
-        ...   map = tgis.RasterDataset("a%i@P"%count)
-        ...   check = map.set_absolute_time(t[0],t[1])
-        ...   if check:
-        ...     maps.append(map)
-        ...   count += 1
-        >>> tgis.compute_absolute_time_granularity(maps)
-        '2 hours'
-
-        >>> maps = []
-        >>> count = 0
-        >>> timelist = ((dt(2000,01,01),dt(2000,02,01)), (dt(2005,05,04,12),dt(2007,05,20,6)))
-        >>> for t in timelist:
-        ...   map = tgis.RasterDataset("a%i@P"%count)
-        ...   check = map.set_absolute_time(t[0],t[1])
-        ...   if check:
-        ...     maps.append(map)
-        ...   count += 1
-        >>> tgis.compute_absolute_time_granularity(maps)
-        '6 hours'
-
-        @endcode
+        The computed granularity is returned as number of seconds or minutes
+        or hours or days or months or years.
+
+        :param maps: a ordered by start_time list of map objects
+        :return: The temporal topology as string "integer unit"
+
+        .. code-block:: python
+
+            >>> import grass.temporal as tgis
+            >>> import datetime
+            >>> dt = datetime.datetime
+            >>> tgis.init()
+            >>> maps = []
+            >>> count = 0
+            >>> timelist = ((dt(2000,01,01),None), (dt(2000,02,01),None))
+            >>> for t in timelist:
+            ...   map = tgis.RasterDataset("a%i@P"%count)
+            ...   check = map.set_absolute_time(t[0],t[1])
+            ...   if check:
+            ...     maps.append(map)
+            ...   count += 1
+            >>> tgis.compute_absolute_time_granularity(maps)
+            '1 month'
+
+            >>> maps = []
+            >>> count = 0
+            >>> timelist = ((dt(2000,01,01),None), (dt(2000,01,02),None), (dt(2000,01,03),None))
+            >>> for t in timelist:
+            ...   map = tgis.RasterDataset("a%i@P"%count)
+            ...   check = map.set_absolute_time(t[0],t[1])
+            ...   if check:
+            ...     maps.append(map)
+            ...   count += 1
+            >>> tgis.compute_absolute_time_granularity(maps)
+            '1 day'
+
+            >>> maps = []
+            >>> count = 0
+            >>> timelist = ((dt(2000,01,01),None), (dt(2000,01,02),None), (dt(2000,05,04,0,5,30),None))
+            >>> for t in timelist:
+            ...   map = tgis.RasterDataset("a%i@P"%count)
+            ...   check = map.set_absolute_time(t[0],t[1])
+            ...   if check:
+            ...     maps.append(map)
+            ...   count += 1
+            >>> tgis.compute_absolute_time_granularity(maps)
+            '30 seconds'
+
+            >>> maps = []
+            >>> count = 0
+            >>> timelist = ((dt(2000,01,01),dt(2000,05,02)), (dt(2000,05,04,2),None))
+            >>> for t in timelist:
+            ...   map = tgis.RasterDataset("a%i@P"%count)
+            ...   check = map.set_absolute_time(t[0],t[1])
+            ...   if check:
+            ...     maps.append(map)
+            ...   count += 1
+            >>> tgis.compute_absolute_time_granularity(maps)
+            '2 hours'
+
+            >>> maps = []
+            >>> count = 0
+            >>> timelist = ((dt(2000,01,01),dt(2000,02,01)), (dt(2005,05,04,12),dt(2007,05,20,6)))
+            >>> for t in timelist:
+            ...   map = tgis.RasterDataset("a%i@P"%count)
+            ...   check = map.set_absolute_time(t[0],t[1])
+            ...   if check:
+            ...     maps.append(map)
+            ...   count += 1
+            >>> tgis.compute_absolute_time_granularity(maps)
+            '6 hours'
+
     """
 
     has_seconds = False
@@ -486,6 +494,269 @@ def compute_absolute_time_granularity(maps):
     return None
 
 ###############################################################################
+
+def compute_common_relative_time_granularity(gran_list):
+	"""Compute the greatest common granule from a list of relative time granules
+    
+        .. code-block:: python
+
+            >>> import grass.temporal as tgis
+            >>> tgis.init()
+            >>> grans = [1,2,30]
+            >>> tgis.compute_common_relative_time_granularity(grans)
+            1
+            
+            >>> import grass.temporal as tgis
+            >>> tgis.init()
+            >>> grans = [10,20,30]
+            >>> tgis.compute_common_relative_time_granularity(grans)
+            10
+    """
+	return gcd_list(gran_list)
+
+###############################################################################
+
+def compute_common_absolute_time_granularity(gran_list):
+    """Compute the greatest common granule from a list of absolute time granules
+
+        .. code-block:: python
+
+            >>> import grass.temporal as tgis
+            >>> tgis.init()
+            >>> grans = ["1 second", "2 seconds", "30 seconds"]
+            >>> tgis.compute_common_absolute_time_granularity(grans)
+            '1 seconds'
+            
+            >>> grans = ["3 second", "6 seconds", "30 seconds"]
+            >>> tgis.compute_common_absolute_time_granularity(grans)
+            '3 seconds'
+            
+            >>> grans = ["12 second", "18 seconds", "30 seconds", "10 minutes"]
+            >>> tgis.compute_common_absolute_time_granularity(grans)
+            '6 seconds'
+            
+            >>> grans = ["20 second", "10 minutes", "2 hours"]
+            >>> tgis.compute_common_absolute_time_granularity(grans)
+            '20 seconds'
+            
+            >>> grans = ["7200 second", "240 minutes", "1 year"]
+            >>> tgis.compute_common_absolute_time_granularity(grans)
+            '7200 seconds'
+            
+            >>> grans = ["7200 second", "89 minutes", "1 year"]
+            >>> tgis.compute_common_absolute_time_granularity(grans)
+            '60 seconds'
+
+            >>> grans = ["10 minutes", "20 minutes", "30 minutes", "40 minutes", "2 hours"]
+            >>> tgis.compute_common_absolute_time_granularity(grans)
+            '10 minutes'
+
+            >>> grans = ["120 minutes", "2 hours"]
+            >>> tgis.compute_common_absolute_time_granularity(grans)
+            '120 minutes'
+
+            >>> grans = ["360 minutes", "3 hours"]
+            >>> tgis.compute_common_absolute_time_granularity(grans)
+            '180 minutes'
+
+            >>> grans = ["2 hours", "4 hours", "8 hours"]
+            >>> tgis.compute_common_absolute_time_granularity(grans)
+            '2 hours'
+
+            >>> grans = ["8 hours", "2 days"]
+            >>> tgis.compute_common_absolute_time_granularity(grans)
+            '8 hours'
+
+            >>> grans = ["48 hours", "1 month"]
+            >>> tgis.compute_common_absolute_time_granularity(grans)
+            '24 hours'
+
+            >>> grans = ["48 hours", "1 year"]
+            >>> tgis.compute_common_absolute_time_granularity(grans)
+            '24 hours'
+
+            >>> grans = ["2 months", "4 months", "1 year"]
+            >>> tgis.compute_common_absolute_time_granularity(grans)
+            '2 months'
+
+            >>> grans = ["120 months", "360 months", "4 years"]
+            >>> tgis.compute_common_absolute_time_granularity(grans)
+            '24 months'
+
+            >>> grans = ["120 months", "361 months", "4 years"]
+            >>> tgis.compute_common_absolute_time_granularity(grans)
+            '1 months'
+
+            >>> grans = ["2 years", "3 years", "4 years"]
+            >>> tgis.compute_common_absolute_time_granularity(grans)
+            '1 years'
+    """
+    
+    has_seconds = False # 0
+    has_minutes = False # 1
+    has_hours = False     # 2
+    has_days = False      # 3
+    has_months = False  # 4
+    has_years = False     # 5
+    
+    seconds = []
+    minutes = []
+    hours = []
+    days = []
+    months = []
+    years = []
+    
+    min_gran = 6
+    max_gran = -1
+    
+    for entry in gran_list:
+        if not check_granularity_string(entry, "absolute"):
+            return False
+
+        num,  gran = entry.split()
+        
+        if gran in ["seconds",  "second"]:
+            has_seconds = True
+            if min_gran > 0:
+                min_gran = 0
+            if max_gran < 0:
+                max_gran = 0
+                
+            seconds.append(int(num))
+
+        if gran in ["minutes",  "minute"]:
+            has_minutes = True
+            if min_gran > 1:
+                min_gran = 1
+            if max_gran < 1:
+                max_gran = 1
+                
+            minutes.append(int(num))
+
+        if gran in ["hours",  "hour"]:
+            has_hours = True
+            if min_gran > 2:
+                min_gran = 2
+            if max_gran < 2:
+                max_gran = 2
+                
+            hours.append(int(num))
+
+        if gran in ["days",  "day"]:
+            has_days = True
+            if min_gran > 3:
+                min_gran = 3
+            if max_gran < 3:
+                max_gran = 3
+                
+            days.append(int(num))
+
+        if gran in ["months",  "month"]:
+            has_months = True
+            if min_gran > 4:
+                min_gran = 4
+            if max_gran < 4:
+                max_gran = 4
+                
+            months.append(int(num))
+
+        if gran in ["years",  "year"]:
+            has_years = True
+            if min_gran > 5:
+                min_gran = 5
+            if max_gran < 5:
+                max_gran = 5
+                
+            years.append(int(num))
+            
+    if has_seconds:
+        if has_minutes:
+            minutes.sort()
+            seconds.append(minutes[0]*60)
+        if has_hours:
+            hours.sort()
+            seconds.append(hours[0]*60*60)
+        if has_days:
+            days.sort()
+            seconds.append(days[0]*60*60*24)
+        if has_months:
+            months.sort()
+            seconds.append(months[0]*60*60*24*28)
+            seconds.append(months[0]*60*60*24*29)
+            seconds.append(months[0]*60*60*24*30)
+            seconds.append(months[0]*60*60*24*31)
+        if has_years:
+            years.sort()
+            seconds.append(years[0]*60*60*24*365)
+            seconds.append(years[0]*60*60*24*366)
+
+        num = gcd_list(seconds)
+        return "%i %s"%(num,  "seconds")
+        
+    elif has_minutes:
+        if has_hours:
+            hours.sort()
+            minutes.append(hours[0]*60)
+        if has_days:
+            days.sort()
+            minutes.append(days[0]*60*24)
+        if has_months:
+            months.sort()
+            minutes.append(months[0]*60*24*28)
+            minutes.append(months[0]*60*24*29)
+            minutes.append(months[0]*60*24*30)
+            minutes.append(months[0]*60*24*31)
+        if has_years:
+            years.sort()
+            minutes.append(years[0]*60*24*365)
+            minutes.append(years[0]*60*24*366)
+        num = gcd_list(minutes)
+        return "%i %s"%(num,  "minutes")
+        
+    elif has_hours:
+        if has_days:
+            days.sort()
+            hours.append(days[0]*24)
+        if has_months:
+            months.sort()
+            hours.append(months[0]*24*28)
+            hours.append(months[0]*24*29)
+            hours.append(months[0]*24*30)
+            hours.append(months[0]*24*31)
+        if has_years:
+            years.sort()
+            hours.append(years[0]*24*365)
+            hours.append(years[0]*24*366)
+        num = gcd_list(hours)
+        return "%i %s"%(num,  "hours")
+
+    elif has_days:
+        if has_months:
+            months.sort()
+            days.append(months[0]*28)
+            days.append(months[0]*29)
+            days.append(months[0]*30)
+            days.append(months[0]*31)
+        if has_years:
+            years.sort()
+            days.append(years[0]*365)
+            days.append(years[0]*366)
+        num = gcd_list(days)
+        return "%i %s"%(num,  "days")
+
+    elif has_months:
+        if has_years:
+            years.sort()
+            months.append(years[0]*12)
+        num = gcd_list(months)
+        return "%i %s"%(num,  "months")
+        
+    elif has_years:
+        num = gcd_list(years)
+        return "%i %s"%(num,  "years")
+        
+
+###############################################################################
 # http://akiscode.com/articles/gcd_of_a_list.shtml
 # Copyright (c) 2010 Stephen Akiki
 # MIT License (Means you can do whatever you want with this)
@@ -495,7 +766,7 @@ def compute_absolute_time_granularity(maps):
 
 
 def gcd(a, b):
-    """!The Euclidean Algorithm """
+    """The Euclidean Algorithm """
     a = abs(a)
     b = abs(b)
     while a:
@@ -506,10 +777,12 @@ def gcd(a, b):
 
 
 def gcd_list(list):
-    """!Finds the GCD of numbers in a list.
-    Input: List of numbers you want to find the GCD of
-            E.g. [8, 24, 12]
-    Returns: GCD of all numbers
+    """Finds the GCD of numbers in a list.
+
+    :param list: List of numbers you want to find the GCD of
+                 E.g. [8, 24, 12]
+    :return: GCD of all numbers
+
     """
     return reduce(gcd, list)
 

+ 615 - 0
lib/python/temporal/temporal_operator.py

@@ -0,0 +1,615 @@
+"""@package grass.temporal
+
+Temporal operator evaluation with PLY
+
+(C) 2013 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.
+
+:authors: Thomas Leppelt and Soeren Gebbert
+
+.. code-block:: python
+
+    >>> p = TemporalOperatorParser()
+    >>> expression =  "{equal| during}"
+    >>> p.parse(expression, optype = 'relation')
+    >>> print(p.relations, p.temporal, p.function)
+    (['equal', 'during'], None, None)
+    >>> p = TemporalOperatorParser()    
+    >>> expression =  "{contains | starts}"
+    >>> p.parse(expression)
+    >>> print(p.relations, p.temporal, p.function)
+    (['contains', 'starts'], None, None)
+    >>> p = TemporalOperatorParser()    
+    >>> expression =  "{&&, during}"
+    >>> p.parse(expression, optype = 'boolean')
+    >>> print(p.relations, p.temporal, p.function,p.aggregate)
+    (['during'], 'l', '&&', '&')
+    >>> p = TemporalOperatorParser()    
+    >>> expression =  "{||, equal | during}"
+    >>> p.parse(expression, optype = 'boolean')
+    >>> print(p.relations, p.temporal, p.function,p.aggregate)
+    (['equal', 'during'], 'l', '||', '|')
+    >>> p = TemporalOperatorParser()    
+    >>> expression =  "{||, equal | during, &}"
+    >>> p.parse(expression, optype = 'boolean')
+    >>> print(p.relations, p.temporal, p.function,p.aggregate)
+    (['equal', 'during'], 'l', '||', '&')
+    >>> p = TemporalOperatorParser()    
+    >>> expression =  "{&&, during, |}"
+    >>> p.parse(expression, optype = 'boolean')
+    >>> print(p.relations, p.temporal, p.function,p.aggregate)
+    (['during'], 'l', '&&', '|')
+    >>> p = TemporalOperatorParser()    
+    >>> expression =  "{&&, during, |, r}"
+    >>> p.parse(expression, optype = 'boolean')
+    >>> print(p.relations, p.temporal, p.function,p.aggregate)
+    (['during'], 'r', '&&', '|')
+    >>> p = TemporalOperatorParser()    
+    >>> expression =  "{&&, during, u}"
+    >>> p.parse(expression, optype = 'boolean')
+    >>> print(p.relations, p.temporal, p.function,p.aggregate)
+    (['during'], 'u', '&&', '&')
+    >>> p = TemporalOperatorParser()    
+    >>> expression =  "{:, during, r}"
+    >>> p.parse(expression, optype = 'select')
+    >>> print(p.relations, p.temporal, p.function)
+    (['during'], 'r', ':')
+    >>> p = TemporalOperatorParser()    
+    >>> expression =  "{!:, equal | contains, d}"
+    >>> p.parse(expression, optype = 'select')
+    >>> print(p.relations, p.temporal, p.function)
+    (['equal', 'contains'], 'd', '!:')
+    >>> p = TemporalOperatorParser()    
+    >>> expression =  "{#, during, r}"
+    >>> p.parse(expression, optype = 'hash')
+    >>> print(p.relations, p.temporal, p.function)
+    (['during'], 'r', '#')
+    >>> p = TemporalOperatorParser()    
+    >>> expression =  "{#, equal | contains}"
+    >>> p.parse(expression, optype = 'hash')
+    >>> print(p.relations, p.temporal, p.function)
+    (['equal', 'contains'], 'l', '#')
+    >>> p = TemporalOperatorParser()    
+    >>> expression =  "{+, during, r}"
+    >>> p.parse(expression, optype = 'raster')
+    >>> print(p.relations, p.temporal, p.function)
+    (['during'], 'r', '+')
+    >>> p = TemporalOperatorParser()    
+    >>> expression =  "{/, equal | contains}"
+    >>> p.parse(expression, optype = 'raster')
+    >>> print(p.relations, p.temporal, p.function)
+    (['equal', 'contains'], 'l', '/')
+    >>> p = TemporalOperatorParser()    
+    >>> expression =  "{+, equal | contains,intersect}"
+    >>> p.parse(expression, optype = 'raster')
+    >>> print(p.relations, p.temporal, p.function)
+    (['equal', 'contains'], 'i', '+')
+    >>> p = TemporalOperatorParser()    
+    >>> expression =  "{*, contains,disjoint}"
+    >>> p.parse(expression, optype = 'raster')
+    >>> print(p.relations, p.temporal, p.function)
+    (['contains'], 'd', '*')
+    >>> p = TemporalOperatorParser()    
+    >>> expression =  "{~, equal,left}"
+    >>> p.parse(expression, optype = 'overlay')
+    >>> print(p.relations, p.temporal, p.function)
+    (['equal'], 'l', '~')
+    >>> p = TemporalOperatorParser()    
+    >>> expression =  "{^, over,right}"
+    >>> p.parse(expression, optype = 'overlay')
+    >>> print(p.relations, p.temporal, p.function)
+    (['overlaps', 'overlapped'], 'r', '^')
+
+"""
+
+try:
+    import ply.lex as lex
+    import ply.yacc as yacc
+except:
+    pass
+
+class TemporalOperatorLexer(object):
+    """Lexical analyzer for the GRASS GIS temporal operator"""
+
+    # Functions that defines topological relations.
+    relations = {
+        'equal'      : "EQUAL",
+        'follows'    : "FOLLOWS",
+        'precedes'   : "PRECEDES",
+        'overlaps'   : "OVERLAPS",
+        'overlapped' : "OVERLAPPED",
+        'during'     : "DURING",
+        'starts'     : "STARTS",
+        'finishes'   : "FINISHES",
+        'contains'   : "CONTAINS",
+        'started'    : "STARTED",
+        'finished'   : "FINISHED",
+        'over'       : "OVER"
+        }
+
+    # This is the list of token names.
+    tokens = (
+        'COMMA',
+        'LEFTREF',
+        'RIGHTREF',
+        'UNION', 
+        'DISJOINT',
+        'INTERSECT',
+        'HASH',
+        'OR',
+        'AND',
+        'DISOR',
+        'XOR',
+        'NOT',        
+        'MOD',
+        'DIV',
+        'MULT',
+        'ADD',      
+        'SUB',
+        'T_SELECT',
+        'T_NOT_SELECT',
+        'CLPAREN',
+        'CRPAREN',
+    )
+
+    # Build the token list
+    tokens = tokens + tuple(relations.values())
+
+    # Regular expression rules for simple tokens
+    t_T_SELECT                = r':'
+    t_T_NOT_SELECT        = r'!:'
+    t_COMMA                    = r','
+    t_LEFTREF                  = '^[l|left]'
+    t_RIGHTREF                ='^[r|right]'
+    t_UNION                     = '^[u|union]'
+    t_DISJOINT                 = '^[d|disjoint]'
+    t_INTERSECT             = '^[i|intersect]'
+    t_HASH                      = r'\#'
+    t_OR                          = r'[\|]'
+    t_AND                        = r'[&]'
+    t_DISOR                     = r'\+'
+    t_XOR                         = r'\^'
+    t_NOT                         = r'\~'    
+    t_MOD                       = r'[\%]'
+    t_DIV                         = r'[\/]'
+    t_MULT                      = r'[\*]'
+    t_ADD                       = r'[\+]'
+    t_SUB                        = r'[-]'
+    t_CLPAREN                = r'\{'
+    t_CRPAREN                = r'\}'
+
+    # These are the things that should be ignored.
+    t_ignore = ' \t'
+
+    # Track line numbers.
+    def t_newline(self, t):
+        r'\n+'
+        t.lineno += len(t.value)
+
+    def t_NAME(self, t):
+        r'[a-zA-Z_][a-zA-Z_0-9]*'
+        self.temporal_symbol(t)
+        return t
+
+    # Parse symbols
+    def temporal_symbol(self, t):
+        # Check for reserved words
+        if t.value in TemporalOperatorLexer.relations.keys():
+            t.type = TemporalOperatorLexer.relations.get(t.value)
+        elif t.value == 'l' or t.value == 'left':
+            t.value = 'l'
+            t.type = 'LEFTREF'
+        elif t.value == 'r' or t.value == 'right':
+            t.value = 'r'
+            t.type = 'RIGHTREF'
+        elif t.value == 'u' or t.value == 'union':
+            t.value = 'u'
+            t.type = 'UNION'
+        elif t.value == 'd' or t.value == 'disjoint':
+            t.value = 'd'
+            t.type = 'DISJOINT'
+        elif t.value == 'i' or t.value == 'intersect':
+            t.value = 'i'
+            t.type = 'INTERSECT'
+        #else:
+        #    t.type = 'NAME'
+        return(t)
+
+    # Handle errors.
+    def t_error(self, t):
+        raise SyntaxError("syntax error on line %d near '%s'" %
+            (t.lineno, t.value))
+
+    # Build the lexer
+    def build(self,**kwargs):
+        self.lexer = lex.lex(module=self, **kwargs)
+
+    # Just for testing
+    def test(self,data):
+        self.name_list = {}
+        print(data)
+        self.lexer.input(data)
+        while True:
+             tok = self.lexer.token()
+             if not tok: break
+             print tok
+
+###############################################################################
+
+class TemporalOperatorParser(object):
+    """The temporal operator class"""
+
+    def __init__(self):
+        self.lexer = TemporalOperatorLexer()
+        self.lexer.build()
+        self.parser = yacc.yacc(module=self)
+        self.relations = None
+        self.temporal  = None
+        self.function  = None
+        self.aggregate = None
+
+    def parse(self, expression,  optype = 'relation'):
+        self.optype = optype        
+        self.parser.parse(expression)
+        # The paramter optype can be of type: select {:, during, r}, boolean{&&, contains, |}, 
+        #                                                            raster{*, equal, |}, vector {|, starts, &},
+        #                                                            hash{#, during, l} or relation {during}.
+    
+    # Error rule for syntax errors.
+    def p_error(self, t):
+        raise SyntaxError("Unexpected syntax error")
+
+    # Get the tokens from the lexer class
+    tokens = TemporalOperatorLexer.tokens
+ 
+    def p_relation_operator(self, t):
+        # The expression should always return a list of maps.
+        """
+        operator : CLPAREN relation CRPAREN
+                 | CLPAREN relationlist CRPAREN
+        """
+        # Check for correct type.
+        if not self.optype == 'relation':
+            raise SyntaxError("invalid syntax")
+        else:
+            # Set three operator components.
+            if isinstance(t[2], list):
+                self.relations = t[2]
+            else:
+                self.relations = [t[2]]
+            self.temporal  = None
+            self.function  = None
+
+            t[0] = t[2]
+
+    def p_relation_bool_operator(self, t):
+        # The expression should always return a list of maps.
+        """
+        operator : CLPAREN OR OR COMMA relation CRPAREN
+                | CLPAREN AND AND COMMA relation CRPAREN
+                | CLPAREN OR OR COMMA relationlist CRPAREN
+                | CLPAREN AND AND COMMA relationlist CRPAREN
+        """
+        if not self.optype == 'boolean':
+            raise SyntaxError("invalid syntax")
+        else:        
+            # Set three operator components.
+            if isinstance(t[5], list):
+                self.relations = t[5]
+            else:
+                self.relations = [t[5]]
+            self.temporal  = "l"
+            self.function  = t[2] + t[3]
+            self.aggregate = t[2]
+            
+            t[0] = t[2]
+
+    def p_relation_bool_combi_operator(self, t):
+        # The expression should always return a list of maps.
+        """
+        operator : CLPAREN OR OR COMMA relation COMMA OR CRPAREN
+                | CLPAREN OR OR COMMA relation COMMA AND CRPAREN
+                | CLPAREN AND AND COMMA relation COMMA OR CRPAREN
+                | CLPAREN AND AND COMMA relation COMMA AND CRPAREN
+                | CLPAREN OR OR COMMA relationlist COMMA OR CRPAREN
+                | CLPAREN OR OR COMMA relationlist COMMA AND CRPAREN
+                | CLPAREN AND AND COMMA relationlist COMMA OR CRPAREN
+                | CLPAREN AND AND COMMA relationlist COMMA AND CRPAREN
+        """
+        if not self.optype == 'boolean':
+            raise SyntaxError("invalid syntax")
+        else:        
+            # Set three operator components.
+            if isinstance(t[5], list):
+                self.relations = t[5]
+            else:
+                self.relations = [t[5]]
+            self.temporal  = "l"
+            self.function  = t[2] + t[3]
+            self.aggregate = t[7]
+            
+            t[0] = t[2]
+
+    def p_relation_bool_combi_operator2(self, t):
+        # The expression should always return a list of maps.
+        """
+        operator : CLPAREN OR OR COMMA relation COMMA temporal CRPAREN
+                | CLPAREN AND AND COMMA relation COMMA temporal CRPAREN
+                | CLPAREN OR OR COMMA relationlist COMMA temporal CRPAREN
+                | CLPAREN AND AND COMMA relationlist COMMA temporal CRPAREN
+        """
+        if not self.optype == 'boolean':
+            raise SyntaxError("invalid syntax")
+        else:        
+            # Set three operator components.
+            if isinstance(t[5], list):
+                self.relations = t[5]
+            else:
+                self.relations = [t[5]]
+            self.temporal  = t[7]
+            self.function  = t[2] + t[3]
+            self.aggregate = t[2]
+            
+            t[0] = t[2]
+    
+    def p_relation_bool_combi_operator3(self, t):
+        # The expression should always return a list of maps.
+        """
+        operator : CLPAREN OR OR COMMA relation COMMA OR COMMA temporal CRPAREN
+                | CLPAREN OR OR COMMA relation COMMA AND COMMA temporal CRPAREN
+                | CLPAREN AND AND COMMA relation COMMA OR COMMA temporal CRPAREN
+                | CLPAREN AND AND COMMA relation COMMA AND COMMA temporal CRPAREN
+                | CLPAREN OR OR COMMA relationlist COMMA OR COMMA temporal CRPAREN
+                | CLPAREN OR OR COMMA relationlist COMMA AND COMMA temporal CRPAREN
+                | CLPAREN AND AND COMMA relationlist COMMA OR COMMA temporal CRPAREN
+                | CLPAREN AND AND COMMA relationlist COMMA AND COMMA temporal CRPAREN
+        """
+        if not self.optype == 'boolean':
+            raise SyntaxError("invalid syntax")
+        else:        
+            # Set three operator components.
+            if isinstance(t[5], list):
+                self.relations = t[5]
+            else:
+                self.relations = [t[5]]
+            self.temporal  = t[9]
+            self.function  = t[2] + t[3]
+            self.aggregate = t[7]
+            
+            t[0] = t[2]
+    
+    def p_select_relation_operator(self, t):
+        # The expression should always return a list of maps.
+        """
+        operator : CLPAREN select CRPAREN
+                    | CLPAREN select COMMA relation CRPAREN
+                    | CLPAREN select COMMA relationlist CRPAREN
+                    | CLPAREN select COMMA relation COMMA temporal CRPAREN
+                    | CLPAREN select COMMA relationlist COMMA temporal CRPAREN
+        """
+        if not self.optype == 'select':
+            raise SyntaxError("invalid syntax")
+        else:
+            if len(t) == 4:
+                # Set three operator components.
+                self.relations = ['equal']
+                self.temporal  = "l"
+                self.function  = t[2]
+            elif len(t) == 5:
+                self.relations = ['equal']
+                self.temporal  = t[3]
+                self.function  = t[2]
+            elif len(t) == 6:
+                if isinstance(t[4], list):
+                    self.relations = t[4]
+                else:
+                    self.relations = [t[4]]
+                self.temporal  = "l"
+                self.function  = t[2]
+            elif len(t) == 8:
+                if isinstance(t[4], list):
+                    self.relations = t[4]
+                else:
+                    self.relations = [t[4]]
+                self.temporal  = t[6]
+                self.function  = t[2]
+            t[0] = t[2]
+
+    def p_hash_relation_operator(self, t):
+        # The expression should always return a list of maps.
+        """
+        operator : CLPAREN HASH CRPAREN
+                    | CLPAREN HASH COMMA relation CRPAREN
+                    | CLPAREN HASH COMMA relationlist CRPAREN
+                    | CLPAREN HASH COMMA relation COMMA temporal CRPAREN
+                    | CLPAREN HASH COMMA relationlist COMMA temporal CRPAREN
+        """
+        if not self.optype == 'hash':
+            raise SyntaxError("invalid syntax")
+        else:
+            if len(t) == 4:
+                # Set three operator components.
+                self.relations = ['equal']
+                self.temporal  = "l"
+                self.function  = t[2]
+            elif len(t) == 5:
+                self.relations = ['equal']
+                self.temporal  = t[3]
+                self.function  = t[2]
+            elif len(t) == 6:
+                if isinstance(t[4], list):
+                    self.relations = t[4]
+                else:
+                    self.relations = [t[4]]
+                self.temporal  = "l"
+                self.function  = t[2]
+            elif len(t) == 8:
+                if isinstance(t[4], list):
+                    self.relations = t[4]
+                else:
+                    self.relations = [t[4]]
+                self.temporal  = t[6]
+                self.function  = t[2]
+            t[0] = t[2]
+
+    def p_raster_relation_operator(self, t):
+        # The expression should always return a list of maps.
+        """
+        operator : CLPAREN arithmetic CRPAREN
+                    | CLPAREN arithmetic COMMA relation CRPAREN
+                    | CLPAREN arithmetic COMMA relationlist CRPAREN
+                    | CLPAREN arithmetic COMMA relation COMMA temporal CRPAREN
+                    | CLPAREN arithmetic COMMA relationlist COMMA temporal CRPAREN
+        """
+        if not self.optype == 'raster':
+            raise SyntaxError("invalid syntax")
+        else:
+            if len(t) == 4:
+                # Set three operator components.
+                self.relations = ['equal']
+                self.temporal  = "l"
+                self.function  = t[2]
+            elif len(t) == 5:
+                self.relations = ['equal']
+                self.temporal  = t[3]
+                self.function  = t[2]
+            elif len(t) == 6:
+                if isinstance(t[4], list):
+                    self.relations = t[4]
+                else:
+                    self.relations = [t[4]]
+                self.temporal  = "l"
+                self.function  = t[2]
+            elif len(t) == 8:
+                if isinstance(t[4], list):
+                    self.relations = t[4]
+                else:
+                    self.relations = [t[4]]
+                self.temporal  = t[6]
+                self.function  = t[2]
+            t[0] = t[2]
+
+    def p_overlay_relation_operator(self, t):
+        # The expression should always return a list of maps.
+        """
+        operator : CLPAREN overlay CRPAREN
+                    | CLPAREN overlay COMMA relation CRPAREN
+                    | CLPAREN overlay COMMA relationlist CRPAREN
+                    | CLPAREN overlay COMMA relation COMMA temporal CRPAREN
+                    | CLPAREN overlay COMMA relationlist COMMA temporal CRPAREN
+        """
+        if not self.optype == 'overlay':
+            raise SyntaxError("invalid syntax")
+        else:
+            if len(t) == 4:
+                # Set three operator components.
+                self.relations = ['equal']
+                self.temporal  = "l"
+                self.function  = t[2]
+            elif len(t) == 5:
+                self.relations = ['equal']
+                self.temporal  = t[3]
+                self.function  = t[2]
+            elif len(t) == 6:
+                if isinstance(t[4], list):
+                    self.relations = t[4]
+                else:
+                    self.relations = [t[4]]
+                self.temporal  = "l"
+                self.function  = t[2]
+            elif len(t) == 8:
+                if isinstance(t[4], list):
+                    self.relations = t[4]
+                else:
+                    self.relations = [t[4]]
+                self.temporal  = t[6]
+                self.function  = t[2]
+            t[0] = t[2]
+
+    def p_relation(self, t):
+        # The list of relations.
+        """
+        relation : EQUAL
+                 | FOLLOWS
+                 | PRECEDES
+                 | OVERLAPS
+                 | OVERLAPPED
+                 | DURING
+                 | STARTS
+                 | FINISHES
+                 | CONTAINS
+                 | STARTED
+                 | FINISHED
+        """
+        t[0] = t[1]
+
+    def p_over(self, t):
+        # The list of relations.
+        """
+        relation : OVER
+        """
+        over_list = ["overlaps", "overlapped"]
+        t[0] = over_list
+
+    def p_relationlist(self, t):
+        # The list of relations.
+        """
+        relationlist : relation OR relation
+                     | relation OR relationlist
+        """
+        rel_list = []
+        rel_list.append(t[1])
+        if isinstance(t[3], list):
+            rel_list = rel_list + t[3]
+        else:
+            rel_list.append(t[3])
+        t[0] =  rel_list
+
+    def p_temporal_operator(self, t):
+        # The list of relations.
+        """
+        temporal : LEFTREF
+                | RIGHTREF
+                | UNION
+                | DISJOINT
+                | INTERSECT
+        """
+        t[0] = t[1]
+
+    def p_select_operator(self, t):
+        # The list of relations.
+        """
+        select : T_SELECT
+               | T_NOT_SELECT
+        """
+        t[0] = t[1]
+
+    def p_arithmetic_operator(self, t):
+        # The list of relations.
+        """
+        arithmetic : MOD
+                   | DIV
+                   | MULT
+                   | ADD
+                   | SUB
+        """
+        t[0] = t[1]
+
+    def p_overlay_operator(self, t):
+        # The list of relations.
+        """
+        overlay : AND
+                   | OR
+                   | XOR
+                   | DISOR
+                   | NOT
+        """
+        t[0] = t[1]
+###############################################################################
+
+if __name__ == "__main__":
+    import doctest
+    doctest.testmod()
+

+ 16 - 20
lib/python/temporal/temporal_raster3d_algebra.py

@@ -7,7 +7,7 @@ This program is free software under the GNU General Public
 License (>=v2). Read the file COPYING that comes with GRASS
 for details.
 
-@author Thomas Leppelt and Soeren Gebbert
+:authors: Thomas Leppelt and Soeren Gebbert
 
 """
 
@@ -23,9 +23,21 @@ class TemporalRaster3DAlgebraParser(TemporalRasterBaseAlgebraParser):
         TemporalRasterBaseAlgebraParser.__init__(self, pid, run, debug, spatial, nprocs, register_null)
 
         self.m_mapcalc = pymod.Module('r3.mapcalc')
-        self.m_remove = pymod.Module('g.remove')
+        self.m_mremove = pymod.Module('g.remove')
 
     def parse(self, expression, basename = None, overwrite=False):
+        # Check for space time dataset type definitions from temporal algebra
+        l = TemporalRasterAlgebraLexer()
+        l.build()
+        l.lexer.input(expression)
+
+        while True:
+            tok = l.lexer.token()
+            if not tok: break
+            
+            if tok.type == "STVDS" or tok.type == "STRDS" or tok.type == "STR3DS":
+                raise SyntaxError("Syntax error near '%s'" %(tok.type))
+
         self.lexer = TemporalRasterAlgebraLexer()
         self.lexer.build()
         self.parser = yacc.yacc(module=self, debug=self.debug)
@@ -33,28 +45,12 @@ class TemporalRaster3DAlgebraParser(TemporalRasterBaseAlgebraParser):
         self.overwrite = overwrite
         self.count = 0
         self.stdstype = "str3ds"
+        self.maptype = "rast3d"
+        self.mapclass = Raster3DDataset
         self.basename = basename
         self.expression = expression
         self.parser.parse(expression)
 
-    def remove_empty_maps(self):
-        """! Removes the intermediate vector maps.
-        """
-        if self.empty_maps:
-            self.msgr.message(_("Removing empty 3D raster maps"))
-            namelist = self.empty_maps.values()
-            max = 100
-            chunklist = [namelist[i:i + max] for i in range(0, len(namelist), max)]
-            for chunk in chunklist:
-                stringlist = ",".join(chunk)
-
-                if self.run:
-                    m = copy.deepcopy(self.m_remove)
-                    m.inputs["type"].value = "rast3d"
-                    m.inputs["pattern"].value = stringlist
-                    m.flags["f"].value = True
-                    m.run()
-
     ######################### Temporal functions ##############################
 
     def p_statement_assign(self, t):

+ 17 - 22
lib/python/temporal/temporal_raster_algebra.py

@@ -7,9 +7,9 @@ This program is free software under the GNU General Public
 License (>=v2). Read the file COPYING that comes with GRASS
 for details.
 
-@author Thomas Leppelt and Soeren Gebbert
+:authors: Thomas Leppelt and Soeren Gebbert
 
-@code
+.. code-block:: python
 
     >>> p = TemporalRasterAlgebraLexer()
     >>> p.build()
@@ -50,7 +50,6 @@ for details.
     LexToken(SUB,'-',1,40)
     LexToken(FLOAT,2.45,1,42)
 
-@endcode
 """
 
 from temporal_raster_base_algebra import *
@@ -64,9 +63,21 @@ class TemporalRasterAlgebraParser(TemporalRasterBaseAlgebraParser):
         TemporalRasterBaseAlgebraParser.__init__(self, pid, run, debug, spatial, nprocs, register_null)
 
         self.m_mapcalc = pymod.Module('r.mapcalc')
-        self.m_remove = pymod.Module('g.remove')
+        self.m_mremove = pymod.Module('g.remove')
 
     def parse(self, expression, basename = None, overwrite=False):
+        # Check for space time dataset type definitions from temporal algebra
+        l = TemporalRasterAlgebraLexer()
+        l.build()
+        l.lexer.input(expression)
+
+        while True:
+            tok = l.lexer.token()
+            if not tok: break
+            
+            if tok.type == "STVDS" or tok.type == "STRDS" or tok.type == "STR3DS":
+                raise SyntaxError("Syntax error near '%s'" %(tok.type))
+        
         self.lexer = TemporalRasterAlgebraLexer()
         self.lexer.build()
         self.parser = yacc.yacc(module=self, debug=self.debug)
@@ -74,28 +85,12 @@ class TemporalRasterAlgebraParser(TemporalRasterBaseAlgebraParser):
         self.overwrite = overwrite
         self.count = 0
         self.stdstype = "strds"
+        self.maptype = "rast"
+        self.mapclass = RasterDataset
         self.basename = basename
         self.expression = expression
         self.parser.parse(expression)
 
-    def remove_empty_maps(self):
-        """! Removes the intermediate vector maps.
-        """
-        if self.empty_maps:
-            self.msgr.message(_("Removing empty raster maps"))
-            namelist = self.empty_maps.values()
-            max = 100
-            chunklist = [namelist[i:i + max] for i in range(0, len(namelist), max)]
-            for chunk in chunklist:
-                stringlist = ",".join(chunk)
-
-                if self.run:
-                    m = copy.deepcopy(self.m_remove)
-                    m.inputs["type"].value = "rast"
-                    m.inputs["pattern"].value = stringlist
-                    m.flags["f"].value = True
-                    m.run()
-
     ######################### Temporal functions ##############################
 
     def p_statement_assign(self, t):

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 800 - 1845
lib/python/temporal/temporal_raster_base_algebra.py


+ 0 - 390
lib/python/temporal/temporal_raster_operator.py

@@ -1,390 +0,0 @@
-"""!@package grass.temporal
-
-Temporal operator evaluation with PLY
-
-(C) 2013 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 Thomas Leppelt and Soeren Gebbert
-
-@code
-    >>> p = TemporalRasterOperatorParser()
-    >>> expression =  "{equal| during | follows,+!:}"
-    >>> p.parse(expression)
-    >>> print(p.relations, p.temporal, p.function)
-    (['equal', 'during', 'follows'], '+', '!:')
-    >>> expression =  "{equal| during,!:}"
-    >>> p.parse(expression)
-    >>> print(p.relations, p.temporal, p.function)
-    (['equal', 'during'], '=', '!:')
-    >>> expression =  "{!:}"
-    >>> p.parse(expression)
-    >>> print(p.relations, p.temporal, p.function)
-    (['equal'], '=', '!:')
-    >>> expression =  "{|#}"
-    >>> p.parse(expression)
-    >>> print(p.relations, p.temporal, p.function)
-    (['equal'], '|', '#')
-    >>> expression =  "{equal|during,=!:}"
-    >>> p.parse(expression)
-    >>> print(p.relations, p.temporal, p.function)
-    (['equal', 'during'], '=', '!:')
-    >>> expression =  "{equal|during|starts}"
-    >>> p.parse(expression)
-    >>> print(p.relations, p.temporal, p.function)
-    (['equal', 'during', 'starts'], None, None)
-    >>> expression =  "{equal,++}"
-    >>> p.parse(expression)
-    >>> print(p.relations, p.temporal, p.function)
-    (['equal'], '+', '+')
-    >>> expression =  "{equal | during,|%}"
-    >>> p.parse(expression)
-    >>> print(p.relations, p.temporal, p.function)
-    (['equal', 'during'], '|', '%')
-    >>> expression =  "{||}"
-    >>> p.parse(expression)
-    >>> print(p.relations, p.temporal, p.function)
-    (['equal'], '=', '||')
-    >>> expression =  "{equal,||}"
-    >>> p.parse(expression)
-    >>> print(p.relations, p.temporal, p.function)
-    (['equal'], '=', '||')
-    >>> expression =  "{equal | during | contains,&&}"
-    >>> p.parse(expression)
-    >>> print(p.relations, p.temporal, p.function)
-    (['equal', 'during', 'contains'], '=', '&&')
-    >>> expression =  "{equal | during | contains,/}"
-    >>> p.parse(expression)
-    >>> print(p.relations, p.temporal, p.function)
-    (['equal', 'during', 'contains'], '=', '/')
-    >>> expression =  "{equal | during | contains,|*}"
-    >>> p.parse(expression)
-    >>> print(p.relations, p.temporal, p.function)
-    (['equal', 'during', 'contains'], '|', '*')
-
-@endcode
-"""
-
-try:
-    import ply.lex as lex
-    import ply.yacc as yacc
-except:
-    pass
-
-class TemporalRasterOperatorLexer(object):
-    """!Lexical analyzer for the GRASS GIS temporal operator"""
-
-    # Functions that defines topological relations.
-    relations = {
-        'equal'      : "EQUAL",
-        'follows'    : "FOLLOWS",
-        'precedes'   : "PRECEDES",
-        'overlaps'   : "OVERLAPS",
-        'overlapped' : "OVERLAPPED",
-        'during'     : "DURING",
-        'starts'     : "STARTS",
-        'finishes'   : "FINISHES",
-        'contains'   : "CONTAINS",
-        'started'    : "STARTED",
-        'finished'   : "FINISHED",
-        'over'       : "OVER"
-        }
-
-    # This is the list of token names.
-    tokens = (
-        'COMMA',
-        'LEFTREF',
-        'HASH',
-        'OR',
-        'AND',
-        'MOD',
-        'DIV',
-        'MULT',
-        'ADD',
-        'SUB',
-        'T_SELECT',
-        'T_NOT_SELECT',
-        'CLPAREN',
-        'CRPAREN',
-    )
-
-    # Build the token list
-    tokens = tokens + tuple(relations.values())
-
-    # Regular expression rules for simple tokens
-    t_T_SELECT           = r':'
-    t_T_NOT_SELECT       = r'!:'
-    t_COMMA              = r','
-    t_LEFTREF             = r'='
-    t_HASH               = r'\#'
-    t_OR                 = r'[\|]'
-    t_AND                = r'[&]'
-    t_MOD                = r'[\%]'
-    t_DIV                = r'[\/]'
-    t_MULT               = r'[\*]'
-    t_ADD                = r'[\+]'
-    t_SUB                = r'[-]'
-    t_CLPAREN             = r'\{'
-    t_CRPAREN             = r'\}'
-
-    # These are the things that should be ignored.
-    t_ignore = ' \t'
-
-    # Track line numbers.
-    def t_newline(self, t):
-        r'\n+'
-        t.lineno += len(t.value)
-
-    def t_NAME(self, t):
-        r'[a-zA-Z_][a-zA-Z_0-9]*'
-        self.temporal_symbol(t)
-        return t
-
-    # Parse symbols
-    def temporal_symbol(self, t):
-        # Check for reserved words
-        if t.value in TemporalRasterOperatorLexer.relations.keys():
-            t.type = TemporalRasterOperatorLexer.relations.get(t.value)
-        #else:
-        #    t.type = 'NAME'
-        return(t)
-
-    # Handle errors.
-    def t_error(self, t):
-        raise SyntaxError("syntax error on line %d near '%s'" %
-            (t.lineno, t.value))
-
-    # Build the lexer
-    def build(self,**kwargs):
-        self.lexer = lex.lex(module=self, **kwargs)
-
-    # Just for testing
-    def test(self,data):
-        self.name_list = {}
-        print(data)
-        self.lexer.input(data)
-        while True:
-             tok = self.lexer.token()
-             if not tok: break
-             print tok
-
-###############################################################################
-
-class TemporalRasterOperatorParser(object):
-    """The temporal algebra class"""
-
-    def __init__(self):
-        self.lexer = TemporalRasterOperatorLexer()
-        self.lexer.build()
-        self.parser = yacc.yacc(module=self)
-
-    def parse(self, expression, comparison = False):
-        self.comparison = comparison
-        self.parser.parse(expression)
-
-    # Error rule for syntax errors.
-    def p_error(self, t):
-        raise SyntaxError("invalid syntax")
-
-    # Get the tokens from the lexer class
-    tokens = TemporalRasterOperatorLexer.tokens
-
-    def p_relation_only(self, t):
-        # The expression should always return a list of maps.
-        """
-        operator : CLPAREN relation CRPAREN
-                 | CLPAREN relationlist CRPAREN
-        """
-        # Set three operator components.
-        if isinstance(t[2], list):
-            self.relations = t[2]
-        else:
-            self.relations = [t[2]]
-        self.temporal  = None
-        self.function  = None
-
-        t[0] = t[2]
-
-
-    def p_operator(self, t):
-        # The expression should always return a list of maps.
-        """
-        operator : CLPAREN select CRPAREN
-                 | CLPAREN HASH CRPAREN
-                 | CLPAREN arithmetic CRPAREN
-        """
-        # Set three operator components.
-        self.relations = ['equal']
-        self.temporal  = "="
-        self.function  = t[2]
-
-        t[0] = t[2]
-
-    def p_comparison(self, t):
-        # The expression should always return a list of maps.
-        """
-        operator : CLPAREN temporal AND CRPAREN
-                 | CLPAREN temporal OR CRPAREN
-        """
-        # Set three operator components.
-        self.relations = ['equal']
-        self.temporal  = "="
-        if t[2] == t[3]:
-            self.function  = t[2] + t[3]
-        else:
-            raise SyntaxError("syntax error on line %d near '%s'" %
-                                (t.lineno, t.value))
-
-        t[0] = t[2]
-
-    def p_operator_temporal(self, t):
-        # The expression should always return a list of maps.
-        """
-        operator : CLPAREN temporal select CRPAREN
-                 | CLPAREN temporal HASH CRPAREN
-                 | CLPAREN temporal arithmetic CRPAREN
-        """
-        # Set three operator components.
-        self.relations = ['equal']
-        self.temporal = t[2]
-        self.function = t[3]
-
-        t[0] = t[3]
-
-    def p_operator_relation(self, t):
-        # The expression should always return a list of maps.
-        """
-        operator : CLPAREN relation COMMA select CRPAREN
-                 | CLPAREN relationlist COMMA select CRPAREN
-                 | CLPAREN relation COMMA HASH CRPAREN
-                 | CLPAREN relationlist COMMA HASH CRPAREN
-                 | CLPAREN relation COMMA arithmetic CRPAREN
-                 | CLPAREN relationlist COMMA arithmetic CRPAREN
-        """
-        # Set three operator components.
-        if isinstance(t[2], list):
-            self.relations = t[2]
-        else:
-            self.relations = [t[2]]
-        self.temporal  = "="
-        self.function  = t[4]
-
-        t[0] = t[4]
-
-    def p_comparison_relation(self, t):
-        # The expression should always return a list of maps.
-        """
-        operator : CLPAREN relation COMMA temporal AND CRPAREN
-                 | CLPAREN relation COMMA temporal OR CRPAREN
-                 | CLPAREN relationlist COMMA temporal AND CRPAREN
-                 | CLPAREN relationlist COMMA temporal OR CRPAREN
-        """
-        # Set three operator components.
-        if isinstance(t[2], list):
-            self.relations = t[2]
-        else:
-            self.relations = [t[2]]
-        self.temporal  = "="
-        if t[4] == t[5]:
-            self.function  = t[4] + t[5]
-        else:
-            raise SyntaxError("syntax error on line %d near '%s'" %
-                                (t.lineno, t.value))
-
-        t[0] = t[4]
-
-    def p_operator_relation_temporal(self, t):
-        # The expression should always return a list of maps.
-        """
-        operator : CLPAREN relation COMMA temporal select CRPAREN
-                 | CLPAREN relationlist COMMA temporal select CRPAREN
-                 | CLPAREN relation COMMA temporal HASH CRPAREN
-                 | CLPAREN relationlist COMMA temporal HASH CRPAREN
-                 | CLPAREN relation COMMA temporal arithmetic CRPAREN
-                 | CLPAREN relationlist COMMA temporal arithmetic CRPAREN
-        """
-        # Set three operator components.
-        if isinstance(t[2], list):
-            self.relations = t[2]
-        else:
-            self.relations = [t[2]]
-        self.temporal = t[4]
-        self.function = t[5]
-        t[0] = t[5]
-
-    def p_relation(self, t):
-        # The list of relations.
-        """
-        relation : EQUAL
-                 | FOLLOWS
-                 | PRECEDES
-                 | OVERLAPS
-                 | OVERLAPPED
-                 | DURING
-                 | STARTS
-                 | FINISHES
-                 | CONTAINS
-                 | STARTED
-                 | FINISHED
-        """
-        t[0] = t[1]
-
-    def p_over(self, t):
-        # The list of relations.
-        """
-        relation : OVER
-        """
-        over_list = ["overlaps", "overlapped"]
-        t[0] = over_list
-
-    def p_relationlist(self, t):
-        # The list of relations.
-        """
-        relationlist : relation OR relation
-                     | relation OR relationlist
-        """
-        rel_list = []
-        rel_list.append(t[1])
-        if isinstance(t[3], list):
-            rel_list = rel_list + t[3]
-        else:
-            rel_list.append(t[3])
-        t[0] =  rel_list
-
-    def p_temporal_operator(self, t):
-        # The list of relations.
-        """
-        temporal : LEFTREF
-                 | OR
-                 | AND
-                 | ADD
-        """
-        t[0] = t[1]
-
-    def p_select_operator(self, t):
-        # The list of relations.
-        """
-        select : T_SELECT
-               | T_NOT_SELECT
-        """
-        t[0] = t[1]
-
-    def p_arithmetic_operator(self, t):
-        # The list of relations.
-        """
-        arithmetic : MOD
-                   | DIV
-                   | MULT
-                   | ADD
-                   | SUB
-        """
-        t[0] = t[1]
-
-###############################################################################
-
-if __name__ == "__main__":
-    import doctest
-    doctest.testmod()
-

+ 211 - 221
lib/python/temporal/temporal_topology_dataset_connector.py

@@ -1,34 +1,36 @@
 # -*- coding: utf-8 -*-
-"""!@package grass.temporal
-
-@brief GRASS Python scripting module (temporal GIS functions)
-
-Temporal GIS related functions to be used in temporal GIS Python library package.
+"""
+Temporal topology dataset connector class
 
 Usage:
 
->>> import grass.temporal as tgis
->>> tmr = tgis.TemporalTopologyDatasetConnector()
+.. code-block:: python:
+
+    >>> import grass.temporal as tgis
+    >>> tmr = tgis.TemporalTopologyDatasetConnector()
 
 (C) 2012-2013 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
+:authors: Soeren Gebbert
 """
 import copy
 
+
 class TemporalTopologyDatasetConnector(object):
-    """!This class implements a temporal topology access structure to connect temporal related datasets
+    """This class implements a temporal topology access structure to connect
+       temporal related datasets
 
-       This object will be set up by temporal topology creation method provided by the 
-       SpatioTemporalTopologyBuilder.
+       This object will be set up by temporal topology creation method provided
+       by the SpatioTemporalTopologyBuilder.
 
-       If correctly initialize the calls next() and prev() 
+       If correctly initialize the calls next() and prev()
        let the user walk temporally forward and backward in time.
 
        The following temporal relations with access methods are supported:
+
        - equal
        - follows
        - precedes
@@ -41,101 +43,96 @@ class TemporalTopologyDatasetConnector(object):
        - finishes
        - finished
 
+       .. code-block:: python:
+
+           # We have build the temporal topology and we know the first map
+           start = first
+           while start:
+
+               # Print all maps this map temporally contains
+               dlist = start.get_contains()
+               for map in dlist:
+                   map.print_info()
+
+               start = start.next()
+
+            >>> import grass.temporal as tgis
+            >>> tgis.init()
+            >>> map = tgis.RasterDataset("a@P")
+            >>> tmr = tgis.TemporalTopologyDatasetConnector()
+            >>> tmr.set_next(map)
+            >>> tmr.set_prev(map)
+            >>> tmr.append_equal(map)
+            >>> tmr.append_follows(map)
+            >>> tmr.append_precedes(map)
+            >>> tmr.append_overlapped(map)
+            >>> tmr.append_overlaps(map)
+            >>> tmr.append_during(map)
+            >>> tmr.append_contains(map)
+            >>> tmr.append_starts(map)
+            >>> tmr.append_started(map)
+            >>> tmr.append_finishes(map)
+            >>> tmr.append_finished(map)
+            >>> tmr.print_temporal_topology_info()
+             +-------------------- Temporal Topology -------------------------------------+
+             | Next: ...................... a@P
+             | Previous: .................. a@P
+             | Equal:...................... a@P
+             | Follows: ................... a@P
+             | Precedes: .................. a@P
+             | Overlaps: .................. a@P
+             | Overlapped: ................ a@P
+             | During: .................... a@P
+             | Contains: .................. a@P
+             | Starts:.. .................. a@P
+             | Started:. .................. a@P
+             | Finishes:................... a@P
+             | Finished:................... a@P
+            >>> tmr.print_temporal_topology_shell_info()
+            next=a@P
+            prev=a@P
+            equal=a@P
+            follows=a@P
+            precedes=a@P
+            overlaps=a@P
+            overlapped=a@P
+            during=a@P
+            contains=a@P
+            starts=a@P
+            started=a@P
+            finishes=a@P
+            finished=a@P
+            >>> rlist = tmr.get_temporal_relations()
+            >>> if "FINISHED" in rlist.keys():
+            ...    print rlist["FINISHED"][0].get_id()
+            a@P
 
-       @code:
-       # We have build the temporal topology and we know the first map
-       start = first
-       while start:
-
-           # Print all maps this map temporally contains
-           dlist = start.get_contains()
-           for map in dlist:
-               map.print_info()
-
-           start = start.next()
-         @endcode  
-        
-        Usage:
-        
-        @code
-        
-        >>> import grass.temporal as tgis
-        >>> tgis.init()
-        >>> map = tgis.RasterDataset("a@P")
-        >>> tmr = tgis.TemporalTopologyDatasetConnector()
-        >>> tmr.set_next(map)
-        >>> tmr.set_prev(map)
-        >>> tmr.append_equal(map)
-        >>> tmr.append_follows(map)
-        >>> tmr.append_precedes(map)
-        >>> tmr.append_overlapped(map)
-        >>> tmr.append_overlaps(map)
-        >>> tmr.append_during(map)
-        >>> tmr.append_contains(map)
-        >>> tmr.append_starts(map)
-        >>> tmr.append_started(map)
-        >>> tmr.append_finishes(map)
-        >>> tmr.append_finished(map)
-        >>> tmr.print_temporal_topology_info()
-         +-------------------- Temporal Topology -------------------------------------+
-         | Next: ...................... a@P
-         | Previous: .................. a@P
-         | Equal:...................... a@P
-         | Follows: ................... a@P
-         | Precedes: .................. a@P
-         | Overlaps: .................. a@P
-         | Overlapped: ................ a@P
-         | During: .................... a@P
-         | Contains: .................. a@P
-         | Starts:.. .................. a@P
-         | Started:. .................. a@P
-         | Finishes:................... a@P
-         | Finished:................... a@P
-        >>> tmr.print_temporal_topology_shell_info()
-        next=a@P
-        prev=a@P
-        equal=a@P
-        follows=a@P
-        precedes=a@P
-        overlaps=a@P
-        overlapped=a@P
-        during=a@P
-        contains=a@P
-        starts=a@P
-        started=a@P
-        finishes=a@P
-        finished=a@P
-        >>> rlist = tmr.get_temporal_relations()
-        >>> if "FINISHED" in rlist.keys():
-        ...    print rlist["FINISHED"][0].get_id()
-        a@P
-
-        @endcode
     """
 
     def __init__(self):
         self.reset_temporal_topology()
 
     def reset_temporal_topology(self):
-        """!Reset any information about temporal topology"""
+        """Reset any information about temporal topology"""
         self._temporal_topology = {}
         self._has_temporal_topology = False
-        
+
     def get_temporal_relations(self):
-        """!Return the dictionary of temporal relationships
-        
+        """Return the dictionary of temporal relationships
+
             Keys are the temporal relationships in upper case,
             values are abstract map objects.
-            
-            @return The temporal relations dictionary
+
+            :return: The temporal relations dictionary
         """
         return copy.copy(self._temporal_topology)
-        
+
     def get_number_of_temporal_relations(self):
-        """! Return a dictionary in which the keys are the relation names and the value
-        are the number of relations.
-        
+        """ Return a dictionary in which the keys are the relation names and
+        the value are the number of relations.
+
         The following relations are available:
+
         - equal
         - follows
         - precedes
@@ -147,327 +144,329 @@ class TemporalTopologyDatasetConnector(object):
         - started
         - finishes
         - finished
-        
-        To access topological information the temporal topology must be build first
-        using the SpatioTemporalTopologyBuilder.
-        
-        @return the dictionary with relations as keys and number as values or None in case the topology wasn't build
+
+        To access topological information the temporal topology must be build
+        first using the SpatioTemporalTopologyBuilder.
+
+        :return: the dictionary with relations as keys and number as values
+                 or None in case the topology wasn't build
         """
-        if self._has_temporal_topology == False:
+        if self._has_temporal_topology is False:
             return None
-    
+
         relations = {}
         try:
-            relations["equal"] = len(self._temporal_topology["EQUAL"]) 
+            relations["equal"] = len(self._temporal_topology["EQUAL"])
         except:
             relations["equal"] = 0
-        try: 
-            relations["follows"] = len(self._temporal_topology["FOLLOWS"]) 
-        except: 
+        try:
+            relations["follows"] = len(self._temporal_topology["FOLLOWS"])
+        except:
             relations["follows"] = 0
-        try: 
+        try:
             relations["precedes"] = len(self._temporal_topology["PRECEDES"])
-        except: 
+        except:
             relations["precedes"] = 0
-        try: 
+        try:
             relations["overlaps"] = len(self._temporal_topology["OVERLAPS"])
-        except: 
+        except:
             relations["overlaps"] = 0
-        try: 
+        try:
             relations["overlapped"] = len(self._temporal_topology["OVERLAPPED"])
-        except: 
+        except:
             relations["overlapped"] = 0
-        try: 
+        try:
             relations["during"] = len(self._temporal_topology["DURING"])
-        except: 
+        except:
             relations["during"] = 0
-        try: 
+        try:
             relations["contains"] = len(self._temporal_topology["CONTAINS"])
-        except: 
+        except:
             relations["contains"] = 0
-        try: 
+        try:
             relations["starts"] = len(self._temporal_topology["STARTS"])
-        except: 
+        except:
             relations["starts"] = 0
-        try:    
+        try:
             relations["started"] = len(self._temporal_topology["STARTED"])
-        except: 
+        except:
             relations["started"] = 0
-        try: 
+        try:
             relations["finishes"] = len(self._temporal_topology["FINISHES"])
-        except: 
+        except:
             relations["finishes"] = 0
-        try: 
+        try:
             relations["finished"] = len(self._temporal_topology["FINISHED"])
-        except: 
+        except:
             relations["finished"] = 0
-            
+
         return relations
 
     def set_temporal_topology_build_true(self):
-        """!Same as name"""
+        """Same as name"""
         self._has_temporal_topology = True
 
     def set_temporal_topology_build_false(self):
-        """!Same as name"""
+        """Same as name"""
         self._has_temporal_topology = False
 
     def is_temporal_topology_build(self):
-        """!Check if the temporal topology was build"""
+        """Check if the temporal topology was build"""
         return self._has_temporal_topology
 
     def set_next(self, map):
-        """!Set the map that is temporally as closest located after this map.
+        """Set the map that is temporally as closest located after this map.
 
            Temporally located means that the start time of the "next" map is
            temporally located AFTER the start time of this map, but temporally
            near than other maps of the same dataset.
 
-           @param map This object should be of type AbstractMapDataset 
-                        or derived classes
+           :param map: This object should be of type AbstractMapDataset
+                       or derived classes
         """
         self._temporal_topology["NEXT"] = map
 
     def set_prev(self, map):
-        """!Set the map that is temporally as closest located before this map.
+        """Set the map that is temporally as closest located before this map.
 
-           Temporally located means that the start time of the "previous" map is
-           temporally located BEFORE the start time of this map, but temporally
-           near than other maps of the same dataset.
+           Temporally located means that the start time of the "previous" map
+           is temporally located BEFORE the start time of this map, but
+           temporally near than other maps of the same dataset.
 
-           @param map This object should be of type AbstractMapDataset 
-                        or derived classes
+           :param map: This object should be of type AbstractMapDataset
+                       or derived classes
         """
         self._temporal_topology["PREV"] = map
 
     def next(self):
-        """!Return the map with a start time temporally located after
+        """Return the map with a start time temporally located after
            the start time of this map, but temporal closer than other maps
 
-           @return A map object or None
+           :return: A map object or None
         """
         if "NEXT" not in self._temporal_topology:
             return None
         return self._temporal_topology["NEXT"]
 
     def prev(self):
-        """!Return the map with a start time temporally located before
+        """Return the map with a start time temporally located before
            the start time of this map, but temporal closer than other maps
 
-           @return A map object or None
+           :return: A map object or None
         """
         if "PREV" not in self._temporal_topology:
             return None
         return self._temporal_topology["PREV"]
 
     def append_equal(self, map):
-        """!Append a map with equivalent temporal extent as this map
+        """Append a map with equivalent temporal extent as this map
 
-           @param map This object should be of type AbstractMapDataset 
-                        or derived classes
+           :param map: This object should be of type AbstractMapDataset
+                       or derived classes
         """
         if "EQUAL" not in self._temporal_topology:
             self._temporal_topology["EQUAL"] = []
         self._temporal_topology["EQUAL"].append(map)
 
     def get_equal(self):
-        """!Return a list of map objects with equivalent temporal extent as this map
+        """Return a list of map objects with equivalent temporal extent as
+           this map
 
-           @return A list of map objects or None
+           :return: A list of map objects or None
         """
         if "EQUAL" not in self._temporal_topology:
             return None
         return self._temporal_topology["EQUAL"]
 
     def append_starts(self, map):
-        """!Append a map that this map temporally starts with
+        """Append a map that this map temporally starts with
 
-           @param map This object should be of type AbstractMapDataset 
-                        or derived classes
+           :param map: This object should be of type AbstractMapDataset
+                       or derived classes
         """
         if "STARTS" not in self._temporal_topology:
             self._temporal_topology["STARTS"] = []
         self._temporal_topology["STARTS"].append(map)
 
     def get_starts(self):
-        """!Return a list of map objects that this map temporally starts with
+        """Return a list of map objects that this map temporally starts with
 
-           @return A list of map objects or None
+           :return: A list of map objects or None
         """
         if "STARTS" not in self._temporal_topology:
             return None
         return self._temporal_topology["STARTS"]
 
     def append_started(self, map):
-        """!Append a map that this map temporally started with
+        """Append a map that this map temporally started with
 
-           @param map This object should be of type AbstractMapDataset 
-                        or derived classes
+           :param map: This object should be of type AbstractMapDataset
+                       or derived classes
         """
         if "STARTED" not in self._temporal_topology:
             self._temporal_topology["STARTED"] = []
         self._temporal_topology["STARTED"].append(map)
 
     def get_started(self):
-        """!Return a list of map objects that this map temporally started with
+        """Return a list of map objects that this map temporally started with
 
-           @return A list of map objects or None
+           :return: A list of map objects or None
         """
         if "STARTED" not in self._temporal_topology:
             return None
         return self._temporal_topology["STARTED"]
 
     def append_finishes(self, map):
-        """!Append a map that this map temporally finishes with
+        """Append a map that this map temporally finishes with
 
-           @param map This object should be of type AbstractMapDataset 
-                        or derived classes
+           :param map: This object should be of type AbstractMapDataset
+                       or derived classes
         """
         if "FINISHES" not in self._temporal_topology:
             self._temporal_topology["FINISHES"] = []
         self._temporal_topology["FINISHES"].append(map)
 
     def get_finishes(self):
-        """!Return a list of map objects that this map temporally finishes with
+        """Return a list of map objects that this map temporally finishes with
 
-           @return A list of map objects or None
+           :return: A list of map objects or None
         """
         if "FINISHES" not in self._temporal_topology:
             return None
         return self._temporal_topology["FINISHES"]
 
     def append_finished(self, map):
-        """!Append a map that this map temporally finished with
+        """Append a map that this map temporally finished with
 
-           @param map This object should be of type AbstractMapDataset 
-                        or derived classes
+           :param map: This object should be of type AbstractMapDataset
+                       or derived classes
         """
         if "FINISHED" not in self._temporal_topology:
             self._temporal_topology["FINISHED"] = []
         self._temporal_topology["FINISHED"].append(map)
 
     def get_finished(self):
-        """!Return a list of map objects that this map temporally finished with
+        """Return a list of map objects that this map temporally finished with
 
-           @return A list of map objects or None
+           :return: A list of map objects or None
         """
         if "FINISHED" not in self._temporal_topology:
             return None
         return self._temporal_topology["FINISHED"]
 
     def append_overlaps(self, map):
-        """!Append a map that this map temporally overlaps
+        """Append a map that this map temporally overlaps
 
-           @param map This object should be of type AbstractMapDataset 
-                        or derived classes
+           :param map: This object should be of type AbstractMapDataset
+                       or derived classes
         """
         if "OVERLAPS" not in self._temporal_topology:
             self._temporal_topology["OVERLAPS"] = []
         self._temporal_topology["OVERLAPS"].append(map)
 
     def get_overlaps(self):
-        """!Return a list of map objects that this map temporally overlaps
+        """Return a list of map objects that this map temporally overlaps
 
-           @return A list of map objects or None
+           :return: A list of map objects or None
         """
         if "OVERLAPS" not in self._temporal_topology:
             return None
         return self._temporal_topology["OVERLAPS"]
 
     def append_overlapped(self, map):
-        """!Append a map that this map temporally overlapped
+        """Append a map that this map temporally overlapped
 
-           @param map This object should be of type AbstractMapDataset 
-                        or derived classes
+           :param map: This object should be of type AbstractMapDataset
+                       or derived classes
         """
         if "OVERLAPPED" not in self._temporal_topology:
             self._temporal_topology["OVERLAPPED"] = []
         self._temporal_topology["OVERLAPPED"].append(map)
 
     def get_overlapped(self):
-        """!Return a list of map objects that this map temporally overlapped
+        """Return a list of map objects that this map temporally overlapped
 
-           @return A list of map objects or None
+           :return: A list of map objects or None
         """
         if "OVERLAPPED" not in self._temporal_topology:
             return None
         return self._temporal_topology["OVERLAPPED"]
 
     def append_follows(self, map):
-        """!Append a map that this map temporally follows
+        """Append a map that this map temporally follows
 
-           @param map This object should be of type AbstractMapDataset 
-                        or derived classes
+           :param map: This object should be of type AbstractMapDataset
+                       or derived classes
         """
         if "FOLLOWS" not in self._temporal_topology:
             self._temporal_topology["FOLLOWS"] = []
         self._temporal_topology["FOLLOWS"].append(map)
 
     def get_follows(self):
-        """!Return a list of map objects that this map temporally follows
+        """Return a list of map objects that this map temporally follows
 
-           @return A list of map objects or None
+           :return: A list of map objects or None
         """
         if "FOLLOWS" not in self._temporal_topology:
             return None
         return self._temporal_topology["FOLLOWS"]
 
     def append_precedes(self, map):
-        """!Append a map that this map temporally precedes
+        """Append a map that this map temporally precedes
 
-           @param map This object should be of type AbstractMapDataset 
-                        or derived classes
+           :param map: This object should be of type AbstractMapDataset
+                       or derived classes
         """
         if "PRECEDES" not in self._temporal_topology:
             self._temporal_topology["PRECEDES"] = []
         self._temporal_topology["PRECEDES"].append(map)
 
     def get_precedes(self):
-        """!Return a list of map objects that this map temporally precedes
+        """Return a list of map objects that this map temporally precedes
 
-           @return A list of map objects or None
+           :return: A list of map objects or None
         """
         if "PRECEDES" not in self._temporal_topology:
             return None
         return self._temporal_topology["PRECEDES"]
 
     def append_during(self, map):
-        """!Append a map that this map is temporally located during
+        """Append a map that this map is temporally located during
            This includes temporal relationships starts and finishes
 
-           @param map This object should be of type 
-                        AbstractMapDataset or derived classes
+           :param map: This object should be of type
+                       AbstractMapDataset or derived classes
         """
         if "DURING" not in self._temporal_topology:
             self._temporal_topology["DURING"] = []
         self._temporal_topology["DURING"].append(map)
 
     def get_during(self):
-        """!Return a list of map objects that this map is temporally located during
+        """Return a list of map objects that this map is temporally located during
            This includes temporally relationships starts and finishes
 
-           @return A list of map objects or None
+           :return: A list of map objects or None
         """
         if "DURING" not in self._temporal_topology:
             return None
         return self._temporal_topology["DURING"]
 
     def append_contains(self, map):
-        """!Append a map that this map temporally contains
+        """Append a map that this map temporally contains
            This includes temporal relationships started and finished
 
-           @param map This object should be of type AbstractMapDataset 
-                        or derived classes
+           :param map: This object should be of type AbstractMapDataset
+                       or derived classes
         """
         if "CONTAINS" not in self._temporal_topology:
             self._temporal_topology["CONTAINS"] = []
         self._temporal_topology["CONTAINS"].append(map)
 
     def get_contains(self):
-        """!Return a list of map objects that this map temporally contains
+        """Return a list of map objects that this map temporally contains
            This includes temporal relationships started and finished
 
-           @return A list of map objects or None
+           :return: A list of map objects or None
         """
         if "CONTAINS" not in self._temporal_topology:
             return None
@@ -487,34 +486,23 @@ class TemporalTopologyDatasetConnector(object):
             count += 1
 
         return string
-    
+
     # Set the properties
-    equal = property(fget=get_equal, 
-                                       fset=append_equal)
-    follows = property(fget=get_follows, 
-                                    fset=append_follows)
-    precedes = property(fget=get_precedes, 
-                                     fset=append_precedes)
-    overlaps = property(fget=get_overlaps, 
-                                     fset=append_overlaps)
-    overlapped = property(fget=get_overlapped, 
-                                       fset=append_overlapped)
-    during = property(fget=get_during, 
-                                   fset=append_during)
-    contains = property(fget=get_contains, 
-                                     fset=append_contains)
-    starts = property(fget=get_starts, 
-                                     fset=append_starts)
-    started = property(fget=get_started, 
-                                     fset=append_started)
-    finishes = property(fget=get_finishes, 
-                                     fset=append_finishes)
-    finished = property(fget=get_finished, 
-                                     fset=append_finished)
+    equal = property(fget=get_equal, fset=append_equal)
+    follows = property(fget=get_follows, fset=append_follows)
+    precedes = property(fget=get_precedes, fset=append_precedes)
+    overlaps = property(fget=get_overlaps, fset=append_overlaps)
+    overlapped = property(fget=get_overlapped, fset=append_overlapped)
+    during = property(fget=get_during, fset=append_during)
+    contains = property(fget=get_contains, fset=append_contains)
+    starts = property(fget=get_starts, fset=append_starts)
+    started = property(fget=get_started, fset=append_started)
+    finishes = property(fget=get_finishes, fset=append_finishes)
+    finished = property(fget=get_finished, fset=append_finished)
 
     def print_temporal_topology_info(self):
-        """!Print information about this class in human readable style"""
-        
+        """Print information about this class in human readable style"""
+
         print " +-------------------- Temporal Topology -------------------------------------+"
         #          0123456789012345678901234567890
         if self.next() is not None:
@@ -556,8 +544,8 @@ class TemporalTopologyDatasetConnector(object):
                 self._generate_map_list_string(self.finished)
 
     def print_temporal_topology_shell_info(self):
-        """!Print information about this class in shell style"""
-        
+        """Print information about this class in shell style"""
+
         if self.next() is not None:
             print "next=" + self.next().get_id()
         if self.prev() is not None:
@@ -565,7 +553,8 @@ class TemporalTopologyDatasetConnector(object):
         if self.equal is not None:
             print "equal=" + self._generate_map_list_string(self.equal, False)
         if self.follows is not None:
-            print "follows=" + self._generate_map_list_string(self.follows, False)
+            print "follows=" + self._generate_map_list_string(self.follows,
+                                                              False)
         if self.precedes is not None:
             print "precedes=" + self._generate_map_list_string(
                 self.precedes, False)
@@ -576,7 +565,8 @@ class TemporalTopologyDatasetConnector(object):
             print "overlapped=" + \
                 self._generate_map_list_string(self.overlapped, False)
         if self.during is not None:
-            print "during=" + self._generate_map_list_string(self.during, False)
+            print "during=" + self._generate_map_list_string(self.during,
+                                                             False)
         if self.contains is not None:
             print "contains=" + self._generate_map_list_string(
                 self.contains, False)

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 298 - 615
lib/python/temporal/temporal_vector_algebra.py


+ 0 - 349
lib/python/temporal/temporal_vector_operator.py

@@ -1,349 +0,0 @@
-"""!@package grass.temporal
-
-Temporal vector operator evaluation with PLY
-
-(C) 2014 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.
-
-@authors Thomas Leppelt and Soeren Gebbert
-
-@code
-    >>> import grass.temporal as tgis
-    >>> tgis.init(True)
-    >>> p = tgis.TemporalVectorOperatorParser()
-    >>> expression =  "{equal| during,&&}"
-    >>> p.parse(expression, True)
-    >>> print(p.relations, p.temporal, p.function)
-    (['equal', 'during'], '=', '&&')
-    >>> expression =  "{equal| during | follows,&&}"
-    >>> p.parse(expression)
-    >>> print(p.relations, p.temporal, p.function)
-    (['equal', 'during', 'follows'], '&', '&')
-    >>> expression =  "{equal| during | follows,+!:}"
-    >>> p.parse(expression)
-    >>> print(p.relations, p.temporal, p.function)
-    (['equal', 'during', 'follows'], '+', '!:')
-    >>> expression =  "{equal| during,!:}"
-    >>> p.parse(expression)
-    >>> print(p.relations, p.temporal, p.function)
-    (['equal', 'during'], '=', '!:')
-    >>> expression =  "{!:}"
-    >>> p.parse(expression)
-    >>> print(p.relations, p.temporal, p.function)
-    (['equal'], '=', '!:')
-    >>> expression =  "{&&}"
-    >>> p.parse(expression, True)
-    >>> print(p.relations, p.temporal, p.function)
-    (['equal'], '=', '&&')
-    >>> expression =  "{&&}"
-    >>> p.parse(expression)
-    >>> print(p.relations, p.temporal, p.function)
-    (['equal'], '&', '&')
-    >>> expression =  "{|#}"
-    >>> p.parse(expression)
-    >>> print(p.relations, p.temporal, p.function)
-    (['equal'], '|', '#')
-    >>> expression =  "{equal,||}"
-    >>> p.parse(expression)
-    >>> print(p.relations, p.temporal, p.function)
-    (['equal'], '|', '|')
-    >>> expression =  "{equal|during,=!:}"
-    >>> p.parse(expression)
-    >>> print(p.relations, p.temporal, p.function)
-    (['equal', 'during'], '=', '!:')
-    >>> expression =  "{equal|during|starts}"
-    >>> p.parse(expression)
-    >>> print(p.relations, p.temporal, p.function)
-    (['equal', 'during', 'starts'], None, None)
-    >>> expression =  "{over| equal,||}"
-    >>> p.parse(expression)
-    >>> print(p.relations, p.temporal, p.function)
-    ([['overlaps', 'overlapped'], 'equal'], '|', '|')
-    
-@endcode
-"""
-try:
-    import ply.lex as lex
-    import ply.yacc as yacc
-except:
-    pass
-
-class TemporalVectorOperatorLexer(object):
-    """!Lexical analyzer for the GRASS GIS temporal vector operators"""
-    
-    # Functions that defines topological relations.
-    relations = {
-        'equal'      : "EQUAL",
-        'follows'    : "FOLLOWS",
-        'precedes'   : "PRECEDES",
-        'overlaps'   : "OVERLAPS",
-        'overlapped' : "OVERLAPPED",
-        'during'     : "DURING",
-        'starts'     : "STARTS",
-        'finishes'   : "FINISHES",
-        'contains'   : "CONTAINS",
-        'started'    : "STARTED",
-        'finished'   : "FINISHED",
-        'over'       : "OVER"
-        }
-        
-    # This is the list of token names.
-    tokens = (
-        'COMMA',
-        'LEFTREF',
-        'HASH',
-        'OR',
-        'AND',
-        'DISOR',
-        'XOR',
-        'NOT',
-        'T_SELECT',
-        'T_NOT_SELECT',
-        'CLPAREN',
-        'CRPAREN',
-    )
-    
-    # Build the token list
-    tokens = tokens + tuple(relations.values())
-
-    # Regular expression rules for simple tokens
-    t_T_SELECT           = r':'
-    t_T_NOT_SELECT       = r'!:'
-    t_COMMA              = r','
-    t_LEFTREF             = r'='
-    t_HASH               = r'\#'
-    t_OR                 = r'[\|]'
-    t_AND                = r'[&]'
-    t_DISOR              = r'\+'
-    t_XOR                = r'\^'
-    t_NOT                = r'\~'
-    t_CLPAREN             = r'\{'
-    t_CRPAREN             = r'\}'
-    
-    # These are the things that should be ignored.
-    t_ignore = ' \t'
-
-    # Track line numbers.
-    def t_newline(self, t):
-        r'\n+'
-        t.lineno += len(t.value)
-        
-    def t_NAME(self, t):
-        r'[a-zA-Z_][a-zA-Z_0-9]*'
-        self.temporal_symbol(t)
-        return t
-        
-    # Parse symbols
-    def temporal_symbol(self, t):
-        # Check for reserved words
-        if t.value in TemporalVectorOperatorLexer.relations.keys():
-            t.type = TemporalVectorOperatorLexer.relations.get(t.value)
-        #else:
-        #    t.type = 'NAME'
-        return(t)
-
-    # Handle errors.
-    def t_error(self, t):
-        raise SyntaxError("syntax error on line %d near '%s'" % 
-            (t.lineno, t.value))
-
-    # Build the lexer
-    def build(self,**kwargs):
-        self.lexer = lex.lex(module=self, **kwargs)
-        
-    # Just for testing
-    def test(self,data):
-        self.name_list = {}
-        print(data)
-        self.lexer.input(data)
-        while True:
-             tok = self.lexer.token()
-             if not tok: break
-             print tok
-             
-class TemporalVectorOperatorParser(object):
-    """!The parser for the GRASS GIS temporal vector operators"""
-    
-    def __init__(self):
-        self.lexer = TemporalVectorOperatorLexer()
-        self.lexer.build()
-        self.parser = yacc.yacc(module=self)
-
-    def parse(self, expression, comparison = False):
-        self.comparison = comparison
-        self.parser.parse(expression)
-        
-    # Error rule for syntax errors.
-    def p_error(self, t):
-        raise SyntaxError("invalid syntax")
-
-    # Get the tokens from the lexer class
-    tokens = TemporalVectorOperatorLexer.tokens
-
-    def p_relation_only(self, t):
-        # The expression should always return a list of maps.
-        """
-        operator : CLPAREN relation CRPAREN
-                 | CLPAREN relationlist CRPAREN
-        """
-        # Set three operator components.
-        if isinstance(t[2], list):
-            self.relations = t[2]
-        else:
-            self.relations = [t[2]]
-        self.temporal  = None 
-        self.function  = None
-        
-        t[0] = t[2]
-
-
-    def p_operator(self, t):
-        # The expression should always return a list of maps.
-        """
-        operator : CLPAREN select CRPAREN
-                 | CLPAREN HASH CRPAREN
-                 | CLPAREN overlay CRPAREN
-        """
-        # Set three operator components.
-        self.relations = ['equal']
-        self.temporal  = "=" 
-        self.function  = t[2]
-        
-        t[0] = t[2]
-        
-    def p_operator_temporal(self, t):
-        # The expression should always return a list of maps.
-        """
-        operator : CLPAREN temporal select CRPAREN
-                 | CLPAREN temporal HASH CRPAREN
-                 | CLPAREN temporal overlay CRPAREN
-        """
-        # Set three operator components.
-        self.relations = ['equal']
-        if self.comparison:
-            self.temporal = "="
-            self.function = t[2] + t[3]
-        else:
-            self.temporal = t[2]
-            self.function = t[3]
-        
-        t[0] = t[3]
-
-    def p_operator_relation(self, t):
-        # The expression should always return a list of maps.
-        """
-        operator : CLPAREN relation COMMA select CRPAREN
-                 | CLPAREN relationlist COMMA select CRPAREN
-                 | CLPAREN relation COMMA HASH CRPAREN
-                 | CLPAREN relationlist COMMA HASH CRPAREN
-                 | CLPAREN relation COMMA overlay CRPAREN
-                 | CLPAREN relationlist COMMA overlay CRPAREN
-        """
-        # Set three operator components.
-        if isinstance(t[2], list):
-            self.relations = t[2]
-        else:
-            self.relations = [t[2]]
-        self.temporal  = "=" 
-        self.function  = t[4]
-        
-        t[0] = t[4]
-
-    def p_operator_relation_temporal(self, t):
-        # The expression should always return a list of maps.
-        """
-        operator : CLPAREN relation COMMA temporal select CRPAREN
-                 | CLPAREN relationlist COMMA temporal select CRPAREN
-                 | CLPAREN relation COMMA temporal HASH CRPAREN
-                 | CLPAREN relationlist COMMA temporal HASH CRPAREN
-                 | CLPAREN relation COMMA temporal overlay CRPAREN
-                 | CLPAREN relationlist COMMA temporal overlay CRPAREN
-        """
-        # Set three operator components.
-        if isinstance(t[2], list):
-            self.relations = t[2]
-        else:
-            self.relations = [t[2]]
-        if self.comparison:
-            self.temporal = "="
-            self.function = t[4] + t[5]
-        else:
-            self.temporal = t[4]
-            self.function = t[5]
-        t[0] = t[5]
-        
-    def p_relation(self, t):
-        # The list of relations.
-        """
-        relation : EQUAL
-                 | FOLLOWS
-                 | PRECEDES
-                 | OVERLAPS
-                 | OVERLAPPED
-                 | DURING
-                 | STARTS
-                 | FINISHES
-                 | CONTAINS
-                 | STARTED
-                 | FINISHED
-        """
-        t[0] = t[1]
-        
-    def p_over(self, t):
-        # The list of relations.
-        """
-        relation : OVER
-        """
-        over_list = ["overlaps", "overlapped"]
-        t[0] = over_list
-
-    def p_relationlist(self, t):
-        # The list of relations.
-        """
-        relationlist : relation OR relation
-                     | relation OR relationlist
-        """
-        rel_list = []
-        rel_list.append(t[1])
-        if isinstance(t[3], list):
-            rel_list = rel_list + t[3]
-        else:
-            rel_list.append(t[3])
-        t[0] =  rel_list
-
-    def p_temporal_operator(self, t):
-        # The list of relations.
-        """
-        temporal : LEFTREF
-                 | OR
-                 | AND
-                 | DISOR
-        """
-        t[0] = t[1]
-
-    def p_select_operator(self, t):
-        # The list of relations.
-        """
-        select : T_SELECT
-               | T_NOT_SELECT
-        """
-        t[0] = t[1]
-
-    def p_overlay_operator(self, t):
-        # The list of relations.
-        """
-        overlay : OR
-                | AND
-                | DISOR
-                | XOR
-                | NOT
-        """
-        t[0] = t[1]
-###############################################################################             
-        
-if __name__ == "__main__":
-    import doctest
-    doctest.testmod()
-    

+ 50 - 0
lib/python/temporal/testsuite/test_doctests.py

@@ -0,0 +1,50 @@
+# -*- coding: utf-8 -*-
+"""
+Temporal framework doctests
+"""
+
+import doctest
+import grass.temporal
+import grass.gunittest
+import grass.gunittest.utils
+import os
+
+doctest.DocFileCase = type('DocFileCase',
+                           (grass.gunittest.TestCase,),
+                           dict(doctest.DocFileCase.__dict__))
+doctest.SkipDocTestCase = type('SkipDocTestCase',
+                               (grass.gunittest.TestCase,),
+                               dict(doctest.SkipDocTestCase.__dict__))
+
+def load_tests(loader, tests, ignore):
+    grass.gunittest.utils.do_doctest_gettext_workaround()
+    tests.addTests(doctest.DocTestSuite(grass.temporal.abstract_dataset))
+    tests.addTests(doctest.DocTestSuite(grass.temporal.abstract_map_dataset))
+    tests.addTests(doctest.DocTestSuite(grass.temporal.abstract_space_time_dataset))
+    tests.addTests(doctest.DocTestSuite(grass.temporal.base))
+    tests.addTests(doctest.DocTestSuite(grass.temporal.c_libraries_interface))
+    # Unexpected error here
+    #tests.addTests(doctest.DocTestSuite(grass.temporal.core))
+    tests.addTests(doctest.DocTestSuite(grass.temporal.datetime_math))
+    # Unexpected error here
+    #tests.addTests(doctest.DocTestSuite(grass.temporal.list_stds))
+    tests.addTests(doctest.DocTestSuite(grass.temporal.metadata))
+    tests.addTests(doctest.DocTestSuite(grass.temporal.register))
+    tests.addTests(doctest.DocTestSuite(grass.temporal.space_time_datasets))
+    tests.addTests(doctest.DocTestSuite(grass.temporal.spatial_extent))
+    tests.addTests(doctest.DocTestSuite(grass.temporal.spatial_topology_dataset_connector))
+    tests.addTests(doctest.DocTestSuite(grass.temporal.spatio_temporal_relationships))
+    tests.addTests(doctest.DocTestSuite(grass.temporal.temporal_extent))
+    tests.addTests(doctest.DocTestSuite(grass.temporal.temporal_granularity))
+    tests.addTests(doctest.DocTestSuite(grass.temporal.temporal_topology_dataset_connector))
+    # Algebra is still very experimental
+    tests.addTests(doctest.DocTestSuite(grass.temporal.temporal_algebra))
+    tests.addTests(doctest.DocTestSuite(grass.temporal.temporal_raster3d_algebra))
+    tests.addTests(doctest.DocTestSuite(grass.temporal.temporal_raster_algebra))
+    tests.addTests(doctest.DocTestSuite(grass.temporal.temporal_raster_base_algebra))
+    tests.addTests(doctest.DocTestSuite(grass.temporal.temporal_operator))
+    tests.addTests(doctest.DocTestSuite(grass.temporal.temporal_vector_algebra))
+    return tests
+
+if __name__ == '__main__':
+    grass.gunittest.test()

+ 302 - 0
lib/python/temporal/testsuite/test_register_function.py

@@ -0,0 +1,302 @@
+"""Unit test to register raster maps with absolute and relative
+   time using tgis.register_maps_in_space_time_dataset()
+
+(C) 2013 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.
+
+:authors: Soeren Gebbert
+"""
+
+import grass.temporal as tgis
+import grass.gunittest
+import datetime
+import os
+
+class TestRegisterFunctions(grass.gunittest.TestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        """Initiate the temporal GIS and set the region
+        """
+        os.putenv("GRASS_OVERWRITE", "1")
+        # Use always the current mapset as temporal database
+        cls.runModule("g.gisenv", set="TGIS_USE_CURRENT_MAPSET=1")
+        tgis.init()
+        cls.use_temp_region()
+        cls.runModule('g.region', n=80.0, s=0.0, e=120.0, w=0.0,
+                      t=1.0, b=0.0, res=10.0)
+
+    @classmethod
+    def tearDownClass(cls):
+        """Remove the temporary region
+        """
+        cls.del_temp_region()
+
+    def setUp(self):
+        """Create the test maps and the space time raster datasets
+        """
+        self.runModule("r.mapcalc", overwrite=True, quiet=True,
+                       expression="register_map_1 = 1")
+        self.runModule("r.mapcalc", overwrite=True, quiet=True,
+                       expression="register_map_2 = 2")
+
+        self.strds_abs = tgis.open_new_stds(name="register_test_abs", type="strds", temporaltype="absolute",
+                                            title="Test strds", descr="Test strds", semantic="field")
+        self.strds_rel = tgis.open_new_stds(name="register_test_rel", type="strds", temporaltype="relative",
+                                            title="Test strds", descr="Test strds", semantic="field")
+
+    def tearDown(self):
+        """Remove maps from temporal database
+        """
+        self.runModule("t.unregister", maps="register_map_1,register_map_2", quiet=True)
+        self.runModule("g.remove", flags='f', type="rast", name="register_map_1,register_map_2", quiet=True)
+        self.strds_abs.delete()
+        self.strds_rel.delete()
+
+    def test_absolute_time_strds_1(self):
+        """Test the registration of maps with absolute time in a
+           space time raster dataset
+        """
+        tgis.register_maps_in_space_time_dataset(type="rast", name=self.strds_abs.get_name(),
+                 maps="register_map_1,register_map_2",
+                 start="2001-01-01", increment="1 day", interval=True)
+
+        map = tgis.RasterDataset("register_map_1@" + tgis.get_current_mapset())
+        map.select()
+        start, end = map.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 2))
+
+        map = tgis.RasterDataset("register_map_2@" + tgis.get_current_mapset())
+        map.select()
+        start, end = map.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 2))
+        self.assertEqual(end, datetime.datetime(2001, 1, 3))
+
+        self.strds_abs.select()
+        start, end = self.strds_abs.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 3))
+
+    def test_absolute_time_strds_2(self):
+        """Test the registration of maps with absolute time in a
+           space time raster dataset.
+           The timestamps are set using the C-Interface beforehand, so that the register function needs
+           to read the timetsamp from the map metadata.
+        """
+
+        ciface = tgis.get_tgis_c_library_interface()
+        ciface.write_raster_timestamp("register_map_1", tgis.get_current_mapset(), "1 Jan 2001/2 Jan 2001")
+        ciface.write_raster_timestamp("register_map_2", tgis.get_current_mapset(), "2 Jan 2001/3 Jan 2001")
+
+        tgis.register_maps_in_space_time_dataset(type="rast", name=self.strds_abs.get_name(),
+                                                 maps="register_map_1,register_map_2")
+
+        map = tgis.RasterDataset("register_map_1@" + tgis.get_current_mapset())
+        map.select()
+        start, end = map.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 2))
+
+        map = tgis.RasterDataset("register_map_2@" + tgis.get_current_mapset())
+        map.select()
+        start, end = map.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 2))
+        self.assertEqual(end, datetime.datetime(2001, 1, 3))
+
+        self.strds_abs.select()
+        start, end = self.strds_abs.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 3))
+
+    def test_absolute_time_1(self):
+        """Test the registration of maps with absolute time
+        """
+        tgis.register_maps_in_space_time_dataset(type="rast", name=None,
+                 maps="register_map_1,register_map_2",
+                 start="2001-01-01", increment="1 day", interval=True)
+
+        map = tgis.RasterDataset("register_map_1@" + tgis.get_current_mapset())
+        map.select()
+        start, end = map.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 2))
+
+        map = tgis.RasterDataset("register_map_2@" + tgis.get_current_mapset())
+        map.select()
+        start, end = map.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 2))
+        self.assertEqual(end, datetime.datetime(2001, 1, 3))
+
+    def test_absolute_time_2(self):
+        """Test the registration of maps with absolute time
+        """
+        tgis.register_maps_in_space_time_dataset(type="rast", name=None,
+                 maps="register_map_1,register_map_2",
+                 start="2001-01-01 10:30:01", increment="8 hours", interval=False)
+
+        map = tgis.RasterDataset("register_map_1@" + tgis.get_current_mapset())
+        map.select()
+        start, end = map.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1, 10, 30, 1))
+
+        map = tgis.RasterDataset("register_map_2@" + tgis.get_current_mapset())
+        map.select()
+        start, end = map.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1, 18, 30, 1))
+
+    def test_absolute_time_3(self):
+        """Test the registration of maps with absolute time.
+           The timestamps are set using the C-Interface beforehand, so that the register function needs
+           to read the timetsamp from the map metadata.
+        """
+
+        ciface = tgis.get_tgis_c_library_interface()
+        ciface.write_raster_timestamp("register_map_1", tgis.get_current_mapset(), "1 Jan 2001 10:30:01")
+        ciface.write_raster_timestamp("register_map_2", tgis.get_current_mapset(), "1 Jan 2001 18:30:01")
+
+        tgis.register_maps_in_space_time_dataset(type="rast", name=None,
+                 maps="register_map_1,register_map_2")
+
+        map = tgis.RasterDataset("register_map_1@" + tgis.get_current_mapset())
+        map.select()
+        start, end = map.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1, 10, 30, 1))
+
+        map = tgis.RasterDataset("register_map_2@" + tgis.get_current_mapset())
+        map.select()
+        start, end = map.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1, 18, 30, 1))
+
+    def test_relative_time_strds_1(self):
+        """Test the registration of maps with relative time in a
+           space time raster dataset
+        """
+
+        tgis.register_maps_in_space_time_dataset(type="rast", name=self.strds_rel.get_name(),
+                                                 maps="register_map_1,register_map_2", start=0,
+                                                 increment=1, unit="day", interval=True)
+
+        map = tgis.RasterDataset("register_map_1@" + tgis.get_current_mapset())
+        map.select()
+        start, end, unit = map.get_relative_time()
+        self.assertEqual(start, 0)
+        self.assertEqual(end, 1)
+        self.assertEqual(unit, "day")
+
+        map = tgis.RasterDataset("register_map_2@" + tgis.get_current_mapset())
+        map.select()
+        start, end, unit = map.get_relative_time()
+        self.assertEqual(start, 1)
+        self.assertEqual(end, 2)
+        self.assertEqual(unit, "day")
+
+        self.strds_rel.select()
+        start, end, unit = self.strds_rel.get_relative_time()
+        self.assertEqual(start, 0)
+        self.assertEqual(end, 2)
+        self.assertEqual(unit, "day")
+
+    def test_relative_time_strds_2(self):
+        """Test the registration of maps with relative time in a
+           space time raster dataset. The timetsamps are set for the maps using the
+           C-interface before registration.
+        """
+        ciface = tgis.get_tgis_c_library_interface()
+        ciface.write_raster_timestamp("register_map_1", tgis.get_current_mapset(), "1000000 seconds/1500000 seconds")
+        ciface.write_raster_timestamp("register_map_2", tgis.get_current_mapset(), "1500000 seconds/2000000 seconds")
+
+        tgis.register_maps_in_space_time_dataset(type="rast", name=self.strds_rel.get_name(),
+                                                 maps="register_map_1,register_map_2")
+
+        map = tgis.RasterDataset("register_map_1@" + tgis.get_current_mapset())
+        map.select()
+        start, end, unit = map.get_relative_time()
+        self.assertEqual(start, 1000000)
+        self.assertEqual(end, 1500000)
+        self.assertEqual(unit, "seconds")
+
+        map = tgis.RasterDataset("register_map_2@" + tgis.get_current_mapset())
+        map.select()
+        start, end, unit = map.get_relative_time()
+        self.assertEqual(start, 1500000)
+        self.assertEqual(end, 2000000)
+        self.assertEqual(unit, "seconds")
+
+        self.strds_rel.select()
+        start, end, unit = self.strds_rel.get_relative_time()
+        self.assertEqual(start, 1000000)
+        self.assertEqual(end, 2000000)
+        self.assertEqual(unit, "seconds")
+
+    def test_relative_time_1(self):
+        """Test the registration of maps with relative time
+        """
+        tgis.register_maps_in_space_time_dataset(type="rast", name=None,
+                 maps="register_map_1,register_map_2",
+                 start=0, increment=1, unit="day", interval=True)
+
+        map = tgis.RasterDataset("register_map_1@" + tgis.get_current_mapset())
+        map.select()
+        start, end, unit = map.get_relative_time()
+        self.assertEqual(start, 0)
+        self.assertEqual(end, 1)
+        self.assertEqual(unit, "day")
+
+        map = tgis.RasterDataset("register_map_2@" + tgis.get_current_mapset())
+        map.select()
+        start, end, unit = map.get_relative_time()
+        self.assertEqual(start, 1)
+        self.assertEqual(end, 2)
+        self.assertEqual(unit, "day")
+
+    def test_relative_time_2(self):
+        """Test the registration of maps with relative time
+        """
+        tgis.register_maps_in_space_time_dataset(type="rast", name=None,
+                 maps="register_map_1,register_map_2",
+                 start=1000000, increment=500000, unit="seconds", interval=True)
+
+        map = tgis.RasterDataset("register_map_1@" + tgis.get_current_mapset())
+        map.select()
+        start, end, unit = map.get_relative_time()
+        self.assertEqual(start, 1000000)
+        self.assertEqual(end, 1500000)
+        self.assertEqual(unit, "seconds")
+
+        map = tgis.RasterDataset("register_map_2@" + tgis.get_current_mapset())
+        map.select()
+        start, end, unit = map.get_relative_time()
+        self.assertEqual(start, 1500000)
+        self.assertEqual(end, 2000000)
+        self.assertEqual(unit, "seconds")
+
+    def test_relative_time_3(self):
+        """Test the registration of maps with relative time. The timetsamps are set beforhand using
+           the C-interface.
+        """
+        ciface = tgis.get_tgis_c_library_interface()
+        ciface.write_raster_timestamp("register_map_1", tgis.get_current_mapset(), "1000000 seconds/1500000 seconds")
+        ciface.write_raster_timestamp("register_map_2", tgis.get_current_mapset(), "1500000 seconds/2000000 seconds")
+
+        tgis.register_maps_in_space_time_dataset(type="rast", name=None,
+                 maps="register_map_1,register_map_2")
+
+        map = tgis.RasterDataset("register_map_1@" + tgis.get_current_mapset())
+        map.select()
+        start, end, unit = map.get_relative_time()
+        self.assertEqual(start, 1000000)
+        self.assertEqual(end, 1500000)
+        self.assertEqual(unit, "seconds")
+
+        map = tgis.RasterDataset("register_map_2@" + tgis.get_current_mapset())
+        map.select()
+        start, end, unit = map.get_relative_time()
+        self.assertEqual(start, 1500000)
+        self.assertEqual(end, 2000000)
+        self.assertEqual(unit, "seconds")
+
+if __name__ == '__main__':
+    grass.gunittest.test()

+ 13 - 20
lib/python/temporal/unittests_register.py

@@ -11,35 +11,36 @@ for details.
 
 import grass.script as grass
 import grass.temporal as tgis
-import unittest
+from gunittest.case import GrassTestCase
 import datetime
 
-class TestRegisterFunctions(unittest.TestCase):
+class TestRegisterFunctions(GrassTestCase):
 
     @classmethod
     def setUpClass(cls):
         """!Initiate the temporal GIS and set the region
         """
+        # Use always the current mapset as temporal database
+        cls.assertModule("g.gisenv",  set="TGIS_USE_CURRENT_MAPSET=1")
         tgis.init()
         grass.overwrite = True
         grass.use_temp_region()
-        ret = grass.run_command("g.region", n=80.0, s=0.0, e=120.0, 
+        cls.assertModule("g.region", n=80.0, s=0.0, e=120.0, 
                                 w=0.0, t=1.0, b=0.0, res=10.0)
 
     def setUp(self):
         """!Create the test maps and the space time raster datasets
         """
-        ret = 0
-        ret += grass.run_command("r.mapcalc", overwrite=True, quiet=True, 
+        self.assertModule("r.mapcalc", overwrite=True, quiet=True, 
                           expression="register_map_1 = 1")
-        ret += grass.run_command("r.mapcalc", overwrite=True, quiet=True, 
+        self.assertModule("r.mapcalc", overwrite=True, quiet=True, 
                           expression="register_map_2 = 2")
         self.assertEqual(ret, 0)
         
         
-        self.strds_abs = tgis.open_new_space_time_dataset(name="register_test_abs", type="strds", temporaltype="absolute", 
+        self.strds_abs = tgis.open_new_stds(name="register_test_abs", type="strds", temporaltype="absolute", 
                                             title="Test strds", descr="Test strds", semantic="field")
-        self.strds_rel = tgis.open_new_space_time_dataset(name="register_test_rel", type="strds", temporaltype="relative", 
+        self.strds_rel = tgis.open_new_stds(name="register_test_rel", type="strds", temporaltype="relative", 
                                             title="Test strds", descr="Test strds", semantic="field")
 
     def test_absolute_time_strds_1(self):
@@ -67,8 +68,6 @@ class TestRegisterFunctions(unittest.TestCase):
         self.assertEqual(start, datetime.datetime(2001, 1, 1))
         self.assertEqual(end, datetime.datetime(2001, 1, 3))
 
-        self.strds_abs.print_info()
-
     def test_absolute_time_strds_2(self):
         """!Test the registration of maps with absolute time in a
            space time raster dataset.
@@ -100,8 +99,6 @@ class TestRegisterFunctions(unittest.TestCase):
         self.assertEqual(start, datetime.datetime(2001, 1, 1))
         self.assertEqual(end, datetime.datetime(2001, 1, 3))
 
-        self.strds_abs.print_info()
-
     def test_absolute_time_1(self):
         """!Test the registration of maps with absolute time
         """
@@ -189,8 +186,6 @@ class TestRegisterFunctions(unittest.TestCase):
         self.assertEqual(start, 0)
         self.assertEqual(end, 2)
         self.assertEqual(unit, "day")
-        
-        self.strds_rel.print_info()
 
     def test_relative_time_strds_2(self):
         """!Test the registration of maps with relative time in a
@@ -224,8 +219,6 @@ class TestRegisterFunctions(unittest.TestCase):
         self.assertEqual(end, 2000000)
         self.assertEqual(unit, "seconds")
         
-        self.strds_rel.print_info()
-        
     def test_relative_time_1(self):
         """!Test the registration of maps with relative time
         """
@@ -296,9 +289,8 @@ class TestRegisterFunctions(unittest.TestCase):
     def tearDown(self):
         """!Remove maps from temporal database
         """
-        ret = grass.run_command("t.unregister", maps="register_map_1,register_map_2", quiet=True)
-        ret = grass.run_command("g.remove", type="rast", name="register_map_1,register_map_2", quiet=True, flags="f")
-        self.assertEqual(ret, 0)
+        self.assertModule("t.unregister", maps="register_map_1,register_map_2", quiet=True)
+        self.assertModule("g.remove", rast="register_map_1,register_map_2", quiet=True)
         self.strds_abs.delete()
         self.strds_rel.delete()
 
@@ -309,6 +301,7 @@ class TestRegisterFunctions(unittest.TestCase):
         grass.del_temp_region()
 
 if __name__ == '__main__':
-    unittest.main()
+    from gunittest.main import test
+    test()
 
 

+ 354 - 0
lib/python/temporal/testsuite/unittests_temporal_algebra.py

@@ -0,0 +1,354 @@
+"""
+(C) 2013 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.
+
+:authors: Soeren Gebbert and Thomas Leppelt
+"""
+
+import grass.script
+import grass.temporal as tgis
+import grass.gunittest
+import datetime
+import os
+
+class TestTemporalAlgebra(grass.gunittest.TestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        """Initiate the temporal GIS and set the region
+        """
+        tgis.init(True) # Raise on error instead of exit(1)
+        cls.use_temp_region()
+        cls.runModule("g.region", n=80.0, s=0.0, e=120.0,
+                                       w=0.0, t=1.0, b=0.0, res=10.0)
+
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="a1 = 1")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="a2 = 2")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="a3 = 3")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="a4 = 4")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="b1 = 5")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="b2 = 6")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="c1 = 7")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="d1 = 8")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="d2 = 9")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="d3 = 10")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="singletmap = 99")
+
+
+        tgis.open_new_stds(name="A", type="strds", temporaltype="absolute",
+                                         title="A", descr="A", semantic="field", overwrite=True)
+        tgis.open_new_stds(name="B", type="strds", temporaltype="absolute",
+                                         title="B", descr="B", semantic="field", overwrite=True)
+        tgis.open_new_stds(name="C", type="strds", temporaltype="absolute",
+                                         title="C", descr="C", semantic="field", overwrite=True)
+        tgis.open_new_stds(name="D", type="strds", temporaltype="absolute",
+                                         title="D", descr="D", semantic="field", overwrite=True)
+
+        tgis.register_maps_in_space_time_dataset(type="rast", name="A", maps="a1,a2,a3,a4",
+                                                 start="2001-01-01", increment="1 day", interval=True)
+        tgis.register_maps_in_space_time_dataset(type="rast", name="B", maps="b1,b2",
+                                                 start="2001-01-01", increment="2 day", interval=True)
+        tgis.register_maps_in_space_time_dataset(type="rast", name="C", maps="c1",
+                                                 start="2001-01-02", increment="2 day", interval=True)
+        tgis.register_maps_in_space_time_dataset(type="rast", name="D", maps="d1,d2,d3",
+                                                 start="2001-01-03", increment="1 day", interval=True)
+        tgis.register_maps_in_space_time_dataset(type="rast", name=None,  maps="singletmap", 
+                                                start="2001-01-03", end="2001-01-04", interval=True)
+
+    def tearDown(self):
+        self.runModule("t.remove", inputs="R", quiet=True)
+
+    @classmethod
+    def tearDownClass(cls):
+        """Remove the temporary region
+        """
+        cls.runModule("t.remove", flags="rf", inputs="A,B,C,D", quiet=True)
+        cls.del_temp_region()
+
+    def test_temporal_select1(self):
+        """Testing the temporal select operator with equal relations. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        ta.parse(expression="R = A : A",  stdstype = 'strds', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 4)
+        self.assertEqual(D.metadata.get_min_min(), 1) 
+        self.assertEqual(D.metadata.get_max_max(), 4) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+
+    def test_temporal_select2(self):
+        """Testing the temporal select operator with equal relations. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        ta.parse(expression="R = A : D",  stdstype = 'strds', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 3) 
+        self.assertEqual(D.metadata.get_max_max(), 4) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 3))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+
+    def test_temporal_select3(self):
+        """Testing the temporal select operator with equal relations. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        ta.parse(expression="R = A !: D",  stdstype = 'strds', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 1) 
+        self.assertEqual(D.metadata.get_max_max(), 2) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 3))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+
+    def test_temporal_select_operators1(self):
+        """Testing the temporal select operator. Including temporal relations. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        ta.parse(expression="R = A {:,during} C",  stdstype = 'strds', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 2) 
+        self.assertEqual(D.metadata.get_max_max(), 3) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 2))
+        self.assertEqual(end, datetime.datetime(2001, 1, 4))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+
+    def test_temporal_select_operators2(self):
+        """Testing the temporal select operator. Including temporal relations. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        ta.parse(expression="R = A {:,equal|during} C",  stdstype = 'strds', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 2) 
+        self.assertEqual(D.metadata.get_max_max(), 3) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 2))
+        self.assertEqual(end, datetime.datetime(2001, 1, 4))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+
+    def test_temporal_select_operators3(self):
+        """Testing the temporal select operator. Including temporal relations 
+            and negation operation. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        ta.parse(expression="R = A {!:,during} C",  stdstype = 'strds', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 1) 
+        self.assertEqual(D.metadata.get_max_max(), 4) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+
+    def test_temporal_select_operators4(self):
+        """Testing the temporal select operator. Including temporal relations and 
+            temporal operators. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        ta.parse(expression="R = A {:,during,d} C",  stdstype = 'strds', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        maplist = D.get_registered_maps_as_objects()
+        for map_i in maplist:
+            start_map, end_map = map_i.get_absolute_time()
+            self.assertEqual(start_map, datetime.datetime(2001, 1, 2))
+            self.assertEqual(end_map, datetime.datetime(2001, 1, 4))
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 2) 
+        self.assertEqual(D.metadata.get_max_max(), 3) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 2))
+        self.assertEqual(end, datetime.datetime(2001, 1, 4))
+        self.assertEqual( D.check_temporal_topology(),  False)
+        self.assertEqual(D.get_granularity(),  u'2 days')
+
+    def test_temporal_select_operators5(self):
+        """Testing the temporal select operator. Including temporal relations and 
+            temporal operators. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        ta.parse(expression="R = C {:,contains} A",  stdstype = 'strds', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        maplist = D.get_registered_maps_as_objects()
+        for map_i in maplist:
+            start_map, end_map = map_i.get_absolute_time()
+            self.assertEqual(start_map, datetime.datetime(2001, 1, 2))
+            self.assertEqual(end_map, datetime.datetime(2001, 1, 4))
+        self.assertEqual(D.metadata.get_number_of_maps(), 1)
+        self.assertEqual(D.metadata.get_min_min(), 7) 
+        self.assertEqual(D.metadata.get_max_max(), 7) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 2))
+        self.assertEqual(end, datetime.datetime(2001, 1, 4))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'2 days')
+
+    def test_temporal_extent1(self):
+        """Testing the temporal extent operators. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        ta.parse(expression="R = A {:,during,r} C",  stdstype = 'strds', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        maplist = D.get_registered_maps_as_objects()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 2) 
+        self.assertEqual(D.metadata.get_max_max(), 3) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 2))
+        self.assertEqual(end, datetime.datetime(2001, 1, 4))
+        self.assertEqual( D.check_temporal_topology(),  False)
+        self.assertEqual(D.get_granularity(),  u'2 days')
+
+    def test_temporal_extent2(self):
+        """Testing the temporal extent operators. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        ta.parse(expression="R = A {:,during,d} C",  stdstype = 'strds', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        maplist = D.get_registered_maps_as_objects()    
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 2) 
+        self.assertEqual(D.metadata.get_max_max(), 3) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 2))
+        self.assertEqual(end, datetime.datetime(2001, 1, 4))
+        self.assertEqual( D.check_temporal_topology(),  False)
+        self.assertEqual(D.get_granularity(),  u'2 days')
+
+    def test_temporal_extent3(self):
+        """Testing the temporal extent operators. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        ta.parse(expression="R = A {:,during,u} C",  stdstype = 'strds', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        maplist = D.get_registered_maps_as_objects()
+        for map_i in maplist:
+            start_map, end_map = map_i.get_absolute_time()
+            self.assertEqual(start_map, datetime.datetime(2001, 1, 2))
+            self.assertEqual(end_map, datetime.datetime(2001, 1, 4))            
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 2) 
+        self.assertEqual(D.metadata.get_max_max(), 3) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 2))
+        self.assertEqual(end, datetime.datetime(2001, 1, 4))
+        self.assertEqual( D.check_temporal_topology(),  False)
+        self.assertEqual(D.get_granularity(),  u'2 days')
+
+    def test_temporal_hash1(self):
+        """Testing the hash function in conditional statement. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        ta.parse(expression="R = if(A # D == 1, A)",  stdstype = 'strds', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        maplist = D.get_registered_maps_as_objects()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 3) 
+        self.assertEqual(D.metadata.get_max_max(), 4) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 3))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+
+    def test_temporal_hash_operator1(self):
+        """Testing the hash operator function in conditional statement. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        ta.parse(expression="R = if(A {#,during} C == 1, A)",  stdstype = 'strds', 
+                                       basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        maplist = D.get_registered_maps_as_objects()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 2) 
+        self.assertEqual(D.metadata.get_max_max(), 3) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 2))
+        self.assertEqual(end, datetime.datetime(2001, 1, 4))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+
+    def test_temporal_hash_operator2(self):
+        """Testing the hash operator function in conditional statement. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        ta.parse(expression="R = if({during}, C {#,contains} A == 2, A)",  
+                                                 stdstype = 'strds', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        maplist = D.get_registered_maps_as_objects()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 2) 
+        self.assertEqual(D.metadata.get_max_max(), 3) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 2))
+        self.assertEqual(end, datetime.datetime(2001, 1, 4))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+    
+    def test_tmap_function1(self):
+        """Testing the tmap function. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        ta.parse(expression='R = tmap(singletmap)',  stdstype = 'strds', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        maplist = D.get_registered_maps_as_objects()
+        self.assertEqual(D.metadata.get_number_of_maps(), 1)
+        self.assertEqual(D.metadata.get_min_min(), 99) 
+        self.assertEqual(D.metadata.get_max_max(), 99) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 3))
+        self.assertEqual(end, datetime.datetime(2001, 1, 4))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+
+    def test_tmap_function2(self):
+        """Testing the tmap function. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        ta.parse(expression='R = A : tmap(singletmap)',  stdstype = 'strds', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        maplist = D.get_registered_maps_as_objects()
+        self.assertEqual(D.metadata.get_number_of_maps(), 1)
+        self.assertEqual(D.metadata.get_min_min(), 3) 
+        self.assertEqual(D.metadata.get_max_max(), 3) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 3))
+        self.assertEqual(end, datetime.datetime(2001, 1, 4))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+
+if __name__ == '__main__':
+    grass.gunittest.test()

+ 228 - 0
lib/python/temporal/testsuite/unittests_temporal_algebra_grs.py

@@ -0,0 +1,228 @@
+"""
+(C) 2013 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.
+
+:authors: Soeren Gebbert and Thomas Leppelt
+"""
+
+import grass.script
+import grass.temporal as tgis
+import grass.gunittest
+import datetime
+import os
+
+class TestTemporalAlgebraGranularity(grass.gunittest.TestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        """Initiate the temporal GIS and set the region
+        """
+        tgis.init(True) # Raise on error instead of exit(1)
+        cls.use_temp_region()
+        cls.runModule("g.region", n=80.0, s=0.0, e=120.0,
+                                       w=0.0, t=1.0, b=0.0, res=10.0)
+
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="a1 = 1")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="a2 = 2")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="a3 = 3")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="a4 = 4")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="a5 = 5")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="a6 = 6")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="b1 = 7")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="b2 = 8")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="c1 = 9")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="d1 = 10")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="d2 = 11")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="d3 = 12")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="singletmap = 99")
+
+
+        tgis.open_new_stds(name="A", type="strds", temporaltype="absolute",
+                                         title="A", descr="A", semantic="field", overwrite=True)
+        tgis.open_new_stds(name="B", type="strds", temporaltype="absolute",
+                                         title="B", descr="B", semantic="field", overwrite=True)
+        tgis.open_new_stds(name="C", type="strds", temporaltype="absolute",
+                                         title="C", descr="C", semantic="field", overwrite=True)
+        tgis.open_new_stds(name="D", type="strds", temporaltype="absolute",
+                                         title="D", descr="D", semantic="field", overwrite=True)
+
+        tgis.register_maps_in_space_time_dataset(type="rast", name="A", maps="a1,a2,a3,a4,a5,a6",
+                                                 start="2001-01-01", increment="1 month", interval=True)
+        tgis.register_maps_in_space_time_dataset(type="rast", name="B", maps="b1,b2",
+                                                 start="2001-01-01", increment="3 months", interval=True)
+        tgis.register_maps_in_space_time_dataset(type="rast", name="C", maps="c1",
+                                                 start="2001-01-01", increment="1 year", interval=True)
+        tgis.register_maps_in_space_time_dataset(type="rast", name="D", maps="d1",
+                                                 start="2001-01-01", increment="31 days", interval=True)
+        tgis.register_maps_in_space_time_dataset(type="rast", name="D", maps="d2",
+                                                 start="2001-03-01", increment="31 days", interval=True)
+        tgis.register_maps_in_space_time_dataset(type="rast", name="D", maps="d3",
+                                                 start="2001-05-01", increment="31 days", interval=True)
+        tgis.register_maps_in_space_time_dataset(type="rast", name=None,  maps="singletmap", 
+                                                start="2001-01-03", end="2001-01-04", interval=True)
+
+    def tearDown(self):
+        pass
+        #self.runModule("t.remove", inputs="R", quiet=True)
+
+    @classmethod
+    def tearDownClass(cls):
+        """Remove the temporary region
+        """
+        #cls.runModule("t.remove", flags="rf", inputs="A,B,C,D", quiet=True)
+        cls.del_temp_region()
+
+    def test_common_granularity_1(self):
+        """Testing the common granularity function. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        expr = 'R = A : B'
+        ret = ta.setup_common_granularity(expression=expr)
+
+        self.assertEqual(ret, True)
+        self.assertEqual(ta.granularity, "1 months")
+
+        ta.count = 0
+        ta.stdstype = "strds"
+        ta.maptype = "rast"
+        ta.mapclass = tgis.RasterDataset
+
+        maplist = ta.check_stds("A")
+        self.assertEqual(len(maplist), 6)
+        maplist = ta.check_stds("B")
+        self.assertEqual(len(maplist), 6)
+        
+        ta.parse(expression=expr, basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+
+        self.assertEqual(D.metadata.get_number_of_maps(), 6)
+        self.assertEqual(D.metadata.get_min_min(), 1) 
+        self.assertEqual(D.metadata.get_max_max(), 6) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 7, 1))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 month')
+       
+    def test_common_granularity_2(self):
+        """Testing the common granularity function year to month samping. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        expr = 'R = A : C'
+        ret = ta.setup_common_granularity(expression=expr)
+        
+        ta.parse(expression=expr, basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+
+        self.assertEqual(D.metadata.get_number_of_maps(), 6)
+        self.assertEqual(D.metadata.get_min_min(), 1) 
+        self.assertEqual(D.metadata.get_max_max(), 6) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 7, 1))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 month')
+       
+
+    def test_common_granularity_3(self):
+        """Testing the common granularity function with gaps. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        expr = 'R = A : D'
+        ret = ta.setup_common_granularity(expression=expr)
+        
+        ta.parse(expression=expr, basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+
+        self.assertEqual(D.metadata.get_number_of_maps(), 3)
+        self.assertEqual(D.metadata.get_min_min(), 1) 
+        self.assertEqual(D.metadata.get_max_max(), 5) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 6, 1))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 month')
+       
+
+    def test_common_granularity_4(self):
+        """Testing the common granularity function year to month with gaps. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        expr = 'R = C : D'
+        ret = ta.setup_common_granularity(expression=expr)
+        
+        ta.parse(expression=expr, basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+
+        self.assertEqual(D.metadata.get_number_of_maps(), 3)
+        self.assertEqual(D.metadata.get_min_min(), 9) 
+        self.assertEqual(D.metadata.get_max_max(), 9) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 6, 1))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 month')
+       
+    def test_common_granularity_4(self):
+        """Testing the common granularity function year to month with gaps. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        expr = 'R = C : D'
+        ret = ta.setup_common_granularity(expression=expr)
+        
+        ta.parse(expression=expr, basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+
+        self.assertEqual(D.metadata.get_number_of_maps(), 3)
+        self.assertEqual(D.metadata.get_min_min(), 9) 
+        self.assertEqual(D.metadata.get_max_max(), 9) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 6, 1))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 month')
+       
+    def test_common_granularity_5(self):
+        """Testing the common granularity function year to month with gaps. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        expr = 'R = A : C : D'
+        ret = ta.setup_common_granularity(expression=expr)
+        
+        ta.parse(expression=expr, basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+
+        self.assertEqual(D.metadata.get_number_of_maps(), 3)
+        self.assertEqual(D.metadata.get_min_min(), 1) 
+        self.assertEqual(D.metadata.get_max_max(), 5) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 6, 1))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 month')
+         
+    def test_common_granularity_6(self):
+        """Testing the common granularity function year to month with gaps. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        expr = 'R = if(start_month(A) > 2, A : C : D)'
+        ret = ta.setup_common_granularity(expression=expr)
+        
+        ta.parse(expression=expr, basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 3) 
+        self.assertEqual(D.metadata.get_max_max(), 5) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 3, 1))
+        self.assertEqual(end, datetime.datetime(2001, 6, 1))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 month')
+       
+
+
+if __name__ == '__main__':
+    grass.gunittest.test()

+ 356 - 0
lib/python/temporal/testsuite/unittests_temporal_conditionals.py

@@ -0,0 +1,356 @@
+"""
+(C) 2014 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.
+
+:authors: Thomas leppelt and Soeren Gebbert
+"""
+
+import grass.script
+import grass.temporal as tgis
+import grass.gunittest
+import datetime
+import os
+
+class TestTemporalConditionals(grass.gunittest.TestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        """Initiate the temporal GIS and set the region
+        """
+        tgis.init(True) # Raise on error instead of exit(1)
+        cls.use_temp_region()
+        cls.runModule("g.region", n=80.0, s=0.0, e=120.0,
+                                       w=0.0, t=1.0, b=0.0, res=10.0)
+
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="a1 = 1")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="a2 = 2")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="a3 = 3")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="a4 = 4")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="b1 = 5")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="b2 = 6")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="c1 = 7")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="d1 = 8")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="d2 = 9")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="d3 = 10")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="e1 = 11")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="e2 = 12")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="e3 = 13")
+        
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="singletmap = 99")
+
+        tgis.open_new_stds(name="A", type="strds", temporaltype="absolute",
+                                         title="A", descr="A", semantic="field", overwrite=True)
+        tgis.open_new_stds(name="B", type="strds", temporaltype="absolute",
+                                         title="B", descr="B", semantic="field", overwrite=True)
+        tgis.open_new_stds(name="C", type="strds", temporaltype="absolute",
+                                         title="C", descr="C", semantic="field", overwrite=True)
+        tgis.open_new_stds(name="D", type="strds", temporaltype="absolute",
+                                         title="D", descr="D", semantic="field", overwrite=True)
+        tgis.open_new_stds(name="E", type="strds", temporaltype="absolute",
+                                         title="E", descr="E", semantic="field", overwrite=True)
+                                         
+        tgis.register_maps_in_space_time_dataset(type="rast", name="A", maps="a1,a2,a3,a4",
+                                                 start="2001-01-01", increment="1 day", interval=True)
+        tgis.register_maps_in_space_time_dataset(type="rast", name="B", maps="b1,b2",
+                                                 start="2001-01-01", increment="2 day", interval=True)
+        tgis.register_maps_in_space_time_dataset(type="rast", name="C", maps="c1",
+                                                 start="2001-01-02", increment="2 day", interval=True)
+        tgis.register_maps_in_space_time_dataset(type="rast", name="D", maps="d1,d2,d3",
+                                                 start="2001-01-03", increment="1 day", interval=True)
+        tgis.register_maps_in_space_time_dataset(type="rast", name="E", maps="e1,e2,e3",
+                                                 start="2000-12-31", increment="2 day", interval=True)
+        tgis.register_maps_in_space_time_dataset(type="rast", name=None,  maps="singletmap", 
+                                                start="2001-01-03", end="2001-01-04", interval=True)
+
+    def tearDown(self):
+        self.runModule("t.remove", inputs="R", quiet=True)
+
+    @classmethod
+    def tearDownClass(cls):
+        """Remove the temporary region
+        """
+        cls.runModule("t.remove", flags="rf", inputs="A,B,C,D,E", quiet=True)
+        cls.del_temp_region()
+
+    def test_temporal_condition_1(self):
+        """Testing the temporal select operator with equal relations. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        ta.parse(expression='R = if(start_date(A) >= "2001-01-03", A)', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 3) 
+        self.assertEqual(D.metadata.get_max_max(), 4) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 3))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+
+    def test_temporal_condition_2(self):
+        """Testing the temporal select operator with equal relations. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        ta.parse(expression='R = if(td(A) == 1, A)', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 4)
+        self.assertEqual(D.metadata.get_min_min(), 1) 
+        self.assertEqual(D.metadata.get_max_max(), 4) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+    
+    def test_temporal_condition_3(self):
+        """Testing the temporal select operator with equal relations. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        ta.parse(expression='R = if(td(A) == 1 || start_date(A) >= "2001-01-03", A)', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 4)
+        self.assertEqual(D.metadata.get_min_min(), 1) 
+        self.assertEqual(D.metadata.get_max_max(), 4) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+    
+    def test_temporal_condition_4(self):
+        """Testing the temporal select operator with equal relations. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        ta.parse(expression='R = if(start_date(A) >= "2001-01-03", A)', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 3) 
+        self.assertEqual(D.metadata.get_max_max(), 4) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 3))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+
+    def test_temporal_condition_5(self):
+        """Testing the temporal select operator with equal relations. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        ta.parse(expression='R = if(start_day(A) <= 2, A)', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 1) 
+        self.assertEqual(D.metadata.get_max_max(), 2) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 3))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+    
+    def test_temporal_condition_6(self):
+        """Testing the temporal select operator with equal relations. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        ta.parse(expression='R = if(td(A) == 1 {||,during} start_date(C) < "2001-01-02", A)', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 2) 
+        self.assertEqual(D.metadata.get_max_max(), 3) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 2))
+        self.assertEqual(end, datetime.datetime(2001, 1, 4))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+
+    def test_temporal_condition_7(self):
+        """Testing the temporal select operator with equal relations. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        ta.parse(expression='R = if({over},start_date(C) == "2001-01-02" {&&,contains} td(A) == 1, B)', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 5) 
+        self.assertEqual(D.metadata.get_max_max(), 6) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'2 days')
+
+    def test_temporal_condition_8(self):
+        """Testing the temporal select operator with equal relations. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        ta.parse(expression='R = if(start_date(B) <= "2001-01-01" {||,over,|} td(E) == 2, B)', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 5) 
+        self.assertEqual(D.metadata.get_max_max(), 6) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'2 days')
+
+    def test_temporal_condition_9(self):
+        """Testing the temporal select operator with equal relations. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        ta.parse(expression='R = if(start_date(B) <= "2001-01-01" {&&,over,&} td(E) == 2, B)', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 1)
+        self.assertEqual(D.metadata.get_min_min(), 5) 
+        self.assertEqual(D.metadata.get_max_max(), 5) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 3))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'2 days')
+
+    def test_temporal_condition_10(self):
+        """Testing the temporal select operator with equal relations. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        ta.parse(expression='R = if(start_date(B) <= "2001-01-01" {||,over,|,r} td(E) == 2, E)', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 3)
+        self.assertEqual(D.metadata.get_min_min(), 11) 
+        self.assertEqual(D.metadata.get_max_max(), 13) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2000, 12, 31))
+        self.assertEqual(end, datetime.datetime(2001, 1, 6))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'2 days')
+ 
+    def test_temporal_condition_11(self):
+        """Testing the temporal select operator with equal relations. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        ta.parse(expression='R = if(start_date(B) <= "2001-01-01" {&&,over,r} td(E) == 2, E)', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 1)
+        self.assertEqual(D.metadata.get_min_min(), 11) 
+        self.assertEqual(D.metadata.get_max_max(), 11) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2000, 12, 31))
+        self.assertEqual(end, datetime.datetime(2001, 1, 2))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'2 days')
+
+    def test_temporal_condition_12(self):
+        """Testing the temporal select operator with equal relations. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        ta.parse(expression='R = if(start_date(B) <= "2001-01-01" {&&,over,|,r} td(E) == 2, E)', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 1)
+        self.assertEqual(D.metadata.get_min_min(), 11) 
+        self.assertEqual(D.metadata.get_max_max(), 11) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2000, 12, 31))
+        self.assertEqual(end, datetime.datetime(2001, 1, 2))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'2 days')
+    
+    def test_temporal_conditional_13(self):
+        """Testing the hash operator function in conditional statement. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        ta.parse(expression='R = if({equal|during},td(B) == 2 {&&,contains} td(A) == 1, A)', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        maplist = D.get_registered_maps_as_objects()
+        self.assertEqual(D.metadata.get_number_of_maps(), 4)
+        self.assertEqual(D.metadata.get_min_min(), 1) 
+        self.assertEqual(D.metadata.get_max_max(), 4) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+ 
+    def test_temporal_condition_else_1(self):
+        """Testing the temporal select operator with equal relations. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        ta.parse(expression='R = if(start_date(A) <= "2001-01-03", A, D)', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 4)
+        self.assertEqual(D.metadata.get_min_min(), 1) 
+        self.assertEqual(D.metadata.get_max_max(), 9) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+    
+    def test_temporal_condition_else_2(self):
+        """Testing the temporal select operator with equal relations. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        ta.parse(expression='R = if(td(D) == 1 && start_date(A) >= "2001-01-04", A, D)', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 4) 
+        self.assertEqual(D.metadata.get_max_max(), 8) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 3))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+
+    def test_temporal_condition_else_3(self):
+        """Testing the temporal select operator with equal relations. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        ta.parse(expression='R = if({during},td(B) == 2 {&&,contains} start_date(D) >= "2001-01-04", A, D)', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 8) 
+        self.assertEqual(D.metadata.get_max_max(), 9) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 3))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+
+    def test_temporal_condition_else_4(self):
+        """Testing the temporal select operator with equal relations. """
+        ta = tgis.TemporalAlgebraParser(run = True, debug = True)
+        ta.parse(expression='R = if({equal|over},start_date(B) <= "2001-01-01" {&&,over,|,r} td(E) == 2, E, B)', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        for map in D.get_registered_maps_as_objects():
+            print(map.get_map_id())
+        self.assertEqual(D.metadata.get_number_of_maps(), 3)
+        self.assertEqual(D.metadata.get_min_min(), 5) 
+        self.assertEqual(D.metadata.get_max_max(), 11) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2000, 12, 31))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( D.check_temporal_topology(),  False)
+        self.assertEqual(D.get_granularity(),  u'2 days')
+
+if __name__ == '__main__':
+    grass.gunittest.test()
+
+
+

+ 27 - 28
lib/python/temporal/unittests_temporal_raster3d_algebra.py

@@ -1,50 +1,58 @@
-"""!Unit test to register raster maps with absolute and relative
-   time using tgis.register_maps_in_space_time_dataset()
-
-(C) 2013 by the GRASS Development Team
+"""
+(C) 2014 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
+:authors: Soeren Gebbert and Thomas Leppelt
 """
 
+
 import grass.script
 import grass.temporal as tgis
-import unittest
+import grass.gunittest as gunittest
 import datetime
 import os
 
-class TestRegisterFunctions(unittest.TestCase):
+class TestTemporalRaster3dAlgebra(gunittest.TestCase):
 
     @classmethod
     def setUpClass(cls):
-        """!Initiate the temporal GIS and set the region
+        """Initiate the temporal GIS and set the region
         """
         tgis.init(True) # Raise on error instead of exit(1)
-        grass.script.use_temp_region()
+        cls.use_temp_region()
         ret = grass.script.run_command("g.region", n=80.0, s=0.0, e=120.0,
                                        w=0.0, t=100.0, b=0.0, res=10.0)
 
-        ret += grass.script.run_command("r3.mapcalc", overwrite=True, quiet=True, expression="a1 = 1")
-        ret += grass.script.run_command("r3.mapcalc", overwrite=True, quiet=True, expression="a2 = 2")
-        ret += grass.script.run_command("r3.mapcalc", overwrite=True, quiet=True, expression="a3 = 3")
-        ret += grass.script.run_command("r3.mapcalc", overwrite=True, quiet=True, expression="a4 = 4")
+        cls.runModule("r3.mapcalc", overwrite=True, quiet=True, expression="a1 = 1")
+        cls.runModule("r3.mapcalc", overwrite=True, quiet=True, expression="a2 = 2")
+        cls.runModule("r3.mapcalc", overwrite=True, quiet=True, expression="a3 = 3")
+        cls.runModule("r3.mapcalc", overwrite=True, quiet=True, expression="a4 = 4")
 
-
-        tgis.open_new_space_time_dataset(name="A", type="str3ds", temporaltype="absolute",
+        tgis.open_new_stds(name="A", type="str3ds", temporaltype="absolute",
                                          title="A", descr="A", semantic="field", overwrite=True)
 
         tgis.register_maps_in_space_time_dataset(type="rast3d", name="A", maps="a1,a2,a3,a4",
                                                  start="2001-01-01", increment="1 day", interval=True)
 
+    def tearDown(self):
+        self.runModule("t.remove", type="str3ds", flags="rf", inputs="D", quiet=True)
+
+    @classmethod
+    def tearDownClass(cls):
+        """Remove the temporary region
+        """
+        cls.runModule("t.remove", type="str3ds", flags="rf", inputs="A", quiet=True)
+        cls.del_temp_region()
+
     def test_temporal_neighbors_1(self):
         """Simple temporal neighborhood computation test"""
         tra = tgis.TemporalRaster3DAlgebraParser(run = True, debug = True)
         tra.parse(expression='D = A[-1] + A[1]',
                   basename="d", overwrite=True)
 
-        D = tgis.open_old_space_time_dataset("D", type="str3ds")
+        D = tgis.open_old_stds("D", type="str3ds")
         D.select()
         self.assertEqual(D.metadata.get_number_of_maps(), 2)
         self.assertEqual(D.metadata.get_min_min(), 4)  # 1 + 3
@@ -59,7 +67,7 @@ class TestRegisterFunctions(unittest.TestCase):
         tra.parse(expression='D = A[0,0,0,-1] + A[0,0,0,1]',
                   basename="d", overwrite=True)
 
-        D = tgis.open_old_space_time_dataset("D", type="str3ds")
+        D = tgis.open_old_stds("D", type="str3ds")
         D.select()
         self.assertEqual(D.metadata.get_number_of_maps(), 2)
         self.assertEqual(D.metadata.get_min_min(), 4)  # 1 + 3
@@ -68,17 +76,8 @@ class TestRegisterFunctions(unittest.TestCase):
         self.assertEqual(start, datetime.datetime(2001, 1, 2))
         self.assertEqual(end, datetime.datetime(2001, 1, 4))
 
-    def tearDown(self):
-        ret = grass.script.run_command("t.remove", type="str3ds", flags="rf", input="D", quiet=True)
-
-    @classmethod
-    def tearDownClass(cls):
-        """!Remove the temporary region
-        """
-        ret = grass.script.run_command("t.remove", type="str3ds", flags="rf", input="A", quiet=True)
-        grass.script.del_temp_region()
-
 if __name__ == '__main__':
-    unittest.main()
+    grass.gunittest.test()
+
 
 

+ 711 - 0
lib/python/temporal/testsuite/unittests_temporal_raster_algebra.py

@@ -0,0 +1,711 @@
+"""
+(C) 2014 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.
+
+:authors: Soeren Gebbert and Thomas Leppelt
+"""
+
+import datetime
+import os
+import grass.script
+import grass.temporal as tgis
+import grass.gunittest as gunittest
+
+class TestTemporalRasterAlgebra(gunittest.TestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        """Initiate the temporal GIS and set the region
+        """
+        tgis.init(True) # Raise on error instead of exit(1)
+        cls.use_temp_region()
+        cls.runModule("g.region", n=80.0, s=0.0, e=120.0,
+                                       w=0.0, t=1.0, b=0.0, res=10.0)
+
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="a1 = 1")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="a2 = 2")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="a3 = 3")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="a4 = 4")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="b1 = 5")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="b2 = 6")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="c1 = 7")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="d1 = 8")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="d2 = 9")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="d3 = 10")        
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="singletmap = 99")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="singlemap = 100")
+
+        tgis.open_new_stds(name="A", type="strds", temporaltype="absolute",
+                                         title="A", descr="A", semantic="field", overwrite=True)
+        tgis.open_new_stds(name="B", type="strds", temporaltype="absolute",
+                                         title="B", descr="B", semantic="field", overwrite=True)
+        tgis.open_new_stds(name="C", type="strds", temporaltype="absolute",
+                                         title="B", descr="C", semantic="field", overwrite=True)
+        tgis.open_new_stds(name="D", type="strds", temporaltype="absolute",
+                                         title="D", descr="D", semantic="field", overwrite=True)
+
+        tgis.register_maps_in_space_time_dataset(type="rast", name="A", maps="a1,a2,a3,a4",
+                                                 start="2001-01-01", increment="1 day", interval=True)
+        tgis.register_maps_in_space_time_dataset(type="rast", name="B", maps="b1,b2",
+                                                 start="2001-01-01", increment="2 day", interval=True)
+        tgis.register_maps_in_space_time_dataset(type="rast", name="C", maps="c1",
+                                                 start="2001-01-02", increment="2 day", interval=True)
+        tgis.register_maps_in_space_time_dataset(type="rast", name="D", maps="d1,d2,d3",
+                                                 start="2001-01-03", increment="1 day", interval=True)                                                 
+        tgis.register_maps_in_space_time_dataset(type="rast", name=None,  maps="singletmap", 
+                                                start="2001-01-03", end="2001-01-04", interval=True)
+        
+    def tearDown(self):
+        self.runModule("t.remove", flags="rf", inputs="R", quiet=True)
+
+    @classmethod
+    def tearDownClass(cls):
+        """Remove the temporary region 
+        """
+        cls.runModule("t.remove", flags="rf", inputs="A,B,C,D", quiet=True)
+        cls.runModule("t.unregister", maps="singletmap", quiet=True)
+        cls.del_temp_region()
+
+    def test_temporal_extent1(self):
+        """Testing the temporal extent operators. """
+        ta = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        ta.parse(expression="R = A {:,during,r} C",   basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        maplist = D.get_registered_maps_as_objects()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 2) 
+        self.assertEqual(D.metadata.get_max_max(), 3) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 2))
+        self.assertEqual(end, datetime.datetime(2001, 1, 4))
+        self.assertEqual( D.check_temporal_topology(),  False)
+        self.assertEqual(D.get_granularity(),  u'2 days')
+
+    def test_temporal_conditional_time_dimension_bug(self):
+        """Testing the conditional time dimension bug, that uses the time 
+            dimension of the conditional statement instead the time dimension 
+            of the then/else statement."""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression="R = if({contains}, B == 5,  A - 1,  A + 1)", basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 4)
+        self.assertEqual(D.metadata.get_min_min(), 0) # 1 - 1
+        self.assertEqual(D.metadata.get_max_max(), 5) # 4 + 1
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+
+    def test_simple_arith_hash_1(self):
+        """Simple arithmetic test including the hash operator"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = A + (A {#, equal,l} A)', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 4)
+        self.assertEqual(D.metadata.get_min_min(), 2)
+        self.assertEqual(D.metadata.get_max_max(), 5)
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+
+
+    def test_simple_arith_td_1(self):
+        """Simple arithmetic test"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = A + td(A)', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 4)
+        self.assertEqual(D.metadata.get_min_min(), 2)
+        self.assertEqual(D.metadata.get_max_max(), 5)
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+
+    def test_simple_arith_td_2(self):
+        """Simple arithmetic test"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = A / td(A)', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 4)
+        self.assertEqual(D.metadata.get_min_min(), 1)
+        self.assertEqual(D.metadata.get_max_max(), 4)
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+
+    def test_simple_arith_td_3(self):
+        """Simple arithmetic test"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = A {+,equal} td(A)', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 4)
+        self.assertEqual(D.metadata.get_min_min(), 2)
+        self.assertEqual(D.metadata.get_max_max(), 5)
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+
+
+    def test_simple_arith_td_4(self):
+        """Simple arithmetic test"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = A {/, equal} td(A)', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 4)
+        self.assertEqual(D.metadata.get_min_min(), 1)
+        self.assertEqual(D.metadata.get_max_max(), 4)
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+
+
+    def test_simple_arith_if_1(self):
+        """Simple arithmetic test with if condition"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = if({equal}, start_date(A) >= "2001-01-02", A + A)', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 3)
+        self.assertEqual(D.metadata.get_min_min(), 4)
+        self.assertEqual(D.metadata.get_max_max(), 8)
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 2))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+
+    def test_simple_arith_if_2(self):
+        """Simple arithmetic test with if condition"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = if({equal}, A#A == 1, A - A)', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 4)
+        self.assertEqual(D.metadata.get_min_min(), 0)
+        self.assertEqual(D.metadata.get_max_max(), 0)
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+
+    def test_complex_arith_if_1(self):
+        """Complex arithmetic test with if condition"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = if(start_date(A) < "2001-01-03" && A#A == 1, A{+, starts,l}C, A{+, finishes,l}C)', \
+                  basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 9)  # 2 + 7 a2 + c1
+        self.assertEqual(D.metadata.get_max_max(), 10) # 3 + 7 a3 + c1
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 2))
+        self.assertEqual(end, datetime.datetime(2001, 1, 4))
+
+    def test_simple_arith_1(self):
+        """Simple arithmetic test"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression="R = A {*, equal} A {+, equal} A", basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 4)
+        self.assertEqual(D.metadata.get_min_min(), 2)  # 1*1 + 1
+        self.assertEqual(D.metadata.get_max_max(), 20) # 4*4 + 4
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+
+    def test_simple_arith_2(self):
+        """Simple arithmetic test that creates an empty strds"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression="R = A {*, during} A {+, during} A", basename="r", overwrite=True)
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 0)
+
+    def test_simple_arith_3(self):
+        """Simple arithmetic test"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression="R = A / A + A*A/A", basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 4)
+        self.assertEqual(D.metadata.get_min_min(), 2) # 1/1 + 1*1/1
+        self.assertEqual(D.metadata.get_max_max(), 5) # 4/4 + 4*4/4
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        
+    def test_temporal_intersection_1(self):
+        """Simple temporal intersection test"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression="R = A {+,equal,i} B", basename="r", overwrite=True)
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 0)
+
+    def test_temporal_intersection_2(self):
+        """Simple temporal intersection test"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression="R = A {+,during,i} B", basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 4)
+        self.assertEqual(D.metadata.get_min_min(), 6) # 1 + 5
+        self.assertEqual(D.metadata.get_max_max(), 10) # 4 + 6
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+
+    def test_temporal_intersection_3(self):
+        """Simple temporal intersection test"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression="R = A {+,starts,i} B", basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 6) # 1 + 5
+        self.assertEqual(D.metadata.get_max_max(), 9) # 3 + 6
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 4))
+
+    def test_temporal_intersection_4(self):
+        """Simple temporal intersection test"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression="R = A {+,finishes,intersect} B", basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 7)  # 2 + 5
+        self.assertEqual(D.metadata.get_max_max(), 10) # 4 + 6
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 2))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+
+    def test_temporal_intersection_5(self):
+        """Simple temporal intersection test"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression="R = A {+,starts|finishes,i} B", basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 4)
+        self.assertEqual(D.metadata.get_min_min(), 6)  # 1 + 5
+        self.assertEqual(D.metadata.get_max_max(), 10) # 4 + 6
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+
+    def test_temporal_intersection_6(self):
+        """Simple temporal intersection test"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression="R = B {+,overlaps,u} C", basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 1)
+        self.assertEqual(D.metadata.get_min_min(), 12) # 5 + 7
+        self.assertEqual(D.metadata.get_max_max(), 12) # 5 + 7
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 4))
+
+    def test_temporal_intersection_7(self):
+        """Simple temporal intersection test"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression="R = B {+,overlapped,u} C", basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 1)
+        self.assertEqual(D.metadata.get_min_min(), 13) # 6 + 7
+        self.assertEqual(D.metadata.get_max_max(), 13) # 6 + 7
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 2))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+
+    def test_temporal_intersection_8(self):
+        """Simple temporal intersection test"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = A {+,during,l} buff_t(C, "1 day") ',
+                  basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 4)
+        self.assertEqual(D.metadata.get_min_min(), 8)  # 1 + 7  a1 + c1
+        self.assertEqual(D.metadata.get_max_max(), 11) # 4 + 7  a4 + c1
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+
+    def test_temporal_neighbors_1(self):
+        """Simple temporal neighborhood computation test"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = A[-1] + A[1]',
+                  basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 4)  # 1 + 3
+        self.assertEqual(D.metadata.get_max_max(), 6) # 2 + 4
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 2))
+        self.assertEqual(end, datetime.datetime(2001, 1, 4))
+
+    def test_temporal_neighbors_2(self):
+        """Simple temporal neighborhood computation test"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = A[0,0,-1] + A[0,0,1]',
+                  basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 4)  # 1 + 3
+        self.assertEqual(D.metadata.get_max_max(), 6) # 2 + 4
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 2))
+        self.assertEqual(end, datetime.datetime(2001, 1, 4))
+
+    def test_tmap_function1(self):
+        """Testing the tmap function. """
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = tmap(singletmap)', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        maplist = D.get_registered_maps_as_objects()
+        self.assertEqual(D.metadata.get_number_of_maps(), 1)
+        self.assertEqual(D.metadata.get_min_min(), 99) 
+        self.assertEqual(D.metadata.get_max_max(), 99) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 3))
+        self.assertEqual(end, datetime.datetime(2001, 1, 4))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+
+    def test_tmap_function2(self):
+        """Testing the tmap function. """
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = tmap(singletmap) + 1', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        maplist = D.get_registered_maps_as_objects()
+        self.assertEqual(D.metadata.get_number_of_maps(), 1)
+        self.assertEqual(D.metadata.get_min_min(), 100) 
+        self.assertEqual(D.metadata.get_max_max(), 100) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 3))
+        self.assertEqual(end, datetime.datetime(2001, 1, 4))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+
+    def test_map_function1(self):
+        """Testing the map function. """
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = map(singlemap) + A', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        maplist = D.get_registered_maps_as_objects()
+        self.assertEqual(D.metadata.get_number_of_maps(), 4)
+        self.assertEqual(D.metadata.get_min_min(), 101) 
+        self.assertEqual(D.metadata.get_max_max(), 104) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+
+    def test_map_function2(self):
+        """Testing the map function. """
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R =  A * map(singlemap)', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        maplist = D.get_registered_maps_as_objects()
+        self.assertEqual(D.metadata.get_number_of_maps(), 4)
+        self.assertEqual(D.metadata.get_min_min(), 100) 
+        self.assertEqual(D.metadata.get_max_max(), 400) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+
+    def test_temporal_select(self):
+        """Testing the temporal select operator. """
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression="R = A : A", basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 4)
+        self.assertEqual(D.metadata.get_min_min(), 1) 
+        self.assertEqual(D.metadata.get_max_max(), 4) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+
+    def test_temporal_select(self):
+        """Testing the temporal select operator. """
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression="R = A : D", basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 3) 
+        self.assertEqual(D.metadata.get_max_max(), 4) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 3))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+
+    def test_temporal_select_operators1(self):
+        """Testing the temporal select operator. Including temporal relations. """
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression="R = A : D", basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 3) 
+        self.assertEqual(D.metadata.get_max_max(), 4) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 3))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+
+    def test_temporal_select_operators2(self):
+        """Testing the temporal select operator. Including temporal relations. """
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression="R = A {!:,during} C", basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 1) 
+        self.assertEqual(D.metadata.get_max_max(), 4) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+
+    def test_temporal_select_operators3(self):
+        """Testing the temporal select operator. Including temporal relations and 
+            different temporal operators (lr|+&)"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression="R = A {:,during,d} B", basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 4)
+        self.assertEqual(D.metadata.get_min_min(), 1) 
+        self.assertEqual(D.metadata.get_max_max(), 4) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( D.check_temporal_topology(),  False)
+        self.assertEqual(D.get_granularity(),  u'2 days')
+
+    def test_temporal_select_operators4(self):
+        """Testing the temporal select operator. Including temporal relations and 
+            different temporal operators (lr|+&)"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression="R = A {:,equal|during,r} C", basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        maplist = D.get_registered_maps_as_objects()
+        for map_i in maplist:
+            start_map, end_map = map_i.get_absolute_time()
+            self.assertEqual(start_map, datetime.datetime(2001, 1, 2))
+            self.assertEqual(end_map, datetime.datetime(2001, 1, 4))
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 2)
+        self.assertEqual(D.metadata.get_max_max(), 3)
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 2))
+        self.assertEqual(end, datetime.datetime(2001, 1, 4))
+        self.assertEqual( D.check_temporal_topology(),  False)
+        self.assertEqual(D.get_granularity(),  u'2 days')
+
+    def test_temporal_hash_operator1(self):
+        """Testing the temporal hash operator in the raster algebra. """
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression="R = if(A # D == 1, A)", basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 3) 
+        self.assertEqual(D.metadata.get_max_max(), 4) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 3))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+
+    def test_temporal_hash_operator2(self):
+        """Testing the temporal hash operator in the raster algebra. """
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression="R = A # D", basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 1) 
+        self.assertEqual(D.metadata.get_max_max(), 1) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 3))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+
+    def test_temporal_hash_operator3(self):
+        """Testing the temporal hash operator in the raster algebra. """
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression="R = C {#,contains} A", basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 1)
+        self.assertEqual(D.metadata.get_min_min(), 2) 
+        self.assertEqual(D.metadata.get_max_max(), 2) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 2))
+        self.assertEqual(end, datetime.datetime(2001, 1, 4))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'2 days')
+
+    def test_temporal_hash_operator4(self):
+        """Testing the temporal hash operator in the raster algebra. """
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression="R = if({contains},A # D == 1, C {#,contains} A)", basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 1)
+        self.assertEqual(D.metadata.get_min_min(), 2) 
+        self.assertEqual(D.metadata.get_max_max(), 2) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 2))
+        self.assertEqual(end, datetime.datetime(2001, 1, 4))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'2 days')
+ 
+    def test_raster_arithmetic_relation_1(self):
+        """Arithmetic test with temporal intersection"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression="R = B {+,contains,l} A ", basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 8) 
+        self.assertEqual(D.metadata.get_max_max(), 13) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'2 days')
+
+    def test_raster_arithmetic_relation_2(self):
+        """Arithmetic test with temporal intersection"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression="R = B {*,contains,l} A ", basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 10) 
+        self.assertEqual(D.metadata.get_max_max(), 72) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'2 days')
+
+    def test_raster_arithmetic_relation_3(self):
+        """Arithmetic test with temporal intersection"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression="R = B {+,contains,l} A ", basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_min_min(), 8) 
+        self.assertEqual(D.metadata.get_max_max(), 13) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'2 days')
+    
+    def test_raster_arithmetic_relation_4(self):
+        """Arithmetic test with temporal intersection"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression="R = B {+,contains,r} A ", basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(),4)
+        self.assertEqual(D.metadata.get_min_min(), 8) 
+        self.assertEqual(D.metadata.get_max_max(), 13) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+    
+    def test_raster_arithmetic_relation_5(self):
+        """Complex arithmetic test with temporal intersection"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression="R = tmap(singletmap) {+,equal| precedes| follows,l} A + map(singlemap)", basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(),1)
+        self.assertEqual(D.metadata.get_min_min(), 208) 
+        self.assertEqual(D.metadata.get_max_max(), 208)
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 3))
+        self.assertEqual(end, datetime.datetime(2001, 1, 4))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+
+if __name__ == '__main__':
+    gunittest.test()

+ 277 - 0
lib/python/temporal/testsuite/unittests_temporal_raster_algebra_grs.py

@@ -0,0 +1,277 @@
+"""
+(C) 2014 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.
+
+:authors: Soeren Gebbert and Thomas Leppelt
+"""
+
+import datetime
+import os
+import grass.script
+import grass.temporal as tgis
+import grass.gunittest as gunittest
+
+class TestTemporalRasterAlgebra(gunittest.TestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        """Initiate the temporal GIS and set the region
+        """
+        tgis.init(True) # Raise on error instead of exit(1)
+        cls.use_temp_region()
+        cls.runModule("g.region", n=80.0, s=0.0, e=120.0,
+                                       w=0.0, t=1.0, b=0.0, res=10.0)
+
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="a1 = 1")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="a2 = 2")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="a3 = 3")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="a4 = 4")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="a5 = 5")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="a6 = 6")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="b1 = 7")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="b2 = 8")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="c1 = 9")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="d1 = 10")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="d2 = 11")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="d3 = 12")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="singletmap = 99")
+
+        tgis.open_new_stds(name="A", type="strds", temporaltype="absolute",
+                                         title="A", descr="A", semantic="field", overwrite=True)
+        tgis.open_new_stds(name="B", type="strds", temporaltype="absolute",
+                                         title="B", descr="B", semantic="field", overwrite=True)
+        tgis.open_new_stds(name="C", type="strds", temporaltype="absolute",
+                                         title="C", descr="C", semantic="field", overwrite=True)
+        tgis.open_new_stds(name="D", type="strds", temporaltype="absolute",
+                                         title="D", descr="D", semantic="field", overwrite=True)
+
+        tgis.register_maps_in_space_time_dataset(type="rast", name="A", maps="a1,a2,a3,a4,a5,a6",
+                                                 start="2001-01-01", increment="1 month", interval=True)
+        tgis.register_maps_in_space_time_dataset(type="rast", name="B", maps="b1,b2",
+                                                 start="2001-01-01", increment="3 months", interval=True)
+        tgis.register_maps_in_space_time_dataset(type="rast", name="C", maps="c1",
+                                                 start="2001-01-01", increment="1 year", interval=True)
+        tgis.register_maps_in_space_time_dataset(type="rast", name="D", maps="d1",
+                                                 start="2001-01-01", increment="5 days", interval=True)
+        tgis.register_maps_in_space_time_dataset(type="rast", name="D", maps="d2",
+                                                 start="2001-03-01", increment="5 days", interval=True)
+        tgis.register_maps_in_space_time_dataset(type="rast", name="D", maps="d3",
+                                                 start="2001-05-01", increment="5 days", interval=True)
+        tgis.register_maps_in_space_time_dataset(type="rast", name=None,  maps="singletmap", 
+                                                start="2001-03-01", end="2001-04-01", interval=True)
+        
+    def tearDown(self):
+        return
+        self.runModule("t.remove", flags="rf", inputs="R", quiet=True)
+
+    @classmethod
+    def tearDownClass(cls):
+        return
+        """Remove the temporary region 
+        """
+        cls.runModule("t.remove", flags="rf", inputs="A,B,C,D", quiet=True)
+        cls.runModule("t.unregister", maps="singletmap", quiet=True)
+        cls.del_temp_region()
+
+    def test_1(self):
+        """Simple arithmetik test"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        expr = "R = if(C == 9,  A - 1)"
+        ret = tra.setup_common_granularity(expression=expr,  lexer = tgis.TemporalRasterAlgebraLexer())
+        self.assertEqual(ret, True)
+        
+        tra.parse(expression=expr, basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+
+        self.assertEqual(D.metadata.get_number_of_maps(), 6)
+        self.assertEqual(D.metadata.get_min_min(), 0) # 1 - 1
+        self.assertEqual(D.metadata.get_max_max(), 5) # 6 - 1
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 7, 1))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 month')
+
+    def test_2(self):
+        """Simple arithmetik test"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        expr = "R = if(D == 11,  A - 1, A + 1)"
+        ret = tra.setup_common_granularity(expression=expr,  lexer = tgis.TemporalRasterAlgebraLexer())
+        self.assertEqual(ret, True)
+        
+        tra.parse(expression=expr, basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+
+        self.assertEqual(D.metadata.get_number_of_maps(), 15)
+        self.assertEqual(D.metadata.get_min_min(), 2) # 1 - 1
+        self.assertEqual(D.metadata.get_max_max(), 6) # 5 + 1
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 5, 6))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+
+    def test_simple_arith_hash_1(self):
+        """Simple arithmetic test including the hash operator"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = A + (A # A)', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+
+        self.assertEqual(D.metadata.get_number_of_maps(), 6)
+        self.assertEqual(D.metadata.get_min_min(), 2)
+        self.assertEqual(D.metadata.get_max_max(), 7)
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 7, 1))
+
+    def test_simple_arith_hash_2(self):
+        """Simple arithmetic test including the hash operator"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = (A + A) # A', basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+
+        self.assertEqual(D.metadata.get_number_of_maps(), 6)
+        self.assertEqual(D.metadata.get_min_min(), 1)
+        self.assertEqual(D.metadata.get_max_max(), 1)
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 7, 1))
+
+    def test_simple_arith_td_1(self):
+        """Simple arithmetic test"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        expr = 'R = A + td(A:D)'
+        ret = tra.setup_common_granularity(expression=expr,  lexer = tgis.TemporalRasterAlgebraLexer())
+        self.assertEqual(ret, True)
+        
+        tra.parse(expression=expr, basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+
+        self.assertEqual(D.metadata.get_number_of_maps(), 15)
+        self.assertEqual(D.metadata.get_min_min(), 2) # 1 - 1
+        self.assertEqual(D.metadata.get_max_max(), 6) # 5 + 1
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 5, 6))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+
+    def test_simple_arith_if_1(self):
+        """Simple arithmetic test with if condition"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        expr = 'R = if(start_date(A) >= "2001-02-01", A + A)'
+        ret = tra.setup_common_granularity(expression=expr,  lexer = tgis.TemporalRasterAlgebraLexer())
+        self.assertEqual(ret, True)
+        
+        tra.parse(expression=expr, basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+
+        self.assertEqual(D.metadata.get_number_of_maps(), 5)
+        self.assertEqual(D.metadata.get_min_min(), 4)
+        self.assertEqual(D.metadata.get_max_max(), 12)
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 2, 1))
+        self.assertEqual(end, datetime.datetime(2001, 7, 1))
+
+    def test_simple_arith_if_2(self):
+        """Simple arithmetic test with if condition"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        expr = 'R = if(A#A == 1, A - A)'
+        ret = tra.setup_common_granularity(expression=expr,  lexer = tgis.TemporalRasterAlgebraLexer())
+        self.assertEqual(ret, True)
+        
+        tra.parse(expression=expr, basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+
+        self.assertEqual(D.metadata.get_number_of_maps(), 6)
+        self.assertEqual(D.metadata.get_min_min(), 0)
+        self.assertEqual(D.metadata.get_max_max(), 0)
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 7, 1))
+
+    def test_complex_arith_if_1(self):
+        """Complex arithmetic test with if condition"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        expr = 'R = if(start_date(A) < "2001-03-01" && A#A == 1, A+C, A-C)'
+        ret = tra.setup_common_granularity(expression=expr,  lexer = tgis.TemporalRasterAlgebraLexer())
+        self.assertEqual(ret, True)
+        
+        tra.parse(expression=expr, basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+
+        self.assertEqual(D.metadata.get_number_of_maps(), 6)
+        self.assertEqual(D.metadata.get_min_min(), -6)  # 3 - 9
+        self.assertEqual(D.metadata.get_max_max(), 11) # 2 + 2
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 7, 1))
+
+    def test_temporal_neighbors(self):
+        """Simple temporal neighborhood computation test"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        expr ='R = (A[0,0,-1] : D) + (A[0,0,1] : D)'
+        ret = tra.setup_common_granularity(expression=expr,  lexer = tgis.TemporalRasterAlgebraLexer())
+        self.assertEqual(ret, True)
+        
+        tra.parse(expression=expr, basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+
+        self.assertEqual(D.metadata.get_number_of_maps(), 14)
+        self.assertEqual(D.metadata.get_min_min(), 2)  # 1 + 1
+        self.assertEqual(D.metadata.get_max_max(), 10) # 5 + 5
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 2))
+        self.assertEqual(end, datetime.datetime(2001, 5, 6))
+    
+    def test_map(self):
+        """Test STDS + single map without timestamp"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        expr = "R = A + map(singletmap)"
+        ret = tra.setup_common_granularity(expression=expr,  lexer = tgis.TemporalRasterAlgebraLexer())
+        self.assertEqual(ret, True)
+        
+        tra.parse(expression=expr, basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+
+        self.assertEqual(D.metadata.get_number_of_maps(), 6)
+        self.assertEqual(D.metadata.get_min_min(), 100)  # 1 + 99
+        self.assertEqual(D.metadata.get_max_max(), 105) # 6 + 99
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 7, 1))
+        
+    def test_tmap_map(self):
+        """Test STDS + single map with and without timestamp"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        expr = "R = tmap(singletmap) + A + map(singletmap)"
+        ret = tra.setup_common_granularity(expression=expr,  lexer = tgis.TemporalRasterAlgebraLexer())
+        self.assertEqual(ret, True)
+        
+        tra.parse(expression=expr, basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="strds")
+
+        self.assertEqual(D.metadata.get_number_of_maps(),1)
+        self.assertEqual(D.metadata.get_min_min(), 201) 
+        self.assertEqual(D.metadata.get_max_max(), 201)
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 3, 1))
+        self.assertEqual(end, datetime.datetime(2001, 4, 1))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 month')
+
+if __name__ == '__main__':
+    gunittest.test()

+ 498 - 0
lib/python/temporal/testsuite/unittests_temporal_raster_conditionals.py

@@ -0,0 +1,498 @@
+"""
+(C) 2014 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.
+
+:authors: Thomas Leppelt
+"""
+
+import datetime
+import os
+import grass.script
+import grass.temporal as tgis
+import grass.gunittest as gunittest
+
+class TestTemporalRasterAlgebraConditionals(gunittest.TestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        """Initiate the temporal GIS and set the region
+        """
+        tgis.init(True) # Raise on error instead of exit(1)
+        cls.use_temp_region()
+        cls.runModule("g.region", n=80.0, s=0.0, e=120.0,
+                                       w=0.0, t=1.0, b=0.0, res=10.0)
+
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="a1 = 1")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="a2 = 2")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="a3 = 3")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="a4 = 4")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="b1 = 5")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="b2 = 6")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="c1 = 7")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="d1 = 8")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="d2 = 9")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="d3 = 10")
+        cls.runModule("r.mapcalc", overwrite=True, quiet=True, expression="d4 = 11")
+
+        tgis.open_new_stds(name="A", type="strds", temporaltype="absolute",
+                                         title="A", descr="A", semantic="field", overwrite=True)
+        tgis.open_new_stds(name="B", type="strds", temporaltype="absolute",
+                                         title="B", descr="B", semantic="field", overwrite=True)
+        tgis.open_new_stds(name="C", type="strds", temporaltype="absolute",
+                                         title="C", descr="C", semantic="field", overwrite=True)
+        tgis.open_new_stds(name="D", type="strds", temporaltype="absolute",
+                                         title="D", descr="D", semantic="field", overwrite=True)
+ 
+        tgis.register_maps_in_space_time_dataset(type="rast", name="A", maps="a1,a2,a3,a4",
+                                                 start="2001-01-01", increment="1 day", interval=True)
+        tgis.register_maps_in_space_time_dataset(type="rast", name="B", maps="b1,b2",
+                                                 start="2001-01-01", increment="2 day", interval=True)
+        tgis.register_maps_in_space_time_dataset(type="rast", name="C", maps="c1",
+                                                 start="2001-01-02", increment="2 day", interval=True)
+        tgis.register_maps_in_space_time_dataset(type="rast", name="D", maps="d1,d2,d3,d4",
+                                                 start="2001-01-03", increment="1 day", interval=True)
+        
+    def tearDown(self):
+        self.runModule("t.remove", flags="rf", inputs="R", quiet=True)
+
+    @classmethod
+    def tearDownClass(cls):
+        """Remove the temporary region
+        """
+        cls.runModule("t.remove", flags="rf", inputs="A,B,C,D", quiet=True)
+        cls.del_temp_region()
+
+    def test_temporal_conditional_time_dimension_bug(self):
+        """Testing the conditional time dimension bug, that uses the time 
+            dimension of the conditional statement instead the time dimension 
+            of the then/else statement."""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = if({contains}, B == 5,  A - 1,  A + 1)', basename="r", overwrite=True)
+
+        R = tgis.open_old_stds("R", type="strds")
+        R.select()
+        self.assertEqual(R.metadata.get_number_of_maps(), 4)
+        self.assertEqual(R.metadata.get_min_min(), 0) # 1 - 1
+        self.assertEqual(R.metadata.get_max_max(), 5) # 4 + 1
+        start, end = R.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( R.check_temporal_topology(),  True)
+        self.assertEqual(R.get_granularity(),  u'1 day')
+
+    def test_temporal_conditional_1(self):
+        """Testing the conditional time dimension bug, that uses the time 
+            dimension of the conditional statement instead the time dimension 
+            of the then/else statement."""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = if(td(A) == 1,  D * 2, D)', basename="r", overwrite=True)
+
+        R = tgis.open_old_stds("R", type="strds")
+        R.select()
+        self.assertEqual(R.metadata.get_number_of_maps(), 2)
+        self.assertEqual(R.metadata.get_min_min(), 16)
+        self.assertEqual(R.metadata.get_max_max(), 18)
+        start, end = R.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1,  3))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( R.check_temporal_topology(),  True)
+        self.assertEqual(R.get_granularity(),  u'1 day')
+
+    def test_temporal_conditional_relation_1(self):
+        """Testing the conditional time dimension bug, that uses the time 
+            dimension of the conditional statement instead the time dimension 
+            of the then/else statement."""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = if({during},exist(A),  B - 1,  B + 1)', basename="r", overwrite=True)
+
+        R = tgis.open_old_stds("R", type="strds")
+        R.select()
+        self.assertEqual(R.metadata.get_number_of_maps(), 4)
+        self.assertEqual(R.metadata.get_min_min(), 4)
+        self.assertEqual(R.metadata.get_max_max(), 5)
+        start, end = R.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( R.check_temporal_topology(),  False)
+        self.assertEqual(R.get_granularity(),  u'2 days')
+
+    def test_spatial_conditional_1(self):
+        """Testing the spatial conditionals combined by AND/OR operators. 
+            Evaluation  """
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = if(A > 1 && A < 4 && isntnull(A), A)', basename="r", overwrite=True)
+
+        R = tgis.open_old_stds("R", type="strds")
+        R.select()
+        self.assertEqual(R.metadata.get_number_of_maps(), 4)
+        self.assertEqual(R.metadata.get_min_min(), 0)
+        self.assertEqual(R.metadata.get_max_max(), 3)
+        start, end = R.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( R.check_temporal_topology(),  True)
+        self.assertEqual(R.get_granularity(),  u'1 day')
+
+    def test_spatial_conditional_2(self):
+        """Testing the spatial conditionals combined by AND/OR operators. 
+            Evaluation  """
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = if(A > 1 && A < 4 && isntnull(A), A, null())', basename="r", overwrite=True)
+
+        R = tgis.open_old_stds("R", type="strds")
+        R.select()
+        self.assertEqual(R.metadata.get_number_of_maps(), 2)
+        self.assertEqual(R.metadata.get_min_min(), 2)
+        self.assertEqual(R.metadata.get_max_max(), 3)
+        start, end = R.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 2))
+        self.assertEqual(end, datetime.datetime(2001, 1, 4))
+        self.assertEqual( R.check_temporal_topology(),  True)
+        self.assertEqual(R.get_granularity(),  u'1 day')
+
+    def test_spatial_conditional_3(self):
+        """Testing the spatial conditionals combined by AND/OR operators. 
+            Evaluation  """
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = if(A > 1, A, D)', basename="r", overwrite=True)
+
+        R = tgis.open_old_stds("R", type="strds")
+        R.select()
+        self.assertEqual(R.metadata.get_number_of_maps(), 2)
+        self.assertEqual(R.metadata.get_min_min(), 3)
+        self.assertEqual(R.metadata.get_max_max(), 4)
+        start, end = R.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 3))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( R.check_temporal_topology(),  True)
+        self.assertEqual(R.get_granularity(),  u'1 day')
+
+    def test_spatial_conditional_4(self):
+        """Testing the spatial conditionals combined by AND/OR operators. 
+            Evaluation  """
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = if(A > 0, A)', basename="r", overwrite=True)
+
+        R = tgis.open_old_stds("R", type="strds")
+        R.select()
+        self.assertEqual(R.metadata.get_number_of_maps(), 4)
+        self.assertEqual(R.metadata.get_min_min(), 1)
+        self.assertEqual(R.metadata.get_max_max(), 4)
+        start, end = R.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( R.check_temporal_topology(),  True)
+        self.assertEqual(R.get_granularity(),  u'1 day')
+
+    def test_spatial_conditional_5(self):
+        """Testing the spatial conditionals combined by AND/OR operators. 
+            Evaluation  """
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = if(B > 5 {&&,contains,l} A < 5, B)', basename="r", overwrite=True)
+
+        R = tgis.open_old_stds("R", type="strds")
+        R.select()
+        self.assertEqual(R.metadata.get_number_of_maps(), 2)
+        self.assertEqual(R.metadata.get_min_min(), 0)
+        self.assertEqual(R.metadata.get_max_max(), 6)
+        start, end = R.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( R.check_temporal_topology(),  True)
+        self.assertEqual(R.get_granularity(),  u'2 days')
+    
+    def test_spatial_conditional_relation_1(self):
+        """Testing the spatial conditionals combined by AND/OR operators. 
+            Evaluation  """
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = if({contains},B > 5, D)', basename="r", overwrite=True)
+
+        R = tgis.open_old_stds("R", type="strds")
+        R.select()
+        self.assertEqual(R.metadata.get_number_of_maps(), 2)
+        self.assertEqual(R.metadata.get_min_min(), 8)
+        self.assertEqual(R.metadata.get_max_max(), 9)
+        start, end = R.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 3))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( R.check_temporal_topology(),  True)
+        self.assertEqual(R.get_granularity(),  u'1 day')
+
+    def test_spatial_conditional_relation_2(self):
+        """Testing the spatial conditionals with numeric conclusions"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = if({contains}, B <= 5, A, A * 2)', basename="r", overwrite=True)
+
+        R = tgis.open_old_stds("R", type="strds")
+        R.select()
+        self.assertEqual(R.metadata.get_number_of_maps(), 4)
+        self.assertEqual(R.metadata.get_min_min(), 1)
+        self.assertEqual(R.metadata.get_max_max(), 8)
+        start, end = R.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( R.check_temporal_topology(),  True)
+        self.assertEqual(R.get_granularity(),  u'1 day')
+
+    def test_spatial_conditional_numeric_relation_1(self):
+        """Testing the spatial conditionals with numeric conclusions"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = if({contains}, B > 5, A, 10)', basename="r", overwrite=True)
+
+        R = tgis.open_old_stds("R", type="strds")
+        R.select()
+        self.assertEqual(R.metadata.get_number_of_maps(), 4)
+        self.assertEqual(R.metadata.get_min_min(), 3)
+        self.assertEqual(R.metadata.get_max_max(), 10)
+        start, end = R.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( R.check_temporal_topology(),  True)
+        self.assertEqual(R.get_granularity(),  u'1 day')
+    
+    def test_spatial_conditional_numeric_relation_2(self):
+        """Testing the spatial conditionals combined by AND/OR operators. 
+            Evaluation  """
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = if({contains},B > 5, A + 2 / 4.0)', basename="r", overwrite=True)
+
+        R = tgis.open_old_stds("R", type="strds")
+        R.select()
+        self.assertEqual(R.metadata.get_number_of_maps(), 4)
+        self.assertEqual(R.metadata.get_min_min(), 0)
+        self.assertEqual(R.metadata.get_max_max(), 4.5)
+        start, end = R.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( R.check_temporal_topology(),  True)
+        self.assertEqual(R.get_granularity(),  u'1 day')
+    
+    def test_spatial_conditional_numeric_1(self):
+        """Testing the spatial conditionals with numeric conclusions"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = if(A > 2, 0, A)', basename="r", overwrite=True)
+
+        R = tgis.open_old_stds("R", type="strds")
+        R.select()
+        self.assertEqual(R.metadata.get_number_of_maps(), 4)
+        self.assertEqual(R.metadata.get_min_min(), 0)
+        self.assertEqual(R.metadata.get_max_max(), 2)
+        start, end = R.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( R.check_temporal_topology(),  True)
+        self.assertEqual(R.get_granularity(),  u'1 day')
+
+    def test_spatial_conditional_numeric_2(self):
+        """Testing the spatial conditionals with numeric conclusions"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = if(A > 2, A, 8)', basename="r", overwrite=True)
+
+        R = tgis.open_old_stds("R", type="strds")
+        R.select()
+        self.assertEqual(R.metadata.get_number_of_maps(), 4)
+        self.assertEqual(R.metadata.get_min_min(), 3)
+        self.assertEqual(R.metadata.get_max_max(), 8)
+        start, end = R.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( R.check_temporal_topology(),  True)
+        self.assertEqual(R.get_granularity(),  u'1 day')
+
+    def test_spatial_conditional_numeric_3(self):
+        """Testing the spatial conditionals with numeric conclusions"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = if(A > 2, 1, 0)', basename="r", overwrite=True)
+
+        R = tgis.open_old_stds("R", type="strds")
+        R.select()
+        self.assertEqual(R.metadata.get_number_of_maps(), 4)
+        self.assertEqual(R.metadata.get_min_min(), 0)
+        self.assertEqual(R.metadata.get_max_max(), 1)
+        start, end = R.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( R.check_temporal_topology(),  True)
+        self.assertEqual(R.get_granularity(),  u'1 day')
+
+    def test_spatial_conditional_numeric_4(self):
+        """Testing the spatial conditionals with numeric conclusions"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = if(A > 2, null())', basename="r", overwrite=True)
+
+        R = tgis.open_old_stds("R", type="strds")
+        R.select()
+        self.assertEqual(R.metadata.get_number_of_maps(), 2)
+        self.assertEqual(R.metadata.get_min_min(), 0)
+        self.assertEqual(R.metadata.get_max_max(), 0)
+        start, end = R.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 3))
+        self.assertEqual( R.check_temporal_topology(),  True)
+        self.assertEqual(R.get_granularity(),  u'1 day')
+
+    def test_spatiotemporal_conditional_1(self):
+        """Testing the spatial conditionals with numeric conclusions"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = if(A < 2 && start_date(A) < "2001-01-03", A)', basename="r", overwrite=True)
+
+        R = tgis.open_old_stds("R", type="strds")
+        R.select()
+        self.assertEqual(R.metadata.get_number_of_maps(), 4)
+        self.assertEqual(R.metadata.get_min_min(), 0)
+        self.assertEqual(R.metadata.get_max_max(), 1)
+        start, end = R.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( R.check_temporal_topology(),  True)
+        self.assertEqual(R.get_granularity(),  u'1 day')
+
+    def test_spatiotemporal_conditional_2(self):
+        """Testing the spatial conditionals with numeric conclusions"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = if(A < 3 || start_date(A) < "2001-01-04", A + 1, A - 1)', basename="r", overwrite=True)
+
+        R = tgis.open_old_stds("R", type="strds")
+        R.select()
+        self.assertEqual(R.metadata.get_number_of_maps(), 4)
+        self.assertEqual(R.metadata.get_min_min(),2)
+        self.assertEqual(R.metadata.get_max_max(),4)
+        start, end = R.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( R.check_temporal_topology(),  True)
+        self.assertEqual(R.get_granularity(),  u'1 day')
+
+    def test_spatiotemporal_conditional_relation_1(self):
+        """Testing the spatial conditionals with numeric conclusions"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = if({contains},B > 5 && start_day(B) < 3, D)', basename="r", overwrite=True)
+
+        R = tgis.open_old_stds("R", type="strds")
+        R.select()
+        self.assertEqual(R.metadata.get_number_of_maps(), 2)
+        self.assertEqual(R.metadata.get_min_min(),0)
+        self.assertEqual(R.metadata.get_max_max(),0)
+        start, end = R.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 3))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( R.check_temporal_topology(),  True)
+        self.assertEqual(R.get_granularity(),  u'1 day')
+
+    def test_spatiotemporal_conditional_relation_2(self):
+        """Testing the spatial conditionals with numeric conclusions"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = if({contains}, start_date(B) < "2001-01-03" || B <= 5, A, A * 2)', basename="r", overwrite=True)
+
+        R = tgis.open_old_stds("R", type="strds")
+        R.select()
+        self.assertEqual(R.metadata.get_number_of_maps(), 4)
+        self.assertEqual(R.metadata.get_min_min(), 1)
+        self.assertEqual(R.metadata.get_max_max(), 8)
+        start, end = R.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( R.check_temporal_topology(),  True)
+        self.assertEqual(R.get_granularity(),  u'1 day')
+
+    def test_spatiotemporal_conditional_numeric_relation_1(self):
+        """Testing the spatial conditionals with numeric conclusions"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = if({contains}, start_date(B) >= "2001-01-03" && B > 5, A, 10)', basename="r", overwrite=True)
+
+        R = tgis.open_old_stds("R", type="strds")
+        R.select()
+        self.assertEqual(R.metadata.get_number_of_maps(), 4)
+        self.assertEqual(R.metadata.get_min_min(), 3)
+        self.assertEqual(R.metadata.get_max_max(), 10)
+        start, end = R.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( R.check_temporal_topology(),  True)
+        self.assertEqual(R.get_granularity(),  u'1 day')
+    
+    def test_spatiotemporal_conditional_numeric_relation_2(self):
+        """Testing the spatial conditionals combined by AND/OR operators. 
+            Evaluation  """
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = if({contains},td(B) == 2 && start_date(B) == "2001-01-03" && B > 5 , A + 2 / 4.0)', basename="r", overwrite=True)
+
+        R = tgis.open_old_stds("R", type="strds")
+        R.select()
+        self.assertEqual(R.metadata.get_number_of_maps(), 4)
+        self.assertEqual(R.metadata.get_min_min(), 0)
+        self.assertEqual(R.metadata.get_max_max(), 4.5)
+        start, end = R.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( R.check_temporal_topology(),  True)
+        self.assertEqual(R.get_granularity(),  u'1 day')
+ 
+    def test_spatiotemporal_conditional_numeric_1(self):
+        """Testing the spatial conditionals with numeric conclusions"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = if(start_date(A) < "2001-01-04" && A > 2, 0, A)', basename="r", overwrite=True)
+
+        R = tgis.open_old_stds("R", type="strds")
+        R.select()
+        self.assertEqual(R.metadata.get_number_of_maps(), 4)
+        self.assertEqual(R.metadata.get_min_min(), 0)
+        self.assertEqual(R.metadata.get_max_max(), 4)
+        start, end = R.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( R.check_temporal_topology(),  True)
+        self.assertEqual(R.get_granularity(),  u'1 day')
+
+    def test_spatiotemporal_conditional_numeric_2(self):
+        """Testing the spatial conditionals with numeric conclusions"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = if(A > 2 || start_date(A) > "2001-01-01" && start_date(A) < "2001-01-04", A, 8)', basename="r", overwrite=True)
+
+        R = tgis.open_old_stds("R", type="strds")
+        R.select()
+        self.assertEqual(R.metadata.get_number_of_maps(), 4)
+        self.assertEqual(R.metadata.get_min_min(), 2)
+        self.assertEqual(R.metadata.get_max_max(), 8)
+        start, end = R.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( R.check_temporal_topology(),  True)
+        self.assertEqual(R.get_granularity(),  u'1 day')
+
+    def test_spatiotemporal_conditional_numeric_3(self):
+        """Testing the spatial conditionals with numeric conclusions"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = if(start_date(A) < "2001-01-04" && A > 2, 1, 0)', basename="r", overwrite=True)
+
+        R = tgis.open_old_stds("R", type="strds")
+        R.select()
+        self.assertEqual(R.metadata.get_number_of_maps(), 4)
+        self.assertEqual(R.metadata.get_min_min(), 0)
+        self.assertEqual(R.metadata.get_max_max(), 1)
+        start, end = R.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( R.check_temporal_topology(),  True)
+        self.assertEqual(R.get_granularity(),  u'1 day')
+
+    def test_spatiotemporal_conditional_numeric_4(self):
+        """Testing the spatial conditionals with numeric conclusions"""
+        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
+        tra.parse(expression='R = if(A > 2 || start_date(A) > "2001-01-01", null())', basename="r", overwrite=True)
+
+        R = tgis.open_old_stds("R", type="strds")
+        R.select()
+        self.assertEqual(R.metadata.get_number_of_maps(), 1)
+        self.assertEqual(R.metadata.get_min_min(), 0)
+        self.assertEqual(R.metadata.get_max_max(), 0)
+        start, end = R.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 2))
+        self.assertEqual( R.check_temporal_topology(),  True)
+        self.assertEqual(R.get_granularity(),  u'1 day')
+
+if __name__ == '__main__':
+    gunittest.test()

+ 209 - 0
lib/python/temporal/testsuite/unittests_temporal_vector_algebra.py

@@ -0,0 +1,209 @@
+"""
+(C) 2014 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.
+
+:authors: Soeren Gebbert and Thomas Leppelt
+"""
+
+import datetime
+import os
+import grass.script
+import grass.temporal as tgis
+import grass.gunittest as gunittest
+
+class TestTemporalVectorAlgebra(gunittest.TestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        """Initiate the temporal GIS and set the region
+        """
+        tgis.init(True) # Raise on error instead of exit(1)
+        cls.use_temp_region()
+        cls.runModule("g.region", n=80.0, s=0.0, e=120.0,
+                                       w=0.0, t=1.0, b=0.0, res=10.0)
+
+        cls.runModule("v.random", overwrite=True, quiet=True, n=20, seed=1,  output='a1')
+        cls.runModule("v.random", overwrite=True, quiet=True, n=20, seed=1,  output='a2')
+        cls.runModule("v.random", overwrite=True, quiet=True, n=20, seed=1,  output='a3')
+        cls.runModule("v.random", overwrite=True, quiet=True, n=20, seed=1,  output='a4')
+        cls.runModule("v.random", overwrite=True, quiet=True, n=20, seed=2,  output='b1')
+        cls.runModule("v.random", overwrite=True, quiet=True, n=20, seed=2,  output='b2')
+        cls.runModule("v.random", overwrite=True, quiet=True, n=20, seed=3,  output='c1')
+        cls.runModule("v.random", overwrite=True, quiet=True, n=20, seed=4,  output='d1')
+        cls.runModule("v.random", overwrite=True, quiet=True, n=20, seed=4,  output='d2')
+        cls.runModule("v.random", overwrite=True, quiet=True, n=20, seed=4,  output='d3')
+        cls.runModule("v.random", overwrite=True, quiet=True, n=20, seed=5,  output='singletmap')
+        cls.runModule("v.random", overwrite=True, quiet=True, n=20, seed=6,  output='singlemap')        
+
+        tgis.open_new_stds(name="A", type="stvds", temporaltype="absolute",
+                                         title="A", descr="A", semantic="field", overwrite=True)
+        tgis.open_new_stds(name="B", type="stvds", temporaltype="absolute",
+                                         title="B", descr="B", semantic="field", overwrite=True)
+        tgis.open_new_stds(name="C", type="stvds", temporaltype="absolute",
+                                         title="B", descr="C", semantic="field", overwrite=True)
+        tgis.open_new_stds(name="D", type="stvds", temporaltype="absolute",
+                                         title="D", descr="D", semantic="field", overwrite=True)
+
+        tgis.register_maps_in_space_time_dataset(type="vect", name="A", maps="a1,a2,a3,a4",
+                                                 start="2001-01-01", increment="1 day", interval=True)
+        tgis.register_maps_in_space_time_dataset(type="vect", name="B", maps="b1,b2",
+                                                 start="2001-01-01", increment="2 day", interval=True)
+        tgis.register_maps_in_space_time_dataset(type="vect", name="C", maps="c1",
+                                                 start="2001-01-02", increment="2 day", interval=True)
+        tgis.register_maps_in_space_time_dataset(type="vect", name="D", maps="d1,d2,d3",
+                                                 start="2001-01-03", increment="1 day", interval=True)
+        tgis.register_maps_in_space_time_dataset(type="vect", name=None,  maps="singletmap", 
+                                                start="2001-01-03", end="2001-01-04", interval=True)
+    
+    def tearDown(self):
+        self.runModule("t.remove", type="stvds", inputs="R", quiet=True)
+
+    @classmethod
+    def tearDownClass(cls):
+        """Remove the temporary region 
+        """
+        cls.runModule("t.remove", flags="rf", inputs="A,B,C,D", type='stvds',  quiet=True)
+        cls.del_temp_region()
+
+    def test_temporal_select(self):
+        """Testing the temporal select operator. """
+        tva = tgis.TemporalVectorAlgebraParser(run = True, debug = True)
+        tva.parse(expression="R = A : A", basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="stvds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 4)
+        self.assertEqual(D.metadata.get_number_of_points(), 80) 
+        self.assertEqual(D.metadata.get_number_of_areas(), 0) 
+        self.assertEqual(D.metadata.get_number_of_centroids(), 0) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+
+    def test_temporal_extent1(self):
+        """Testing the temporal extent operators. """
+        ta = tgis.TemporalVectorAlgebraParser(run = True, debug = True)
+        ta.parse(expression="R = A {:,during,r} C",  basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="stvds")
+        D.select()
+        D.print_info()
+        maplist = D.get_registered_maps_as_objects()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 2))
+        self.assertEqual(end, datetime.datetime(2001, 1, 4))
+        self.assertEqual( D.check_temporal_topology(),  False)
+        self.assertEqual(D.get_granularity(),  u'2 days')
+
+    def test_temporal_select_operators(self):
+        """Testing the temporal select operator. Including temporal relations. """
+        tva = tgis.TemporalVectorAlgebraParser(run = True, debug = True)
+        tva.parse(expression="R = A {:,during} C", basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="stvds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_number_of_points(), 40) 
+        self.assertEqual(D.metadata.get_number_of_areas(), 0) 
+        self.assertEqual(D.metadata.get_number_of_centroids(), 0) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 2))
+        self.assertEqual(end, datetime.datetime(2001, 1, 4))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+
+    def test_temporal_buff_operators_1(self):
+        """Testing the bufferoperator."""
+        tva = tgis.TemporalVectorAlgebraParser(run = True, debug = True)
+        tva.parse(expression="R = buff_p(A,0.5)", basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="stvds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 4)
+        self.assertEqual(D.metadata.get_number_of_points(), 0) 
+        self.assertEqual(D.metadata.get_number_of_areas(), 80) 
+        self.assertEqual(D.metadata.get_number_of_centroids(), 80) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+
+    def test_temporal_buff_operators_2(self):
+        """Testing the bufferoperator."""
+        tva = tgis.TemporalVectorAlgebraParser(run = True, debug = True)
+        tva.parse(expression="R = buff_a(buff_p(A,1),10)", basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="stvds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 4)
+        self.assertEqual(D.metadata.get_number_of_points(), 0) 
+        self.assertEqual(D.metadata.get_number_of_areas(), 20) 
+        self.assertEqual(D.metadata.get_number_of_centroids(), 20) 
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+
+    def test_temporal_overlay_operators_1(self):
+        """Testing the spatial overlay operator."""
+        tva = tgis.TemporalVectorAlgebraParser(run = True, debug = True)
+        tva.parse(expression="R = buff_p(A,2) & buff_p(D,2)", basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="stvds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_number_of_points(), 0)
+        self.assertEqual(D.metadata.get_number_of_areas(), 6)
+        self.assertEqual(D.metadata.get_number_of_centroids(), 6)
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 3))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+
+    def test_temporal_overlay_operators_2(self):
+        """Testing the spatial overlay operator."""
+        tva = tgis.TemporalVectorAlgebraParser(run = True, debug = True)
+        tva.parse(expression="R = buff_p(A,1.5) {&,during,r} buff_p(B,1.5)", basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="stvds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 4)
+        self.assertEqual(D.metadata.get_number_of_points(), 0)
+        self.assertEqual(D.metadata.get_number_of_areas(), 8)
+        self.assertEqual(D.metadata.get_number_of_centroids(), 8)
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 1))
+        self.assertEqual(end, datetime.datetime(2001, 1, 5))
+        self.assertEqual( D.check_temporal_topology(),  False)
+        self.assertEqual(D.get_granularity(),  u'2 days')
+
+    def test_temporal_overlay_operators_3(self):
+        """Testing the spatial overlay operator."""
+        tva = tgis.TemporalVectorAlgebraParser(run = True, debug = True)
+        tva.parse(expression="R = buff_p(A,2.5) {&,during,l} buff_p(C,2.5)", basename="r", overwrite=True)
+
+        D = tgis.open_old_stds("R", type="stvds")
+        D.select()
+        self.assertEqual(D.metadata.get_number_of_maps(), 2)
+        self.assertEqual(D.metadata.get_number_of_points(), 0)
+        self.assertEqual(D.metadata.get_number_of_areas(), 8)
+        self.assertEqual(D.metadata.get_number_of_centroids(), 8)
+        start, end = D.get_absolute_time()
+        self.assertEqual(start, datetime.datetime(2001, 1, 2))
+        self.assertEqual(end, datetime.datetime(2001, 1, 4))
+        self.assertEqual( D.check_temporal_topology(),  True)
+        self.assertEqual(D.get_granularity(),  u'1 day')
+
+if __name__ == '__main__':
+    gunittest.test()
+
+
+

+ 46 - 49
lib/python/temporal/unit_tests.py

@@ -1,27 +1,15 @@
-"""!@package grass.temporal
-
-@brief GRASS Python scripting module (temporal GIS functions)
-
-Temporal GIS unit tests
-
-Usage:
-
-@code
-import grass.temporal as tgis
-
-tgis.test_increment_datetime_by_string()
-...
-@endcode
+"""
+Depricazed unittests
 
 (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
+:authors: Soeren Gebbert
 """
 import copy
-from datetime import datetime, date, time, timedelta
+from datetime import datetime
 import grass.script.core as core
 from temporal_granularity import *
 from datetime_math import *
@@ -37,6 +25,7 @@ core.set_raise_on_error(True)
 
 ###############################################################################
 
+
 def test_increment_datetime_by_string():
 
     # First test
@@ -105,6 +94,7 @@ def test_increment_datetime_by_string():
 
 ###############################################################################
 
+
 def test_adjust_datetime_to_granularity():
 
     # First test
@@ -221,6 +211,7 @@ def test_adjust_datetime_to_granularity():
 
 ###############################################################################
 
+
 def test_compute_datetime_delta():
 
     print "Test 1"
@@ -564,6 +555,7 @@ def test_compute_datetime_delta():
     if delta != 0:
         core.fatal("Compute datetime delta is wrong %s" % (delta))
 
+
 def test_compute_absolute_time_granularity():
 
     # First we test intervals
@@ -902,6 +894,7 @@ def test_compute_absolute_time_granularity():
 
 ###############################################################################
 
+
 def test_spatial_extent_intersection():
     # Generate the extents
 
@@ -965,6 +958,7 @@ def test_spatial_extent_intersection():
 
 ###############################################################################
 
+
 def test_spatial_relations():
     # Generate the extents
 
@@ -1320,7 +1314,6 @@ def test_spatial_relations():
     print relation
     if relation != "meet":
         core.fatal("Wrong spatial relation: %s" % (relation))
- ###
 
     A = SpatialExtent(north=80, south=40, east=60, west=20, bottom=-50, top=0)
     A.print_info()
@@ -1374,6 +1367,7 @@ def test_spatial_relations():
 
 ###############################################################################
 
+
 def test_temporal_topology_builder():
     map_listA = []
 
@@ -1402,7 +1396,7 @@ def test_temporal_topology_builder():
         _map.print_topology_info()
         if _map.get_id() != map_listA[count].get_id():
             core.fatal("Error building temporal topology <%s> != <%s>" %
-                (_map.get_id(), map_listA[count].get_id()))
+                       (_map.get_id(), map_listA[count].get_id()))
         count += 1
 
     map_listB = []
@@ -1438,12 +1432,11 @@ def test_temporal_topology_builder():
 
     count = 0
     for _map in tb:
-        print "[%s]" % (_map.get_map_id
-        ())
+        print "[%s]" % (_map.get_map_id())
         _map.print_topology_shell_info()
         if _map.get_id() != map_listB[count].get_id():
             core.fatal("Error building temporal topology <%s> != <%s>" %
-                (_map.get_id(), map_listB[count].get_id()))
+                       (_map.get_id(), map_listB[count].get_id()))
         count += 1
 
     tb = SpatioTemporalTopologyBuilder()
@@ -1455,7 +1448,7 @@ def test_temporal_topology_builder():
         _map.print_topology_shell_info()
         if _map.get_id() != map_listA[count].get_id():
             core.fatal("Error building temporal topology <%s> != <%s>" %
-                (_map.get_id(), map_listA[count].get_id()))
+                       (_map.get_id(), map_listA[count].get_id()))
         count += 1
 
     count = 0
@@ -1480,6 +1473,7 @@ def test_temporal_topology_builder():
 
 ###############################################################################
 
+
 def test_map_list_sorting():
 
     map_list = []
@@ -1523,13 +1517,14 @@ def test_map_list_sorting():
 
 ###############################################################################
 
+
 def test_1d_rtree():
     """Testing the rtree ctypes wrapper"""
 
     tree = rtree.RTreeCreateTree(-1, 0, 1)
 
     for i in xrange(10):
-        
+
         rect = rtree.RTreeAllocRect(tree)
         rtree.RTreeSetRect1D(rect, tree, float(i - 2), float(i + 2))
         rtree.RTreeInsertRect(rect, i + 1, tree)
@@ -1540,7 +1535,7 @@ def test_1d_rtree():
     list_ = gis.ilist()
 
     num = vector.RTreeSearch2(tree, rect, byref(list_))
-    
+
     rtree.RTreeFreeRect(rect)
 
     # print rectangle ids
@@ -1549,24 +1544,24 @@ def test_1d_rtree():
         print "id", list_.value[i]
 
     rtree.RTreeDestroyTree(tree)
-    
+
 ###############################################################################
 
+
 def test_2d_rtree():
     """Testing the rtree ctypes wrapper"""
 
     tree = rtree.RTreeCreateTree(-1, 0, 2)
 
     for i in xrange(10):
-        
-        
+
         rect = rtree.RTreeAllocRect(tree)
 
-        rtree.RTreeSetRect2D(rect, tree, 
-                              float(i - 2), float(i + 2), 
-                              float(i - 2), float(i + 2))
+        rtree.RTreeSetRect2D(rect, tree,
+                             float(i - 2), float(i + 2),
+                             float(i - 2), float(i + 2))
         rtree.RTreeInsertRect(rect, i + 1, tree)
-    
+
     rect = rtree.RTreeAllocRect(tree)
     rtree.RTreeSetRect2D(rect, tree, 2.0, 7.0, 2.0, 7.0)
 
@@ -1581,21 +1576,22 @@ def test_2d_rtree():
         print "id", list_.value[i]
 
     rtree.RTreeDestroyTree(tree)
-    
+
 ###############################################################################
 
+
 def test_3d_rtree():
     """Testing the rtree ctypes wrapper"""
 
     tree = rtree.RTreeCreateTree(-1, 0, 3)
 
     for i in xrange(10):
-        
+
         rect = rtree.RTreeAllocRect(tree)
-        rtree.RTreeSetRect3D(rect, tree, 
-                              float(i - 2), float(i + 2), 
-                              float(i - 2), float(i + 2), 
-                              float(i - 2), float(i + 2))
+        rtree.RTreeSetRect3D(rect, tree,
+                             float(i - 2), float(i + 2),
+                             float(i - 2), float(i + 2),
+                             float(i - 2), float(i + 2))
         rtree.RTreeInsertRect(rect, i + 1, tree)
         print i + 1
         rtree.RTreePrintRect(rect, 1, tree)
@@ -1604,7 +1600,7 @@ def test_3d_rtree():
     rtree.RTreeSetRect3D(rect, tree, 2.0, 7.0, 2.0, 7.0, 2.0, 7.0)
     print "Select"
     rtree.RTreePrintRect(rect, 1, tree)
-        
+
     list_ = gis.ilist()
 
     num = vector.RTreeSearch2(tree, rect, byref(list_))
@@ -1614,31 +1610,32 @@ def test_3d_rtree():
     print "Number of overlapping rectangles", num
     for i in xrange(list_.n_values):
         print "id", list_.value[i]
-        
+
     rtree.RTreeDestroyTree(tree)
 
 ###############################################################################
 
+
 def test_4d_rtree():
     """Testing the rtree ctypes wrapper"""
 
     tree = rtree.RTreeCreateTree(-1, 0, 4)
 
     for i in xrange(10):
-        
+
         # Allocate the boundary
         rect = rtree.RTreeAllocRect(tree)
-        rtree.RTreeSetRect4D(rect, tree, 
-                              float(i - 2), float(i + 2), 
-                              float(i - 2), float(i + 2), 
-                              float(i - 2), float(i + 2), 
-                              float(i - 2), float(i + 2))
+        rtree.RTreeSetRect4D(rect, tree,
+                             float(i - 2), float(i + 2),
+                             float(i - 2), float(i + 2),
+                             float(i - 2), float(i + 2),
+                             float(i - 2), float(i + 2))
         rtree.RTreeInsertRect(rect, i + 1, tree)
 
     rect = rtree.RTreeAllocRect(tree)
-    rtree.RTreeSetRect4D(rect, tree, 2.0, 7.0, 2.0, 
-                          7.0, 2.0, 7.0, 2.0, 7.0)
-    
+    rtree.RTreeSetRect4D(rect, tree, 2.0, 7.0, 2.0,
+                         7.0, 2.0, 7.0, 2.0, 7.0)
+
     list_ = gis.ilist()
 
     num = vector.RTreeSearch2(tree, rect, byref(list_))
@@ -1649,7 +1646,7 @@ def test_4d_rtree():
     print "Number of overlapping rectangles", num
     for i in xrange(list_.n_values):
         print "id", list_.value[i]
-        
+
     rtree.RTreeDestroyTree(tree)
 
 ###############################################################################

+ 0 - 374
lib/python/temporal/unittests_temporal_raster_algebra.py

@@ -1,374 +0,0 @@
-"""!Unit test to register raster maps with absolute and relative
-   time using tgis.register_maps_in_space_time_dataset()
-
-(C) 2013 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
-"""
-
-import grass.script
-import grass.temporal as tgis
-import unittest
-import datetime
-import os
-
-class TestRegisterFunctions(unittest.TestCase):
-
-    @classmethod
-    def setUpClass(cls):
-        """!Initiate the temporal GIS and set the region
-        """
-        tgis.init(True) # Raise on error instead of exit(1)
-        grass.script.use_temp_region()
-        ret = grass.script.run_command("g.region", n=80.0, s=0.0, e=120.0,
-                                       w=0.0, t=1.0, b=0.0, res=10.0)
-
-        ret += grass.script.run_command("r.mapcalc", overwrite=True, quiet=True, expression="a1 = 1")
-        ret += grass.script.run_command("r.mapcalc", overwrite=True, quiet=True, expression="a2 = 2")
-        ret += grass.script.run_command("r.mapcalc", overwrite=True, quiet=True, expression="a3 = 3")
-        ret += grass.script.run_command("r.mapcalc", overwrite=True, quiet=True, expression="a4 = 4")
-        ret += grass.script.run_command("r.mapcalc", overwrite=True, quiet=True, expression="b1 = 5")
-        ret += grass.script.run_command("r.mapcalc", overwrite=True, quiet=True, expression="b2 = 6")
-        ret += grass.script.run_command("r.mapcalc", overwrite=True, quiet=True, expression="c1 = 7")
-
-
-        tgis.open_new_space_time_dataset(name="A", type="strds", temporaltype="absolute",
-                                         title="A", descr="A", semantic="field", overwrite=True)
-        tgis.open_new_space_time_dataset(name="B", type="strds", temporaltype="absolute",
-                                         title="B", descr="B", semantic="field", overwrite=True)
-        tgis.open_new_space_time_dataset(name="C", type="strds", temporaltype="absolute",
-                                         title="B", descr="C", semantic="field", overwrite=True)
-
-        tgis.register_maps_in_space_time_dataset(type="rast", name="A", maps="a1,a2,a3,a4",
-                                                 start="2001-01-01", increment="1 day", interval=True)
-        tgis.register_maps_in_space_time_dataset(type="rast", name="B", maps="b1,b2",
-                                                 start="2001-01-01", increment="2 day", interval=True)
-
-        tgis.register_maps_in_space_time_dataset(type="rast", name="C", maps="c1",
-                                                 start="2001-01-02", increment="2 day", interval=True)
-
-
-    def test_temporal_conditional_time_dimension_bug(self):
-        """Testing the conditional time dimension bug, that uses the time 
-            dimension of the conditional statement instead the time dimension 
-            of the then/else statement."""
-        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
-        tra.parse(expression="D = if({contains}, B == 5,  A - 1,  A + 1)", basename="d", overwrite=True)
-
-        D = tgis.open_old_space_time_dataset("D", type="strds")
-        D.select()
-        self.assertEqual(D.metadata.get_number_of_maps(), 4)
-        self.assertEqual(D.metadata.get_min_min(), 0) # 1 - 1
-        self.assertEqual(D.metadata.get_max_max(), 5) # 4 + 1
-        start, end = D.get_absolute_time()
-        self.assertEqual(start, datetime.datetime(2001, 1, 1))
-        self.assertEqual(end, datetime.datetime(2001, 1, 5))
-        self.assertEqual( D.check_temporal_topology(),  True)
-        self.assertEqual(D.get_granularity(),  u'1 day')
-
-    def test_simple_arith_hash_1(self):
-        """Simple arithmetic test including the hash operator"""
-        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
-        tra.parse(expression='D = A + A{equal,=#}A', basename="d", overwrite=True)
-
-        D = tgis.open_old_space_time_dataset("D", type="strds")
-        D.select()
-        self.assertEqual(D.metadata.get_number_of_maps(), 4)
-        self.assertEqual(D.metadata.get_min_min(), 2)
-        self.assertEqual(D.metadata.get_max_max(), 5)
-        start, end = D.get_absolute_time()
-        self.assertEqual(start, datetime.datetime(2001, 1, 1))
-        self.assertEqual(end, datetime.datetime(2001, 1, 5))
-
-
-    def test_simple_arith_td_1(self):
-        """Simple arithmetic test"""
-        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
-        tra.parse(expression='D = A + td(A)', basename="d", overwrite=True)
-
-        D = tgis.open_old_space_time_dataset("D", type="strds")
-        D.select()
-        self.assertEqual(D.metadata.get_number_of_maps(), 4)
-        self.assertEqual(D.metadata.get_min_min(), 2)
-        self.assertEqual(D.metadata.get_max_max(), 5)
-        start, end = D.get_absolute_time()
-        self.assertEqual(start, datetime.datetime(2001, 1, 1))
-        self.assertEqual(end, datetime.datetime(2001, 1, 5))
-
-    def test_simple_arith_td_2(self):
-        """Simple arithmetic test"""
-        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
-        tra.parse(expression='D = A / td(A)', basename="d", overwrite=True)
-
-        D = tgis.open_old_space_time_dataset("D", type="strds")
-        D.select()
-        self.assertEqual(D.metadata.get_number_of_maps(), 4)
-        self.assertEqual(D.metadata.get_min_min(), 1)
-        self.assertEqual(D.metadata.get_max_max(), 4)
-        start, end = D.get_absolute_time()
-        self.assertEqual(start, datetime.datetime(2001, 1, 1))
-        self.assertEqual(end, datetime.datetime(2001, 1, 5))
-
-    def test_simple_arith_td_3(self):
-        """Simple arithmetic test"""
-        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
-        tra.parse(expression='D = A {equal,+} td(A)', basename="d", overwrite=True)
-
-        D = tgis.open_old_space_time_dataset("D", type="strds")
-        D.select()
-        self.assertEqual(D.metadata.get_number_of_maps(), 4)
-        self.assertEqual(D.metadata.get_min_min(), 2)
-        self.assertEqual(D.metadata.get_max_max(), 5)
-        start, end = D.get_absolute_time()
-        self.assertEqual(start, datetime.datetime(2001, 1, 1))
-        self.assertEqual(end, datetime.datetime(2001, 1, 5))
-
-
-    def test_simple_arith_td_4(self):
-        """Simple arithmetic test"""
-        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
-        tra.parse(expression='D = A {equal,/} td(A)', basename="d", overwrite=True)
-
-        D = tgis.open_old_space_time_dataset("D", type="strds")
-        D.select()
-        self.assertEqual(D.metadata.get_number_of_maps(), 4)
-        self.assertEqual(D.metadata.get_min_min(), 1)
-        self.assertEqual(D.metadata.get_max_max(), 4)
-        start, end = D.get_absolute_time()
-        self.assertEqual(start, datetime.datetime(2001, 1, 1))
-        self.assertEqual(end, datetime.datetime(2001, 1, 5))
-
-
-    def test_simple_arith_if_1(self):
-        """Simple arithmetic test with if condition"""
-        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
-        tra.parse(expression='D = if({equal}, start_date() >= "2001-01-02", A + A)', basename="d", overwrite=True)
-
-        D = tgis.open_old_space_time_dataset("D", type="strds")
-        D.select()
-        self.assertEqual(D.metadata.get_number_of_maps(), 3)
-        self.assertEqual(D.metadata.get_min_min(), 4)
-        self.assertEqual(D.metadata.get_max_max(), 8)
-        start, end = D.get_absolute_time()
-        self.assertEqual(start, datetime.datetime(2001, 1, 2))
-        self.assertEqual(end, datetime.datetime(2001, 1, 5))
-
-    def test_simple_arith_if_2(self):
-        """Simple arithmetic test with if condition"""
-        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
-        tra.parse(expression='D = if({equal}, A#A == 1, A - A)', basename="d", overwrite=True)
-
-        D = tgis.open_old_space_time_dataset("D", type="strds")
-        D.select()
-        self.assertEqual(D.metadata.get_number_of_maps(), 4)
-        self.assertEqual(D.metadata.get_min_min(), 0)
-        self.assertEqual(D.metadata.get_max_max(), 0)
-        start, end = D.get_absolute_time()
-        self.assertEqual(start, datetime.datetime(2001, 1, 1))
-        self.assertEqual(end, datetime.datetime(2001, 1, 5))
-
-    def test_complex_arith_if_1(self):
-        """Complex arithmetic test with if condition"""
-        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
-        tra.parse(expression='D = if(start_date() < "2001-01-03" && A#A == 1, A{starts,=+}C, A{finishes,=+}C)', \
-                  basename="d", overwrite=True)
-
-        D = tgis.open_old_space_time_dataset("D", type="strds")
-        D.select()
-        self.assertEqual(D.metadata.get_number_of_maps(), 2)
-        self.assertEqual(D.metadata.get_min_min(), 9)  # 2 + 7 a2 + c1
-        self.assertEqual(D.metadata.get_max_max(), 10) # 3 + 7 a3 + c1
-        start, end = D.get_absolute_time()
-        self.assertEqual(start, datetime.datetime(2001, 1, 2))
-        self.assertEqual(end, datetime.datetime(2001, 1, 4))
-
-    def test_simple_arith_1(self):
-        """Simple arithmetic test"""
-        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
-        tra.parse(expression="D = A {equal,*} A {equal,+} A", basename="d", overwrite=True)
-
-        D = tgis.open_old_space_time_dataset("D", type="strds")
-        D.select()
-        self.assertEqual(D.metadata.get_number_of_maps(), 4)
-        self.assertEqual(D.metadata.get_min_min(), 2)  # 1*1 + 1
-        self.assertEqual(D.metadata.get_max_max(), 20) # 4*4 + 4
-        start, end = D.get_absolute_time()
-        self.assertEqual(start, datetime.datetime(2001, 1, 1))
-        self.assertEqual(end, datetime.datetime(2001, 1, 5))
-
-    def test_simple_arith_2(self):
-        """Simple arithmetic test that creates an empty strds"""
-        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
-        tra.parse(expression="D = A {during,*} A {during,+} A", basename="d", overwrite=True)
-        D = tgis.open_old_space_time_dataset("D", type="strds")
-        D.select()
-        self.assertEqual(D.metadata.get_number_of_maps(), 0)
-
-    def test_simple_arith_3(self):
-        """Simple arithmetic test"""
-        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
-        tra.parse(expression="D = A / A + A*A/A", basename="d", overwrite=True)
-
-        D = tgis.open_old_space_time_dataset("D", type="strds")
-        D.select()
-        self.assertEqual(D.metadata.get_number_of_maps(), 4)
-        self.assertEqual(D.metadata.get_min_min(), 2) # 1/1 + 1*1/1
-        self.assertEqual(D.metadata.get_max_max(), 5) # 4/4 + 4*4/4
-        start, end = D.get_absolute_time()
-        self.assertEqual(start, datetime.datetime(2001, 1, 1))
-        self.assertEqual(end, datetime.datetime(2001, 1, 5))
-        
-    def test_temporal_intersection_1(self):
-        """Simple temporal intersection test"""
-        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
-        tra.parse(expression="D = A {equal,&+} B", basename="d", overwrite=True)
-        D = tgis.open_old_space_time_dataset("D", type="strds")
-        D.select()
-        self.assertEqual(D.metadata.get_number_of_maps(), 0)
-
-    def test_temporal_intersection_2(self):
-        """Simple temporal intersection test"""
-        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
-        tra.parse(expression="D = A {during,&+} B", basename="d", overwrite=True)
-
-        D = tgis.open_old_space_time_dataset("D", type="strds")
-        D.select()
-        self.assertEqual(D.metadata.get_number_of_maps(), 4)
-        self.assertEqual(D.metadata.get_min_min(), 6) # 1 + 5
-        self.assertEqual(D.metadata.get_max_max(), 10) # 4 + 6
-        start, end = D.get_absolute_time()
-        self.assertEqual(start, datetime.datetime(2001, 1, 1))
-        self.assertEqual(end, datetime.datetime(2001, 1, 5))
-
-    def test_temporal_intersection_3(self):
-        """Simple temporal intersection test"""
-        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
-        tra.parse(expression="D = A {starts,&+} B", basename="d", overwrite=True)
-
-        D = tgis.open_old_space_time_dataset("D", type="strds")
-        D.select()
-        self.assertEqual(D.metadata.get_number_of_maps(), 2)
-        self.assertEqual(D.metadata.get_min_min(), 6) # 1 + 5
-        self.assertEqual(D.metadata.get_max_max(), 9) # 3 + 6
-        start, end = D.get_absolute_time()
-        self.assertEqual(start, datetime.datetime(2001, 1, 1))
-        self.assertEqual(end, datetime.datetime(2001, 1, 4))
-
-    def test_temporal_intersection_4(self):
-        """Simple temporal intersection test"""
-        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
-        tra.parse(expression="D = A {finishes,&+} B", basename="d", overwrite=True)
-
-        D = tgis.open_old_space_time_dataset("D", type="strds")
-        D.select()
-        self.assertEqual(D.metadata.get_number_of_maps(), 2)
-        self.assertEqual(D.metadata.get_min_min(), 7)  # 2 + 5
-        self.assertEqual(D.metadata.get_max_max(), 10) # 4 + 6
-        start, end = D.get_absolute_time()
-        self.assertEqual(start, datetime.datetime(2001, 1, 2))
-        self.assertEqual(end, datetime.datetime(2001, 1, 5))
-
-    def test_temporal_intersection_5(self):
-        """Simple temporal intersection test"""
-        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
-        tra.parse(expression="D = A {starts|finishes,&+} B", basename="d", overwrite=True)
-
-        D = tgis.open_old_space_time_dataset("D", type="strds")
-        D.select()
-        self.assertEqual(D.metadata.get_number_of_maps(), 4)
-        self.assertEqual(D.metadata.get_min_min(), 6)  # 1 + 5
-        self.assertEqual(D.metadata.get_max_max(), 10) # 4 + 6
-        start, end = D.get_absolute_time()
-        self.assertEqual(start, datetime.datetime(2001, 1, 1))
-        self.assertEqual(end, datetime.datetime(2001, 1, 5))
-
-    def test_temporal_intersection_6(self):
-        """Simple temporal intersection test"""
-        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
-        tra.parse(expression="D = B {overlaps,|+} C", basename="d", overwrite=True)
-
-        D = tgis.open_old_space_time_dataset("D", type="strds")
-        D.select()
-        self.assertEqual(D.metadata.get_number_of_maps(), 1)
-        self.assertEqual(D.metadata.get_min_min(), 12) # 5 + 7
-        self.assertEqual(D.metadata.get_max_max(), 12) # 5 + 7
-        start, end = D.get_absolute_time()
-        self.assertEqual(start, datetime.datetime(2001, 1, 1))
-        self.assertEqual(end, datetime.datetime(2001, 1, 4))
-
-    def test_temporal_intersection_7(self):
-        """Simple temporal intersection test"""
-        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
-        tra.parse(expression="D = B {overlapped,|+} C", basename="d", overwrite=True)
-
-        D = tgis.open_old_space_time_dataset("D", type="strds")
-        D.select()
-        self.assertEqual(D.metadata.get_number_of_maps(), 1)
-        self.assertEqual(D.metadata.get_min_min(), 13) # 6 + 7
-        self.assertEqual(D.metadata.get_max_max(), 13) # 6 + 7
-        start, end = D.get_absolute_time()
-        self.assertEqual(start, datetime.datetime(2001, 1, 2))
-        self.assertEqual(end, datetime.datetime(2001, 1, 5))
-
-    def test_temporal_intersection_8(self):
-        """Simple temporal intersection test"""
-        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
-        tra.parse(expression='D = A {during,=+} buff_t(C, "1 day") ',
-                  basename="d", overwrite=True)
-
-        D = tgis.open_old_space_time_dataset("D", type="strds")
-        D.select()
-        self.assertEqual(D.metadata.get_number_of_maps(), 4)
-        self.assertEqual(D.metadata.get_min_min(), 8)  # 1 + 7  a1 + c1
-        self.assertEqual(D.metadata.get_max_max(), 11) # 4 + 7  a4 + c1
-        start, end = D.get_absolute_time()
-        self.assertEqual(start, datetime.datetime(2001, 1, 1))
-        self.assertEqual(end, datetime.datetime(2001, 1, 5))
-
-    def test_temporal_neighbors_1(self):
-        """Simple temporal neighborhood computation test"""
-        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
-        tra.parse(expression='D = A[-1] + A[1]',
-                  basename="d", overwrite=True)
-
-        D = tgis.open_old_space_time_dataset("D", type="strds")
-        D.select()
-        self.assertEqual(D.metadata.get_number_of_maps(), 2)
-        self.assertEqual(D.metadata.get_min_min(), 4)  # 1 + 3
-        self.assertEqual(D.metadata.get_max_max(), 6) # 2 + 4
-        start, end = D.get_absolute_time()
-        self.assertEqual(start, datetime.datetime(2001, 1, 2))
-        self.assertEqual(end, datetime.datetime(2001, 1, 4))
-
-    def test_temporal_neighbors_2(self):
-        """Simple temporal neighborhood computation test"""
-        tra = tgis.TemporalRasterAlgebraParser(run = True, debug = True)
-        tra.parse(expression='D = A[0,0,-1] + A[0,0,1]',
-                  basename="d", overwrite=True)
-
-        D = tgis.open_old_space_time_dataset("D", type="strds")
-        D.select()
-        self.assertEqual(D.metadata.get_number_of_maps(), 2)
-        self.assertEqual(D.metadata.get_min_min(), 4)  # 1 + 3
-        self.assertEqual(D.metadata.get_max_max(), 6) # 2 + 4
-        start, end = D.get_absolute_time()
-        self.assertEqual(start, datetime.datetime(2001, 1, 2))
-        self.assertEqual(end, datetime.datetime(2001, 1, 4))
-
-    def tearDown(self):
-        ret = grass.script.run_command("t.remove", flags="rf", input="D", quiet=True)
-
-    @classmethod
-    def tearDownClass(cls):
-        """!Remove the temporary region
-        """
-        ret = grass.script.run_command("t.remove", flags="rf", input="A,B,C", quiet=True)
-        grass.script.del_temp_region()
-
-if __name__ == '__main__':
-    unittest.main()
-
-

+ 60 - 59
lib/python/temporal/univar_statistics.py

@@ -1,58 +1,55 @@
-"""!@package grass.temporal
-
-@brief GRASS Python scripting module (temporal GIS functions)
-
-Temporal GIS related functions to be used in Python scripts.
+"""
+Univariate statistic function for space time datasets
 
 Usage:
 
-@code
-import grass.temporal as tgis
+.. code-block:: python
 
-tgis.print_gridded_dataset_univar_statistics(
-    type, input, where, extended, no_header, fs)
+    import grass.temporal as tgis
+
+    tgis.print_gridded_dataset_univar_statistics(type, input, where, extended, no_header, fs)
 
-...
-@endcode
 
 (C) 2012-2013 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
+:authors: Soeren Gebbert
 """
 
 from open_stds import *
+import grass.script as gscript
 
 ###############################################################################
 
 
 def print_gridded_dataset_univar_statistics(type, input, where, extended,
                                             no_header=False, fs="|"):
-    """!Print univariate statistics for a space time raster or raster3d dataset
-
-       @param type Must be "strds" or "str3ds"
-       @param input The name of the space time dataset
-       @param where A temporal database where statement
-       @param extended If True compute extended statistics
-       @param no_header Supress the printing of column names
-       @param fs Field separator
+    """Print univariate statistics for a space time raster or raster3d dataset
+
+       :param type: Must be "strds" or "str3ds"
+       :param input: The name of the space time dataset
+       :param where: A temporal database where statement
+       :param extended: If True compute extended statistics
+       :param no_header: Supress the printing of column names
+       :param fs: Field separator
     """
 
     # We need a database interface
     dbif = SQLDatabaseInterfaceConnection()
     dbif.connect()
 
-    sp = open_old_space_time_dataset(input, type, dbif)
+    sp = open_old_stds(input, type, dbif)
 
     rows = sp.get_registered_maps(
         "id,start_time,end_time", where, "start_time", dbif)
 
     if not rows:
         dbif.close()
-        core.fatal(_("Space time %(sp)s dataset <%(i)s> is empty") % {
-                     'sp': sp.get_new_map_instance(None).get_type(), 'i': sp.get_id()})
+        gscript.fatal(_("Space time %(sp)s dataset <%(i)s> is empty") % {
+                      'sp': sp.get_new_map_instance(None).get_type(),
+                      'i': sp.get_id()})
 
     if no_header is False:
         string = ""
@@ -60,7 +57,7 @@ def print_gridded_dataset_univar_statistics(type, input, where, extended,
         string += "min" + fs + "max" + fs
         string += "mean_of_abs" + fs + "stddev" + fs + "variance" + fs
         string += "coeff_var" + fs + "sum" + fs + "null_cells" + fs + "cells"
-        if extended == True:
+        if extended is True:
             string += fs + "first_quartile" + fs + "median" + fs
             string += "third_quartile" + fs + "percentile_90"
 
@@ -74,28 +71,30 @@ def print_gridded_dataset_univar_statistics(type, input, where, extended,
 
         flag = "g"
 
-        if extended == True:
+        if extended is True:
             flag += "e"
 
         if type == "strds":
-            stats = core.parse_command("r.univar", map=id, flags=flag)
+            stats = gscript.parse_command("r.univar", map=id, flags=flag)
         elif type == "str3ds":
-            stats = core.parse_command("r3.univar", map=id, flags=flag)
+            stats = gscript.parse_command("r3.univar", map=id, flags=flag)
 
         if not stats:
             if type == "strds":
-                core.warning(_("Unable to get statistics for raster map <%s>") % id)
+                gscript.warning(_("Unable to get statistics for raster map "
+                                  "<%s>") % id)
             elif type == "str3ds":
-                core.warning(_("Unable to get statistics for 3d raster map <%s>") % id)
+                gscript.warning(_("Unable to get statistics for 3d raster map"
+                                  " <%s>") % id)
             continue
-        
+
         string += str(id) + fs + str(start) + fs + str(end)
         string += fs + str(stats["mean"]) + fs + str(stats["min"])
         string += fs + str(stats["max"]) + fs + str(stats["mean_of_abs"])
         string += fs + str(stats["stddev"]) + fs + str(stats["variance"])
         string += fs + str(stats["coeff_var"]) + fs + str(stats["sum"])
         string += fs + str(stats["null_cells"]) + fs + str(stats["cells"])
-        if extended == True:            
+        if extended is True:
             string += fs + str(stats["first_quartile"]) + fs + str(stats["median"])
             string += fs + str(stats["third_quartile"]) + fs + str(stats["percentile_90"])
         print string
@@ -106,19 +105,20 @@ def print_gridded_dataset_univar_statistics(type, input, where, extended,
 
 
 def print_vector_dataset_univar_statistics(input, twhere, layer, type, column,
-                                           where, extended, no_header=False, fs="|"):
-    """!Print univariate statistics for a space time vector dataset
+                                           where, extended, no_header=False,
+                                           fs="|"):
+    """Print univariate statistics for a space time vector dataset
 
-       @param input The name of the space time dataset
-       @param twhere A temporal database where statement
-       @param layer The layer number used in case no layer is present
+       :param input: The name of the space time dataset
+       :param twhere: A temporal database where statement
+       :param layer: The layer number used in case no layer is present
               in the temporal dataset
-       @param type options: point,line,boundary,centroid,area
-       @param column The name of the attribute column
-       @param where A temporal database where statement
-       @param extended If True compute extended statistics
-       @param no_header Supress the printing of column names
-       @param fs Field separator
+       :param type: options: point,line,boundary,centroid,area
+       :param column: The name of the attribute column
+       :param where: A temporal database where statement
+       :param extended: If True compute extended statistics
+       :param no_header: Supress the printing of column names
+       :param fs: Field separator
     """
 
     # We need a database interface
@@ -134,10 +134,10 @@ def print_vector_dataset_univar_statistics(input, twhere, layer, type, column,
 
     sp = dataset_factory("stvds", id)
 
-    if sp.is_in_db(dbif) == False:
+    if sp.is_in_db(dbif) is False:
         dbif.close()
-        core.fatal(_("Space time %(sp)s dataset <%(i)s> not found") % {
-                     'sp': sp.get_new_map_instance(None).get_type(), 'i': id})
+        gscript.fatal(_("Space time %(sp)s dataset <%(i)s> not found") % {
+                      'sp': sp.get_new_map_instance(None).get_type(), 'i': id})
 
     sp.select(dbif)
 
@@ -146,8 +146,8 @@ def print_vector_dataset_univar_statistics(input, twhere, layer, type, column,
 
     if not rows:
         dbif.close()
-        core.fatal(_("Space time %(sp)s dataset <%(i)s> is empty") % {
-                     'sp': sp.get_new_map_instance(None).get_type(), 'i': id})
+        gscript.fatal(_("Space time %(sp)s dataset <%(i)s> is empty") % {
+                      'sp': sp.get_new_map_instance(None).get_type(), 'i': id})
 
     string = ""
     if no_header is False:
@@ -160,7 +160,7 @@ def print_vector_dataset_univar_statistics(input, twhere, layer, type, column,
             string += "population_coeff_variation" + fs + \
                 "sample_stddev" + fs + "sample_variance" + fs
             string += "kurtosis" + fs + "skewness"
-            if extended == True:
+            if extended is True:
                 string += fs + "first_quartile" + fs + "median" + fs + \
                     "third_quartile" + fs + "percentile_90"
 
@@ -174,22 +174,23 @@ def print_vector_dataset_univar_statistics(input, twhere, layer, type, column,
 
         flags = "g"
 
-        if extended == True:
+        if extended is True:
             flags += "e"
 
         if not mylayer:
             mylayer = layer
 
-        stats = core.parse_command("v.univar", map=id, where=where,
-                                   column=column, layer=mylayer,
-                                   type=type, flags=flags)
+        stats = gscript.parse_command("v.univar", map=id, where=where,
+                                      column=column, layer=mylayer,
+                                      type=type, flags=flags)
 
         string = ""
 
         if not stats:
-            core.warning(_("Unable to get statistics for vector map <%s>") % id)
+            gscript.warning(_("Unable to get statistics for vector map <%s>")
+                            % id)
             continue
-        
+
         string += str(id) + fs + str(start) + fs + str(end)
         string += fs + str(stats["n"]) + fs + str(stats[
             "nmissing"]) + fs + str(stats["nnull"])
@@ -211,15 +212,15 @@ def print_vector_dataset_univar_statistics(input, twhere, layer, type, column,
                 str(stats["sample_variance"])
 
                 string += fs + str(stats["kurtosis"]) + fs + \
-                str(stats["skewness"])
+                          str(stats["skewness"])
             else:
                 string += fs + fs + fs + fs + fs + fs + fs + fs + fs
-            if extended == True:
+            if extended is True:
                 if "first_quartile" in stats:
                     string += fs + str(stats["first_quartile"]) + fs + \
-                    str(stats["median"]) + fs + \
-                    str(stats["third_quartile"]) + fs + \
-                    str(stats["percentile_90"])
+                              str(stats["median"]) + fs + \
+                              str(stats["third_quartile"]) + fs + \
+                              str(stats["percentile_90"])
                 else:
                     string += fs + fs + fs + fs