[GRASS-SVN] r48132 - in grass/trunk: . lib lib/python lib/temporal
temporal temporal/t.create temporal/t.info temporal/t.remove
svn_grass at osgeo.org
svn_grass at osgeo.org
Mon Sep 5 10:29:35 EDT 2011
Author: huhabla
Date: 2011-09-05 07:29:35 -0700 (Mon, 05 Sep 2011)
New Revision: 48132
Added:
grass/trunk/lib/python/temporal.py
grass/trunk/lib/temporal/
grass/trunk/lib/temporal/map_stds_register_table_template.sql
grass/trunk/lib/temporal/map_tables_template.sql
grass/trunk/lib/temporal/raster3d_metadata_table.sql
grass/trunk/lib/temporal/raster_metadata_table.sql
grass/trunk/lib/temporal/stds_map_register_table_template.sql
grass/trunk/lib/temporal/stds_raster3d_register_trigger_template.sql
grass/trunk/lib/temporal/stds_raster_register_trigger_template.sql
grass/trunk/lib/temporal/stds_tables_template.sql
grass/trunk/lib/temporal/str3ds_metadata_table.sql
grass/trunk/lib/temporal/strds_metadata_table.sql
grass/trunk/lib/temporal/stvds_metadata_table.sql
grass/trunk/lib/temporal/test.temporal.py
grass/trunk/lib/temporal/vector_metadata_table.sql
grass/trunk/temporal/
grass/trunk/temporal/t.create/
grass/trunk/temporal/t.create/Makefile
grass/trunk/temporal/t.create/t.create.html
grass/trunk/temporal/t.create/t.create.py
grass/trunk/temporal/t.info/
grass/trunk/temporal/t.info/Makefile
grass/trunk/temporal/t.info/t.info.html
grass/trunk/temporal/t.info/t.info.py
grass/trunk/temporal/t.remove/
grass/trunk/temporal/t.remove/Makefile
grass/trunk/temporal/t.remove/t.remove.html
grass/trunk/temporal/t.remove/t.remove.py
Modified:
grass/trunk/lib/python/Makefile
grass/trunk/lib/python/__init__.py
Log:
Initial commit of the temporal GIS extension in grass. The file names
are still objects of change.
Modified: grass/trunk/lib/python/Makefile
===================================================================
--- grass/trunk/lib/python/Makefile 2011-09-05 13:20:10 UTC (rev 48131)
+++ grass/trunk/lib/python/Makefile 2011-09-05 14:29:35 UTC (rev 48132)
@@ -8,7 +8,7 @@
GDIR = $(PYDIR)/grass
DSTDIR = $(GDIR)/script
-MODULES = core db raster raster3d vector array setup task
+MODULES = core db raster raster3d vector array setup task temporal
PYFILES := $(patsubst %,$(DSTDIR)/%.py,$(MODULES) __init__)
PYCFILES := $(patsubst %,$(DSTDIR)/%.pyc,$(MODULES) __init__)
Modified: grass/trunk/lib/python/__init__.py
===================================================================
--- grass/trunk/lib/python/__init__.py 2011-09-05 13:20:10 UTC (rev 48131)
+++ grass/trunk/lib/python/__init__.py 2011-09-05 14:29:35 UTC (rev 48132)
@@ -3,3 +3,4 @@
from raster import *
from raster3d import *
from vector import *
+from temporal import *
Added: grass/trunk/lib/python/temporal.py
===================================================================
--- grass/trunk/lib/python/temporal.py (rev 0)
+++ grass/trunk/lib/python/temporal.py 2011-09-05 14:29:35 UTC (rev 48132)
@@ -0,0 +1,1354 @@
+"""!@package grass.script.temporal
+
+ at brief GRASS Python scripting module (temporal GIS functions)
+
+Temporal GIS related functions to be used in Python scripts.
+
+Usage:
+
+ at code
+from grass.script import temporal as grass
+
+...
+ at endcode
+
+(C) 2008-2009 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.
+
+ at author Soeren Gebbert
+"""
+
+import sqlite3
+import os
+from datetime import datetime, date, time
+import core
+import raster
+import raster3d
+import getpass
+
+def get_grass_location_db_path():
+ grassenv = core.gisenv()
+ dbpath = os.path.join(grassenv["GISDBASE"], grassenv["LOCATION_NAME"])
+ print os.path.join(dbpath, "grass.db")
+ return os.path.join(dbpath, "grass.db")
+
+def get_sql_template_path():
+ return "./"
+
+###############################################################################
+
+def create_temporal_database():
+ """This function creates the grass location database structure for raster, vector and raster3d maps
+ as well as for the space-time datasets strds, str3ds and stvds"""
+
+ # Check if it already exists
+ if os.path.exists(get_grass_location_db_path()):
+ return False
+
+ # Read all SQL scripts and templates
+ map_tables_template_sql = open(os.path.join(get_sql_template_path(), "map_tables_template.sql"), 'r').read()
+ raster_metadata_sql = open(os.path.join(get_sql_template_path(), "raster_metadata_table.sql"), 'r').read()
+ raster3d_metadata_sql = open(os.path.join(get_sql_template_path(), "raster3d_metadata_table.sql"), 'r').read()
+ vector_metadata_sql = open(os.path.join(get_sql_template_path(), "vector_metadata_table.sql"), 'r').read()
+ stds_tables_template_sql = open(os.path.join(get_sql_template_path(), "stds_tables_template.sql"), 'r').read()
+ strds_metadata_sql = open(os.path.join(get_sql_template_path(), "strds_metadata_table.sql"), 'r').read()
+ str3ds_metadata_sql = open(os.path.join(get_sql_template_path(), "str3ds_metadata_table.sql"), 'r').read()
+ stvds_metadata_sql = open(os.path.join(get_sql_template_path(), "stvds_metadata_table.sql"), 'r').read()
+
+ # Create the raster, raster3d and vector tables
+ raster_tables_sql = map_tables_template_sql.replace("GRASS_MAP", "raster")
+ vector_tables_sql = map_tables_template_sql.replace("GRASS_MAP", "vector")
+ raster3d_tables_sql = map_tables_template_sql.replace("GRASS_MAP", "raster3d")
+
+ # Create the space-time raster, raster3d and vector dataset tables
+ strds_tables_sql = stds_tables_template_sql.replace("STDS", "strds")
+ stvds_tables_sql = stds_tables_template_sql.replace("STDS", "stvds")
+ str3ds_tables_sql = stds_tables_template_sql.replace("STDS", "str3ds")
+
+ # Check for completion
+ sqlite3.complete_statement(raster_tables_sql)
+ sqlite3.complete_statement(vector_tables_sql)
+ sqlite3.complete_statement(raster3d_tables_sql)
+ sqlite3.complete_statement(raster_metadata_sql)
+ sqlite3.complete_statement(vector_metadata_sql)
+ sqlite3.complete_statement(raster3d_metadata_sql)
+ sqlite3.complete_statement(strds_tables_sql)
+ sqlite3.complete_statement(stvds_tables_sql)
+ sqlite3.complete_statement(str3ds_tables_sql)
+ sqlite3.complete_statement(strds_metadata_sql)
+ sqlite3.complete_statement(stvds_metadata_sql)
+ sqlite3.complete_statement(str3ds_metadata_sql)
+
+ # Connect to database
+ connection = sqlite3.connect(get_grass_location_db_path())
+ cursor = connection.cursor()
+
+ # Execute the SQL statements
+ # Create the global tables for the native grass datatypes
+ cursor.executescript(raster_tables_sql)
+ cursor.executescript(raster_metadata_sql)
+ cursor.executescript(vector_tables_sql)
+ cursor.executescript(vector_metadata_sql)
+ cursor.executescript(raster3d_tables_sql)
+ cursor.executescript(raster3d_metadata_sql)
+ # Create the tables for the new space-time datatypes
+ cursor.executescript(strds_tables_sql)
+ cursor.executescript(strds_metadata_sql)
+ cursor.executescript(stvds_tables_sql)
+ cursor.executescript(stvds_metadata_sql)
+ cursor.executescript(str3ds_tables_sql)
+ cursor.executescript(str3ds_metadata_sql)
+
+ connection.commit()
+ cursor.close()
+
+###############################################################################
+
+class dict_sql_serializer():
+ def __init__(self):
+ self.D = {}
+ def serialize(self, type, table, where=None):
+ """Convert the internal dictionary into a string of semicolon separated SQL statements
+ The keys are the colum names and the values are the row entries
+
+ @type must be SELECT. INSERT, UPDATE
+ @table The name of the table to select, insert or update
+ @where The optinal where statment
+ @return the sql string
+ """
+
+ sql = ""
+ args = []
+
+ # Create ordered select statement
+ if type == "SELECT":
+ sql += 'SELECT '
+ count = 0
+ for key in self.D.keys():
+ if count == 0:
+ sql += ' %s ' % key
+ else:
+ sql += ' , %s ' % key
+ count += 1
+ sql += ' FROM ' + table + ' '
+ if where:
+ sql += where
+
+ # Create insert statement
+ if type =="INSERT":
+ count = 0
+ sql += 'INSERT INTO ' + table + ' ('
+ for key in self.D.keys():
+ if count == 0:
+ sql += ' %s ' % key
+ else:
+ sql += ' ,%s ' % key
+ count += 1
+
+ count = 0
+ sql += ') VALUES ('
+ for key in self.D.keys():
+ if count == 0:
+ sql += '?'
+ else:
+ sql += ',?'
+ count += 1
+ args.append(self.D[key])
+ sql += ') '
+
+ if where:
+ sql += where
+
+ # Create update statement
+ if type =="UPDATE":
+ count = 0
+ sql += 'UPDATE ' + table + ' SET '
+ for key in self.D.keys():
+ # Update only entries which are not None
+ if self.D[key] != None:
+ if count == 0:
+ sql += ' %s = ? ' % key
+ else:
+ sql += ' ,%s = ? ' % key
+ count += 1
+ args.append(self.D[key])
+ if where:
+ sql += where
+
+ return sql, tuple(args)
+
+ def deserialize(self, row):
+ """Convert the content of the sqlite row into the internal dictionary"""
+ self.D = {}
+ for key in row.keys():
+ self.D[key] = row[key]
+
+ def clear(self):
+ """Remove all the content of this class"""
+ self.D = {}
+
+ def print_self(self):
+ print self.D
+
+ def test(self):
+ t = dict_sql_serializer()
+ t.D["id"] = "soil at PERMANENT"
+ t.D["name"] = "soil"
+ t.D["mapset"] = "PERMANENT"
+ t.D["creator"] = "soeren"
+ t.D["creation_time"] = datetime.now()
+ t.D["modification_time"] = datetime.now()
+ t.D["revision"] = 1
+ sql, values = t.serialize(type="SELECT", table="raster_base")
+ print sql, '\n', values
+ sql, values = t.serialize(type="INSERT", table="raster_base")
+ print sql, '\n', values
+ sql, values = t.serialize(type="UPDATE", table="raster_base")
+ print sql, '\n', values
+
+###############################################################################
+
+class sql_database_interface(dict_sql_serializer):
+ """This is the sql database interface to sqlite3"""
+ def __init__(self, table=None, ident=None):
+
+ dict_sql_serializer.__init__(self)
+
+ self.table = table # Name of the table, set in the subclass
+ self.database = get_grass_location_db_path()
+ self.ident = ident
+
+ def connect(self):
+ self.connection = sqlite3.connect(self.database, detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
+ self.connection.row_factory = sqlite3.Row
+ self.cursor = self.connection.cursor()
+
+ def close(self):
+ self.connection.commit()
+ self.cursor.close()
+
+ def get_delete_statement(self):
+ return "DELETE FROM " + self.table + " WHERE id = \"" + str(self.ident) + "\""
+
+ def delete(self):
+ self.connect()
+ sql = self.get_delete_statement()
+ print sql
+ self.cursor.execute(sql)
+ self.close()
+
+ def get_is_in_db_statement(self):
+ return "SELECT id FROM " + self.table + " WHERE id = \"" + str(self.ident) + "\""
+
+ def is_in_db(self):
+ self.connect()
+ sql = self.get_is_in_db_statement()
+ print sql
+ self.cursor.execute(sql)
+ row = self.cursor.fetchone()
+ self.close()
+
+ # Nothing found
+ if row == None:
+ return False
+
+ return True
+
+ def get_select_statement(self):
+ return self.serialize("SELECT", self.table, "WHERE id = \"" + str(self.ident) + "\"")
+
+ def select(self):
+ self.connect()
+ sql, args = self.get_select_statement()
+ #print sql
+ #print args
+ if len(args) == 0:
+ self.cursor.execute(sql)
+ else:
+ self.cursor.execute(sql, args)
+ row = self.cursor.fetchone()
+
+ # Nothing found
+ if row == None:
+ return False
+
+ if len(row) > 0:
+ self.deserialize(row)
+ else:
+ raise IOError
+ self.close()
+
+ return True
+
+ def get_insert_statement(self):
+ return self.serialize("INSERT", self.table)
+
+ def insert(self):
+ self.connect()
+ sql, args = self.get_insert_statement()
+ #print sql
+ #print args
+ self.cursor.execute(sql, args)
+ self.close()
+
+ def get_update_statement(self):
+ return self.serialize("UPDATE", self.table, "WHERE id = \"" + str(self.ident) + "\"")
+
+ def update(self):
+ if self.ident == None:
+ raise IOError("Missing identifer");
+
+ sql, args = self.get_update_statement()
+ #print sql
+ #print args
+ self.connect()
+ self.cursor.execute(sql, args)
+ self.close()
+
+###############################################################################
+
+class dataset_identifer(sql_database_interface):
+ """This is the base class for all maps and spacetime datasets storing basic information"""
+ def __init__(self, table=None, ident=None, name=None, mapset=None, creator=None, ctime=None,\
+ mtime=None, ttype=None, revision=1):
+
+ sql_database_interface.__init__(self, table, ident)
+
+ self.set_id(ident)
+ self.set_name(name)
+ self.set_mapset(mapset)
+ self.set_creator(creator)
+ self.set_ctime(ctime)
+ self.set_mtime(mtime)
+ self.set_ttype(ttype)
+ self.set_revision(revision)
+
+ def set_id(self, ident):
+ """Convenient method to set the unique identifier (primary key)"""
+ self.ident = ident
+ self.D["id"] = ident
+
+ def set_name(self, name):
+ """Set the name of the map"""
+ self.D["name"] = name
+
+ def set_mapset(self, mapset):
+ """Set the mapset of the map"""
+ self.D["mapset"] = mapset
+
+ def set_creator(self, creator):
+ """Set the creator of the map"""
+ self.D["creator"] = creator
+
+ def set_ctime(self, ctime=None):
+ """Set the creation time of the map, if nothing set the current time is used"""
+ if ctime == None:
+ self.D["creation_time"] = datetime.now()
+ else:
+ self.D["creation_time"] = ctime
+
+ def set_mtime(self, mtime=None):
+ """Set the modification time of the map, if nothing set the current time is used"""
+ if mtime == None:
+ self.D["modification_time"] = datetime.now()
+ else:
+ self.D["modification_time"] = mtime
+
+ def set_ttype(self, ttype):
+ """Set the temporal type of the map: absolute or relative, if nothing set absolute time will assumed"""
+ if ttype == None or (ttype != "absolute" and ttype != "relative"):
+ self.D["temporal_type"] = "absolute"
+ else:
+ self.D["temporal_type"] = ttype
+
+ def set_revision(self, revision=1):
+ """Set the revision of the map: if nothing set revision 1 will assumed"""
+ self.D["revision"] = revision
+
+ def get_id(self):
+ """Convenient method to get the unique identifier (primary key)
+ @return None if not found
+ """
+ if self.D.has_key("id"):
+ return self.D["id"]
+ else:
+ return None
+
+ def get_name(self):
+ """Get the name of the map
+ @return None if not found"""
+ if self.D.has_key("name"):
+ return self.D["name"]
+ else:
+ return None
+
+ def get_mapset(self):
+ """Get the mapset of the map
+ @return None if not found"""
+ if self.D.has_key("mapset"):
+ return self.D["mapset"]
+ else:
+ return None
+
+ def get_creator(self):
+ """Get the creator of the map
+ @return None if not found"""
+ if self.D.has_key("creator"):
+ return self.D["creator"]
+ else:
+ return None
+
+ def get_ctime(self):
+ """Get the creation time of the map, datatype is datetime
+ @return None if not found"""
+ if self.D.has_key("creation_time"):
+ return self.D["creation_time"]
+ else:
+ return None
+
+ def get_mtime(self):
+ """Get the modification time of the map, datatype is datetime
+ @return None if not found"""
+ if self.D.has_key("modification_time"):
+ return self.D["modification_time"]
+ else:
+ return None
+
+ def get_ttype(self):
+ """Get the temporal type of the map
+ @return None if not found"""
+ if self.D.has_key("temporal_type"):
+ return self.D["temporal_type"]
+ else:
+ return None
+
+ def get_revision(self):
+ """Get the revision of the map
+ @return None if not found"""
+ if self.D.has_key("revision"):
+ return self.D["revision"]
+ else:
+ return None
+
+###############################################################################
+
+class raster_base(dataset_identifer):
+ def __init__(self, ident=None, name=None, mapset=None, creator=None, creation_time=None,\
+ modification_time=None, temporal_type=None, revision=1):
+ dataset_identifer.__init__(self, "raster_base", ident, name, mapset, creator, creation_time,\
+ modification_time, temporal_type, revision)
+
+class raster3d_base(dataset_identifer):
+ def __init__(self, ident=None, name=None, mapset=None, creator=None, creation_time=None,\
+ modification_time=None, temporal_type=None, revision=1):
+ dataset_identifer.__init__(self, "raster3d_base", ident, name, mapset, creator, creation_time,\
+ modification_time, temporal_type, revision)
+
+class vector_base(dataset_identifer):
+ def __init__(self, ident=None, name=None, mapset=None, creator=None, creation_time=None,\
+ modification_time=None, temporal_type=None, revision=1):
+ dataset_identifer.__init__(self, "vector_base", ident, name, mapset, creator, creation_time,\
+ modification_time, temporal_type, revision)
+
+###############################################################################
+
+class absolute_timestamp(sql_database_interface):
+ """This is the absolute time base class for all maps and spacetime datasets"""
+ def __init__(self, table=None, ident=None, start_time=None, end_time=None, timezone=None):
+
+ sql_database_interface.__init__(self, table, ident)
+
+ self.set_id(ident)
+ self.set_start_time(start_time)
+ self.set_end_time(end_time)
+ self.set_timezone(timezone)
+
+ def starts(self, map):
+ """Return True if this absolute time object starts at the start of the provided absolute time object and finishes within it
+ A |-----|
+ B |---------|
+ """
+ if self.D["start_time"] == map.D["start_time"] and self.D["end_time"] < map.D["end_time"]:
+ return True
+ else:
+ return False
+
+ def started(self, map):
+ """Return True if this absolute time object is started at the start of the provided absolute time object
+ A |---------|
+ B |-----|
+ """
+ if self.D["start_time"] == map.D["start_time"] and self.D["end_time"] > map.D["end_time"]:
+ return True
+ else:
+ return False
+
+ def finishes(self, map):
+ """Return True if this absolute time object finishes at the end and within of the provided absolute time object
+ A |-----|
+ B |---------|
+ """
+ if self.D["end_time"] == map.D["end_time"] and self.D["start_time"] > map.D["start_time"] :
+ return True
+ else:
+ return False
+
+ def finished(self, map):
+ """Return True if this absolute time object finished at the end of the provided absolute time object
+ A |---------|
+ B |-----|
+ """
+ if self.D["end_time"] == map.D["end_time"] and self.D["start_time"] < map.D["start_time"] :
+ return True
+ else:
+ return False
+
+ def after(self, map):
+ """Return True if this absolute time object is temporal located after the provided absolute time object
+ A |---------|
+ B |---------|
+ """
+ if self.D["start_time"] > map.D["end_time"]:
+ return True
+ else:
+ return False
+
+ def before(self, map):
+ """Return True if this absolute time object is temporal located bevor the provided absolute time object
+ A |---------|
+ B |---------|
+ """
+ if self.D["end_time"] < map.D["start_time"]:
+ return True
+ else:
+ return False
+
+ def adjacent(self, map):
+ """Return True if this absolute time object is a meeting neighbour the provided absolute time object
+ A |---------|
+ B |---------|
+ A |---------|
+ B |---------|
+ """
+ if (self.D["start_time"] == map.D["end_time"]) or (self.D["end_time"] == map.D["start_time"]):
+ return True
+ else:
+ return False
+
+ def follows(self, map):
+ """Return True if this absolute time object is temporal follows the provided absolute time object
+ A |---------|
+ B |---------|
+ """
+ if self.D["start_time"] == map.D["end_time"]:
+ return True
+ else:
+ return False
+
+ def precedes(self, map):
+ """Return True if this absolute time object is temporal precedes the provided absolute time object
+ A |---------|
+ B |---------|
+ """
+ if self.D["end_time"] == map.D["start_time"]:
+ return True
+ else:
+ return False
+
+ def during(self, map):
+ """Return True if this absolute time object is temporal located during the provided absolute time object
+ A |-------|
+ B |---------|
+ """
+ if self.D["start_time"] > map.D["start_time"] and self.D["end_time"] < map.D["end_time"]:
+ return True
+ else:
+ return False
+
+ def contains(self, map):
+ """Return True if this absolute time object is temporal located during the provided absolute time object
+ A |---------|
+ B |-------|
+ """
+ if self.D["start_time"] < map.D["start_time"] and self.D["end_time"] > map.D["end_time"]:
+ return True
+ else:
+ return False
+
+ def equivalent(self, map):
+ """Return True if this absolute time object is temporal located equivalent the provided absolute time object
+ A |---------|
+ B |---------|
+ """
+ if self.D["start_time"] == map.D["start_time"] and self.D["end_time"] == map.D["end_time"]:
+ return True
+ else:
+ return False
+
+ def overlaps(self, map):
+ """Return True if this absolute time object is temporal overlaps the provided absolute time object
+ A |---------|
+ B |---------|
+ """
+ if self.D["start_time"] < map.D["start_time"] and self.D["end_time"] < map.D["end_time"] and\
+ self.D["end_time"] > map.D["start_time"]:
+ return True
+ else:
+ return False
+
+ def overlapped(self, map):
+ """Return True if this absolute time object is temporal overlaped by the provided absolute time object
+ A |---------|
+ B |---------|
+ """
+ if self.D["start_time"] > map.D["start_time"] and self.D["end_time"] > map.D["end_time"] and\
+ self.D["start_time"] < map.D["end_time"]:
+ return True
+ else:
+ return False
+
+ def temporal_relation(self, map):
+ """Returns the temporal relation between absolute time temporal objects
+ Temporal relationsships are implemented after [Allen and Ferguson 1994 Actions and Events in Interval Temporal Logic]
+ """
+ if self.equivalent(map):
+ return "equivalent"
+ if self.during(map):
+ return "during"
+ if self.contains(map):
+ return "contains"
+ if self.overlaps(map):
+ return "overlaps"
+ if self.overlapped(map):
+ return "overlapped"
+ if self.after(map):
+ return "after"
+ if self.before(map):
+ return "before"
+ if self.starts(map):
+ return "starts"
+ if self.finishes(map):
+ return "finishes"
+ if self.started(map):
+ return "started"
+ if self.finished(map):
+ return "finished"
+ if self.equivalent(map):
+ return "equivalent"
+ if self.follows(map):
+ return "follows"
+ if self.precedes(map):
+ return "precedes"
+ return None
+
+ def set_id(self, ident):
+ """Convenient method to set the unique identifier (primary key)"""
+ self.ident = ident
+ self.D["id"] = ident
+
+ def set_start_time(self, start_time):
+ """Set the valid start time of the map, this should be of type datetime"""
+ self.D["start_time"] = start_time
+
+ def set_end_time(self, end_time):
+ """Set the valid end time of the map, this should be of type datetime"""
+ self.D["end_time"] = end_time
+
+ def set_timezone(self, timezone):
+ """Set the timezone of the map, integer from 1 - 24"""
+ self.D["timezone"] = timezone
+
+ def get_id(self):
+ """Convenient method to get the unique identifier (primary key)
+ @return None if not found
+ """
+ if self.D.has_key("id"):
+ return self.D["id"]
+ else:
+ return None
+
+ def get_start_time(self):
+ """Get the valid start time of the map
+ @return None if not found"""
+ if self.D.has_key("start_time"):
+ return self.D["start_time"]
+ else:
+ return None
+
+ def get_end_time(self):
+ """Get the valid end time of the map
+ @return None if not found"""
+ if self.D.has_key("end_time"):
+ return self.D["end_time"]
+ else:
+ return None
+
+ def get_timezone(self):
+ """Get the timezone of the map
+ @return None if not found"""
+ if self.D.has_key("timezone"):
+ return self.D["timezone"]
+ else:
+ return None
+
+###############################################################################
+
+class raster_absolute_time(absolute_timestamp):
+ def __init__(self, ident=None, start_time=None, end_time=None, timezone=None):
+ absolute_timestamp.__init__(self, "raster_absolute_time", ident, start_time, end_time, timezone)
+
+class raster3d_absolute_time(absolute_timestamp):
+ def __init__(self, ident=None, start_time=None, end_time=None, timezone=None):
+ absolute_timestamp.__init__(self, "raster3d_absolute_time", ident, start_time, end_time, timezone)
+
+class vector_absolute_time(absolute_timestamp):
+ def __init__(self, ident=None, start_time=None, end_time=None, timezone=None):
+ absolute_timestamp.__init__(self, "vector_absolute_time", ident, start_time, end_time, timezone)
+
+###############################################################################
+
+class relative_timestamp(sql_database_interface):
+ """This is the relative time base class for all maps and spacetime datasets"""
+ def __init__(self, table=None, ident=None, interval=None):
+
+ sql_database_interface.__init__(self, table, ident)
+
+ self.set_id(ident)
+ self.set_interval(interval)
+
+ def after(self, map):
+ """Return True if this relative time object is temporal located after the provided relative time object
+ A |
+ B |
+ """
+ if self.D["interval"] > map.D["interval"]:
+ return True
+ else:
+ return False
+
+
+ def before(self, map):
+ """Return True if this relative time object is temporal located bevor the provided relative time object
+ A |
+ B |
+ """
+ if self.D["interval"] < map.D["interval"]:
+ return True
+ else:
+ return False
+
+ def equivalent(self, map):
+ """Return True if this relative time object is equivalent to the provided relative time object
+ A |
+ B |
+ """
+ if self.D["interval"] == map.D["interval"]:
+ return True
+ else:
+ return False
+
+ def temporal_relation(self, map):
+ """Returns the temporal relation between relative time temporal objects
+ """
+ if self.equivalent(map):
+ return "equivalent"
+ if self.after(map):
+ return "after"
+ if self.before(map):
+ return "before"
+ return None
+
+ def set_id(self, ident):
+ """Convenient method to set the unique identifier (primary key)"""
+ self.ident = ident
+ self.D["id"] = ident
+
+ def set_interval(self, interval):
+ """Set the valid interval time of the map, this should be of type datetime"""
+ self.D["interval"] = interval
+
+ def get_id(self):
+ """Convenient method to get the unique identifier (primary key)
+ @return None if not found
+ """
+ if self.D.has_key("id"):
+ return self.D["id"]
+ else:
+ return None
+
+ def get_interval(self):
+ """Get the valid interval time of the map
+ @return None if not found"""
+ if self.D.has_key("interval"):
+ return self.D["interval"]
+ else:
+ return None
+
+###############################################################################
+
+class raster_relative_time(relative_timestamp):
+ def __init__(self, ident=None, interval=None):
+ relative_timestamp.__init__(self, "raster_relative_time", ident, interval)
+
+class raster3d_relative_time(relative_timestamp):
+ def __init__(self, ident=None, interval=None):
+ relative_timestamp.__init__(self, "raster3d_relative_time", ident, interval)
+
+class vector_relative_time(relative_timestamp):
+ def __init__(self, ident=None, interval=None):
+ relative_timestamp.__init__(self, "vector_relative_time", ident, interval)
+
+###############################################################################
+
+class spatial_extent(sql_database_interface):
+ """This is the spatial extent base class for all maps and spacetime datasets"""
+ def __init__(self, table=None, ident=None, north=None, south=None, east=None, west=None, top=None, bottom=None):
+
+ sql_database_interface.__init__(self, table, ident)
+
+ self.set_id(ident)
+ self.set_north(north)
+ self.set_south(south)
+ self.set_east(east)
+ self.set_west(west)
+ self.set_top(top)
+ self.set_bottom(bottom)
+
+ def set_id(self, ident):
+ """Convenient method to set the unique identifier (primary key)"""
+ self.ident = ident
+ self.D["id"] = ident
+
+ def set_north(self, north):
+ """Set the northern edge of the map"""
+ self.D["north"] = north
+
+ def set_south(self, sourth):
+ """Set the sourthern edge of the map"""
+ self.D["south"] = sourth
+
+
+ def set_west(self, west):
+ """Set the western edge of the map"""
+ self.D["west"] = west
+
+
+ def set_east(self, east):
+ """Set the eastern edge of the map"""
+ self.D["east"] = east
+
+
+ def set_top(self, top):
+ """Set the top edge of the map"""
+ self.D["top"] = top
+
+
+ def set_bottom(self, bottom):
+ """Set the bottom edge of the map"""
+ self.D["bottom"] = bottom
+
+
+ def get_id(self):
+ """Convenient method to get the unique identifier (primary key)
+ @return None if not found
+ """
+ if self.D.has_key("id"):
+ return self.D["id"]
+ else:
+ return None
+
+ def get_north(self):
+ """Get the northern edge of the map
+ @return None if not found"""
+ if self.D.has_key("north"):
+ return self.D["north"]
+ else:
+ return None
+
+ def get_south(self):
+ """Get the southern edge of the map
+ @return None if not found"""
+ if self.D.has_key("south"):
+ return self.D["south"]
+ else:
+ return None
+
+
+ def get_east(self):
+ """Get the eastern edge of the map
+ @return None if not found"""
+ if self.D.has_key("east"):
+ return self.D["east"]
+ else:
+ return None
+
+
+ def get_west(self):
+ """Get the western edge of the map
+ @return None if not found"""
+ if self.D.has_key("west"):
+ return self.D["west"]
+ else:
+ return None
+
+
+ def get_top(self):
+ """Get the top edge of the map
+ @return None if not found"""
+ if self.D.has_key("top"):
+ return self.D["top"]
+ else:
+ return None
+
+
+ def get_bottom(self):
+ """Get the bottom edge of the map
+ @return None if not found"""
+ if self.D.has_key("bottom"):
+ return self.D["bottom"]
+ else:
+ return None
+
+###############################################################################
+
+class raster_spatial_extent(spatial_extent):
+ def __init__(self, ident=None, interval=None, north=None, south=None, east=None, west=None, top=None, bottom=None):
+ spatial_extent.__init__(self, "raster_spatial_extent", ident, north, south, east, west, top, bottom)
+
+class raster3d_spatial_extent(spatial_extent):
+ def __init__(self, ident=None, interval=None, north=None, south=None, east=None, west=None, top=None, bottom=None):
+ spatial_extent.__init__(self, "raster3d_spatial_extent", ident, north, south, east, west, top, bottom)
+
+class vector_spatial_extent(spatial_extent):
+ def __init__(self, ident=None, interval=None, north=None, south=None, east=None, west=None, top=None, bottom=None):
+ spatial_extent.__init__(self, "vector_spatial_extent", ident, north, south, east, west, top, bottom)
+
+###############################################################################
+
+class raster_metadata_base(sql_database_interface):
+ """This is the raster metadata base class for raster and raster3d maps"""
+ 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):
+
+ sql_database_interface.__init__(self, table, ident)
+
+ self.set_id(ident)
+ self.set_datatype(datatype)
+ self.set_cols(cols)
+ self.set_rows(rows)
+ self.set_number_of_cells(number_of_cells)
+ self.set_nsres(nsres)
+ self.set_ewres(ewres)
+ self.set_min(min)
+ self.set_max(max)
+
+ def set_id(self, ident):
+ """Convenient method to set the unique identifier (primary key)"""
+ self.ident = ident
+ self.D["id"] = ident
+
+ def set_datatype(self, datatype):
+ """Set the datatype"""
+ self.D["datatype"] = datatype
+
+ def set_cols(self, cols):
+ """Set the number of cols"""
+ self.D["cols"] = cols
+
+ def set_rows(self, rows):
+ """Set the number of rows"""
+ self.D["rows"] = rows
+
+ def set_number_of_cells(self, number_of_cells):
+ """Set the number of cells"""
+ self.D["number_of_cells"] = number_of_cells
+
+ def set_nsres(self, nsres):
+ """Set the north-south resolution"""
+ self.D["nsres"] = nsres
+
+ def set_ewres(self, ewres):
+ """Set the east-west resolution"""
+ self.D["ewres"] = ewres
+
+ def set_min(self, min):
+ """Set the minimum raster value"""
+ self.D["min"] = min
+
+ def set_max(self, max):
+ """Set the maximum raster value"""
+ self.D["max"] = max
+
+ def get_id(self):
+ """Convenient method to get the unique identifier (primary key)
+ @return None if not found
+ """
+ if self.D.has_key("id"):
+ return self.D["id"]
+ else:
+ return None
+
+ def get_datatype(self):
+ """Get the map type
+ @return None if not found"""
+ if self.D.has_key("datatype"):
+ return self.D["datatype"]
+ else:
+ return None
+
+ def get_cols(self):
+ """Get number of cols
+ @return None if not found"""
+ if self.D.has_key("cols"):
+ return self.D["cols"]
+ else:
+ return None
+
+ def get_rows(self):
+ """Get number of rows
+ @return None if not found"""
+ if self.D.has_key("rows"):
+ return self.D["rows"]
+ else:
+ return None
+
+ def get_number_of_cells(self):
+ """Get number of cells
+ @return None if not found"""
+ if self.D.has_key("number_of_cells"):
+ return self.D["number_of_cells"]
+ else:
+ return None
+
+ def get_nsres(self):
+ """Get the north-south resolution
+ @return None if not found"""
+ if self.D.has_key("nsres"):
+ return self.D["nsres"]
+ else:
+ return None
+
+ def get_ewres(self):
+ """Get east-west resolution
+ @return None if not found"""
+ if self.D.has_key("ewres"):
+ return self.D["ewres"]
+ else:
+ return None
+
+ def get_min(self):
+ """Get the minimum cell value
+ @return None if not found"""
+ if self.D.has_key("min"):
+ return self.D["min"]
+ else:
+ return None
+
+ def get_max(self):
+ """Get the maximum cell value
+ @return None if not found"""
+ if self.D.has_key("max"):
+ return self.D["max"]
+ else:
+ return None
+
+###############################################################################
+
+class raster_metadata(raster_metadata_base):
+ """This is the raster metadata class"""
+ 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):
+
+ raster_metadata_base.__init__(self, "raster_metadata", ident, datatype, cols, rows, number_of_cells, nsres, ewres, min, max)
+
+ self.set_strds_register(strds_register)
+
+ def set_strds_register(self, strds_register):
+ """Set the space time raster dataset register table name"""
+ self.D["strds_register"] = strds_register
+
+ def get_strds_register(self):
+ """Get the space time raster dataset register table name
+ @return None if not found"""
+ if self.D.has_key("strds_register"):
+ return self.D["strds_register"]
+ else:
+ return None
+
+###############################################################################
+
+class raster3d_metadata(raster_metadata_base):
+ """This is the raster3d metadata class"""
+ 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):
+
+ raster_metadata_base.__init__(self, "raster3d_metadata", ident, datatype, cols, rows, number_of_cells, nsres, ewres, min, max)
+
+ self.set_str3ds_register(str3ds_register)
+ self.set_tbres(tbres)
+ self.set_depths(depths)
+
+ def set_str3ds_register(self, str3ds_register):
+ """Set the space time raster3d dataset register table name"""
+ self.D["str3ds_register"] = str3ds_register
+
+ def set_depths(self, depths):
+ """Set the number of depths"""
+ self.D["depths"] = depths
+
+ def set_tbres(self, tbres):
+ """Set the top-bottom resolution"""
+ self.D["tbres"] = tbres
+
+ def get_str3ds_register(self):
+ """Get the space time raster3d dataset register table name
+ @return None if not found"""
+ if self.D.has_key("str3ds_register"):
+ return self.D["str3ds_register"]
+ else:
+ return None
+
+ def get_depths(self):
+ """Get number of depths
+ @return None if not found"""
+ if self.D.has_key("depths"):
+ return self.D["depths"]
+ else:
+ return None
+
+ def get_tbres(self):
+ """Get top-bottom resolution
+ @return None if not found"""
+ if self.D.has_key("tbres"):
+ return self.D["tbres"]
+ else:
+ return None
+
+###############################################################################
+
+class vector_metadata(sql_database_interface):
+ """This is the vector metadata class"""
+ def __init__(self, ident=None, stvds_register=None):
+
+ sql_database_interface.__init__(self, "vector_metadata", ident)
+
+ self.set_id(ident)
+ self.set_stvds_register(stvds_register)
+
+ def set_id(self, ident):
+ """Convenient method to set the unique identifier (primary key)"""
+ self.ident = ident
+ self.D["id"] = ident
+
+ def set_stvds_register(self, stvds_register):
+ """Set the space time vector dataset register table name"""
+ self.D["stvds_register"] = stvds_register
+
+ def get_id(self):
+ """Convenient method to get the unique identifier (primary key)
+ @return None if not found
+ """
+ if self.D.has_key("id"):
+ return self.D["id"]
+ else:
+ return None
+
+ def get_stvds_register(self):
+ """Get the space time vector dataset register table name
+ @return None if not found"""
+ if self.D.has_key("stvds_register"):
+ return self.D["stvds_register"]
+ else:
+ return None
+
+###############################################################################
+
+class abstract_dataset():
+ def __init__(self, ident):
+ self.reset(ident)
+
+ def reset(self, ident):
+ """Reset the internal structure and set the identifier"""
+ raise IOError("This method must be implemented in the subclasses")
+
+ def select(self):
+ """Select temporal dataset entry from database and fill up the internal structure"""
+ self.base.select()
+ if self.is_time_absolute():
+ self.absolute_time.select()
+ if self.is_time_relative():
+ self.relative_time.select()
+ self.spatial_extent.select()
+ self.metadata.select()
+
+ def is_in_db(self):
+ """Check if the temporal dataset entry is in the database"""
+ return self.base.is_in_db()
+
+ def delete(self):
+ """Delete temporal dataset entry from database if it exists"""
+ if self.is_in_db():
+ self.base.delete()
+
+ def insert(self):
+ """Insert temporal dataset entry into database from the internal structure"""
+ self.base.insert()
+ if self.is_time_absolute():
+ self.absolute_time.insert()
+ if self.is_time_relative():
+ self.relative_time.insert()
+ self.spatial_extent.insert()
+ self.metadata.insert()
+
+ def update(self):
+ """Update temporal dataset entry of database from the internal structure"""
+ self.base.update()
+ if self.is_time_absolute():
+ self.absolute_time.update()
+ if self.is_time_relative():
+ self.relative_time.update()
+ self.spatial_extent.update()
+ self.metadata.update()
+
+ 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()
+ if self.is_time_relative():
+ self.relative_time.print_self()
+ self.spatial_extent.print_self()
+ self.metadata.print_self()
+
+ def load_from_file(self):
+ raise IOError("This method must be implemented in the subclasses")
+
+ def is_time_absolute(self):
+ if self.base.D.has_key("temporal_type"):
+ return self.base.get_ttype() == "absolute"
+ else:
+ return None
+
+ def is_time_relative(self):
+ if self.base.D.has_key("temporal_type"):
+ return self.base.get_ttype() == "relative"
+ else:
+ return None
+
+ def temporal_relation(self, map):
+ """Return the temporal relation of this and the provided temporal raster 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.absolute_time)
+ return None
+
+###############################################################################
+
+class raster_dataset(abstract_dataset):
+ def __init__(self, ident):
+ self.reset(ident)
+
+ def reset(self, ident):
+ """Reset the internal structure and set the identifier"""
+ self.ident = ident
+
+ self.base = raster_base(ident=ident)
+ self.absolute_time = raster_absolute_time(ident=ident)
+ self.relative_time = raster_relative_time(ident=ident)
+ self.spatial_extent = raster_spatial_extent(ident=ident)
+ self.metadata = raster_metadata(ident=ident)
+
+ def load_from_file(self):
+
+ # Get the data from an existing raster map
+ kvp = raster.raster_info(self.ident)
+
+ # Fill base information
+
+ self.base.set_name(self.ident.split("@")[0])
+ self.base.set_mapset(self.ident.split("@")[1])
+ self.base.set_creator(str(getpass.getuser()))
+
+ # Fill spatial extent
+
+ self.spatial_extent.set_north(kvp["north"])
+ self.spatial_extent.set_south(kvp["south"])
+ self.spatial_extent.set_west(kvp["west"])
+ self.spatial_extent.set_east(kvp["east"])
+ self.spatial_extent.set_top(0)
+ self.spatial_extent.set_bottom(0)
+
+ # Fill metadata
+
+ self.metadata.set_nsres(kvp["nsres"])
+ self.metadata.set_ewres(kvp["ewres"])
+ self.metadata.set_datatype(kvp["datatype"])
+ self.metadata.set_min(kvp["min"])
+ self.metadata.set_max(kvp["max"])
+
+ rows = (kvp["north"] - kvp["south"])/kvp["nsres"]
+ cols = (kvp["east"] - kvp["west"])/kvp["ewres"]
+
+ ncells = cols * rows
+
+ self.metadata.set_cols(cols)
+ self.metadata.set_rows(rows)
+ self.metadata.set_number_of_cells(ncells)
+
+
+###############################################################################
+
+class raster3d_dataset(abstract_dataset):
+ def __init__(self, ident):
+ self.reset(ident)
+
+ def reset(self, ident):
+ """Reset the internal structure and set the identifier"""
+ self.ident = ident
+
+ self.base = raster3d_base(ident=ident)
+ self.absolute_time = raster3d_absolute_time(ident=ident)
+ self.relative_time = raster3d_relative_time(ident=ident)
+ self.spatial_extent = raster3d_spatial_extent(ident=ident)
+ self.metadata = raster3d_metadata(ident=ident)
+
+ def load_from_file(self):
+
+ # Get the data from an existing raster map
+ kvp = raster3d.raster3d_info(self.ident)
+
+ # Fill base information
+
+ self.base.set_name(self.ident.split("@")[0])
+ self.base.set_mapset(self.ident.split("@")[1])
+ self.base.set_creator(str(getpass.getuser()))
+
+ # Fill spatial extent
+
+ self.spatial_extent.set_north(kvp["north"])
+ self.spatial_extent.set_south(kvp["south"])
+ self.spatial_extent.set_west(kvp["west"])
+ self.spatial_extent.set_east(kvp["east"])
+ self.spatial_extent.set_top(kvp["top"])
+ self.spatial_extent.set_bottom(kvp["bottom"])
+
+ # Fill metadata
+
+ self.metadata.set_nsres(kvp["nsres"])
+ self.metadata.set_ewres(kvp["ewres"])
+ self.metadata.set_ewres(kvp["tbres"])
+ self.metadata.set_datatype(kvp["datatype"])
+ self.metadata.set_min(kvp["min"])
+ self.metadata.set_max(kvp["max"])
+
+ rows = (kvp["north"] - kvp["south"])/kvp["nsres"]
+ cols = (kvp["east"] - kvp["west"])/kvp["ewres"]
+ depths = (kvp["top"] - kvp["bottom"])/kvp["tbres"]
+
+ ncells = cols * rows * depths
+
+ self.metadata.set_cols(cols)
+ self.metadata.set_rows(depths)
+ self.metadata.set_depths(rows)
+ self.metadata.set_number_of_cells(ncells)
+
Added: grass/trunk/lib/temporal/map_stds_register_table_template.sql
===================================================================
--- grass/trunk/lib/temporal/map_stds_register_table_template.sql (rev 0)
+++ grass/trunk/lib/temporal/map_stds_register_table_template.sql 2011-09-05 14:29:35 UTC (rev 48132)
@@ -0,0 +1,37 @@
+--#############################################################################
+-- This SQL script generates the table listing all STDS in
+-- which the GRASS_MAP map is registered
+--
+-- This table is map specific and created for each GRASS_MAP map which is registered
+-- in a STDS. MAP_NAME is a placeholder for the dataset name.
+--
+-- Author: Soeren Gebbert soerengebbert <at> googlemail <dot> com
+--#############################################################################
+
+PRAGMA foreign_keys = ON;
+
+-- MAP_NAME is a placeholder for specific map name (SQL compliant): name_mapset
+-- MAP_ID is a placeholder for specific map id: name at mapset
+-- GRASS_MAP is a placeholder for specific map type: raster, raster3d or vector
+-- STDS is a placeholder for specific space-time dataset type: strds, str3ds, stvds
+
+-- This table stores the names of the space-time datasets in which this map is registered
+CREATE TABLE MAP_NAME_STDS_register (
+ id VARCHAR NOT NULL, -- This column is a primary foreign key storing the STDS names
+ PRIMARY KEY (id),
+ FOREIGN KEY (id) REFERENCES STDS_base (id) ON DELETE CASCADE
+);
+
+CREATE TRIGGER MAP_NAME_STDS_register_insert AFTER INSERT ON MAP_NAME_STDS_register
+ BEGIN
+ UPDATE GRASS_MAP_base SET modification_time = datetime("NOW") WHERE GRASS_MAP_base.id = "MAP_ID";
+ UPDATE GRASS_MAP_base SET revision = (revision + 1) WHERE GRASS_MAP_base.id = "MAP_ID";
+ END;
+
+CREATE TRIGGER MAP_NAME_STDS_register_delete AFTER DELETE ON MAP_NAME_STDS_register
+ BEGIN
+ UPDATE GRASS_MAP_base SET modification_time = datetime("NOW") WHERE GRASS_MAP_base.id = "MAP_ID";
+ UPDATE GRASS_MAP_base SET revision = (revision + 1) WHERE GRASS_MAP_base.id = "MAP_ID";
+ END;
+
+
Added: grass/trunk/lib/temporal/map_tables_template.sql
===================================================================
--- grass/trunk/lib/temporal/map_tables_template.sql (rev 0)
+++ grass/trunk/lib/temporal/map_tables_template.sql 2011-09-05 14:29:35 UTC (rev 48132)
@@ -0,0 +1,79 @@
+--#############################################################################
+-- This SQL script generates the grass map tables to store time stamps, revision
+-- and spatial extent for SQL queries and temporal GIS support.
+-- Additionally several triggers are created for convenient functions
+-- The grass map metadata is map specific (raster, raster3d and vector maps are
+-- supported)
+--
+-- The placeholder GRASS_MAP will be replaced by raster, raster3d and vector
+--
+-- Author: Soeren Gebbert soerengebbert <at> googlemail <dot> com
+--#############################################################################
+
+-- GRASS_MAP is a placeholder for specific map type: raster, raster3d or vector
+
+PRAGMA foreign_keys = ON;
+
+CREATE TABLE GRASS_MAP_base (
+ id VARCHAR NOT NULL, -- The id (PK) is the unique identifier for all tables, it is based on name and mapset (name at mapset) and is used as primary key
+ name VARCHAR NOT NULL, -- name of the grass map
+ mapset VARCHAR NOT NULL, -- mapset of the grass map
+ creator VARCHAR NOT NULL,
+ temporal_type VARCHAR, -- The temporal type of the grass map "absolute" or "relative" or NULL in case no time stamp is available
+ creation_time TIMESTAMP NOT NULL, -- The time of creation of the grass map
+ modification_time TIMESTAMP NOT NULL, -- The time of the last modification of the grass map
+ revision SMALLINT NOT NULL, -- The revision number
+ PRIMARY KEY (id)
+);
+
+CREATE TABLE GRASS_MAP_relative_time (
+ id VARCHAR NOT NULL, -- The id (PFK) is the unique identifier for all tables, it is based on name and mapset (name at mapset) and is used as primary foreign key
+ interval DOUBLE PRECISION, -- The relative time interval in [days], this interval starts always from 0 or the event befor this event
+ PRIMARY KEY (id),
+ FOREIGN KEY (id) REFERENCES GRASS_MAP_base (id) ON DELETE CASCADE
+);
+
+CREATE TABLE GRASS_MAP_absolute_time (
+ id VARCHAR NOT NULL, -- The id (PFK) is the unique identifier for all tables, it is based on name and mapset (name at mapset) and is used as primary foreign key
+ start_time TIMESTAMP, -- Start of the valid time, can be NULL if no time information is available
+ end_time TIMESTAMP, -- End of the valid time, can be NULL if no time information is available or valid time is a single point in time
+ timezone SMALLINT, -- The timezone of the valid time
+ PRIMARY KEY (id),
+ FOREIGN KEY (id) REFERENCES GRASS_MAP_base (id) ON DELETE CASCADE
+);
+
+-- The spatial extent of a raster map
+
+CREATE TABLE GRASS_MAP_spatial_extent (
+ id VARCHAR NOT NULL, -- The id (PFK) is the unique identifier for all tables, it is based on name and mapset (name at mapset) and is used as primary foreigen key
+ -- below is the spatial extent of the map
+ north DOUBLE PRECISION NOT NULL,
+ south DOUBLE PRECISION NOT NULL,
+ east DOUBLE PRECISION NOT NULL,
+ west DOUBLE PRECISION NOT NULL,
+ top DOUBLE PRECISION NOT NULL,
+ bottom DOUBLE PRECISION NOT NULL,
+ PRIMARY KEY (id),
+ FOREIGN KEY (id) REFERENCES GRASS_MAP_base (id) ON DELETE CASCADE
+);
+
+-- Create a trigger to update the modification time and revision number in case the metadata or timestanps have been updated
+
+CREATE TRIGGER update_GRASS_MAP_absolute_time AFTER UPDATE ON GRASS_MAP_absolute_time
+ BEGIN
+ UPDATE GRASS_MAP_base SET modification_time = datetime("NOW") WHERE id = old.id;
+ UPDATE GRASS_MAP_base SET revision = (revision + 1) WHERE id = old.id;
+ END;
+
+CREATE TRIGGER update_GRASS_MAP_relative_time AFTER UPDATE ON GRASS_MAP_relative_time
+ BEGIN
+ UPDATE GRASS_MAP_base SET modification_time = datetime("NOW") WHERE id = old.id;
+ UPDATE GRASS_MAP_base SET revision = (revision + 1) WHERE id = old.id;
+ END;
+
+
+CREATE TRIGGER update_GRASS_MAP_spatial_extent AFTER UPDATE ON GRASS_MAP_spatial_extent
+ BEGIN
+ UPDATE GRASS_MAP_base SET modification_time = datetime("NOW") WHERE id = old.id;
+ UPDATE GRASS_MAP_base SET revision = (revision + 1) WHERE id = old.id;
+ END;
Added: grass/trunk/lib/temporal/raster3d_metadata_table.sql
===================================================================
--- grass/trunk/lib/temporal/raster3d_metadata_table.sql (rev 0)
+++ grass/trunk/lib/temporal/raster3d_metadata_table.sql 2011-09-05 14:29:35 UTC (rev 48132)
@@ -0,0 +1,81 @@
+--#############################################################################
+-- This SQL script generates the raster3d metadata table to store
+-- and metadata for SQL queries and temporal GIS support. Additionally two views
+-- are created to access all map specific tables
+--
+-- Author: Soeren Gebbert soerengebbert <at> googlemail <dot> com
+--#############################################################################
+
+PRAGMA foreign_keys = ON;
+
+-- The metadata table reflects most of the raster3d metadata available in grass
+
+CREATE TABLE raster3d_metadata (
+ id VARCHAR NOT NULL, -- The id (PFK) is the unique identifier for all tables, it is based on name and mapset (name at mapset) and is used as primary foreign key
+ str3ds_register VARCHAR, -- The name of the table storing all space-time raster3d datasets in which this map is registered
+ maptype VARCHAR NOT NULL,
+ cols INTEGER NOT NULL,
+ rows INTEGER NOT NULL,
+ depths INTEGER NOT NULL,
+ number_of_cells INTEGER NOT NULL,
+ nsres DOUBLE PRECISION NOT NULL,
+ ewres DOUBLE PRECISION NOT NULL,
+ tbres DOUBLE PRECISION NOT NULL,
+ min DOUBLE PRECISION NOT NULL,
+ max DOUBLE PRECISION NOT NULL,
+ PRIMARY KEY (id),
+ FOREIGN KEY (id) REFERENCES raster3d_base (id) ON DELETE CASCADE
+);
+
+-- Create the views to access all cols for the absolute and relative time
+
+CREATE VIEW raster3d_view_abs_time AS SELECT
+ A1.id, A1.mapset,
+ A1.name, A1.temporal_type,
+ A1.creation_time, A1.modification_time,
+ A1.revision, A1.creator,
+ A2.start_time, A2.end_time,
+ A3.north, A3.south, A3.east, A3.west,
+ A4.maptype, A4.cols, A4.rows, A4.depths,
+ A4.nsres, A4.ewres, A4.tbres,
+ A4.min, A4.max,
+ A4.str3ds_register,
+ A4.number_of_cells
+ FROM raster3d_base A1, raster3d_absolute_time A2,
+ raster3d_spatial_extent A3, raster3d_metadata A4
+ WHERE A1.id = A2.id AND A1.id = A3.id AND A1.id = A4.id;
+
+CREATE VIEW raster3d_view_rel_time AS SELECT
+ A1.id, A1.mapset,
+ A1.name, A1.temporal_type,
+ A1.creation_time, A1.modification_time,
+ A1.revision, A1.creator,
+ A2.interval,
+ A3.north, A3.south, A3.east, A3.west,
+ A4.maptype, A4.cols, A4.rows, A4.depths,
+ A4.nsres, A4.ewres, A4.tbres,
+ A4.min, A4.max,
+ A4.str3ds_register,
+ A4.number_of_cells
+ FROM raster3d_base A1, raster3d_relative_time A2,
+ raster3d_spatial_extent A3, raster3d_metadata A4
+ WHERE A1.id = A2.id AND A1.id = A3.id AND A1.id = A4.id;
+
+-- Create a trigger to update the modification time and revision number in case the metadata have been updated
+
+CREATE TRIGGER update_raster3d_metadata AFTER UPDATE ON raster3d_metadata
+ BEGIN
+ UPDATE raster3d_base SET modification_time = datetime("NOW") WHERE id = old.id;
+ UPDATE raster3d_base SET revision = (revision + 1) WHERE id = old.id;
+ END;
+
+-- Create trigger for automated deletion of dependent rows, this should normally be done using foreign keys
+
+CREATE TRIGGER delete_raster3d_base AFTER DELETE ON raster3d_base
+ BEGIN
+ DELETE FROM raster3d_absolute_time WHERE id = old.id;
+ DELETE FROM raster3d_relative_time WHERE id = old.id;
+ DELETE FROM raster3d_spatial_extent WHERE id = old.id;
+ DELETE FROM raster3d_metadata WHERE id = old.id;
+ END;
+
Added: grass/trunk/lib/temporal/raster_metadata_table.sql
===================================================================
--- grass/trunk/lib/temporal/raster_metadata_table.sql (rev 0)
+++ grass/trunk/lib/temporal/raster_metadata_table.sql 2011-09-05 14:29:35 UTC (rev 48132)
@@ -0,0 +1,77 @@
+--#############################################################################
+-- This SQL script generates the raster metadata table to store
+-- and metadata for SQL queries and temporal GIS support. Additionally two views
+-- are created to access all map specific tables
+--
+-- Author: Soeren Gebbert soerengebbert <at> googlemail <dot> com
+--#############################################################################
+
+PRAGMA foreign_keys = ON;
+
+-- The metadata table reflects most of the raster metadata available in grass
+
+CREATE TABLE raster_metadata (
+ id VARCHAR NOT NULL, -- The id (PFK) is the unique identifier for all tables, it is based on name and mapset (name at mapset) and is used as primary foreign key
+ strds_register VARCHAR, -- The name of the table storing all space-time raster datasets in which this map is registered
+ datatype VARCHAR NOT NULL,
+ cols INTEGER NOT NULL,
+ rows INTEGER NOT NULL,
+ number_of_cells INTEGER NOT NULL,
+ nsres DOUBLE PRECISION NOT NULL,
+ ewres DOUBLE PRECISION NOT NULL,
+ min DOUBLE PRECISION NOT NULL,
+ max DOUBLE PRECISION NOT NULL,
+ PRIMARY KEY (id),
+ FOREIGN KEY (id) REFERENCES raster_base (id) ON DELETE CASCADE
+);
+
+-- Create the views to access all cols for the absolute and relative time
+
+CREATE VIEW raster_view_abs_time AS SELECT
+ A1.id, A1.mapset,
+ A1.name, A1.temporal_type,
+ A1.creation_time, A1.modification_time,
+ A1.revision, A1.creator,
+ A2.start_time, A2.end_time,
+ A3.north, A3.south, A3.east, A3.west,
+ A4.datatype, A4.cols, A4.rows,
+ A4.nsres, A4.ewres, A4.min, A4.max,
+ A4.strds_register,
+ A4.number_of_cells
+ FROM raster_base A1, raster_absolute_time A2,
+ raster_spatial_extent A3, raster_metadata A4
+ WHERE A1.id = A2.id AND A1.id = A3.id AND A1.id = A4.id;
+
+CREATE VIEW raster_view_rel_time AS SELECT
+ A1.id, A1.mapset,
+ A1.name, A1.temporal_type,
+ A1.creation_time, A1.modification_time,
+ A1.revision, A1.creator,
+ A2.interval,
+ A3.north, A3.south, A3.east, A3.west,
+ A4.datatype, A4.cols, A4.rows,
+ A4.nsres, A4.ewres, A4.min, A4.max,
+ A4.strds_register,
+ A4.number_of_cells
+ FROM raster_base A1, raster_relative_time A2,
+ raster_spatial_extent A3, raster_metadata A4
+ WHERE A1.id = A2.id AND A1.id = A3.id AND A1.id = A4.id;
+
+-- Create a trigger to update the modification time and revision number in case the metadata have been updated
+
+CREATE TRIGGER update_raster_metadata AFTER UPDATE ON raster_metadata
+ BEGIN
+ UPDATE raster_base SET modification_time = datetime("NOW") WHERE id = old.id;
+ UPDATE raster_base SET revision = (revision + 1) WHERE id = old.id;
+ END;
+
+-- Create trigger for automated deletion of dependent rows, this should normally be done using foreign keys
+
+CREATE TRIGGER delete_raster_base AFTER DELETE ON raster_base
+ BEGIN
+ DELETE FROM raster_absolute_time WHERE id = old.id;
+ DELETE FROM raster_relative_time WHERE id = old.id;
+ DELETE FROM raster_spatial_extent WHERE id = old.id;
+ DELETE FROM raster_metadata WHERE id = old.id;
+ END;
+
Added: grass/trunk/lib/temporal/stds_map_register_table_template.sql
===================================================================
--- grass/trunk/lib/temporal/stds_map_register_table_template.sql (rev 0)
+++ grass/trunk/lib/temporal/stds_map_register_table_template.sql 2011-09-05 14:29:35 UTC (rev 48132)
@@ -0,0 +1,111 @@
+--#############################################################################
+-- This SQL script generates the table in which all registered GRASS_MAP maps
+-- are listed in.
+--
+-- This table will be created for each STDS.
+--
+-- Author: Soeren Gebbert soerengebbert <at> googlemail <dot> com
+--#############################################################################
+
+-- SPACETIME_NAME is a placeholder for specific stds name (SQL compliant): name_mapset
+-- SPACETIME_ID is a placeholder for specific stds id: name at mapset
+-- GRASS_MAP is a placeholder for specific map type: raster, raster3d or vector
+-- STDS is a placeholder for specific space-time dataset type: strds, str3ds, stvds
+
+PRAGMA foreign_keys = ON;
+
+-- This table stores the.ids of the GRASS_MAP maps registered in the current spacetime GRASS_MAP table
+CREATE TABLE SPACETIME_NAME_GRASS_MAP_register (
+ id VARCHAR NOT NULL, -- This colum is a primary foreign key storing the registered GRASS_MAP map.ids
+ PRIMARY KEY (id),
+ FOREIGN KEY (id) REFERENCES GRASS_MAP_base (id) ON DELETE CASCADE
+);
+
+CREATE TRIGGER SPACETIME_NAME_GRASS_MAP_register_insert_trigger AFTER INSERT ON SPACETIME_NAME_GRASS_MAP_register
+ BEGIN
+ UPDATE STDS_base SET modification_time = datetime("NOW") WHERE id = "SPACETIME_ID";
+ UPDATE STDS_base SET revision = (revision + 1) WHERE id = "SPACETIME_ID";
+ -- Number of registered maps
+ UPDATE STDS_metadata SET number_of_registered_maps =
+ (SELECT count.id) FROM SPACETIME_NAME_GRASS_MAP_register)
+ WHERE id = "SPACETIME_ID";
+ -- Update the temporal extent
+ UPDATE STDS_absolute_time SET start_time =
+ (SELECT min(start_time) FROM GRASS_MAP_absolute_time WHERE GRASS_MAP_absolute_time.id IN
+ (SELECT id FROM SPACETIME_NAME_GRASS_MAP_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE STDS_absolute_time SET end_time =
+ (SELECT max(end_time) FROM GRASS_MAP_absolute_time WHERE GRASS_MAP_absolute_time.id IN
+ (SELECT id FROM SPACETIME_NAME_GRASS_MAP_register)
+ ) WHERE id = "SPACETIME_ID";
+ -- Update the spatial extent
+ UPDATE STDS_spatial_extent SET north =
+ (SELECT max(north) FROM GRASS_MAP_spatial_extent WHERE GRASS_MAP_spatial_extent.id IN
+ (SELECT id FROM SPACETIME_NAME_GRASS_MAP_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE STDS_spatial_extent SET south =
+ (SELECT min(south) FROM GRASS_MAP_spatial_extent WHERE GRASS_MAP_spatial_extent.id IN
+ (SELECT id FROM SPACETIME_NAME_GRASS_MAP_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE STDS_spatial_extent SET east =
+ (SELECT max(east) FROM GRASS_MAP_spatial_extent WHERE GRASS_MAP_spatial_extent.id IN
+ (SELECT id FROM SPACETIME_NAME_GRASS_MAP_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE STDS_spatial_extent SET west =
+ (SELECT min(west) FROM GRASS_MAP_spatial_extent WHERE GRASS_MAP_spatial_extent.id IN
+ (SELECT id FROM SPACETIME_NAME_GRASS_MAP_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE STDS_spatial_extent SET top =
+ (SELECT max(top) FROM GRASS_MAP_spatial_extent WHERE GRASS_MAP_spatial_extent.id IN
+ (SELECT id FROM SPACETIME_NAME_GRASS_MAP_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE STDS_spatial_extent SET bottom =
+ (SELECT min(bottom) FROM GRASS_MAP_spatial_extent WHERE GRASS_MAP_spatial_extent.id IN
+ (SELECT id FROM SPACETIME_NAME_GRASS_MAP_register)
+ ) WHERE id = "SPACETIME_ID";
+ END;
+
+CREATE TRIGGER SPACETIME_NAME_GRASS_MAP_register_delete_trigger AFTER DELETE ON SPACETIME_NAME_GRASS_MAP_register
+ BEGIN
+ UPDATE STDS_base SET modification_time = datetime("NOW") WHERE id = "SPACETIME_ID";
+ UPDATE STDS_base SET revision = (revision + 1) WHERE id = "SPACETIME_ID";
+ -- Number of registered maps
+ UPDATE STDS_metadata SET number_of_registered_maps =
+ (SELECT count.id) FROM SPACETIME_NAME_GRASS_MAP_register)
+ WHERE id = "SPACETIME_ID";
+ -- Update the temporal extent
+ UPDATE STDS_absolute_time SET start_time =
+ (SELECT min(start_time) FROM GRASS_MAP_absolute_time WHERE GRASS_MAP_absolute_time.id IN
+ (SELECT id FROM SPACETIME_NAME_GRASS_MAP_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE STDS_absolute_time SET end_time =
+ (SELECT max(end_time) FROM GRASS_MAP_absolute_time WHERE GRASS_MAP_absolute_time.id IN
+ (SELECT id FROM SPACETIME_NAME_GRASS_MAP_register)
+ ) WHERE id = "SPACETIME_ID";
+ -- Update the spatial extent
+ UPDATE STDS_spatial_extent SET north =
+ (SELECT max(north) FROM GRASS_MAP_spatial_extent WHERE GRASS_MAP_spatial_extent.id IN
+ (SELECT id FROM SPACETIME_NAME_GRASS_MAP_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE STDS_spatial_extent SET south =
+ (SELECT min(south) FROM GRASS_MAP_spatial_extent WHERE GRASS_MAP_spatial_extent.id IN
+ (SELECT id FROM SPACETIME_NAME_GRASS_MAP_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE STDS_spatial_extent SET east =
+ (SELECT max(east) FROM GRASS_MAP_spatial_extent WHERE GRASS_MAP_spatial_extent.id IN
+ (SELECT id FROM SPACETIME_NAME_GRASS_MAP_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE STDS_spatial_extent SET west =
+ (SELECT min(west) FROM GRASS_MAP_spatial_extent WHERE GRASS_MAP_spatial_extent.id IN
+ (SELECT id FROM SPACETIME_NAME_GRASS_MAP_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE STDS_spatial_extent SET top =
+ (SELECT max(top) FROM GRASS_MAP_spatial_extent WHERE GRASS_MAP_spatial_extent.id IN
+ (SELECT id FROM SPACETIME_NAME_GRASS_MAP_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE STDS_spatial_extent SET bottom =
+ (SELECT min(bottom) FROM GRASS_MAP_spatial_extent WHERE GRASS_MAP_spatial_extent.id IN
+ (SELECT id FROM SPACETIME_NAME_GRASS_MAP_register)
+ ) WHERE id = "SPACETIME_ID";
+ END;
+
Added: grass/trunk/lib/temporal/stds_raster3d_register_trigger_template.sql
===================================================================
--- grass/trunk/lib/temporal/stds_raster3d_register_trigger_template.sql (rev 0)
+++ grass/trunk/lib/temporal/stds_raster3d_register_trigger_template.sql 2011-09-05 14:29:35 UTC (rev 48132)
@@ -0,0 +1,104 @@
+--#############################################################################
+-- This SQL script creates a trigger to update a space-time raster3d dataset
+-- metadata
+--
+-- Author: Soeren Gebbert soerengebbert <at> googlemail <dot> com
+--#############################################################################
+
+-- SPACETIME_NAME is a placeholder for specific stds name (SQL compliant): name_mapset
+-- SPACETIME_ID is a placeholder for specific stds id: name at mapset
+
+PRAGMA foreign_keys = ON;
+
+CREATE TRIGGER SPACETIME_NAME_raster3d_metadata_register_insert_trigger AFTER INSERT ON SPACETIME_NAME_raster3d_register
+ BEGIN
+ -- Update the min and max values
+ UPDATE str3ds_metadata SET min_min =
+ (SELECT min(min) FROM raster3d_metadata WHERE raster3d_metadata.id IN
+ (SELECT id FROM SPACETIME_NAME_raster3d_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE str3ds_metadata SET min_max =
+ (SELECT max(min) FROM raster3d_metadata WHERE raster3d_metadata.id IN
+ (SELECT id FROM SPACETIME_NAME_raster3d_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE str3ds_metadata SET max_min =
+ (SELECT min(max) FROM raster3d_metadata WHERE raster3d_metadata.id IN
+ (SELECT id FROM SPACETIME_NAME_raster3d_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE str3ds_metadata SET max_max =
+ (SELECT max(max) FROM raster3d_metadata WHERE raster3d_metadata.id IN
+ (SELECT id FROM SPACETIME_NAME_raster3d_register)
+ ) WHERE id = "SPACETIME_ID";
+ -- Update the resolution
+ UPDATE str3ds_metadata SET nsres_min =
+ (SELECT min(nsres) FROM raster3d_metadata WHERE raster3d_metadata.id IN
+ (SELECT id FROM SPACETIME_NAME_raster3d_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE str3ds_metadata SET nsres_max =
+ (SELECT max(nsres) FROM raster3d_metadata WHERE raster3d_metadata.id IN
+ (SELECT id FROM SPACETIME_NAME_raster3d_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE str3ds_metadata SET ewres_min =
+ (SELECT min(ewres) FROM raster3d_metadata WHERE raster3d_metadata.id IN
+ (SELECT id FROM SPACETIME_NAME_raster3d_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE str3ds_metadata SET ewres_max =
+ (SELECT max(ewres) FROM raster3d_metadata WHERE raster3d_metadata.id IN
+ (SELECT id FROM SPACETIME_NAME_raster3d_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE str3ds_metadata SET tbres_min =
+ (SELECT min(tbres) FROM raster3d_metadata WHERE raster3d_metadata.id IN
+ (SELECT id FROM SPACETIME_NAME_raster3d_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE str3ds_metadata SET tbres_max =
+ (SELECT max(tbres) FROM raster3d_metadata WHERE raster3d_metadata.id IN
+ (SELECT id FROM SPACETIME_NAME_raster3d_register)
+ ) WHERE id = "SPACETIME_ID";
+ END;
+
+CREATE TRIGGER SPACETIME_NAME_raster3d_metadata_register_delete_trigger AFTER DELETE ON SPACETIME_NAME_raster3d_register
+ BEGIN
+ -- Update the min and max values
+ UPDATE str3ds_metadata SET min_min =
+ (SELECT min(min) FROM raster3d_metadata WHERE raster3d_metadata.id IN
+ (SELECT id FROM SPACETIME_NAME_raster3d_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE str3ds_metadata SET min_max =
+ (SELECT max(min) FROM raster3d_metadata WHERE raster3d_metadata.id IN
+ (SELECT id FROM SPACETIME_NAME_raster3d_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE str3ds_metadata SET max_min =
+ (SELECT min(max) FROM raster3d_metadata WHERE raster3d_metadata.id IN
+ (SELECT id FROM SPACETIME_NAME_raster3d_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE str3ds_metadata SET max_max =
+ (SELECT max(max) FROM raster3d_metadata WHERE raster3d_metadata.id IN
+ (SELECT id FROM SPACETIME_NAME_raster3d_register)
+ ) WHERE id = "SPACETIME_ID";
+ -- Update the resolution
+ UPDATE str3ds_metadata SET nsres_min =
+ (SELECT min(nsres) FROM raster3d_metadata WHERE raster3d_metadata.id IN
+ (SELECT id FROM SPACETIME_NAME_raster3d_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE str3ds_metadata SET nsres_max =
+ (SELECT max(nsres) FROM raster3d_metadata WHERE raster3d_metadata.id IN
+ (SELECT id FROM SPACETIME_NAME_raster3d_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE str3ds_metadata SET ewres_min =
+ (SELECT min(ewres) FROM raster3d_metadata WHERE raster3d_metadata.id IN
+ (SELECT id FROM SPACETIME_NAME_raster3d_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE str3ds_metadata SET ewres_max =
+ (SELECT max(ewres) FROM raster3d_metadata WHERE raster3d_metadata.id IN
+ (SELECT id FROM SPACETIME_NAME_raster3d_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE str3ds_metadata SET tbres_min =
+ (SELECT min(tbres) FROM raster3d_metadata WHERE raster3d_metadata.id IN
+ (SELECT id FROM SPACETIME_NAME_raster3d_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE str3ds_metadata SET tbres_max =
+ (SELECT max(tbres) FROM raster3d_metadata WHERE raster3d_metadata.id IN
+ (SELECT id FROM SPACETIME_NAME_raster3d_register)
+ ) WHERE id = "SPACETIME_ID";
+ END;
+
Added: grass/trunk/lib/temporal/stds_raster_register_trigger_template.sql
===================================================================
--- grass/trunk/lib/temporal/stds_raster_register_trigger_template.sql (rev 0)
+++ grass/trunk/lib/temporal/stds_raster_register_trigger_template.sql 2011-09-05 14:29:35 UTC (rev 48132)
@@ -0,0 +1,88 @@
+--#############################################################################
+-- This SQL script creates a trigger to update a space-time raster dataset
+-- metadata
+--
+-- Author: Soeren Gebbert soerengebbert <at> googlemail <dot> com
+--#############################################################################
+
+-- SPACETIME_NAME is a placeholder for specific stds name (SQL compliant): name_mapset
+-- SPACETIME_ID is a placeholder for specific stds id: name at mapset
+
+PRAGMA foreign_keys = ON;
+
+CREATE TRIGGER SPACETIME_NAME_raster_metadata_register_insert_trigger AFTER INSERT ON SPACETIME_NAME_raster_register
+ BEGIN
+ -- Update the min and max values
+ UPDATE strds_metadata SET min_min =
+ (SELECT min(min) FROM raster_metadata WHERE raster_metadata.id IN
+ (SELECT id FROM SPACETIME_NAME_raster_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE strds_metadata SET min_max =
+ (SELECT max(min) FROM raster_metadata WHERE raster_metadata.id IN
+ (SELECT id FROM SPACETIME_NAME_raster_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE strds_metadata SET max_min =
+ (SELECT min(max) FROM raster_metadata WHERE raster_metadata.id IN
+ (SELECT id FROM SPACETIME_NAME_raster_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE strds_metadata SET max_max =
+ (SELECT max(max) FROM raster_metadata WHERE raster_metadata.id IN
+ (SELECT id FROM SPACETIME_NAME_raster_register)
+ ) WHERE id = "SPACETIME_ID";
+ -- Update the resolution
+ UPDATE strds_metadata SET nsres_min =
+ (SELECT min(nsres) FROM raster_metadata WHERE raster_metadata.id IN
+ (SELECT id FROM SPACETIME_NAME_raster_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE strds_metadata SET nsres_max =
+ (SELECT max(nsres) FROM raster_metadata WHERE raster_metadata.id IN
+ (SELECT id FROM SPACETIME_NAME_raster_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE strds_metadata SET ewres_min =
+ (SELECT min(ewres) FROM raster_metadata WHERE raster_metadata.id IN
+ (SELECT id FROM SPACETIME_NAME_raster_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE strds_metadata SET ewres_max =
+ (SELECT max(ewres) FROM raster_metadata WHERE raster_metadata.id IN
+ (SELECT id FROM SPACETIME_NAME_raster_register)
+ ) WHERE id = "SPACETIME_ID";
+ END;
+
+CREATE TRIGGER SPACETIME_NAME_raster_metadata_register_delete_trigger AFTER DELETE ON SPACETIME_NAME_raster_register
+ BEGIN
+ -- Update the min and max values
+ UPDATE strds_metadata SET min_min =
+ (SELECT min(min) FROM raster_metadata WHERE raster_metadata.id IN
+ (SELECT id FROM SPACETIME_NAME_raster_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE strds_metadata SET min_max =
+ (SELECT max(min) FROM raster_metadata WHERE raster_metadata.id IN
+ (SELECT id FROM SPACETIME_NAME_raster_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE strds_metadata SET max_min =
+ (SELECT min(max) FROM raster_metadata WHERE raster_metadata.id IN
+ (SELECT id FROM SPACETIME_NAME_raster_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE strds_metadata SET max_max =
+ (SELECT max(max) FROM raster_metadata WHERE raster_metadata.id IN
+ (SELECT id FROM SPACETIME_NAME_raster_register)
+ ) WHERE id = "SPACETIME_ID";
+ -- Update the resolution
+ UPDATE strds_metadata SET nsres_min =
+ (SELECT min(nsres) FROM raster_metadata WHERE raster_metadata.id IN
+ (SELECT id FROM SPACETIME_NAME_raster_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE strds_metadata SET nsres_max =
+ (SELECT max(nsres) FROM raster_metadata WHERE raster_metadata.id IN
+ (SELECT id FROM SPACETIME_NAME_raster_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE strds_metadata SET ewres_min =
+ (SELECT min(ewres) FROM raster_metadata WHERE raster_metadata.id IN
+ (SELECT id FROM SPACETIME_NAME_raster_register)
+ ) WHERE id = "SPACETIME_ID";
+ UPDATE strds_metadata SET ewres_max =
+ (SELECT max(ewres) FROM raster_metadata WHERE raster_metadata.id IN
+ (SELECT id FROM SPACETIME_NAME_raster_register)
+ ) WHERE id = "SPACETIME_ID";
+ END;
+
Added: grass/trunk/lib/temporal/stds_tables_template.sql
===================================================================
--- grass/trunk/lib/temporal/stds_tables_template.sql (rev 0)
+++ grass/trunk/lib/temporal/stds_tables_template.sql 2011-09-05 14:29:35 UTC (rev 48132)
@@ -0,0 +1,74 @@
+--#############################################################################
+-- This SQL script generates the space time dataset tables to store time
+-- stamps and revision for SQL queries and temporal GIS support.
+--
+-- Author: Soeren Gebbert soerengebbert <at> googlemail <dot> com
+--#############################################################################
+
+-- STDS is a placeholder for specific space-time dataset type: strds, str3ds, stvds
+
+PRAGMA foreign_keys = ON;
+
+CREATE TABLE STDS_base (
+ id VARCHAR NOT NULL, -- Id of the space-time dataset, name at mapset this is the primary key
+ name VARCHAR NOT NULL, -- name of the space-time dataset
+ mapset VARCHAR NOT NULL, -- mapset of the space-time dataset
+ creator VARCHAR NOT NULL, -- Name of the creator
+ temporal_type VARCHAR NOT NULL, -- The temporal type of the dataset "absolute" or "relative"
+ semantic_type VARCHAR NOT NULL, -- The semantic data description used for aggregation/decomposition algorithm selection
+ creation_time TIMESTAMP NOT NULL, -- The time of creation of the space-time dataset
+ modification_time TIMESTAMP NOT NULL, -- The time of the last modification of the space-time dataset
+ revision SMALLINT NOT NULL, -- The revision number
+ PRIMARY KEY (id)
+);
+
+CREATE TABLE STDS_relative_time (
+ id VARCHAR NOT NULL, -- Id of the space-time dataset, this is the primary foreign key
+ interval DOUBLE, -- The relative time interval in [days], this interval starts always at 0 days
+ granularity DOUBLE, -- The granularity in [days]
+ PRIMARY KEY (id),
+ FOREIGN KEY (id) REFERENCES STDS_base (id) ON DELETE CASCADE
+);
+
+CREATE TABLE STDS_absolute_time (
+ id VARCHAR NOT NULL, -- Id of the space-time dataset, this is the primary foreign key
+ start_time TIMESTAMP, -- Start of the valid time, can be NULL if no map is registered
+ end_time TIMESTAMP, -- End of the valid time, can be NULL if no map is registered
+ granularity VARCHAR, -- The granularity "NNN seconds, NNN minutes, NNN hours, NNN days, NNN weeks, NNN months, NNN years"
+ timezone SMALLINT, -- The time zone number
+ PRIMARY KEY (id),
+ FOREIGN KEY (id) REFERENCES STDS_base (id) ON DELETE CASCADE
+);
+
+CREATE TABLE STDS_spatial_extent (
+ id VARCHAR NOT NULL, -- Id of the space-time dataset, this is the primary foreign key
+ north DOUBLE PRECISION, -- The spatial north extent, derived from the registered maps
+ south DOUBLE PRECISION, -- The spatial south extent, derived from the registered maps
+ east DOUBLE PRECISION, -- The spatial east extent, derived from the registered maps
+ west DOUBLE PRECISION, -- The spatial west extent, derived from the registered maps
+ top DOUBLE PRECISION, -- The spatial top extent, derived from the registered maps
+ bottom DOUBLE PRECISION, -- The spatial bottom extent, derived from the registered maps
+ PRIMARY KEY (id),
+ FOREIGN KEY (id) REFERENCES STDS_base (id) ON DELETE CASCADE
+);
+
+-- Create a trigger to update the modification time and revision number in case the metadata or timestanps have been updated
+
+CREATE TRIGGER update_STDS_abs_time AFTER UPDATE ON STDS_absolute_time
+ BEGIN
+ UPDATE STDS_base SET modification_time = datetime("NOW") WHERE id = old.id;
+ UPDATE STDS_base SET revision = (revision + 1) WHERE id = old.id;
+ END;
+
+CREATE TRIGGER update_STDS_rel_time AFTER UPDATE ON STDS_relative_time
+ BEGIN
+ UPDATE STDS_base SET modification_time = datetime("NOW") WHERE id = old.id;
+ UPDATE STDS_base SET revision = (revision + 1) WHERE id = old.id;
+ END;
+
+CREATE TRIGGER update_STDS_spatial_extent AFTER UPDATE ON STDS_spatial_extent
+ BEGIN
+ UPDATE STDS_base SET modification_time = datetime("NOW") WHERE id = old.id;
+ UPDATE STDS_base SET revision = (revision + 1) WHERE id = old.id;
+ END;
+
Added: grass/trunk/lib/temporal/str3ds_metadata_table.sql
===================================================================
--- grass/trunk/lib/temporal/str3ds_metadata_table.sql (rev 0)
+++ grass/trunk/lib/temporal/str3ds_metadata_table.sql 2011-09-05 14:29:35 UTC (rev 48132)
@@ -0,0 +1,87 @@
+--#############################################################################
+-- This SQL script generates the space time raster3d dataset metadata table,
+-- view and trigger
+--
+-- Author: Soeren Gebbert soerengebbert <at> googlemail <dot> com
+--#############################################################################
+
+PRAGMA foreign_keys = ON;
+
+CREATE TABLE str3ds_metadata (
+ id VARCHAR NOT NULL, -- Id of the space-time raster3d dataset, this is the primary foreign key
+ raster3d_register VARCHAR, -- The id of the table in which the raster3d maps are registered for this dataset
+ number_of_registered_maps INTEGER, -- The number of registered raster3d maps
+ max_min DOUBLE PRECISION, -- The minimal maximum of the registered raster3d maps
+ min_min DOUBLE PRECISION, -- The minimal minimum of the registered raster3d maps
+ max_max DOUBLE PRECISION, -- The maximal maximum of the registered raster3d maps
+ min_max DOUBLE PRECISION, -- The maximal minimum of the registered raster3d maps
+ nsres_min DOUBLE PRECISION, -- The lowest north-south resolution of the registered raster3d maps
+ nsres_max DOUBLE PRECISION, -- The highest north-south resolution of the registered raster3d maps
+ ewres_min DOUBLE PRECISION, -- The lowest east-west resolution of the registered raster3d maps
+ ewres_max DOUBLE PRECISION, -- The highest east-west resolution of the registered raster3d maps
+ tbres_min DOUBLE PRECISION, -- The lowest top-bottom resolution of the registered raster3d maps
+ tbres_max DOUBLE PRECISION, -- The highest top-bottom resolution of the registered raster3d maps
+ title VARCHAR, -- Title of the space-time raster3d dataset
+ description VARCHAR, -- Detailed description of the space-time raster3d dataset
+ PRIMARY KEY (id),
+ FOREIGN KEY (id) REFERENCES str3ds_base (id) ON DELETE CASCADE
+);
+-- Create the views to access all cols for absolute or relative time
+
+CREATE VIEW str3ds_view_abs_time AS SELECT
+ A1.id, A1.temporal_type,
+ A1.creator, A1.semantic_type,
+ A1.creation_time, A1.modification_time,
+ A1.revision, A2.start_time,
+ A2.end_time, A2.granularity,
+ A3.north, A3.south, A3.east, A3.west,
+ A4.raster3d_register,
+ A4.number_of_registered_maps,
+ A4.nsres_min, A4.ewres_min,
+ A4.nsres_max, A4.ewres_max,
+ A4.tbres_min, A4.tbres_max,
+ A4.min_min, A4.min_max,
+ A4.max_min, A4.max_max,
+ A4.title, A4.description
+ FROM str3ds_base A1, str3ds_absolute_time A2,
+ str3ds_spatial_extent A3, str3ds_metadata A4 WHERE A1.id = A2.id AND
+ A1.id = A3.id AND A1.id = A4.id;
+
+CREATE VIEW str3ds_view_rel_time AS SELECT
+ A1.id, A1.temporal_type,
+ A1.creator, A1.semantic_type,
+ A1.creation_time, A1.modification_time,
+ A1.revision,
+ A2.interval, A2.granularity,
+ A3.north, A3.south, A3.east, A3.west,
+ A4.raster3d_register,
+ A4.number_of_registered_maps,
+ A4.nsres_min, A4.ewres_min,
+ A4.nsres_max, A4.ewres_max,
+ A4.tbres_min, A4.tbres_max,
+ A4.min_min, A4.min_max,
+ A4.max_min, A4.max_max,
+ A4.title, A4.description
+ FROM str3ds_base A1, str3ds_relative_time A2,
+ str3ds_spatial_extent A3, str3ds_metadata A4 WHERE A1.id = A2.id AND
+ A1.id = A3.id AND A1.id = A4.id;
+
+
+-- Create a trigger to update the modification time and revision number in case the metadata or timestanps have been updated
+
+CREATE TRIGGER update_str3ds_metadata AFTER UPDATE ON str3ds_metadata
+ BEGIN
+ UPDATE str3ds_base SET modification_time = datetime("NOW") WHERE id = old.id;
+ UPDATE str3ds_base SET revision = (revision + 1) WHERE id = old.id;
+ END;
+
+-- Create trigger for automated deletion of dependent rows, this should normally be done using foreign keys
+
+CREATE TRIGGER delete_str3ds_base AFTER DELETE ON str3ds_base
+ BEGIN
+ DELETE FROM str3ds_absolute_time WHERE id = old.id;
+ DELETE FROM str3ds_relative_time WHERE id = old.id;
+ DELETE FROM str3ds_spatial_extent WHERE id = old.id;
+ DELETE FROM str3ds_metadata WHERE id = old.id;
+ END;
+
Added: grass/trunk/lib/temporal/strds_metadata_table.sql
===================================================================
--- grass/trunk/lib/temporal/strds_metadata_table.sql (rev 0)
+++ grass/trunk/lib/temporal/strds_metadata_table.sql 2011-09-05 14:29:35 UTC (rev 48132)
@@ -0,0 +1,83 @@
+--#############################################################################
+-- This SQL script generates the space time raster dataset metadata table,
+-- view and trigger
+--
+-- Author: Soeren Gebbert soerengebbert <at> googlemail <dot> com
+--#############################################################################
+
+PRAGMA foreign_keys = ON;
+
+CREATE TABLE strds_metadata (
+ id VARCHAR NOT NULL, -- Id of the space-time dataset, this is the primary foreign key
+ raster_register VARCHAR, -- The id of the table in which the raster maps are registered for this dataset
+ number_of_registered_maps INTEGER, -- The number of registered raster maps
+ max_min DOUBLE PRECISION, -- The minimal maximum of the registered raster maps
+ min_min DOUBLE PRECISION, -- The minimal minimum of the registered raster maps
+ max_max DOUBLE PRECISION, -- The maximal maximum of the registered raster maps
+ min_max DOUBLE PRECISION, -- The maximal minimum of the registered raster maps
+ nsres_min DOUBLE PRECISION, -- The lowest north-south resolution of the registered raster maps
+ nsres_max DOUBLE PRECISION, -- The highest north-south resolution of the registered raster maps
+ ewres_min DOUBLE PRECISION, -- The lowest east-west resolution of the registered raster maps
+ ewres_max DOUBLE PRECISION, -- The highest east-west resolution of the registered raster maps
+ title VARCHAR, -- Title of the space-time raster dataset
+ description VARCHAR, -- Detailed description of the space-time raster dataset
+ PRIMARY KEY (id),
+ FOREIGN KEY (id) REFERENCES strds_base (id) ON DELETE CASCADE
+);
+-- Create the views to access all cols for absolute or relative time
+
+CREATE VIEW strds_view_abs_time AS SELECT
+ A1.id, A1.temporal_type,
+ A1.creator, A1.semantic_type,
+ A1.creation_time, A1.modification_time,
+ A1.revision, A2.start_time,
+ A2.end_time, A2.granularity,
+ A3.north, A3.south, A3.east, A3.west,
+ A4.raster_register,
+ A4.number_of_registered_maps,
+ A4.nsres_min, A4.ewres_min,
+ A4.nsres_max, A4.ewres_max,
+ A4.min_min, A4.min_max,
+ A4.max_min, A4.max_max,
+ A4.title, A4.description
+ FROM strds_base A1, strds_absolute_time A2,
+ strds_spatial_extent A3, strds_metadata A4 WHERE A1.id = A2.id AND
+ A1.id = A3.id AND A1.id = A4.id;
+
+CREATE VIEW strds_view_rel_time AS SELECT
+ A1.id, A1.temporal_type,
+ A1.creator, A1.semantic_type,
+ A1.creation_time, A1.modification_time,
+ A1.revision,
+ A2.interval, A2.granularity,
+ A3.north, A3.south, A3.east, A3.west,
+ A4.raster_register,
+ A4.number_of_registered_maps,
+ A4.nsres_min, A4.ewres_min,
+ A4.nsres_max, A4.ewres_max,
+ A4.min_min, A4.min_max,
+ A4.max_min, A4.max_max,
+ A4.title, A4.description
+ FROM strds_base A1, strds_relative_time A2,
+ strds_spatial_extent A3, strds_metadata A4 WHERE A1.id = A2.id AND
+ A1.id = A3.id AND A1.id = A4.id;
+
+
+-- Create a trigger to update the modification time and revision number in case the metadata or timestanps have been updated
+
+CREATE TRIGGER update_strds_metadata AFTER UPDATE ON strds_metadata
+ BEGIN
+ UPDATE strds_base SET modification_time = datetime("NOW") WHERE id = old.id;
+ UPDATE strds_base SET revision = (revision + 1) WHERE id = old.id;
+ END;
+
+-- Create trigger for automated deletion of dependent rows, this should normally be done using foreign keys
+
+CREATE TRIGGER delete_strds_base AFTER DELETE ON strds_base
+ BEGIN
+ DELETE FROM strds_absolute_time WHERE id = old.id;
+ DELETE FROM strds_relative_time WHERE id = old.id;
+ DELETE FROM strds_spatial_extent WHERE id = old.id;
+ DELETE FROM strds_metadata WHERE id = old.id;
+ END;
+
Added: grass/trunk/lib/temporal/stvds_metadata_table.sql
===================================================================
--- grass/trunk/lib/temporal/stvds_metadata_table.sql (rev 0)
+++ grass/trunk/lib/temporal/stvds_metadata_table.sql 2011-09-05 14:29:35 UTC (rev 48132)
@@ -0,0 +1,67 @@
+--#############################################################################
+-- This SQL script generates the space time vector dataset metadata table,
+-- view and trigger
+--
+-- Author: Soeren Gebbert soerengebbert <at> googlemail <dot> com
+--#############################################################################
+
+PRAGMA foreign_keys = ON;
+
+CREATE TABLE stvds_metadata (
+ id VARCHAR NOT NULL, -- Name of the space-time vector dataset, this is the primary foreign key
+ vector_register VARCHAR, -- The id of the table in which the vector maps are registered for this dataset
+ number_of_registered_maps INTEGER, -- The number of registered vector maps
+ title VARCHAR, -- Title of the space-time vector dataset
+ description VARCHAR, -- Detailed description of the space-time vector dataset
+ PRIMARY KEY (id),
+ FOREIGN KEY (id) REFERENCES stvds_base (id) ON DELETE CASCADE
+);
+-- Create the views to access all columns for absolute or relative time
+
+CREATE VIEW stvds_view_abs_time AS SELECT
+ A1.id, A1.temporal_type,
+ A1.creator, A1.semantic_type,
+ A1.creation_time, A1.modification_time,
+ A1.revision, A2.start_time,
+ A2.end_time, A2.granularity,
+ A3.north, A3.south, A3.east, A3.west,
+ A4.vector_register,
+ A4.number_of_registered_maps,
+ A4.title, A4.description
+ FROM stvds_base A1, stvds_absolute_time A2,
+ stvds_spatial_extent A3, stvds_metadata A4 WHERE A1.id = A2.id AND
+ A1.id = A3.id AND A1.id = A4.id;
+
+CREATE VIEW stvds_view_rel_time AS SELECT
+ A1.id, A1.temporal_type,
+ A1.creator, A1.semantic_type,
+ A1.creation_time, A1.modification_time,
+ A1.revision,
+ A2.interval, A2.granularity,
+ A3.north, A3.south, A3.east, A3.west,
+ A4.vector_register,
+ A4.number_of_registered_maps,
+ A4.title, A4.description
+ FROM stvds_base A1, stvds_relative_time A2,
+ stvds_spatial_extent A3, stvds_metadata A4 WHERE A1.id = A2.id AND
+ A1.id = A3.id AND A1.id = A4.id;
+
+
+-- Create a trigger to update the modification time and revision number in case the metadata or timestanps have been updated
+
+CREATE TRIGGER update_stvds_metadata AFTER UPDATE ON stvds_metadata
+ BEGIN
+ UPDATE stvds_base SET modification_time = datetime("NOW") WHERE id = old.id;
+ UPDATE stvds_base SET revision = (revision + 1) WHERE id = old.id;
+ END;
+
+-- Create trigger for automated deletion of dependent rows, this should normally be done using foreign keys
+
+CREATE TRIGGER delete_stvds_base AFTER DELETE ON stvds_base
+ BEGIN
+ DELETE FROM stvds_absolute_time WHERE id = old.id;
+ DELETE FROM stvds_relative_time WHERE id = old.id;
+ DELETE FROM stvds_spatial_exntent WHERE id = old.id;
+ DELETE FROM stvds_metadata WHERE id = old.id;
+ END;
+
Added: grass/trunk/lib/temporal/test.temporal.py
===================================================================
--- grass/trunk/lib/temporal/test.temporal.py (rev 0)
+++ grass/trunk/lib/temporal/test.temporal.py 2011-09-05 14:29:35 UTC (rev 48132)
@@ -0,0 +1,374 @@
+from temporal import *
+import os
+
+###############################################################################
+
+def test_dict_sql_serializer():
+ t = dict_sql_serializer()
+ t.test()
+
+def test_dataset_identifer():
+ for i in range(2):
+ base = raster_base(ident="soil" + str(i) + "@PERMANENT", name="soil" + str(i), mapset="PERMANENT", creator="soeren", temporal_type="absolute", revision=1)
+ base.insert()
+ base.select()
+ base.print_self()
+ base.clear()
+ base.set_creator("rene")
+ base.update()
+ base.select()
+ base.print_self()
+
+ for i in range(2):
+ base = raster3d_base(ident="soil" + str(i) + "@PERMANENT", name="soil" + str(i), mapset="PERMANENT", creator="soeren")
+ base.insert()
+ base.select()
+ base.print_self()
+ base.clear()
+ base.set_creator("rene")
+ base.update()
+ base.select()
+ base.print_self()
+
+ for i in range(2):
+ base = vector_base(ident="soil" + str(i) + "@PERMANENT", name="soil" + str(i), mapset="PERMANENT", creator="soeren")
+ base.insert()
+ base.select()
+ base.print_self()
+ base.clear()
+ base.set_creator("rene")
+ base.update()
+ base.select()
+ base.print_self()
+
+def test_absolute_timestamp():
+ for i in range(2):
+ base = raster_absolute_time(ident="soil" + str(i) + "@PERMANENT", start_time=datetime(2011,01,01), end_time=datetime(2011,07,01), timezone=1)
+ base.insert()
+ base.select()
+ base.print_self()
+ base.clear()
+ base.set_start_time(datetime(2010,01,01))
+ base.update()
+ base.select()
+ base.print_self()
+
+ for i in range(2):
+ base = raster3d_absolute_time(ident="soil" + str(i) + "@PERMANENT", start_time=datetime(2011,01,01), end_time=datetime(2011,07,01), timezone=1)
+ base.insert()
+ base.select()
+ base.print_self()
+ base.clear()
+ base.set_start_time(datetime(2010,01,01))
+ base.update()
+ base.select()
+ base.print_self()
+
+ for i in range(2):
+ base = vector_absolute_time(ident="soil" + str(i) + "@PERMANENT", start_time=datetime(2011,01,01), end_time=datetime(2011,07,01), timezone=1)
+ base.insert()
+ base.select()
+ base.print_self()
+ base.clear()
+ base.set_start_time(datetime(2010,01,01))
+ base.update()
+ base.select()
+ base.print_self()
+
+def test_spatial_extent():
+ for i in range(2):
+ base = raster_spatial_extent(ident="soil" + str(i) + "@PERMANENT", north=100 + i, south=10+i, east=50+i, west=20+i, top=i, bottom=0)
+ base.insert()
+ base.select()
+ base.print_self()
+ base.clear()
+ base.set_north(120+i)
+ base.update()
+ base.select()
+ base.print_self()
+
+ for i in range(2):
+ base = raster3d_spatial_extent(ident="soil" + str(i) + "@PERMANENT", north=100 + i, south=10+i, east=50+i, west=20+i, top=i, bottom=0)
+ base.insert()
+ base.select()
+ base.print_self()
+ base.clear()
+ base.set_north(120+i)
+ base.update()
+ base.select()
+ base.print_self()
+
+ for i in range(2):
+ base = vector_spatial_extent(ident="soil" + str(i) + "@PERMANENT", north=100 + i, south=10+i, east=50+i, west=20+i, top=i, bottom=0)
+ base.insert()
+ base.select()
+ base.print_self()
+ base.clear()
+ base.set_north(120+i)
+ base.update()
+ base.select()
+ base.print_self()
+
+def test_relative_timestamp():
+ for i in range(2):
+ base = raster_relative_time(ident="soil" + str(i) + "@PERMANENT", interval=i)
+ base.insert()
+ base.select()
+ base.print_self()
+ base.clear()
+ base.set_interval(i+1)
+ base.update()
+ base.select()
+ base.print_self()
+
+ for i in range(2):
+ base = raster3d_relative_time(ident="soil" + str(i) + "@PERMANENT", interval=i)
+ base.insert()
+ base.select()
+ base.print_self()
+ base.clear()
+ base.set_interval(i+1)
+ base.update()
+ base.select()
+ base.print_self()
+
+ for i in range(2):
+ base = vector_relative_time(ident="soil" + str(i) + "@PERMANENT", interval=i)
+ base.insert()
+ base.select()
+ base.print_self()
+ base.clear()
+ base.set_interval(i+1)
+ base.update()
+ base.select()
+ base.print_self()
+
+def test_map_metadata():
+ for i in range(2):
+ base = raster_metadata(ident="soil" + str(i) + "@PERMANENT", strds_register="PERMANENT_soil_strds-register", maptype="CELL", \
+ cols=500, rows=400, number_of_cells=200000,nsres=1, ewres=1, min=0, max=33)
+ base.insert()
+ base.select()
+ base.print_self()
+ base.clear()
+ base.set_maptype("FCELL")
+ base.update()
+ base.select()
+ base.print_self()
+
+ for i in range(2):
+ base = raster3d_metadata(ident="soil" + str(i) + "@PERMANENT", str3ds_register="PERMANENT_soil_str3ds-register", maptype="FCELL", \
+ cols=500, rows=400, depths=20, number_of_cells=200000,nsres=1, ewres=1, tbres=10, min=0, max=33)
+ base.insert()
+ base.select()
+ base.print_self()
+ base.clear()
+ base.set_maptype("DCELL")
+ base.update()
+ base.select()
+ base.print_self()
+
+ for i in range(2):
+ base = vector_metadata(ident="soil" + str(i) + "@PERMANENT", stvds_register="PERMANENT_soil_stvds_register")
+ base.insert()
+ base.select()
+ base.print_self()
+ base.clear()
+ base.set_stvds_register("PERMANENT_soil_stvds_register")
+ base.update()
+ base.select()
+ base.print_self()
+
+def test_base_absolute_time_extent_metadata():
+
+ for i in range(10):
+ base = vector_base(ident="water" + str(i) + "@PERMANENT", name="water" + str(i), mapset="PERMANENT", creator="soeren")
+ base.insert()
+ base = raster_base(ident="water" + str(i) + "@PERMANENT", name="water" + str(i), mapset="PERMANENT", creator="soeren")
+ base.insert()
+ base = raster3d_base(ident="water" + str(i) + "@PERMANENT", name="water" + str(i), mapset="PERMANENT", creator="soeren")
+ base.insert()
+
+ for i in range(10):
+ base = vector_base(ident="water" + str(i) + "@PERMANENT")
+ base.set_creator("rene")
+ base.update()
+ base = raster_base(ident="water" + str(i) + "@PERMANENT")
+ base.set_creator("rene")
+ base.update()
+ base = raster3d_base(ident="water" + str(i) + "@PERMANENT")
+ base.set_creator("rene")
+ base.update()
+
+ for i in range(10):
+ base = vector_absolute_time(ident="water" + str(i) + "@PERMANENT", start_time=datetime.now(), end_time=datetime.now(), timezone=1)
+ base.insert()
+ base = raster_absolute_time(ident="water" + str(i) + "@PERMANENT", start_time=datetime.now(), end_time=datetime.now(), timezone=1)
+ base.insert()
+ base = raster3d_absolute_time(ident="water" + str(i) + "@PERMANENT", start_time=datetime.now(), end_time=datetime.now(), timezone=1)
+ base.insert()
+
+ for i in range(10):
+ base = vector_absolute_time(ident="water" + str(i) + "@PERMANENT")
+ base.set_start_time(datetime(2010, 6, 1))
+ base.update()
+ base = raster_absolute_time(ident="water" + str(i) + "@PERMANENT")
+ base.set_start_time(datetime(2010, 6, 1))
+ base.update()
+ base = raster3d_absolute_time(ident="water" + str(i) + "@PERMANENT")
+ base.set_start_time(datetime(2010, 6, 1))
+ base.update()
+
+ for i in range(10):
+ base = vector_spatial_extent(ident="water" + str(i) + "@PERMANENT", north=100 + i, south=10+i, east=50+i, west=20+i, top=i, bottom=0)
+ base.insert()
+ base = raster_spatial_extent(ident="water" + str(i) + "@PERMANENT", north=100 + i, south=10+i, east=50+i, west=20+i, top=0, bottom=0)
+ base.insert()
+ base = raster3d_spatial_extent(ident="water" + str(i) + "@PERMANENT", north=100 + i, south=10+i, east=50+i, west=20+i, top=i, bottom=0)
+ base.insert()
+
+ for i in range(10):
+ base = vector_spatial_extent(ident="water" + str(i) + "@PERMANENT")
+ base.set_north(120 + i)
+ base.set_south(20 + i)
+ base.update()
+ base = raster_spatial_extent(ident="water" + str(i) + "@PERMANENT")
+ base.set_north(120 + i)
+ base.set_south(20 + i)
+ base.update()
+ base = raster3d_spatial_extent(ident="water" + str(i) + "@PERMANENT")
+ base.set_north(120 + i)
+ base.set_south(20 + i)
+ base.update()
+
+ for i in range(10):
+ base = vector_metadata(ident="water" + str(i) + "@PERMANENT", stvds_register="PERMANENT_water_stvds_register")
+ base.insert()
+ base = raster_metadata(ident="water" + str(i) + "@PERMANENT", strds_register="PERMANENT_water_strds-register", maptype="CELL", \
+ cols=500, rows=400, number_of_cells=200000,nsres=1, ewres=1, min=0, max=33)
+ base.insert()
+ base = raster3d_metadata(ident="water" + str(i) + "@PERMANENT", str3ds_register="PERMANENT_water_str3ds-register", maptype="FCELL", \
+ cols=500, rows=400, depths=20, number_of_cells=200000,nsres=1, ewres=1, tbres=10, min=0, max=33)
+ base.insert()
+
+ for i in range(10):
+ base = vector_metadata(ident="water" + str(i) + "@PERMANENT")
+ base.set_stvds_register("PERMANENT_water_stvds_register")
+ base.update()
+ base = raster_metadata(ident="water" + str(i) + "@PERMANENT")
+ base.set_maptype("DCELL")
+ base.update()
+ base = raster3d_metadata(ident="water" + str(i) + "@PERMANENT")
+ base.set_maptype("DCELL")
+ base.update()
+
+ for i in range(10):
+ base = vector_base(ident="water" + str(i) + "@PERMANENT")
+ base.select()
+ base.print_self()
+ base = raster_base(ident="water" + str(i) + "@PERMANENT")
+ base.select()
+ base.print_self()
+ base = raster3d_base(ident="water" + str(i) + "@PERMANENT")
+ base.select()
+ base.print_self()
+
+ print "Create a raster object"
+
+ rds = raster_dataset("water0 at PERMANENT")
+ rds.select()
+ rds.print_self()
+
+ print rds.temporal_relation(rds)
+
+def test_absolut_time_temporal_relations():
+
+ A = raster_absolute_time(ident="test1 at PERMANENT", start_time=datetime(year=2000, month=1, day=1), \
+ end_time=datetime(year=2001, month=1, day=1), timezone=1)
+ B = raster_absolute_time(ident="test2 at PERMANENT", start_time=datetime(year=2001, month=1, day=1), \
+ end_time=datetime(year=2002, month=1, day=1), timezone=1)
+
+ print "Precedes: ", A.temporal_relation(B)
+ print "Follows: ", B.temporal_relation(A)
+
+ A = raster_absolute_time(ident="test1 at PERMANENT", start_time=datetime(year=2000, month=1, day=1), \
+ end_time=datetime(year=2001, month=1, day=1), timezone=1)
+ B = raster_absolute_time(ident="test2 at PERMANENT", start_time=datetime(year=2001, month=1, day=2), \
+ end_time=datetime(year=2002, month=1, day=1), timezone=1)
+
+ print "Before: ", A.temporal_relation(B)
+ print "After: ", B.temporal_relation(A)
+
+ A = raster_absolute_time(ident="test1 at PERMANENT", start_time=datetime(year=2000, month=1, day=1), \
+ end_time=datetime(year=2001, month=1, day=1), timezone=1)
+ B = raster_absolute_time(ident="test2 at PERMANENT", start_time=datetime(year=2000, month=1, day=1), \
+ end_time=datetime(year=2002, month=1, day=1), timezone=1)
+
+ print "Starts: ", A.temporal_relation(B)
+ print "Started: ", B.temporal_relation(A)
+
+ A = raster_absolute_time(ident="test1 at PERMANENT", start_time=datetime(year=2000, month=1, day=1), \
+ end_time=datetime(year=2001, month=1, day=1), timezone=1)
+ B = raster_absolute_time(ident="test2 at PERMANENT", start_time=datetime(year=2000, month=1, day=2), \
+ end_time=datetime(year=2001, month=1, day=1), timezone=1)
+
+ print "Finished: ", A.temporal_relation(B)
+ print "Finishes: ", B.temporal_relation(A)
+
+ A = raster_absolute_time(ident="test1 at PERMANENT", start_time=datetime(year=2000, month=1, day=1), \
+ end_time=datetime(year=2001, month=1, day=1), timezone=1)
+ B = raster_absolute_time(ident="test2 at PERMANENT", start_time=datetime(year=2000, month=3, day=1), \
+ end_time=datetime(year=2000, month=9, day=1), timezone=1)
+
+ print "Contains: ", A.temporal_relation(B)
+ print "During: ", B.temporal_relation(A)
+
+
+ A = raster_absolute_time(ident="test1 at PERMANENT", start_time=datetime(year=2000, month=1, day=1), \
+ end_time=datetime(year=2000, month=6, day=1), timezone=1)
+ B = raster_absolute_time(ident="test2 at PERMANENT", start_time=datetime(year=2000, month=3, day=1), \
+ end_time=datetime(year=2000, month=9, day=1), timezone=1)
+
+ print "Overlap: ", A.temporal_relation(B)
+ print "Overlapped:", B.temporal_relation(A)
+
+ A = raster_absolute_time(ident="test1 at PERMANENT", start_time=datetime(year=2000, month=1, day=1), \
+ end_time=datetime(year=2000, month=1, day=1), timezone=1)
+ B = raster_absolute_time(ident="test2 at PERMANENT", start_time=datetime(year=2000, month=1, day=1), \
+ end_time=datetime(year=2000, month=1, day=1), timezone=1)
+
+ print "Equivalent:", A.temporal_relation(B)
+ print "Equivalent:", B.temporal_relation(A)
+
+
+def test_raster_dataset():
+ print "Create a raster object"
+
+ rds = raster_dataset("a at test")
+
+ rds.load_from_file()
+
+ print "Is in db: ", rds.base.is_in_db()
+
+ rds.base.set_ttype("absolue")
+ rds.absolute_time.set_start_time(datetime(year=2000, month=1, day=1))
+ rds.absolute_time.set_end_time(datetime(year=2010, month=1, day=1))
+
+ # Remove the entry if it is in the db
+ rds.base.delete()
+
+ rds.insert()
+ rds.print_self()
+
+ print rds.temporal_relation(rds)
+
+#test_dict_sql_serializer()
+create_temporal_database()
+#test_dataset_identifer()
+#test_absolute_timestamp()
+#test_relative_timestamp()
+#test_spatial_extent()
+#test_map_metadata()
+#test_base_absolute_time_extent_metadata()
+#test_absolut_time_temporal_relations()
+test_raster_dataset()
\ No newline at end of file
Added: grass/trunk/lib/temporal/vector_metadata_table.sql
===================================================================
--- grass/trunk/lib/temporal/vector_metadata_table.sql (rev 0)
+++ grass/trunk/lib/temporal/vector_metadata_table.sql 2011-09-05 14:29:35 UTC (rev 48132)
@@ -0,0 +1,62 @@
+--#############################################################################
+-- This SQL script generates the vector table to store
+-- metadata for SQL queries and temporal GIS support.
+--
+-- Author: Soeren Gebbert soerengebbert <at> googlemail <dot> com
+--#############################################################################
+
+PRAGMA foreign_keys = ON;
+
+-- The metadata table
+
+CREATE TABLE vector_metadata (
+ id VARCHAR NOT NULL, -- The id (PFK) is the unique identifier for all tables, it is based on name and mapset (name at mapset) and is used as primary foreign key
+ stvds_register VARCHAR, -- The name of the table storing all space-time vector datasets in which this map is registered
+ PRIMARY KEY (id),
+ FOREIGN KEY (id) REFERENCES vector_base (id) ON DELETE CASCADE
+);
+
+-- Create the views to access all columns for the absolute and relative time
+
+CREATE VIEW vector_view_abs_time AS SELECT
+ A1.id, A1.mapset,
+ A1.name, A1.temporal_type,
+ A1.creation_time, A1.modification_time,
+ A1.revision, A1.creator,
+ A2.start_time, A2.end_time,
+ A3.north, A3.south, A3.east, A3.west,
+ A4.stvds_register
+ FROM vector_base A1, vector_absolute_time A2,
+ vector_spatial_extent A3, vector_metadata A4
+ WHERE A1.id = A2.id AND A1.id = A3.id AND A1.id = A4.id;
+
+CREATE VIEW vector_view_rel_time AS SELECT
+ A1.id, A1.mapset,
+ A1.name, A1.temporal_type,
+ A1.creation_time, A1.modification_time,
+ A1.revision, A1.creator,
+ A2.interval,
+ A3.north, A3.south, A3.east, A3.west,
+ A4.stvds_register
+ FROM vector_base A1, vector_relative_time A2,
+ vector_spatial_extent A3, vector_metadata A4
+ WHERE A1.id = A2.id AND A1.id = A3.id AND A1.id = A4.id;
+
+-- Create a trigger to update the modification time and revision number in case the metadata or timestanps have been updated
+
+CREATE TRIGGER update_vector_metadata AFTER UPDATE ON vector_metadata
+ BEGIN
+ UPDATE vector_base SET modification_time = datetime("NOW") WHERE id = old.id;
+ UPDATE vector_base SET revision = (revision + 1) WHERE id = old.id;
+ END;
+
+-- Create trigger for automated deletion of dependent rows, this should normally be done using foreign keys
+
+CREATE TRIGGER delete_vector_base AFTER DELETE ON vector_base
+ BEGIN
+ DELETE FROM vector_absolute_time WHERE id = old.id;
+ DELETE FROM vector_relative_time WHERE id = old.id;
+ DELETE FROM vector_spatial_extent WHERE id = old.id;
+ DELETE FROM vector_metadata WHERE id = old.id;
+ END;
+
Added: grass/trunk/temporal/t.create/Makefile
===================================================================
--- grass/trunk/temporal/t.create/Makefile (rev 0)
+++ grass/trunk/temporal/t.create/Makefile 2011-09-05 14:29:35 UTC (rev 48132)
@@ -0,0 +1,7 @@
+MODULE_TOPDIR = ../../
+
+PGM = t.create
+
+include $(MODULE_TOPDIR)/include/Make/Script.make
+
+default: script $(TEST_DST)
Added: grass/trunk/temporal/t.create/t.create.html
===================================================================
Added: grass/trunk/temporal/t.create/t.create.py
===================================================================
--- grass/trunk/temporal/t.create/t.create.py (rev 0)
+++ grass/trunk/temporal/t.create/t.create.py 2011-09-05 14:29:35 UTC (rev 48132)
@@ -0,0 +1,103 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+############################################################################
+#
+# MODULE: t.create
+# AUTHOR(S): Soeren Gebbert
+#
+# PURPOSE: Create a space-time dataset
+# COPYRIGHT: (C) 2011 by the GRASS Development Team
+#
+# This program is free software under the GNU General Public
+# License (version 2). Read the file COPYING that comes with GRASS
+# for details.
+#
+#############################################################################
+
+#%module
+#% description: Create a space-time dataset
+#% keywords: spacetime dataset
+#% keywords: create
+#%end
+
+#%option
+#% key: name
+#% type: string
+#% description: Name of the new space-time dataset
+#% required: yes
+#% multiple: no
+#%end
+
+#%option
+#% key: granularity
+#% type: string
+#% description: The granularity of the new space-time dataset (NNN day, NNN week, NNN month)
+#% required: yes
+#% multiple: no
+#%end
+
+#%option
+#% key: semantictype
+#% type: string
+#% description: The semantic type of the space-time dataset
+#% required: yes
+#% multiple: no
+#% options: event, const, continuous
+#% answer: event
+#%end
+
+#%option
+#% key: type
+#% type: string
+#% description: Type of the space time dataset, default is strds
+#% required: no
+#% options: strds
+#% answer: strds
+#%end
+#%option
+#% key: temporaltype
+#% type: string
+#% description: The temporal type of the space time dataset, default is absolute
+#% required: no
+#% options: absolute,relative
+#% answer: absolute
+#%end
+
+#%option
+#% key: title
+#% type: string
+#% description: Title of the new space-time dataset
+#% required: yes
+#% multiple: no
+#%end
+
+#%option
+#% key: description
+#% type: string
+#% description: Description of the new space-time dataset
+#% required: yes
+#% multiple: no
+#%end
+
+import sys
+import os
+import getpass
+import subprocess
+import grass.script as grass
+############################################################################
+
+def main():
+
+ # Get the options
+ name = options["name"]
+ type = options["type"]
+ temporaltype = options["temporaltype"]
+ title = options["title"]
+ descr = options["description"]
+ semantic = options["semantictype"]
+ gran = options["granularity"]
+
+if __name__ == "__main__":
+ options, flags = grass.core.parser()
+ main()
+
Property changes on: grass/trunk/temporal/t.create/t.create.py
___________________________________________________________________
Added: svn:executable
+ *
Added: grass/trunk/temporal/t.info/Makefile
===================================================================
--- grass/trunk/temporal/t.info/Makefile (rev 0)
+++ grass/trunk/temporal/t.info/Makefile 2011-09-05 14:29:35 UTC (rev 48132)
@@ -0,0 +1,7 @@
+MODULE_TOPDIR = ../../
+
+PGM = t.info
+
+include $(MODULE_TOPDIR)/include/Make/Script.make
+
+default: script $(TEST_DST)
Added: grass/trunk/temporal/t.info/t.info.html
===================================================================
Added: grass/trunk/temporal/t.info/t.info.py
===================================================================
--- grass/trunk/temporal/t.info/t.info.py (rev 0)
+++ grass/trunk/temporal/t.info/t.info.py 2011-09-05 14:29:35 UTC (rev 48132)
@@ -0,0 +1,54 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+############################################################################
+#
+# MODULE: t.info
+# AUTHOR(S): Soeren Gebbert
+#
+# PURPOSE: Print information about a space-time dataset
+# COPYRIGHT: (C) 2011 by the GRASS Development Team
+#
+# This program is free software under the GNU General Public
+# License (version 2). Read the file COPYING that comes with GRASS
+# for details.
+#
+#############################################################################
+
+#%module
+#% description: Remove a space-time dataset
+#% keywords: spacetime dataset
+#% keywords: remove
+#%end
+
+#%option
+#% key: name
+#% type: string
+#% description: Name of the new space-time dataset
+#% required: yes
+#% multiple: no
+#%end
+#%option
+#% key: type
+#% type: string
+#% description: Type of the space time dataset, default is strds
+#% required: no
+#% options: strds
+#% answer: strds
+#%end
+
+import sys
+import os
+import grass.script as grass
+
+############################################################################
+
+def main():
+
+ # Get the options
+ name = options["name"]
+ type = options["type"]
+
+if __name__ == "__main__":
+ options, flags = grass.core.parser()
+ main()
+
Property changes on: grass/trunk/temporal/t.info/t.info.py
___________________________________________________________________
Added: svn:executable
+ *
Added: grass/trunk/temporal/t.remove/Makefile
===================================================================
--- grass/trunk/temporal/t.remove/Makefile (rev 0)
+++ grass/trunk/temporal/t.remove/Makefile 2011-09-05 14:29:35 UTC (rev 48132)
@@ -0,0 +1,7 @@
+MODULE_TOPDIR = ../../
+
+PGM = t.remove
+
+include $(MODULE_TOPDIR)/include/Make/Script.make
+
+default: script $(TEST_DST)
Added: grass/trunk/temporal/t.remove/t.remove.html
===================================================================
Added: grass/trunk/temporal/t.remove/t.remove.py
===================================================================
--- grass/trunk/temporal/t.remove/t.remove.py (rev 0)
+++ grass/trunk/temporal/t.remove/t.remove.py 2011-09-05 14:29:35 UTC (rev 48132)
@@ -0,0 +1,54 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+############################################################################
+#
+# MODULE: t.remove
+# AUTHOR(S): Soeren Gebbert
+#
+# PURPOSE: Remove a space-time raster dataset
+# COPYRIGHT: (C) 2011 by the GRASS Development Team
+#
+# This program is free software under the GNU General Public
+# License (version 2). Read the file COPYING that comes with GRASS
+# for details.
+#
+#############################################################################
+
+#%module
+#% description: Remove a space-time dataset
+#% keywords: spacetime dataset
+#% keywords: remove
+#%end
+
+#%option
+#% key: name
+#% type: string
+#% description: Name of the new space-time dataset
+#% required: yes
+#% multiple: no
+#%end
+#%option
+#% key: type
+#% type: string
+#% description: Type of the space time dataset, default is strds
+#% required: no
+#% options: strds
+#% answer: strds
+#%end
+
+import sys
+import os
+import grass.script as grass
+
+############################################################################
+
+def main():
+
+ # Get the options
+ name = options["name"]
+ type = options["type"]
+
+if __name__ == "__main__":
+ options, flags = grass.core.parser()
+ main()
+
Property changes on: grass/trunk/temporal/t.remove/t.remove.py
___________________________________________________________________
Added: svn:executable
+ *
More information about the grass-commit
mailing list