[GRASS-SVN] r73487 - in grass-addons/grass7/vector: . v.what.strds.timestamp
svn_grass at osgeo.org
svn_grass at osgeo.org
Thu Oct 4 15:51:23 PDT 2018
Author: sbl
Date: 2018-10-04 15:51:23 -0700 (Thu, 04 Oct 2018)
New Revision: 73487
Added:
grass-addons/grass7/vector/v.what.strds.timestamp/
grass-addons/grass7/vector/v.what.strds.timestamp/Makefile
grass-addons/grass7/vector/v.what.strds.timestamp/v.what.strds.timestamp.html
grass-addons/grass7/vector/v.what.strds.timestamp/v.what.strds.timestamp.py
Log:
new, experimental addon v.what.strds.timestamp
Added: grass-addons/grass7/vector/v.what.strds.timestamp/Makefile
===================================================================
--- grass-addons/grass7/vector/v.what.strds.timestamp/Makefile (rev 0)
+++ grass-addons/grass7/vector/v.what.strds.timestamp/Makefile 2018-10-04 22:51:23 UTC (rev 73487)
@@ -0,0 +1,7 @@
+MODULE_TOPDIR = ../..
+
+PGM = v.what.strds.timestamp
+
+include $(MODULE_TOPDIR)/include/Make/Script.make
+
+default: script
Property changes on: grass-addons/grass7/vector/v.what.strds.timestamp/Makefile
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/x-makefile
\ No newline at end of property
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: grass-addons/grass7/vector/v.what.strds.timestamp/v.what.strds.timestamp.html
===================================================================
--- grass-addons/grass7/vector/v.what.strds.timestamp/v.what.strds.timestamp.html (rev 0)
+++ grass-addons/grass7/vector/v.what.strds.timestamp/v.what.strds.timestamp.html 2018-10-04 22:51:23 UTC (rev 73487)
@@ -0,0 +1,37 @@
+<h2>DESCRIPTION</h2>
+
+<em>v.what.strds.timestamp</em> matches points with a timestamp in
+the attribute table (<i>timestamp_column</i>) (e.g. recordings from
+stationary (temperature logger, wildlife camera traps) or non-stationary
+sensors (e.g GPS collars)) with Space Time Raster Datasets (STRDS) based
+on point locaitions in space and time. Raster values at the specific
+space-time position are written into the user-defined <i>column</i> in
+the attribute table of the input vector map.
+
+<h2>NOTES</h2>
+
+The SQLite DB backend does not provide specific date/datetime datatypes.
+However, text columns with ISO formated date strings are supported for
+the <em>timestamp_column</em> as well.
+
+<p>
+Curretnly, <em>only STRDS with absolute temporal type are supported.</em>
+</p>
+
+<h2>EXAMPLE</h2>
+
+TBD
+
+<h2>SEE ALSO</h2>
+<em>
+<a href="v.what.rast.html">v.what.rast</a>,
+<a href="v.what.strds.html">v.what.strds</a>,
+<a href="t.rast.what.html">r.connectivity.corridors</a>
+</em>
+
+<h2>AUTHOR</h2>
+Stefan Blumentrath, Norwegian Institute for Nature Research (NINA)<br>
+Written for the 2018 <a href="irsae.no">IRSAE</a> GRASS GIS course at
+Studenterhytta, Oslo
+<br>
+<p></p><i>Last changed: $Date$</i>
Property changes on: grass-addons/grass7/vector/v.what.strds.timestamp/v.what.strds.timestamp.html
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/html
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id
\ No newline at end of property
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: grass-addons/grass7/vector/v.what.strds.timestamp/v.what.strds.timestamp.py
===================================================================
--- grass-addons/grass7/vector/v.what.strds.timestamp/v.what.strds.timestamp.py (rev 0)
+++ grass-addons/grass7/vector/v.what.strds.timestamp/v.what.strds.timestamp.py 2018-10-04 22:51:23 UTC (rev 73487)
@@ -0,0 +1,255 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+############################################################################
+#
+# MODULE: v.what.strds.timestamp
+# AUTHOR(S): Stefan Blumentrath, NINA, based on
+# v.what.strds by Luca delucchi
+# Written for the IRSAE GIS course 2018 in Oslo
+#
+# PURPOSE: Uploads space time raster dataset values at positions of vector points to the table
+# COPYRIGHT: (C) 2018 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: Uploads space time raster dataset values to the attribute table at positions of vector points in space and time.
+#% keyword: vector
+#% keyword: temporal
+#% keyword: sampling
+#% keyword: position
+#% keyword: querying
+#% keyword: attribute table
+#% keyword: timestamp
+#% keyword: time
+#%end
+
+#%option G_OPT_V_INPUT
+#%end
+
+#%option G_OPT_V_FIELD
+#%end
+
+#%option G_OPT_DB_COLUMN
+#%key: timestamp_column
+#%end
+
+#%option G_OPT_DB_COLUMN
+#%key: column
+#%end
+
+#%option G_OPT_DB_WHERE
+#%end
+
+#%option G_OPT_STRDS_INPUTS
+#% key: strds
+#%end
+
+#%option G_OPT_T_WHERE
+#% key: t_where
+#%end
+
+#%flag
+#% key: u
+#% label: Update column of attribute table in input vector map if it already exists
+#% description: Instead of creating a new vector map update the attribute table with value(s)
+#%end
+
+#%flag
+#% key: i
+#% label: Interpolate raster values from the four nearest pixels
+#%end
+
+"""
+To do:
+- implement usage of temporal envelope of vector points
+- implement relative temporal type
+"""
+import os
+try:
+ from subprocess import DEVNULL # Python 3.
+except ImportError:
+ DEVNULL = open(os.devnull, 'wb')
+import grass.script as grass
+#from grass.exceptions import CalledModuleError
+import grass.temporal as tgis
+#from grass.pygrass.utils import copy as gcopy
+#from grass.pygrass.messages import Messenger
+from grass.pygrass.modules import Module
+
+# i18N
+import gettext
+gettext.install('grassmods', os.path.join(os.getenv("GISBASE"), 'locale'))
+
+def sample_relative(input, layer, timestamp_column, column, t_raster,
+ where, i_flag):
+ """Point sampling in STRDS with relative temporal type
+ Not implemented yet.
+ """
+ start = t_raster["start_time"]
+ end = t_raster["end_time"]
+ raster_map = '{}@{}'.format(t_raster["name"], t_raster["mapset"])
+ where += """(julianday({0}) > date('{1}') AND \
+ julianday({0}) < date('{2}'))""".format(timestamp_column, start, end)
+
+def sample_absolute(input, layer, timestamp_column, column, t_raster,
+ where, i_flag):
+ """Point sampling in STRDS with absolute temporal type
+ """
+ start = t_raster["start_time"]
+ end = t_raster["end_time"]
+ raster_map = '{}@{}'.format(t_raster["name"], t_raster["mapset"])
+ where += """({0} > date('{1}') AND \
+ {0} < date('{2}'))""".format(timestamp_column, start, end)
+
+ grass.verbose(_('Sampling points between {} and {}'.format(start, end)))
+
+ # If only one core is used, processing can be faster if computational region is temporarily moved
+ # to where datapoints are (e.g. in case of tracking data)
+ # Move computational region temporarily to where points are in
+ # in space and time
+ treg = grass.parse_command('v.db.select', flags='r',
+ map=input, where=where, quiet=True) # stderr=subproess.PIPE,
+
+ if len(set(treg.values())) > 1:
+ grass.use_temp_region()
+ grass.run_command("g.region", n=treg['n'], s=treg['s'], e=treg['e'],
+ w=treg['w'], align=raster_map)
+
+ # Sample spatio-temporally matching points and raster map
+ rast_what = Module('v.what.rast', map=input, layer=layer,
+ column=column, raster=raster_map,
+ where=where, stderr_=DEVNULL, quiet=True)
+ rast_what.flags.i = i_flag
+ rast_what.run()
+
+def main():
+ # Get the options
+ input = options["input"]
+ timestamp_column = options["timestamp_column"]
+ columns = options["column"]
+ layer = options["layer"]
+ where = options["where"]
+ strds = options["strds"]
+ tempwhere = options["t_where"]
+ i_flag = flags["i"]
+
+ if where == "" or where == " " or where == "\n":
+ where = None
+
+ # overwrite = grass.overwrite()
+
+ # Set verbosity level
+ # quiet = True
+ # if grass.verbosity() > 2:
+ # quiet = False
+
+ grass.warning(_('This addon is experimental!'))
+
+ # Check DB connection for input vector map
+ dbcon = grass.vector_layer_db(input, layer)
+ # Check the number of sample strds and the number of columns
+ strds_names = strds.split(",")
+ column_names = columns.split(",")
+ if not len(column_names) == len(strds_names):
+ grass.fatal(_('Number of columns and number of STRDS does not match.'))
+
+ # Check type of timestamp column
+ cols = grass.vector_columns(input, layer=layer)
+ if not timestamp_column in cols.keys():
+ grass.fatal(_('Could not find column {} \
+ in table connected to vector map {} \
+ at layer {}'.format(timestamp_column, input, layer)))
+ if cols[timestamp_column]['type'] != 'DATE':
+ if dbcon['driver'] != 'sqlite':
+ # Note that SQLite does not have a DATE datatype and
+ # and an index does not significantly speedup the process
+ # (at least not with a couple of 100 points)
+ grass.warning(_('Timestamp column is of type {}. \
+ It is recommended to use DATE type with an index. \
+ '.format(cols[timestamp_column]['type'])))
+
+ # Make sure the temporal database exists
+ tgis.init()
+ # We need a database interface
+ dbif = tgis.SQLDatabaseInterfaceConnection()
+ dbif.connect()
+
+ # Limit temporal extent to extent of points if no tempwhere is given
+ if not tempwhere:
+ extent = []
+ for stat in ('min', 'max'):
+ tsql = "SELECT {}({}) FROM {}".format(stat, timestamp_column,
+ dbcon['table'])
+ extent.append(grass.read_command('db.select', flags='c',
+ sql=tsql))
+
+ grass.verbose(_('Temporal extent of vector points map is \
+ {} to {}'.format(extent[0], extent[1])))
+ else:
+ tempwhere = '({}) AND '.format(tempwhere)
+
+ # Loop over STRDS
+ counter = 0
+ for strds_name in strds_names:
+
+ cur_strds = tgis.open_old_stds(strds_name, "strds", dbif)
+
+ granu = cur_strds.get_granularity()
+ start_time = tgis.datetime_math.check_datetime_string(extent[0])
+ start_gran = tgis.datetime_math.adjust_datetime_to_granularity(start_time, granu).isoformat()
+ tempwhere += "(end_time > '{}' and start_time <= '{}')".format(start_gran, extent[1]) # needs to be set properly
+
+ # Get info on registered maps in STRDS
+ rows = cur_strds.get_registered_maps("name,mapset,start_time,end_time",
+ tempwhere, "start_time",
+ dbif)
+
+ # Check temporal type and
+ # define sampling function to use
+ # becomes relevant when temporal type relative gets implemented
+ if cur_strds.is_time_relative():
+ grass.fatal(_('Sorry, STRDS of relative temporal type is not (yet) supported'))
+ sample = sample_relative
+ else:
+ sample = sample_absolute
+
+ # Check if there are raster maps to sample from that fullfill
+ # temporal conditions
+ if not rows and not tempwhere:
+ dbif.close()
+ grass.fatal(_("Space time raster dataset <%s> is empty".format(cur_strds.get_id())))
+ elif not rows and tempwhere:
+ dbif.close()
+ grass.fatal(_("No maps selected from Space time raster dataset <%s>, \
+ or dataset is empty".format(cur_strds.get_id())))
+
+ # Include temporal condition into where clause
+ where_clause = '({}) AND '.format(where) if where else ''
+
+ # Loop over registered maps in STRDS
+ row_number = 0
+ for row in rows:
+ # If r.what had a where option, r.what could be used to
+ # collect raster values (without interpolation)
+ # in a ParallelModuleQueue to collect values using multiple
+ # cores and then upload results in one operation
+
+ sample(input, layer, timestamp_column,
+ column_names[counter], row, where_clause, i_flag)
+
+ row_number += 1
+ grass.percent(row_number, len(rows), 3)
+ counter = counter + 1
+
+ dbif.close()
+ grass.vector_history(input)
+
+if __name__ == "__main__":
+ options, flags = grass.parser()
+ main()
+
Property changes on: grass-addons/grass7/vector/v.what.strds.timestamp/v.what.strds.timestamp.py
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/x-python
\ No newline at end of property
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
More information about the grass-commit
mailing list