[GRASS-SVN] r57598 - grass/trunk/lib/python/temporal
svn_grass at osgeo.org
svn_grass at osgeo.org
Thu Sep 5 06:57:43 PDT 2013
Author: huhabla
Date: 2013-09-05 06:57:42 -0700 (Thu, 05 Sep 2013)
New Revision: 57598
Modified:
grass/trunk/lib/python/temporal/abstract_space_time_dataset.py
grass/trunk/lib/python/temporal/base.py
grass/trunk/lib/python/temporal/core.py
grass/trunk/lib/python/temporal/datetime_math.py
grass/trunk/lib/python/temporal/sampling.py
grass/trunk/lib/python/temporal/spatio_temporal_relationships.py
Log:
Enabled deepcopy of map and space time datasets.
Fixed some topology builder issues. Implemented a fast sample method
that makes use of the topology builder.
Modified: grass/trunk/lib/python/temporal/abstract_space_time_dataset.py
===================================================================
--- grass/trunk/lib/python/temporal/abstract_space_time_dataset.py 2013-09-05 13:51:57 UTC (rev 57597)
+++ grass/trunk/lib/python/temporal/abstract_space_time_dataset.py 2013-09-05 13:57:42 UTC (rev 57598)
@@ -484,6 +484,219 @@
"""!Sample this space time dataset with the temporal topology
of a second space time dataset
+ In case spatial is True, the spatial overlap between
+ temporal related maps is performed. Only
+ temporal related and spatial overlapping maps are returned.
+
+ Return all registered maps as ordered (by start_time) object list.
+ Each list entry is a list of map
+ objects which are potentially located in temporal relation to the
+ actual granule of the second space time dataset.
+
+ Each entry in the object list is a dict. The actual sampler
+ map and its temporal extent (the actual granule) and
+ the list of samples are stored:
+
+ @code
+ list = self.sample_by_dataset(stds=sampler, method=[
+ "during","overlap","contains","equal"])
+ for entry in list:
+ granule = entry["granule"]
+ maplist = entry["samples"]
+ for map in maplist:
+ map.select()
+ map.print_info()
+ @endcode
+
+ A valid temporal topology (no overlapping or inclusion allowed)
+ is needed to get correct results in case of gaps in the sample
+ dataset.
+
+ Gaps between maps are identified as unregistered maps with id==None.
+
+ The objects are initialized with their id's' and the spatio-temporal
+ extent (temporal type, start time, end time, west, east, south,
+ north, bottom and top).
+ In case more map information are needed, use the select()
+ method for each listed object.
+
+ @param stds The space time dataset to be used for temporal sampling
+ @param method This option specifies what sample method should be
+ used. In case the registered maps are of temporal
+ point type, only the start time is used for sampling.
+ In case of mixed of interval data the user can chose
+ between:
+
+ - Example @code ["start", "during", "equals"] @endcode
+
+ - start: Select maps of which the start time is
+ located in the selection granule
+ @verbatim
+ map : s
+ granule: s-----------------e
+
+ map : s--------------------e
+ granule: s-----------------e
+
+ map : s--------e
+ granule: s-----------------e
+ @endverbatim
+
+ - contains: Select maps which are temporal
+ during the selection granule
+ @verbatim
+ map : s-----------e
+ granule: s-----------------e
+ @endverbatim
+
+ - overlap: Select maps which temporal overlap
+ the selection granule, this includes overlaps and overlapped
+ @verbatim
+ map : s-----------e
+ granule: s-----------------e
+
+ map : s-----------e
+ granule: s----------e
+ @endverbatim
+
+ - during: Select maps which temporally contains
+ the selection granule
+ @verbatim
+ map : s-----------------e
+ granule: s-----------e
+ @endverbatim
+
+ - equals: Select maps which temporally equal
+ to the selection granule
+ @verbatim
+ map : s-----------e
+ granule: s-----------e
+ @endverbatim
+
+ - follows: Select maps which temporally follow
+ the selection granule
+ @verbatim
+ map : s-----------e
+ granule: s-----------e
+ @endverbatim
+
+ - precedes: Select maps which temporally precedes
+ the selection granule
+ @verbatim
+ map : s-----------e
+ granule: s-----------e
+ @endverbatim
+
+ All these methods can be combined. Method must be of
+ type tuple including the identification strings.
+
+ @param spatial If set True additional the 2d spatial overlapping
+ is used for selection -> spatio-temporal relation.
+ The returned map objects will have temporal and
+ spatial extents
+ @param dbif The database interface to be used
+
+ @return A list of lists of map objects or None in case nothing was
+ found None
+ """
+
+ if self.get_temporal_type() != stds.get_temporal_type():
+ core.error(_("The space time datasets must be of "
+ "the same temporal type"))
+ return None
+
+ if stds.get_map_time() != "interval":
+ core.error(_("The temporal map type of the sample "
+ "dataset must be interval"))
+ return None
+
+ dbif, connected = init_dbif(dbif)
+ relations = copy.deepcopy(method)
+
+ # Tune the temporal relations
+ if "start" in relations:
+ if "overlapped" not in relations:
+ relations.append("overlapped")
+ if "starts" not in relations:
+ relations.append("starts")
+ if "started" not in relations:
+ relations.append("started")
+ if "finishes" not in relations:
+ relations.append("finishes")
+ if "contains" not in relations:
+ relations.append("contains")
+ if "equals" not in relations:
+ relations.append("equals")
+
+ if "overlap" in relations or "over" in relations:
+ if "overlapped" not in relations:
+ relations.append("overlapped")
+ if "overlaps" not in relations:
+ relations.append("overlaps")
+
+ if "contain" in relations:
+ if "contains" not in relations:
+ relations.append("contains")
+
+ # Remove start, equal, contain and overlap
+ relations = [relation.upper().strip() for relation in relations if relation \
+ not in ["start", "overlap", "contain"]]
+
+ #print(relations)
+
+ tb = SpatioTemporalTopologyBuilder()
+ if spatial:
+ spatial = "2D"
+ else:
+ spatial = None
+
+ mapsA = self.get_registered_maps_as_objects(dbif=dbif)
+ mapsB = stds.get_registered_maps_as_objects_with_gaps(dbif=dbif)
+ tb.build(mapsB, mapsA, spatial)
+
+ obj_list = []
+ for map in mapsB:
+ result = {}
+ maplist = []
+ # Get map relations
+ map_relations = map.get_temporal_relations()
+ #print(map.get_temporal_extent_as_tuple())
+ #for key in map_relations.keys():
+ # if key not in ["NEXT", "PREV"]:
+ # print(key, map_relations[key][0].get_temporal_extent_as_tuple())
+
+ result["granule"] = map
+ # Append the maps that fullfill the relations
+ for relation in relations:
+ if relation in map_relations.keys():
+ for sample_map in map_relations[relation]:
+ if sample_map not in maplist:
+ maplist.append(sample_map)
+
+ # Add an empty map if no map was found
+ if not maplist:
+ empty_map = self.get_new_map_instance(None)
+ empty_map.set_spatial_extent(map.get_spatial_extent())
+ empty_map.set_temporal_extent(map.get_temporal_extent())
+ maplist.append(empty_map)
+
+ result["samples"] = maplist
+
+ obj_list.append(result)
+
+ if connected:
+ dbif.close()
+
+ return obj_list
+
+
+ def sample_by_dataset_sql(self, stds, method=None, spatial=False, dbif=None):
+ """!Sample this space time dataset with the temporal topology
+ of a second space time dataset using SQL queries.
+
+ This function is very slow for huge large space time datasets
+ but can run several times in the same process without problems.
+
The sample dataset must have "interval" as temporal map type,
so all sample maps have valid interval time.
@@ -529,6 +742,7 @@
point type, only the start time is used for sampling.
In case of mixed of interval data the user can chose
between:
+ - ["start", "during", "equals"]
- start: Select maps of which the start time is
located in the selection granule
@@ -543,15 +757,15 @@
granule: s-----------------e
@endverbatim
- - during: Select maps which are temporal
- during the selection granule
+ - contains: Select maps which are temporal
+ during the selection granule
@verbatim
map : s-----------e
granule: s-----------------e
@endverbatim
- overlap: Select maps which temporal overlap
- the selection granule
+ the selection granule, this includes overlaps and overlapped
@verbatim
map : s-----------e
granule: s-----------------e
@@ -560,14 +774,14 @@
granule: s----------e
@endverbatim
- - contain: Select maps which temporally contain
- the selection granule
+ - during: Select maps which temporally contains
+ the selection granule
@verbatim
map : s-----------------e
granule: s-----------e
@endverbatim
- - equal: Select maps which temporally equal
+ - equals: Select maps which temporally equal
to the selection granule
@verbatim
map : s-----------e
@@ -591,7 +805,7 @@
All these methods can be combined. Method must be of
type tuple including the identification strings.
- @param spatial If set True additional the spatial overlapping
+ @param spatial If set True additional the 2d spatial overlapping
is used for selection -> spatio-temporal relation.
The returned map objects will have temporal and
spatial extents
@@ -618,9 +832,9 @@
use_during = True
if name == "overlap":
use_overlap = True
- if name == "contain":
+ if name == "contain" or name == "contains":
use_contain = True
- if name == "equal":
+ if name == "equal" or name == "equals":
use_equal = True
if name == "follows":
use_follows = True
@@ -916,6 +1130,7 @@
next = start + gran
map = first.get_new_instance(None)
+ map.set_spatial_extent_from_values(0,0,0,0,0,0)
if first.is_time_absolute():
map.set_absolute_time(start, next, None)
else:
@@ -1009,6 +1224,7 @@
elif self.is_time_relative():
map.set_relative_time(start, end,
self.get_relative_time_unit())
+ map.set_spatial_extent_from_values(0,0,0,0,0,0)
obj_list.append(copy.copy(map))
if connected:
@@ -1076,24 +1292,25 @@
# Older temporal databases have no bottom and top columns
# in their views so we need a work around to set the full
# spatial extent as well
- has_bt_columns = True
- try:
- rows = self.get_registered_maps(
- "id,start_time,end_time, west,east,south,north,bottom,top",
- where, order, dbif)
- except:
- try:
- dbif.rollback()
- rows = self.get_registered_maps("id,start_time,end_time",
- where, order, dbif)
- has_bt_columns = False
- core.warning(_("Old temporal database format detected. "
- "The top and "
- "bottom column is missing in the views, using"
- "a work around."))
- except:
- raise
+ rows = get_tgis_metadata(dbif)
+ db_version = 0
+
+ if rows:
+ for row in rows:
+ if row["key"] == "tgis_db_version":
+ db_version = int(row["value"])
+
+ if db_version >= 1:
+ has_bt_columns = True
+ columns = "id,start_time,end_time, west,east,south,north,bottom,top"
+ else:
+ has_bt_columns = False
+ columns = "id,start_time,end_time, west,east,south,north"
+
+ rows = self.get_registered_maps(columns, where, order, dbif)
+
+
if rows is not None:
for row in rows:
map = self.get_new_map_instance(row["id"])
Modified: grass/trunk/lib/python/temporal/base.py
===================================================================
--- grass/trunk/lib/python/temporal/base.py 2013-09-05 13:51:57 UTC (rev 57597)
+++ grass/trunk/lib/python/temporal/base.py 2013-09-05 13:57:42 UTC (rev 57598)
@@ -5,8 +5,8 @@
Temporal GIS base classes to be used in other
Python temporal gis packages.
-This packages includes all base classes to store basic information
-like id, name, mapset creation and modification time as well as sql
+This packages includes all base classes to store basic information
+like id, name, mapset creation and modification time as well as sql
serialization and de-serialization and the sql database interface.
Usage:
@@ -41,15 +41,14 @@
class DictSQLSerializer(object):
def __init__(self):
self.D = {}
- self.dbif = SQLDatabaseInterfaceConnection()
def serialize(self, type, table, where=None):
- """!Convert the internal dictionary into a string of semicolon
- separated SQL statements The keys are the column names and
+ """!Convert the internal dictionary into a string of semicolon
+ separated SQL statements The keys are the column names and
the values are the row entries
-
+
Usage:
-
+
\code
>>> init()
>>> t = DictSQLSerializer()
@@ -67,15 +66,17 @@
('UPDATE raster_base SET name = ? ,creator = ? ,creation_time = ? ,modification_time = ? ,mapset = ? ,id = ? ;\\n', ('soil', 'soeren', datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2001, 1, 1, 0, 0), 'PERMANENT', 'soil at PERMANENT'))
>>> t.serialize(type="UPDATE ALL", table="raster_base")
('UPDATE raster_base SET name = ? ,creator = ? ,creation_time = ? ,modification_time = ? ,mapset = ? ,id = ? ;\\n', ('soil', 'soeren', datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2001, 1, 1, 0, 0), 'PERMANENT', 'soil at PERMANENT'))
-
+
@param type must be SELECT. INSERT, UPDATE
@param table The name of the table to select, insert or update
@param where The optional where statement
@return a tuple containing the SQL string and the arguments
-
+
\endcode
"""
+ dbif = SQLDatabaseInterfaceConnection()
+
sql = ""
args = []
@@ -109,12 +110,12 @@
sql += ') VALUES ('
for key in self.D.keys():
if count == 0:
- if self.dbif.dbmi.paramstyle == "qmark":
+ if dbif.dbmi.paramstyle == "qmark":
sql += '?'
else:
sql += '%s'
else:
- if self.dbif.dbmi.paramstyle == "qmark":
+ if dbif.dbmi.paramstyle == "qmark":
sql += ' ,?'
else:
sql += ' ,%s'
@@ -134,13 +135,13 @@
# Update only entries which are not None
if self.D[key] is not None:
if count == 0:
- if self.dbif.dbmi.paramstyle == "qmark":
+ if dbif.dbmi.paramstyle == "qmark":
sql += ' %s = ? ' % key
else:
sql += ' %s ' % key
sql += '= %s '
else:
- if self.dbif.dbmi.paramstyle == "qmark":
+ if dbif.dbmi.paramstyle == "qmark":
sql += ' ,%s = ? ' % key
else:
sql += ' ,%s ' % key
@@ -157,13 +158,13 @@
sql += 'UPDATE ' + table + ' SET '
for key in self.D.keys():
if count == 0:
- if self.dbif.dbmi.paramstyle == "qmark":
+ if dbif.dbmi.paramstyle == "qmark":
sql += ' %s = ? ' % key
else:
sql += ' %s ' % key
sql += '= %s '
else:
- if self.dbif.dbmi.paramstyle == "qmark":
+ if dbif.dbmi.paramstyle == "qmark":
sql += ' ,%s = ? ' % key
else:
sql += ' ,%s ' % key
@@ -177,7 +178,7 @@
return sql, tuple(args)
def deserialize(self, row):
- """!Convert the content of the dbmi dictionary like row into the
+ """!Convert the content of the dbmi dictionary like row into the
internal dictionary
@param row The dictionary like row to store in the internal dict
@@ -200,19 +201,19 @@
class SQLDatabaseInterface(DictSQLSerializer):
"""!This class represents the SQL database interface
- Functions to insert, select and update the internal
+ Functions to insert, select and update the internal
structure of this class in the temporal database are implemented.
- This is the base class for raster, raster3d, vector and
+ This is the base class for raster, raster3d, vector and
space time datasets data management classes:
- Identification information (base)
- Spatial extent
- Temporal extent
- Metadata
-
+
Usage:
-
+
\code
-
+
>>> init()
>>> t = SQLDatabaseInterface("raster", "soil at PERMANENT")
>>> t.D["name"] = "soil"
@@ -239,14 +240,14 @@
("UPDATE raster SET creation_time = ? ,mapset = ? ,name = ? ,creator = ? WHERE id = 'soil at PERMANENT';\\n", (datetime.datetime(2001, 1, 1, 0, 0), 'PERMANENT', 'soil', 'soeren'))
>>> t.get_update_all_statement_mogrified()
"UPDATE raster SET creation_time = '2001-01-01 00:00:00' ,mapset = 'PERMANENT' ,name = 'soil' ,creator = 'soeren' WHERE id = 'soil at PERMANENT';\\n"
-
+
\endcode
"""
def __init__(self, table=None, ident=None):
"""!Constructor of this class
@param table The name of the table
- @param ident The identifier (primary key) of this
+ @param ident The identifier (primary key) of this
object in the database table
"""
DictSQLSerializer.__init__(self)
@@ -255,7 +256,7 @@
self.ident = ident
def get_table_name(self):
- """!Return the name of the table in which the internal
+ """!Return the name of the table in which the internal
data are inserted, updated or selected
@return The name of the table
"""
@@ -271,7 +272,7 @@
def delete(self, dbif=None):
"""!Delete the entry of this object from the temporal database
- @param dbif The database interface to be used,
+ @param dbif The database interface to be used,
if None a temporary connection will be established
"""
sql = self.get_delete_statement()
@@ -296,7 +297,7 @@
def is_in_db(self, dbif=None):
"""!Check if this object is present in the temporal database
- @param dbif The database interface to be used,
+ @param dbif The database interface to be used,
if None a temporary connection will be established
@return True if this object is present in the temporal database, False otherwise
"""
@@ -321,17 +322,17 @@
return True
def get_select_statement(self):
- """!Return the sql statement and the argument list in
+ """!Return the sql statement and the argument list in
database specific style
@return The SELECT string
"""
- return self.serialize("SELECT", self.get_table_name(),
+ return self.serialize("SELECT", self.get_table_name(),
"WHERE id = \'" + str(self.ident) + "\'")
def get_select_statement_mogrified(self, dbif=None):
"""!Return the select statement as mogrified string
- @param dbif The database interface to be used,
+ @param dbif The database interface to be used,
if None a temporary connection will be established
@return The SELECT string
"""
@@ -344,7 +345,7 @@
"""!Select the content from the temporal database and store it
in the internal dictionary structure
- @param dbif The database interface to be used,
+ @param dbif The database interface to be used,
if None a temporary connection will be established
"""
sql, args = self.get_select_statement()
@@ -380,7 +381,7 @@
return True
def get_insert_statement(self):
- """!Return the sql statement and the argument
+ """!Return the sql statement and the argument
list in database specific style
@return The INSERT string"""
return self.serialize("INSERT", self.get_table_name())
@@ -388,7 +389,7 @@
def get_insert_statement_mogrified(self, dbif=None):
"""!Return the insert statement as mogrified string
- @param dbif The database interface to be used,
+ @param dbif The database interface to be used,
if None a temporary connection will be established
@return The INSERT string
"""
@@ -401,7 +402,7 @@
"""!Serialize the content of this object and store it in the temporal
database using the internal identifier
- @param dbif The database interface to be used,
+ @param dbif The database interface to be used,
if None a temporary connection will be established
"""
sql, args = self.get_insert_statement()
@@ -417,24 +418,24 @@
dbif.close()
def get_update_statement(self, ident=None):
- """!Return the sql statement and the argument list
+ """!Return the sql statement and the argument list
in database specific style
-
+
@param ident The identifier to be updated, useful for renaming
@return The UPDATE string
-
+
"""
if ident:
- return self.serialize("UPDATE", self.get_table_name(),
+ return self.serialize("UPDATE", self.get_table_name(),
"WHERE id = \'" + str(ident) + "\'")
else:
- return self.serialize("UPDATE", self.get_table_name(),
+ return self.serialize("UPDATE", self.get_table_name(),
"WHERE id = \'" + str(self.ident) + "\'")
def get_update_statement_mogrified(self, dbif=None, ident=None):
"""!Return the update statement as mogrified string
- @param dbif The database interface to be used,
+ @param dbif The database interface to be used,
if None a temporary connection will be established
@param ident The identifier to be updated, useful for renaming
@return The UPDATE string
@@ -450,7 +451,7 @@
Only object entries which are exists (not None) are updated
- @param dbif The database interface to be used,
+ @param dbif The database interface to be used,
if None a temporary connection will be established
@param ident The identifier to be updated, useful for renaming
"""
@@ -470,23 +471,23 @@
dbif.close()
def get_update_all_statement(self, ident=None):
- """!Return the sql statement and the argument
+ """!Return the sql statement and the argument
list in database specific style
-
+
@param ident The identifier to be updated, useful for renaming
@return The UPDATE string
"""
if ident:
- return self.serialize("UPDATE ALL", self.get_table_name(),
+ return self.serialize("UPDATE ALL", self.get_table_name(),
"WHERE id = \'" + str(ident) + "\'")
else:
- return self.serialize("UPDATE ALL", self.get_table_name(),
+ return self.serialize("UPDATE ALL", self.get_table_name(),
"WHERE id = \'" + str(self.ident) + "\'")
def get_update_all_statement_mogrified(self, dbif=None, ident=None):
"""!Return the update all statement as mogrified string
- @param dbif The database interface to be used,
+ @param dbif The database interface to be used,
if None a temporary connection will be established
@param ident The identifier to be updated, useful for renaming
@return The UPDATE string
@@ -497,10 +498,10 @@
return dbif.mogrify_sql_statement(self.get_update_all_statement(ident))
def update_all(self, dbif=None, ident=None):
- """!Serialize the content of this object, including None objects,
+ """!Serialize the content of this object, including None objects,
and update it in the temporal database using the internal identifier
- @param dbif The database interface to be used,
+ @param dbif The database interface to be used,
if None a temporary connection will be established
@param ident The identifier to be updated, useful for renaming
"""
@@ -523,11 +524,11 @@
class DatasetBase(SQLDatabaseInterface):
- """!This is the base class for all maps and spacetime datasets storing
+ """!This is the base class for all maps and spacetime datasets storing
basic identification information
-
+
Usage:
-
+
\code
>>> init()
@@ -559,22 +560,22 @@
creator=soeren
creation_time=2001-01-01 00:00:00
temporal_type=absolute
-
+
\endcode
"""
-
- def __init__(self, table=None, ident=None, name=None, mapset=None,
+
+ def __init__(self, table=None, ident=None, name=None, mapset=None,
creator=None, ctime=None,ttype=None):
"""!Constructor
-
- @param table The name of the temporal database table
+
+ @param table The name of the temporal database table
that should be used to store the values
- @param ident The unique identifier must be a combination of
- the dataset name, layer name and the mapset
+ @param ident The unique identifier must be a combination of
+ the dataset name, layer name and the mapset
"name at mapset" or "name:layer at mapset"
used as as primary key in the temporal database
@param name The name of the map or dataset
- @param mapset The name of the mapset
+ @param mapset The name of the mapset
@param creator The name of the creator
@param ctime The creation datetime object
@param ttype The temporal type
@@ -602,8 +603,8 @@
def set_id(self, ident):
"""!Convenient method to set the unique identifier (primary key)
- @param ident The unique identifier must be a combination
- of the dataset name, layer name and the mapset
+ @param ident The unique identifier must be a combination
+ of the dataset name, layer name and the mapset
"name at mapset" or "name:layer at mapset"
"""
self.ident = ident
@@ -653,7 +654,7 @@
self.D["creator"] = creator
def set_ctime(self, ctime=None):
- """!Set the creation time of the dataset,
+ """!Set the creation time of the dataset,
if nothing set the current time is used
@param ctime The current time of type datetime
@@ -664,7 +665,7 @@
self.D["creation_time"] = ctime
def set_ttype(self, ttype):
- """!Set the temporal type of the dataset: absolute or relative,
+ """!Set the temporal type of the dataset: absolute or relative,
if nothing set absolute time will assumed
@param ttype The temporal type of the dataset "absolute or relative"
@@ -696,7 +697,7 @@
return None
def get_map_id(self):
- """!Convenient method to get the unique map identifier
+ """!Convenient method to get the unique map identifier
without layer information
@return the name of the vector map as "name at mapset"
@@ -822,24 +823,24 @@
class RasterBase(DatasetBase):
"""!Time stamped raster map base information class"""
- def __init__(self, ident=None, name=None, mapset=None, creator=None,
+ def __init__(self, ident=None, name=None, mapset=None, creator=None,
creation_time=None, temporal_type=None):
- DatasetBase.__init__(self, "raster_base", ident, name, mapset,
+ DatasetBase.__init__(self, "raster_base", ident, name, mapset,
creator, creation_time, temporal_type)
class Raster3DBase(DatasetBase):
"""!Time stamped 3D raster map base information class"""
- def __init__(self, ident=None, name=None, mapset=None, creator=None,
+ def __init__(self, ident=None, name=None, mapset=None, creator=None,
creation_time=None, temporal_type=None,):
- DatasetBase.__init__(self, "raster3d_base", ident, name,
- mapset, creator, creation_time,
+ DatasetBase.__init__(self, "raster3d_base", ident, name,
+ mapset, creator, creation_time,
temporal_type)
class VectorBase(DatasetBase):
"""!Time stamped vector map base information class"""
- def __init__(self, ident=None, name=None, mapset=None, layer=None,
+ def __init__(self, ident=None, name=None, mapset=None, layer=None,
creator=None, creation_time=None, temporal_type=None):
DatasetBase.__init__(self, "vector_base", ident, name, mapset,
creator, creation_time, temporal_type)
@@ -861,14 +862,14 @@
class STDSBase(DatasetBase):
"""!Base class for space time datasets
-
- This class adds the semantic type member variable to the dataset
+
+ This class adds the semantic type member variable to the dataset
base class.
-
+
Usage:
\code
-
+
>>> init()
>>> t = STDSBase("stds", "soil at PERMANENT", semantic_type="average", creator="soeren", ctime=datetime(2001,1,1), ttype="absolute")
>>> t.semantic_type
@@ -890,10 +891,10 @@
creation_time=2001-01-01 00:00:00
temporal_type=absolute
semantic_type=average
-
+
\endcode
"""
- def __init__(self, table=None, ident=None, name=None, mapset=None,
+ def __init__(self, table=None, ident=None, name=None, mapset=None,
semantic_type=None, creator=None, ctime=None,
ttype=None):
DatasetBase.__init__(self, table, ident, name, mapset, creator,
@@ -914,7 +915,7 @@
return None
semantic_type = property(fget=get_semantic_type, fset=set_semantic_type)
-
+
def print_info(self):
"""!Print information about this class in human readable style"""
DatasetBase.print_info(self)
@@ -932,30 +933,30 @@
class STRDSBase(STDSBase):
"""!Space time raster dataset base information class"""
- def __init__(self, ident=None, name=None, mapset=None,
+ def __init__(self, ident=None, name=None, mapset=None,
semantic_type=None, creator=None, ctime=None,
ttype=None):
- STDSBase.__init__(self, "strds_base", ident, name, mapset,
+ STDSBase.__init__(self, "strds_base", ident, name, mapset,
semantic_type, creator, ctime,
ttype)
class STR3DSBase(STDSBase):
"""!Space time 3D raster dataset base information class"""
- def __init__(self, ident=None, name=None, mapset=None,
+ def __init__(self, ident=None, name=None, mapset=None,
semantic_type=None, creator=None, ctime=None,
ttype=None):
- STDSBase.__init__(self, "str3ds_base", ident, name, mapset,
+ STDSBase.__init__(self, "str3ds_base", ident, name, mapset,
semantic_type, creator, ctime,
ttype)
class STVDSBase(STDSBase):
"""!Space time vector dataset base information class"""
- def __init__(self, ident=None, name=None, mapset=None,
+ def __init__(self, ident=None, name=None, mapset=None,
semantic_type=None, creator=None, ctime=None,
ttype=None):
- STDSBase.__init__(self, "stvds_base", ident, name, mapset,
+ STDSBase.__init__(self, "stvds_base", ident, name, mapset,
semantic_type, creator, ctime,
ttype)
Modified: grass/trunk/lib/python/temporal/core.py
===================================================================
--- grass/trunk/lib/python/temporal/core.py 2013-09-05 13:51:57 UTC (rev 57597)
+++ grass/trunk/lib/python/temporal/core.py 2013-09-05 13:57:42 UTC (rev 57598)
@@ -408,6 +408,7 @@
class SQLDatabaseInterfaceConnection():
"""!This class represents the database interface connection
+ and provides access to the chisen backend modules.
The following DBMS are supported:
- sqlite via the sqlite3 standard library
Modified: grass/trunk/lib/python/temporal/datetime_math.py
===================================================================
--- grass/trunk/lib/python/temporal/datetime_math.py 2013-09-05 13:51:57 UTC (rev 57597)
+++ grass/trunk/lib/python/temporal/datetime_math.py 2013-09-05 13:57:42 UTC (rev 57598)
@@ -20,7 +20,6 @@
###############################################################################
-
def relative_time_to_time_delta(value):
"""!Convert the double value representing days
into a timedelta object.
Modified: grass/trunk/lib/python/temporal/sampling.py
===================================================================
--- grass/trunk/lib/python/temporal/sampling.py 2013-09-05 13:51:57 UTC (rev 57597)
+++ grass/trunk/lib/python/temporal/sampling.py 2013-09-05 13:57:42 UTC (rev 57598)
@@ -25,19 +25,18 @@
from space_time_datasets import *
from factory import *
-###############################################################################
-def sample_stds_by_stds_topology(intype, sampletype, inputs, sampler, header,
- separator, method, spatial=False,
+def sample_stds_by_stds_topology(intype, sampletype, inputs, sampler, header,
+ separator, method, spatial=False,
print_only=True):
- """!Sample the input space time datasets with a sample
- space time dataset, return the created map matrix and optionally
+ """!Sample the input space time datasets with a sample
+ space time dataset, return the created map matrix and optionally
print the result to stdout
- In case multiple maps are located in the current granule,
+ In case multiple maps are located in the current granule,
the map names are separated by comma.
- In case a layer is present, the names map ids are extended
+ In case a layer is present, the names map ids are extended
in this form: "name:layer at mapset"
Attention: Do not use the comma as separator for printing
@@ -48,13 +47,13 @@
@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
+ @param method The method to be used for temporal sampling
(start,during,contain,overlap,equal)
@param spatial Perform spatial overlapping check
- @param print_only If set True (default) then the result of the sampling will be
- printed to stdout, if set to False the resulting map matrix
- will be returned.
-
+ @param print_only If set True (default) then the result of the sampling will be
+ printed to stdout, if set to False the resulting map matrix
+ will be returned.
+
@return The map matrix or None if nothing found
"""
mapset = core.gisenv()["MAPSET"]
@@ -105,7 +104,7 @@
mapmatrizes.append(mapmatrix)
if len(mapmatrizes) > 0:
-
+
# Simply return the map matrix
if not print_only:
dbif.close()
@@ -166,5 +165,5 @@
dbif.close()
if len(mapmatrizes) > 0:
return mapmatrizes
-
+
return None
Modified: grass/trunk/lib/python/temporal/spatio_temporal_relationships.py
===================================================================
--- grass/trunk/lib/python/temporal/spatio_temporal_relationships.py 2013-09-05 13:51:57 UTC (rev 57597)
+++ grass/trunk/lib/python/temporal/spatio_temporal_relationships.py 2013-09-05 13:57:42 UTC (rev 57598)
@@ -320,6 +320,42 @@
('OVERLAPPED', (datetime.datetime(2000, 1, 1, 0, 0, 2), datetime.datetime(2000, 1, 1, 0, 0, 4)))
('EQUAL', (datetime.datetime(2000, 1, 1, 0, 0, 3), datetime.datetime(2000, 1, 1, 0, 0, 5)))
+ >>> mapsA = []
+ >>> for i in range(4):
+ ... idA = "a%i at B"%(i)
+ ... mapA = tgis.RasterDataset(idA)
+ ... start = datetime.datetime(2000, 1, 1, 0, 0, i)
+ ... end = datetime.datetime(2000, 1, 1, 0, 0, i + 2)
+ ... check = mapA.set_absolute_time(start, end)
+ ... mapsA.append(mapA)
+ >>> tb = SpatioTemporalTopologyBuilder()
+ >>> tb.build(mapsA)
+ >>> # Check relations of mapsA
+ >>> for map in mapsA:
+ ... print(map.get_temporal_extent_as_tuple())
+ ... m = map.get_temporal_relations()
+ ... for key in m.keys():
+ ... if key not in ["NEXT", "PREV"]:
+ ... print(key, m[key][0].get_temporal_extent_as_tuple())
+ (datetime.datetime(2000, 1, 1, 0, 0), datetime.datetime(2000, 1, 1, 0, 0, 2))
+ ('OVERLAPS', (datetime.datetime(2000, 1, 1, 0, 0, 1), datetime.datetime(2000, 1, 1, 0, 0, 3)))
+ ('PRECEDES', (datetime.datetime(2000, 1, 1, 0, 0, 2), datetime.datetime(2000, 1, 1, 0, 0, 4)))
+ ('EQUAL', (datetime.datetime(2000, 1, 1, 0, 0), datetime.datetime(2000, 1, 1, 0, 0, 2)))
+ (datetime.datetime(2000, 1, 1, 0, 0, 1), datetime.datetime(2000, 1, 1, 0, 0, 3))
+ ('OVERLAPS', (datetime.datetime(2000, 1, 1, 0, 0, 2), datetime.datetime(2000, 1, 1, 0, 0, 4)))
+ ('OVERLAPPED', (datetime.datetime(2000, 1, 1, 0, 0), datetime.datetime(2000, 1, 1, 0, 0, 2)))
+ ('PRECEDES', (datetime.datetime(2000, 1, 1, 0, 0, 3), datetime.datetime(2000, 1, 1, 0, 0, 5)))
+ ('EQUAL', (datetime.datetime(2000, 1, 1, 0, 0, 1), datetime.datetime(2000, 1, 1, 0, 0, 3)))
+ (datetime.datetime(2000, 1, 1, 0, 0, 2), datetime.datetime(2000, 1, 1, 0, 0, 4))
+ ('OVERLAPS', (datetime.datetime(2000, 1, 1, 0, 0, 3), datetime.datetime(2000, 1, 1, 0, 0, 5)))
+ ('OVERLAPPED', (datetime.datetime(2000, 1, 1, 0, 0, 1), datetime.datetime(2000, 1, 1, 0, 0, 3)))
+ ('FOLLOWS', (datetime.datetime(2000, 1, 1, 0, 0), datetime.datetime(2000, 1, 1, 0, 0, 2)))
+ ('EQUAL', (datetime.datetime(2000, 1, 1, 0, 0, 2), datetime.datetime(2000, 1, 1, 0, 0, 4)))
+ (datetime.datetime(2000, 1, 1, 0, 0, 3), datetime.datetime(2000, 1, 1, 0, 0, 5))
+ ('FOLLOWS', (datetime.datetime(2000, 1, 1, 0, 0, 1), datetime.datetime(2000, 1, 1, 0, 0, 3)))
+ ('OVERLAPPED', (datetime.datetime(2000, 1, 1, 0, 0, 2), datetime.datetime(2000, 1, 1, 0, 0, 4)))
+ ('EQUAL', (datetime.datetime(2000, 1, 1, 0, 0, 3), datetime.datetime(2000, 1, 1, 0, 0, 5)))
+
@endcode
"""
@@ -494,7 +530,7 @@
if mapsB == None:
mapsB = mapsA
- idetnical = True
+ identical = True
for map_ in mapsA:
map_.reset_topology()
@@ -505,15 +541,16 @@
tree = self. _build_rtree(mapsA, spatial)
+ list_ = gis.G_new_ilist()
+
for j in xrange(len(mapsB)):
- list_ = gis.ilist()
rect = self._map_to_rect(tree, mapsB[j], spatial)
- vector.RTreeSearch2(tree, rect, byref(list_))
+ vector.RTreeSearch2(tree, rect, list_)
vector.RTreeFreeRect(rect)
- for k in xrange(list_.n_values):
- i = list_.value[k] - 1
+ for k in xrange(list_.contents.n_values):
+ i = list_.contents.value[k] - 1
# Get the temporal relationship
relation = mapsB[j].temporal_relation(mapsA[i])
@@ -530,6 +567,8 @@
if not identical and mapsB != None:
self._build_iteratable(mapsB, spatial)
+ gis.G_free_ilist(list_)
+
vector.RTreeDestroyTree(tree)
def __iter__(self):
@@ -550,16 +589,15 @@
###############################################################################
def set_temoral_relationship(A, B, relation):
- if relation == "equal":
- if B != A:
- if not B.get_equal() or \
- (B.get_equal() and \
- A not in B.get_equal()):
- B.append_equal(A)
- if not A.get_equal() or \
- (A.get_equal() and \
- B not in A.get_equal()):
- A.append_equal(B)
+ if relation == "equal" or relation == "equals":
+ if not B.get_equal() or \
+ (B.get_equal() and \
+ A not in B.get_equal()):
+ B.append_equal(A)
+ if not A.get_equal() or \
+ (A.get_equal() and \
+ B not in A.get_equal()):
+ A.append_equal(B)
elif relation == "follows":
if not B.get_follows() or \
(B.get_follows() and \
@@ -658,15 +696,14 @@
def set_spatial_relationship(A, B, relation):
if relation == "equivalent":
- if B != A:
- if not B.get_equivalent() or \
- (B.get_equivalent() and \
- A not in B.get_equivalent()):
- B.append_equivalent(A)
- if not A.get_equivalent() or \
- (A.get_equivalent() and \
- B not in A.get_equivalent()):
- A.append_equivalent(B)
+ if not B.get_equivalent() or \
+ (B.get_equivalent() and \
+ A not in B.get_equivalent()):
+ B.append_equivalent(A)
+ if not A.get_equivalent() or \
+ (A.get_equivalent() and \
+ B not in A.get_equivalent()):
+ A.append_equivalent(B)
elif relation == "overlap":
if not B.get_overlap() or \
(B.get_overlap() and \
More information about the grass-commit
mailing list