[GRASS-SVN] r49056 - grass/trunk/lib/python/temporal
svn_grass at osgeo.org
svn_grass at osgeo.org
Wed Nov 2 17:32:12 EDT 2011
Author: huhabla
Date: 2011-11-02 14:32:12 -0700 (Wed, 02 Nov 2011)
New Revision: 49056
Modified:
grass/trunk/lib/python/temporal/abstract_dataset.py
grass/trunk/lib/python/temporal/abstract_map_dataset.py
grass/trunk/lib/python/temporal/abstract_space_time_dataset.py
grass/trunk/lib/python/temporal/space_time_datasets_tools.py
Log:
Added temporal sampling methods.
Modified: grass/trunk/lib/python/temporal/abstract_dataset.py
===================================================================
--- grass/trunk/lib/python/temporal/abstract_dataset.py 2011-11-02 20:51:27 UTC (rev 49055)
+++ grass/trunk/lib/python/temporal/abstract_dataset.py 2011-11-02 21:32:12 UTC (rev 49056)
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
"""!@package grass.temporal
@brief GRASS Python scripting module (temporal GIS functions)
@@ -100,7 +101,12 @@
bottom = self.spatial_extent.get_bottom()
return (north, south, east, west, top, bottom)
+
+ def spatial_overlap(self, dataset):
+ """Return True if the spatial extents overlap"""
+ north = self.spatial_extent.overlap(dataset.spatial_extent)
+
def select(self, dbif=None):
"""Select temporal dataset entry from database and fill up the internal structure"""
Modified: grass/trunk/lib/python/temporal/abstract_map_dataset.py
===================================================================
--- grass/trunk/lib/python/temporal/abstract_map_dataset.py 2011-11-02 20:51:27 UTC (rev 49055)
+++ grass/trunk/lib/python/temporal/abstract_map_dataset.py 2011-11-02 21:32:12 UTC (rev 49056)
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
"""!@package grass.temporal
@brief GRASS Python scripting module (temporal GIS functions)
@@ -48,6 +49,10 @@
"""
raise IOError("This method must be implemented in the subclasses")
+ def load(self):
+ """Load the content of this object from map files"""
+ raise IOError("This method must be implemented in the subclasses")
+
def set_absolute_time(self, start_time, end_time=None, timezone=None):
"""Set the absolute time interval with start time and end time
Modified: grass/trunk/lib/python/temporal/abstract_space_time_dataset.py
===================================================================
--- grass/trunk/lib/python/temporal/abstract_space_time_dataset.py 2011-11-02 20:51:27 UTC (rev 49055)
+++ grass/trunk/lib/python/temporal/abstract_space_time_dataset.py 2011-11-02 21:32:12 UTC (rev 49056)
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
"""!@package grass.temporal
@brief GRASS Python scripting module (temporal GIS functions)
@@ -39,13 +40,6 @@
def __init__(self, ident):
self.reset(ident)
- def get_new_instance(self, ident=None):
- """Return a new instance with the type of this class
-
- @param ident: The unique identifier of the new object
- """
- raise IOError("This method must be implemented in the subclasses")
-
def get_new_map_instance(self, ident=None):
"""Return a new instance of a map dataset which is associated with the type of this class
@@ -345,10 +339,154 @@
return True
+ def sample_by_dataset_topology_simple(self, stds, dbif=None):
+ """Sample this space time dataset with the temporal topology of a second space time dataset
+
+ Only the start time of the registered maps of the dataset is considered. So that maps with end time
+ in a sample granule are not listed.
+
+ Return all registered maps as ordered (by start_time) object list with
+ "gap" map objects (id==None). Each list entry is a list of map objects
+ which are potentially located in each granule of the second space time dataset.
+
+ A valid temporal topology (no overlapping or inclusion allowed) is needed to get correct results.
+
+ The sample dataset must have "interval" as temporal map type, so all sample maps have valid interval time.
+
+ Gaps between maps are identified as unregistered maps with id==None.
+
+ The objects are initialized with the id and the temporal extent (temporal type, start time, end time).
+ In case more map informations are needed, use the select() method for each listed object.
+
+ @param stds: The space time dataset to be used for temporal sampling
+ @param dbif: The database interface to be used
+
+ In case nothing found None is returned
+ """
+
+ 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
+
+
+ connect = False
+
+ if dbif == None:
+ dbif = sql_database_interface()
+ dbif.connect()
+ connect = True
+
+ obj_list = []
+ sample_maps = stds.get_registered_maps_as_objects_with_gaps(where=None, dbif=dbif)
+
+
+ for sample in sample_maps:
+ start, end = sample.get_valid_time()
+
+ where = "((start_time >= '%s' and start_time < '%s'))" % (start, end)
+ rows = self.get_registered_maps("id", where, "start_time", dbif)
+
+ if rows:
+ maplist = []
+ for row in rows:
+ map = self.get_new_map_instance(row["id"])
+
+ if self.is_time_absolute():
+ map.set_absolute_time(start, end)
+ elif self.is_time_relative():
+ map.set_relative_time(start, end)
+
+ maplist.append(copy.copy(map))
+
+ obj_list.append(copy.copy(maplist))
+
+ if connect == True:
+ dbif.close()
+
+ return obj_list
+
+
+ def sample_by_dataset_topology(self, stds, dbif=None):
+ """Sample this space time dataset with the temporal topology of a second space time dataset
+
+ This dataset and the sample dataset must have "interval" as temporal map type, so all maps have valid interval time.
+
+ Return all registered maps as ordered (by start_time) object list with
+ "gap" map objects (id==None). Each list entry is a list of map objects
+ which are potentially located in each granule of the second space time dataset.
+
+ A valid temporal topology (no overlapping or inclusion allowed) is needed to get correct results.
+
+ Gaps between maps are identified as unregistered maps with id==None.
+
+ The objects are initialized with the id and the temporal extent (temporal type, start time, end time).
+ In case more map informations are needed, use the select() method for each listed object.
+
+ @param stds: The space time dataset to be used for temporal sampling
+ @param dbif: The database interface to be used
+
+ In case nothing found None is returned
+ """
+
+ 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 self.get_map_time() != "interval":
+ core.error(_("The temporal map type of the dataset must be interval"))
+ return None
+
+ if stds.get_map_time() != "interval":
+ core.error(_("The temporal map type of the sample dataset must be interval"))
+ return None
+
+
+ connect = False
+
+ if dbif == None:
+ dbif = sql_database_interface()
+ dbif.connect()
+ connect = True
+
+ obj_list = []
+ sample_maps = stds.get_registered_maps_as_objects_with_gaps(where=None, dbif=dbif)
+
+
+ for sample in sample_maps:
+ start, end = sample.get_valid_time()
+
+ where = "((start_time <= '%s' and end_time >= '%s') OR (start_time >= '%s' and end_time <= '%s') OR (start_time < '%s' and end_time >= '%s') OR (start_time <= '%s' and end_time > '%s'))" % (start, end, start, end, end, end, start, start)
+ rows = self.get_registered_maps("id", where, "start_time", dbif)
+
+ if rows:
+ maplist = []
+ for row in rows:
+ map = self.get_new_map_instance(row["id"])
+
+ if self.is_time_absolute():
+ map.set_absolute_time(start, end)
+ elif self.is_time_relative():
+ map.set_relative_time(start, end)
+
+ maplist.append(copy.copy(map))
+
+ obj_list.append(copy.copy(maplist))
+
+ if connect == True:
+ dbif.close()
+
+ return obj_list
+
+
def get_registered_maps_as_objects_by_granularity(self, gran=None, dbif=None):
"""Return all registered maps as ordered (by start_time) object list with
"gap" map objects (id==None) for temporal topological operations using the
- granularity of the space time dataset as increment
+ granularity of the space time dataset as increment. Each list entry is a list of map objects
+ which are potentially located in the actual granule.
A valid temporal topology (no overlapping or inclusion allowed) is needed to get correct results.
@@ -374,11 +512,6 @@
obj_list = []
- if self.get_map_time() != "interval":
- core.error(_("The temporal map type must be interval"))
- #TODO: Check for valid topology too?
- return None
-
if gran == None:
gran = self.get_granularity()
@@ -390,26 +523,28 @@
else:
next = start + gran
- where = "(start_time <= '%s' and end_time >= '%s')" % (start, next)
+ where = "((start_time <= '%s' and end_time >= '%s') OR (start_time >= '%s' and end_time <= '%s') OR (start_time < '%s' and end_time >= '%s') OR (start_time <= '%s' and end_time > '%s'))" % (start, end, start, end, end, end, start, start)
rows = self.get_registered_maps("id", where, "start_time", dbif)
if rows:
if len(rows) > 1:
- core.error(_("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."))
- # Take the first map
- map = self.get_new_map_instance(rows[0]["id"])
- else:
- # In case of a gap, create a dummy map with identifier None
- map = self.get_new_map_instance(None)
+ 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:
+ # Take the first map
+ map = self.get_new_map_instance(rows[0]["id"])
- if self.is_time_absolute():
- map.set_absolute_time(start, next)
- elif self.is_time_relative():
- map.set_relative_time(start, next)
+ if self.is_time_absolute():
+ map.set_absolute_time(start, next)
+ elif self.is_time_relative():
+ map.set_relative_time(start, next)
- obj_list.append(copy.copy(map))
+ maplist.append(copy.copy(map))
+ obj_list.append(copy.copy(maplist))
+
start = next
if connect == True:
Modified: grass/trunk/lib/python/temporal/space_time_datasets_tools.py
===================================================================
--- grass/trunk/lib/python/temporal/space_time_datasets_tools.py 2011-11-02 20:51:27 UTC (rev 49055)
+++ grass/trunk/lib/python/temporal/space_time_datasets_tools.py 2011-11-02 21:32:12 UTC (rev 49056)
@@ -597,9 +597,18 @@
if maps and len(maps) > 0:
- first_time, dummy = maps[0].get_valid_time()
+ if isinstance(maps[0], list):
+ first_time, dummy = maps[0][0].get_valid_time()
+ else:
+ first_time, dummy = maps[0].get_valid_time()
- for map in maps:
+ for mymap in maps:
+
+ if isinstance(mymap, list):
+ map = mymap[0]
+ else:
+ map = mymap
+
start, end = map.get_valid_time()
if end:
delta = end -start
@@ -668,3 +677,99 @@
print output
+def sample_stds_by_stds_topology(intype, sampletype, input, sampler, header, separator, use_simple):
+ """ Sample the input space time dataset with a sample space time dataset and print the result to stdout
+
+ In case multiple maps are located in the current granule, the map names are separated by comma.
+
+ Attention: Do not use the comma as separator
+
+ @param input: Name of a space time dataset
+ @param sampler: Name of a space time dataset used for temporal sampling
+ """
+ mapset = core.gisenv()["MAPSET"]
+
+ if input.find("@") >= 0:
+ id = input
+ else:
+ id = input + "@" + mapset
+
+ sp = dataset_factory(intype, id)
+
+ if sampler.find("@") >= 0:
+ sid = sampler
+ else:
+ sid = sampler + "@" + mapset
+
+ ssp = dataset_factory(sampletype, sid)
+
+ dbif = sql_database_interface()
+ dbif.connect()
+
+
+ if sp.is_in_db(dbif) == False:
+ core.fatal(_("Dataset <%s> not found in temporal database") % (id))
+
+ if ssp.is_in_db(dbif) == False:
+ core.fatal(_("Dataset <%s> not found in temporal database") % (sid))
+
+ sp.select(dbif)
+ ssp.select(dbif)
+
+ if separator == None or separator == "" or separator.find(",") >= 0:
+ separator = " | "
+
+ if use_simple:
+ mapmatrix = sp.sample_by_dataset_topology_simple(ssp, dbif)
+ else:
+ mapmatrix = sp.sample_by_dataset_topology(ssp, dbif)
+ samplerlist = ssp.get_registered_maps_as_objects_with_gaps(dbif=dbif)
+
+ if mapmatrix and len(mapmatrix) > 0:
+
+ if header:
+ string = ""
+ string += "%s%s" % ("sample_id", separator)
+ string += "%s%s" % ("ids", separator)
+ string += "%s%s" % ("start_time", separator)
+ string += "%s%s" % ("end_time", separator)
+ string += "%s%s" % ("interval_length", separator)
+ string += "%s" % ("distance_from_begin")
+ print string
+
+ first_time, dummy = mapmatrix[0][0].get_valid_time()
+
+ for i in range(len(mapmatrix)):
+ mapnames = ""
+ count = 0
+ for map in mapmatrix[i]:
+ if count == 0:
+ mapnames += map.get_id()
+ else:
+ mapnames += ",%s" % map.get_id()
+ count += 1
+
+ map = mapmatrix[i][0]
+
+ start, end = map.get_valid_time()
+ if end:
+ delta = end - start
+ else:
+ delta = None
+ delta_first = start - first_time
+
+ if map.is_time_absolute():
+ if end:
+ delta = time_delta_to_relative_time(delta)
+ delta_first = time_delta_to_relative_time(delta_first)
+
+ string = ""
+ string += "%s%s" % (samplerlist[i].get_id(), separator)
+ string += "%s%s" % (mapnames, separator)
+ string += "%s%s" % (start, separator)
+ string += "%s%s" % (end, separator)
+ string += "%s%s" % (delta, separator)
+ string += "%s" % (delta_first)
+ print string
+
+ dbif.close()
More information about the grass-commit
mailing list