123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298 |
- # -*- coding: utf-8 -*-
- """!@package grass.temporal
- @brief GRASS Python scripting module (temporal GIS functions)
- Temporal GIS related functions to be used in temporal GIS Python library package.
- Usage:
- @code
- import grass.temporal as tgis
- ...
- @endcode
- (C) 2008-2011 by the GRASS Development Team
- This program is free software under the GNU General Public
- License (>=v2). Read the file COPYING that comes with GRASS
- for details.
- @author Soeren Gebbert
- """
- from abstract_dataset import *
- ###############################################################################
- class abstract_map_dataset(abstract_dataset):
- """This is the base class for all maps (raster, vector, raster3d)
- providing additional function to set the valid time and the spatial extent.
- """
-
- def get_new_stds_instance(self, ident):
- """Return a new space time dataset instance in which maps are stored with the type of this class
- @param ident: The identifier of the dataset
- """
- raise IOError("This method must be implemented in the subclasses")
-
- def get_stds_register(self):
- """Return the space time dataset register table name in which stds are listed in which this map is registered"""
- raise IOError("This method must be implemented in the subclasses")
-
- def set_stds_register(self, name):
- """Set the space time dataset register table name.
-
- This table stores all space time datasets in which this map is registered.
- @param ident: The name of the register table
- """
- 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
-
- @param start_time: a datetime object specifying the start time of the map
- @param end_time: a datetime object specifying the end time of the map
- @param timezone: Thee timezone of the map
-
- """
- if start_time and not isinstance(start_time, datetime) :
- core.fatal(_("Start time must be of type datetime for %s map <%s>") % (self.get_type(), self.get_id()))
- if end_time and not isinstance(end_time, datetime) :
- core.fatal(_("End time must be of type datetime for %s map <%s>") % (self.get_type(), self.get_id()))
- if start_time and end_time:
- if start_time > end_time:
- core.fatal(_("End time must be greater than start time for %s map <%s>") % (self.get_type(), self.get_id()))
- else:
- # Do not create an interval in case start and end time are equal
- if start_time == end_time:
- end_time = None
- self.base.set_ttype("absolute")
-
- self.absolute_time.set_start_time(start_time)
- self.absolute_time.set_end_time(end_time)
- self.absolute_time.set_timezone(timezone)
- def update_absolute_time(self, start_time, end_time=None, timezone=None, dbif = None):
- """Update the absolute time
- @param start_time: a datetime object specifying the start time of the map
- @param end_time: a datetime object specifying the end time of the map
- @param timezone: Thee timezone of the map
- """
- connect = False
- if dbif == None:
- dbif = sql_database_interface()
- dbif.connect()
- connect = True
- self.set_absolute_time(start_time, end_time, timezone)
- self.absolute_time.update_all(dbif)
- self.base.update(dbif)
- if connect == True:
- dbif.close()
- def set_relative_time(self, start_time, end_time=None):
- """Set the relative time interval
-
- @param start_time: A double value in days
- @param end_time: A double value in days
- """
- if start_time != None and end_time != None:
- if abs(float(start_time)) > abs(float(end_time)):
- core.fatal(_("End time must be greater than start time for %s map <%s>") % (self.get_type(), self.get_id()))
- else:
- # Do not create an interval in case start and end time are equal
- if start_time == end_time:
- end_time = None
- self.base.set_ttype("relative")
-
- self.relative_time.set_start_time(float(start_time))
- if end_time != None:
- self.relative_time.set_end_time(float(end_time))
- else:
- self.relative_time.set_end_time(None)
- def update_relative_time(self, start_time, end_time=None, dbif = None):
- """Update the relative time interval
- @param start_time: A double value in days
- @param end_time: A double value in days
- @param dbif: The database interface to be used
- """
- connect = False
- if dbif == None:
- dbif = sql_database_interface()
- dbif.connect()
- connect = True
- self.set_relative_time(start_time, end_time)
- self.relative_time.update_all(dbif)
- self.base.update(dbif)
- dbif.connection.commit()
- if connect == True:
- dbif.close()
- def set_spatial_extent(self, north, south, east, west, top=0, bottom=0):
- """Set the spatial extent of the map
- @param north: The northern edge
- @param south: The southern edge
- @param east: The eastern edge
- @param west: The western edge
- @param top: The top edge
- @param bottom: The bottom ege
- """
- self.spatial_extent.set_spatial_extent(north, south, east, west, top, bottom)
-
- def check_valid_time(self):
- """Check for correct valid time"""
- if self.is_time_absolute():
- start, end, tz = self.get_absolute_time()
- else:
- start, end = self.get_relative_time()
- if start != None:
- if end != None:
- if start >= end:
- core.error(_("Map <%s> has incorrect time interval, start time is greater than end time") % (self.get_id()))
- return False
- else:
- core.error(_("Map <%s> has incorrect start time") % (self.get_id()))
- return False
- return True
- def delete(self, dbif=None):
- """Delete a map entry from database if it exists
-
- Remove dependent entries:
- * Remove the map entry in each space time dataset in which this map is registered
- * Remove the space time dataset register table
-
- @param dbif: The database interface to be used
- """
- connect = False
- if dbif == None:
- dbif = sql_database_interface()
- dbif.connect()
- connect = True
- if self.is_in_db(dbif):
-
- # SELECT all needed informations from the database
- self.select(dbif)
-
- # First we unregister from all dependent space time datasets
- self.unregister(dbif)
- # Remove the strds register table
- if self.get_stds_register():
- sql = "DROP TABLE " + self.get_stds_register()
- #print sql
- try:
- dbif.cursor.execute(sql)
- except:
- core.error(_("Unable to remove space time dataset register table <%s>") % (self.get_stds_register()))
- core.verbose(_("Delete %s dataset <%s> from temporal database") % (self.get_type(), self.get_id()))
- # Delete yourself from the database, trigger functions will take care of dependencies
- self.base.delete(dbif)
- self.reset(None)
- dbif.connection.commit()
- if connect == True:
- dbif.close()
- def unregister(self, dbif=None, update=True):
- """ Remove the map entry in each space time dataset in which this map is registered
- @param dbif: The database interface to be used
- @param update: Call for each unregister statement the update_from_registered_maps
- of the space time dataset. This can slow down the unregistration process significantly.
- """
- core.verbose(_("Unregister %s dataset <%s> from space time datasets") % (self.get_type(), self.get_id()))
-
- connect = False
- if dbif == None:
- dbif = sql_database_interface()
- dbif.connect()
- connect = True
- # Get all datasets in which this map is registered
- rows = self.get_registered_datasets(dbif)
- # For each stds in which the map is registered
- if rows:
- count = 0
- num_sps = len(rows)
- for row in rows:
- core.percent(count, num_sps, 1)
- count += 1
- # Create a space time dataset object to remove the map
- # from its register
- stds = self.get_new_stds_instance(row["id"])
- stds.select(dbif)
- stds.unregister_map(self, dbif)
- # Take care to update the space time dataset after
- # the map has been unregistred
- if update == True:
- stds.update_from_registered_maps(dbif)
- core.percent(1, 1, 1)
- dbif.connection.commit()
- if connect == True:
- dbif.close()
-
- def get_registered_datasets(self, dbif=None):
- """Return all space time dataset ids in which this map is registered as
- dictionary like rows with column "id" or None if this map is not registered in any
- space time dataset.
- @param dbif: The database interface to be used
- """
- connect = False
- if dbif == None:
- dbif = sql_database_interface()
- dbif.connect()
- connect = True
- rows = None
- try:
- if self.get_stds_register() != None:
- # Select all stds tables in which this map is registered
- sql = "SELECT id FROM " + self.get_stds_register()
- dbif.cursor.execute(sql)
- rows = dbif.cursor.fetchall()
- except:
- core.error(_("Unable to select space time dataset register table <%s>") % (self.get_stds_register()))
- if connect == True:
- dbif.close()
-
- return rows
|