|
@@ -7,11 +7,17 @@ Temporal GIS related functions to be used in temporal GIS Python library package
|
|
|
|
|
|
Usage:
|
|
|
|
|
|
-@code
|
|
|
-import grass.temporal as tgis
|
|
|
-
|
|
|
-...
|
|
|
-@endcode
|
|
|
+>>> import grass.temporal as tgis
|
|
|
+>>> ad = abstract_dataset()
|
|
|
+>>> ad.reset(ident="soil@PERMANENT")
|
|
|
+Traceback (most recent call last):
|
|
|
+ File "/usr/lib/python2.7/doctest.py", line 1289, in __run
|
|
|
+ compileflags, 1) in test.globs
|
|
|
+ File "<doctest __main__[2]>", line 1, in <module>
|
|
|
+ ad.reset(ident="soil@PERMANENT")
|
|
|
+ File "abstract_dataset.py", line 53, in reset
|
|
|
+ raise ImplementationError("This method must be implemented in the subclasses")
|
|
|
+ImplementationError: 'This method must be implemented in the subclasses'
|
|
|
|
|
|
(C) 2008-2011 by the GRASS Development Team
|
|
|
This program is free software under the GNU General Public
|
|
@@ -26,74 +32,84 @@ from temporal_extent import *
|
|
|
from spatial_extent import *
|
|
|
from metadata import *
|
|
|
|
|
|
+
|
|
|
+class ImplementationError(Exception):
|
|
|
+ """!Exception raised for the calling of methods that should be implemented in
|
|
|
+ sub classes.
|
|
|
+ """
|
|
|
+ def __init__(self, msg):
|
|
|
+ self.msg = msg
|
|
|
+ def __str__(self):
|
|
|
+ return repr(self.msg)
|
|
|
+
|
|
|
class abstract_dataset(object):
|
|
|
"""!This is the base class for all datasets (raster, vector, raster3d, strds, stvds, str3ds)"""
|
|
|
|
|
|
def reset(self, ident):
|
|
|
- """!Reset the internal structure and set the identifier
|
|
|
+ """!Reset the internal structure and set the identifier
|
|
|
|
|
|
@param ident: The identifier of the dataset
|
|
|
"""
|
|
|
- raise IOError("This method must be implemented in the subclasses")
|
|
|
+ raise ImplementationError("This method must be implemented in the subclasses")
|
|
|
|
|
|
def get_type(self):
|
|
|
"""!Return the type of this class"""
|
|
|
- raise IOError("This method must be implemented in the subclasses")
|
|
|
-
|
|
|
+ raise ImplementationError("This method must be implemented in the subclasses")
|
|
|
+
|
|
|
def get_new_instance(self, ident):
|
|
|
"""!Return a new instance with the type of this class
|
|
|
|
|
|
@param ident: The identifier of the dataset
|
|
|
"""
|
|
|
- raise IOError("This method must be implemented in the subclasses")
|
|
|
+ raise ImplementationError("This method must be implemented in the subclasses")
|
|
|
|
|
|
def spatial_overlapping(self, dataset):
|
|
|
"""!Return True if the spatial extents are overlapping"""
|
|
|
|
|
|
- raise IOError("This method must be implemented in the subclasses")
|
|
|
+ raise ImplementationError("This method must be implemented in the subclasses")
|
|
|
|
|
|
def spatial_relation(self, dataset):
|
|
|
"""Return the spatial relationship between self and dataset"""
|
|
|
|
|
|
- raise IOError("This method must be implemented in the subclasses")
|
|
|
-
|
|
|
+ raise ImplementationError("This method must be implemented in the subclasses")
|
|
|
+
|
|
|
def print_info(self):
|
|
|
"""!Print information about this class in human readable style"""
|
|
|
- raise IOError("This method must be implemented in the subclasses")
|
|
|
-
|
|
|
+ raise ImplementationError("This method must be implemented in the subclasses")
|
|
|
+
|
|
|
def print_shell_info(self):
|
|
|
"""!Print information about this class in shell style"""
|
|
|
- raise IOError("This method must be implemented in the subclasses")
|
|
|
-
|
|
|
+ raise ImplementationError("This method must be implemented in the subclasses")
|
|
|
+
|
|
|
def print_self(self):
|
|
|
- """!Print the content of the internal structure to stdout"""
|
|
|
- self.base.print_self()
|
|
|
- if self.is_time_absolute():
|
|
|
- self.absolute_time.print_self()
|
|
|
+ """!Print the content of the internal structure to stdout"""
|
|
|
+ self.base.print_self()
|
|
|
+ if self.is_time_absolute():
|
|
|
+ self.absolute_time.print_self()
|
|
|
if self.is_time_relative():
|
|
|
- self.relative_time.print_self()
|
|
|
- self.spatial_extent.print_self()
|
|
|
- self.metadata.print_self()
|
|
|
-
|
|
|
+ self.relative_time.print_self()
|
|
|
+ self.spatial_extent.print_self()
|
|
|
+ self.metadata.print_self()
|
|
|
+
|
|
|
def set_id(self, ident):
|
|
|
- self.base.set_id(ident)
|
|
|
- if self.is_time_absolute():
|
|
|
- self.absolute_time.set_id(ident)
|
|
|
+ self.base.set_id(ident)
|
|
|
+ if self.is_time_absolute():
|
|
|
+ self.absolute_time.set_id(ident)
|
|
|
if self.is_time_relative():
|
|
|
- self.relative_time.set_id(ident)
|
|
|
- self.spatial_extent.set_id(ident)
|
|
|
- self.metadata.set_id(ident)
|
|
|
+ self.relative_time.set_id(ident)
|
|
|
+ self.spatial_extent.set_id(ident)
|
|
|
+ self.metadata.set_id(ident)
|
|
|
|
|
|
def get_id(self):
|
|
|
- """!Return the unique identifier of the dataset"""
|
|
|
+ """!Return the unique identifier of the dataset"""
|
|
|
return self.base.get_id()
|
|
|
|
|
|
def get_name(self):
|
|
|
- """!Return the name"""
|
|
|
+ """!Return the name"""
|
|
|
return self.base.get_name()
|
|
|
|
|
|
def get_mapset(self):
|
|
|
- """!Return the mapset"""
|
|
|
+ """!Return the mapset"""
|
|
|
return self.base.get_mapset()
|
|
|
|
|
|
def get_valid_time(self):
|
|
@@ -103,27 +119,27 @@ class abstract_dataset(object):
|
|
|
|
|
|
start = None
|
|
|
end = None
|
|
|
-
|
|
|
- if self.is_time_absolute():
|
|
|
+
|
|
|
+ if self.is_time_absolute():
|
|
|
start = self.absolute_time.get_start_time()
|
|
|
end = self.absolute_time.get_end_time()
|
|
|
if self.is_time_relative():
|
|
|
start = self.relative_time.get_start_time()
|
|
|
end = self.relative_time.get_end_time()
|
|
|
-
|
|
|
+
|
|
|
return (start, end)
|
|
|
-
|
|
|
+
|
|
|
def get_absolute_time(self):
|
|
|
"""!Returns a tuple of the start, the end valid time and the timezone of the map
|
|
|
@return A tuple of (start_time, end_time, timezone)
|
|
|
"""
|
|
|
-
|
|
|
+
|
|
|
start = self.absolute_time.get_start_time()
|
|
|
end = self.absolute_time.get_end_time()
|
|
|
tz = self.absolute_time.get_timezone()
|
|
|
-
|
|
|
+
|
|
|
return (start, end, tz)
|
|
|
-
|
|
|
+
|
|
|
def get_relative_time(self):
|
|
|
"""!Returns the relative time interval (start_time, end_time, unit) or None if not present"""
|
|
|
|
|
@@ -132,7 +148,7 @@ class abstract_dataset(object):
|
|
|
unit = self.relative_time.get_unit()
|
|
|
|
|
|
return (start, end, unit)
|
|
|
-
|
|
|
+
|
|
|
def get_relative_time_unit(self):
|
|
|
"""!Returns the relative time unit or None if not present"""
|
|
|
|
|
@@ -142,57 +158,49 @@ class abstract_dataset(object):
|
|
|
|
|
|
def check_relative_time_unit(self, unit):
|
|
|
"""!Check if unit is of type years, months, days, hours, minutes or seconds
|
|
|
-
|
|
|
- Return True if success or False otherwise
|
|
|
+
|
|
|
+ Return True if success or False otherwise
|
|
|
"""
|
|
|
# Check unit
|
|
|
- units = ["years","months","days","hours","minutes","seconds"]
|
|
|
+ units = ["years", "months", "days", "hours", "minutes", "seconds"]
|
|
|
if unit not in units:
|
|
|
return False
|
|
|
return True
|
|
|
-
|
|
|
+
|
|
|
def get_temporal_type(self):
|
|
|
"""!Return the temporal type of this dataset"""
|
|
|
return self.base.get_ttype()
|
|
|
-
|
|
|
+
|
|
|
def get_spatial_extent(self):
|
|
|
"""!Return a tuple of spatial extent (north, south, east, west, top, bottom) """
|
|
|
-
|
|
|
- north = self.spatial_extent.get_north()
|
|
|
- south = self.spatial_extent.get_south()
|
|
|
- east = self.spatial_extent.get_east()
|
|
|
- west = self.spatial_extent.get_west()
|
|
|
- top = self.spatial_extent.get_top()
|
|
|
- bottom = self.spatial_extent.get_bottom()
|
|
|
-
|
|
|
- return (north, south, east, west, top, bottom)
|
|
|
-
|
|
|
+ return self.spatial_extent.get_spatial_extent()
|
|
|
+
|
|
|
def select(self, dbif=None):
|
|
|
- """!Select temporal dataset entry from database and fill up the internal structure"""
|
|
|
+ """!Select temporal dataset entry from database and fill up the internal structure"""
|
|
|
|
|
|
dbif, connect = init_dbif(dbif)
|
|
|
|
|
|
- self.base.select(dbif)
|
|
|
- if self.is_time_absolute():
|
|
|
- self.absolute_time.select(dbif)
|
|
|
+ self.base.select(dbif)
|
|
|
+ if self.is_time_absolute():
|
|
|
+ self.absolute_time.select(dbif)
|
|
|
if self.is_time_relative():
|
|
|
- self.relative_time.select(dbif)
|
|
|
- self.spatial_extent.select(dbif)
|
|
|
- self.metadata.select(dbif)
|
|
|
+ self.relative_time.select(dbif)
|
|
|
+ self.spatial_extent.select(dbif)
|
|
|
+ self.metadata.select(dbif)
|
|
|
|
|
|
if connect:
|
|
|
dbif.close()
|
|
|
|
|
|
def is_in_db(self, dbif=None):
|
|
|
"""!Check if the temporal dataset entry is in the database
|
|
|
-
|
|
|
+
|
|
|
@param dbif: The database interface to be used
|
|
|
"""
|
|
|
return self.base.is_in_db(dbif)
|
|
|
|
|
|
def delete(self):
|
|
|
- """!Delete temporal dataset entry from database if it exists"""
|
|
|
- raise IOError("This method must be implemented in the subclasses")
|
|
|
+ """!Delete temporal dataset entry from database if it exists"""
|
|
|
+ raise ImplementationError("This method must be implemented in the subclasses")
|
|
|
|
|
|
def insert(self, dbif=None, execute=True):
|
|
|
"""!Insert temporal dataset entry into database from the internal structure
|
|
@@ -204,20 +212,22 @@ class abstract_dataset(object):
|
|
|
"""
|
|
|
|
|
|
dbif, connect = init_dbif(dbif)
|
|
|
-
|
|
|
+
|
|
|
# Build the INSERT SQL statement
|
|
|
statement = self.base.get_insert_statement_mogrified(dbif)
|
|
|
if self.is_time_absolute():
|
|
|
- statement += self.absolute_time.get_insert_statement_mogrified(dbif)
|
|
|
+ statement += self.absolute_time.get_insert_statement_mogrified(
|
|
|
+ dbif)
|
|
|
if self.is_time_relative():
|
|
|
- statement += self.relative_time.get_insert_statement_mogrified(dbif)
|
|
|
+ statement += self.relative_time.get_insert_statement_mogrified(
|
|
|
+ dbif)
|
|
|
statement += self.spatial_extent.get_insert_statement_mogrified(dbif)
|
|
|
statement += self.metadata.get_insert_statement_mogrified(dbif)
|
|
|
|
|
|
if execute == True:
|
|
|
dbif.execute_transaction(statement)
|
|
|
- if connect:
|
|
|
- dbif.close()
|
|
|
+ if connect:
|
|
|
+ dbif.close()
|
|
|
return ""
|
|
|
|
|
|
if connect:
|
|
@@ -225,59 +235,64 @@ class abstract_dataset(object):
|
|
|
return statement
|
|
|
|
|
|
def update(self, dbif=None, execute=True):
|
|
|
- """!Update temporal dataset entry of database from the internal structure
|
|
|
- excluding None variables
|
|
|
+ """!Update temporal dataset entry of 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.
|
|
|
If False the prepared SQL statements are returned and must be executed by the caller.
|
|
|
- """
|
|
|
+ """
|
|
|
|
|
|
dbif, connect = init_dbif(dbif)
|
|
|
-
|
|
|
+
|
|
|
# Build the UPDATE SQL statement
|
|
|
statement = self.base.get_update_statement_mogrified(dbif)
|
|
|
- if self.is_time_absolute():
|
|
|
- statement += self.absolute_time.get_update_statement_mogrified(dbif)
|
|
|
+ if self.is_time_absolute():
|
|
|
+ statement += self.absolute_time.get_update_statement_mogrified(
|
|
|
+ dbif)
|
|
|
if self.is_time_relative():
|
|
|
- statement += self.relative_time.get_update_statement_mogrified(dbif)
|
|
|
+ statement += self.relative_time.get_update_statement_mogrified(
|
|
|
+ dbif)
|
|
|
statement += self.spatial_extent.get_update_statement_mogrified(dbif)
|
|
|
statement += self.metadata.get_update_statement_mogrified(dbif)
|
|
|
|
|
|
if execute == True:
|
|
|
dbif.execute_transaction(statement)
|
|
|
- if connect:
|
|
|
- dbif.close()
|
|
|
+ if connect:
|
|
|
+ dbif.close()
|
|
|
return ""
|
|
|
|
|
|
if connect:
|
|
|
dbif.close()
|
|
|
return statement
|
|
|
-
|
|
|
+
|
|
|
def update_all(self, dbif=None, execute=True):
|
|
|
- """!Update temporal dataset entry of database from the internal structure
|
|
|
- and include None varuables.
|
|
|
+ """!Update temporal dataset entry of 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.
|
|
|
If False the prepared SQL statements are returned and must be executed by the caller.
|
|
|
- """
|
|
|
+ """
|
|
|
|
|
|
dbif, connect = init_dbif(dbif)
|
|
|
-
|
|
|
+
|
|
|
# Build the UPDATE SQL statement
|
|
|
statement = self.base.get_update_all_statement_mogrified(dbif)
|
|
|
- if self.is_time_absolute():
|
|
|
- statement += self.absolute_time.get_update_all_statement_mogrified(dbif)
|
|
|
+ if self.is_time_absolute():
|
|
|
+ statement += self.absolute_time.get_update_all_statement_mogrified(
|
|
|
+ dbif)
|
|
|
if self.is_time_relative():
|
|
|
- statement += self.relative_time.get_update_all_statement_mogrified(dbif)
|
|
|
- statement += self.spatial_extent.get_update_all_statement_mogrified(dbif)
|
|
|
+ statement += self.relative_time.get_update_all_statement_mogrified(
|
|
|
+ dbif)
|
|
|
+ statement += self.spatial_extent.get_update_all_statement_mogrified(
|
|
|
+ dbif)
|
|
|
statement += self.metadata.get_update_all_statement_mogrified(dbif)
|
|
|
|
|
|
if execute == True:
|
|
|
dbif.execute_transaction(statement)
|
|
|
- if connect:
|
|
|
- dbif.close()
|
|
|
+ if connect:
|
|
|
+ dbif.close()
|
|
|
return ""
|
|
|
|
|
|
if connect:
|
|
@@ -285,107 +300,33 @@ class abstract_dataset(object):
|
|
|
return statement
|
|
|
|
|
|
def set_time_to_absolute(self):
|
|
|
- self.base.set_ttype("absolute")
|
|
|
+ self.base.set_ttype("absolute")
|
|
|
|
|
|
def set_time_to_relative(self):
|
|
|
self.base.set_ttype("relative")
|
|
|
|
|
|
def is_time_absolute(self):
|
|
|
- if self.base.D.has_key("temporal_type"):
|
|
|
- return self.base.get_ttype() == "absolute"
|
|
|
+ if "temporal_type" in self.base.D:
|
|
|
+ return self.base.get_ttype() == "absolute"
|
|
|
else:
|
|
|
- return None
|
|
|
+ return None
|
|
|
|
|
|
def is_time_relative(self):
|
|
|
- if self.base.D.has_key("temporal_type"):
|
|
|
- return self.base.get_ttype() == "relative"
|
|
|
+ if "temporal_type" in self.base.D:
|
|
|
+ return self.base.get_ttype() == "relative"
|
|
|
else:
|
|
|
- return None
|
|
|
+ return None
|
|
|
|
|
|
def temporal_relation(self, map):
|
|
|
- """!Return the temporal relation of this and the provided temporal map"""
|
|
|
- if self.is_time_absolute() and map.is_time_absolute():
|
|
|
- return self.absolute_time.temporal_relation(map.absolute_time)
|
|
|
+ """!Return the temporal relation of this and the provided temporal map"""
|
|
|
+ if self.is_time_absolute() and map.is_time_absolute():
|
|
|
+ return self.absolute_time.temporal_relation(map.absolute_time)
|
|
|
if self.is_time_relative() and map.is_time_relative():
|
|
|
- return self.relative_time.temporal_relation(map.relative_time)
|
|
|
- return None
|
|
|
+ return self.relative_time.temporal_relation(map.relative_time)
|
|
|
+ return None
|
|
|
|
|
|
###############################################################################
|
|
|
-
|
|
|
-class abstract_dataset_comparison_key_start_time(object):
|
|
|
- """!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()
|
|
|
-
|
|
|
- # Sort the maps in the list by start time
|
|
|
- sorted_map_list = sorted(map_list, key=abstract_dataset_comparison_key_start_time)
|
|
|
- """
|
|
|
- def __init__(self, obj, *args):
|
|
|
- self.obj = obj
|
|
|
- def __lt__(self, other):
|
|
|
- startA, endA = self.obj.get_valid_time()
|
|
|
- startB, endB = other.obj.get_valid_time()
|
|
|
- return startA < startB
|
|
|
- def __gt__(self, other):
|
|
|
- startA, endA = self.obj.get_valid_time()
|
|
|
- startB, endB = other.obj.get_valid_time()
|
|
|
- return startA > startB
|
|
|
- def __eq__(self, other):
|
|
|
- startA, endA = self.obj.get_valid_time()
|
|
|
- startB, endB = other.obj.get_valid_time()
|
|
|
- return startA == startB
|
|
|
- def __le__(self, other):
|
|
|
- startA, endA = self.obj.get_valid_time()
|
|
|
- startB, endB = other.obj.get_valid_time()
|
|
|
- return startA <= startB
|
|
|
- def __ge__(self, other):
|
|
|
- startA, endA = self.obj.get_valid_time()
|
|
|
- startB, endB = other.obj.get_valid_time()
|
|
|
- return startA >= startB
|
|
|
- def __ne__(self, other):
|
|
|
- startA, endA = self.obj.get_valid_time()
|
|
|
- startB, endB = other.obj.get_valid_time()
|
|
|
- return startA != startB
|
|
|
-
|
|
|
-###############################################################################
|
|
|
-
|
|
|
-class abstract_dataset_comparison_key_end_time(object):
|
|
|
- """!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()
|
|
|
-
|
|
|
- # Sort the maps in the list by end time
|
|
|
- sorted_map_list = sorted(map_list, key=abstract_dataset_comparison_key_end_time)
|
|
|
- """
|
|
|
- def __init__(self, obj, *args):
|
|
|
- self.obj = obj
|
|
|
- def __lt__(self, other):
|
|
|
- startA, endA = self.obj.get_valid_time()
|
|
|
- startB, endB = other.obj.get_valid_time()
|
|
|
- return endA < endB
|
|
|
- def __gt__(self, other):
|
|
|
- startA, endA = self.obj.get_valid_time()
|
|
|
- startB, endB = other.obj.get_valid_time()
|
|
|
- return endA > endB
|
|
|
- def __eq__(self, other):
|
|
|
- startA, endA = self.obj.get_valid_time()
|
|
|
- startB, endB = other.obj.get_valid_time()
|
|
|
- return endA == endB
|
|
|
- def __le__(self, other):
|
|
|
- startA, endA = self.obj.get_valid_time()
|
|
|
- startB, endB = other.obj.get_valid_time()
|
|
|
- return endA <= endB
|
|
|
- def __ge__(self, other):
|
|
|
- startA, endA = self.obj.get_valid_time()
|
|
|
- startB, endB = other.obj.get_valid_time()
|
|
|
- return endA >= endB
|
|
|
- def __ne__(self, other):
|
|
|
- startA, endA = self.obj.get_valid_time()
|
|
|
- startB, endB = other.obj.get_valid_time()
|
|
|
- return endA != endB
|
|
|
+
|
|
|
+if __name__ == "__main__":
|
|
|
+ import doctest
|
|
|
+ doctest.testmod()
|