Browse Source

Map list resampling by granularity rewritten to gain massive speedup and have some test. Metadata test update. White space removal.
Temporal topology computation bugfix for time instances.


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

Soeren Gebbert 11 years ago
parent
commit
beb053835a

+ 2 - 10
lib/python/temporal/abstract_dataset.py

@@ -5,14 +5,6 @@
 
 Temporal GIS related functions to be used in temporal GIS Python library package.
 
-Usage:
-
-@code
-
->>> import grass.temporal as tgis
->>> ad = AbstractDataset()
-
-@endcode
 
 (C) 2011-2012 by the GRASS Development Team
 This program is free software under the GNU General Public
@@ -488,7 +480,7 @@ class AbstractDataset(SpatialTopologyDatasetConnector, TemporalTopologyDatasetCo
         else:
             return None
 
-    def _get_temporal_extent(self):
+    def get_temporal_extent(self):
         """!Return the temporal extent of the correct internal type
         """
         if self.is_time_absolute():
@@ -497,7 +489,7 @@ class AbstractDataset(SpatialTopologyDatasetConnector, TemporalTopologyDatasetCo
             return self.relative_time
         return None
 
-    temporal_extent = property(fget=_get_temporal_extent)
+    temporal_extent = property(fget=get_temporal_extent)
 
     def temporal_relation(self, dataset):
         """!Return the temporal relation of self and the provided dataset

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

@@ -516,12 +516,12 @@ class AbstractMapDataset(AbstractDataset):
            >>> import datetime
            >>> import grass.temporal as tgis
            >>> map      = tgis.RasterDataset(None)
-           >>> temp_ext = tgis.RelativeTemporalExtent(start_time=1, end_time=2, unit="years")
+           >>> temp_ext = tgis.RasterRelativeTime(start_time=1, end_time=2, unit="years")
            >>> map.set_temporal_extent(temp_ext)
            >>> print map.get_temporal_extent_as_tuple()
            (1, 2)
            >>> map      = tgis.VectorDataset(None)
-           >>> temp_ext = tgis.AbsoluteTemporalExtent(start_time=datetime.datetime(2000, 1, 1),
+           >>> temp_ext = tgis.VectorAbsoluteTime(start_time=datetime.datetime(2000, 1, 1),
            ...                                        end_time=datetime.datetime(2001, 1, 1))
            >>> map.set_temporal_extent(temp_ext)
            >>> print map.get_temporal_extent_as_tuple()
@@ -530,14 +530,15 @@ class AbstractMapDataset(AbstractDataset):
            @endcode
         """
 
-        if issubclass(RelativeTemporalExtent, type(temporal_extent)):
+
+        if issubclass(type(temporal_extent), RelativeTemporalExtent):
             start = temporal_extent.get_start_time()
             end = temporal_extent.get_end_time()
             unit = temporal_extent.get_unit()
 
             self.set_relative_time(start, end, unit)
 
-        elif issubclass(AbsoluteTemporalExtent, type(temporal_extent)):
+        elif issubclass(type(temporal_extent), AbsoluteTemporalExtent):
             start = temporal_extent.get_start_time()
             end = temporal_extent.get_end_time()
             tz = temporal_extent.get_timezone()

+ 174 - 110
lib/python/temporal/abstract_space_time_dataset.py

@@ -3,7 +3,8 @@
 
 @brief GRASS Python scripting module (temporal GIS functions)
 
-Temporal GIS related functions to be used in temporal GIS Python library package.
+Temporal GIS related functions to be used in temporal GIS Python
+library package.
 
 (C) 2011-2012 by the GRASS Development Team
 This program is free software under the GNU General Public
@@ -715,8 +716,13 @@ class AbstractSpaceTimeDataset(AbstractDataset):
            with "gap" map objects (id==None) for spatio-temporal topological
            operations that require the temporal extent only.
 
-           Each list entry is a list of map objects
-           which are potentially located in the actual granule.
+           Each list entry is a list of AbstractMapDatasets objects
+           which are potentially equal the actual granule, contain the
+           actual granule or are located in the actual granule.
+           Hence for each granule a list of AbstractMapDatasets can be
+           expected.
+
+           Maps that overlap the granule are ignored.
 
            The granularity of the space time dataset is used as increment in
            case the granule is not user defined.
@@ -746,13 +752,12 @@ class AbstractSpaceTimeDataset(AbstractDataset):
                        unit and can not be changed.
            @param dbif The database interface to be used
 
-           @return ordered object list, or None in case nothing found
+           @return ordered list of map lists. Each list represents a single
+                   granule, or None in case nothing found
         """
 
         dbif, connected = init_dbif(dbif)
 
-        obj_list = []
-
         if gran is None:
             gran = self.get_granularity()
 
@@ -765,137 +770,194 @@ class AbstractSpaceTimeDataset(AbstractDataset):
         if start is None or end is None:
             return None
 
-        # Time instances and mixed time
-        is_irregular = False
+        maps = self.get_registered_maps_as_objects(dbif=dbif,
+                                                   order="start_time")
+
+        if not maps:
+            return None
 
         # We need to adjust the end time in case the the dataset has no
         # interval time, so we can catch time instances at the end
         if self.get_map_time() != "interval":
-            is_irregular = True
-
             if self.is_time_absolute():
                 end = increment_datetime_by_string(end, gran)
             else:
                 end = end + gran
 
-        while start < end:
-            if self.is_time_absolute():
-                next = increment_datetime_by_string(start, gran)
-            else:
-                next = start + gran
+        l = AbstractSpaceTimeDataset.resample_maplist_by_granularity(maps,
+                                                                     start,
+                                                                     end,
+                                                                     gran)
+        if connected:
+            dbif.close()
 
-            # First we search for intervals that are are equal the granule or
-            # contain it
-            where = create_temporal_relation_sql_where_statement(
-                    start=start, end=next, use_start=False, use_during=False,
-                    use_overlap=False, use_contain=True, use_equal=True,
-                    use_follows=False, use_precedes=False)
-            rows = self.get_registered_maps("id", where, "start_time", dbif)
-
-            found_gap = False
-
-            if rows is not None and len(rows) != 0:
-                if len(rows) > 1:
-                    core.warning(_("More than one map found in a granule. "
-                                   "Temporal granularity seems to be invalid "
-                                   "or the chosen granularity is not a "
-                                   "greatest common divider of all intervals "
-                                   "and gaps in the dataset."))
-
-                maplist = []
-                for row in rows:
+        return l
 
-                    map = self.get_new_map_instance(row["id"])
+    @staticmethod
+    def resample_maplist_by_granularity(maps, start, end, gran):
+        """!Resample a list of AbstractMapDatasets by a given granularity
 
-                    if self.is_time_absolute():
-                        map.set_absolute_time(start, next)
-                    elif self.is_time_relative():
-                        map.set_relative_time(start, next,
-                                              self.get_relative_time_unit())
+           The provided map list must be sorted by start time.
+           A valid temporal topology (no overlapping or inclusion allowed)
+           is needed to receive correct results.
 
-                    maplist.append(copy.copy(map))
+           Maps with interval time, time instances and mixed
+           time are supported.
 
-                obj_list.append(copy.copy(maplist))
-            else:
-                # We may found a gap or a gap after a time instance
-                found_gap = True
+           The temporal topology search order is as follows:
+           1. Maps that are equal to the actual granule are used
+           2. If no euqal found then maps that contain the actual granule
+              are used
+           3. If no maps are found that contain the actual granule then maps
+              are used that overlaps the actual granule
+           4. If no overlaps maps found then overlapped maps are used
+           5. If no overlapped maps are found then maps are used that are
+              durin the actual granule
+
+           Each entry in the resulting list is a list of
+           AbstractMapDatasets objects.
+           Hence for each granule a list of AbstractMapDatasets can be
+           expected.
 
-                # Searching for time instances and intervals that are during
-                # the current granule or overlapping it
-                where = create_temporal_relation_sql_where_statement(
-                        start=start, end=next, use_start=True, use_during=True,
-                        use_overlap=True, use_contain=False, use_equal=False,
-                        use_follows=False, use_precedes=False)
+           Gaps between maps are identified as unregistered maps with id==None.
 
-                rows = self.get_registered_maps("id,start_time,end_time",
-                                                where, "start_time", dbif)
-
-                if rows is not None and len(rows) != 0:
-                    # No gap if we found something in the granule with
-                    # intervaltime
-                    if len(rows) > 1:
-                        core.warning(_("More than one map found in a granule. "
-                                       "Temporal granularity seems to be "
-                                       "invalid or the chosen granularity is "
-                                       "not a greatest common divider of all "
-                                       "time instances in the dataset."))
-
-                    maplist = []
-                    count = 0
-                    for row in rows:
-                        if count == 0:
-                            if row["end_time"] is not None or row["start_time"] != start:
-                                found_gap = False
-                        count += 1
-
-                        map = self.get_new_map_instance(row["id"])
+           @param maps An ordered list (by start time) of AbstractMapDatasets
+                   objects. All maps must have the same temporal type
+                   and the same unit in case of relative time.
+           @param start The start time of the provided map list
+           @param end   The end time of the provided map list
+           @param gran The granularity string to be used, if None the
+                   granularity of the space time dataset is used.
+                   Absolute time has the format "number unit", relative
+                   time has the format "number".
+                   The unit in case of absolute time can be one of "second,
+                   seconds, minute, minutes, hour, hours, day, days, week,
+                   weeks, month, months, year, years". The unit of the
+                   relative time granule is always the space time dataset
+                   unit and can not be changed.
+
+           @return ordered list of map lists. Each list represents a single
+               granule, or None in case nothing found
 
-                        if self.is_time_absolute():
-                            if row["end_time"] is not None or row["start_time"] != start:
-                                map.set_absolute_time(start, next)
-                            else:
-                                map.set_absolute_time(start, None)
-                        elif self.is_time_relative():
-                            if row["end_time"] is not None or row["start_time"] != start:
-                                map.set_relative_time(start, next,
-                                                 self.get_relative_time_unit())
-                            else:
-                                map.set_relative_time(start, None,
-                                                 self.get_relative_time_unit())
+           Usage:
 
-                        maplist.append(copy.copy(map))
+        @code
+
+        >>> import grass.temporal as tgis
+        >>> maps = []
+        >>> for i in xrange(3):
+        ...     map = tgis.RasterDataset("map%i@PERMANENT"%i)
+        ...     check = map.set_relative_time(i + 2, i + 3, "days")
+        ...     maps.append(map)
+        >>> grans = tgis.AbstractSpaceTimeDataset.resample_maplist_by_granularity(maps,0,8,1)
+        >>> for map_list in grans:
+        ...    print map_list[0].get_id(), map_list[0].get_temporal_extent_as_tuple()
+        None (0, 1)
+        None (1, 2)
+        map0@PERMANENT (2, 3)
+        map1@PERMANENT (3, 4)
+        map2@PERMANENT (4, 5)
+        None (5, 6)
+        None (6, 7)
+        None (7, 8)
+
+        >>> maps = []
+        >>> map1 = tgis.RasterDataset("map1@PERMANENT")
+        >>> check = map1.set_relative_time(2, 6, "days")
+        >>> maps.append(map1)
+        >>> map2 = tgis.RasterDataset("map2@PERMANENT")
+        >>> check = map2.set_relative_time(7, 13, "days")
+        >>> maps.append(map2)
+        >>> grans = tgis.AbstractSpaceTimeDataset.resample_maplist_by_granularity(maps,0,16,2)
+        >>> for map_list in grans:
+        ...    print map_list[0].get_id(), map_list[0].get_temporal_extent_as_tuple()
+        None (0, 2)
+        map1@PERMANENT (2, 4)
+        map1@PERMANENT (4, 6)
+        map2@PERMANENT (6, 8)
+        map2@PERMANENT (8, 10)
+        map2@PERMANENT (10, 12)
+        map2@PERMANENT (12, 14)
+        None (14, 16)
+
+        >>> maps = []
+        >>> map1 = tgis.RasterDataset("map1@PERMANENT")
+        >>> check = map1.set_relative_time(2, None, "days")
+        >>> maps.append(map1)
+        >>> map2 = tgis.RasterDataset("map2@PERMANENT")
+        >>> check = map2.set_relative_time(7, None, "days")
+        >>> maps.append(map2)
+        >>> grans = tgis.AbstractSpaceTimeDataset.resample_maplist_by_granularity(maps,0,16,2)
+        >>> for map_list in grans:
+        ...    print map_list[0].get_id(), map_list[0].get_temporal_extent_as_tuple()
+        None (0, 2)
+        map1@PERMANENT (2, 4)
+        None (4, 6)
+        map2@PERMANENT (6, 8)
+        None (8, 10)
+        None (10, 12)
+        None (12, 14)
+        None (14, 16)
+
+        @endcode
+        """
 
-                    obj_list.append(copy.copy(maplist))
+        if not maps:
+            return None
 
-                # In case of irregular time (point, mixed) the last granule
-                # does not belong to the dataset and will be ignored
-                if is_irregular:
-                    if next == end:
-                        found_gap = False
+        first = maps[0]
 
-            # Gap handling
-            if found_gap:
-                # Append a map object with None as id to indicate a gap
-                map = self.get_new_map_instance(None)
+        # Build the gaplist
+        gap_list = []
+        while start < end:
+            if first.is_time_absolute():
+                next = increment_datetime_by_string(start, gran)
+            else:
+                next = start + gran
 
-                if self.is_time_absolute():
-                    map.set_absolute_time(start, next)
-                elif self.is_time_relative():
-                    map.set_relative_time(start, next,
-                                          self.get_relative_time_unit())
+            map = first.get_new_instance(None)
+            if first.is_time_absolute():
+                map.set_absolute_time(start, next, None)
+            else:
+                map.set_relative_time(start, next, first.get_relative_time_unit())
 
-                maplist = []
-                maplist.append(copy.copy(map))
+            gap_list.append(copy.copy(map))
+            start = next
 
-                obj_list.append(copy.copy(maplist))
+        tb = SpatioTemporalTopologyBuilder()
+        tb.build(gap_list, maps)
 
-            start = next
+        relations_order = ["EQUAL", "DURING", "OVERLAPS", "OVERLAPPED", "CONTAINS"]
 
-        if connected:
-            dbif.close()
+        gran_list = []
+        for gap in gap_list:
+            # If not temporal relations then gap
+            if not gap.get_temporal_relations():
+                gran_list.append([gap,])
+            else:
+                relations = gap.get_temporal_relations()
+
+                map_list = []
+
+                for relation in relations_order:
+                    if relation in relations:
+                        map_list += relations[relation]
+                        break
+
+                if map_list:
+                    new_maps = []
+                    for map in map_list:
+                        new_map = map.get_new_instance(map.get_id())
+                        new_map.set_temporal_extent(gap.get_temporal_extent())
+                        new_map.set_spatial_extent(map.get_spatial_extent())
+                        new_maps.append(new_map)
+                    gran_list.append(new_maps)
+                else:
+                    gran_list.append([gap,])
+
+        if gran_list:
+            return gran_list
 
-        if obj_list:
-            return obj_list
         return None
 
     def get_registered_maps_as_objects_with_gaps(self, where=None, dbif=None):
@@ -1465,6 +1527,8 @@ class AbstractSpaceTimeDataset(AbstractDataset):
            This method renames the space time dataset, the map register table
            and updates the entries in registered maps stds register.
 
+           Renaming does not work with Postgresql yet.
+
            @param ident The new identifier "name@mapset"
            @param dbif The database interface to be used
         """

+ 164 - 159
lib/python/temporal/metadata.py

@@ -33,11 +33,11 @@ from base import *
 
 class RasterMetadataBase(SQLDatabaseInterface):
     """!This is the metadata base class for time stamped raster and raster3d maps
-    
+
         Usage:
-        
+
         @code
-        
+
         >>> init()
         >>> meta = RasterMetadataBase(table="metadata", ident="soil@PERMANENT",
         ... datatype="CELL", cols=100, rows=100, number_of_cells=10000, nsres=0.1,
@@ -76,11 +76,11 @@ class RasterMetadataBase(SQLDatabaseInterface):
         ewres=0.1
         min=0.0
         max=100.0
-        
+
         @endcode
     """
-    def __init__(self, table=None, ident=None, datatype=None, cols=None, 
-		rows=None, number_of_cells=None, nsres=None, ewres=None, 
+    def __init__(self, table=None, ident=None, datatype=None, cols=None,
+		rows=None, number_of_cells=None, nsres=None, ewres=None,
 		min=None, max=None):
 
         SQLDatabaseInterface.__init__(self, table, ident)
@@ -225,7 +225,7 @@ class RasterMetadataBase(SQLDatabaseInterface):
             return self.D["max"]
         else:
             return None
-    
+
     # Properties
     datatype = property(fget=get_datatype, fset=set_datatype)
     cols = property(fget=get_cols, fset=set_cols)
@@ -235,7 +235,7 @@ class RasterMetadataBase(SQLDatabaseInterface):
     ewres = property(fget=get_ewres, fset=set_ewres)
     min = property(fget=get_min, fset=set_min)
     max = property(fget=get_max, fset=set_max)
-    
+
     def print_info(self):
         """!Print information about this class in human readable style"""
         #      0123456789012345678901234567890
@@ -265,19 +265,19 @@ class RasterMetadataBase(SQLDatabaseInterface):
 
 class RasterMetadata(RasterMetadataBase):
     """!This is the raster metadata class
-       
+
         This class is the interface to the raster_metadata table in the
         temporal database that stores the metadata of all registered raster maps.
-        
+
         The metadata includes the datatype, number of cols, rows and cells and
-        the north-south and east west resolution of the map. Additionally the 
+        the north-south and east west resolution of the map. Additionally the
         minimum and maximum values and the name of the space time raster dataset
         register table is stored.
-       
+
         Usage:
-        
+
         @code
-       
+
         >>> init()
         >>> meta = RasterMetadata(ident="soil@PERMANENT",
         ... datatype="CELL", cols=100, rows=100, number_of_cells=10000, nsres=0.1,
@@ -320,15 +320,15 @@ class RasterMetadata(RasterMetadataBase):
         min=0.0
         max=100.0
         strds_register=None
-        
+
         @endcode
     """
-    def __init__(self, ident=None, strds_register=None, datatype=None, 
-		 cols=None, rows=None, number_of_cells=None, nsres=None, 
+    def __init__(self, ident=None, strds_register=None, datatype=None,
+		 cols=None, rows=None, number_of_cells=None, nsres=None,
 		 ewres=None, min=None, max=None):
 
         RasterMetadataBase.__init__(self, "raster_metadata", ident, datatype,
-                                      cols, rows, number_of_cells, nsres, 
+                                      cols, rows, number_of_cells, nsres,
                                       ewres, min, max)
 
         self.set_strds_register(strds_register)
@@ -344,7 +344,7 @@ class RasterMetadata(RasterMetadataBase):
             return self.D["strds_register"]
         else:
             return None
-        
+
     strds_register = property(fget=get_strds_register, fset=set_strds_register)
 
     def print_info(self):
@@ -365,19 +365,19 @@ class RasterMetadata(RasterMetadataBase):
 
 class Raster3DMetadata(RasterMetadataBase):
     """!This is the raster3d metadata class
-       
+
         This class is the interface to the raster3d_metadata table in the
-        temporal database that stores the metadata of all registered 
+        temporal database that stores the metadata of all registered
         3D raster maps.
-        
+
         The metadata includes all raster metadata variables and additional
         the number of depths, the top-bottom resolution and the space time 3D
         raster dataset register table is stored.
-       
+
         Usage:
-        
+
         @code
-       
+
         >>> init()
         >>> meta = Raster3DMetadata(ident="soil@PERMANENT",
         ... datatype="FCELL", cols=100, rows=100, depths=100,
@@ -429,15 +429,15 @@ class Raster3DMetadata(RasterMetadataBase):
         str3ds_register=None
         depths=100
         tbres=0.1
-        
+
         @endcode
     """
-    def __init__(self, ident=None, str3ds_register=None, datatype=None, 
-		 cols=None, rows=None, depths=None, number_of_cells=None, 
+    def __init__(self, ident=None, str3ds_register=None, datatype=None,
+		 cols=None, rows=None, depths=None, number_of_cells=None,
 		 nsres=None, ewres=None, tbres=None, min=None, max=None):
 
-        RasterMetadataBase.__init__(self, "raster3d_metadata", ident, 
-				datatype, cols, rows, number_of_cells, nsres, 
+        RasterMetadataBase.__init__(self, "raster3d_metadata", ident,
+				datatype, cols, rows, number_of_cells, nsres,
 				ewres, min, max)
 
         self.set_str3ds_register(str3ds_register)
@@ -489,7 +489,7 @@ class Raster3DMetadata(RasterMetadataBase):
     depths = property(fget=get_depths, fset=set_depths)
     tbres = property(fget=get_tbres, fset=set_tbres)
     str3ds_register = property(fget=get_str3ds_register, fset=set_str3ds_register)
-    
+
     def print_info(self):
         """!Print information about this class in human readable style"""
         print " +-------------------- Metadata information ----------------------------------+"
@@ -513,19 +513,19 @@ class Raster3DMetadata(RasterMetadataBase):
 
 class VectorMetadata(SQLDatabaseInterface):
     """!This is the vector metadata class
-        
+
         This class is the interface to the vector_metadata table in the
-        temporal database that stores the metadata of all registered 
+        temporal database that stores the metadata of all registered
         vector maps.
-        
+
         Usage:
-        
+
         @code
-       
+
         >>> init()
-        >>> meta = VectorMetadata(ident="lidar@PERMANENT", is_3d=True, 
+        >>> meta = VectorMetadata(ident="lidar@PERMANENT", is_3d=True,
         ... number_of_points=1, number_of_lines=2, number_of_boundaries=3,
-        ... number_of_centroids=4, number_of_faces=5, number_of_kernels=6, 
+        ... number_of_centroids=4, number_of_faces=5, number_of_kernels=6,
         ... number_of_primitives=7, number_of_nodes=8, number_of_areas=9,
         ... number_of_islands=10, number_of_holes=11, number_of_volumes=12)
         >>> meta.id
@@ -587,13 +587,13 @@ class VectorMetadata(SQLDatabaseInterface):
         islands=10
         holes=11
         volumes=12
-        
+
         @endcode
     """
     def __init__(
-        self, ident=None, stvds_register=None, is_3d=False, 
+        self, ident=None, stvds_register=None, is_3d=False,
         number_of_points=None, number_of_lines=None, number_of_boundaries=None,
-        number_of_centroids=None, number_of_faces=None, number_of_kernels=None, 
+        number_of_centroids=None, number_of_faces=None, number_of_kernels=None,
         number_of_primitives=None, number_of_nodes=None, number_of_areas=None,
         number_of_islands=None, number_of_holes=None, number_of_volumes=None):
 
@@ -694,7 +694,7 @@ class VectorMetadata(SQLDatabaseInterface):
             return None
 
     def get_3d_info(self):
-        """!Return True if the map is three dimensional, 
+        """!Return True if the map is three dimensional,
            False if not and None if not info was found"""
         if "is_3d" in self.D:
             return self.D["is_3d"]
@@ -796,37 +796,37 @@ class VectorMetadata(SQLDatabaseInterface):
             return self.D["volumes"]
         else:
             return None
-    
+
     # Set the properties
     id  = property(fget=get_id, fset=set_id)
-    stvds_register  = property(fget=get_stvds_register, 
+    stvds_register  = property(fget=get_stvds_register,
                                fset=set_stvds_register)
     is_3d  = property(fget=get_3d_info, fset=set_3d_info)
-    number_of_points = property(fget=get_number_of_points, 
+    number_of_points = property(fget=get_number_of_points,
                                 fset=set_number_of_points)
-    number_of_lines = property(fget=get_number_of_lines, 
+    number_of_lines = property(fget=get_number_of_lines,
                                fset=set_number_of_lines)
-    number_of_boundaries = property(fget=get_number_of_boundaries, 
+    number_of_boundaries = property(fget=get_number_of_boundaries,
                                     fset=set_number_of_boundaries)
-    number_of_centroids = property(fget=get_number_of_centroids, 
+    number_of_centroids = property(fget=get_number_of_centroids,
                                    fset=set_number_of_centroids)
-    number_of_faces = property(fget=get_number_of_faces, 
+    number_of_faces = property(fget=get_number_of_faces,
                                fset=set_number_of_faces)
-    number_of_kernels = property(fget=get_number_of_kernels, 
+    number_of_kernels = property(fget=get_number_of_kernels,
                                  fset=set_number_of_kernels)
-    number_of_primitives = property(fget=get_number_of_primitives, 
+    number_of_primitives = property(fget=get_number_of_primitives,
                                     fset=set_number_of_primitives)
-    number_of_nodes = property(fget=get_number_of_nodes, 
+    number_of_nodes = property(fget=get_number_of_nodes,
                                fset=set_number_of_nodes)
-    number_of_areas = property(fget=get_number_of_areas, 
+    number_of_areas = property(fget=get_number_of_areas,
                                fset=set_number_of_areas)
-    number_of_islands = property(fget=get_number_of_islands, 
+    number_of_islands = property(fget=get_number_of_islands,
                                  fset=set_number_of_islands)
-    number_of_holes = property(fget=get_number_of_holes, 
+    number_of_holes = property(fget=get_number_of_holes,
                                fset=set_number_of_holes)
-    number_of_volumes = property(fget=get_number_of_volumes, 
+    number_of_volumes = property(fget=get_number_of_volumes,
                                  fset=set_number_of_volumes)
-        
+
     def print_info(self):
         """!Print information about this class in human readable style"""
         #      0123456789012345678901234567890
@@ -868,14 +868,14 @@ class VectorMetadata(SQLDatabaseInterface):
 
 
 class STDSMetadataBase(SQLDatabaseInterface):
-    """!This is the space time dataset metadata base class for 
+    """!This is the space time dataset metadata base class for
        strds, stvds and str3ds datasets
        setting/getting the id, the title and the description
-       
+
         Usage:
-        
+
         @code
-        
+
         >>> init()
         >>> meta = STDSMetadataBase(ident="soils@PERMANENT",
         ... title="Soils", description="Soils 1950 - 2010")
@@ -888,14 +888,15 @@ class STDSMetadataBase(SQLDatabaseInterface):
         >>> meta.number_of_maps
         >>> meta.print_info()
          | Number of registered maps:.. None
+         |
          | Title:
          | Soils
          | Description:
          | Soils 1950 - 2010
-         | Commands of creation:
+         | Command history:
         >>> meta.print_shell_info()
         number_of_maps=None
-        
+
         @endcode
     """
     def __init__(self, table=None, ident=None, title=None, description=None, command=None):
@@ -925,7 +926,7 @@ class STDSMetadataBase(SQLDatabaseInterface):
     def set_command(self, command):
         """!Set the number of cols"""
         self.D["command"] = command
-        
+
     def get_id(self):
         """!Convenient method to get the unique identifier (primary key)
            @return None if not found
@@ -958,9 +959,9 @@ class STDSMetadataBase(SQLDatabaseInterface):
             return self.D["command"]
         else:
             return None
-            
+
     def get_number_of_maps(self):
-        """!Get the number of registered maps, 
+        """!Get the number of registered maps,
            this value is set in the database
            automatically via SQL, so no setter exists
            @return None if not found"""
@@ -968,12 +969,12 @@ class STDSMetadataBase(SQLDatabaseInterface):
             return self.D["number_of_maps"]
         else:
             return None
-        
+
     id  = property(fget=get_id, fset=set_id)
     title  = property(fget=get_title, fset=set_title)
     description  = property(fget=get_description, fset=set_description)
     number_of_maps  = property(fget=get_number_of_maps)
-    
+
     def print_info(self):
         """!Print information about this class in human readable style"""
         #      0123456789012345678901234567890
@@ -991,7 +992,7 @@ class STDSMetadataBase(SQLDatabaseInterface):
                 print " | " + str(token)
 
     def print_history(self):
-        """!Print history information about this class in human readable 
+        """!Print history information about this class in human readable
             shell style
         """
         #      0123456789012345678901234567890
@@ -1001,7 +1002,7 @@ class STDSMetadataBase(SQLDatabaseInterface):
         print "# " + str(self.get_description())
         print "# Command history:"
         command = self.get_command()
-        
+
         if command:
             tokens = command.split("\n")
             print_list = []
@@ -1009,7 +1010,7 @@ class STDSMetadataBase(SQLDatabaseInterface):
                 token = str(token).rstrip().lstrip()
                 if len(token) > 1:
                     print_list.append(token)
-                
+
             count = 0
             for token in print_list:
                 count += 1
@@ -1019,8 +1020,8 @@ class STDSMetadataBase(SQLDatabaseInterface):
                     elif count < len(print_list):
                         print token + " \\"
                     else:
-                        print token 
-                        
+                        print token
+
     def print_shell_info(self):
         """!Print information about this class in shell style"""
         print "number_of_maps=" + str(self.get_number_of_maps())
@@ -1029,16 +1030,16 @@ class STDSMetadataBase(SQLDatabaseInterface):
 
 
 class STDSRasterMetadataBase(STDSMetadataBase):
-    """!This is the space time dataset metadata base 
+    """!This is the space time dataset metadata base
         class for strds and str3ds datasets
 
         Most of the metadata values are set by SQL scripts in the database when
-        new maps are added. Therefor only some set- an many 
+        new maps are added. Therefor only some set- an many
         get-functions are available.
-        
-       
+
+
         Usage:
-        
+
         @code
         >>> init()
         >>> meta = STDSRasterMetadataBase(ident="soils@PERMANENT",
@@ -1059,12 +1060,6 @@ class STDSRasterMetadataBase(STDSMetadataBase):
         >>> meta.ewres_min
         >>> meta.ewres_max
         >>> meta.print_info()
-         | Number of registered maps:.. None
-         | Title:
-         | Soils
-         | Description:
-         | Soils 1950 - 2010
-         | Commands of creation:
          | North-South resolution min:. None
          | North-South resolution max:. None
          | East-west resolution min:... None
@@ -1073,6 +1068,13 @@ class STDSRasterMetadataBase(STDSMetadataBase):
          | Minimum value max:.......... None
          | Maximum value min:.......... None
          | Maximum value max:.......... None
+         | Number of registered maps:.. None
+         |
+         | Title:
+         | Soils
+         | Description:
+         | Soils 1950 - 2010
+         | Command history:
         >>> meta.print_shell_info()
         number_of_maps=None
         nsres_min=None
@@ -1083,7 +1085,7 @@ class STDSRasterMetadataBase(STDSMetadataBase):
         min_max=None
         max_min=None
         max_max=None
-        
+
         @endcode
     """
     def __init__(self, table=None, ident=None, title=None, description=None):
@@ -1101,7 +1103,7 @@ class STDSRasterMetadataBase(STDSMetadataBase):
         self.D["ewres_max"] = None
 
     def get_max_min(self):
-        """!Get the minimal maximum of all registered maps, 
+        """!Get the minimal maximum of all registered maps,
            this value is set in the database
            automatically via SQL, so no setter exists
            @return None if not found"""
@@ -1111,7 +1113,7 @@ class STDSRasterMetadataBase(STDSMetadataBase):
             return None
 
     def get_min_min(self):
-        """!Get the minimal minimum of all registered maps, 
+        """!Get the minimal minimum of all registered maps,
            this value is set in the database
            automatically via SQL, so no setter exists
            @return None if not found"""
@@ -1121,7 +1123,7 @@ class STDSRasterMetadataBase(STDSMetadataBase):
             return None
 
     def get_max_max(self):
-        """!Get the maximal maximum of all registered maps, 
+        """!Get the maximal maximum of all registered maps,
            this value is set in the database
            automatically via SQL, so no setter exists
            @return None if not found"""
@@ -1131,7 +1133,7 @@ class STDSRasterMetadataBase(STDSMetadataBase):
             return None
 
     def get_min_max(self):
-        """!Get the maximal minimum of all registered maps, 
+        """!Get the maximal minimum of all registered maps,
            this value is set in the database
            automatically via SQL, so no setter exists
            @return None if not found"""
@@ -1141,7 +1143,7 @@ class STDSRasterMetadataBase(STDSMetadataBase):
             return None
 
     def get_nsres_min(self):
-        """!Get the minimal north-south resolution of all registered maps, 
+        """!Get the minimal north-south resolution of all registered maps,
            this value is set in the database
            automatically via SQL, so no setter exists
            @return None if not found"""
@@ -1151,7 +1153,7 @@ class STDSRasterMetadataBase(STDSMetadataBase):
             return None
 
     def get_nsres_max(self):
-        """!Get the maximal north-south resolution of all registered maps, 
+        """!Get the maximal north-south resolution of all registered maps,
            this value is set in the database
            automatically via SQL, so no setter exists
            @return None if not found"""
@@ -1161,7 +1163,7 @@ class STDSRasterMetadataBase(STDSMetadataBase):
             return None
 
     def get_ewres_min(self):
-        """!Get the minimal east-west resolution of all registered maps, 
+        """!Get the minimal east-west resolution of all registered maps,
            this value is set in the database
            automatically via SQL, so no setter exists
            @return None if not found"""
@@ -1171,7 +1173,7 @@ class STDSRasterMetadataBase(STDSMetadataBase):
             return None
 
     def get_ewres_max(self):
-        """!Get the maximal east-west resolution of all registered maps, 
+        """!Get the maximal east-west resolution of all registered maps,
            this value is set in the database
            automatically via SQL, so no setter exists
            @return None if not found"""
@@ -1179,7 +1181,7 @@ class STDSRasterMetadataBase(STDSMetadataBase):
             return self.D["ewres_max"]
         else:
             return None
-    
+
     nsres_min = property(fget=get_nsres_min)
     nsres_max = property(fget=get_nsres_max)
     ewres_min = property(fget=get_ewres_min)
@@ -1188,7 +1190,7 @@ class STDSRasterMetadataBase(STDSMetadataBase):
     min_max = property(fget=get_min_max)
     max_min = property(fget=get_max_min)
     max_max = property(fget=get_max_max)
-    
+
     def print_info(self):
         """!Print information about this class in human readable style"""
         #      0123456789012345678901234567890
@@ -1219,19 +1221,19 @@ class STDSRasterMetadataBase(STDSMetadataBase):
 
 class STRDSMetadata(STDSRasterMetadataBase):
     """!This is the raster metadata class
-        
+
         This class is the interface to the strds_metadata table in the
-        temporal database that stores the metadata of all registered 
+        temporal database that stores the metadata of all registered
         space time raster datasets
-        
+
         Most of the metadata values are set by SQL scripts in the database when
-        new raster maps are added. Therefor only some set- an many 
+        new raster maps are added. Therefor only some set- an many
         get-functions are available.
-        
+
         Usage:
-        
+
         @code
-        
+
         >>> init()
         >>> meta = STRDSMetadata(ident="soils@PERMANENT",
         ... title="Soils", description="Soils 1950 - 2010")
@@ -1253,12 +1255,7 @@ class STRDSMetadata(STDSRasterMetadataBase):
         >>> meta.raster_register
         >>> meta.print_info()
          +-------------------- Metadata information ----------------------------------+
-         | Number of registered maps:.. None
-         | Title:
-         | Soils
-         | Description:
-         | Soils 1950 - 2010
-         | Commands of creation:
+         | Raster register table:...... None
          | North-South resolution min:. None
          | North-South resolution max:. None
          | East-west resolution min:... None
@@ -1267,7 +1264,13 @@ class STRDSMetadata(STDSRasterMetadataBase):
          | Minimum value max:.......... None
          | Maximum value min:.......... None
          | Maximum value max:.......... None
-         | Raster register table:...... None
+         | Number of registered maps:.. None
+         |
+         | Title:
+         | Soils
+         | Description:
+         | Soils 1950 - 2010
+         | Command history:
         >>> meta.print_shell_info()
         number_of_maps=None
         nsres_min=None
@@ -1279,7 +1282,7 @@ class STRDSMetadata(STDSRasterMetadataBase):
         max_min=None
         max_max=None
         raster_register=None
-        
+
         @endcode
     """
     def __init__(self, ident=None, raster_register=None, title=None, description=None):
@@ -1300,8 +1303,8 @@ class STRDSMetadata(STDSRasterMetadataBase):
             return self.D["raster_register"]
         else:
             return None
-    
-    raster_register = property(fget=get_raster_register, 
+
+    raster_register = property(fget=get_raster_register,
                                fset=set_raster_register)
 
     def print_info(self):
@@ -1322,19 +1325,19 @@ class STRDSMetadata(STDSRasterMetadataBase):
 
 class STR3DSMetadata(STDSRasterMetadataBase):
     """!This is the space time 3D raster metadata class
-    
+
         This class is the interface to the str3ds_metadata table in the
-        temporal database that stores the metadata of all registered 
+        temporal database that stores the metadata of all registered
         space time 3D raster datasets
-        
+
         Most of the metadata values are set by SQL scripts in the database when
-        new 3D raster maps are added. Therefor only some set- an many 
+        new 3D raster maps are added. Therefor only some set- an many
         get-functions are available.
-        
+
         Usage:
-        
+
         @code
-        
+
         >>> init()
         >>> meta = STR3DSMetadata(ident="soils@PERMANENT",
         ... title="Soils", description="Soils 1950 - 2010")
@@ -1358,12 +1361,9 @@ class STR3DSMetadata(STDSRasterMetadataBase):
         >>> meta.raster3d_register
         >>> meta.print_info()
          +-------------------- Metadata information ----------------------------------+
-         | Number of registered maps:.. None
-         | Title:
-         | Soils
-         | Description:
-         | Soils 1950 - 2010
-         | Commands of creation:
+         | 3D raster register table:... None
+         | Top-bottom resolution min:.. None
+         | Top-bottom resolution max:.. None
          | North-South resolution min:. None
          | North-South resolution max:. None
          | East-west resolution min:... None
@@ -1372,9 +1372,13 @@ class STR3DSMetadata(STDSRasterMetadataBase):
          | Minimum value max:.......... None
          | Maximum value min:.......... None
          | Maximum value max:.......... None
-         | Top-bottom resolution min:.. None
-         | Top-bottom resolution max:.. None
-         | 3D raster register table:... None
+         | Number of registered maps:.. None
+         |
+         | Title:
+         | Soils
+         | Description:
+         | Soils 1950 - 2010
+         | Command history:
         >>> meta.print_shell_info()
         number_of_maps=None
         nsres_min=None
@@ -1388,7 +1392,7 @@ class STR3DSMetadata(STDSRasterMetadataBase):
         tbres_min=None
         tbres_max=None
         raster3d_register=None
-        
+
         @endcode
         """
     def __init__(self, ident=None, raster3d_register=None, title=None, description=None):
@@ -1423,7 +1427,7 @@ class STR3DSMetadata(STDSRasterMetadataBase):
             return None
 
     def get_tbres_max(self):
-        """!Get the maximal top-bottom resolution of all registered maps, 
+        """!Get the maximal top-bottom resolution of all registered maps,
            this value is set in the database
            automatically via SQL, so no setter exists
            @return None if not found"""
@@ -1432,11 +1436,11 @@ class STR3DSMetadata(STDSRasterMetadataBase):
         else:
             return None
 
-    raster3d_register = property(fget=get_raster3d_register, 
+    raster3d_register = property(fget=get_raster3d_register,
                                fset=set_raster3d_register)
     tbres_min = property(fget=get_tbres_min)
     tbres_max = property(fget=get_tbres_max)
-    
+
     def print_info(self):
         """!Print information about this class in human readable style"""
         print " +-------------------- Metadata information ----------------------------------+"
@@ -1459,19 +1463,19 @@ class STR3DSMetadata(STDSRasterMetadataBase):
 
 class STVDSMetadata(STDSMetadataBase):
     """!This is the space time vector dataset metadata class
-        
+
        This class is the interface to the stvds_metadata table in the
-       temporal database that stores the metadata of all registered 
+       temporal database that stores the metadata of all registered
        space time vector datasets
-        
+
        Most of the metadata values are set by SQL scripts in the database when
        new vector maps are added. Therefor only some set- an many get-functions
        are available.
-        
+
         Usage:
-        
+
         @code
-        
+
         >>> init()
         >>> meta = STVDSMetadata(ident="lidars@PERMANENT",
         ... title="LIDARS", description="LIDARS 2008 - 2010")
@@ -1496,12 +1500,6 @@ class STVDSMetadata(STDSMetadataBase):
         >>> meta.number_of_volumes
         >>> meta.print_info()
          +-------------------- Metadata information ----------------------------------+
-         | Number of registered maps:.. None
-         | Title:
-         | LIDARS
-         | Description:
-         | LIDARS 2008 - 2010
-         | Commands of creation:
          | Vector register table:...... None
          | Number of points ........... None
          | Number of lines ............ None
@@ -1515,6 +1513,13 @@ class STVDSMetadata(STDSMetadataBase):
          | Number of islands .......... None
          | Number of holes ............ None
          | Number of volumes .......... None
+         | Number of registered maps:.. None
+         |
+         | Title:
+         | LIDARS
+         | Description:
+         | LIDARS 2008 - 2010
+         | Command history:
         >>> meta.print_shell_info()
         number_of_maps=None
         vector_register=None
@@ -1530,7 +1535,7 @@ class STVDSMetadata(STDSMetadataBase):
         islands=None
         holes=None
         volumes=None
-        
+
         @endcode
     """
     def __init__(
@@ -1552,7 +1557,7 @@ class STVDSMetadata(STDSMetadataBase):
         self.D["islands"] = None
         self.D["holes"] = None
         self.D["volumes"] = None
-        
+
     def set_vector_register(self, vector_register):
         """!Set the vector map register table name"""
         self.D["vector_register"] = vector_register
@@ -1566,7 +1571,7 @@ class STVDSMetadata(STDSMetadataBase):
             return None
 
     def get_number_of_points(self):
-        """!Get the number of points of all registered maps, 
+        """!Get the number of points of all registered maps,
            this value is set in the database
            automatically via SQL, so no setter exists
            @return None if not found"""
@@ -1576,7 +1581,7 @@ class STVDSMetadata(STDSMetadataBase):
             return None
 
     def get_number_of_lines(self):
-        """!Get the number of lines of all registered maps, 
+        """!Get the number of lines of all registered maps,
            this value is set in the database
            automatically via SQL, so no setter exists
            @return None if not found"""
@@ -1586,7 +1591,7 @@ class STVDSMetadata(STDSMetadataBase):
             return None
 
     def get_number_of_boundaries(self):
-        """!Get the number of boundaries of all registered maps, 
+        """!Get the number of boundaries of all registered maps,
            this value is set in the database
            automatically via SQL, so no setter exists
            @return None if not found"""
@@ -1596,7 +1601,7 @@ class STVDSMetadata(STDSMetadataBase):
             return None
 
     def get_number_of_centroids(self):
-        """!Get the number of centroids of all registered maps, 
+        """!Get the number of centroids of all registered maps,
            this value is set in the database
            automatically via SQL, so no setter exists
            @return None if not found"""
@@ -1606,7 +1611,7 @@ class STVDSMetadata(STDSMetadataBase):
             return None
 
     def get_number_of_faces(self):
-        """!Get the number of faces of all registered maps, 
+        """!Get the number of faces of all registered maps,
            this value is set in the database
            automatically via SQL, so no setter exists
            @return None if not found"""
@@ -1616,7 +1621,7 @@ class STVDSMetadata(STDSMetadataBase):
             return None
 
     def get_number_of_kernels(self):
-        """!Get the number of kernels of all registered maps, 
+        """!Get the number of kernels of all registered maps,
            this value is set in the database
            automatically via SQL, so no setter exists
            @return None if not found"""
@@ -1626,7 +1631,7 @@ class STVDSMetadata(STDSMetadataBase):
             return None
 
     def get_number_of_primitives(self):
-        """!Get the number of primitives of all registered maps, 
+        """!Get the number of primitives of all registered maps,
            this value is set in the database
            automatically via SQL, so no setter exists
            @return None if not found"""
@@ -1636,7 +1641,7 @@ class STVDSMetadata(STDSMetadataBase):
             return None
 
     def get_number_of_nodes(self):
-        """!Get the number of nodes of all registered maps, 
+        """!Get the number of nodes of all registered maps,
            this value is set in the database
            automatically via SQL, so no setter exists
            @return None if not found"""
@@ -1646,7 +1651,7 @@ class STVDSMetadata(STDSMetadataBase):
             return None
 
     def get_number_of_areas(self):
-        """!Get the number of areas of all registered maps, 
+        """!Get the number of areas of all registered maps,
            this value is set in the database
            automatically via SQL, so no setter exists
            @return None if not found"""
@@ -1656,7 +1661,7 @@ class STVDSMetadata(STDSMetadataBase):
             return None
 
     def get_number_of_islands(self):
-        """!Get the number of islands of all registered maps, 
+        """!Get the number of islands of all registered maps,
            this value is set in the database
            automatically via SQL, so no setter exists
            @return None if not found"""
@@ -1666,7 +1671,7 @@ class STVDSMetadata(STDSMetadataBase):
             return None
 
     def get_number_of_holes(self):
-        """!Get the number of holes of all registered maps, 
+        """!Get the number of holes of all registered maps,
            this value is set in the database
            automatically via SQL, so no setter exists
            @return None if not found"""
@@ -1676,7 +1681,7 @@ class STVDSMetadata(STDSMetadataBase):
             return None
 
     def get_number_of_volumes(self):
-        """!Get the number of volumes of all registered maps, 
+        """!Get the number of volumes of all registered maps,
            this value is set in the database
            automatically via SQL, so no setter exists
            @return None if not found"""
@@ -1684,7 +1689,7 @@ class STVDSMetadata(STDSMetadataBase):
             return self.D["volumes"]
         else:
             return None
-    
+
     # Set the properties
     vector_register  = property(fget=get_vector_register,
                                 fset=set_vector_register)

File diff suppressed because it is too large
+ 196 - 193
lib/python/temporal/temporal_extent.py