[GRASS-SVN] r58249 - grass/trunk/lib/python/temporal
svn_grass at osgeo.org
svn_grass at osgeo.org
Sun Nov 17 16:26:00 PST 2013
Author: huhabla
Date: 2013-11-17 16:26:00 -0800 (Sun, 17 Nov 2013)
New Revision: 58249
Added:
grass/trunk/lib/python/temporal/c_libraries_interface.py
Modified:
grass/trunk/lib/python/temporal/Makefile
grass/trunk/lib/python/temporal/__init__.py
grass/trunk/lib/python/temporal/abstract_map_dataset.py
grass/trunk/lib/python/temporal/aggregation.py
grass/trunk/lib/python/temporal/core.py
grass/trunk/lib/python/temporal/space_time_datasets.py
Log:
New G_fatal_error() safe C-libraries interface to access C-functions via ctypes implemented
to reduce the use of ctype functions in the temporal framework.
Modified: grass/trunk/lib/python/temporal/Makefile
===================================================================
--- grass/trunk/lib/python/temporal/Makefile 2013-11-17 18:22:12 UTC (rev 58248)
+++ grass/trunk/lib/python/temporal/Makefile 2013-11-18 00:26:00 UTC (rev 58249)
@@ -8,7 +8,7 @@
GDIR = $(PYDIR)/grass
DSTDIR = $(GDIR)/temporal
-MODULES = base core abstract_dataset abstract_map_dataset abstract_space_time_dataset space_time_datasets open factory gui_support list register sampling metadata spatial_extent temporal_extent datetime_math temporal_granularity spatio_temporal_relationships unit_tests aggregation stds_export stds_import extract mapcalc univar_statistics temporal_topology_dataset_connector spatial_topology_dataset_connector
+MODULES = base core abstract_dataset abstract_map_dataset abstract_space_time_dataset space_time_datasets open factory gui_support list register sampling metadata spatial_extent temporal_extent datetime_math temporal_granularity spatio_temporal_relationships unit_tests aggregation stds_export stds_import extract mapcalc univar_statistics temporal_topology_dataset_connector spatial_topology_dataset_connector c_libraries_interface
PYFILES := $(patsubst %,$(DSTDIR)/%.py,$(MODULES) __init__)
PYCFILES := $(patsubst %,$(DSTDIR)/%.pyc,$(MODULES) __init__)
Modified: grass/trunk/lib/python/temporal/__init__.py
===================================================================
--- grass/trunk/lib/python/temporal/__init__.py 2013-11-17 18:22:12 UTC (rev 58248)
+++ grass/trunk/lib/python/temporal/__init__.py 2013-11-18 00:26:00 UTC (rev 58249)
@@ -24,3 +24,4 @@
from stds_import import *
from mapcalc import *
from univar_statistics import *
+from c_libraries_interface import *
Modified: grass/trunk/lib/python/temporal/abstract_map_dataset.py
===================================================================
--- grass/trunk/lib/python/temporal/abstract_map_dataset.py 2013-11-17 18:22:12 UTC (rev 58248)
+++ grass/trunk/lib/python/temporal/abstract_map_dataset.py 2013-11-18 00:26:00 UTC (rev 58249)
@@ -14,9 +14,6 @@
"""
from abstract_dataset import *
from datetime_math import *
-import grass.lib.date as libdate
-import grass.lib.gis as libgis
-import ctypes
class AbstractMapDataset(AbstractDataset):
@@ -44,6 +41,7 @@
def __init__(self):
AbstractDataset.__init__(self)
+ self.ciface = get_tgis_c_library_interface()
@abstractmethod
def get_new_stds_instance(self, ident):
@@ -114,83 +112,6 @@
in the temporal database.
"""
- def _set_timestamp_from_grass(self, ts):
- """!Set the timestamp of this map from the map metadata
- in the grass file system based spatial database and
- set the internal time stamp that should be insert/updated
- in the temporal database.
-
- @param ts The timetsamp to be set, is of type libgis.TimeStamp()
- """
-
- if not self.has_grass_timestamp():
- return False
-
- dt1 = libgis.DateTime()
- dt2 = libgis.DateTime()
- count = ctypes.c_int()
-
- libgis.G_get_timestamps(ctypes.byref(ts),
- ctypes.byref(dt1),
- ctypes.byref(dt2),
- ctypes.byref(count))
-
-
- if dt1.mode == libdate.DATETIME_ABSOLUTE:
- pdt1 = None
- pdt2 = None
- if count.value >= 1:
- pdt1 = datetime(int(dt1.year), int(dt1.month), int(dt1.day),
- int(dt1.hour), int(dt1.minute),
- int(dt1.second))
- if count.value == 2:
- pdt2 = datetime(int(dt2.year), int(dt2.month), int(dt2.day),
- int(dt2.hour), int(dt2.minute),
- int(dt2.second))
-
- # ATTENTION: We ignore the time zone
- # TODO: Write time zone support
- self.set_absolute_time(pdt1, pdt2, None)
- else:
- unit = None
- start = None
- end = None
- if count >= 1:
- if dt1.year > 0:
- unit = "years"
- start = dt1.year
- elif dt1.month > 0:
- unit = "months"
- start = dt1.month
- elif dt1.day > 0:
- unit = "days"
- start = dt1.day
- elif dt1.hour > 0:
- unit = "hours"
- start = dt1.hour
- elif dt1.minute > 0:
- unit = "minutess"
- start = dt1.minutes
- elif dt1.seconds > 0:
- unit = "seconds"
- start = dt1.seconds
- if count == 2:
- if dt2.year > 0:
- end = dt2.year
- elif dt2.month > 0:
- end = dt2.month
- elif dt2.day > 0:
- end = dt2.day
- elif dt2.hour > 0:
- end = dt2.hour
- elif dt2.minute > 0:
- end = dt2.minutes
- elif dt2.seconds > 0:
- end = dt2.seconds
- self.set_relative_time(start, end, unit)
-
- return True
-
@abstractmethod
def remove_timestamp_from_grass(self):
"""!Remove the timestamp from the grass file
@@ -205,12 +126,6 @@
"""
@abstractmethod
- def read_info(self):
- """!Read the map info from the grass file system based database and
- store the content into a dictionary
- """
-
- @abstractmethod
def load(self):
"""!Load the content of this object from the grass
file system based database"""
Modified: grass/trunk/lib/python/temporal/aggregation.py
===================================================================
--- grass/trunk/lib/python/temporal/aggregation.py 2013-11-17 18:22:12 UTC (rev 58248)
+++ grass/trunk/lib/python/temporal/aggregation.py 2013-11-18 00:26:00 UTC (rev 58249)
@@ -24,7 +24,6 @@
"""
from space_time_datasets import *
-import grass.lib.gis as libgis
###############################################################################
@@ -125,7 +124,7 @@
msgr.verbose(_("Aggregate %s raster maps") % (len(inputs)))
output = "%s_%i" % (base, count)
- mapset = libgis.G_mapset()
+ mapset = get_current_mapset()
map_id = output + "@" + mapset
new_map = RasterDataset(map_id)
Added: grass/trunk/lib/python/temporal/c_libraries_interface.py
===================================================================
--- grass/trunk/lib/python/temporal/c_libraries_interface.py (rev 0)
+++ grass/trunk/lib/python/temporal/c_libraries_interface.py 2013-11-18 00:26:00 UTC (rev 58249)
@@ -0,0 +1,1045 @@
+# -*- coding: utf-8 -*-
+"""!@package grass.pygrass.massages
+
+ at brief Temporal Framework GRASS C-library interface
+
+Fast and exit-safe interface to GRASS C-library functions
+using ctypes and multiprocessing
+
+
+(C) 2013 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 sys
+from multiprocessing import Process, Lock, Pipe
+import logging
+from ctypes import *
+from core import *
+import grass.lib.gis as libgis
+import grass.lib.raster as libraster
+import grass.lib.vector as libvector
+import grass.lib.date as libdate
+import grass.lib.raster3d as libraster3d
+
+###############################################################################
+
+class RPCDefs(object):
+ # Function identifier and index
+ STOP=0
+ HAS_TIMESTAMP=1
+ WRITE_TIMESTAMP=2
+ READ_TIMESTAMP=3
+ REMOVE_TIMESTAMP=4
+ READ_MAP_INFO=5
+ MAP_EXISTS=6
+ READ_MAP_INFO=7
+
+ TYPE_RASTER=0
+ TYPE_RASTER3D=1
+ TYPE_VECTOR=2
+
+###############################################################################
+
+def _has_timestamp(lock, conn, data):
+ """!Check if the file based GRASS timestamp is present and send
+ True or False using the provided pipe.
+
+ @param lock A multiprocessing.Lock instance
+ @param conn A multiprocessing.Pipe instance used to send True or False
+ @param data The list of data entries [function_id, maptype, name, mapset, layer]
+
+ """
+ maptype = data[1]
+ name = data[2]
+ mapset = data[3]
+ layer= data[4]
+ check = False
+ if maptype == RPCDefs.TYPE_RASTER:
+ if libgis.G_has_raster_timestamp(name, mapset) == 1:
+ check = True
+ elif maptype == RPCDefs.TYPE_VECTOR:
+ if libgis.G_has_vector_timestamp(name, layer, mapset) == 1:
+ check = True
+ elif maptype == RPCDefs.TYPE_RASTER3D:
+ if libgis.G_has_raster3d_timestamp(name, mapset) == 1:
+ check = True
+ conn.send(check)
+
+###############################################################################
+
+def _read_timestamp(lock, conn, data):
+ """!Read the file based GRASS timestamp and send
+ the result using the provided pipe.
+
+ The tuple to be send via pipe: (return value of G_read_*_timestamp, timestamps).
+
+ Please have a look at the documentation of G_read_raster_timestamp,
+ G_read_vector_timestamp and G_read_raster3d_timestamp for the return
+ values description.
+
+ The timestamps to be send are tuples of values:
+ - relative time (start, end, unit), start and end are of type
+ integer, unit is of type string.
+ - absolute time (start, end), start and end are of type datetime
+
+ The end time may be None in case of a time instance.
+
+ @param lock A multiprocessing.Lock instance
+ @param conn A multiprocessing.Pipe instance used to send the result
+ @param data The list of data entries [function_id, maptype, name, mapset, layer]
+
+ """
+ maptype = data[1]
+ name = data[2]
+ mapset = data[3]
+ layer= data[4]
+ check = False
+ ts = libgis.TimeStamp()
+ if maptype == RPCDefs.TYPE_RASTER:
+ check = libgis.G_read_raster_timestamp(name, mapset, byref(ts))
+ elif maptype == RPCDefs.TYPE_VECTOR:
+ check = libgis.G_read_vector_timestamp(name, layer, mapset, byref(ts))
+ elif maptype == RPCDefs.TYPE_RASTER3D:
+ check = libgis.G_read_raster3d_timestamp(name, mapset, byref(ts))
+
+ dates = _convert_timestamp_from_grass(ts)
+ conn.send((check, dates))
+
+###############################################################################
+
+def _write_timestamp(lock, conn, data):
+ """!Write the file based GRASS timestamp
+ the return values of the called C-functions using the provided pipe.
+
+ The value to be send via pipe is the return value of G_write_*_timestamp.
+
+ Please have a look at the documentation of G_write_raster_timestamp,
+ G_write_vector_timestamp and G_write_raster3d_timestamp for the return
+ values description.
+
+ @param lock A multiprocessing.Lock instance
+ @param conn A multiprocessing.Pipe instance used to send True or False
+ @param data The list of data entries [function_id, maptype, name, mapset, layer, timestring]
+ """
+ maptype = data[1]
+ name = data[2]
+ mapset = data[3]
+ layer= data[4]
+ timestring = data[5]
+ check = -3
+ ts = libgis.TimeStamp()
+ check = libgis.G_scan_timestamp(byref(ts), timestring)
+
+ if check != 1:
+ logging.error("Unable to convert the timestamp: "+ timestring)
+ return -2
+
+ if maptype == RPCDefs.TYPE_RASTER:
+ check = libgis.G_write_raster_timestamp(name, byref(ts))
+ elif maptype == RPCDefs.TYPE_VECTOR:
+ check = libgis.G_write_vector_timestamp(name, layer, byref(ts))
+ elif maptype == RPCDefs.TYPE_RASTER3D:
+ check = libgis.G_write_raster3d_timestamp(name, byref(ts))
+
+ conn.send(check)
+
+###############################################################################
+
+def _remove_timestamp(lock, conn, data):
+ """!Remove the file based GRASS timestamp
+ the return values of the called C-functions using the provided pipe.
+
+ The value to be send via pipe is the return value of G_remove_*_timestamp.
+
+ Please have a look at the documentation of G_remove_raster_timestamp,
+ G_remove_vector_timestamp and G_remove_raster3d_timestamp for the return
+ values description.
+
+ @param lock A multiprocessing.Lock instance
+ @param conn A multiprocessing.Pipe instance used to send True or False
+ @param data The list of data entries [function_id, maptype, name, mapset, layer]
+
+ """
+ maptype = data[1]
+ name = data[2]
+ mapset = data[3]
+ layer= data[4]
+ check = False
+ if maptype == RPCDefs.TYPE_RASTER:
+ check = libgis.G_remove_raster_timestamp(name, mapset)
+ elif maptype == RPCDefs.TYPE_VECTOR:
+ check = libgis.G_remove_vector_timestamp(name, layer, mapset)
+ elif maptype == RPCDefs.TYPE_RASTER3D:
+ check = libgis.G_remove_raster3d_timestamp(name, mapset)
+
+ conn.send(check)
+
+###############################################################################
+
+def _map_exists(lock, conn, data):
+ """!Check if a map exists in the spatial database
+
+ The value to be send via pipe is True in case the map exists and False
+ if not.
+
+ @param lock A multiprocessing.Lock instance
+ @param conn A multiprocessing.Pipe instance used to send True or False
+ @param data The list of data entries [function_id, maptype, name, mapset]
+
+ """
+ maptype = data[1]
+ name = data[2]
+ mapset = data[3]
+ check = False
+ if maptype == RPCDefs.TYPE_RASTER:
+ mapset = libgis.G_find_raster(name, mapset)
+ elif maptype == RPCDefs.TYPE_VECTOR:
+ mapset = libgis.G_find_vector(name, mapset)
+ elif maptype == RPCDefs.TYPE_RASTER3D:
+ mapset = libgis.G_find_raster3d(name, mapset)
+
+ if mapset:
+ check = True
+
+ conn.send(check)
+
+###############################################################################
+
+def _read_map_info(lock, conn, data):
+ """!Read map specific metadata from the spatial database using C-library
+ functions
+
+ @param lock A multiprocessing.Lock instance
+ @param conn A multiprocessing.Pipe instance used to send True or False
+ @param data The list of data entries [function_id, maptype, name, mapset]
+ """
+ maptype = data[1]
+ name = data[2]
+ mapset = data[3]
+ if maptype == RPCDefs.TYPE_RASTER:
+ kvp = _read_raster_info(name, mapset)
+ elif maptype == RPCDefs.TYPE_VECTOR:
+ kvp = _read_vector_info(name, mapset)
+ elif maptype == RPCDefs.TYPE_RASTER3D:
+ kvp = _read_raster3d_info(name, mapset)
+
+ conn.send(kvp)
+
+###############################################################################
+
+def _read_raster_info(name, mapset):
+ """!Read the raster map info from the file system and store the content
+ into a dictionary
+
+ This method uses the ctypes interface to the gis and raster libraries
+ to read the map metadata information
+
+ @param name The name of the map
+ @param mapset The mapset of the map
+ @return The key value pairs of the map specific metadata, or None in case of an error
+ """
+
+ kvp = {}
+
+ if not libgis.G_find_raster(name, mapset):
+ return None
+
+ # Read the region information
+ region = libgis.Cell_head()
+ libraster.Rast_get_cellhd(name, mapset, byref(region))
+
+ kvp["north"] = region.north
+ kvp["south"] = region.south
+ kvp["east"] = region.east
+ kvp["west"] = region.west
+ kvp["nsres"] = region.ns_res
+ kvp["ewres"] = region.ew_res
+ kvp["rows"] = region.cols
+ kvp["cols"] = region.rows
+
+ maptype = libraster.Rast_map_type(name, mapset)
+
+ if maptype == libraster.DCELL_TYPE:
+ kvp["datatype"] = "DCELL"
+ elif maptype == libraster.FCELL_TYPE:
+ kvp["datatype"] = "FCELL"
+ elif maptype == libraster.CELL_TYPE:
+ kvp["datatype"] = "CELL"
+
+ # Read range
+ if libraster.Rast_map_is_fp(name, mapset):
+ range = libraster.FPRange()
+ libraster.Rast_init_fp_range(byref(range))
+ ret = libraster.Rast_read_fp_range(name, mapset, byref(range))
+ if ret < 0:
+ logging.error(_("Unable to read range file"))
+ return None
+ if ret == 2:
+ kvp["min"] = None
+ kvp["max"] = None
+ else:
+ min = libgis.DCELL()
+ max = libgis.DCELL()
+ libraster.Rast_get_fp_range_min_max(
+ byref(range), byref(min), byref(max))
+ kvp["min"] = min.value
+ kvp["max"] = max.value
+ else:
+ range = libraster.Range()
+ libraster.Rast_init_range(byref(range))
+ ret = libraster.Rast_read_range(name, mapset, byref(range))
+ if ret < 0:
+ logging.error(_("Unable to read range file"))
+ return None
+ if ret == 2:
+ kvp["min"] = None
+ kvp["max"] = None
+ else:
+ min = libgis.CELL()
+ max = libgis.CELL()
+ libraster.Rast_get_range_min_max(
+ byref(range), byref(min), byref(max))
+ kvp["min"] = min.value
+ kvp["max"] = max.value
+
+ return kvp
+
+###############################################################################
+
+def _read_raster3d_info(name, mapset):
+ """!Read the 3D raster map info from the file system and store the content
+ into a dictionary
+
+ This method uses the ctypes interface to the gis and raster3d libraries
+ to read the map metadata information
+
+ @param name The name of the map
+ @param mapset The mapset of the map
+ @return The key value pairs of the map specific metadata, or None in case of an error
+ """
+
+ kvp = {}
+
+ if not libgis.G_find_raster3d(name, mapset):
+ return None
+
+ # Read the region information
+ region = libraster3d.RASTER3D_Region()
+ libraster3d.Rast3d_read_region_map(name, mapset, byref(region))
+
+ kvp["north"] = region.north
+ kvp["south"] = region.south
+ kvp["east"] = region.east
+ kvp["west"] = region.west
+ kvp["nsres"] = region.ns_res
+ kvp["ewres"] = region.ew_res
+ kvp["tbres"] = region.tb_res
+ kvp["rows"] = region.cols
+ kvp["cols"] = region.rows
+ kvp["depths"] = region.depths
+ kvp["top"] = region.top
+ kvp["bottom"] = region.bottom
+
+ # We need to open the map, this function returns a void pointer
+ # but we may need the correct type which is RASTER3D_Map, hence
+ # the casting
+ g3map = cast(libraster3d.Rast3d_open_cell_old(name, mapset,
+ libraster3d.RASTER3D_DEFAULT_WINDOW,
+ libraster3d.RASTER3D_TILE_SAME_AS_FILE,
+ libraster3d.RASTER3D_NO_CACHE),
+ POINTER(libraster3d.RASTER3D_Map))
+
+ if not g3map:
+ logging.error(_("Unable to open 3D raster map <%s>" % (name)))
+ return None
+
+ maptype = libraster3d.Rast3d_file_type_map(g3map)
+
+ if maptype == libraster.DCELL_TYPE:
+ kvp["datatype"] = "DCELL"
+ elif maptype == libraster.FCELL_TYPE:
+ kvp["datatype"] = "FCELL"
+
+ # Read range
+ min = libgis.DCELL()
+ max = libgis.DCELL()
+ ret = libraster3d.Rast3d_range_load(g3map)
+ if not ret:
+ logging.error(_("Unable to load range of 3D raster map <%s>" %
+ (name)))
+ return None
+ libraster3d.Rast3d_range_min_max(g3map, byref(min), byref(max))
+
+ if min.value != min.value:
+ kvp["min"] = None
+ else:
+ kvp["min"] = float(min.value)
+ if max.value != max.value:
+ kvp["max"] = None
+ else:
+ kvp["max"] = float(max.value)
+
+ if not libraster3d.Rast3d_close(g3map):
+ logging.error(_("Unable to close 3D raster map <%s>" % (name)))
+ return None
+
+ return kvp
+
+###############################################################################
+
+def _read_vector_info(name, mapset):
+ """!Read the vector map info from the file system and store the content
+ into a dictionary
+
+ This method uses the ctypes interface to the vector libraries
+ to read the map metadata information
+
+ @param name The name of the map
+ @param mapset The mapset of the map
+ @return The key value pairs of the map specific metadata, or None in case of an error
+ """
+
+ kvp = {}
+
+ if not libgis.G_find_vector(name, mapset):
+ return None
+
+ # The vector map structure
+ Map = libvector.Map_info()
+
+ # We open the maps always in topology mode first
+ libvector.Vect_set_open_level(2)
+ with_topo = True
+
+ # Code lend from v.info main.c
+ if libvector.Vect_open_old_head2(byref(Map), name, mapset, "1") < 2:
+ # force level 1, open fully
+ # NOTE: number of points, lines, boundaries, centroids,
+ # faces, kernels is still available
+ libvector.Vect_set_open_level(1) # no topology
+ with_topo = False
+ if libvector.Vect_open_old2(byref(Map), name, mapset, "1") < 1:
+ logging.error(_("Unable to open vector map <%s>" %
+ (libvector.Vect_get_full_name(byref(Map)))))
+ return None
+
+ # Release the vector spatial index memory when closed
+ libvector.Vect_set_release_support(byref(Map))
+
+ # Read the extent information
+ bbox = libvector.bound_box()
+ libvector.Vect_get_map_box(byref(Map), byref(bbox))
+
+ kvp["north"] = bbox.N
+ kvp["south"] = bbox.S
+ kvp["east"] = bbox.E
+ kvp["west"] = bbox.W
+ kvp["top"] = bbox.T
+ kvp["bottom"] = bbox.B
+
+ kvp["map3d"] = bool(libvector.Vect_is_3d(byref(Map)))
+
+ # Read number of features
+ if with_topo:
+ kvp["points"] = libvector.Vect_get_num_primitives(
+ byref(Map), libvector.GV_POINT)
+ kvp["lines"] = libvector.Vect_get_num_primitives(
+ byref(Map), libvector.GV_LINE)
+ kvp["boundaries"] = libvector.Vect_get_num_primitives(
+ byref(Map), libvector.GV_BOUNDARY)
+ kvp["centroids"] = libvector.Vect_get_num_primitives(
+ byref(Map), libvector.GV_CENTROID)
+ kvp["faces"] = libvector.Vect_get_num_primitives(
+ byref(Map), libvector.GV_FACE)
+ kvp["kernels"] = libvector.Vect_get_num_primitives(
+ byref(Map), libvector.GV_KERNEL)
+
+ # Summarize the primitives
+ kvp["primitives"] = kvp["points"] + kvp["lines"] + \
+ kvp["boundaries"] + kvp["centroids"]
+ if kvp["map3d"]:
+ kvp["primitives"] += kvp["faces"] + kvp["kernels"]
+
+ # Read topology information
+ kvp["nodes"] = libvector.Vect_get_num_nodes(byref(Map))
+ kvp["areas"] = libvector.Vect_get_num_areas(byref(Map))
+ kvp["islands"] = libvector.Vect_get_num_islands(byref(Map))
+ kvp["holes"] = libvector.Vect_get_num_holes(byref(Map))
+ kvp["volumes"] = libvector.Vect_get_num_primitives(
+ byref(Map), libvector.GV_VOLUME)
+ else:
+ kvp["points"] = None
+ kvp["lines"] = None
+ kvp["boundaries"] = None
+ kvp["centroids"] = None
+ kvp["faces"] = None
+ kvp["kernels"] = None
+ kvp["primitives"] = None
+ kvp["nodes"] = None
+ kvp["areas"] = None
+ kvp["islands"] = None
+ kvp["holes"] = None
+ kvp["volumes"] = None
+
+ libvector.Vect_close(byref(Map))
+
+ return kvp
+
+###############################################################################
+
+def _convert_timestamp_from_grass(ts):
+ """!Convert a GRASS file based timestamp into the temporal framework
+ format datetime or integer.
+
+ A tuple of two datetime objects (start, end) is returned in case of absolute time.
+ In case of relative time a tuple with start time, end time and the
+ relative unit (start, end, unit) will be returned.
+
+ Note:
+ The end time will be set to None in case of a time instance.
+
+ @param ts grass.lib.gis.TimeStamp object created by G_read_*_timestamp
+ """
+
+ dt1 = libgis.DateTime()
+ dt2 = libgis.DateTime()
+ count = c_int()
+
+ libgis.G_get_timestamps(byref(ts),
+ byref(dt1),
+ byref(dt2),
+ byref(count))
+
+
+ if dt1.mode == libdate.DATETIME_ABSOLUTE:
+ pdt1 = None
+ pdt2 = None
+ if count.value >= 1:
+ pdt1 = datetime(int(dt1.year), int(dt1.month), int(dt1.day),
+ int(dt1.hour), int(dt1.minute),
+ int(dt1.second))
+ if count.value == 2:
+ pdt2 = datetime(int(dt2.year), int(dt2.month), int(dt2.day),
+ int(dt2.hour), int(dt2.minute),
+ int(dt2.second))
+
+ # ATTENTION: We ignore the time zone
+ # TODO: Write time zone support
+ return (pdt1, pdt2)
+ else:
+ unit = None
+ start = None
+ end = None
+ if count >= 1:
+ if dt1.year > 0:
+ unit = "years"
+ start = dt1.year
+ elif dt1.month > 0:
+ unit = "months"
+ start = dt1.month
+ elif dt1.day > 0:
+ unit = "days"
+ start = dt1.day
+ elif dt1.hour > 0:
+ unit = "hours"
+ start = dt1.hour
+ elif dt1.minute > 0:
+ unit = "minutess"
+ start = dt1.minutes
+ elif dt1.seconds > 0:
+ unit = "seconds"
+ start = dt1.seconds
+ if count == 2:
+ if dt2.year > 0:
+ end = dt2.year
+ elif dt2.month > 0:
+ end = dt2.month
+ elif dt2.day > 0:
+ end = dt2.day
+ elif dt2.hour > 0:
+ end = dt2.hour
+ elif dt2.minute > 0:
+ end = dt2.minutes
+ elif dt2.seconds > 0:
+ end = dt2.seconds
+ return (start, end, unit)
+
+###############################################################################
+
+def _stop(lock, conn, data):
+ conn.close()
+ lock.release()
+ sys.exit()
+
+###############################################################################
+
+def c_library_server(lock, conn):
+ """!The GRASS C-libraries server function designed to be a target for
+ multiprocessing.Process
+
+ @param lock A multiprocessing.Lock
+ @param conn A multiprocessing.Pipe
+ """
+ # Crerate the function array
+ functions = [0]*8
+ functions[RPCDefs.STOP] = _stop
+ functions[RPCDefs.HAS_TIMESTAMP] = _has_timestamp
+ functions[RPCDefs.WRITE_TIMESTAMP] = _write_timestamp
+ functions[RPCDefs.READ_TIMESTAMP] = _read_timestamp
+ functions[RPCDefs.REMOVE_TIMESTAMP] = _remove_timestamp
+ functions[RPCDefs.READ_MAP_INFO] = _read_map_info
+ functions[RPCDefs.MAP_EXISTS] = _map_exists
+
+ libgis.G_gisinit("c_library_server")
+
+ while True:
+ # Avoid busy waiting
+ conn.poll(4)
+ data = conn.recv()
+ lock.acquire()
+ functions[data[0]](lock, conn, data)
+ lock.release()
+
+class CLibrariesInterface(object):
+ """!Fast and exit-safe interface to GRASS C-libraries functions
+
+ This class implements a fast and exit-safe interface to the GRASS
+ gis, raster, 3D raster and vector C-libraries functions.
+
+ The C-libraries functions are called via ctypes in a subprocess
+ using a pipe (multiprocessing.Pipe) to transfer the text messages.
+ Hence, the process that uses the CLibrariesInterface will not be
+ exited, if a G_fatal_error() was invoked in the subprocess.
+ In this case the CLibrariesInterface object will simply start a
+ new subprocess and restarts the pipeline.
+
+
+ Usage:
+
+ @code
+ >>> import grass.script as grass
+ >>> import grass.temporal as tgis
+ >>> grass.use_temp_region()
+ >>> grass.run_command("g.region", n=80.0, s=0.0, e=120.0, w=0.0,
+ ... t=1.0, b=0.0, res=10.0, res3=10.0)
+ 0
+ >>> tgis.init()
+ >>> grass.run_command("r.mapcalc", expression="test = 1", overwrite=True, quiet=True)
+ 0
+ >>> grass.run_command("r3.mapcalc", expression="test = 1", overwrite=True, quiet=True)
+ 0
+ >>> grass.run_command("v.random", output="test", n=10, overwrite=True, quiet=True)
+ 0
+ >>> grass.run_command("r.timestamp", map="test", date='12 Mar 1995', overwrite=True, quiet=True)
+ 0
+ >>> grass.run_command("r3.timestamp", map="test", date='12 Mar 1995', overwrite=True, quiet=True)
+ 0
+ >>> grass.run_command("v.timestamp", map="test", date='12 Mar 1995', overwrite=True, quiet=True)
+ 0
+
+
+ # Raster map
+ >>> ciface = tgis.CLibrariesInterface()
+ >>> check = ciface.raster_map_exists("test", tgis.get_current_mapset())
+ >>> print check
+ True
+ >>> ciface.read_raster_info("test", tgis.get_current_mapset())
+ {'rows': 12, 'north': 80.0, 'min': 1, 'datatype': 'CELL', 'max': 1, 'ewres': 10.0, 'cols': 8, 'west': 0.0, 'east': 120.0, 'nsres': 10.0, 'south': 0.0}
+ >>> check = ciface.has_raster_timestamp("test", tgis.get_current_mapset())
+ >>> print check
+ True
+ >>> if check:
+ ... res = ciface.read_raster_timestamp("test", tgis.get_current_mapset())
+ ... if res[0]:
+ ... print str(res[1][0]), str(res[1][0])
+ ... ciface.remove_raster_timestamp("test", tgis.get_current_mapset())
+ 1995-03-12 00:00:00 1995-03-12 00:00:00
+ 1
+ >>> ciface.has_raster_timestamp("test", tgis.get_current_mapset())
+ False
+ >>> ciface.write_raster_timestamp("test", tgis.get_current_mapset(), "13 Jan 1999")
+ 1
+ >>> ciface.has_raster_timestamp("test", tgis.get_current_mapset())
+ True
+
+
+ # 3D raster map
+ >>> check = ciface.raster3d_map_exists("test", tgis.get_current_mapset())
+ >>> print check
+ True
+ >>> ciface.read_raster3d_info("test", tgis.get_current_mapset())
+ {'tbres': 1.0, 'rows': 12, 'north': 80.0, 'bottom': 0.0, 'datatype': 'DCELL', 'max': 1.0, 'top': 1.0, 'min': 1.0, 'cols': 8, 'depths': 1, 'west': 0.0, 'ewres': 10.0, 'east': 120.0, 'nsres': 10.0, 'south': 0.0}
+ >>> check = ciface.has_raster3d_timestamp("test", tgis.get_current_mapset())
+ >>> print check
+ True
+ >>> if check:
+ ... res = ciface.read_raster3d_timestamp("test", tgis.get_current_mapset())
+ ... if res[0]:
+ ... print str(res[1][0]), str(res[1][0])
+ ... ciface.remove_raster3d_timestamp("test", tgis.get_current_mapset())
+ 1995-03-12 00:00:00 1995-03-12 00:00:00
+ 1
+ >>> ciface.has_raster3d_timestamp("test", tgis.get_current_mapset())
+ False
+ >>> ciface.write_raster3d_timestamp("test", tgis.get_current_mapset(), "13 Jan 1999")
+ 1
+ >>> ciface.has_raster3d_timestamp("test", tgis.get_current_mapset())
+ True
+
+
+ # Vector map
+ >>> check = ciface.vector_map_exists("test", tgis.get_current_mapset())
+ >>> print check
+ True
+ >>> kvp = ciface.read_vector_info("test", tgis.get_current_mapset())
+ >>> print kvp['points']
+ 10
+ >>> check = ciface.has_vector_timestamp("test", tgis.get_current_mapset(), None)
+ >>> print check
+ True
+ >>> if check:
+ ... res = ciface.read_vector_timestamp("test", tgis.get_current_mapset())
+ ... if res[0]:
+ ... print str(res[1][0]), str(res[1][0])
+ ... ciface.remove_vector_timestamp("test", tgis.get_current_mapset())
+ 1995-03-12 00:00:00 1995-03-12 00:00:00
+ 1
+ >>> ciface.has_vector_timestamp("test", tgis.get_current_mapset())
+ False
+ >>> ciface.write_vector_timestamp("test", tgis.get_current_mapset(), "13 Jan 1999")
+ 1
+ >>> ciface.has_vector_timestamp("test", tgis.get_current_mapset())
+ True
+
+ >>> grass.del_temp_region()
+
+ @endcode
+ """
+ def __init__(self):
+ self.client_conn = None
+ self.server_conn = None
+ self.server = None
+ self.start_server()
+
+ def __del__(self):
+ self.stop()
+
+ def start_server(self):
+ self.client_conn, self.server_conn = Pipe()
+ self.lock = Lock()
+ self.server = Process(target=c_library_server, args=(self.lock,
+ self.server_conn))
+ self.server.daemon = True
+ self.server.start()
+
+ def _check_restart_server(self):
+ """!Restart the server if it was terminated
+ """
+ if self.server.is_alive() is True:
+ return
+ self.client_conn.close()
+ self.server_conn.close()
+ self.start_server()
+ logging.warning("Needed to restart the libgis server")
+
+ def raster_map_exists(self, name, mapset):
+ """!Check if a raster map exists in the spatial database
+
+ @param name The name of the map
+ @param mapset The mapset of the map
+ @return True if exists, False if not
+ """
+ self._check_restart_server()
+ self.client_conn.send([RPCDefs.MAP_EXISTS, RPCDefs.TYPE_RASTER,
+ name, mapset, None])
+ return self.client_conn.recv()
+
+ def read_raster_info(self, name, mapset):
+ """!Read the raster map info from the file system and store the content
+ into a dictionary
+
+ @param name The name of the map
+ @param mapset The mapset of the map
+ @return The key value pairs of the map specific metadata, or None in case of an error
+ """
+ self._check_restart_server()
+ self.client_conn.send([RPCDefs.READ_MAP_INFO, RPCDefs.TYPE_RASTER,
+ name, mapset, None])
+ return self.client_conn.recv()
+
+ def has_raster_timestamp(self, name, mapset):
+ """!Check if a file based raster timetamp exists
+
+ @param name The name of the map
+ @param mapset The mapset of the map
+ @return True if exists, False if not
+ """
+ self._check_restart_server()
+ self.client_conn.send([RPCDefs.HAS_TIMESTAMP, RPCDefs.TYPE_RASTER,
+ name, mapset, None])
+ return self.client_conn.recv()
+
+ def remove_raster_timestamp(self, name, mapset):
+ """!Remove a file based raster timetamp
+
+ Please have a look at the documentation G_remove_raster_timestamp
+ for the return values description.
+
+ @param name The name of the map
+ @param mapset The mapset of the map
+ @return The return value of G_remove_raster_timestamp
+ """
+ self._check_restart_server()
+ self.client_conn.send([RPCDefs.REMOVE_TIMESTAMP, RPCDefs.TYPE_RASTER,
+ name, mapset, None])
+ return self.client_conn.recv()
+
+ def read_raster_timestamp(self, name, mapset):
+ """!Read a file based raster timetamp
+
+ Please have a look at the documentation G_read_raster_timestamp
+ for the return values description.
+
+ The timestamps to be send are tuples of values:
+ - relative time (start, end, unit), start and end are of type
+ integer, unit is of type string.
+ - absolute time (start, end), start and end are of type datetime
+
+ The end time may be None in case of a time instance.
+
+ @param name The name of the map
+ @param mapset The mapset of the map
+ @return The return value of G_read_raster_timestamp
+ """
+ self._check_restart_server()
+ self.client_conn.send([RPCDefs.READ_TIMESTAMP, RPCDefs.TYPE_RASTER,
+ name, mapset, None])
+ return self.client_conn.recv()
+
+ def write_raster_timestamp(self, name, mapset, timestring):
+ """!Write a file based raster timetamp
+
+ Please have a look at the documentation G_write_raster_timestamp
+ for the return values description.
+
+ Note:
+ Only timestamps of maps from the current mapset can written.
+
+ @param name The name of the map
+ @param mapset The mapset of the map
+ @param timestring A GRASS datetime C-library compatible string
+ @return The return value of G_write_raster_timestamp
+ """
+ self._check_restart_server()
+ self.client_conn.send([RPCDefs.WRITE_TIMESTAMP, RPCDefs.TYPE_RASTER,
+ name, mapset, None, timestring])
+ return self.client_conn.recv()
+
+ def raster3d_map_exists(self, name, mapset):
+ """!Check if a 3D raster map exists in the spatial database
+
+ @param name The name of the map
+ @param mapset The mapset of the map
+ @return True if exists, False if not
+ """
+ self._check_restart_server()
+ self.client_conn.send([RPCDefs.MAP_EXISTS, RPCDefs.TYPE_RASTER3D,
+ name, mapset, None])
+ return self.client_conn.recv()
+
+ def read_raster3d_info(self, name, mapset):
+ """!Read the 3D raster map info from the file system and store the content
+ into a dictionary
+
+ @param name The name of the map
+ @param mapset The mapset of the map
+ @return The key value pairs of the map specific metadata, or None in case of an error
+ """
+ self._check_restart_server()
+ self.client_conn.send([RPCDefs.READ_MAP_INFO, RPCDefs.TYPE_RASTER3D,
+ name, mapset, None])
+ return self.client_conn.recv()
+
+ def has_raster3d_timestamp(self, name, mapset):
+ """!Check if a file based 3D raster timetamp exists
+
+ @param name The name of the map
+ @param mapset The mapset of the map
+ @return True if exists, False if not
+ """
+ self._check_restart_server()
+ self.client_conn.send([RPCDefs.HAS_TIMESTAMP, RPCDefs.TYPE_RASTER3D,
+ name, mapset, None])
+ return self.client_conn.recv()
+
+ def remove_raster3d_timestamp(self, name, mapset):
+ """!Remove a file based 3D raster timetamp
+
+ Please have a look at the documentation G_remove_raster3d_timestamp
+ for the return values description.
+
+ @param name The name of the map
+ @param mapset The mapset of the map
+ @return The return value of G_remove_raster3d_timestamp
+ """
+ self._check_restart_server()
+ self.client_conn.send([RPCDefs.REMOVE_TIMESTAMP, RPCDefs.TYPE_RASTER3D,
+ name, mapset, None])
+ return self.client_conn.recv()
+
+ def read_raster3d_timestamp(self, name, mapset):
+ """!Read a file based 3D raster timetamp
+
+ Please have a look at the documentation G_read_raster3d_timestamp
+ for the return values description.
+
+ The timestamps to be send are tuples of values:
+ - relative time (start, end, unit), start and end are of type
+ integer, unit is of type string.
+ - absolute time (start, end), start and end are of type datetime
+
+ The end time may be None in case of a time instance.
+
+ @param name The name of the map
+ @param mapset The mapset of the map
+ @return The return value of G_read_raster3d_timestamp
+ """
+ self._check_restart_server()
+ self.client_conn.send([RPCDefs.READ_TIMESTAMP, RPCDefs.TYPE_RASTER3D,
+ name, mapset, None])
+ return self.client_conn.recv()
+
+ def write_raster3d_timestamp(self, name, mapset, timestring):
+ """!Write a file based 3D raster timetamp
+
+ Please have a look at the documentation G_write_raster3d_timestamp
+ for the return values description.
+
+ Note:
+ Only timestamps of maps from the current mapset can written.
+
+ @param name The name of the map
+ @param mapset The mapset of the map
+ @param timestring A GRASS datetime C-library compatible string
+ @return The return value of G_write_raster3d_timestamp
+ """
+ self._check_restart_server()
+ self.client_conn.send([RPCDefs.WRITE_TIMESTAMP, RPCDefs.TYPE_RASTER3D,
+ name, mapset, None, timestring])
+ return self.client_conn.recv()
+
+ def vector_map_exists(self, name, mapset):
+ """!Check if a vector map exists in the spatial database
+
+ @param name The name of the map
+ @param mapset The mapset of the map
+ @return True if exists, False if not
+ """
+ self._check_restart_server()
+ self.client_conn.send([RPCDefs.MAP_EXISTS, RPCDefs.TYPE_VECTOR,
+ name, mapset, None])
+ return self.client_conn.recv()
+
+ def read_vector_info(self, name, mapset):
+ """!Read the vector map info from the file system and store the content
+ into a dictionary
+
+ @param name The name of the map
+ @param mapset The mapset of the map
+ @return The key value pairs of the map specific metadata, or None in case of an error
+ """
+ self._check_restart_server()
+ self.client_conn.send([RPCDefs.READ_MAP_INFO, RPCDefs.TYPE_VECTOR,
+ name, mapset, None])
+ return self.client_conn.recv()
+
+ def has_vector_timestamp(self, name, mapset, layer=None):
+ """!Check if a file based vector timetamp exists
+
+ @param name The name of the map
+ @param mapset The mapset of the map
+ @param layer The layer of the vector map
+ @return True if exists, False if not
+ """
+ self._check_restart_server()
+ self.client_conn.send([RPCDefs.HAS_TIMESTAMP, RPCDefs.TYPE_VECTOR,
+ name, mapset, layer])
+ return self.client_conn.recv()
+
+ def remove_vector_timestamp(self, name, mapset, layer=None):
+ """!Remove a file based vector timetamp
+
+ Please have a look at the documentation G_remove_vector_timestamp
+ for the return values description.
+
+ @param name The name of the map
+ @param mapset The mapset of the map
+ @param layer The layer of the vector map
+ @return The return value of G_remove_vector_timestamp
+ """
+ self._check_restart_server()
+ self.client_conn.send([RPCDefs.REMOVE_TIMESTAMP, RPCDefs.TYPE_VECTOR,
+ name, mapset, layer])
+ return self.client_conn.recv()
+
+ def read_vector_timestamp(self, name, mapset, layer=None):
+ """!Read a file based vector timetamp
+
+ Please have a look at the documentation G_read_vector_timestamp
+ for the return values description.
+
+ The timestamps to be send are tuples of values:
+ - relative time (start, end, unit), start and end are of type
+ integer, unit is of type string.
+ - absolute time (start, end), start and end are of type datetime
+
+ The end time may be None in case of a time instance.
+
+ @param name The name of the map
+ @param mapset The mapset of the map
+ @param layer The layer of the vector map
+ @return The return value ofG_read_vector_timestamp and the timestamps
+ """
+ self._check_restart_server()
+ self.client_conn.send([RPCDefs.READ_TIMESTAMP, RPCDefs.TYPE_VECTOR,
+ name, mapset, layer])
+ return self.client_conn.recv()
+
+ def write_vector_timestamp(self, name, mapset, timestring, layer=None):
+ """!Write a file based vector timetamp
+
+ Please have a look at the documentation G_write_vector_timestamp
+ for the return values description.
+
+ Note:
+ Only timestamps pf maps from the current mapset can written.
+
+ @param name The name of the map
+ @param mapset The mapset of the map
+ @param timestring A GRASS datetime C-library compatible string
+ @param layer The layer of the vector map
+ @return The return value of G_write_vector_timestamp
+ """
+ self._check_restart_server()
+ self.client_conn.send([RPCDefs.WRITE_TIMESTAMP, RPCDefs.TYPE_VECTOR,
+ name, mapset, layer, timestring])
+ return self.client_conn.recv()
+
+ def stop(self):
+ """!Stop the messenger server and close the pipe
+ """
+ if self.server is not None and self.server.is_alive():
+ self.client_conn.send([0,])
+ self.server.join(5)
+ self.server.terminate()
+ if self.client_conn is not None:
+ self.client_conn.close()
+
+if __name__ == "__main__":
+ import doctest
+ doctest.testmod()
Modified: grass/trunk/lib/python/temporal/core.py
===================================================================
--- grass/trunk/lib/python/temporal/core.py 2013-11-17 18:22:12 UTC (rev 58248)
+++ grass/trunk/lib/python/temporal/core.py 2013-11-18 00:26:00 UTC (rev 58249)
@@ -37,6 +37,7 @@
import os
import grass.script.core as core
from datetime import datetime
+from c_libraries_interface import *
# Import all supported database backends
# Ignore import errors since they are checked later
try:
@@ -104,10 +105,8 @@
# provides a fast and exit safe interface to the C-library message functions
message_interface=None
-def _set_tgis_message_interface():
- """!Set the global mesage interface variable
-
- @param messenger The grass.pyhrass.message.Messenger() object
+def _init_tgis_message_interface():
+ """!Initiate the global mesage interface
"""
global message_interface
from grass.pygrass import messages
@@ -125,6 +124,29 @@
###############################################################################
+# The global variable that stores the C-library interface object that
+# provides a fast and exit safe interface to the C-library libgis,
+# libraster, libraster3d and libvector functions
+c_library_interface=None
+
+def _init_tgis_c_library_interface():
+ """!Set the global C-library interface variable that
+ provides a fast and exit safe interface to the C-library libgis,
+ libraster, libraster3d and libvector functions
+ """
+ global c_library_interface
+ c_library_interface = CLibrariesInterface()
+
+def get_tgis_c_library_interface():
+ """!Return the C-library interface that
+ provides a fast and exit safe interface to the C-library libgis,
+ libraster, libraster3d and libvector functions
+ """
+ global c_library_interface
+ return c_library_interface
+
+###############################################################################
+
def get_tgis_version():
"""!Get the verion number of the temporal framework
@return The version number of the temporal framework as string
@@ -197,38 +219,6 @@
###############################################################################
-# This variable specifies if the ctypes interface to the grass
-# libraries should be used to read map specific data. If set to False
-# the grass scripting library will be used to get map informations.
-# The advantage of the ctypes inteface is speed, the disadvantage is that
-# the GRASS C functions may call G_fatal_error() which exits the process.
-# That is not catchable in Python.
-use_ctypes_map_access = True
-
-def set_use_ctypes_map_access(use_ctype = True):
- """!Define the map access method for the temporal GIS library
-
- Using ctypes to read map metadata is much faster
- then using the grass.script interface that calls grass modules.
- The disadvantage is that GRASS C-library function will call
- G_fatal_error() that will exit the calling process.
-
- GUI developer should set this flag to False.
-
- @param use_ctype True use ctypes interface, False use grass.script interface
- """
- global use_ctypes_map_access
- use_ctypes_map_access = use_ctype
-
-###############################################################################
-
-def get_use_ctypes_map_access():
- """!Return true if ctypes is used for map access """
- global use_ctypes_map_access
- return use_ctypes_map_access
-
-###############################################################################
-
def get_sql_template_path():
base = os.getenv("GISBASE")
base_etc = os.path.join(base, "etc")
@@ -255,7 +245,9 @@
# Set the global variable current_mapset for fast mapset access
_set_current_mapset(grassenv["MAPSET"])
# Start the GRASS message interface server
- _set_tgis_message_interface()
+ _init_tgis_message_interface()
+ # Start the C-library interface server
+ _init_tgis_c_library_interface()
msgr = get_tgis_message_interface()
Modified: grass/trunk/lib/python/temporal/space_time_datasets.py
===================================================================
--- grass/trunk/lib/python/temporal/space_time_datasets.py 2013-11-17 18:22:12 UTC (rev 58248)
+++ grass/trunk/lib/python/temporal/space_time_datasets.py 2013-11-18 00:26:00 UTC (rev 58249)
@@ -12,13 +12,7 @@
@author Soeren Gebbert
"""
import getpass
-from ctypes import *
-import grass.lib.gis as libgis
-import grass.lib.raster as libraster
-import grass.lib.vector as libvector
-import grass.lib.raster3d as libraster3d
-import grass.script as grass
-
+import logging
from abstract_map_dataset import *
from abstract_space_time_dataset import *
@@ -40,11 +34,11 @@
>>> grass.run_command("g.region", n=80.0, s=0.0, e=120.0, w=0.0,
... t=1.0, b=0.0, res=10.0)
0
- >>> grass.run_command("r.mapcalc", overwrite=True,
+ >>> grass.run_command("r.mapcalc", overwrite=True, quiet=True,
... expression="strds_map_test_case = 1")
0
>>> grass.run_command("r.timestamp", map="strds_map_test_case",
- ... date="15 jan 1999")
+ ... date="15 jan 1999", quiet=True)
0
>>> mapset = get_current_mapset()
>>> name = "strds_map_test_case"
@@ -110,7 +104,7 @@
>>> rmap.is_time_relative()
False
- >>> grass.run_command("g.remove", rast=name)
+ >>> grass.run_command("g.remove", rast=name, quiet=True)
0
>>> grass.del_temp_region()
@@ -208,151 +202,93 @@
def has_grass_timestamp(self):
"""!Check if a grass file bsased time stamp exists for this map.
+
+ @return True if success, False on error
"""
- if libgis.G_has_raster_timestamp(self.get_name(), self.get_mapset()):
- return True
- else:
- return False
+ return self.ciface.has_raster_timestamp(self.get_name(),
+ self.get_mapset())
def read_timestamp_from_grass(self):
"""!Read the timestamp of this map from the map metadata
in the grass file system based spatial database and
set the internal time stamp that should be insert/updated
in the temporal database.
+
+ @return True if success, False on error
"""
if not self.has_grass_timestamp():
return False
- ts = libgis.TimeStamp()
- check = libgis.G_read_raster_timestamp(self.get_name(), self.get_mapset(),
- byref(ts))
+ check, dates = self.ciface.read_raster_timestamp(self.get_name(),
+ self.get_mapset(),)
if check < 1:
self.msgr.error(_("Unable to read timestamp file "
"for raster map <%s>" % (self.get_map_id())))
return False
- return self._set_timestamp_from_grass(ts)
+ if len(dates) == 2:
+ self.set_absolute_time(dates[0], dates[1], None)
+ else:
+ self.set_relative_time(dates[0], dates[1], dates[2])
+ return True
+
def write_timestamp_to_grass(self):
"""!Write the timestamp of this map into the map metadata in
the grass file system based spatial database.
Internally the libgis API functions are used for writing
+
+ @return True if success, False on error
"""
+ check = self.ciface.write_raster_timestamp(self.get_name(),
+ self.get_mapset(),
+ self._convert_timestamp())
- ts = libgis.TimeStamp()
-
- libgis.G_scan_timestamp(byref(ts), self._convert_timestamp())
- check = libgis.G_write_raster_timestamp(self.get_name(), byref(ts))
-
if check == -1:
self.msgr.error(_("Unable to create timestamp file "
"for raster map <%s>" % (self.get_map_id())))
+ return False
if check == -2:
self.msgr.error(_("Invalid datetime in timestamp for raster map <%s>" %
(self.get_map_id())))
+ return False
+ if check == -3:
+ self.msgr.error(_("Internal error"))
+ return False
+
+ return True
+
def remove_timestamp_from_grass(self):
"""!Remove the timestamp from the grass file system based
spatial database
Internally the libgis API functions are used for removal
+
+ @return True if success, False on error
"""
- check = libgis.G_remove_raster_timestamp(self.get_name())
+ check = self.ciface.remove_raster_timestamp(self.get_name(),
+ self.get_mapset())
if check == -1:
- core.error(_("Unable to remove timestamp for raster map <%s>" %
+ self.msgr.error(_("Unable to remove timestamp for raster map <%s>" %
(self.get_name())))
+ return False
+ return True
+
def map_exists(self):
"""!Return True in case the map exists in the grass spatial database
@return True if map exists, False otherwise
"""
- mapset = libgis.G_find_raster(self.get_name(), self.get_mapset())
+ return self.ciface.raster_map_exists(self.get_name(),
+ self.get_mapset())
- if not mapset:
- return False
-
- return True
-
- def read_info(self):
- """!Read the raster map info from the file system and store the content
- into a dictionary
-
- This method uses the ctypes interface to the gis and raster libraries
- to read the map metadata information
- """
-
- kvp = {}
-
- name = self.get_name()
- mapset = self.get_mapset()
-
- if not self.map_exists():
- core.fatal(_("Raster map <%s> not found" % name))
-
- # Read the region information
- region = libgis.Cell_head()
- libraster.Rast_get_cellhd(name, mapset, byref(region))
-
- kvp["north"] = region.north
- kvp["south"] = region.south
- kvp["east"] = region.east
- kvp["west"] = region.west
- kvp["nsres"] = region.ns_res
- kvp["ewres"] = region.ew_res
- kvp["rows"] = region.cols
- kvp["cols"] = region.rows
-
- maptype = libraster.Rast_map_type(name, mapset)
-
- if maptype == libraster.DCELL_TYPE:
- kvp["datatype"] = "DCELL"
- elif maptype == libraster.FCELL_TYPE:
- kvp["datatype"] = "FCELL"
- elif maptype == libraster.CELL_TYPE:
- kvp["datatype"] = "CELL"
-
- # Read range
- if libraster.Rast_map_is_fp(name, mapset):
- range = libraster.FPRange()
- libraster.Rast_init_fp_range(byref(range))
- ret = libraster.Rast_read_fp_range(name, mapset, byref(range))
- if ret < 0:
- core.fatal(_("Unable to read range file"))
- if ret == 2:
- kvp["min"] = None
- kvp["max"] = None
- else:
- min = libgis.DCELL()
- max = libgis.DCELL()
- libraster.Rast_get_fp_range_min_max(
- byref(range), byref(min), byref(max))
- kvp["min"] = min.value
- kvp["max"] = max.value
- else:
- range = libraster.Range()
- libraster.Rast_init_range(byref(range))
- ret = libraster.Rast_read_range(name, mapset, byref(range))
- if ret < 0:
- core.fatal(_("Unable to read range file"))
- if ret == 2:
- kvp["min"] = None
- kvp["max"] = None
- else:
- min = libgis.CELL()
- max = libgis.CELL()
- libraster.Rast_get_range_min_max(
- byref(range), byref(min), byref(max))
- kvp["min"] = min.value
- kvp["max"] = max.value
-
- return kvp
-
def load(self):
"""!Load all info from an existing raster map into the internal s
tructure"""
@@ -360,20 +296,16 @@
# Fill base information
self.base.set_creator(str(getpass.getuser()))
- # Get the data from an existing raster map
+ kvp = self.ciface.read_raster_info(self.get_name(),
+ self.get_mapset())
- if get_use_ctypes_map_access() == True:
- kvp = self.read_info()
- else:
- kvp = grass.raster_info(self.get_id())
-
# Fill spatial extent
+ self.set_spatial_extent_from_values(north=kvp["north"],
+ south=kvp["south"],
+ east=kvp["east"],
+ west=kvp["west"])
- self.set_spatial_extent_from_values(north=kvp["north"], south=kvp["south"],
- east=kvp["east"], west=kvp["west"])
-
# Fill metadata
-
self.metadata.set_nsres(kvp["nsres"])
self.metadata.set_ewres(kvp["ewres"])
self.metadata.set_datatype(kvp["datatype"])
@@ -405,13 +337,13 @@
>>> init()
>>> grass.use_temp_region()
>>> grass.run_command("g.region", n=80.0, s=0.0, e=120.0, w=0.0,
- ... t=100.0, b=0.0, res=10.0)
+ ... t=100.0, b=0.0, res=10.0, res3=10.0)
0
- >>> grass.run_command("r3.mapcalc", overwrite=True,
+ >>> grass.run_command("r3.mapcalc", overwrite=True, quiet=True,
... expression="str3ds_map_test_case = 1")
0
>>> grass.run_command("r3.timestamp", map="str3ds_map_test_case",
- ... date="15 jan 1999")
+ ... date="15 jan 1999", quiet=True)
0
>>> mapset = get_current_mapset()
>>> name = "str3ds_map_test_case"
@@ -478,7 +410,7 @@
True
>>> r3map.is_time_relative()
False
- >>> grass.run_command("g.remove", rast3d=name)
+ >>> grass.run_command("g.remove", rast3d=name, quiet=True)
0
>>> grass.del_temp_region()
"""
@@ -589,152 +521,90 @@
def has_grass_timestamp(self):
"""!Check if a grass file bsased time stamp exists for this map.
+
+ @return True if success, False on error
"""
- if libgis.G_has_raster3d_timestamp(self.get_name(), self.get_mapset()):
- return True
- else:
- return False
+ return self.ciface.has_raster3d_timestamp(self.get_name(),
+ self.get_mapset())
-
def read_timestamp_from_grass(self):
"""!Read the timestamp of this map from the map metadata
in the grass file system based spatial database and
set the internal time stamp that should be insert/updated
in the temporal database.
+
+ @return True if success, False on error
"""
if not self.has_grass_timestamp():
return False
- ts = libgis.TimeStamp()
- check = libgis.G_read_raster3d_timestamp(self.get_name(), self.get_mapset(),
- byref(ts))
+ check, dates = self.ciface.read_raster3d_timestamp(self.get_name(),
+ self.get_mapset(),)
if check < 1:
self.msgr.error(_("Unable to read timestamp file "
"for 3D raster map <%s>" % (self.get_map_id())))
return False
- return self._set_timestamp_from_grass(ts)
+ if len(dates) == 2:
+ self.set_absolute_time(dates[0], dates[1], None)
+ else:
+ self.set_relative_time(dates[0], dates[1], dates[2])
+ return True
+
def write_timestamp_to_grass(self):
"""!Write the timestamp of this map into the map metadata
in the grass file system based spatial database.
Internally the libgis API functions are used for writing
+
+ @return True if success, False on error
"""
+ check = self.ciface.write_raster3d_timestamp(self.get_name(),
+ self.get_mapset(),
+ self._convert_timestamp())
- ts = libgis.TimeStamp()
-
- libgis.G_scan_timestamp(byref(ts), self._convert_timestamp())
- check = libgis.G_write_raster3d_timestamp(self.get_name(), byref(ts))
-
if check == -1:
self.msgr.error(_("Unable to create timestamp file "
- "for raster3d map <%s>" % (self.get_map_id())))
+ "for 3D raster map <%s>" % (self.get_map_id())))
+ return False
if check == -2:
- self.msgr.error(_("Invalid datetime in timestamp "
- "for raster3d map <%s>" % (self.get_map_id())))
+ self.msgr.error(_("Invalid datetime in timestamp for 3D raster map <%s>" %
+ (self.get_map_id())))
+ return False
+ if check == -3:
+ self.msgr.error(_("Internal error"))
+ return False
+
+ return True
+
def remove_timestamp_from_grass(self):
"""!Remove the timestamp from the grass file system based spatial database
- Internally the libgis API functions are used for removal
+ @return True if success, False on error
"""
- check = libgis.G_remove_raster3d_timestamp(self.get_name())
+ check = self.ciface.remove_raster3d_timestamp(self.get_name(),
+ self.get_mapset())
if check == -1:
- self.msgr.error(_("Unable to remove timestamp for raster3d map <%s>" %
+ self.msgr.error(_("Unable to remove timestamp for raster map <%s>" %
(self.get_name())))
+ return False
+ return True
+
def map_exists(self):
"""!Return True in case the map exists in the grass spatial database
@return True if map exists, False otherwise
"""
- mapset = libgis.G_find_raster3d(self.get_name(), self.get_mapset())
+ return self.ciface.raster3d_map_exists(self.get_name(),
+ self.get_mapset())
- if not mapset:
- return False
-
- return True
-
- def read_info(self):
- """!Read the raster3d map info from the file system and store the content
- into a dictionary
-
- This method uses the ctypes interface to the gis and raster3d libraries
- to read the map metadata information
- """
-
- kvp = {}
-
- name = self.get_name()
- mapset = self.get_mapset()
-
- if not self.map_exists():
- core.fatal(_("Raster3d map <%s> not found" % name))
-
- # Read the region information
- region = libraster3d.RASTER3D_Region()
- libraster3d.Rast3d_read_region_map(name, mapset, byref(region))
-
- kvp["north"] = region.north
- kvp["south"] = region.south
- kvp["east"] = region.east
- kvp["west"] = region.west
- kvp["nsres"] = region.ns_res
- kvp["ewres"] = region.ew_res
- kvp["tbres"] = region.tb_res
- kvp["rows"] = region.cols
- kvp["cols"] = region.rows
- kvp["depths"] = region.depths
- kvp["top"] = region.top
- kvp["bottom"] = region.bottom
-
- # We need to open the map, this function returns a void pointer
- # but we may need the correct type which is RASTER3D_Map, hence
- # the casting
- g3map = cast(libraster3d.Rast3d_open_cell_old(name, mapset,
- libraster3d.RASTER3D_DEFAULT_WINDOW,
- libraster3d.RASTER3D_TILE_SAME_AS_FILE,
- libraster3d.RASTER3D_NO_CACHE),
- POINTER(libraster3d.RASTER3D_Map))
-
- if not g3map:
- core.fatal(_("Unable to open 3D raster map <%s>" % (name)))
-
- maptype = libraster3d.Rast3d_file_type_map(g3map)
-
- if maptype == libraster.DCELL_TYPE:
- kvp["datatype"] = "DCELL"
- elif maptype == libraster.FCELL_TYPE:
- kvp["datatype"] = "FCELL"
-
- # Read range
- min = libgis.DCELL()
- max = libgis.DCELL()
- ret = libraster3d.Rast3d_range_load(g3map)
- if not ret:
- core.fatal(_("Unable to load range of 3D raster map <%s>" %
- (name)))
- libraster3d.Rast3d_range_min_max(g3map, byref(min), byref(max))
-
- if min.value != min.value:
- kvp["min"] = None
- else:
- kvp["min"] = float(min.value)
- if max.value != max.value:
- kvp["max"] = None
- else:
- kvp["max"] = float(max.value)
-
- if not libraster3d.Rast3d_close(g3map):
- G_fatal_error(_("Unable to close 3D raster map <%s>" % (name)))
-
- return kvp
-
def load(self):
"""!Load all info from an existing raster3d map into the internal structure"""
@@ -742,14 +612,9 @@
self.base.set_creator(str(getpass.getuser()))
# Fill spatial extent
+ kvp = self.ciface.read_raster3d_info(self.get_name(),
+ self.get_mapset())
- # Get the data from an existing 3D raster map
-
- if get_use_ctypes_map_access() == True:
- kvp = self.read_info()
- else:
- kvp = grass.raster3d_info(self.get_id())
-
self.set_spatial_extent_from_values(north=kvp["north"], south=kvp["south"],
east=kvp["east"], west=kvp["west"],
top=kvp["top"], bottom=kvp["bottom"])
@@ -792,10 +657,10 @@
... t=1.0, b=0.0, res=10.0)
0
>>> grass.run_command("v.random", overwrite=True, output="stvds_map_test_case",
- ... n=100, zmin=0, zmax=100, flags="z", column="elevation")
+ ... n=100, zmin=0, zmax=100, flags="z", column="elevation", quiet=True)
0
>>> grass.run_command("v.timestamp", map="stvds_map_test_case",
- ... date="15 jan 1999")
+ ... date="15 jan 1999", quiet=True)
0
>>> mapset = get_current_mapset()
>>> name = "stvds_map_test_case"
@@ -854,7 +719,7 @@
True
>>> vmap.is_time_relative()
False
- >>> grass.run_command("g.remove", vect=name)
+ >>> grass.run_command("g.remove", vect=name, quiet=True)
0
>>> grass.del_temp_region()
@@ -937,11 +802,9 @@
def has_grass_timestamp(self):
"""!Check if a grass file bsased time stamp exists for this map.
"""
- if libgis.G_has_vector_timestamp(self.get_name(), self.get_layer(),
- self.get_mapset()):
- return True
- else:
- return False
+ return self.ciface.has_vector_timestamp(self.get_name(),
+ self.get_mapset(),
+ self.get_layer())
def read_timestamp_from_grass(self):
@@ -954,162 +817,69 @@
if not self.has_grass_timestamp():
return False
- ts = libgis.TimeStamp()
- check = libgis.G_read_vector_timestamp(self.get_name(),
- self.get_layer(),
- self.get_mapset(),
- byref(ts))
+ check, dates = self.ciface.read_vector_timestamp(self.get_name(),
+ self.get_mapset(),)
if check < 1:
self.msgr.error(_("Unable to read timestamp file "
"for vector map <%s>" % (self.get_map_id())))
return False
- return self._set_timestamp_from_grass(ts)
+ if len(dates) == 2:
+ self.set_absolute_time(dates[0], dates[1], None)
+ else:
+ self.set_relative_time(dates[0], dates[1], dates[2])
+ return True
+
def write_timestamp_to_grass(self):
"""!Write the timestamp of this map into the map metadata in
the grass file system based spatial database.
Internally the libgis API functions are used for writing
"""
+ check = self.ciface.write_vector_timestamp(self.get_name(),
+ self.get_mapset(),
+ self._convert_timestamp(),
+ self.get_layer())
- ts = libgis.TimeStamp()
-
- libgis.G_scan_timestamp(byref(ts), self._convert_timestamp())
- check = libgis.G_write_vector_timestamp(
- self.get_name(), self.get_layer(), byref(ts))
-
if check == -1:
self.msgr.error(_("Unable to create timestamp file "
"for vector map <%s>" % (self.get_map_id())))
+ return False
if check == -2:
self.msgr.error(_("Invalid datetime in timestamp for vector map <%s>" %
(self.get_map_id())))
+ return False
+ return True
+
def remove_timestamp_from_grass(self):
"""!Remove the timestamp from the grass file system based spatial
database
Internally the libgis API functions are used for removal
"""
- check = libgis.G_remove_vector_timestamp(
- self.get_name(), self.get_layer())
+ check = self.ciface.remove_vector_timestamp(self.get_name(),
+ self.get_mapset())
if check == -1:
self.msgr.error(_("Unable to remove timestamp for vector map <%s>" %
(self.get_name())))
+ return False
+ return True
+
def map_exists(self):
"""!Return True in case the map exists in the grass spatial database
@return True if map exists, False otherwise
"""
- mapset = libgis.G_find_vector(self.get_name(), self.get_mapset())
+ return self.ciface.vector_map_exists(self.get_name(),
+ self.get_mapset())
- if not mapset:
- return False
- return True
-
- def read_info(self):
- """!Read the vector map info from the file system and store the content
- into a dictionary
-
- This method uses the ctypes interface to the vector libraries
- to read the map metadata information
- """
-
- kvp = {}
-
- name = self.get_name()
- mapset = self.get_mapset()
-
- if not self.map_exists():
- core.fatal(_("Vector map <%s> not found" % name))
-
- # The vector map structure
- Map = libvector.Map_info()
-
- # We open the maps always in topology mode first
- libvector.Vect_set_open_level(2)
- with_topo = True
-
- # Code lend from v.info main.c
- if libvector.Vect_open_old_head2(byref(Map), name, mapset, "1") < 2:
- # force level 1, open fully
- # NOTE: number of points, lines, boundaries, centroids,
- # faces, kernels is still available
- libvector.Vect_set_open_level(1) # no topology
- with_topo = False
- self.msgr.message(_("Open map without topology support"))
- if libvector.Vect_open_old2(byref(Map), name, mapset, "1") < 1:
- core.fatal(_("Unable to open vector map <%s>" %
- (libvector.Vect_get_full_name(byref(Map)))))
-
- # Release the vector spatial index memory when closed
- libvector.Vect_set_release_support(byref(Map))
-
- # Read the extent information
- bbox = libvector.bound_box()
- libvector.Vect_get_map_box(byref(Map), byref(bbox))
-
- kvp["north"] = bbox.N
- kvp["south"] = bbox.S
- kvp["east"] = bbox.E
- kvp["west"] = bbox.W
- kvp["top"] = bbox.T
- kvp["bottom"] = bbox.B
-
- kvp["map3d"] = bool(libvector.Vect_is_3d(byref(Map)))
-
- # Read number of features
- if with_topo:
- kvp["points"] = libvector.Vect_get_num_primitives(
- byref(Map), libvector.GV_POINT)
- kvp["lines"] = libvector.Vect_get_num_primitives(
- byref(Map), libvector.GV_LINE)
- kvp["boundaries"] = libvector.Vect_get_num_primitives(
- byref(Map), libvector.GV_BOUNDARY)
- kvp["centroids"] = libvector.Vect_get_num_primitives(
- byref(Map), libvector.GV_CENTROID)
- kvp["faces"] = libvector.Vect_get_num_primitives(
- byref(Map), libvector.GV_FACE)
- kvp["kernels"] = libvector.Vect_get_num_primitives(
- byref(Map), libvector.GV_KERNEL)
-
- # Summarize the primitives
- kvp["primitives"] = kvp["points"] + kvp["lines"] + \
- kvp["boundaries"] + kvp["centroids"]
- if kvp["map3d"]:
- kvp["primitives"] += kvp["faces"] + kvp["kernels"]
-
- # Read topology information
- kvp["nodes"] = libvector.Vect_get_num_nodes(byref(Map))
- kvp["areas"] = libvector.Vect_get_num_areas(byref(Map))
- kvp["islands"] = libvector.Vect_get_num_islands(byref(Map))
- kvp["holes"] = libvector.Vect_get_num_holes(byref(Map))
- kvp["volumes"] = libvector.Vect_get_num_primitives(
- byref(Map), libvector.GV_VOLUME)
- else:
- kvp["points"] = None
- kvp["lines"] = None
- kvp["boundaries"] = None
- kvp["centroids"] = None
- kvp["faces"] = None
- kvp["kernels"] = None
- kvp["primitives"] = None
- kvp["nodes"] = None
- kvp["areas"] = None
- kvp["islands"] = None
- kvp["holes"] = None
- kvp["volumes"] = None
-
- libvector.Vect_close(byref(Map))
-
- return kvp
-
def load(self):
"""!Load all info from an existing vector map into the internal
structure"""
@@ -1119,10 +889,8 @@
# Get the data from an existing vector map
- if get_use_ctypes_map_access() == True:
- kvp = self.read_info()
- else:
- kvp = grass.vector_info(self.get_map_id())
+ kvp = self.ciface.read_vector_info(self.get_name(),
+ self.get_mapset())
# Fill spatial extent
self.set_spatial_extent_from_values(north=kvp["north"], south=kvp["south"],
More information about the grass-commit
mailing list